https://github.com/weliveindetail updated https://github.com/llvm/llvm-project/pull/84150
From 27ff0ddc0d736f4959abe61c9fd43b9c48ffb6a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graen...@gmail.com> Date: Wed, 28 Feb 2024 15:45:53 +0100 Subject: [PATCH 1/7] Add test cases for variable definitions inside for-init and condition statements Interpreter/execute-stmts.cpp fails with: ``` i = 2 i = 5 i = 5 i = 5 j = 4 error: Parsing failed. error: Parsing failed. error: 'expected-error' diagnostics seen but not expected: Line 1: redefinition of 'i' Line 1: redefinition of 'i' error: 'expected-note' diagnostics seen but not expected: Line 1: previous definition is here Line 1: previous definition is here ``` --- clang/test/Interpreter/execute-stmts.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/clang/test/Interpreter/execute-stmts.cpp b/clang/test/Interpreter/execute-stmts.cpp index 2d4c17e0c91e66..34a2a35c0027d8 100644 --- a/clang/test/Interpreter/execute-stmts.cpp +++ b/clang/test/Interpreter/execute-stmts.cpp @@ -9,6 +9,8 @@ //CODEGEN-CHECK-COUNT-2: define internal void @__stmts__ //CODEGEN-CHECK-NOT: define internal void @__stmts__ +// New tests fail right now +// XFAIL: * extern "C" int printf(const char*,...); @@ -41,3 +43,9 @@ for (; i > 4; --i) { printf("i = %d\n", i); }; int j = i; printf("j = %d\n", j); // CHECK-NEXT: j = 4 + +if (int i = j) printf("i = %d\n", i); +// CHECK-NEXT: i = 4 + +for (int i = j; i > 3; --i) printf("i = %d\n", i); +// CHECK-NEXT: i = 4 From b97605ae98b10ef9cbb1544f997c6a7fed917bf3 Mon Sep 17 00:00:00 2001 From: Vassil Vassilev <v.g.vassi...@gmail.com> Date: Mon, 4 Mar 2024 17:51:43 +0000 Subject: [PATCH 2/7] Try to fix llvm/llvm-project#83028 --- clang/include/clang/AST/Decl.h | 16 ++++++++++------ clang/include/clang/AST/DeclBase.h | 1 + clang/include/clang/Basic/DeclNodes.td | 2 +- clang/include/clang/Sema/Sema.h | 3 ++- clang/lib/AST/Decl.cpp | 11 ++++++++--- clang/lib/AST/DeclBase.cpp | 1 + clang/lib/Parse/ParseDecl.cpp | 24 ++++++++++++++++-------- clang/lib/Sema/SemaDecl.cpp | 13 ++++++++++--- clang/test/Interpreter/execute-stmts.cpp | 10 ++++++++++ 9 files changed, 59 insertions(+), 22 deletions(-) diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index 61117cc5ce71f9..bca9d42c7e0586 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -4419,7 +4419,7 @@ class FileScopeAsmDecl : public Decl { /// /// \note This is used in libInterpreter, clang -cc1 -fincremental-extensions /// and in tools such as clang-repl. -class TopLevelStmtDecl : public Decl { +class TopLevelStmtDecl : public Decl, public DeclContext { friend class ASTDeclReader; friend class ASTDeclWriter; @@ -4427,7 +4427,7 @@ class TopLevelStmtDecl : public Decl { bool IsSemiMissing = false; TopLevelStmtDecl(DeclContext *DC, SourceLocation L, Stmt *S) - : Decl(TopLevelStmt, DC, L), Statement(S) {} + : Decl(TopLevelStmt, DC, L), DeclContext(TopLevelStmt), Statement(S) {} virtual void anchor(); @@ -4438,15 +4438,19 @@ class TopLevelStmtDecl : public Decl { SourceRange getSourceRange() const override LLVM_READONLY; Stmt *getStmt() { return Statement; } const Stmt *getStmt() const { return Statement; } - void setStmt(Stmt *S) { - assert(IsSemiMissing && "Operation supported for printing values only!"); - Statement = S; - } + void setStmt(Stmt *S); bool isSemiMissing() const { return IsSemiMissing; } void setSemiMissing(bool Missing = true) { IsSemiMissing = Missing; } static bool classof(const Decl *D) { return classofKind(D->getKind()); } static bool classofKind(Kind K) { return K == TopLevelStmt; } + + static DeclContext *castToDeclContext(const TopLevelStmtDecl *D) { + return static_cast<DeclContext *>(const_cast<TopLevelStmtDecl*>(D)); + } + static TopLevelStmtDecl *castFromDeclContext(const DeclContext *DC) { + return static_cast<TopLevelStmtDecl *>(const_cast<DeclContext*>(DC)); + } }; /// Represents a block literal declaration, which is like an diff --git a/clang/include/clang/AST/DeclBase.h b/clang/include/clang/AST/DeclBase.h index 9a4736019d1b1b..76810a86a78a46 100644 --- a/clang/include/clang/AST/DeclBase.h +++ b/clang/include/clang/AST/DeclBase.h @@ -2120,6 +2120,7 @@ class DeclContext { case Decl::Block: case Decl::Captured: case Decl::ObjCMethod: + case Decl::TopLevelStmt: return true; default: return getDeclKind() >= Decl::firstFunction && diff --git a/clang/include/clang/Basic/DeclNodes.td b/clang/include/clang/Basic/DeclNodes.td index 8b1f415dd5fe2c..48396e85c5adac 100644 --- a/clang/include/clang/Basic/DeclNodes.td +++ b/clang/include/clang/Basic/DeclNodes.td @@ -95,7 +95,7 @@ def LinkageSpec : DeclNode<Decl>, DeclContext; def Export : DeclNode<Decl>, DeclContext; def ObjCPropertyImpl : DeclNode<Decl>; def FileScopeAsm : DeclNode<Decl>; -def TopLevelStmt : DeclNode<Decl>; +def TopLevelStmt : DeclNode<Decl>, DeclContext; def AccessSpec : DeclNode<Decl>; def Friend : DeclNode<Decl>; def FriendTemplate : DeclNode<Decl>; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index f3d3a57104ee07..a79f3c0786ce47 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3263,7 +3263,8 @@ class Sema final { Decl *ActOnFileScopeAsmDecl(Expr *expr, SourceLocation AsmLoc, SourceLocation RParenLoc); - Decl *ActOnTopLevelStmtDecl(Stmt *Statement); + TopLevelStmtDecl *ActOnStartTopLevelStmtDecl(Scope *S); + void ActOnFinishTopLevelStmtDecl(TopLevelStmtDecl* D, Stmt *Statement); void ActOnPopScope(SourceLocation Loc, Scope *S); diff --git a/clang/lib/AST/Decl.cpp b/clang/lib/AST/Decl.cpp index 59c039f1f8daeb..d681791d3920c3 100644 --- a/clang/lib/AST/Decl.cpp +++ b/clang/lib/AST/Decl.cpp @@ -5552,14 +5552,13 @@ FileScopeAsmDecl *FileScopeAsmDecl::CreateDeserialized(ASTContext &C, void TopLevelStmtDecl::anchor() {} TopLevelStmtDecl *TopLevelStmtDecl::Create(ASTContext &C, Stmt *Statement) { - assert(Statement); assert(C.getLangOpts().IncrementalExtensions && "Must be used only in incremental mode"); - SourceLocation BeginLoc = Statement->getBeginLoc(); + SourceLocation Loc = Statement ? Statement->getBeginLoc() : SourceLocation(); DeclContext *DC = C.getTranslationUnitDecl(); - return new (C, DC) TopLevelStmtDecl(DC, BeginLoc, Statement); + return new (C, DC) TopLevelStmtDecl(DC, Loc, Statement); } TopLevelStmtDecl *TopLevelStmtDecl::CreateDeserialized(ASTContext &C, @@ -5572,6 +5571,12 @@ SourceRange TopLevelStmtDecl::getSourceRange() const { return SourceRange(getLocation(), Statement->getEndLoc()); } +void TopLevelStmtDecl::setStmt(Stmt *S) { + assert(S); + Statement = S; + setLocation(Statement->getBeginLoc()); +} + void EmptyDecl::anchor() {} EmptyDecl *EmptyDecl::Create(ASTContext &C, DeclContext *DC, SourceLocation L) { diff --git a/clang/lib/AST/DeclBase.cpp b/clang/lib/AST/DeclBase.cpp index 10fe8bb97ce660..fcedb3cfd176a0 100644 --- a/clang/lib/AST/DeclBase.cpp +++ b/clang/lib/AST/DeclBase.cpp @@ -1352,6 +1352,7 @@ DeclContext *DeclContext::getPrimaryContext() { case Decl::ExternCContext: case Decl::LinkageSpec: case Decl::Export: + case Decl::TopLevelStmt: case Decl::Block: case Decl::Captured: case Decl::OMPDeclareReduction: diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 81f1c711269445..7ce37cf61164e9 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -5678,24 +5678,32 @@ Parser::DeclGroupPtrTy Parser::ParseTopLevelStmtDecl() { // Parse a top-level-stmt. Parser::StmtVector Stmts; ParsedStmtContext SubStmtCtx = ParsedStmtContext(); - Actions.PushFunctionScope(); + ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope | + Scope::CompoundStmtScope); + TopLevelStmtDecl *TLSD = Actions.ActOnStartTopLevelStmtDecl(getCurScope()); StmtResult R = ParseStatementOrDeclaration(Stmts, SubStmtCtx); - Actions.PopFunctionScopeInfo(); if (!R.isUsable()) return nullptr; - SmallVector<Decl *, 2> DeclsInGroup; - DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(R.get())); + Actions.ActOnFinishTopLevelStmtDecl(TLSD, R.get()); if (Tok.is(tok::annot_repl_input_end) && Tok.getAnnotationValue() != nullptr) { ConsumeAnnotationToken(); - cast<TopLevelStmtDecl>(DeclsInGroup.back())->setSemiMissing(); + TLSD->setSemiMissing(); } - // Currently happens for things like -fms-extensions and use `__if_exists`. - for (Stmt *S : Stmts) - DeclsInGroup.push_back(Actions.ActOnTopLevelStmtDecl(S)); + SmallVector<Decl *, 2> DeclsInGroup; + DeclsInGroup.push_back(TLSD); + + // Currently happens for things like -fms-extensions and use `__if_exists`. + for (Stmt *S : Stmts) { + // Here we should be safe as `__if_exists` and friends are not introducing + // new variables which need to live outside file scope. + TopLevelStmtDecl *D = Actions.ActOnStartTopLevelStmtDecl(getCurScope()); + Actions.ActOnFinishTopLevelStmtDecl(D, S); + DeclsInGroup.push_back(D); + } return Actions.BuildDeclaratorGroup(DeclsInGroup); } diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 6b81ee183cc440..b8177e47e4aa5c 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -20519,12 +20519,19 @@ Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, return New; } -Decl *Sema::ActOnTopLevelStmtDecl(Stmt *Statement) { - auto *New = TopLevelStmtDecl::Create(Context, Statement); - Context.getTranslationUnitDecl()->addDecl(New); +TopLevelStmtDecl *Sema::ActOnStartTopLevelStmtDecl(Scope *S) { + auto *New = TopLevelStmtDecl::Create(Context, /*Statement=*/nullptr); + PushFunctionScope(); + PushDeclContext(S, New); return New; } +void Sema::ActOnFinishTopLevelStmtDecl(TopLevelStmtDecl* D, Stmt *Statement) { + D->setStmt(Statement); + PopDeclContext(); + PopFunctionScopeInfo(); +} + void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name, IdentifierInfo* AliasName, SourceLocation PragmaLoc, diff --git a/clang/test/Interpreter/execute-stmts.cpp b/clang/test/Interpreter/execute-stmts.cpp index 34a2a35c0027d8..912b180849ef8b 100644 --- a/clang/test/Interpreter/execute-stmts.cpp +++ b/clang/test/Interpreter/execute-stmts.cpp @@ -49,3 +49,13 @@ if (int i = j) printf("i = %d\n", i); for (int i = j; i > 3; --i) printf("i = %d\n", i); // CHECK-NEXT: i = 4 + +for(int i=0; i<2; i+=1) {}; + +for(int i=0; i<2; i+=1) ; + +int a = 2; +for(int i=0; i<2; i+=1) a-=1; + +int *aa=nullptr; +if (auto *b=aa) *b += 1; From ff26b1273e0cc5e2d04144434aaaedff9aad9330 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graen...@gmail.com> Date: Tue, 5 Mar 2024 13:58:46 +0100 Subject: [PATCH 3/7] fixup! Try to fix llvm/llvm-project#83028 Drop duplicate test-case --- clang/test/Interpreter/execute-stmts.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/clang/test/Interpreter/execute-stmts.cpp b/clang/test/Interpreter/execute-stmts.cpp index 912b180849ef8b..d339b3506e84a6 100644 --- a/clang/test/Interpreter/execute-stmts.cpp +++ b/clang/test/Interpreter/execute-stmts.cpp @@ -54,8 +54,5 @@ for(int i=0; i<2; i+=1) {}; for(int i=0; i<2; i+=1) ; -int a = 2; -for(int i=0; i<2; i+=1) a-=1; - int *aa=nullptr; if (auto *b=aa) *b += 1; From 5aa374d4453a8ac82eda7605f248c275b571e7c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graen...@gmail.com> Date: Wed, 6 Mar 2024 11:35:37 +0100 Subject: [PATCH 4/7] fixup! Try to fix llvm/llvm-project#83028 clang-format --- clang/include/clang/AST/Decl.h | 6 +++--- clang/include/clang/Sema/Sema.h | 2 +- clang/lib/Parse/ParseDecl.cpp | 2 +- clang/lib/Sema/SemaDecl.cpp | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/clang/include/clang/AST/Decl.h b/clang/include/clang/AST/Decl.h index bca9d42c7e0586..a5879591f4c659 100644 --- a/clang/include/clang/AST/Decl.h +++ b/clang/include/clang/AST/Decl.h @@ -4427,7 +4427,7 @@ class TopLevelStmtDecl : public Decl, public DeclContext { bool IsSemiMissing = false; TopLevelStmtDecl(DeclContext *DC, SourceLocation L, Stmt *S) - : Decl(TopLevelStmt, DC, L), DeclContext(TopLevelStmt), Statement(S) {} + : Decl(TopLevelStmt, DC, L), DeclContext(TopLevelStmt), Statement(S) {} virtual void anchor(); @@ -4446,10 +4446,10 @@ class TopLevelStmtDecl : public Decl, public DeclContext { static bool classofKind(Kind K) { return K == TopLevelStmt; } static DeclContext *castToDeclContext(const TopLevelStmtDecl *D) { - return static_cast<DeclContext *>(const_cast<TopLevelStmtDecl*>(D)); + return static_cast<DeclContext *>(const_cast<TopLevelStmtDecl *>(D)); } static TopLevelStmtDecl *castFromDeclContext(const DeclContext *DC) { - return static_cast<TopLevelStmtDecl *>(const_cast<DeclContext*>(DC)); + return static_cast<TopLevelStmtDecl *>(const_cast<DeclContext *>(DC)); } }; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index a79f3c0786ce47..464649aee8a26b 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -3264,7 +3264,7 @@ class Sema final { SourceLocation RParenLoc); TopLevelStmtDecl *ActOnStartTopLevelStmtDecl(Scope *S); - void ActOnFinishTopLevelStmtDecl(TopLevelStmtDecl* D, Stmt *Statement); + void ActOnFinishTopLevelStmtDecl(TopLevelStmtDecl *D, Stmt *Statement); void ActOnPopScope(SourceLocation Loc, Scope *S); diff --git a/clang/lib/Parse/ParseDecl.cpp b/clang/lib/Parse/ParseDecl.cpp index 7ce37cf61164e9..64b234eb460d24 100644 --- a/clang/lib/Parse/ParseDecl.cpp +++ b/clang/lib/Parse/ParseDecl.cpp @@ -5679,7 +5679,7 @@ Parser::DeclGroupPtrTy Parser::ParseTopLevelStmtDecl() { Parser::StmtVector Stmts; ParsedStmtContext SubStmtCtx = ParsedStmtContext(); ParseScope FnScope(this, Scope::FnScope | Scope::DeclScope | - Scope::CompoundStmtScope); + Scope::CompoundStmtScope); TopLevelStmtDecl *TLSD = Actions.ActOnStartTopLevelStmtDecl(getCurScope()); StmtResult R = ParseStatementOrDeclaration(Stmts, SubStmtCtx); if (!R.isUsable()) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index b8177e47e4aa5c..7227f26d5462d3 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -20526,7 +20526,7 @@ TopLevelStmtDecl *Sema::ActOnStartTopLevelStmtDecl(Scope *S) { return New; } -void Sema::ActOnFinishTopLevelStmtDecl(TopLevelStmtDecl* D, Stmt *Statement) { +void Sema::ActOnFinishTopLevelStmtDecl(TopLevelStmtDecl *D, Stmt *Statement) { D->setStmt(Statement); PopDeclContext(); PopFunctionScopeInfo(); From 83265cf0101b48b222b40e3a0d3a9ee26234f8f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graen...@gmail.com> Date: Tue, 5 Mar 2024 13:58:19 +0100 Subject: [PATCH 5/7] fixup! Try to fix llvm/llvm-project#83028 ActOnForStmt() requires a CompoundScope when processing a NullStmt body --- clang/lib/Sema/SemaDecl.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 7227f26d5462d3..c30bdf3e7fb488 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -20522,6 +20522,7 @@ Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, TopLevelStmtDecl *Sema::ActOnStartTopLevelStmtDecl(Scope *S) { auto *New = TopLevelStmtDecl::Create(Context, /*Statement=*/nullptr); PushFunctionScope(); + PushCompoundScope(false); PushDeclContext(S, New); return New; } @@ -20529,6 +20530,7 @@ TopLevelStmtDecl *Sema::ActOnStartTopLevelStmtDecl(Scope *S) { void Sema::ActOnFinishTopLevelStmtDecl(TopLevelStmtDecl *D, Stmt *Statement) { D->setStmt(Statement); PopDeclContext(); + PopCompoundScope(); PopFunctionScopeInfo(); } From 27341ab72c084ee0264ea5bbee025ff8c4d313d5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graen...@gmail.com> Date: Wed, 6 Mar 2024 11:18:42 +0100 Subject: [PATCH 6/7] fixup! Try to fix llvm/llvm-project#83028 Add TopLevelStmtDecl to outer DeclContext (and push new scopes afterwards) --- clang/lib/Sema/SemaDecl.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index c30bdf3e7fb488..67e56a917a51de 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -20521,17 +20521,18 @@ Decl *Sema::ActOnFileScopeAsmDecl(Expr *expr, TopLevelStmtDecl *Sema::ActOnStartTopLevelStmtDecl(Scope *S) { auto *New = TopLevelStmtDecl::Create(Context, /*Statement=*/nullptr); + CurContext->addDecl(New); + PushDeclContext(S, New); PushFunctionScope(); PushCompoundScope(false); - PushDeclContext(S, New); return New; } void Sema::ActOnFinishTopLevelStmtDecl(TopLevelStmtDecl *D, Stmt *Statement) { D->setStmt(Statement); - PopDeclContext(); PopCompoundScope(); PopFunctionScopeInfo(); + PopDeclContext(); } void Sema::ActOnPragmaRedefineExtname(IdentifierInfo* Name, From 68ed18f4aa66b57d0c9efd103f82aa615db8b824 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graen...@gmail.com> Date: Wed, 6 Mar 2024 11:30:16 +0100 Subject: [PATCH 7/7] Test cases for variable definitions inside for-init and condition statements pass now --- clang/test/Interpreter/execute-stmts.cpp | 3 --- 1 file changed, 3 deletions(-) diff --git a/clang/test/Interpreter/execute-stmts.cpp b/clang/test/Interpreter/execute-stmts.cpp index d339b3506e84a6..e341b06d154f18 100644 --- a/clang/test/Interpreter/execute-stmts.cpp +++ b/clang/test/Interpreter/execute-stmts.cpp @@ -9,9 +9,6 @@ //CODEGEN-CHECK-COUNT-2: define internal void @__stmts__ //CODEGEN-CHECK-NOT: define internal void @__stmts__ -// New tests fail right now -// XFAIL: * - extern "C" int printf(const char*,...); template <typename T> T call() { printf("called\n"); return T(); } _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits