Author: Richard Smith
Date: 2020-10-20T17:37:07-07:00
New Revision: 15e772e8dc39f609115430f39078fbe58812fddb

URL: 
https://github.com/llvm/llvm-project/commit/15e772e8dc39f609115430f39078fbe58812fddb
DIFF: 
https://github.com/llvm/llvm-project/commit/15e772e8dc39f609115430f39078fbe58812fddb.diff

LOG: Don't instantiate lambda closure types in default member initializers
when instantiating the enclosing class.

We'll build new lambda closure types if and when we instantiate the
default member initializer, and instantiating the closure type by itself
can go wrong in cases where we fully-instantiate nested classes (in
explicit instantiations of the enclosing class and when the enclosing
class is a local class) -- we will instantiate the 'operator()' as a
regular function rather than as a lambda call operator, so it doesn't
get to use its captures, has the wrong 'this' type, etc.

Added: 
    

Modified: 
    clang/lib/Sema/SemaTemplateInstantiate.cpp
    clang/test/SemaTemplate/explicit-instantiation.cpp
    clang/test/SemaTemplate/instantiate-local-class.cpp

Removed: 
    


################################################################################
diff  --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp 
b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 2e96eaa7df1a..a13118839036 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -2696,7 +2696,10 @@ Sema::InstantiateClass(SourceLocation 
PointOfInstantiation,
 
     // BlockDecls can appear in a default-member-initializer. They must be the
     // child of a BlockExpr, so we only know how to instantiate them from 
there.
-    if (isa<BlockDecl>(Member))
+    // Similarly, lambda closure types are recreated when instantiating the
+    // corresponding LambdaExpr.
+    if (isa<BlockDecl>(Member) ||
+        (isa<CXXRecordDecl>(Member) && 
cast<CXXRecordDecl>(Member)->isLambda()))
       continue;
 
     if (Member->isInvalidDecl()) {

diff  --git a/clang/test/SemaTemplate/explicit-instantiation.cpp 
b/clang/test/SemaTemplate/explicit-instantiation.cpp
index d88c50bc29de..73f07ef41347 100644
--- a/clang/test/SemaTemplate/explicit-instantiation.cpp
+++ b/clang/test/SemaTemplate/explicit-instantiation.cpp
@@ -179,4 +179,10 @@ struct B : A<0> {
   virtual void foo() override; // expected-error{{declaration of 'foo' 
overrides a 'final' function}}
 };
 }
+
+template<typename T> struct LambdaInDefaultMemberInitInExplicitInstantiation {
+  int a = [this] { return a; }();
+};
+template struct LambdaInDefaultMemberInitInExplicitInstantiation<int>;
+LambdaInDefaultMemberInitInExplicitInstantiation<float> x;
 #endif

diff  --git a/clang/test/SemaTemplate/instantiate-local-class.cpp 
b/clang/test/SemaTemplate/instantiate-local-class.cpp
index 15b455f62569..65caaa1a43e8 100644
--- a/clang/test/SemaTemplate/instantiate-local-class.cpp
+++ b/clang/test/SemaTemplate/instantiate-local-class.cpp
@@ -495,3 +495,12 @@ namespace PR45000 {
   void g() { f<int>(); }
   // expected-note@-1 {{in instantiation of default function argument 
expression for 'f<int>' required here}}
 }
+
+namespace LambdaInDefaultMemberInitializer {
+  template<typename T> void f() {
+    struct S {
+      void *p = [this] { return &p; }();
+    };
+  }
+  template void f<int>();
+}


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to