]> granicus.if.org Git - clang/commitdiff
Fix PR12378: provide conversion warnings on default args of function templates
authorDavid Blaikie <dblaikie@gmail.com>
Mon, 30 Apr 2012 18:21:31 +0000 (18:21 +0000)
committerDavid Blaikie <dblaikie@gmail.com>
Mon, 30 Apr 2012 18:21:31 +0000 (18:21 +0000)
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

lib/Sema/SemaExpr.cpp
lib/Sema/SemaTemplateInstantiate.cpp
test/SemaCXX/conversion.cpp

index 87a67ff632b88777af57e6fd05367d5026676490..4ed588565f1a3af9e69ada7edc0fda7537897bec 100644 (file)
@@ -3300,9 +3300,11 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
     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
index 793ee0e50ade67ea19ef205c61016ae7eb0500cd..3635e64f3d0d4cc9853b72828af7dcd5f0e64b5b 100644 (file)
@@ -1594,8 +1594,13 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
   } 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());
   
index a64b18721a5f2ccc8f1af3f77f2df52815f436ac..225bc837b562492ba8bdf76aba3e4852095adac8 100644 (file)
@@ -81,3 +81,22 @@ void test3() {
 #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*>();
+  }
+}