void ActOnParamDefaultArgument(Decl *param,
SourceLocation EqualLoc,
Expr *defarg);
- void ActOnParamUnparsedDefaultArgument(Decl *param,
- SourceLocation EqualLoc,
+ void ActOnParamUnparsedDefaultArgument(Decl *param, SourceLocation EqualLoc,
SourceLocation ArgLoc);
void ActOnParamDefaultArgumentError(Decl *param, SourceLocation EqualLoc);
- bool SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
+ ExprResult ConvertParamDefaultArgument(const ParmVarDecl *Param,
+ Expr *DefaultArg,
+ SourceLocation EqualLoc);
+ void SetParamDefaultArgument(ParmVarDecl *Param, Expr *DefaultArg,
SourceLocation EqualLoc);
// Contexts where using non-trivial C union types can be disallowed. This is
ComputedEST = EST_None;
}
-bool
-Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg,
- SourceLocation EqualLoc) {
+ExprResult Sema::ConvertParamDefaultArgument(const ParmVarDecl *Param,
+ Expr *Arg,
+ SourceLocation EqualLoc) {
if (RequireCompleteType(Param->getLocation(), Param->getType(),
- diag::err_typecheck_decl_incomplete_type)) {
- Param->setInvalidDecl();
+ diag::err_typecheck_decl_incomplete_type))
return true;
- }
// C++ [dcl.fct.default]p5
// A default argument expression is implicitly converted (clause
CheckCompletedExpr(Arg, EqualLoc);
Arg = MaybeCreateExprWithCleanups(Arg);
- // Okay: add the default argument to the parameter
+ return Arg;
+}
+
+void Sema::SetParamDefaultArgument(ParmVarDecl *Param, Expr *Arg,
+ SourceLocation EqualLoc) {
+ // Add the default argument to the parameter
Param->setDefaultArg(Arg);
// We have already instantiated this parameter; provide each of the
// We're done tracking this parameter's instantiations.
UnparsedDefaultArgInstantiations.erase(InstPos);
}
-
- return false;
}
/// ActOnParamDefaultArgument - Check whether the default argument
return;
}
+ ExprResult Result = ConvertParamDefaultArgument(Param, DefaultArg, EqualLoc);
+ if (Result.isInvalid())
+ return Fail();
+
+ DefaultArg = Result.getAs<Expr>();
+
// Check that the default argument is well-formed
CheckDefaultArgumentVisitor DefaultArgChecker(*this, DefaultArg);
if (DefaultArgChecker.Visit(DefaultArg))
return Fail();
- if (SetParamDefaultArgument(Param, DefaultArg, EqualLoc))
- return Fail();
+ SetParamDefaultArgument(Param, DefaultArg, EqualLoc);
}
/// ActOnParamUnparsedDefaultArgument - We've seen a default
if (NewArg.isUsable()) {
// It would be nice if we still had this.
SourceLocation EqualLoc = NewArg.get()->getBeginLoc();
- SetParamDefaultArgument(NewParm, NewArg.get(), EqualLoc);
+ ExprResult Result =
+ ConvertParamDefaultArgument(NewParm, NewArg.get(), EqualLoc);
+ if (Result.isInvalid())
+ return nullptr;
+
+ SetParamDefaultArgument(NewParm, Result.getAs<Expr>(), EqualLoc);
}
} else {
// FIXME: if we non-lazily instantiated non-dependent default args for
// expected-error@-1 {{default argument references local variable 'i1' of enclosing function}}
const int i2 = 0;
- extern void h2a(int x = i2); // FIXME: ok, not odr-use
- // expected-error@-1 {{default argument references local variable 'i2' of enclosing function}}
+ extern void h2a(int x = i2); // ok, not odr-use
extern void h2b(int x = i2 + 0); // ok, not odr-use
const int i3 = 0;
};
void A::test() {
- void g(int = this); // expected-error {{default argument references 'this'}}
+ void g(int = this);
+ // expected-error@-1 {{cannot initialize a parameter of type 'int' with an rvalue of type 'A *'}}
+ // expected-note@-2 {{passing argument to parameter here}}
+
+ void h(int = ((void)this,42));
+ // expected-error@-1 {{default argument references 'this'}}
}
template<typename T> auto fn1 = [](auto a) { return a + T(1); };
template<typename T> auto v1 = [](int a = T()) { return a; }();
// expected-error@-1{{cannot initialize a parameter of type 'int' with an rvalue of type 'int *'}}
-// expected-error@-2{{no matching function for call}}
-// expected-note@-3{{passing argument to parameter 'a' here}}
-// expected-note@-4{{candidate function not viable}}
-// expected-note@-5{{conversion candidate of type 'int (*)(int)'}}
+// expected-note@-2{{passing argument to parameter 'a' here}}
struct S {
template<class T>
struct Inner { // expected-note {{in instantiation}}
void operator()(T a = "") {} // expected-error {{conversion function from 'const char [1]' to 'rdar23721638::A' invokes a deleted function}}
// expected-note@-1 {{passing argument to parameter 'a' here}}
- // expected-note@-2 {{candidate function not viable}}
};
- Inner()(); // expected-error {{no matching function}}
+ Inner()(); // expected-error {{type 'Inner' does not provide a call operator}}
}
template void foo<A>(); // expected-note 2 {{in instantiation}}
template <typename T> void bar() {
auto lambda = [](T a = "") {}; // expected-error {{conversion function from 'const char [1]' to 'rdar23721638::A' invokes a deleted function}}
// expected-note@-1 {{passing argument to parameter 'a' here}}
- // expected-note@-2 {{candidate function not viable}}
- // expected-note@-3 {{conversion candidate of type}}
- lambda(); // expected-error {{no matching function}}
+ lambda();
}
template void bar<A>(); // expected-note {{in instantiation}}
}
void f(int x = [](T x = nullptr) -> int { return x; }());
// expected-error@-1 {{cannot initialize a parameter of type 'int' with an rvalue of type 'nullptr_t'}}
// expected-note@-2 {{passing argument to parameter 'x' here}}
- // expected-error@-3 {{no matching function for call}}
- // expected-note@-4 {{candidate function not viable: requires single argument 'x', but no arguments were provided}}
- // expected-note@-5 {{conversion candidate of type 'auto (*)(int) -> int'}}
void g() { f<int>(); }
// expected-note@-1 {{in instantiation of default function argument expression for 'f<int>' required here}}