From: David Blaikie Date: Tue, 1 May 2012 06:05:57 +0000 (+0000) Subject: PR12710 - broken default argument handling for templates. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=5729672524865f212cbadb51170dca0694e79a71;p=clang PR12710 - broken default argument handling for templates. I broke this in r155838 by not actually instantiating non-dependent default arg expressions. The motivation for that change was to avoid producing duplicate conversion warnings for such default args (we produce them once when we parse the template - there's no need to produce them at each instantiation) but without actually instantiating the default arg, things break in weird ways. Technically, I think we could still get the right diagnostic experience without the bugs if we instantiated the non-dependent args (for non-dependent params only) immediately, rather than lazily. But I'm not sure if such a refactoring/ change would be desirable so here's the conservative fix for now. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@155893 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/Sema/SemaTemplateInstantiate.cpp b/lib/Sema/SemaTemplateInstantiate.cpp index 3635e64f3d..344af6097d 100644 --- a/lib/Sema/SemaTemplateInstantiate.cpp +++ b/lib/Sema/SemaTemplateInstantiate.cpp @@ -1594,13 +1594,11 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm, } else if (OldParm->hasUnparsedDefaultArg()) { NewParm->setUnparsedDefaultArg(); UnparsedDefaultArgInstantiations[OldParm].push_back(NewParm); - } else if (Expr *Arg = OldParm->getDefaultArg()) { - if (Arg->isInstantiationDependent() || - OldDI->getType()->isInstantiationDependentType()) - NewParm->setUninstantiatedDefaultArg(Arg); - else - NewParm->setDefaultArg(Arg); - } + } else if (Expr *Arg = OldParm->getDefaultArg()) + // FIXME: if we non-lazily instantiated non-dependent default args for + // non-dependent parameter types we could remove a bunch of duplicate + // conversion warnings for such arguments. + NewParm->setUninstantiatedDefaultArg(Arg); NewParm->setHasInheritedDefaultArg(OldParm->hasInheritedDefaultArg()); diff --git a/test/CodeGenCXX/destructors.cpp b/test/CodeGenCXX/destructors.cpp index d9962e615e..b8ec2761be 100644 --- a/test/CodeGenCXX/destructors.cpp +++ b/test/CodeGenCXX/destructors.cpp @@ -350,6 +350,22 @@ namespace test8 { // CHECK: unreachable } +// PR12710 +namespace test9 { + struct ArgType { + ~ArgType(); + }; + template + void f1(const ArgType& = ArgType()); + void f2(); + void bar() { + f1(); + f2(); + } + // CHECK: call void @_ZN5test97ArgTypeD1Ev(%"struct.test9::ArgType"* %ref.tmp) + // CHECK: call void @_ZN5test92f2Ev() +} + // Checks from test3: // CHECK: define internal void @_ZN5test312_GLOBAL__N_11DD0Ev(%"struct.test3::::D"* %this) unnamed_addr diff --git a/test/SemaCXX/conversion.cpp b/test/SemaCXX/conversion.cpp index 225bc837b5..da78510c64 100644 --- a/test/SemaCXX/conversion.cpp +++ b/test/SemaCXX/conversion.cpp @@ -83,8 +83,10 @@ void test3() { } namespace test4 { + // FIXME: We should warn for non-dependent args (only when the param type is also non-dependent) only once + // not once for the template + once for every instantiation template - void tmpl(char c = NULL, // expected-warning {{implicit conversion of NULL constant to 'char'}} + void tmpl(char c = NULL, // expected-warning 3 {{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}} @@ -95,8 +97,8 @@ namespace test4 { } void func() { - tmpl(); // expected-note {{in instantiation of default function argument expression for 'tmpl' required here}} - tmpl(); // expected-note {{in instantiation of default function argument expression for 'tmpl' required here}} + tmpl(); // expected-note 2 {{in instantiation of default function argument expression for 'tmpl' required here}} + tmpl(); // expected-note 2 {{in instantiation of default function argument expression for 'tmpl' required here}} tmpl2(); } }