constructor with default arguments.
We used to try to rebuild the call as a call to the faked-up inherited
constructor, which is only a placeholder and lacks (for example) default
arguments. Instead, build the call by reference to the original
constructor.
In passing, add a note to say where a call that recursively uses a
default argument from within itself occurs. This is usually pretty
obvious, but still at least somewhat useful, and would have saved
significant debugging time for this particular bug.
def note_default_argument_declared_here : Note<
"default argument declared here">;
def err_recursive_default_argument : Error<"recursive evaluation of default argument">;
+def note_recursive_default_argument_used_here : Note<
+ "default argument used here">;
def ext_param_promoted_not_compatible_with_prototype : ExtWarn<
"%diff{promoted type $ of K&R function parameter is not compatible with the "
// If the default argument expression is not set yet, we are building it now.
if (!Param->hasInit()) {
Diag(Param->getBeginLoc(), diag::err_recursive_default_argument) << FD;
+ Diag(CallLoc, diag::note_recursive_default_argument_used_here);
Param->setInvalidDecl();
return true;
}
bool RequiresZeroInit,
CXXConstructExpr::ConstructionKind ConstructKind,
SourceRange ParenRange) {
+ // Reconstruct the constructor we originally found, which might be
+ // different if this is a call to an inherited constructor.
+ CXXConstructorDecl *FoundCtor = Constructor;
+ if (Constructor->isInheritingConstructor())
+ FoundCtor = Constructor->getInheritedConstructor().getConstructor();
+
SmallVector<Expr*, 8> ConvertedArgs;
- if (getSema().CompleteConstructorCall(Constructor, Args, Loc,
- ConvertedArgs))
+ if (getSema().CompleteConstructorCall(FoundCtor, Args, Loc, ConvertedArgs))
return ExprError();
return getSema().BuildCXXConstructExpr(Loc, T, Constructor,
T<0, 1> t;
struct PR28105 {
- PR28105 (int = 0, int = 0, PR28105 = 0); // expected-error{{recursive evaluation of default argument}}
+ PR28105 (int = 0, int = 0,
+ PR28105 // expected-error{{recursive evaluation of default argument}}
+ =
+ 0); // expected-note {{default argument used here}}
};
// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+namespace std {
+ template<typename T> struct initializer_list {
+ T *p;
+ __SIZE_TYPE__ n;
+ initializer_list(T*, __SIZE_TYPE__);
+ };
+}
+
struct X0 { // expected-note 8{{candidate}}
X0(int*, float*); // expected-note 4{{candidate}}
};
void g(AA, AA);
void h() { f<1, 2>(); } // expected-note {{instantiation of}}
}
+
+namespace RebuildStdInitList {
+ struct A { A(std::initializer_list<int>, int = 0) {} };
+ struct B : A { using A::A; };
+ struct PES { PES(B); };
+
+ // Check we can rebuild the use of the default argument here. This requires
+ // going to the original (base class) constructor, because we don't copy
+ // default arguments onto our fake derived class inherited constructors.
+ template<typename U> void f() { PES({1, 2, 3}); }
+ void g() { f<int>(); }
+}