https://github.com/cor3ntin updated https://github.com/llvm/llvm-project/pull/95233
>From f567bbcafc211ecd3a76075ece26ea8eb1e8d803 Mon Sep 17 00:00:00 2001 From: Corentin Jabot <corentinja...@gmail.com> Date: Wed, 12 Jun 2024 14:12:39 +0200 Subject: [PATCH] [Clang] Fix conseval propagation in templated entities * Lambdas were not considered immediate escalating in a template * Calls to an immediate function whose arguments were dependent was incorrectly treated as immediate escalating. Fixes #94935 --- clang/docs/ReleaseNotes.rst | 1 + clang/include/clang/Sema/Sema.h | 6 +++ clang/lib/Sema/SemaExpr.cpp | 8 ++++ clang/lib/Sema/TreeTransform.h | 3 ++ clang/test/SemaCXX/cxx2a-consteval.cpp | 8 +++- .../SemaCXX/cxx2b-consteval-propagate.cpp | 42 +++++++++++++++++++ 6 files changed, 66 insertions(+), 2 deletions(-) diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index cf1ba02cbc4b2..c5e9363a12119 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -846,6 +846,7 @@ Bug Fixes to C++ Support - Fix a crash caused by improper use of ``__array_extent``. (#GH80474) - Fixed several bugs in capturing variables within unevaluated contexts. (#GH63845), (#GH67260), (#GH69307), (#GH88081), (#GH89496), (#GH90669) and (#GH91633). +- Fix immediate escalation bugs in the presence of dependent call arguments. (#GH94935) Bug Fixes to AST Handling ^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 9bf01417186c3..69ac2e804fa75 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -5239,6 +5239,12 @@ class Sema final : public SemaBase { return ExprEvalContexts.back(); }; + ExpressionEvaluationContextRecord ¤tEvaluationContext() { + assert(!ExprEvalContexts.empty() && + "Must be in an expression evaluation context"); + return ExprEvalContexts.back(); + }; + ExpressionEvaluationContextRecord &parentEvaluationContext() { assert(ExprEvalContexts.size() >= 2 && "Must be in an expression evaluation context"); diff --git a/clang/lib/Sema/SemaExpr.cpp b/clang/lib/Sema/SemaExpr.cpp index 44f886bf54e3a..2c221fd9c828a 100644 --- a/clang/lib/Sema/SemaExpr.cpp +++ b/clang/lib/Sema/SemaExpr.cpp @@ -6471,6 +6471,14 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc, if (LangOpts.CPlusPlus) { if (const auto *CE = dyn_cast<CallExpr>(Call.get())) DiagnosedUnqualifiedCallsToStdFunctions(*this, CE); + + // If we previously found that the id-expression of this call refers to a + // consteval function but the call is dependent, we should not treat is an + // an invalid immediate call. + if (auto *DRE = dyn_cast<DeclRefExpr>(Fn->IgnoreParens()); + DRE && Call.get()->isValueDependent()) { + currentEvaluationContext().ReferenceToConsteval.erase(DRE); + } } return Call; } diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index f117fe98d142b..cf4e80399632b 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -14550,6 +14550,9 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) { E->getCallOperator()->isConsteval() ? Sema::ExpressionEvaluationContext::ImmediateFunctionContext : Sema::ExpressionEvaluationContext::PotentiallyEvaluated); + getSema().currentEvaluationContext().InImmediateEscalatingFunctionContext = + getSema().getLangOpts().CPlusPlus20 && + E->getCallOperator()->isImmediateEscalating(); Sema::CodeSynthesisContext C; C.Kind = clang::Sema::CodeSynthesisContext::LambdaExpressionSubstitution; diff --git a/clang/test/SemaCXX/cxx2a-consteval.cpp b/clang/test/SemaCXX/cxx2a-consteval.cpp index 622ec31c459dd..fb8385eb02051 100644 --- a/clang/test/SemaCXX/cxx2a-consteval.cpp +++ b/clang/test/SemaCXX/cxx2a-consteval.cpp @@ -1195,14 +1195,18 @@ namespace GH66562 { namespace ns { - consteval int foo(int x) { return 1; } // expected-note {{declared here}} + consteval int foo(int x) { return 1; } // expected-note {{declared here}} \ + // expected-note {{passing argument to parameter 'x' here}} } template <class A> struct T { - static constexpr auto xx = ns::foo(A{}); // expected-error {{cannot take address of consteval function 'foo' outside of an immediate invocation}} + static constexpr auto xx = ns::foo(A{}); // expected-error {{cannot take address of consteval function 'foo' outside of an immediate invocation}} \ + // expected-error {{cannot initialize a parameter of type 'int' with an rvalue of type 'char *'}} }; +template class T<char*>; // expected-note {{in instantiation}} + } namespace GH65520 { diff --git a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp index b70c02201ac3c..378414f136172 100644 --- a/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp +++ b/clang/test/SemaCXX/cxx2b-consteval-propagate.cpp @@ -454,3 +454,45 @@ namespace GH91308 { } using R1 = decltype(&f<int>); } + +namespace GH94935 { + +consteval void f(int) {} +consteval void undef(int); // expected-note {{declared here}} + +template<typename T> +struct G { + void g() { + GH94935::f(T::fn()); + GH94935::f(T::undef2()); // expected-error {{call to consteval function 'GH94935::f' is not a constant expression}} \ + // expected-note {{undefined function 'undef2' cannot be used in a constant expression}} + GH94935::undef(T::fn()); // expected-error {{call to consteval function 'GH94935::undef' is not a constant expression}} \ + // expected-note {{undefined function 'undef' cannot be used in a constant expression}} + } +}; + +struct X { + static consteval int fn() { return 0; } + static consteval int undef2(); // expected-note {{declared here}} + +}; + +void test() { + G<X>{}.g(); // expected-note {{instantiation}} +} + + +template<typename T> +void g() { + auto l = []{ + ::f(T::fn()); + }; +} + +struct Y { + static int fn(); +}; + +template void g<Y>(); + +} _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits