Skip to content

Commit

Permalink
[Clang] call HandleImmediateInvocation before checking for immediate …
Browse files Browse the repository at this point in the history
…escacalating expressions (#124414)

HandleImmediateInvocation can call MarkExpressionAsImmediateEscalating
and should always be called before
CheckImmediateEscalatingFunctionDefinition.

However, we were not doing that in `ActFunctionBody`.

We simply move CheckImmediateEscalatingFunctionDefinition to
PopExpressionEvaluationContext.

Fixes #119046
  • Loading branch information
cor3ntin authored Jan 27, 2025
1 parent ad9da92 commit 5815a31
Show file tree
Hide file tree
Showing 6 changed files with 56 additions and 4 deletions.
1 change: 1 addition & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1003,6 +1003,7 @@ Bug Fixes to C++ Support
- Fixed assertions or false compiler diagnostics in the case of C++ modules for
lambda functions or inline friend functions defined inside templates (#GH122493).
- Clang now rejects declaring an alias template with the same name as its template parameter. (#GH123423)
- Fix that some dependent immediate expressions did not cause immediate escalation (#GH119046)
- Fixed the rejection of valid code when referencing an enumerator of an unscoped enum member with a prior declaration. (#GH124405)
- Fixed immediate escalation of non-dependent expressions. (#GH123405)
- Fix type of expression when calling a template which returns an ``__array_rank`` querying a type depending on a
Expand Down
6 changes: 3 additions & 3 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -13139,10 +13139,10 @@ class Sema final : public SemaBase {
~SynthesizedFunctionScope() {
if (PushedCodeSynthesisContext)
S.popCodeSynthesisContext();
if (auto *FD = dyn_cast<FunctionDecl>(S.CurContext)) {

if (auto *FD = dyn_cast<FunctionDecl>(S.CurContext))
FD->setWillHaveBody(false);
S.CheckImmediateEscalatingFunctionDefinition(FD, S.getCurFunction());
}

S.PopExpressionEvaluationContext();
S.PopFunctionScopeInfo();
}
Expand Down
1 change: 0 additions & 1 deletion clang/lib/Sema/SemaDecl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16019,7 +16019,6 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
if (!FD->isDeletedAsWritten())
FD->setBody(Body);
FD->setWillHaveBody(false);
CheckImmediateEscalatingFunctionDefinition(FD, FSI);

if (getLangOpts().CPlusPlus14) {
if (!FD->isInvalidDecl() && Body && !FD->isDependentContext() &&
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/Sema/SemaExpr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17881,6 +17881,9 @@ void Sema::PopExpressionEvaluationContext() {
WarnOnPendingNoDerefs(Rec);
HandleImmediateInvocations(*this, Rec);

if (auto *FD = dyn_cast<FunctionDecl>(CurContext); FD && getCurFunction())
CheckImmediateEscalatingFunctionDefinition(FD, getCurFunction());

// Warn on any volatile-qualified simple-assignments that are not discarded-
// value expressions nor unevaluated operands (those cases get removed from
// this list by CheckUnusedVolatileAssignment).
Expand Down
32 changes: 32 additions & 0 deletions clang/test/CodeGenCXX/gh119046.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// RUN: %clang_cc1 -std=c++2a -triple x86_64-elf-gnu %s -emit-llvm -o - | FileCheck %s

struct S {
consteval void operator()() {}
};

template <class Fn>
constexpr void dispatch(Fn fn) {
fn();
}

template <class Visitor>
struct value_visitor {
constexpr void operator()() { visitor(); }
Visitor&& visitor;
};

template <class Visitor>
constexpr auto make_dispatch() {
return dispatch<value_visitor<S>>;
}

template <class Visitor>
constexpr void visit(Visitor&&) {
make_dispatch<Visitor>();
}

void f() { visit(S{}); }

// CHECK: define {{.*}} @_Z1fv
// CHECK-NOT: define {{.*}} @_Z5visitI1SEvOT_
// CHECK-NOT: define {{.*}} @_Z13make_dispatchI1SEDav
17 changes: 17 additions & 0 deletions clang/test/SemaCXX/cxx2b-consteval-propagate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -529,6 +529,23 @@ D d(0); // expected-note {{in implicit initialization for inherited constructor

}

namespace GH119046 {

template <typename Cls> constexpr auto tfn(int) {
return (unsigned long long)(&Cls::sfn);
//expected-note@-1 {{'tfn<GH119046::S>' is an immediate function because its body evaluates the address of a consteval function 'sfn'}}
};
struct S { static consteval void sfn() {} };

int f() {
int a = 0; // expected-note{{declared here}}
return tfn<S>(a);
//expected-error@-1 {{call to immediate function 'GH119046::tfn<GH119046::S>' is not a constant expression}}
//expected-note@-2 {{read of non-const variable 'a' is not allowed in a constant expression}}
}

}

namespace GH123405 {

consteval void fn() {}
Expand Down

0 comments on commit 5815a31

Please sign in to comment.