[clang] a85b2dc - [Clang] only inherit the parent eval context inside of lambdas (#124426)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Jan 27 12:30:33 PST 2025
Author: cor3ntin
Date: 2025-01-27T21:30:29+01:00
New Revision: a85b2dc45a5f1312d6ee5e2522c24e81a086bf60
URL: https://github.com/llvm/llvm-project/commit/a85b2dc45a5f1312d6ee5e2522c24e81a086bf60
DIFF: https://github.com/llvm/llvm-project/commit/a85b2dc45a5f1312d6ee5e2522c24e81a086bf60.diff
LOG: [Clang] only inherit the parent eval context inside of lambdas (#124426)
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
Added:
Modified:
clang/include/clang/AST/ASTLambda.h
clang/include/clang/Sema/Sema.h
clang/lib/AST/ASTImporter.cpp
clang/lib/AST/Expr.cpp
clang/lib/CodeGen/CGExpr.cpp
clang/lib/Sema/SemaDeclCXX.cpp
clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/AST/ASTLambda.h b/clang/include/clang/AST/ASTLambda.h
index 646cb574847fe2..a1854b6a1a9491 100644
--- a/clang/include/clang/AST/ASTLambda.h
+++ b/clang/include/clang/AST/ASTLambda.h
@@ -17,6 +17,7 @@
#include "clang/AST/DeclCXX.h"
#include "clang/AST/DeclTemplate.h"
+#include "llvm/Support/Casting.h"
namespace clang {
inline StringRef getLambdaStaticInvokerName() {
@@ -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();
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h
index 4d6e02fe2956e0..528304409b8092 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -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"
@@ -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));
diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp
index be1a65a49622d3..f661de54504a9c 100644
--- a/clang/lib/AST/ASTImporter.cpp
+++ b/clang/lib/AST/ASTImporter.cpp
@@ -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"
@@ -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();
diff --git a/clang/lib/AST/Expr.cpp b/clang/lib/AST/Expr.cpp
index 31b95bca613c21..06b04914426737 100644
--- a/clang/lib/AST/Expr.cpp
+++ b/clang/lib/AST/Expr.cpp
@@ -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()
diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp
index e9f5497aaae249..d921b4f19212c4 100644
--- a/clang/lib/CodeGen/CGExpr.cpp
+++ b/clang/lib/CodeGen/CGExpr.cpp
@@ -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"
@@ -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)) {
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index c1a016ff91cb23..97954a2b3c6db5 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -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);
diff --git a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
index 6a2331e59477a2..b3dcb12c4c8352 100644
--- a/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiateDecl.cpp
@@ -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());
diff --git a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
index 868a52c3572414..05904d9ade067f 100644
--- a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
+++ b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
@@ -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
More information about the cfe-commits
mailing list