Apparently we weren't checking default arguments when they were instantiated.
This adds the check, fixes the lack of instantiation caching (which seems like
it was mostly implemented but just missed the last step), and avoids
implementing non-dependent default args (for non-dependent parameter types) as
uninstantiated default arguments (so that we don't warn once for every
instantiation when it's not instantiation dependent).
Reviewed by Richard Smith.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155838
91177308-0d34-0410-b5e6-
96231b3b80d8
if (Result.isInvalid())
return ExprError();
+ Expr *Arg = Result.takeAs<Expr>();
+ CheckImplicitConversions(Arg, Arg->getExprLoc());
+ Param->setDefaultArg(Arg);
// Build the default argument expression.
- return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param,
- Result.takeAs<Expr>()));
+ return Owned(CXXDefaultArgExpr::Create(Context, CallLoc, Param, Arg));
}
// If the default expression creates temporaries, we need to
} else if (OldParm->hasUnparsedDefaultArg()) {
NewParm->setUnparsedDefaultArg();
UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm);
- } else if (Expr *Arg = OldParm->getDefaultArg())
- NewParm->setUninstantiatedDefaultArg(Arg);
+ } else if (Expr *Arg = OldParm->getDefaultArg()) {
+ if (Arg->isInstantiationDependent() ||
+ OldDI->getType()->isInstantiationDependentType())
+ NewParm->setUninstantiatedDefaultArg(Arg);
+ else
+ NewParm->setDefaultArg(Arg);
+ }
NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg());
#define FINIT int a3 = NULL;
FINIT // expected-warning {{implicit conversion of NULL constant to 'int'}}
}
+
+namespace test4 {
+ template<typename T>
+ void tmpl(char c = NULL, // expected-warning {{implicit conversion of NULL constant to 'char'}}
+ T a = NULL, // expected-warning {{implicit conversion of NULL constant to 'char'}} \
+ expected-warning {{implicit conversion of NULL constant to 'int'}}
+ T b = 1024) { // expected-warning {{implicit conversion from 'int' to 'char' changes value from 1024 to 0}}
+ }
+
+ template<typename T>
+ void tmpl2(T t = NULL) {
+ }
+
+ void func() {
+ tmpl<char>(); // expected-note {{in instantiation of default function argument expression for 'tmpl<char>' required here}}
+ tmpl<int>(); // expected-note {{in instantiation of default function argument expression for 'tmpl<int>' required here}}
+ tmpl2<int*>();
+ }
+}