Fznamznon created this revision. Herald added a project: All. Fznamznon requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
Constant evaluator only considered access to `this` pointer to be possible if `this` poitners was captured. However `this` can also appear if there was a default member initializer. Fixes https://github.com/llvm/llvm-project/issues/60936 Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D144866 Files: clang/lib/AST/ExprConstant.cpp clang/test/SemaCXX/lambda-expressions.cpp Index: clang/test/SemaCXX/lambda-expressions.cpp =================================================================== --- clang/test/SemaCXX/lambda-expressions.cpp +++ clang/test/SemaCXX/lambda-expressions.cpp @@ -665,3 +665,17 @@ // expected-note@-2 2 {{default capture by}} } }; + +#if __cplusplus > 201402L +namespace GH60936 { +struct S { + int i; + int *p = &i; +}; + +static_assert([]() constexpr { + S r = S{2}; + return r.p != nullptr; +}()); +} // namespace GH60936 +#endif Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -8758,16 +8758,19 @@ return false; } Result = *Info.CurrentCall->This; - // If we are inside a lambda's call operator, the 'this' expression refers - // to the enclosing '*this' object (either by value or reference) which is - // either copied into the closure object's field that represents the '*this' - // or refers to '*this'. + if (isLambdaCallOperator(Info.CurrentCall->Callee)) { - // Ensure we actually have captured 'this'. (an error will have - // been previously reported if not). + // Ensure we actually have captured 'this'. If something was wrong with + // 'this' capture, the error would have been previously reported. + // Otherwise we can be inside of a default initialization of an object + // declared by lambda's body, so no need to return false. if (!Info.CurrentCall->LambdaThisCaptureField) - return false; + return true; + // If we have captured 'this', the 'this' expression refers + // to the enclosing '*this' object (either by value or reference) which is + // either copied into the closure object's field that represents the + // '*this' or refers to '*this'. // Update 'Result' to refer to the data member/field of the closure object // that represents the '*this' capture. if (!HandleLValueMember(Info, E, Result,
Index: clang/test/SemaCXX/lambda-expressions.cpp =================================================================== --- clang/test/SemaCXX/lambda-expressions.cpp +++ clang/test/SemaCXX/lambda-expressions.cpp @@ -665,3 +665,17 @@ // expected-note@-2 2 {{default capture by}} } }; + +#if __cplusplus > 201402L +namespace GH60936 { +struct S { + int i; + int *p = &i; +}; + +static_assert([]() constexpr { + S r = S{2}; + return r.p != nullptr; +}()); +} // namespace GH60936 +#endif Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -8758,16 +8758,19 @@ return false; } Result = *Info.CurrentCall->This; - // If we are inside a lambda's call operator, the 'this' expression refers - // to the enclosing '*this' object (either by value or reference) which is - // either copied into the closure object's field that represents the '*this' - // or refers to '*this'. + if (isLambdaCallOperator(Info.CurrentCall->Callee)) { - // Ensure we actually have captured 'this'. (an error will have - // been previously reported if not). + // Ensure we actually have captured 'this'. If something was wrong with + // 'this' capture, the error would have been previously reported. + // Otherwise we can be inside of a default initialization of an object + // declared by lambda's body, so no need to return false. if (!Info.CurrentCall->LambdaThisCaptureField) - return false; + return true; + // If we have captured 'this', the 'this' expression refers + // to the enclosing '*this' object (either by value or reference) which is + // either copied into the closure object's field that represents the + // '*this' or refers to '*this'. // Update 'Result' to refer to the data member/field of the closure object // that represents the '*this' capture. if (!HandleLValueMember(Info, E, Result,
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits