Skip to content

Commit 5430660

Browse files
cor3ntinAlexisPerry
authored andcommitted
[Clang] Fix immediate escalation in templated entities (llvm#95233)
* Lambdas were not considered immediate escalating in a template * Calls to an immediate function whose arguments were dependent were incorrectly treated as immediate escalating. Fixes llvm#94935
1 parent ae6b2e8 commit 5430660

File tree

6 files changed

+67
-2
lines changed

6 files changed

+67
-2
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -864,6 +864,8 @@ Bug Fixes to C++ Support
864864
- Clang now instantiates local constexpr functions eagerly for constant evaluators. (#GH35052), (#GH94849)
865865
- Fixed a failed assertion when attempting to convert an integer representing the difference
866866
between the addresses of two labels (a GNU extension) to a pointer within a constant expression. (#GH95366).
867+
- Fix immediate escalation bugs in the presence of dependent call arguments. (#GH94935)
868+
867869

868870
Bug Fixes to AST Handling
869871
^^^^^^^^^^^^^^^^^^^^^^^^^

clang/include/clang/Sema/Sema.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5239,6 +5239,12 @@ class Sema final : public SemaBase {
52395239
return ExprEvalContexts.back();
52405240
};
52415241

5242+
ExpressionEvaluationContextRecord &currentEvaluationContext() {
5243+
assert(!ExprEvalContexts.empty() &&
5244+
"Must be in an expression evaluation context");
5245+
return ExprEvalContexts.back();
5246+
};
5247+
52425248
ExpressionEvaluationContextRecord &parentEvaluationContext() {
52435249
assert(ExprEvalContexts.size() >= 2 &&
52445250
"Must be in an expression evaluation context");

clang/lib/Sema/SemaExpr.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6471,6 +6471,14 @@ ExprResult Sema::ActOnCallExpr(Scope *Scope, Expr *Fn, SourceLocation LParenLoc,
64716471
if (LangOpts.CPlusPlus) {
64726472
if (const auto *CE = dyn_cast<CallExpr>(Call.get()))
64736473
DiagnosedUnqualifiedCallsToStdFunctions(*this, CE);
6474+
6475+
// If we previously found that the id-expression of this call refers to a
6476+
// consteval function but the call is dependent, we should not treat is an
6477+
// an invalid immediate call.
6478+
if (auto *DRE = dyn_cast<DeclRefExpr>(Fn->IgnoreParens());
6479+
DRE && Call.get()->isValueDependent()) {
6480+
currentEvaluationContext().ReferenceToConsteval.erase(DRE);
6481+
}
64746482
}
64756483
return Call;
64766484
}

clang/lib/Sema/TreeTransform.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14545,6 +14545,9 @@ TreeTransform<Derived>::TransformLambdaExpr(LambdaExpr *E) {
1454514545
E->getCallOperator()->isConsteval() ?
1454614546
Sema::ExpressionEvaluationContext::ImmediateFunctionContext :
1454714547
Sema::ExpressionEvaluationContext::PotentiallyEvaluated);
14548+
getSema().currentEvaluationContext().InImmediateEscalatingFunctionContext =
14549+
getSema().getLangOpts().CPlusPlus20 &&
14550+
E->getCallOperator()->isImmediateEscalating();
1454814551

1454914552
Sema::CodeSynthesisContext C;
1455014553
C.Kind = clang::Sema::CodeSynthesisContext::LambdaExpressionSubstitution;

clang/test/SemaCXX/cxx2a-consteval.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,14 +1195,18 @@ namespace GH66562 {
11951195

11961196
namespace ns
11971197
{
1198-
consteval int foo(int x) { return 1; } // expected-note {{declared here}}
1198+
consteval int foo(int x) { return 1; } // expected-note {{declared here}} \
1199+
// expected-note {{passing argument to parameter 'x' here}}
11991200
}
12001201

12011202
template <class A>
12021203
struct T {
1203-
static constexpr auto xx = ns::foo(A{}); // expected-error {{cannot take address of consteval function 'foo' outside of an immediate invocation}}
1204+
static constexpr auto xx = ns::foo(A{}); // expected-error {{cannot take address of consteval function 'foo' outside of an immediate invocation}} \
1205+
// expected-error {{cannot initialize a parameter of type 'int' with an rvalue of type 'char *'}}
12041206
};
12051207

1208+
template class T<char*>; // expected-note {{in instantiation}}
1209+
12061210
}
12071211

12081212
namespace GH65520 {

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

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -454,3 +454,45 @@ namespace GH91308 {
454454
}
455455
using R1 = decltype(&f<int>);
456456
}
457+
458+
namespace GH94935 {
459+
460+
consteval void f(int) {}
461+
consteval void undef(int); // expected-note {{declared here}}
462+
463+
template<typename T>
464+
struct G {
465+
void g() {
466+
GH94935::f(T::fn());
467+
GH94935::f(T::undef2()); // expected-error {{call to consteval function 'GH94935::f' is not a constant expression}} \
468+
// expected-note {{undefined function 'undef2' cannot be used in a constant expression}}
469+
GH94935::undef(T::fn()); // expected-error {{call to consteval function 'GH94935::undef' is not a constant expression}} \
470+
// expected-note {{undefined function 'undef' cannot be used in a constant expression}}
471+
}
472+
};
473+
474+
struct X {
475+
static consteval int fn() { return 0; }
476+
static consteval int undef2(); // expected-note {{declared here}}
477+
478+
};
479+
480+
void test() {
481+
G<X>{}.g(); // expected-note {{instantiation}}
482+
}
483+
484+
485+
template<typename T>
486+
void g() {
487+
auto l = []{
488+
::f(T::fn());
489+
};
490+
}
491+
492+
struct Y {
493+
static int fn();
494+
};
495+
496+
template void g<Y>();
497+
498+
}

0 commit comments

Comments
 (0)