]> granicus.if.org Git - clang/commitdiff
PR12710 - broken default argument handling for templates.
authorDavid Blaikie <dblaikie@gmail.com>
Tue, 1 May 2012 06:05:57 +0000 (06:05 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Tue, 1 May 2012 06:05:57 +0000 (06:05 +0000)
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

lib/Sema/SemaTemplateInstantiate.cpp
test/CodeGenCXX/destructors.cpp
test/SemaCXX/conversion.cpp

index 3635e64f3d0d4cc9853b72828af7dcd5f0e64b5b..344af6097d8034ce65675353181d47e494732f67 100644 (file)
@@ -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());
   
index d9962e615ec5b65c3e877df7e8a61305716bd701..b8ec2761be86399a94b22f884fb8b93d289216d1 100644 (file)
@@ -350,6 +350,22 @@ namespace test8 {
   // CHECK:      unreachable
 }
 
+// PR12710
+namespace test9 {
+  struct ArgType {
+    ~ArgType();
+  };
+  template<typename T>
+  void f1(const ArgType& = ArgType());
+  void f2();
+  void bar() {
+    f1<int>();
+    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::<anonymous namespace>::D"* %this) unnamed_addr
index 225bc837b562492ba8bdf76aba3e4852095adac8..da78510c6418809ba8790e5c88e1ae039a8c52e7 100644 (file)
@@ -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<typename T>
-  void tmpl(char c = NULL, // expected-warning {{implicit conversion of NULL constant to 'char'}}
+  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}}
@@ -95,8 +97,8 @@ namespace test4 {
   }
 
   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}}
+    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*>();
   }
 }