https://github.com/Serosh-commits created https://github.com/llvm/llvm-project/pull/180261
this fixes an assertion failure where the interpreter would crash on invalid initializer lists The problem was that we kept processing expressions even after they were flagged with errors. this led to bad state and the eventual crash so i added checks for `containsErrors()` in compiler.cpp and other entry points so we bail out early instead of asserting. fixes #175432 >From d7181759082c06607e8214d7feba0cb9840ef137 Mon Sep 17 00:00:00 2001 From: Serosh <[email protected]> Date: Fri, 6 Feb 2026 23:35:24 +0530 Subject: [PATCH] [clang][bytecode] Fix assertion failure on invalid init list (GH175432) This patch fixes a crash/assertion failure in the new constant interpreter when handling invalid initializer lists or expressions containing errors. The interpreter was attempting to evaluate/visit AST nodes that had been flagged with errors by the frontend (e.g., e->containsErrors()), leading to invalid state (such as unexpected pointer bases) and subsequent assertions in Pointer.cpp. We now guard the entry points of the Compiler (visit, visitInitList, VisitCastExpr, etc.) to immediately return false if the expression contains errors, ensuring we bail out gracefully instead of asserting. Fixes #175432 --- clang/lib/AST/ByteCode/Compiler.cpp | 23 +++++++++++++++++++++-- clang/test/AST/ByteCode/gh175432.cpp | 4 ++++ 2 files changed, 25 insertions(+), 2 deletions(-) create mode 100644 clang/test/AST/ByteCode/gh175432.cpp diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp index a0138c402e143..a5a9f1e2e440d 100644 --- a/clang/lib/AST/ByteCode/Compiler.cpp +++ b/clang/lib/AST/ByteCode/Compiler.cpp @@ -211,6 +211,9 @@ template <class Emitter> class LocOverrideScope final { template <class Emitter> bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) { + if (CE->containsErrors()) + return false; + const Expr *SubExpr = CE->getSubExpr(); if (DiscardResult) @@ -477,8 +480,6 @@ bool Compiler<Emitter>::VisitCastExpr(const CastExpr *CE) { return this->delegate(SubExpr); case CK_BitCast: { - if (CE->containsErrors()) - return false; QualType CETy = CE->getType(); // Reject bitcasts to atomic types. if (CETy->isAtomicType()) { @@ -1836,6 +1837,9 @@ bool Compiler<Emitter>::VisitArraySubscriptExpr(const ArraySubscriptExpr *E) { template <class Emitter> bool Compiler<Emitter>::visitInitList(ArrayRef<const Expr *> Inits, const Expr *ArrayFiller, const Expr *E) { + if (E->containsErrors()) + return false; + InitLinkScope<Emitter> ILS(this, InitLink::InitList()); QualType QT = E->getType(); @@ -4264,12 +4268,18 @@ bool Compiler<Emitter>::VisitStmtExpr(const StmtExpr *E) { } template <class Emitter> bool Compiler<Emitter>::discard(const Expr *E) { + if (E->containsErrors()) + return false; + OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/true, /*NewInitializing=*/false, /*ToLValue=*/false); return this->Visit(E); } template <class Emitter> bool Compiler<Emitter>::delegate(const Expr *E) { + if (E->containsErrors()) + return false; + // We're basically doing: // OptionScope<Emitter> Scope(this, DicardResult, Initializing, ToLValue); // but that's unnecessary of course. @@ -4302,6 +4312,9 @@ static const Expr *stripDerivedToBaseCasts(const Expr *E) { } template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) { + if (E->containsErrors()) + return false; + if (E->getType().isNull()) return false; @@ -4330,6 +4343,9 @@ template <class Emitter> bool Compiler<Emitter>::visit(const Expr *E) { template <class Emitter> bool Compiler<Emitter>::visitInitializer(const Expr *E) { + if (E->containsErrors()) + return false; + assert(!canClassify(E->getType())); OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false, @@ -4338,6 +4354,9 @@ bool Compiler<Emitter>::visitInitializer(const Expr *E) { } template <class Emitter> bool Compiler<Emitter>::visitAsLValue(const Expr *E) { + if (E->containsErrors()) + return false; + OptionScope<Emitter> Scope(this, /*NewDiscardResult=*/false, /*NewInitializing=*/false, /*ToLValue=*/true); return this->Visit(E); diff --git a/clang/test/AST/ByteCode/gh175432.cpp b/clang/test/AST/ByteCode/gh175432.cpp new file mode 100644 index 0000000000000..9433a83c76f56 --- /dev/null +++ b/clang/test/AST/ByteCode/gh175432.cpp @@ -0,0 +1,4 @@ +// RUN: %clang_cc1 -fexperimental-new-constant-interpreter -verify %s + +constexpr const int *foo[][2] = { {nullptr, int}, }; // expected-error {{expected expression}} +static_assert(foo[0][0] == nullptr, ""); _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
