diff --git a/clang/include/clang/AST/ASTLambda.h b/clang/include/clang/AST/ASTLambda.h index 646cb574847fe..a1854b6a1a949 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(DC)); } +inline bool isLambdaMethod(const DeclContext *DC) { + if (const auto *MD = dyn_cast_if_present(DC)) + return MD->getParent()->isLambda(); + return false; +} + inline bool isLambdaCallWithExplicitObjectParameter(const DeclContext *DC) { return isLambdaCallOperator(DC) && cast(DC)->isExplicitObjectMemberFunction(); diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 4d6e02fe2956e..528304409b809 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(DC)); diff --git a/clang/lib/AST/ASTImporter.cpp b/clang/lib/AST/ASTImporter.cpp index be1a65a49622d..f661de54504a9 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(D)) - return cast(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 31b95bca613c2..06b0491442673 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(FD) && - cast(FD)->getParent()->isLambda()) + if (isLambdaMethod(FD)) Proto = "auto " + Proto; else if (FT && FT->getReturnType()->getAs()) FT->getReturnType() diff --git a/clang/lib/CodeGen/CGExpr.cpp b/clang/lib/CodeGen/CGExpr.cpp index e9f5497aaae24..d921b4f19212c 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(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()) { if (const VarDecl *VD = dyn_cast(D)) { diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index 08065e3cad2bb..c803e1fba43d3 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(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 6a2331e59477a..b3dcb12c4c835 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(D->getParent())->isLambda() && - !D->getTypeSourceInfo() && + if (isLambdaMethod(D) && !D->getTypeSourceInfo() && isa(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 868a52c357241..05904d9ade067 100644 --- a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp +++ b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp @@ -544,5 +544,19 @@ void g() { tfn(a); // expected-error {{call to immediate function 'GH123405::tfn' 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