[clang] [clang-repl] Names declared in if conditions and for-init statements are local to the inner context (C++ 3.3.2p4) (PR #84150)

Stefan Gränitz via cfe-commits cfe-commits at lists.llvm.org
Wed Mar 6 08:46:35 PST 2024


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.graenitz at gmail.com>
Date: Wed, 28 Feb 2024 15:45:53 +0100
Subject: [PATCH 1/9] 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.vassilev at gmail.com>
Date: Mon, 4 Mar 2024 17:51:43 +0000
Subject: [PATCH 2/9] 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.graenitz at gmail.com>
Date: Tue, 5 Mar 2024 13:58:46 +0100
Subject: [PATCH 3/9] 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.graenitz at gmail.com>
Date: Wed, 6 Mar 2024 11:35:37 +0100
Subject: [PATCH 4/9] 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.graenitz at gmail.com>
Date: Tue, 5 Mar 2024 13:58:19 +0100
Subject: [PATCH 5/9] 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.graenitz at gmail.com>
Date: Wed, 6 Mar 2024 11:18:42 +0100
Subject: [PATCH 6/9] 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.graenitz at gmail.com>
Date: Wed, 6 Mar 2024 11:30:16 +0100
Subject: [PATCH 7/9] 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(); }

>From 7b7cd67d6249f4cfa6e2ea271c1af0e562160c74 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Wed, 6 Mar 2024 14:43:56 +0100
Subject: [PATCH 8/9] Refine test execute-stmts.cpp

---
 clang/test/Interpreter/execute-stmts.cpp | 19 +++++++++++++------
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/clang/test/Interpreter/execute-stmts.cpp b/clang/test/Interpreter/execute-stmts.cpp
index e341b06d154f18..af44b1b174fb66 100644
--- a/clang/test/Interpreter/execute-stmts.cpp
+++ b/clang/test/Interpreter/execute-stmts.cpp
@@ -41,15 +41,22 @@ 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
+{++i; printf("i = %d (global scope)\n", i);}
+// CHECK-NEXT: i = 5
 
-for (int i = j; i > 3; --i) printf("i = %d\n", i);
-// CHECK-NEXT: i = 4
+while (int i = 1) { printf("i = %d (while condition)\n", i--); break; }
+// CHECK-NEXT: i = 1
 
-for(int i=0; i<2; i+=1) {};
+if (int i = 2) printf("i = %d (if condition)\n", i);
+// CHECK-NEXT: i = 2
 
-for(int i=0; i<2; i+=1) ;
+switch (int i = 3) { default: printf("i = %d (switch condition)\n", i); }
+// CHECK-NEXT: i = 3
+
+for (int i = 4; i > 3; --i) printf("i = %d (for-init)\n", i);
+// CHECK-NEXT: i = 4
 
 int *aa=nullptr;
 if (auto *b=aa) *b += 1;
+while (auto *b=aa) ;
+for (auto *b=aa; b; *b+=1) ;

>From 4f328842acd43373d8d13e6bbadec8878961e853 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Stefan=20Gr=C3=A4nitz?= <stefan.graenitz at gmail.com>
Date: Wed, 6 Mar 2024 17:46:13 +0100
Subject: [PATCH 9/9] Add test-case for variable definition in range-based
 for-loop

---
 clang/test/Interpreter/execute-stmts.cpp | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/clang/test/Interpreter/execute-stmts.cpp b/clang/test/Interpreter/execute-stmts.cpp
index af44b1b174fb66..433c6811777dac 100644
--- a/clang/test/Interpreter/execute-stmts.cpp
+++ b/clang/test/Interpreter/execute-stmts.cpp
@@ -41,8 +41,8 @@ for (; i > 4; --i) { printf("i = %d\n", i); };
 int j = i; printf("j = %d\n", j);
 // CHECK-NEXT: j = 4
 
-{++i; printf("i = %d (global scope)\n", i);}
-// CHECK-NEXT: i = 5
+{i = 0; printf("i = %d (global scope)\n", i);}
+// CHECK-NEXT: i = 0
 
 while (int i = 1) { printf("i = %d (while condition)\n", i--); break; }
 // CHECK-NEXT: i = 1
@@ -56,6 +56,9 @@ switch (int i = 3) { default: printf("i = %d (switch condition)\n", i); }
 for (int i = 4; i > 3; --i) printf("i = %d (for-init)\n", i);
 // CHECK-NEXT: i = 4
 
+for (const auto &i : "5") printf("i = %c (range-based for-init)\n", i);
+// CHECK-NEXT: i = 5
+
 int *aa=nullptr;
 if (auto *b=aa) *b += 1;
 while (auto *b=aa) ;



More information about the cfe-commits mailing list