(`#60887 <https://github.com/llvm/llvm-project/issues/60887>`_)
- Fix incorrect merging of lambdas across modules.
(`#60985 <https://github.com/llvm/llvm-project/issues/60985>`_)
+- Fix crash when handling nested immediate invocations in initializers of global
+ variables.
+ (`#58207 <https://github.com/llvm/llvm-project/issues/58207>`_)
Bug Fixes to Compiler Builtins
/// A stack of expression evaluation contexts.
SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;
+ // Set of failed immediate invocations to avoid double diagnosing.
+ llvm::SmallPtrSet<ConstantExpr *, 4> FailedImmediateInvocations;
+
/// Emit a warning for all pending noderef expressions that we recorded.
void WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec);
bool Result = CE->EvaluateAsConstantExpr(
Eval, SemaRef.getASTContext(), ConstantExprKind::ImmediateInvocation);
if (!Result || !Notes.empty()) {
+ SemaRef.FailedImmediateInvocations.insert(CE);
Expr *InnerExpr = CE->getSubExpr()->IgnoreImplicit();
if (auto *FunctionalCast = dyn_cast<CXXFunctionalCastExpr>(InnerExpr))
InnerExpr = FunctionalCast->getSubExpr();
[E](Sema::ImmediateInvocationCandidate Elem) {
return Elem.getPointer() == E;
});
- assert(It != IISet.rend() &&
- "ConstantExpr marked IsImmediateInvocation should "
- "be present");
- It->setInt(1); // Mark as deleted
+ // It is possible that some subexpression of the current immediate
+ // invocation was handled from another expression evaluation context. Do
+ // not handle the current immediate invocation if some of its
+ // subexpressions failed before.
+ if (It == IISet.rend()) {
+ if (SemaRef.FailedImmediateInvocations.contains(E))
+ CurrentII->setInt(1);
+ } else {
+ It->setInt(1); // Mark as deleted
+ }
}
ExprResult TransformConstantExpr(ConstantExpr *E) {
if (!E->isImmediateInvocation())
SemaRef.RebuildingImmediateInvocation)
return;
- /// When we have more then 1 ImmediateInvocationCandidates we need to check
- /// for nested ImmediateInvocationCandidates. when we have only 1 we only
- /// need to remove ReferenceToConsteval in the immediate invocation.
- if (Rec.ImmediateInvocationCandidates.size() > 1) {
+ /// When we have more than 1 ImmediateInvocationCandidates or previously
+ /// failed immediate invocations, we need to check for nested
+ /// ImmediateInvocationCandidates in order to avoid duplicate diagnostics.
+ /// Otherwise we only need to remove ReferenceToConsteval in the immediate
+ /// invocation.
+ if (Rec.ImmediateInvocationCandidates.size() > 1 ||
+ !SemaRef.FailedImmediateInvocations.empty()) {
/// Prevent sema calls during the tree transform from adding pointers that
/// are already in the sets.
static_assert(B == 0);
}
+
+namespace GH58207 {
+struct tester {
+ consteval tester(const char* name) noexcept { }
+};
+consteval const char* make_name(const char* name) { return name;}
+consteval const char* pad(int P) { return "thestring"; }
+
+int bad = 10; // expected-note 6{{declared here}}
+
+tester glob1(make_name("glob1"));
+tester glob2(make_name("glob2"));
+constexpr tester cglob(make_name("cglob"));
+tester paddedglob(make_name(pad(bad))); // expected-error {{call to consteval function 'GH58207::make_name' is not a constant expression}} \
+ // expected-note {{read of non-const variable 'bad' is not allowed in a constant expression}}
+
+constexpr tester glob3 = { make_name("glob3") };
+constexpr tester glob4 = { make_name(pad(bad)) }; // expected-error {{call to consteval function 'GH58207::make_name' is not a constant expression}} \
+ // expected-error {{constexpr variable 'glob4' must be initialized by a constant expression}} \
+ // expected-note 2{{read of non-const variable 'bad' is not allowed in a constant expression}}
+
+auto V = make_name(pad(3));
+auto V1 = make_name(pad(bad)); // expected-error {{call to consteval function 'GH58207::make_name' is not a constant expression}} \
+ // expected-note {{read of non-const variable 'bad' is not allowed in a constant expression}}
+
+
+void foo() {
+ static tester loc1(make_name("loc1"));
+ static constexpr tester loc2(make_name("loc2"));
+ static tester paddedloc(make_name(pad(bad))); // expected-error {{call to consteval function 'GH58207::make_name' is not a constant expression}} \
+ // expected-note {{read of non-const variable 'bad' is not allowed in a constant expression}}
+}
+
+void bar() {
+ static tester paddedloc(make_name(pad(bad))); // expected-error {{call to consteval function 'GH58207::make_name' is not a constant expression}} \
+ // expected-note {{read of non-const variable 'bad' is not allowed in a constant expression}}
+}
+}