From 92bcd856fb9f8cde209a10fcbc85a762519e6f49 Mon Sep 17 00:00:00 2001 From: Devajith Valaparambil Sreeramaswamy Date: Wed, 23 Jul 2025 14:15:13 +0200 Subject: [PATCH] [clang-repl] Always clean up scope and context for TopLevelStmtDecl This fixes an issue introduced by llvm/llvm-project@4b70d17bcffa, where failing to pop compound scope, function scope info, and decl context after a failed statement could lead to an inconsistent internal state. --- clang/lib/Parse/ParseDecl.cpp | 3 +-- clang/lib/Sema/SemaDecl.cpp | 3 ++- clang/test/Interpreter/fail.cpp | 7 +++++++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 893ef02450921..e47caeb855d0c 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -5695,11 +5695,10 @@ Parser::DeclGroupPtrTy Parser::ParseTopLevelStmtDecl() { Scope::CompoundStmtScope); TopLevelStmtDecl *TLSD = Actions.ActOnStartTopLevelStmtDecl(getCurScope()); StmtResult R = ParseStatementOrDeclaration(Stmts, SubStmtCtx); + Actions.ActOnFinishTopLevelStmtDecl(TLSD, R.get()); if (!R.isUsable()) R = Actions.ActOnNullStmt(Tok.getLocation()); - Actions.ActOnFinishTopLevelStmtDecl(TLSD, R.get()); - if (Tok.is(tok::annot_repl_input_end) && Tok.getAnnotationValue() != nullptr) { ConsumeAnnotationToken(); diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index fd22e012ea8b0..6e6669886ba36 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -20573,7 +20573,8 @@ TopLevelStmtDecl *Sema::ActOnStartTopLevelStmtDecl(Scope *S) { } void Sema::ActOnFinishTopLevelStmtDecl(TopLevelStmtDecl *D, Stmt *Statement) { - D->setStmt(Statement); + if (Statement) + D->setStmt(Statement); PopCompoundScope(); PopFunctionScopeInfo(); PopDeclContext(); diff --git a/clang/test/Interpreter/fail.cpp b/clang/test/Interpreter/fail.cpp index 633d92794325c..4963df8c54a49 100644 --- a/clang/test/Interpreter/fail.cpp +++ b/clang/test/Interpreter/fail.cpp @@ -18,4 +18,11 @@ extern "C" int printf(const char *, ...); int i = 42; auto r1 = printf("i = %d\n", i); // CHECK: i = 42 + +1aap = 42; // expected-error {{invalid digit 'a' in decimal constant}} +1aap = 42; i = 5; // expected-error {{invalid digit 'a' in decimal constant}} + +printf("i = %d\n", i); +// CHECK: i = 42 + %quit