forked from OSchip/llvm-project
PotentiallyEvaluatedContext in a ImmediateFunctionContext.
Body of `consteval` should be in an `ImmediateFunctionContext` instead of `ConstantEvaluated`. PotentiallyEvaluated expressions in Immediate functions are in a `ImmediateFunctionContext` as well. Fixes https://github.com/llvm/llvm-project/issues/51182 Original divergence: https://godbolt.org/z/vadGT5j6f Differential Revision: https://reviews.llvm.org/D132659
This commit is contained in:
parent
9142f67ef2
commit
4a043c6376
|
@ -174,6 +174,9 @@ C++20 Feature Support
|
|||
- Class member variables are now in scope when parsing a ``requires`` clause. Fixes
|
||||
`GH55216 <https://github.com/llvm/llvm-project/issues/55216>`_.
|
||||
|
||||
- Correctly set expression evaluation context as 'immediate function context' in
|
||||
consteval functions.
|
||||
This fixes `GH51182 https://github.com/llvm/llvm-project/issues/51182`
|
||||
|
||||
|
||||
C++2b Feature Support
|
||||
|
|
|
@ -1351,6 +1351,15 @@ public:
|
|||
bool isImmediateFunctionContext() const {
|
||||
return Context == ExpressionEvaluationContext::ImmediateFunctionContext ||
|
||||
(Context == ExpressionEvaluationContext::DiscardedStatement &&
|
||||
InImmediateFunctionContext) ||
|
||||
// C++2b [expr.const]p14:
|
||||
// An expression or conversion is in an immediate function
|
||||
// context if it is potentially evaluated and either:
|
||||
// * its innermost enclosing non-block scope is a function
|
||||
// parameter scope of an immediate function, or
|
||||
// * its enclosing statement is enclosed by the compound-
|
||||
// statement of a consteval if statement.
|
||||
(Context == ExpressionEvaluationContext::PotentiallyEvaluated &&
|
||||
InImmediateFunctionContext);
|
||||
}
|
||||
|
||||
|
|
|
@ -14800,8 +14800,12 @@ Decl *Sema::ActOnStartOfFunctionDef(Scope *FnBodyScope, Decl *D,
|
|||
// Do not push if it is a lambda because one is already pushed when building
|
||||
// the lambda in ActOnStartOfLambdaDefinition().
|
||||
if (!isLambdaCallOperator(FD))
|
||||
// [expr.const]/p14.1
|
||||
// An expression or conversion is in an immediate function context if it is
|
||||
// potentially evaluated and either: its innermost enclosing non-block scope
|
||||
// is a function parameter scope of an immediate function.
|
||||
PushExpressionEvaluationContext(
|
||||
FD->isConsteval() ? ExpressionEvaluationContext::ConstantEvaluated
|
||||
FD->isConsteval() ? ExpressionEvaluationContext::ImmediateFunctionContext
|
||||
: ExprEvalContexts.back().Context);
|
||||
|
||||
// Check for defining attributes before the check for redefinition.
|
||||
|
|
|
@ -19675,8 +19675,8 @@ void Sema::MarkDeclRefReferenced(DeclRefExpr *E, const Expr *Base) {
|
|||
|
||||
if (auto *FD = dyn_cast<FunctionDecl>(E->getDecl()))
|
||||
if (!isUnevaluatedContext() && !isConstantEvaluated() &&
|
||||
FD->isConsteval() && !RebuildingImmediateInvocation &&
|
||||
!FD->isDependentContext())
|
||||
!isImmediateFunctionContext() && FD->isConsteval() &&
|
||||
!RebuildingImmediateInvocation && !FD->isDependentContext())
|
||||
ExprEvalContexts.back().ReferenceToConsteval.insert(E);
|
||||
MarkExprReferenced(*this, E->getLocation(), E->getDecl(), E, OdrUse,
|
||||
RefsMinusAssignments);
|
||||
|
|
|
@ -908,3 +908,34 @@ int test() {
|
|||
return testDefaultArgForParam() + testDefaultArgForParam((E)1);
|
||||
}
|
||||
}
|
||||
|
||||
namespace GH51182 {
|
||||
// Nested consteval function.
|
||||
consteval int f(int v) {
|
||||
return v;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
consteval int g(T a) {
|
||||
// An immediate function context.
|
||||
int n = f(a);
|
||||
return n;
|
||||
}
|
||||
static_assert(g(100) == 100);
|
||||
// --------------------------------------
|
||||
template <typename T>
|
||||
consteval T max(const T& a, const T& b) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
template <typename T>
|
||||
consteval T mid(const T& a, const T& b, const T& c) {
|
||||
T m = max(max(a, b), c);
|
||||
if (m == a)
|
||||
return max(b, c);
|
||||
if (m == b)
|
||||
return max(a, c);
|
||||
return max(a, b);
|
||||
}
|
||||
static_assert(max(1,2)==2);
|
||||
static_assert(mid(1,2,3)==2);
|
||||
} // namespace GH51182
|
||||
|
|
Loading…
Reference in New Issue