mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-17 08:16:47 +00:00
[Clang] call HandleImmediateInvocation before checking for immediate escacalating expressions (reland) (#124708)
HandleImmediateInvocation can call MarkExpressionAsImmediateEscalating and should always be called before CheckImmediateEscalatingFunctionDefinition. However, we were not doing that in `ActFunctionBody`. Fixes #119046
This commit is contained in:
parent
78b5bb702f
commit
820c6ac7f5
@ -1036,6 +1036,7 @@ Bug Fixes to C++ Support
|
||||
- Fix type of expression when calling a template which returns an ``__array_rank`` querying a type depending on a
|
||||
template parameter. Now, such expression can be used with ``static_assert`` and ``constexpr``. (#GH123498)
|
||||
- Correctly determine the implicit constexprness of lambdas in dependent contexts. (#GH97958) (#GH114234)
|
||||
- Fix that some dependent immediate expressions did not cause immediate escalation (#GH119046)
|
||||
|
||||
Bug Fixes to AST Handling
|
||||
^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||
|
@ -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() &&
|
||||
@ -16397,6 +16396,9 @@ Decl *Sema::ActOnFinishFunctionBody(Decl *dcl, Stmt *Body,
|
||||
// the declaration context below. Otherwise, we're unable to transform
|
||||
// 'this' expressions when transforming immediate context functions.
|
||||
|
||||
if (FD)
|
||||
CheckImmediateEscalatingFunctionDefinition(FD, getCurFunction());
|
||||
|
||||
if (!IsInstantiation)
|
||||
PopDeclContext();
|
||||
|
||||
|
32
clang/test/CodeGenCXX/gh119046.cpp
Normal file
32
clang/test/CodeGenCXX/gh119046.cpp
Normal file
@ -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
|
@ -560,3 +560,19 @@ void foo() {
|
||||
S s;
|
||||
}
|
||||
} // namespace GH118000
|
||||
|
||||
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}}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user