]> granicus.if.org Git - clang/commitdiff
Lambda closure types are always considered to be like "local" classes,
authorDouglas Gregor <dgregor@apple.com>
Thu, 16 Feb 2012 21:36:18 +0000 (21:36 +0000)
committerDouglas Gregor <dgregor@apple.com>
Thu, 16 Feb 2012 21:36:18 +0000 (21:36 +0000)
even if they are not within a function scope. Teach template
instantiation to treat them as such, and make sure that we have a
local instantiation scope when instantiating default arguments and
static data members.

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@150725 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Sema/SemaExpr.cpp
lib/Sema/SemaTemplateInstantiateDecl.cpp
test/CXX/expr/expr.prim/expr.prim.lambda/templates.cpp

index 6b66a42ad3457712c87b9b93e7c3b7281e7f5620..5202f96354d81e4aaa24069027aaccf4d02dbf6e 100644 (file)
@@ -3128,6 +3128,7 @@ ExprResult Sema::BuildCXXDefaultArgExpr(SourceLocation CallLoc,
       //   the semantic constraints are checked, at the point where the
       //   default argument expression appears.
       ContextRAII SavedContext(*this, FD);
+      LocalInstantiationScope Local(*this);
       Result = SubstExpr(UninstExpr, ArgList);
     }
     if (Result.isInvalid())
index f480825412307b093e8423c053a6b8e096f4b4f0..d491dfc51ed4440fd4950301de74fecc0d5f8340 100644 (file)
@@ -2629,7 +2629,8 @@ void Sema::InstantiateStaticDataMemberDefinition(
   // Enter the scope of this instantiation. We don't use
   // PushDeclContext because we don't have a scope.
   ContextRAII previousContext(*this, Var->getDeclContext());
-
+  LocalInstantiationScope Local(*this);
+  
   VarDecl *OldVar = Var;
   Var = cast_or_null<VarDecl>(SubstDecl(Def, Var->getDeclContext(),
                                         getTemplateInstantiationArgs(Var)));
@@ -2644,7 +2645,8 @@ void Sema::InstantiateStaticDataMemberDefinition(
     DeclGroupRef DG(Var);
     Consumer.HandleTopLevelDecl(DG);
   }
-
+  Local.Exit();
+  
   if (Recursive) {
     // Define any newly required vtables.
     DefineUsedVTables();
@@ -3096,7 +3098,8 @@ NamedDecl *Sema::FindInstantiatedDecl(SourceLocation Loc, NamedDecl *D,
   DeclContext *ParentDC = D->getDeclContext();
   if (isa<ParmVarDecl>(D) || isa<NonTypeTemplateParmDecl>(D) ||
       isa<TemplateTypeParmDecl>(D) || isa<TemplateTemplateParmDecl>(D) ||
-      (ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext())) {
+      (ParentDC->isFunctionOrMethod() && ParentDC->isDependentContext()) ||
+      (isa<CXXRecordDecl>(D) && cast<CXXRecordDecl>(D)->isLambda())) {
     // D is a local of some kind. Look into the map of local
     // declarations to their instantiations.
     typedef LocalInstantiationScope::DeclArgumentPack DeclArgumentPack;
index 14491cc3b208b9c5515ad1ec2f6105d5eea28574..49b9c66b1ce547132a3feb721b5dfaab90aa939d 100644 (file)
@@ -114,3 +114,36 @@ namespace p5 {
 
   template void double_capture(NonConstCopy&);
 }
+
+namespace NonLocalLambdaInstantation {
+  template<typename T>
+  struct X {
+    static int value;
+  };
+
+  template<typename T>
+  int X<T>::value = []{ return T(); }(); // expected-error{{cannot initialize a variable of type 'int' with an rvalue of type 'int *'}}
+
+  template int X<int>::value;
+  template int X<float>::value;
+  template int X<int*>::value; // expected-note{{in instantiation of static data member }}
+
+  template<typename T>
+  void defaults(int x = []{ return T(); }()) { }; // expected-error{{cannot initialize a parameter of type 'int' with an rvalue of type 'int *'}} \
+     // expected-note{{passing argument to parameter 'x' here}}
+
+  void call_defaults() {
+    defaults<int>();
+    defaults<float>();
+    defaults<int*>(); // expected-note{{in instantiation of default function argument expression for 'defaults<int *>' required here}}
+  }
+
+  template<typename T>
+  struct X2 {
+    int x = []{ return T(); }(); // expected-error{{cannot initialize a member subobject of type 'int' with an rvalue of type 'int *'}}
+  };
+
+  X2<int> x2i;
+  X2<float> x2f;
+  X2<int*> x2ip; // expected-note{{in instantiation of template class 'NonLocalLambdaInstantation::X2<int *>' requested here}}
+}