https://github.com/akash-manna-sky updated 
https://github.com/llvm/llvm-project/pull/233248

>From db2ead9b54115ca237f9a390575acab653bdd6cb Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Wed, 14 Oct 2026 23:24:32 +0530
Subject: [PATCH 1/4] [Clang][OpenMP] Fix crash on a braced-init-list in the
 init or increment of a transformed loop

Fixes #202562

The loop analysis kept the initializer of `int i = {0}` as the lower bound as 
written, a braced-init-list, and did the same with the step of `i += {1}`. 
Plain loop directives got away with that, but `unroll partial`, `reverse`, 
`interchange`, `flatten` and `fuse` copy the trip count through a 
`TreeTransform`, which rebuilds the list without a type, so `{0} - 1` fails to 
build and the transform asserts.

The analysis now looks through a list that merely wraps one expression of the 
counter's type, so `int i = {0}`, `int i{0}`, `i = {0}` and `i += {1}` are 
analysed as `0` and `1`. A list that wraps nothing, like `{}`, is rejected as a 
non-canonical init or increment.

LLM tools were used for this contribution. I've reviewed, built, and tested the 
change myself before pushing to GitHub.
---
 clang/docs/ReleaseNotes.md                    |  2 +
 clang/lib/Sema/SemaOpenMP.cpp                 | 26 ++++++++
 clang/test/OpenMP/for_loop_messages.cpp       | 11 ++++
 clang/test/OpenMP/reverse_messages.cpp        |  9 +++
 .../OpenMP/unroll_codegen_braced_init.cpp     | 18 ++++++
 clang/test/OpenMP/unroll_messages.cpp         | 61 +++++++++++++++++++
 6 files changed, 127 insertions(+)
 create mode 100644 clang/test/OpenMP/unroll_codegen_braced_init.cpp

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 1dc1764978ea27..a65ed7fcd5e878 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -1243,6 +1243,8 @@ The `alpha.cplusplus.UseAfterLifetimeEnd` checker was 
renamed to `alpha.core.Use
   matching the behavior of such maps outside a mapper.
 - Fixed a crash when the `safelen` and `simdlen` clauses of an OpenMP directive
   have arguments of different integer types. (#GH108367)
+- Fixed a crash when the init or increment of a loop under an OpenMP loop
+  transformation directive uses a braced list, such as `int i = {0}`. 
(#GH202562)
 - The `holds` clause on the `assume` directive now lowers side-effect-free
   conditions to `llvm.assume`, enabling downstream optimizations. Previously
   the clause was parsed but its condition was discarded without effect.
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index a3be416d2da24f..7aa05e46f7bfaa 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -8674,6 +8674,15 @@ static const StmtExpr *findStmtExpr(const Expr *E) {
   return nullptr;
 }
 
+static Expr *ignoreTransparentInitLists(Expr *E) {
+  while (auto *ILE = dyn_cast<InitListExpr>(E)) {
+    if (!ILE->isTransparent())
+      break;
+    E = ILE->getInit(0);
+  }
+  return E;
+}
+
 bool OpenMPIterationSpaceChecker::checkNonRectangularBound(
     const Expr *E, bool IsInitializer) const {
   // Such a bound is emitted at every use, its declarations cannot be.
@@ -8694,6 +8703,15 @@ bool 
OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
          UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
   if (!NewLCDecl || !NewLB || NewLB->containsErrors())
     return true;
+  if (!SemaRef.CurContext->isDependentContext()) {
+    NewLB = ignoreTransparentInitLists(NewLB);
+    if (auto *ILE = dyn_cast<InitListExpr>(NewLB)) {
+      if (EmitDiags)
+        SemaRef.Diag(ILE->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
+            << ILE->getSourceRange();
+      return true;
+    }
+  }
   LCDecl = getCanonicalDecl(NewLCDecl);
   LCRef = NewLCRefExpr;
   if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
@@ -8738,6 +8756,14 @@ bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, 
bool Subtract) {
   assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
   if (!NewStep || NewStep->containsErrors())
     return true;
+  if (!SemaRef.CurContext->isDependentContext()) {
+    NewStep = ignoreTransparentInitLists(NewStep);
+    if (auto *ILE = dyn_cast<InitListExpr>(NewStep)) {
+      SemaRef.Diag(ILE->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
+          << ILE->getSourceRange() << LCDecl;
+      return true;
+    }
+  }
   if (!NewStep->isValueDependent()) {
     // Check that the step is integer expression.
     SourceLocation StepLoc = NewStep->getBeginLoc();
diff --git a/clang/test/OpenMP/for_loop_messages.cpp 
b/clang/test/OpenMP/for_loop_messages.cpp
index d2fbeea106a513..e10952887b0759 100644
--- a/clang/test/OpenMP/for_loop_messages.cpp
+++ b/clang/test/OpenMP/for_loop_messages.cpp
@@ -414,6 +414,17 @@ int test_iteration_spaces() {
   for (int a{0}; a < 10; ++a) {
   }
 
+#pragma omp parallel
+#pragma omp for
+  for (int a = {0}; a < 10; ++a) {
+  }
+
+#pragma omp parallel
+// expected-error@+2 {{initialization clause of OpenMP for loop is not in 
canonical form ('var = init' or 'T var = init')}}
+#pragma omp for
+  for (int a = {}; a < 10; ++a) {
+  }
+
   return 0;
 }
 
diff --git a/clang/test/OpenMP/reverse_messages.cpp 
b/clang/test/OpenMP/reverse_messages.cpp
index 9636a70bf2753b..07a9010a584735 100644
--- a/clang/test/OpenMP/reverse_messages.cpp
+++ b/clang/test/OpenMP/reverse_messages.cpp
@@ -36,5 +36,14 @@ void func() {
   for (int i = 0; i < 7; ++i)
     ;
 
+  #pragma omp reverse
+  for (int i = {0}; i < 7; ++i)
+    ;
+
+  // expected-error@+2 {{initialization clause of OpenMP for loop is not in 
canonical form ('var = init' or 'T var = init')}}
+  #pragma omp reverse
+  for (int i = {}; i < 7; ++i)
+    ;
+
 }
 
diff --git a/clang/test/OpenMP/unroll_codegen_braced_init.cpp 
b/clang/test/OpenMP/unroll_codegen_braced_init.cpp
new file mode 100644
index 00000000000000..dae66b579b520d
--- /dev/null
+++ b/clang/test/OpenMP/unroll_codegen_braced_init.cpp
@@ -0,0 +1,18 @@
+// RUN: %clang_cc1 -verify -triple x86_64-pc-linux-gnu -fopenmp -emit-llvm %s 
-o - | FileCheck %s
+// expected-no-diagnostics
+
+extern "C" void body(int);
+
+// CHECK-LABEL: define {{.*}}void @_Z11braced_initv(
+// CHECK:         store i32 3, ptr %[[I:.+]], align 4
+// CHECK:         icmp sgt i32 %{{.+}}, 1
+// CHECK:         icmp slt i32 %{{.+}}, 4
+// CHECK:         %[[MUL:.+]] = mul nsw i32 %{{.+}}, 1
+// CHECK-NEXT:    %[[ADD:.+]] = add nsw i32 3, %[[MUL]]
+// CHECK-NEXT:    store i32 %[[ADD]], ptr %[[I]], align 4
+void braced_init() {
+#pragma omp for
+#pragma omp unroll partial(2)
+  for (int i = {3}; i < 7; i++)
+    body(i);
+}
diff --git a/clang/test/OpenMP/unroll_messages.cpp 
b/clang/test/OpenMP/unroll_messages.cpp
index 17d5ed83e162f2..b21a71b37d2183 100644
--- a/clang/test/OpenMP/unroll_messages.cpp
+++ b/clang/test/OpenMP/unroll_messages.cpp
@@ -137,3 +137,64 @@ void f(void) {
     ;
 }
 }
+
+namespace GH202562 {
+void braced_init() {
+#pragma omp unroll partial
+  for (int i = {0}; i < 2; i++)
+    ;
+
+#pragma omp unroll partial(2)
+  for (int i = {0}; i < 2; i++)
+    ;
+
+  // expected-warning@+2 {{initialization clause of OpenMP for loop is not in 
canonical form ('var = init' or 'T var = init')}}
+#pragma omp unroll partial
+  for (int i{0}; i < 2; i++)
+    ;
+
+  // expected-warning@+2 {{initialization clause of OpenMP for loop is not in 
canonical form ('var = init' or 'T var = init')}}
+#pragma omp unroll partial
+  for (int i(0); i < 2; i++)
+    ;
+
+  int j;
+#pragma omp unroll partial
+  for (j = {0}; j < 2; j++)
+    ;
+
+  // expected-error@+2 {{initialization clause of OpenMP for loop is not in 
canonical form ('var = init' or 'T var = init')}}
+#pragma omp unroll partial
+  for (int i = {}; i < 2; i++)
+    ;
+
+  // expected-warning@+2 {{too many braces around scalar initializer}}
+#pragma omp unroll partial
+  for (int i = {{0}}; i < 2; i++)
+    ;
+
+#pragma omp unroll partial
+  for (int i = 0; i < 2; i += {1})
+    ;
+
+#pragma omp unroll partial
+  for (int i = 0; i < 2; i -= {-1})
+    ;
+
+  // expected-error@+2 {{increment clause of OpenMP for loop must perform 
simple addition or subtraction on loop variable 'i'}}
+#pragma omp unroll partial
+  for (int i = 0; i < 2; i += {})
+    ;
+
+#pragma omp unroll partial
+  for (int i = 0; i < 2; i++)
+    ;
+}
+
+template <typename T> void braced_init_templ() {
+#pragma omp unroll partial
+  for (T i = {0}; i < 2; i++)
+    ;
+}
+void braced_init_inst() { braced_init_templ<int>(); }
+}

>From bf41815523914d9786c349524588107acd91fdb7 Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Mon, 19 Oct 2026 08:24:11 +0530
Subject: [PATCH 2/4] [Clang][OpenMP] Handle an empty braced list as
 value-initialization instead of rejecting it

---
 clang/lib/Sema/SemaOpenMP.cpp                 | 36 +++++++++----------
 clang/test/OpenMP/for_loop_messages.cpp       |  1 -
 clang/test/OpenMP/reverse_messages.cpp        |  1 -
 .../OpenMP/unroll_codegen_braced_init.cpp     | 14 ++++++++
 clang/test/OpenMP/unroll_messages.cpp         |  3 +-
 5 files changed, 33 insertions(+), 22 deletions(-)

diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 7aa05e46f7bfaa..4521fb422c6da2 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -8674,13 +8674,18 @@ static const StmtExpr *findStmtExpr(const Expr *E) {
   return nullptr;
 }
 
-static Expr *ignoreTransparentInitLists(Expr *E) {
-  while (auto *ILE = dyn_cast<InitListExpr>(E)) {
-    if (!ILE->isTransparent())
-      break;
-    E = ILE->getInit(0);
-  }
-  return E;
+static ExprResult buildInitListValue(Sema &SemaRef, Expr *E) {
+  auto *ILE = dyn_cast<InitListExpr>(E);
+  if (!ILE)
+    return E;
+  if (ILE->isTransparent())
+    return buildInitListValue(SemaRef, ILE->getInit(0));
+  if (ILE->getNumInits() != 0 || !ILE->getType()->isScalarType())
+    return E;
+  SourceLocation Loc = ILE->getLBraceLoc();
+  return SemaRef.BuildCStyleCastExpr(
+      Loc, SemaRef.Context.getTrivialTypeSourceInfo(ILE->getType(), Loc), Loc,
+      SemaRef.ActOnIntegerConstant(Loc, 0).get());
 }
 
 bool OpenMPIterationSpaceChecker::checkNonRectangularBound(
@@ -8704,13 +8709,10 @@ bool 
OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
   if (!NewLCDecl || !NewLB || NewLB->containsErrors())
     return true;
   if (!SemaRef.CurContext->isDependentContext()) {
-    NewLB = ignoreTransparentInitLists(NewLB);
-    if (auto *ILE = dyn_cast<InitListExpr>(NewLB)) {
-      if (EmitDiags)
-        SemaRef.Diag(ILE->getBeginLoc(), diag::err_omp_loop_not_canonical_init)
-            << ILE->getSourceRange();
+    ExprResult LBVal = buildInitListValue(SemaRef, NewLB);
+    if (LBVal.isInvalid())
       return true;
-    }
+    NewLB = LBVal.get();
   }
   LCDecl = getCanonicalDecl(NewLCDecl);
   LCRef = NewLCRefExpr;
@@ -8757,12 +8759,10 @@ bool OpenMPIterationSpaceChecker::setStep(Expr 
*NewStep, bool Subtract) {
   if (!NewStep || NewStep->containsErrors())
     return true;
   if (!SemaRef.CurContext->isDependentContext()) {
-    NewStep = ignoreTransparentInitLists(NewStep);
-    if (auto *ILE = dyn_cast<InitListExpr>(NewStep)) {
-      SemaRef.Diag(ILE->getBeginLoc(), diag::err_omp_loop_not_canonical_incr)
-          << ILE->getSourceRange() << LCDecl;
+    ExprResult StepVal = buildInitListValue(SemaRef, NewStep);
+    if (StepVal.isInvalid())
       return true;
-    }
+    NewStep = StepVal.get();
   }
   if (!NewStep->isValueDependent()) {
     // Check that the step is integer expression.
diff --git a/clang/test/OpenMP/for_loop_messages.cpp 
b/clang/test/OpenMP/for_loop_messages.cpp
index e10952887b0759..a6d92bfe43cf16 100644
--- a/clang/test/OpenMP/for_loop_messages.cpp
+++ b/clang/test/OpenMP/for_loop_messages.cpp
@@ -420,7 +420,6 @@ int test_iteration_spaces() {
   }
 
 #pragma omp parallel
-// expected-error@+2 {{initialization clause of OpenMP for loop is not in 
canonical form ('var = init' or 'T var = init')}}
 #pragma omp for
   for (int a = {}; a < 10; ++a) {
   }
diff --git a/clang/test/OpenMP/reverse_messages.cpp 
b/clang/test/OpenMP/reverse_messages.cpp
index 07a9010a584735..df62ce2902b142 100644
--- a/clang/test/OpenMP/reverse_messages.cpp
+++ b/clang/test/OpenMP/reverse_messages.cpp
@@ -40,7 +40,6 @@ void func() {
   for (int i = {0}; i < 7; ++i)
     ;
 
-  // expected-error@+2 {{initialization clause of OpenMP for loop is not in 
canonical form ('var = init' or 'T var = init')}}
   #pragma omp reverse
   for (int i = {}; i < 7; ++i)
     ;
diff --git a/clang/test/OpenMP/unroll_codegen_braced_init.cpp 
b/clang/test/OpenMP/unroll_codegen_braced_init.cpp
index dae66b579b520d..034556cf090383 100644
--- a/clang/test/OpenMP/unroll_codegen_braced_init.cpp
+++ b/clang/test/OpenMP/unroll_codegen_braced_init.cpp
@@ -16,3 +16,17 @@ void braced_init() {
   for (int i = {3}; i < 7; i++)
     body(i);
 }
+
+// CHECK-LABEL: define {{.*}}void @_Z10empty_initv(
+// CHECK:         store i32 0, ptr %[[I:.+]], align 4
+// CHECK:         icmp sgt i32 %{{.+}}, 1
+// CHECK:         icmp slt i32 %{{.+}}, 4
+// CHECK:         %[[MUL:.+]] = mul nsw i32 %{{.+}}, 1
+// CHECK-NEXT:    %[[ADD:.+]] = add nsw i32 0, %[[MUL]]
+// CHECK-NEXT:    store i32 %[[ADD]], ptr %[[I]], align 4
+void empty_init() {
+#pragma omp for
+#pragma omp unroll partial(2)
+  for (int i = {}; i < 4; i++)
+    body(i);
+}
diff --git a/clang/test/OpenMP/unroll_messages.cpp 
b/clang/test/OpenMP/unroll_messages.cpp
index b21a71b37d2183..87fc6ded58f9d2 100644
--- a/clang/test/OpenMP/unroll_messages.cpp
+++ b/clang/test/OpenMP/unroll_messages.cpp
@@ -163,7 +163,6 @@ void braced_init() {
   for (j = {0}; j < 2; j++)
     ;
 
-  // expected-error@+2 {{initialization clause of OpenMP for loop is not in 
canonical form ('var = init' or 'T var = init')}}
 #pragma omp unroll partial
   for (int i = {}; i < 2; i++)
     ;
@@ -181,7 +180,7 @@ void braced_init() {
   for (int i = 0; i < 2; i -= {-1})
     ;
 
-  // expected-error@+2 {{increment clause of OpenMP for loop must perform 
simple addition or subtraction on loop variable 'i'}}
+  // expected-error@+2 {{increment expression must cause 'i' to increase on 
each iteration of OpenMP for loop}} expected-note@+2 {{loop step is expected to 
be positive due to this condition}}
 #pragma omp unroll partial
   for (int i = 0; i < 2; i += {})
     ;

>From c613f596f7e1d9d92229d2a8f7d59df64cb2670b Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Mon, 19 Oct 2026 23:13:40 +0530
Subject: [PATCH 3/4] [Clang][OpenMP] Convert the empty-list zero implicitly
 instead of with a C-style cast

---
 clang/lib/Sema/SemaOpenMP.cpp           | 7 +++----
 clang/test/OpenMP/for_loop_messages.cpp | 5 +++++
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 4521fb422c6da2..36a5262af30976 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -8682,10 +8682,9 @@ static ExprResult buildInitListValue(Sema &SemaRef, Expr 
*E) {
     return buildInitListValue(SemaRef, ILE->getInit(0));
   if (ILE->getNumInits() != 0 || !ILE->getType()->isScalarType())
     return E;
-  SourceLocation Loc = ILE->getLBraceLoc();
-  return SemaRef.BuildCStyleCastExpr(
-      Loc, SemaRef.Context.getTrivialTypeSourceInfo(ILE->getType(), Loc), Loc,
-      SemaRef.ActOnIntegerConstant(Loc, 0).get());
+  return SemaRef.PerformImplicitConversion(
+      SemaRef.ActOnIntegerConstant(ILE->getLBraceLoc(), 0).get(),
+      ILE->getType(), AssignmentAction::Converting);
 }
 
 bool OpenMPIterationSpaceChecker::checkNonRectangularBound(
diff --git a/clang/test/OpenMP/for_loop_messages.cpp 
b/clang/test/OpenMP/for_loop_messages.cpp
index a6d92bfe43cf16..bf3bda16f225ec 100644
--- a/clang/test/OpenMP/for_loop_messages.cpp
+++ b/clang/test/OpenMP/for_loop_messages.cpp
@@ -424,6 +424,11 @@ int test_iteration_spaces() {
   for (int a = {}; a < 10; ++a) {
   }
 
+#pragma omp parallel
+#pragma omp for
+  for (int(*p)[4] = {}; p < lb + 8; ++p) {
+  }
+
   return 0;
 }
 

>From 7a03d42b244aa23d5c3b696665ba385213bda3b3 Mon Sep 17 00:00:00 2001
From: Akash Manna <[email protected]>
Date: Mon, 26 Oct 2026 23:37:16 +0530
Subject: [PATCH 4/4] [Clang][OpenMP] Handle braced lists in the IRBuilder loop
 path and for non-integer counters

---
 clang/docs/ReleaseNotes.md                  |  4 +-
 clang/lib/Sema/SemaOpenMP.cpp               | 60 ++++++++++-----------
 clang/test/OpenMP/irbuilder_braced_init.cpp | 16 ++++++
 clang/test/OpenMP/unroll_messages.cpp       | 22 ++++++++
 4 files changed, 69 insertions(+), 33 deletions(-)
 create mode 100644 clang/test/OpenMP/irbuilder_braced_init.cpp

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 9e6872c3b40522..acb086e27f45b1 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -1383,8 +1383,8 @@ The `alpha.cplusplus.UseAfterLifetimeEnd` checker was 
renamed to `alpha.core.Use
   matching the behavior of such maps outside a mapper.
 - Fixed a crash when the `safelen` and `simdlen` clauses of an OpenMP directive
   have arguments of different integer types. (#GH108367)
-- Fixed a crash when the init or increment of a loop under an OpenMP loop
-  transformation directive uses a braced list, such as `int i = {0}`. 
(#GH202562)
+- Fixed a crash when the init or increment of an OpenMP loop uses a braced
+  list, such as `int i = {0}`. (#GH202562)
 - The `holds` clause on the `assume` directive now lowers side-effect-free
   conditions to `llvm.assume`, enabling downstream optimizations. Previously
   the clause was parsed but its condition was discarded without effect.
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 31082cc2979f6e..85079d7cc3722a 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -6020,6 +6020,26 @@ static QualType getIntTypeForBitwidthOrBitInt(ASTContext 
&C, unsigned Bits,
   return Ty;
 }
 
+static Expr *buildInitListValue(Sema &SemaRef, Expr *E) {
+  auto *ILE = dyn_cast<InitListExpr>(E);
+  if (!ILE)
+    return E;
+  if (ILE->isTransparent())
+    return buildInitListValue(SemaRef, ILE->getInit(0));
+  ASTContext &Context = SemaRef.Context;
+  QualType Ty = ILE->getType();
+  bool IsEmptyScalar = ILE->getNumInits() == 0 && Ty->isScalarType();
+  if (!SemaRef.getLangOpts().CPlusPlus)
+    return IsEmptyScalar ? new (Context) ImplicitValueInitExpr(Ty) : E;
+  if (!IsEmptyScalar && !Ty->isRecordType())
+    return E;
+  return CXXFunctionalCastExpr::Create(
+      Context, Ty, VK_PRValue,
+      Context.getTrivialTypeSourceInfo(Ty, ILE->getLBraceLoc()), CK_NoOp, ILE,
+      /*Path=*/nullptr, SemaRef.CurFPFeatureOverrides(), SourceLocation(),
+      SourceLocation());
+}
+
 static VarDecl *precomputeExpr(Sema &Actions,
                                SmallVectorImpl<Stmt *> &BodyStmts, Expr *E,
                                StringRef Name) {
@@ -6364,11 +6384,11 @@ StmtResult SemaOpenMP::ActOnOpenMPCanonicalLoop(Stmt 
*AStmt) {
         llvm::APInt(Ctx.getIntWidth(LogicalTy), Direction, /*isSigned=*/true),
         LogicalTy, {});
   } else if (auto *IncBin = dyn_cast<BinaryOperator>(Inc)) {
+    Expr *IncRHS = buildInitListValue(SemaRef, IncBin->getRHS());
     if (IncBin->getOpcode() == BO_AddAssign) {
-      Step = IncBin->getRHS();
+      Step = IncRHS;
     } else if (IncBin->getOpcode() == BO_SubAssign) {
-      Step = AssertSuccess(
-          SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, IncBin->getRHS()));
+      Step = AssertSuccess(SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, 
IncRHS));
     } else
       llvm_unreachable("unhandled binary increment operator");
   } else if (auto *CondCXXOp = dyn_cast<CXXOperatorCallExpr>(Inc)) {
@@ -6382,11 +6402,12 @@ StmtResult SemaOpenMP::ActOnOpenMPCanonicalLoop(Stmt 
*AStmt) {
           Ctx, llvm::APInt(Ctx.getIntWidth(LogicalTy), -1), LogicalTy, {});
       break;
     case OO_PlusEqual:
-      Step = CondCXXOp->getArg(1);
+      Step = buildInitListValue(SemaRef, CondCXXOp->getArg(1));
       break;
     case OO_MinusEqual:
-      Step = AssertSuccess(
-          SemaRef.BuildUnaryOp(nullptr, {}, UO_Minus, CondCXXOp->getArg(1)));
+      Step = AssertSuccess(SemaRef.BuildUnaryOp(
+          nullptr, {}, UO_Minus,
+          buildInitListValue(SemaRef, CondCXXOp->getArg(1))));
       break;
     default:
       llvm_unreachable("unhandled overloaded increment operator");
@@ -8701,19 +8722,6 @@ static const StmtExpr *findStmtExpr(const Expr *E) {
   return nullptr;
 }
 
-static ExprResult buildInitListValue(Sema &SemaRef, Expr *E) {
-  auto *ILE = dyn_cast<InitListExpr>(E);
-  if (!ILE)
-    return E;
-  if (ILE->isTransparent())
-    return buildInitListValue(SemaRef, ILE->getInit(0));
-  if (ILE->getNumInits() != 0 || !ILE->getType()->isScalarType())
-    return E;
-  return SemaRef.PerformImplicitConversion(
-      SemaRef.ActOnIntegerConstant(ILE->getLBraceLoc(), 0).get(),
-      ILE->getType(), AssignmentAction::Converting);
-}
-
 bool OpenMPIterationSpaceChecker::checkNonRectangularBound(
     const Expr *E, bool IsInitializer) const {
   // Such a bound is emitted at every use, its declarations cannot be.
@@ -8734,12 +8742,7 @@ bool 
OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
          UB == nullptr && Step == nullptr && !TestIsLessOp && !TestIsStrictOp);
   if (!NewLCDecl || !NewLB || NewLB->containsErrors())
     return true;
-  if (!SemaRef.CurContext->isDependentContext()) {
-    ExprResult LBVal = buildInitListValue(SemaRef, NewLB);
-    if (LBVal.isInvalid())
-      return true;
-    NewLB = LBVal.get();
-  }
+  NewLB = buildInitListValue(SemaRef, NewLB);
   LCDecl = getCanonicalDecl(NewLCDecl);
   LCRef = NewLCRefExpr;
   if (auto *CE = dyn_cast_or_null<CXXConstructExpr>(NewLB))
@@ -8784,12 +8787,7 @@ bool OpenMPIterationSpaceChecker::setStep(Expr *NewStep, 
bool Subtract) {
   assert(LCDecl != nullptr && LB != nullptr && Step == nullptr);
   if (!NewStep || NewStep->containsErrors())
     return true;
-  if (!SemaRef.CurContext->isDependentContext()) {
-    ExprResult StepVal = buildInitListValue(SemaRef, NewStep);
-    if (StepVal.isInvalid())
-      return true;
-    NewStep = StepVal.get();
-  }
+  NewStep = buildInitListValue(SemaRef, NewStep);
   if (!NewStep->isValueDependent()) {
     // Check that the step is integer expression.
     SourceLocation StepLoc = NewStep->getBeginLoc();
diff --git a/clang/test/OpenMP/irbuilder_braced_init.cpp 
b/clang/test/OpenMP/irbuilder_braced_init.cpp
new file mode 100644
index 00000000000000..68eb12f8a57f79
--- /dev/null
+++ b/clang/test/OpenMP/irbuilder_braced_init.cpp
@@ -0,0 +1,16 @@
+// RUN: %clang_cc1 -fopenmp -fopenmp-enable-irbuilder -x c++ -triple 
x86_64-unknown-unknown -fsyntax-only -verify %s
+
+void braced_init(int n) {
+#pragma omp for
+  for (int i = {0}; i < n; i += {1})
+    ;
+
+#pragma omp for
+  for (int i = {}; i < n; i -= {-1})
+    ;
+
+  // expected-error@+2 {{increment expression must cause 'i' to increase on 
each iteration of OpenMP for loop}} expected-note@+2 {{loop step is expected to 
be positive due to this condition}}
+#pragma omp for
+  for (int i = 0; i < n; i += {})
+    ;
+}
diff --git a/clang/test/OpenMP/unroll_messages.cpp 
b/clang/test/OpenMP/unroll_messages.cpp
index 87fc6ded58f9d2..2dd2242e9b42b7 100644
--- a/clang/test/OpenMP/unroll_messages.cpp
+++ b/clang/test/OpenMP/unroll_messages.cpp
@@ -196,4 +196,26 @@ template <typename T> void braced_init_templ() {
     ;
 }
 void braced_init_inst() { braced_init_templ<int>(); }
+
+struct It {
+  int *p;
+  It &operator++() { ++p; return *this; }
+  It &operator+=(int n) { p += n; return *this; }
+  friend bool operator<(It a, It b) { return a.p < b.p; }
+  friend int operator-(It a, It b) { return a.p - b.p; }
+  friend It operator+(It a, int n) { return {a.p + n}; }
+};
+void aggregate_counter(int *q) {
+#pragma omp for
+  for (It it = {q}; it < It{q + 4}; ++it)
+    ;
+
+#pragma omp unroll partial
+  for (It it = {q}; it < It{q + 4}; ++it)
+    ;
+
+#pragma omp unroll partial
+  for (It it = {}; it < It{q + 4}; ++it)
+    ;
+}
 }

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

Reply via email to