Skip to content

Commit 5815a31

Browse files
authored
[Clang] call HandleImmediateInvocation before checking for immediate 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
1 parent ad9da92 commit 5815a31

File tree

6 files changed

+56
-4
lines changed

6 files changed

+56
-4
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1003,6 +1003,7 @@ Bug Fixes to C++ Support
10031003
- Fixed assertions or false compiler diagnostics in the case of C++ modules for
10041004
lambda functions or inline friend functions defined inside templates (#GH122493).
10051005
- Clang now rejects declaring an alias template with the same name as its template parameter. (#GH123423)
1006+
- Fix that some dependent immediate expressions did not cause immediate escalation (#GH119046)
10061007
- Fixed the rejection of valid code when referencing an enumerator of an unscoped enum member with a prior declaration. (#GH124405)
10071008
- Fixed immediate escalation of non-dependent expressions. (#GH123405)
10081009
- Fix type of expression when calling a template which returns an ``__array_rank`` querying a type depending on a

clang/include/clang/Sema/Sema.h

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13139,10 +13139,10 @@ class Sema final : public SemaBase {
1313913139
~SynthesizedFunctionScope() {
1314013140
if (PushedCodeSynthesisContext)
1314113141
S.popCodeSynthesisContext();
13142-
if (auto *FD = dyn_cast<FunctionDecl>(S.CurContext)) {
13142+
13143+
if (auto *FD = dyn_cast<FunctionDecl>(S.CurContext))
1314313144
FD->setWillHaveBody(false);
13144-
S.CheckImmediateEscalatingFunctionDefinition(FD, S.getCurFunction());
13145-
}
13145+
1314613146
S.PopExpressionEvaluationContext();
1314713147
S.PopFunctionScopeInfo();
1314813148
}

clang/lib/Sema/SemaDecl.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16019,7 +16019,6 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
1601916019
if (!FD->isDeletedAsWritten())
1602016020
FD->setBody(Body);
1602116021
FD->setWillHaveBody(false);
16022-
CheckImmediateEscalatingFunctionDefinition(FD, FSI);
1602316022

1602416023
if (getLangOpts().CPlusPlus14) {
1602516024
if (!FD->isInvalidDecl() && Body && !FD->isDependentContext() &&

clang/lib/Sema/SemaExpr.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17881,6 +17881,9 @@ void Sema::PopExpressionEvaluationContext() {
1788117881
WarnOnPendingNoDerefs(Rec);
1788217882
HandleImmediateInvocations(*this, Rec);
1788317883

17884+
if (auto *FD = dyn_cast<FunctionDecl>(CurContext); FD && getCurFunction())
17885+
CheckImmediateEscalatingFunctionDefinition(FD, getCurFunction());
17886+
1788417887
// Warn on any volatile-qualified simple-assignments that are not discarded-
1788517888
// value expressions nor unevaluated operands (those cases get removed from
1788617889
// this list by CheckUnusedVolatileAssignment).

clang/test/CodeGenCXX/gh119046.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
// RUN: %clang_cc1 -std=c++2a -triple x86_64-elf-gnu %s -emit-llvm -o - | FileCheck %s
2+
3+
struct S {
4+
consteval void operator()() {}
5+
};
6+
7+
template <class Fn>
8+
constexpr void dispatch(Fn fn) {
9+
fn();
10+
}
11+
12+
template <class Visitor>
13+
struct value_visitor {
14+
constexpr void operator()() { visitor(); }
15+
Visitor&& visitor;
16+
};
17+
18+
template <class Visitor>
19+
constexpr auto make_dispatch() {
20+
return dispatch<value_visitor<S>>;
21+
}
22+
23+
template <class Visitor>
24+
constexpr void visit(Visitor&&) {
25+
make_dispatch<Visitor>();
26+
}
27+
28+
void f() { visit(S{}); }
29+
30+
// CHECK: define {{.*}} @_Z1fv
31+
// CHECK-NOT: define {{.*}} @_Z5visitI1SEvOT_
32+
// CHECK-NOT: define {{.*}} @_Z13make_dispatchI1SEDav

clang/test/SemaCXX/cxx2b-consteval-propagate.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -529,6 +529,23 @@ D d(0); // expected-note {{in implicit initialization for inherited constructor
529529

530530
}
531531

532+
namespace GH119046 {
533+
534+
template <typename Cls> constexpr auto tfn(int) {
535+
return (unsigned long long)(&Cls::sfn);
536+
//expected-note@-1 {{'tfn<GH119046::S>' is an immediate function because its body evaluates the address of a consteval function 'sfn'}}
537+
};
538+
struct S { static consteval void sfn() {} };
539+
540+
int f() {
541+
int a = 0; // expected-note{{declared here}}
542+
return tfn<S>(a);
543+
//expected-error@-1 {{call to immediate function 'GH119046::tfn<GH119046::S>' is not a constant expression}}
544+
//expected-note@-2 {{read of non-const variable 'a' is not allowed in a constant expression}}
545+
}
546+
547+
}
548+
532549
namespace GH123405 {
533550

534551
consteval void fn() {}

0 commit comments

Comments
 (0)