https://github.com/IvyXu420 created 
https://github.com/llvm/llvm-project/pull/230054

This is a regression from PR #150215.

After #150215, if R was an unusable statement (e.g., parsed from a top-level 
return statement), `R = Actions.ActOnNullStmt(Tok.getLocation());` updates the 
local variable R's value, but the value was never used.
This resulted in a null pointer dereference because `TLSD->setStmt()` was never 
called, leaving `TLSD->getStmt() == nullptr`.

This PR correctly sets the `TLSD.Statement`'s value when parsing unusable 
top-level declarations.

Fixes #229339.

>From 27c0546c666b43bd69603666d86698a63d7b5c23 Mon Sep 17 00:00:00 2001
From: Ivy Xu <[email protected]>
Date: Thu, 8 Oct 2026 17:52:21 +0800
Subject: [PATCH] Fix clang-repl crashing on unusable top-level declarations

---
 clang/lib/Parse/ParseDecl.cpp                   |  4 +++-
 clang/unittests/Interpreter/InterpreterTest.cpp | 14 ++++++++++++++
 2 files changed, 17 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp
index fbecae7b80fb97..a984e1c7ee7d2d 100644
--- a/clang/lib/Parse/ParseDecl.cpp
+++ b/clang/lib/Parse/ParseDecl.cpp
@@ -5840,8 +5840,10 @@ Parser::DeclGroupPtrTy Parser::ParseTopLevelStmtDecl() {
   TopLevelStmtDecl *TLSD = Actions.ActOnStartTopLevelStmtDecl(getCurScope());
   StmtResult R = ParseStatementOrDeclaration(Stmts, SubStmtCtx);
   Actions.ActOnFinishTopLevelStmtDecl(TLSD, R.get());
-  if (!R.isUsable())
+  if (!R.isUsable()) {
     R = Actions.ActOnNullStmt(Tok.getLocation());
+    TLSD->setStmt(R.get());
+  }
 
   if (Tok.is(tok::annot_repl_input_end) &&
       Tok.getAnnotationValue() != nullptr) {
diff --git a/clang/unittests/Interpreter/InterpreterTest.cpp 
b/clang/unittests/Interpreter/InterpreterTest.cpp
index 3becd00c128205..8d7c75cdcaab87 100644
--- a/clang/unittests/Interpreter/InterpreterTest.cpp
+++ b/clang/unittests/Interpreter/InterpreterTest.cpp
@@ -573,4 +573,18 @@ TEST_F(InterpreterTest, TranslationUnit_CanonicalDecl) {
             sema.getASTContext().getTranslationUnitDecl()->getCanonicalDecl());
 }
 
+TEST_F(InterpreterTest, UnusableTopLevelDecl) {
+  std::vector<const char *> Args;
+  std::unique_ptr<Interpreter> Interp = createInterpreter(Args);
+
+  Value V;
+
+  llvm::cantFail(Interp->ParseAndExecute("return;", &V));
+
+  EXPECT_FALSE(V.isValid());
+  EXPECT_FALSE(V.hasValue());
+  ASSERT_EQ(V.getKind(), Value::K_Unspecified);
+  EXPECT_FALSE(V.isManuallyAlloc());
+}
+
 } // end anonymous namespace

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to