[Clang] [Sema] Always rebuild this
if captured by value in a lambda with a dependent explicit object parameter (#154276)
We have a flag that tracks whether a `CXXThisExpr` refers to a `*this` capture in a lambda with a dependent explicit object parameter; this is to mark it and member accesses involving it as dependent because there is no other way to track that (DREs have a similar flag); when instantiating the lambda, we need to always rebuild the `CXXThisExpr` to potentially clear that flag if the explicit object parameter is no longer dependent. Fixes #154054.
This commit is contained in:
parent
58c41b7491
commit
7f20c6c29e
@ -232,6 +232,8 @@ Bug Fixes to C++ Support
|
||||
"intializing multiple members of union" coincide (#GH149985).
|
||||
- Fix a crash when using ``explicit(bool)`` in pre-C++11 language modes. (#GH152729)
|
||||
- Fix the parsing of variadic member functions when the ellipis immediately follows a default argument.(#GH153445)
|
||||
- Fixed a bug that caused ``this`` captured by value in a lambda with a dependent explicit object parameter to not be
|
||||
instantiated properly. (#GH154054)
|
||||
|
||||
Bug Fixes to AST Handling
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -14326,7 +14326,9 @@ TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
|
||||
// for type deduction, so we need to recompute it.
|
||||
//
|
||||
// Always recompute the type if we're in the body of a lambda, and
|
||||
// 'this' is dependent on a lambda's explicit object parameter.
|
||||
// 'this' is dependent on a lambda's explicit object parameter; we
|
||||
// also need to always rebuild the expression in this case to clear
|
||||
// the flag.
|
||||
QualType T = [&]() {
|
||||
auto &S = getSema();
|
||||
if (E->isCapturedByCopyInLambdaWithExplicitObjectParameter())
|
||||
@ -14336,7 +14338,8 @@ TreeTransform<Derived>::TransformCXXThisExpr(CXXThisExpr *E) {
|
||||
return S.getCurrentThisType();
|
||||
}();
|
||||
|
||||
if (!getDerived().AlwaysRebuild() && T == E->getType()) {
|
||||
if (!getDerived().AlwaysRebuild() && T == E->getType() &&
|
||||
!E->isCapturedByCopyInLambdaWithExplicitObjectParameter()) {
|
||||
// Mark it referenced in the new context regardless.
|
||||
// FIXME: this is a bit instantiation-specific.
|
||||
getSema().MarkThisReferenced(E);
|
||||
|
@ -264,3 +264,55 @@ void test() {
|
||||
// CHECK: call void @_ZNH5P27971C1cERKS0_
|
||||
// CHECK: call void @_ZN5P27971C1cEi
|
||||
}
|
||||
|
||||
// This used to crash because we weren’t instantiating a dependent 'this'.
|
||||
namespace GH154054 {
|
||||
struct S {
|
||||
int x;
|
||||
auto byval() {
|
||||
return [*this](this auto) { return this->x; };
|
||||
}
|
||||
};
|
||||
|
||||
// CHECK-LABEL: define {{.*}} void @_ZN8GH1540544mainEv
|
||||
void main() {
|
||||
S s{ 42 };
|
||||
|
||||
// CHECK: call {{.*}} i32 @_ZZN8GH1540541S5byvalEvENHUlT_E_clIS2_EEDaS1_
|
||||
if ( s.byval()() != 42)
|
||||
__builtin_abort();
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define {{.*}} i32 @_ZZN8GH1540541S5byvalEvENHUlT_E_clIS2_EEDaS1_(i32 %.coerce)
|
||||
// CHECK: entry:
|
||||
// CHECK: %0 = alloca %class.anon.11, align 4
|
||||
// CHECK: %coerce.dive = getelementptr inbounds nuw %class.anon.11, ptr %0, i32 0, i32 0
|
||||
// CHECK: %coerce.dive1 = getelementptr inbounds nuw %"struct.GH154054::S", ptr %coerce.dive, i32 0, i32 0
|
||||
// CHECK: store i32 %.coerce, ptr %coerce.dive1, align 4
|
||||
// CHECK: %1 = getelementptr inbounds nuw %class.anon.11, ptr %0, i32 0, i32 0
|
||||
// CHECK: %x = getelementptr inbounds nuw %"struct.GH154054::S", ptr %1, i32 0, i32 0
|
||||
// CHECK: %2 = load i32, ptr %x, align 4
|
||||
// CHECK: ret i32 %2
|
||||
|
||||
struct s {
|
||||
int q;
|
||||
auto f() {
|
||||
return [*this](this auto) { return this; };
|
||||
}
|
||||
};
|
||||
|
||||
// CHECK-LABEL: define {{.*}} void @_ZN8GH1540541fEv
|
||||
void f() {
|
||||
// CHECK: call {{.*}} ptr @_ZZN8GH1540541s1fEvENHUlT_E_clIS2_EEDaS1_
|
||||
s{}.f()();
|
||||
}
|
||||
|
||||
// CHECK-LABEL: define {{.*}} ptr @_ZZN8GH1540541s1fEvENHUlT_E_clIS2_EEDaS1_(i32 %.coerce)
|
||||
// CHECK: entry:
|
||||
// CHECK: %0 = alloca %class.anon.12, align 4
|
||||
// CHECK: %coerce.dive = getelementptr inbounds nuw %class.anon.12, ptr %0, i32 0, i32 0
|
||||
// CHECK: %coerce.dive1 = getelementptr inbounds nuw %"struct.GH154054::s", ptr %coerce.dive, i32 0, i32 0
|
||||
// CHECK: store i32 %.coerce, ptr %coerce.dive1, align 4
|
||||
// CHECK: %1 = getelementptr inbounds nuw %class.anon.12, ptr %0, i32 0, i32 0
|
||||
// CHECK: ret ptr %1
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user