// copy-initialization semantics (8.5).
if (CheckInitializerTypes(Arg, ParamType, EqualLoc,
Param->getDeclName(), /*DirectInit=*/false))
- return false;
+ return true;
Arg = MaybeCreateCXXExprWithTemporaries(Arg, /*DestroyTemps=*/false);
DefaultArg.release();
- return true;
+ return false;
}
/// ActOnParamDefaultArgument - Check whether the default argument
Diag(UnparsedDefaultArgLocs[Param],
diag::note_default_argument_declared_here);
} else {
+ if (Param->hasUninstantiatedDefaultArg()) {
+ Expr *UninstExpr = Param->getUninstantiatedDefaultArg();
+
+ // Instantiate the expression.
+ const TemplateArgumentList &ArgList =
+ getTemplateInstantiationArgs(FDecl);
+
+ // FIXME: We should really make a new InstantiatingTemplate ctor
+ // that has a better message - right now we're just piggy-backing
+ // off the "default template argument" error message.
+ InstantiatingTemplate Inst(*this, Call->getSourceRange().getBegin(),
+ FDecl->getPrimaryTemplate(),
+ ArgList.getFlatArgumentList(),
+ ArgList.flat_size());
+
+ OwningExprResult Result
+ = InstantiateExpr(UninstExpr,
+ getTemplateInstantiationArgs(FDecl));
+ if (Result.isInvalid())
+ return true;
+
+ if (SetParamDefaultArgument(Param, move(Result),
+ /*FIXME:EqualLoc*/
+ UninstExpr->getSourceRange().getBegin()))
+ return true;
+ }
+
Expr *DefaultExpr = Param->getDefaultArg();
// If the default expression creates temporaries, we need to
QualType T = SemaRef.adjustParameterType(OrigT);
- if (D->getDefaultArg()) {
- // FIXME: Leave a marker for "uninstantiated" default
- // arguments. They only get instantiated on demand at the call
- // site.
- unsigned DiagID = SemaRef.Diags.getCustomDiagID(Diagnostic::Warning,
- "sorry, dropping default argument during template instantiation");
- SemaRef.Diag(D->getDefaultArg()->getSourceRange().getBegin(), DiagID)
- << D->getDefaultArg()->getSourceRange();
- }
-
// Allocate the parameter
ParmVarDecl *Param = 0;
if (T == OrigT)
T, D->getDeclaratorInfo(), OrigT,
D->getStorageClass(), 0);
+ // Mark the default argument as being uninstantiated.
+ if (Expr *Arg = D->getDefaultArg())
+ Param->setUninstantiatedDefaultArg(Arg);
+
// Note: we don't try to instantiate function parameters until after
// we've instantiated the function's type. Therefore, we don't have
// to check for 'void' parameter types here.
--- /dev/null
+// RUN: clang-cc -fsyntax-only -verify %s
+
+struct S { };
+
+template<typename T> void f1(T a, T b = 10) { } // expected-error{{cannot initialize 'b' with an rvalue of type 'int'}}
+
+template<typename T> void f2(T a, T b = T()) { }
+
+template<typename T> void f3(T a, T b = T() + T()); // expected-error{{invalid operands to binary expression ('struct S' and 'struct S')}}
+
+void g() {
+ f1(10);
+ f1(S()); // expected-note{{in instantiation of default argument for 'f1<struct S>' required here}}
+
+ f2(10);
+ f2(S());
+
+ f3(10);
+ f3(S()); // expected-note{{in instantiation of default argument for 'f3<struct S>' required here}}
+}