Skip to content

[Clang] only inherit the parent eval context inside of lambdas #124426

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Jan 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions clang/include/clang/AST/ASTLambda.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
#include "llvm/Support/Casting.h"

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

inline bool isLambdaMethod(const DeclContext *DC) {
if (const auto *MD = dyn_cast_if_present<CXXMethodDecl>(DC))
return MD->getParent()->isLambda();
return false;
}

inline bool isLambdaCallWithExplicitObjectParameter(const DeclContext *DC) {
return isLambdaCallOperator(DC) &&
cast<CXXMethodDecl>(DC)->isExplicitObjectMemberFunction();
Expand Down
15 changes: 9 additions & 6 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

#include "clang/APINotes/APINotesManager.h"
#include "clang/AST/ASTFwd.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/Attr.h"
#include "clang/AST/AttrIterator.h"
#include "clang/AST/CharUnits.h"
Expand Down Expand Up @@ -13108,14 +13109,16 @@ class Sema final : public SemaBase {
? ExpressionEvaluationContext::ImmediateFunctionContext
: ExpressionEvaluationContext::PotentiallyEvaluated);
if (FD) {
auto &Current = S.currentEvaluationContext();
const auto &Parent = S.parentEvaluationContext();

FD->setWillHaveBody(true);
S.ExprEvalContexts.back().InImmediateFunctionContext =
Current.InImmediateFunctionContext =
FD->isImmediateFunction() ||
S.ExprEvalContexts[S.ExprEvalContexts.size() - 2]
.isConstantEvaluated() ||
S.ExprEvalContexts[S.ExprEvalContexts.size() - 2]
.isImmediateFunctionContext();
S.ExprEvalContexts.back().InImmediateEscalatingFunctionContext =
(isLambdaMethod(FD) && (Parent.isConstantEvaluated() ||
Parent.isImmediateFunctionContext()));

Current.InImmediateEscalatingFunctionContext =
S.getLangOpts().CPlusPlus20 && FD->isImmediateEscalating();
} else
assert(isa<ObjCMethodDecl>(DC));
Expand Down
6 changes: 2 additions & 4 deletions clang/lib/AST/ASTImporter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTDiagnostic.h"
#include "clang/AST/ASTImporterSharedState.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/ASTStructuralEquivalence.h"
#include "clang/AST/Attr.h"
#include "clang/AST/Decl.h"
Expand Down Expand Up @@ -3729,10 +3730,7 @@ bool ASTNodeImporter::hasReturnTypeDeclaredInside(FunctionDecl *D) {
if (Importer.FromContext.getLangOpts().CPlusPlus14) // C++14 or later
return false;

if (const auto *MD = dyn_cast<CXXMethodDecl>(D))
return cast<CXXRecordDecl>(MD->getDeclContext())->isLambda();

return false;
return isLambdaMethod(D);
};

QualType RetT = FromFPT->getReturnType();
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/AST/Expr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -895,8 +895,7 @@ std::string PredefinedExpr::ComputeName(PredefinedIdentKind IK,
// type deduction and lambdas. For trailing return types resolve the
// decltype expression. Otherwise print the real type when this is
// not a constructor or destructor.
if (isa<CXXMethodDecl>(FD) &&
cast<CXXMethodDecl>(FD)->getParent()->isLambda())
if (isLambdaMethod(FD))
Proto = "auto " + Proto;
else if (FT && FT->getReturnType()->getAs<DecltypeType>())
FT->getReturnType()
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CodeGen/CGExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "ConstantEmitter.h"
#include "TargetInfo.h"
#include "clang/AST/ASTContext.h"
#include "clang/AST/ASTLambda.h"
#include "clang/AST/Attr.h"
#include "clang/AST/DeclObjC.h"
#include "clang/AST/NSAPI.h"
Expand Down Expand Up @@ -1809,8 +1810,7 @@ CodeGenFunction::tryEmitAsConstant(DeclRefExpr *refExpr) {
if (CGM.getLangOpts().CUDAIsDevice && result.Val.isLValue() &&
refExpr->refersToEnclosingVariableOrCapture()) {
auto *MD = dyn_cast_or_null<CXXMethodDecl>(CurCodeDecl);
if (MD && MD->getParent()->isLambda() &&
MD->getOverloadedOperator() == OO_Call) {
if (isLambdaMethod(MD) && MD->getOverloadedOperator() == OO_Call) {
const APValue::LValueBase &base = result.Val.getLValueBase();
if (const ValueDecl *D = base.dyn_cast<const ValueDecl *>()) {
if (const VarDecl *VD = dyn_cast<const VarDecl>(D)) {
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/Sema/SemaDeclCXX.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -13855,8 +13855,7 @@ void Sema::setupImplicitSpecialMemberType(CXXMethodDecl *SpecialMem,
// During template instantiation of implicit special member functions we need
// a reliable TypeSourceInfo for the function prototype in order to allow
// functions to be substituted.
if (inTemplateInstantiation() &&
cast<CXXRecordDecl>(SpecialMem->getParent())->isLambda()) {
if (inTemplateInstantiation() && isLambdaMethod(SpecialMem)) {
TypeSourceInfo *TSI =
Context.getTrivialTypeSourceInfo(SpecialMem->getType());
SpecialMem->setTypeSourceInfo(TSI);
Expand Down
3 changes: 1 addition & 2 deletions clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2606,8 +2606,7 @@ Decl *TemplateDeclInstantiator::VisitCXXMethodDecl(
// conditionally populate the TSI without breaking non-template related use
// cases. Populate TSIs prior to calling SubstFunctionType to make sure we get
// a proper transformation.
if (cast<CXXRecordDecl>(D->getParent())->isLambda() &&
!D->getTypeSourceInfo() &&
if (isLambdaMethod(D) && !D->getTypeSourceInfo() &&
isa<CXXConstructorDecl, CXXDestructorDecl>(D)) {
TypeSourceInfo *TSI =
SemaRef.Context.getTrivialTypeSourceInfo(D->getType());
Expand Down
14 changes: 14 additions & 0 deletions clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -544,5 +544,19 @@ void g() {
tfn<int>(a); // expected-error {{call to immediate function 'GH123405::tfn<int>' is not a constant expression}}\
// expected-note {{read of non-const variable 'a' is not allowed in a constant expression}}
}
} // namespace GH123405

namespace GH118000 {
consteval int baz() { return 0;}
struct S {
int mSize = baz();
};

consteval void bar() {
S s;
}

void foo() {
S s;
}
} // namespace GH118000
Loading