Correctly type-check the default arguments of local functions
authorJohn McCall <rjmccall@apple.com>
Fri, 11 Dec 2015 01:56:36 +0000 (01:56 +0000)
committerJohn McCall <rjmccall@apple.com>
Fri, 11 Dec 2015 01:56:36 +0000 (01:56 +0000)
when eagerly instantiating them.

rdar://23721638

llvm-svn: 255325

clang/lib/Sema/SemaTemplateInstantiate.cpp
clang/test/SemaTemplate/instantiate-local-class.cpp

index 3a3f632..ac99a25 100644 (file)
@@ -1680,8 +1680,11 @@ ParmVarDecl *Sema::SubstParmVarDecl(ParmVarDecl *OldParm,
       Sema::ContextRAII SavedContext(*this, OwningFunc);
       LocalInstantiationScope Local(*this);
       ExprResult NewArg = SubstExpr(Arg, TemplateArgs);
-      if (NewArg.isUsable())
-        NewParm->setDefaultArg(NewArg.get());
+      if (NewArg.isUsable()) {
+        // It would be nice if we still had this.
+        SourceLocation EqualLoc = NewArg.get()->getLocStart();
+        SetParamDefaultArgument(NewParm, NewArg.get(), EqualLoc);
+      }
     } else {
       // FIXME: if we non-lazily instantiated non-dependent default args for
       // non-dependent parameter types we could remove a bunch of duplicate
index c0ea6a0..a61af7a 100644 (file)
@@ -448,3 +448,30 @@ namespace PR21332 {
   }
   template void f7<int>();
 }
+
+// rdar://23721638: Ensure that we correctly perform implicit
+// conversions when instantiating the default arguments of local functions.
+namespace rdar23721638 {
+  struct A {
+    A(const char *) = delete;  // expected-note 2 {{explicitly marked deleted here}}
+  };
+
+  template <typename T> void foo() {
+    struct Inner { // expected-note {{in instantiation}}
+      void operator()(T a = "") {} // expected-error {{conversion function from 'const char [1]' to 'rdar23721638::A' invokes a deleted function}}
+      // expected-note@-1 {{passing argument to parameter 'a' here}}
+      // expected-note@-2 {{candidate function not viable}}
+    };
+    Inner()(); // expected-error {{no matching function}}
+  }
+  template void foo<A>(); // expected-note 2 {{in instantiation}}
+
+  template <typename T> void bar() {
+    auto lambda = [](T a = "") {}; // expected-error {{conversion function from 'const char [1]' to 'rdar23721638::A' invokes a deleted function}}
+      // expected-note@-1 {{passing argument to parameter 'a' here}}
+      // expected-note@-2 {{candidate function not viable}}
+      // expected-note@-3 {{conversion candidate of type}}
+    lambda(); // expected-error {{no matching function}}
+  }
+  template void bar<A>(); // expected-note {{in instantiation}}
+}