Apply clang fix for assertion building emulators/rpcs3
Merge commit a5e1a93ea10f from llvm-project (by Mariya Podchishchaeva): [clang] Fix crash when handling nested immediate invocations Before this patch it was expected that if there was several immediate invocations they all belong to the same expression evaluation context. During parsing of non local variable initializer a new evaluation context is pushed, so code like this ``` namespace scope { struct channel { consteval channel(const char* name) noexcept { } }; consteval const char* make_channel_name(const char* name) { return name;} channel rsx_log(make_channel_name("rsx_log")); } ``` produced a nested immediate invocation whose subexpressions are attached to different expression evaluation contexts. The constructor call belongs to TU context and `make_channel_name` call to context of variable initializer. This patch removes this assumption and adds tracking of previously failed immediate invocations, so it is possible when handling an immediate invocation th check that its subexpressions from possibly another evaluation context contains errors and not produce duplicate diagnostics. Fixes https://github.com/llvm/llvm-project/issues/58207 Reviewed By: aaron.ballman, shafik Differential Revision: https://reviews.llvm.org/D146234 PR: 269489 MFC after: 3 days
This commit is contained in:
parent
dc81813497
commit
56f2446575
@ -1365,6 +1365,9 @@ class Sema final {
|
|||||||
/// A stack of expression evaluation contexts.
|
/// A stack of expression evaluation contexts.
|
||||||
SmallVector<ExpressionEvaluationContextRecord, 8> ExprEvalContexts;
|
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.
|
/// Emit a warning for all pending noderef expressions that we recorded.
|
||||||
void WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec);
|
void WarnOnPendingNoDerefs(ExpressionEvaluationContextRecord &Rec);
|
||||||
|
|
||||||
|
@ -17529,6 +17529,7 @@ static void EvaluateAndDiagnoseImmediateInvocation(
|
|||||||
bool Result = CE->EvaluateAsConstantExpr(
|
bool Result = CE->EvaluateAsConstantExpr(
|
||||||
Eval, SemaRef.getASTContext(), ConstantExprKind::ImmediateInvocation);
|
Eval, SemaRef.getASTContext(), ConstantExprKind::ImmediateInvocation);
|
||||||
if (!Result || !Notes.empty()) {
|
if (!Result || !Notes.empty()) {
|
||||||
|
SemaRef.FailedImmediateInvocations.insert(CE);
|
||||||
Expr *InnerExpr = CE->getSubExpr()->IgnoreImplicit();
|
Expr *InnerExpr = CE->getSubExpr()->IgnoreImplicit();
|
||||||
if (auto *FunctionalCast = dyn_cast<CXXFunctionalCastExpr>(InnerExpr))
|
if (auto *FunctionalCast = dyn_cast<CXXFunctionalCastExpr>(InnerExpr))
|
||||||
InnerExpr = FunctionalCast->getSubExpr();
|
InnerExpr = FunctionalCast->getSubExpr();
|
||||||
@ -17567,10 +17568,16 @@ static void RemoveNestedImmediateInvocation(
|
|||||||
[E](Sema::ImmediateInvocationCandidate Elem) {
|
[E](Sema::ImmediateInvocationCandidate Elem) {
|
||||||
return Elem.getPointer() == E;
|
return Elem.getPointer() == E;
|
||||||
});
|
});
|
||||||
assert(It != IISet.rend() &&
|
// It is possible that some subexpression of the current immediate
|
||||||
"ConstantExpr marked IsImmediateInvocation should "
|
// invocation was handled from another expression evaluation context. Do
|
||||||
"be present");
|
// not handle the current immediate invocation if some of its
|
||||||
It->setInt(1); // Mark as deleted
|
// 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) {
|
ExprResult TransformConstantExpr(ConstantExpr *E) {
|
||||||
if (!E->isImmediateInvocation())
|
if (!E->isImmediateInvocation())
|
||||||
@ -17639,10 +17646,13 @@ HandleImmediateInvocations(Sema &SemaRef,
|
|||||||
SemaRef.RebuildingImmediateInvocation)
|
SemaRef.RebuildingImmediateInvocation)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/// When we have more then 1 ImmediateInvocationCandidates we need to check
|
/// When we have more than 1 ImmediateInvocationCandidates or previously
|
||||||
/// for nested ImmediateInvocationCandidates. when we have only 1 we only
|
/// failed immediate invocations, we need to check for nested
|
||||||
/// need to remove ReferenceToConsteval in the immediate invocation.
|
/// ImmediateInvocationCandidates in order to avoid duplicate diagnostics.
|
||||||
if (Rec.ImmediateInvocationCandidates.size() > 1) {
|
/// 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
|
/// Prevent sema calls during the tree transform from adding pointers that
|
||||||
/// are already in the sets.
|
/// are already in the sets.
|
||||||
|
Loading…
Reference in New Issue
Block a user