Skip to content

Commit 15e772e

Browse files
committed
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.
1 parent ebdcef2 commit 15e772e

File tree

3 files changed

+19
-1
lines changed

3 files changed

+19
-1
lines changed

clang/lib/Sema/SemaTemplateInstantiate.cpp

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2696,7 +2696,10 @@ Sema::InstantiateClass(SourceLocation PointOfInstantiation,
26962696

26972697
// BlockDecls can appear in a default-member-initializer. They must be the
26982698
// child of a BlockExpr, so we only know how to instantiate them from there.
2699-
if (isa<BlockDecl>(Member))
2699+
// Similarly, lambda closure types are recreated when instantiating the
2700+
// corresponding LambdaExpr.
2701+
if (isa<BlockDecl>(Member) ||
2702+
(isa<CXXRecordDecl>(Member) && cast<CXXRecordDecl>(Member)->isLambda()))
27002703
continue;
27012704

27022705
if (Member->isInvalidDecl()) {

clang/test/SemaTemplate/explicit-instantiation.cpp

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,4 +179,10 @@ struct B : A<0> {
179179
virtual void foo() override; // expected-error{{declaration of 'foo' overrides a 'final' function}}
180180
};
181181
}
182+
183+
template<typename T> struct LambdaInDefaultMemberInitInExplicitInstantiation {
184+
int a = [this] { return a; }();
185+
};
186+
template struct LambdaInDefaultMemberInitInExplicitInstantiation<int>;
187+
LambdaInDefaultMemberInitInExplicitInstantiation<float> x;
182188
#endif

clang/test/SemaTemplate/instantiate-local-class.cpp

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -495,3 +495,12 @@ namespace PR45000 {
495495
void g() { f<int>(); }
496496
// expected-note@-1 {{in instantiation of default function argument expression for 'f<int>' required here}}
497497
}
498+
499+
namespace LambdaInDefaultMemberInitializer {
500+
template<typename T> void f() {
501+
struct S {
502+
void *p = [this] { return &p; }();
503+
};
504+
}
505+
template void f<int>();
506+
}

0 commit comments

Comments
 (0)