Skip to content

Commit 139531b

Browse files
committed
[Clang] only inherit the parent eval context inside of lambdas
As we create defaul constructors lazily, we should not inherit from the parent evaluation context. However, we need to make an exception for lambdas (in particular their conversion operators, which are also implicitly defined). As a drive-by, we introduce a generic way to query whether a function is a member of a lambda. This fixes a regression introduced by baf6bd3. Fixes #118000
1 parent 658f850 commit 139531b

File tree

8 files changed

+37
-18
lines changed

8 files changed

+37
-18
lines changed

clang/include/clang/AST/ASTLambda.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717

1818
#include "clang/AST/DeclCXX.h"
1919
#include "clang/AST/DeclTemplate.h"
20+
#include "llvm/Support/Casting.h"
2021

2122
namespace clang {
2223
inline StringRef getLambdaStaticInvokerName() {
@@ -35,6 +36,12 @@ inline bool isLambdaCallOperator(const DeclContext *DC) {
3536
return isLambdaCallOperator(cast<CXXMethodDecl>(DC));
3637
}
3738

39+
inline bool isLambdaMethod(const DeclContext *DC) {
40+
if (auto *MD = dyn_cast_or_null<CXXMethodDecl>(DC); MD)
41+
return MD->getParent()->isLambda();
42+
return false;
43+
}
44+
3845
inline bool isLambdaCallWithExplicitObjectParameter(const DeclContext *DC) {
3946
return isLambdaCallOperator(DC) &&
4047
cast<CXXMethodDecl>(DC)->isExplicitObjectMemberFunction();

clang/include/clang/Sema/Sema.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
#include "clang/APINotes/APINotesManager.h"
1818
#include "clang/AST/ASTFwd.h"
19+
#include "clang/AST/ASTLambda.h"
1920
#include "clang/AST/Attr.h"
2021
#include "clang/AST/AttrIterator.h"
2122
#include "clang/AST/CharUnits.h"
@@ -13108,14 +13109,16 @@ class Sema final : public SemaBase {
1310813109
? ExpressionEvaluationContext::ImmediateFunctionContext
1310913110
: ExpressionEvaluationContext::PotentiallyEvaluated);
1311013111
if (FD) {
13112+
auto &Current = S.currentEvaluationContext(),
13113+
Parent = S.parentEvaluationContext();
13114+
1311113115
FD->setWillHaveBody(true);
13112-
S.ExprEvalContexts.back().InImmediateFunctionContext =
13116+
Current.InImmediateFunctionContext =
1311313117
FD->isImmediateFunction() ||
13114-
S.ExprEvalContexts[S.ExprEvalContexts.size() - 2]
13115-
.isConstantEvaluated() ||
13116-
S.ExprEvalContexts[S.ExprEvalContexts.size() - 2]
13117-
.isImmediateFunctionContext();
13118-
S.ExprEvalContexts.back().InImmediateEscalatingFunctionContext =
13118+
(isLambdaMethod(FD) && (Parent.isConstantEvaluated() ||
13119+
Parent.isImmediateFunctionContext()));
13120+
13121+
Current.InImmediateEscalatingFunctionContext =
1311913122
S.getLangOpts().CPlusPlus20 && FD->isImmediateEscalating();
1312013123
} else
1312113124
assert(isa<ObjCMethodDecl>(DC));

clang/lib/AST/ASTImporter.cpp

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
#include "clang/AST/ASTContext.h"
1616
#include "clang/AST/ASTDiagnostic.h"
1717
#include "clang/AST/ASTImporterSharedState.h"
18+
#include "clang/AST/ASTLambda.h"
1819
#include "clang/AST/ASTStructuralEquivalence.h"
1920
#include "clang/AST/Attr.h"
2021
#include "clang/AST/Decl.h"
@@ -3729,10 +3730,7 @@ bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
37293730
if (Importer.FromContext.getLangOpts().CPlusPlus14) // C++14 or later
37303731
return false;
37313732

3732-
if (const auto *MD = dyn_cast<CXXMethodDecl>(D))
3733-
return cast<CXXRecordDecl>(MD->getDeclContext())->isLambda();
3734-
3735-
return false;
3733+
return isLambdaMethod(D);
37363734
};
37373735

37383736
QualType RetT = FromFPT->getReturnType();

clang/lib/AST/Expr.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -895,8 +895,7 @@ std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK,
895895
// type deduction and lambdas. For trailing return types resolve the
896896
// decltype expression. Otherwise print the real type when this is
897897
// not a constructor or destructor.
898-
if (isa<CXXMethodDecl>(FD) &&
899-
cast<CXXMethodDecl>(FD)->getParent()->isLambda())
898+
if (isLambdaMethod(FD))
900899
Proto = "auto " + Proto;
901900
else if (FT && FT->getReturnType()->getAs<DecltypeType>())
902901
FT->getReturnType()

clang/lib/CodeGen/CGExpr.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "ConstantEmitter.h"
2525
#include "TargetInfo.h"
2626
#include "clang/AST/ASTContext.h"
27+
#include "clang/AST/ASTLambda.h"
2728
#include "clang/AST/Attr.h"
2829
#include "clang/AST/DeclObjC.h"
2930
#include "clang/AST/NSAPI.h"
@@ -1809,8 +1810,7 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
18091810
if (CGM.getLangOpts().CUDAIsDevice && result.Val.isLValue() &&
18101811
refExpr->refersToEnclosingVariableOrCapture()) {
18111812
auto *MD = dyn_cast_or_null<CXXMethodDecl>(CurCodeDecl);
1812-
if (MD && MD->getParent()->isLambda() &&
1813-
MD->getOverloadedOperator() == OO_Call) {
1813+
if (isLambdaMethod(MD) && MD->getOverloadedOperator() == OO_Call) {
18141814
const APValue::LValueBase &base = result.Val.getLValueBase();
18151815
if (const ValueDecl *D = base.dyn_cast<const ValueDecl *>()) {
18161816
if (const VarDecl *VD = dyn_cast<const VarDecl>(D)) {

clang/lib/Sema/SemaDeclCXX.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13855,8 +13855,7 @@ void Sema::setupImplicitSpecialMemberType(CXXMethodDecl *SpecialMem,
1385513855
// During template instantiation of implicit special member functions we need
1385613856
// a reliable TypeSourceInfo for the function prototype in order to allow
1385713857
// functions to be substituted.
13858-
if (inTemplateInstantiation() &&
13859-
cast<CXXRecordDecl>(SpecialMem->getParent())->isLambda()) {
13858+
if (inTemplateInstantiation() && isLambdaMethod(SpecialMem)) {
1386013859
TypeSourceInfo *TSI =
1386113860
Context.getTrivialTypeSourceInfo(SpecialMem->getType());
1386213861
SpecialMem->setTypeSourceInfo(TSI);

clang/lib/Sema/SemaTemplateInstantiateDecl.cpp

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2606,8 +2606,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
26062606
// conditionally populate the TSI without breaking non-template related use
26072607
// cases. Populate TSIs prior to calling SubstFunctionType to make sure we get
26082608
// a proper transformation.
2609-
if (cast<CXXRecordDecl>(D->getParent())->isLambda() &&
2610-
!D->getTypeSourceInfo() &&
2609+
if (isLambdaMethod(D) && !D->getTypeSourceInfo() &&
26112610
isa<CXXConstructorDecl, CXXDestructorDecl>(D)) {
26122611
TypeSourceInfo *TSI =
26132612
SemaRef.Context.getTrivialTypeSourceInfo(D->getType());

clang/test/SemaCXX/cxx2b-consteval-propagate.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -544,5 +544,19 @@ void g() {
544544
tfn<int>(a); // expected-error {{call to immediate function 'GH123405::tfn<int>' is not a constant expression}}\
545545
// expected-note {{read of non-const variable 'a' is not allowed in a constant expression}}
546546
}
547+
} // namespace GH123405
547548

549+
namespace GH118000 {
550+
consteval int baz() { return 0;}
551+
struct S {
552+
int mSize = baz();
553+
};
554+
555+
consteval void bar() {
556+
S s;
557+
}
558+
559+
void foo() {
560+
S s;
548561
}
562+
} // namespace GH118000

0 commit comments

Comments
 (0)