[clang] [OpenMP][Clang] Parsing support for num_teams lower bound (PR #180608)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Feb 13 12:50:25 PST 2026
https://github.com/ykhatav updated https://github.com/llvm/llvm-project/pull/180608
>From 911e236f65cc14874bdc77d17ea5c0da9d326041 Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Mon, 9 Feb 2026 12:39:08 -0800
Subject: [PATCH 1/9] Add parsing support for num_teams lower bound
---
.../clang/Basic/DiagnosticSemaKinds.td | 4 ++
clang/lib/Parse/ParseOpenMP.cpp | 48 ++++++++++++++++
clang/lib/Sema/SemaOpenMP.cpp | 56 ++++++++++++++-----
.../num_teams_lower_bound_error_test.cpp | 49 ++++++++++++++++
.../OpenMP/num_teams_lower_bound_support.cpp | 12 ++++
...et_teams_distribute_num_teams_messages.cpp | 4 +-
...ribute_parallel_for_num_teams_messages.cpp | 4 +-
.../test/OpenMP/teams_num_teams_messages.cpp | 4 +-
8 files changed, 161 insertions(+), 20 deletions(-)
create mode 100644 clang/test/OpenMP/num_teams_lower_bound_error_test.cpp
create mode 100644 clang/test/OpenMP/num_teams_lower_bound_support.cpp
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f12677ac11600..59ff6e563d779 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12543,6 +12543,10 @@ def err_omp_transparent_invalid_value : Error<"invalid value for transparent cla
" expected one of: omp_not_impex, omp_import, omp_export, omp_impex">;
def err_omp_transparent_invalid_type : Error<
"transparent clause cannot be applied to type: %0">;
+def err_omp_num_teams_multi_expr_not_allowed
+ : Error<"only two expression allowed in 'num_teams' clause">;
+def err_omp_num_teams_lower_bound_larger
+ : Error<"lower bound is greater than upper bound in 'num_teams' clause">;
} // end of OpenMP category
let CategoryName = "Related Result Type Issue" in {
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index b41803d23cb25..5bdaeb182bb9e 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -5080,6 +5080,54 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
Diag(Tok, diag::err_modifier_expected_colon) << "fallback";
}
}
+ } // Handle num_teams clause with optional lower-bound:upper-bound syntax
+ if (Kind == OMPC_num_teams && !Tok.is(tok::r_paren) &&
+ !Tok.is(tok::annot_pragma_openmp_end)) {
+ // Look ahead to detect top-level colon
+ TentativeParsingAction TPA(*this);
+ bool HasColon = false;
+ int Depth = 0;
+
+ while (!Tok.is(tok::r_paren) && !Tok.is(tok::annot_pragma_openmp_end)) {
+ if (Tok.isOneOf(tok::l_paren, tok::l_square))
+ Depth++;
+ else if (Tok.isOneOf(tok::r_paren, tok::r_square)) {
+ if (Depth == 0)
+ break;
+ Depth--;
+ } else if (Tok.is(tok::comma) && Depth == 0)
+ break; // comma-separated syntax
+ else if (Tok.is(tok::colon) && Depth == 0) {
+ HasColon = true;
+ break;
+ }
+ ConsumeAnyToken();
+ }
+ TPA.Revert();
+
+ // Only handle colon syntax, let normal parsing handle everything else
+ if (HasColon) {
+ ExprResult LowerBound = ParseAssignmentExpression();
+ if (!LowerBound.isInvalid()) {
+ Vars.push_back(LowerBound.get());
+ if (Tok.is(tok::colon)) {
+ ConsumeToken();
+ ExprResult UpperBound = ParseAssignmentExpression();
+ if (!UpperBound.isInvalid())
+ Vars.push_back(UpperBound.get());
+ else
+ SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end,
+ StopBeforeMatch);
+ }
+ } else {
+ SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch);
+ }
+
+ Data.RLoc = Tok.getLocation();
+ if (!T.consumeClose())
+ Data.RLoc = T.getCloseLocation();
+ return false;
+ }
}
bool IsComma =
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index e90884a89bf6e..0caef8dbf0c5f 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -13508,7 +13508,7 @@ StmtResult SemaOpenMP::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
return StmtError();
if (!checkNumExprsInClause<OMPNumTeamsClause>(
- *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
+ *this, Clauses, /*MaxNum=*/2, diag::err_omp_num_teams_multi_expr_not_allowed) ||
!checkNumExprsInClause<OMPThreadLimitClause>(
*this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
return StmtError();
@@ -14287,16 +14287,20 @@ StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDirective(
return StmtError();
}
- unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 1;
- unsigned DiagNo = HasBareClause
- ? diag::err_ompx_more_than_three_expr_not_allowed
- : diag::err_omp_multi_expr_not_allowed;
- if (!checkNumExprsInClause<OMPNumTeamsClause>(*this, Clauses,
- ClauseMaxNumExprs, DiagNo) ||
- !checkNumExprsInClause<OMPThreadLimitClause>(*this, Clauses,
- ClauseMaxNumExprs, DiagNo))
- return StmtError();
+ unsigned ClauseMaxNumExprs = HasBareClause ? 3 : 2;
+ unsigned NumTeamsDiag = HasBareClause
+ ? diag::err_ompx_more_than_three_expr_not_allowed
+ : diag::err_omp_num_teams_multi_expr_not_allowed;
+ unsigned ThreadLimitDiag =
+ HasBareClause ? diag::err_ompx_more_than_three_expr_not_allowed
+ : diag::err_omp_multi_expr_not_allowed;
+ if (!checkNumExprsInClause<OMPNumTeamsClause>(
+ *this, Clauses, ClauseMaxNumExprs, NumTeamsDiag) ||
+ !checkNumExprsInClause<OMPThreadLimitClause>(
+ *this, Clauses, ClauseMaxNumExprs, ThreadLimitDiag)) {
+ return StmtError();
+ }
return OMPTargetTeamsDirective::Create(getASTContext(), StartLoc, EndLoc,
Clauses, AStmt);
}
@@ -14308,7 +14312,7 @@ StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeDirective(
return StmtError();
if (!checkNumExprsInClause<OMPNumTeamsClause>(
- *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
+ *this, Clauses, /*MaxNum=*/2, diag::err_omp_num_teams_multi_expr_not_allowed) ||
!checkNumExprsInClause<OMPThreadLimitClause>(
*this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
return StmtError();
@@ -14340,7 +14344,7 @@ StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
return StmtError();
if (!checkNumExprsInClause<OMPNumTeamsClause>(
- *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
+ *this, Clauses, /*MaxNum=*/2, diag::err_omp_num_teams_multi_expr_not_allowed) ||
!checkNumExprsInClause<OMPThreadLimitClause>(
*this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
return StmtError();
@@ -14373,7 +14377,7 @@ StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
return StmtError();
if (!checkNumExprsInClause<OMPNumTeamsClause>(
- *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
+ *this, Clauses, /*MaxNum=*/2, diag::err_omp_num_teams_multi_expr_not_allowed) ||
!checkNumExprsInClause<OMPThreadLimitClause>(
*this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
return StmtError();
@@ -14409,7 +14413,7 @@ StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeSimdDirective(
return StmtError();
if (!checkNumExprsInClause<OMPNumTeamsClause>(
- *this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed) ||
+ *this, Clauses, /*MaxNum=*/2, diag::err_omp_num_teams_multi_expr_not_allowed) ||
!checkNumExprsInClause<OMPThreadLimitClause>(
*this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
return StmtError();
@@ -23880,6 +23884,30 @@ OMPClause *SemaOpenMP::ActOnOpenMPNumTeamsClause(ArrayRef<Expr *> VarList,
return nullptr;
}
+ // OpenMP 5.2: Validate lower-bound ≤ upper-bound constraint
+ if (VarList.size() == 2) {
+ Expr *LowerBound = VarList[0];
+ Expr *UpperBound = VarList[1];
+
+ // Check if both are compile-time constants for validation
+ if (LowerBound->isIntegerConstantExpr(getASTContext()) &&
+ UpperBound->isIntegerConstantExpr(getASTContext())) {
+
+ // Get the actual constant values
+ llvm::APSInt LowerVal =
+ LowerBound->EvaluateKnownConstInt(getASTContext());
+ llvm::APSInt UpperVal =
+ UpperBound->EvaluateKnownConstInt(getASTContext());
+
+ if (LowerVal > UpperVal) {
+ Diag(LowerBound->getExprLoc(),
+ diag::err_omp_num_teams_lower_bound_larger)
+ << LowerBound->getSourceRange() << UpperBound->getSourceRange();
+ return nullptr;
+ }
+ }
+ }
+
OpenMPDirectiveKind DKind = DSAStack->getCurrentDirective();
OpenMPDirectiveKind CaptureRegion = getOpenMPCaptureRegionForClause(
DKind, OMPC_num_teams, getLangOpts().OpenMP);
diff --git a/clang/test/OpenMP/num_teams_lower_bound_error_test.cpp b/clang/test/OpenMP/num_teams_lower_bound_error_test.cpp
new file mode 100644
index 0000000000000..9c6817999f17c
--- /dev/null
+++ b/clang/test/OpenMP/num_teams_lower_bound_error_test.cpp
@@ -0,0 +1,49 @@
+// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s -Wuninitialized
+
+// Test invalid syntax cases for num_teams lower-bound:upper-bound
+void test_invalid_syntax() {
+ int a = 1, b = 2, c = 3;
+
+ // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
+ #pragma omp teams num_teams(a, b, c)
+ { }
+ // expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
+ #pragma omp teams num_teams(10:5)
+ { }
+
+ // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
+ #pragma omp target teams num_teams(a, b, c)
+ { }
+ // expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
+ #pragma omp target teams num_teams(8:3)
+ { }
+
+ // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
+ #pragma omp target teams distribute num_teams(a, b, c)
+ for (int i = 0; i < 100; ++i) { }
+ // expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
+ #pragma omp target teams distribute num_teams(15:7)
+ for (int i = 0; i < 100; ++i) { }
+
+ // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
+ #pragma omp target teams distribute parallel for num_teams(a, b, c)
+ for (int i = 0; i < 100; ++i) { }
+ // expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
+ #pragma omp target teams distribute parallel for num_teams(12:4)
+ for (int i = 0; i < 100; ++i) { }
+
+ // Test target teams distribute parallel for simd directive
+ // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
+ #pragma omp target teams distribute parallel for simd num_teams(a, b, c)
+ for (int i = 0; i < 100; ++i) { }
+ // expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
+ #pragma omp target teams distribute parallel for simd num_teams(20:6)
+ for (int i = 0; i < 100; ++i) { }
+
+ // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
+ #pragma omp target teams distribute simd num_teams(a, b, c)
+ for (int i = 0; i < 100; ++i) { }
+ // expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
+ #pragma omp target teams distribute simd num_teams(9:2)
+ for (int i = 0; i < 100; ++i) { }
+}
diff --git a/clang/test/OpenMP/num_teams_lower_bound_support.cpp b/clang/test/OpenMP/num_teams_lower_bound_support.cpp
new file mode 100644
index 0000000000000..13aa1dacd9a8e
--- /dev/null
+++ b/clang/test/OpenMP/num_teams_lower_bound_support.cpp
@@ -0,0 +1,12 @@
+// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-linux-gnu -emit-llvm %s -o -
+// expected-no-diagnostics
+//
+
+int main() {
+ #pragma omp teams num_teams(1:1)
+ {
+ // Teams region
+ }
+
+ return 0;
+}
diff --git a/clang/test/OpenMP/target_teams_distribute_num_teams_messages.cpp b/clang/test/OpenMP/target_teams_distribute_num_teams_messages.cpp
index 8bf388f0b5da9..478c2d5202419 100644
--- a/clang/test/OpenMP/target_teams_distribute_num_teams_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_num_teams_messages.cpp
@@ -44,7 +44,7 @@ T tmain(T argc) {
#pragma omp target teams distribute num_teams(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
for (int i=0; i<100; i++) foo();
-#pragma omp target teams distribute num_teams(1, 2, 3) // expected-error {{only one expression allowed in 'num_teams' clause}}
+#pragma omp target teams distribute num_teams(1, 2, 3) // expected-error {{only two expression allowed in 'num_teams' clause}}
for (int i=0; i<100; i++) foo();
#pragma omp target teams distribute thread_limit(1, 2, 3) // expected-error {{only one expression allowed in 'thread_limit' clause}}
@@ -97,7 +97,7 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute num_teams (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
for (int i=0; i<100; i++) foo();
-#pragma omp target teams distribute num_teams(1, 2, 3) // expected-error {{only one expression allowed in 'num_teams' clause}}
+#pragma omp target teams distribute num_teams(1, 2, 3) // expected-error {{only two expression allowed in 'num_teams' clause}}
for (int i=0; i<100; i++) foo();
#pragma omp target teams distribute thread_limit(1, 2, 3) // expected-error {{only one expression allowed in 'thread_limit' clause}}
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_num_teams_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_num_teams_messages.cpp
index 092e0137d250d..c9b3d3f562ed7 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_num_teams_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_num_teams_messages.cpp
@@ -43,7 +43,7 @@ T tmain(T argc) {
for (int i=0; i<100; i++) foo();
#pragma omp target teams distribute parallel for num_teams(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
for (int i=0; i<100; i++) foo();
-#pragma omp target teams distribute parallel for num_teams(1, 2, 3) // expected-error {{only one expression allowed in 'num_teams' clause}}
+#pragma omp target teams distribute parallel for num_teams(1, 2, 3) // expected-error {{only two expression allowed in 'num_teams' clause}}
for (int i=0; i<100; i++) foo();
#pragma omp target teams distribute parallel for thread_limit(1, 2, 3) // expected-error {{only one expression allowed in 'thread_limit' clause}}
for (int i=0; i<100; i++) foo();
@@ -89,7 +89,7 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute parallel for num_teams (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
for (int i=0; i<100; i++) foo();
-#pragma omp target teams distribute parallel for num_teams(1, 2, 3) // expected-error {{only one expression allowed in 'num_teams' clause}}
+#pragma omp target teams distribute parallel for num_teams(1, 2, 3) // expected-error {{only two expression allowed in 'num_teams' clause}}
for (int i=0; i<100; i++) foo();
#pragma omp target teams distribute parallel for thread_limit(1, 2, 3) // expected-error {{only one expression allowed in 'thread_limit' clause}}
diff --git a/clang/test/OpenMP/teams_num_teams_messages.cpp b/clang/test/OpenMP/teams_num_teams_messages.cpp
index 615bf0be0d814..458e4e9d640b3 100644
--- a/clang/test/OpenMP/teams_num_teams_messages.cpp
+++ b/clang/test/OpenMP/teams_num_teams_messages.cpp
@@ -58,7 +58,7 @@ T tmain(T argc) {
#pragma omp teams num_teams(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
foo();
#pragma omp target
-#pragma omp teams num_teams (1, 2, 3) // expected-error {{only one expression allowed in 'num_teams' clause}}
+#pragma omp teams num_teams (1, 2, 3) // expected-error {{only two expression allowed in 'num_teams' clause}}
foo();
#pragma omp target
#pragma omp teams thread_limit(1, 2, 3) // expected-error {{only one expression allowed in 'thread_limit' clause}}
@@ -118,7 +118,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
-#pragma omp teams num_teams (1, 2, 3) // expected-error {{only one expression allowed in 'num_teams' clause}}
+#pragma omp teams num_teams (1, 2, 3) // expected-error {{only two expression allowed in 'num_teams' clause}}
foo();
#pragma omp target
>From 81efa66b63185b9af9dd37a6282fe1608f2ee79d Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Mon, 9 Feb 2026 12:46:31 -0800
Subject: [PATCH 2/9] Apply clang-format
---
clang/lib/Sema/SemaOpenMP.cpp | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 0caef8dbf0c5f..f2dc68481b451 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -13508,7 +13508,8 @@ StmtResult SemaOpenMP::ActOnOpenMPTeamsDirective(ArrayRef<OMPClause *> Clauses,
return StmtError();
if (!checkNumExprsInClause<OMPNumTeamsClause>(
- *this, Clauses, /*MaxNum=*/2, diag::err_omp_num_teams_multi_expr_not_allowed) ||
+ *this, Clauses, /*MaxNum=*/2,
+ diag::err_omp_num_teams_multi_expr_not_allowed) ||
!checkNumExprsInClause<OMPThreadLimitClause>(
*this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
return StmtError();
@@ -14312,7 +14313,8 @@ StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeDirective(
return StmtError();
if (!checkNumExprsInClause<OMPNumTeamsClause>(
- *this, Clauses, /*MaxNum=*/2, diag::err_omp_num_teams_multi_expr_not_allowed) ||
+ *this, Clauses, /*MaxNum=*/2,
+ diag::err_omp_num_teams_multi_expr_not_allowed) ||
!checkNumExprsInClause<OMPThreadLimitClause>(
*this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
return StmtError();
@@ -14344,7 +14346,8 @@ StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForDirective(
return StmtError();
if (!checkNumExprsInClause<OMPNumTeamsClause>(
- *this, Clauses, /*MaxNum=*/2, diag::err_omp_num_teams_multi_expr_not_allowed) ||
+ *this, Clauses, /*MaxNum=*/2,
+ diag::err_omp_num_teams_multi_expr_not_allowed) ||
!checkNumExprsInClause<OMPThreadLimitClause>(
*this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
return StmtError();
@@ -14377,7 +14380,8 @@ StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeParallelForSimdDirective(
return StmtError();
if (!checkNumExprsInClause<OMPNumTeamsClause>(
- *this, Clauses, /*MaxNum=*/2, diag::err_omp_num_teams_multi_expr_not_allowed) ||
+ *this, Clauses, /*MaxNum=*/2,
+ diag::err_omp_num_teams_multi_expr_not_allowed) ||
!checkNumExprsInClause<OMPThreadLimitClause>(
*this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
return StmtError();
@@ -14413,7 +14417,8 @@ StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeSimdDirective(
return StmtError();
if (!checkNumExprsInClause<OMPNumTeamsClause>(
- *this, Clauses, /*MaxNum=*/2, diag::err_omp_num_teams_multi_expr_not_allowed) ||
+ *this, Clauses, /*MaxNum=*/2,
+ diag::err_omp_num_teams_multi_expr_not_allowed) ||
!checkNumExprsInClause<OMPThreadLimitClause>(
*this, Clauses, /*MaxNum=*/1, diag::err_omp_multi_expr_not_allowed))
return StmtError();
>From e582cc226f19e6ce5bd209d0ccd585d78b138f5f Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Tue, 10 Feb 2026 14:15:39 -0800
Subject: [PATCH 3/9] Address review comment regarding test case
---
clang/lib/AST/OpenMPClause.cpp | 20 ++++++-
clang/test/OpenMP/num_teams_clause_ast.cpp | 56 +++++++++++++++++++
.../num_teams_lower_bound_error_test.cpp | 49 ----------------
.../OpenMP/num_teams_lower_bound_support.cpp | 12 ----
.../test/OpenMP/teams_num_teams_messages.cpp | 48 ++++++++++++++++
5 files changed, 122 insertions(+), 63 deletions(-)
create mode 100644 clang/test/OpenMP/num_teams_clause_ast.cpp
delete mode 100644 clang/test/OpenMP/num_teams_lower_bound_error_test.cpp
delete mode 100644 clang/test/OpenMP/num_teams_lower_bound_support.cpp
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 9e7a8a48372c7..ad72c3d5a143c 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -2290,8 +2290,24 @@ void OMPClausePrinter::VisitOMPDeviceClause(OMPDeviceClause *Node) {
void OMPClausePrinter::VisitOMPNumTeamsClause(OMPNumTeamsClause *Node) {
if (!Node->varlist_empty()) {
- OS << "num_teams";
- VisitOMPClauseList(Node, '(');
+ OS << "num_teams(";
+ // Handle lower-bound:upper-bound syntax when there are exactly 2 expressions
+ if (Node->varlist_size() == 2) {
+ auto *I = Node->varlist_begin();
+ (*I)->printPretty(OS, nullptr, Policy, 0);
+ OS << ":";
+ ++I;
+ (*I)->printPretty(OS, nullptr, Policy, 0);
+ } else {
+ // For single expression or other cases, use comma-separated list
+ bool First = true;
+ for (auto *I = Node->varlist_begin(), *E = Node->varlist_end(); I != E; ++I) {
+ if (!First)
+ OS << ",";
+ First = false;
+ (*I)->printPretty(OS, nullptr, Policy, 0);
+ }
+ }
OS << ")";
}
}
diff --git a/clang/test/OpenMP/num_teams_clause_ast.cpp b/clang/test/OpenMP/num_teams_clause_ast.cpp
new file mode 100644
index 0000000000000..2136928076a88
--- /dev/null
+++ b/clang/test/OpenMP/num_teams_clause_ast.cpp
@@ -0,0 +1,56 @@
+// RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s
+// expected-no-diagnostics
+
+void foo();
+
+// CHECK-LABEL: void test_lower_upper_bound()
+void test_lower_upper_bound() {
+ int lower = 2, upper = 8;
+ // CHECK: #pragma omp teams num_teams(2:8)
+ #pragma omp teams num_teams(2:8)
+ { foo(); }
+
+ // CHECK: #pragma omp teams num_teams(lower:upper)
+ #pragma omp teams num_teams(lower:upper)
+ { foo(); }
+
+ // CHECK: #pragma omp target teams num_teams(1:10)
+ #pragma omp target teams num_teams(1:10)
+ { foo(); }
+
+ // CHECK: #pragma omp target teams distribute num_teams(3:6)
+ #pragma omp target teams distribute num_teams(3:6)
+ for (int i = 0; i < 100; ++i) { }
+}
+
+// CHECK-LABEL: void test_various_directives()
+void test_various_directives() {
+ int lb = 4, ub = 12;
+
+ // CHECK: #pragma omp target teams distribute parallel for num_teams(lb:ub)
+ #pragma omp target teams distribute parallel for num_teams(lb:ub)
+ for (int i = 0; i < 100; ++i) { }
+
+ // CHECK: #pragma omp target teams distribute parallel for simd num_teams(2:16)
+ #pragma omp target teams distribute parallel for simd num_teams(2:16)
+ for (int i = 0; i < 100; ++i) { }
+
+ // CHECK: #pragma omp target teams distribute simd num_teams(1:8)
+ #pragma omp target teams distribute simd num_teams(1:8)
+ for (int i = 0; i < 100; ++i) { }
+}
+
+template <typename T>
+T tmain(T argc) {
+ T lower = 1, upper = 5;
+
+ // CHECK: #pragma omp teams num_teams(argc)
+ #pragma omp teams num_teams(argc)
+ { foo(); }
+
+ // CHECK: #pragma omp teams num_teams(lower:upper)
+ #pragma omp teams num_teams(lower:upper)
+ { foo(); }
+
+ return argc;
+}
diff --git a/clang/test/OpenMP/num_teams_lower_bound_error_test.cpp b/clang/test/OpenMP/num_teams_lower_bound_error_test.cpp
deleted file mode 100644
index 9c6817999f17c..0000000000000
--- a/clang/test/OpenMP/num_teams_lower_bound_error_test.cpp
+++ /dev/null
@@ -1,49 +0,0 @@
-// RUN: %clang_cc1 -verify -fopenmp -std=c++11 %s -Wuninitialized
-
-// Test invalid syntax cases for num_teams lower-bound:upper-bound
-void test_invalid_syntax() {
- int a = 1, b = 2, c = 3;
-
- // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
- #pragma omp teams num_teams(a, b, c)
- { }
- // expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
- #pragma omp teams num_teams(10:5)
- { }
-
- // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
- #pragma omp target teams num_teams(a, b, c)
- { }
- // expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
- #pragma omp target teams num_teams(8:3)
- { }
-
- // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
- #pragma omp target teams distribute num_teams(a, b, c)
- for (int i = 0; i < 100; ++i) { }
- // expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
- #pragma omp target teams distribute num_teams(15:7)
- for (int i = 0; i < 100; ++i) { }
-
- // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
- #pragma omp target teams distribute parallel for num_teams(a, b, c)
- for (int i = 0; i < 100; ++i) { }
- // expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
- #pragma omp target teams distribute parallel for num_teams(12:4)
- for (int i = 0; i < 100; ++i) { }
-
- // Test target teams distribute parallel for simd directive
- // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
- #pragma omp target teams distribute parallel for simd num_teams(a, b, c)
- for (int i = 0; i < 100; ++i) { }
- // expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
- #pragma omp target teams distribute parallel for simd num_teams(20:6)
- for (int i = 0; i < 100; ++i) { }
-
- // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
- #pragma omp target teams distribute simd num_teams(a, b, c)
- for (int i = 0; i < 100; ++i) { }
- // expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
- #pragma omp target teams distribute simd num_teams(9:2)
- for (int i = 0; i < 100; ++i) { }
-}
diff --git a/clang/test/OpenMP/num_teams_lower_bound_support.cpp b/clang/test/OpenMP/num_teams_lower_bound_support.cpp
deleted file mode 100644
index 13aa1dacd9a8e..0000000000000
--- a/clang/test/OpenMP/num_teams_lower_bound_support.cpp
+++ /dev/null
@@ -1,12 +0,0 @@
-// RUN: %clang_cc1 -verify -fopenmp -x c++ -triple x86_64-unknown-linux-gnu -emit-llvm %s -o -
-// expected-no-diagnostics
-//
-
-int main() {
- #pragma omp teams num_teams(1:1)
- {
- // Teams region
- }
-
- return 0;
-}
diff --git a/clang/test/OpenMP/teams_num_teams_messages.cpp b/clang/test/OpenMP/teams_num_teams_messages.cpp
index 458e4e9d640b3..3e204ba373baa 100644
--- a/clang/test/OpenMP/teams_num_teams_messages.cpp
+++ b/clang/test/OpenMP/teams_num_teams_messages.cpp
@@ -127,3 +127,51 @@ int main(int argc, char **argv) {
return tmain<int, 10>(argc); // expected-note {{in instantiation of function template specialization 'tmain<int, 10>' requested here}}
}
+
+// Test invalid syntax cases for num_teams lower-bound:upper-bound
+void test_invalid_syntax() {
+ int a = 1, b = 2, c = 3;
+
+ // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
+ #pragma omp teams num_teams(a, b, c)
+ { }
+ // expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
+ #pragma omp teams num_teams(10:5)
+ { }
+
+ // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
+ #pragma omp target teams num_teams(a, b, c)
+ { }
+ // expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
+ #pragma omp target teams num_teams(8:3)
+ { }
+
+ // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
+ #pragma omp target teams distribute num_teams(a, b, c)
+ for (int i = 0; i < 100; ++i) { }
+ // expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
+ #pragma omp target teams distribute num_teams(15:7)
+ for (int i = 0; i < 100; ++i) { }
+
+ // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
+ #pragma omp target teams distribute parallel for num_teams(a, b, c)
+ for (int i = 0; i < 100; ++i) { }
+ // expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
+ #pragma omp target teams distribute parallel for num_teams(12:4)
+ for (int i = 0; i < 100; ++i) { }
+
+ // Test target teams distribute parallel for simd directive
+ // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
+ #pragma omp target teams distribute parallel for simd num_teams(a, b, c)
+ for (int i = 0; i < 100; ++i) { }
+ // expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
+ #pragma omp target teams distribute parallel for simd num_teams(20:6)
+ for (int i = 0; i < 100; ++i) { }
+
+ // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
+ #pragma omp target teams distribute simd num_teams(a, b, c)
+ for (int i = 0; i < 100; ++i) { }
+ // expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
+ #pragma omp target teams distribute simd num_teams(9:2)
+ for (int i = 0; i < 100; ++i) { }
+}
>From b7bab7bc13a89f483700f8fc1a5ad46a4f5e986d Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Tue, 10 Feb 2026 14:33:36 -0800
Subject: [PATCH 4/9] Apply clang-format
---
clang/lib/AST/OpenMPClause.cpp | 6 ++++--
clang/test/OpenMP/num_teams_clause_ast.cpp | 14 --------------
2 files changed, 4 insertions(+), 16 deletions(-)
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index ad72c3d5a143c..f9bc5a9a1c0a1 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -2291,7 +2291,8 @@ void OMPClausePrinter::VisitOMPDeviceClause(OMPDeviceClause *Node) {
void OMPClausePrinter::VisitOMPNumTeamsClause(OMPNumTeamsClause *Node) {
if (!Node->varlist_empty()) {
OS << "num_teams(";
- // Handle lower-bound:upper-bound syntax when there are exactly 2 expressions
+ // Handle lower-bound:upper-bound syntax when there are exactly 2
+ // expressions
if (Node->varlist_size() == 2) {
auto *I = Node->varlist_begin();
(*I)->printPretty(OS, nullptr, Policy, 0);
@@ -2301,7 +2302,8 @@ void OMPClausePrinter::VisitOMPNumTeamsClause(OMPNumTeamsClause *Node) {
} else {
// For single expression or other cases, use comma-separated list
bool First = true;
- for (auto *I = Node->varlist_begin(), *E = Node->varlist_end(); I != E; ++I) {
+ for (auto *I = Node->varlist_begin(), *E = Node->varlist_end(); I != E;
+ ++I) {
if (!First)
OS << ",";
First = false;
diff --git a/clang/test/OpenMP/num_teams_clause_ast.cpp b/clang/test/OpenMP/num_teams_clause_ast.cpp
index 2136928076a88..658320352c5cd 100644
--- a/clang/test/OpenMP/num_teams_clause_ast.cpp
+++ b/clang/test/OpenMP/num_teams_clause_ast.cpp
@@ -40,17 +40,3 @@ void test_various_directives() {
for (int i = 0; i < 100; ++i) { }
}
-template <typename T>
-T tmain(T argc) {
- T lower = 1, upper = 5;
-
- // CHECK: #pragma omp teams num_teams(argc)
- #pragma omp teams num_teams(argc)
- { foo(); }
-
- // CHECK: #pragma omp teams num_teams(lower:upper)
- #pragma omp teams num_teams(lower:upper)
- { foo(); }
-
- return argc;
-}
>From 166e823a29b3ad0ed7691d8a301869041b7af315 Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Wed, 11 Feb 2026 10:50:20 -0800
Subject: [PATCH 5/9] Update the error message
---
clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 +-
...arget_teams_distribute_num_teams_messages.cpp | 4 ++--
...istribute_parallel_for_num_teams_messages.cpp | 4 ++--
clang/test/OpenMP/teams_num_teams_messages.cpp | 16 ++++++++--------
4 files changed, 13 insertions(+), 13 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 59ff6e563d779..9a52f7a7a1a8e 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -12544,7 +12544,7 @@ def err_omp_transparent_invalid_value : Error<"invalid value for transparent cla
def err_omp_transparent_invalid_type : Error<
"transparent clause cannot be applied to type: %0">;
def err_omp_num_teams_multi_expr_not_allowed
- : Error<"only two expression allowed in 'num_teams' clause">;
+ : Error<"only two expressions allowed in 'num_teams' clause">;
def err_omp_num_teams_lower_bound_larger
: Error<"lower bound is greater than upper bound in 'num_teams' clause">;
} // end of OpenMP category
diff --git a/clang/test/OpenMP/target_teams_distribute_num_teams_messages.cpp b/clang/test/OpenMP/target_teams_distribute_num_teams_messages.cpp
index 478c2d5202419..51948adba354f 100644
--- a/clang/test/OpenMP/target_teams_distribute_num_teams_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_num_teams_messages.cpp
@@ -44,7 +44,7 @@ T tmain(T argc) {
#pragma omp target teams distribute num_teams(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
for (int i=0; i<100; i++) foo();
-#pragma omp target teams distribute num_teams(1, 2, 3) // expected-error {{only two expression allowed in 'num_teams' clause}}
+#pragma omp target teams distribute num_teams(1, 2, 3) // expected-error {{only two expressions allowed in 'num_teams' clause}}
for (int i=0; i<100; i++) foo();
#pragma omp target teams distribute thread_limit(1, 2, 3) // expected-error {{only one expression allowed in 'thread_limit' clause}}
@@ -97,7 +97,7 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute num_teams (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
for (int i=0; i<100; i++) foo();
-#pragma omp target teams distribute num_teams(1, 2, 3) // expected-error {{only two expression allowed in 'num_teams' clause}}
+#pragma omp target teams distribute num_teams(1, 2, 3) // expected-error {{only two expressions allowed in 'num_teams' clause}}
for (int i=0; i<100; i++) foo();
#pragma omp target teams distribute thread_limit(1, 2, 3) // expected-error {{only one expression allowed in 'thread_limit' clause}}
diff --git a/clang/test/OpenMP/target_teams_distribute_parallel_for_num_teams_messages.cpp b/clang/test/OpenMP/target_teams_distribute_parallel_for_num_teams_messages.cpp
index c9b3d3f562ed7..02393f5094e09 100644
--- a/clang/test/OpenMP/target_teams_distribute_parallel_for_num_teams_messages.cpp
+++ b/clang/test/OpenMP/target_teams_distribute_parallel_for_num_teams_messages.cpp
@@ -43,7 +43,7 @@ T tmain(T argc) {
for (int i=0; i<100; i++) foo();
#pragma omp target teams distribute parallel for num_teams(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
for (int i=0; i<100; i++) foo();
-#pragma omp target teams distribute parallel for num_teams(1, 2, 3) // expected-error {{only two expression allowed in 'num_teams' clause}}
+#pragma omp target teams distribute parallel for num_teams(1, 2, 3) // expected-error {{only two expressions allowed in 'num_teams' clause}}
for (int i=0; i<100; i++) foo();
#pragma omp target teams distribute parallel for thread_limit(1, 2, 3) // expected-error {{only one expression allowed in 'thread_limit' clause}}
for (int i=0; i<100; i++) foo();
@@ -89,7 +89,7 @@ int main(int argc, char **argv) {
#pragma omp target teams distribute parallel for num_teams (3.14) // expected-error {{expression must have integral or unscoped enumeration type, not 'double'}}
for (int i=0; i<100; i++) foo();
-#pragma omp target teams distribute parallel for num_teams(1, 2, 3) // expected-error {{only two expression allowed in 'num_teams' clause}}
+#pragma omp target teams distribute parallel for num_teams(1, 2, 3) // expected-error {{only two expressions allowed in 'num_teams' clause}}
for (int i=0; i<100; i++) foo();
#pragma omp target teams distribute parallel for thread_limit(1, 2, 3) // expected-error {{only one expression allowed in 'thread_limit' clause}}
diff --git a/clang/test/OpenMP/teams_num_teams_messages.cpp b/clang/test/OpenMP/teams_num_teams_messages.cpp
index 3e204ba373baa..5248cd0197f9a 100644
--- a/clang/test/OpenMP/teams_num_teams_messages.cpp
+++ b/clang/test/OpenMP/teams_num_teams_messages.cpp
@@ -58,7 +58,7 @@ T tmain(T argc) {
#pragma omp teams num_teams(3.14) // expected-error 2 {{expression must have integral or unscoped enumeration type, not 'double'}}
foo();
#pragma omp target
-#pragma omp teams num_teams (1, 2, 3) // expected-error {{only two expression allowed in 'num_teams' clause}}
+#pragma omp teams num_teams (1, 2, 3) // expected-error {{only two expressions allowed in 'num_teams' clause}}
foo();
#pragma omp target
#pragma omp teams thread_limit(1, 2, 3) // expected-error {{only one expression allowed in 'thread_limit' clause}}
@@ -118,7 +118,7 @@ int main(int argc, char **argv) {
foo();
#pragma omp target
-#pragma omp teams num_teams (1, 2, 3) // expected-error {{only two expression allowed in 'num_teams' clause}}
+#pragma omp teams num_teams (1, 2, 3) // expected-error {{only two expressions allowed in 'num_teams' clause}}
foo();
#pragma omp target
@@ -132,28 +132,28 @@ int main(int argc, char **argv) {
void test_invalid_syntax() {
int a = 1, b = 2, c = 3;
- // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
+ // expected-error at +1 {{only two expressions allowed in 'num_teams' clause}}
#pragma omp teams num_teams(a, b, c)
{ }
// expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
#pragma omp teams num_teams(10:5)
{ }
- // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
+ // expected-error at +1 {{only two expressions allowed in 'num_teams' clause}}
#pragma omp target teams num_teams(a, b, c)
{ }
// expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
#pragma omp target teams num_teams(8:3)
{ }
- // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
+ // expected-error at +1 {{only two expressions allowed in 'num_teams' clause}}
#pragma omp target teams distribute num_teams(a, b, c)
for (int i = 0; i < 100; ++i) { }
// expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
#pragma omp target teams distribute num_teams(15:7)
for (int i = 0; i < 100; ++i) { }
- // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
+ // expected-error at +1 {{only two expressions allowed in 'num_teams' clause}}
#pragma omp target teams distribute parallel for num_teams(a, b, c)
for (int i = 0; i < 100; ++i) { }
// expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
@@ -161,14 +161,14 @@ void test_invalid_syntax() {
for (int i = 0; i < 100; ++i) { }
// Test target teams distribute parallel for simd directive
- // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
+ // expected-error at +1 {{only two expressions allowed in 'num_teams' clause}}
#pragma omp target teams distribute parallel for simd num_teams(a, b, c)
for (int i = 0; i < 100; ++i) { }
// expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
#pragma omp target teams distribute parallel for simd num_teams(20:6)
for (int i = 0; i < 100; ++i) { }
- // expected-error at +1 {{only two expression allowed in 'num_teams' clause}}
+ // expected-error at +1 {{only two expressions allowed in 'num_teams' clause}}
#pragma omp target teams distribute simd num_teams(a, b, c)
for (int i = 0; i < 100; ++i) { }
// expected-error at +1 {{lower bound is greater than upper bound in 'num_teams' clause}}
>From 457ca18bf7adb853e1d12e79c1c2ec1461d5db3f Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Thu, 12 Feb 2026 08:41:20 -0800
Subject: [PATCH 6/9] Apply review comments
---
clang/lib/AST/OpenMPClause.cpp | 21 ++++++++------------
clang/lib/Parse/ParseOpenMP.cpp | 3 ++-
clang/test/OpenMP/target_teams_ast_print.cpp | 4 ++--
3 files changed, 12 insertions(+), 16 deletions(-)
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index f9bc5a9a1c0a1..72da1636e8d73 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -2294,21 +2294,16 @@ void OMPClausePrinter::VisitOMPNumTeamsClause(OMPNumTeamsClause *Node) {
// Handle lower-bound:upper-bound syntax when there are exactly 2
// expressions
if (Node->varlist_size() == 2) {
- auto *I = Node->varlist_begin();
- (*I)->printPretty(OS, nullptr, Policy, 0);
- OS << ":";
- ++I;
- (*I)->printPretty(OS, nullptr, Policy, 0);
+ llvm::interleave(Node->varlist(), OS,
+ [&](const auto *Expr) {
+ Expr->printPretty(OS, nullptr, Policy, 0);
+ },
+ ":");
} else {
// For single expression or other cases, use comma-separated list
- bool First = true;
- for (auto *I = Node->varlist_begin(), *E = Node->varlist_end(); I != E;
- ++I) {
- if (!First)
- OS << ",";
- First = false;
- (*I)->printPretty(OS, nullptr, Policy, 0);
- }
+ llvm::interleaveComma(Node->varlist(), OS, [&](const auto *Expr) {
+ Expr->printPretty(OS, nullptr, Policy, 0);
+ });
}
OS << ")";
}
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 5bdaeb182bb9e..db4a5e9d81eff 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -5095,8 +5095,9 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
if (Depth == 0)
break;
Depth--;
- } else if (Tok.is(tok::comma) && Depth == 0)
+ } else if (Tok.is(tok::comma) && Depth == 0) {
break; // comma-separated syntax
+ }
else if (Tok.is(tok::colon) && Depth == 0) {
HasColon = true;
break;
diff --git a/clang/test/OpenMP/target_teams_ast_print.cpp b/clang/test/OpenMP/target_teams_ast_print.cpp
index cc47ae92efac0..5a577bd2d1b1e 100644
--- a/clang/test/OpenMP/target_teams_ast_print.cpp
+++ b/clang/test/OpenMP/target_teams_ast_print.cpp
@@ -95,7 +95,7 @@ T tmain(T argc, T *argv) {
// CHECK-NEXT: foo()
// CHECK-NEXT: #pragma omp target teams allocate(my_allocator: f) reduction(^: e,f) reduction(&&: g) uses_allocators(my_allocator(traits))
// CHECK-NEXT: foo()
-// CHECK-NEXT: #pragma omp target teams ompx_bare num_teams(1,1,1) thread_limit(d * 1,d * 1,d * 1)
+// CHECK-NEXT: #pragma omp target teams ompx_bare num_teams(1, 1, 1) thread_limit(d * 1,d * 1,d * 1)
// CHECK-NEXT: foo();
enum Enum { };
@@ -116,7 +116,7 @@ int main (int argc, char **argv) {
a=3;
// CHECK-NEXT: a = 3;
#pragma omp target teams ompx_bare num_teams(1, 2, 3) thread_limit(2, 4, 6)
-// CHECK-NEXT: #pragma omp target teams ompx_bare num_teams(1,2,3) thread_limit(2,4,6)
+// CHECK-NEXT: #pragma omp target teams ompx_bare num_teams(1, 2, 3) thread_limit(2,4,6)
a=4;
// CHECK-NEXT: a = 4;
#pragma omp target teams default(none), private(argc,b) num_teams(f) firstprivate(argv) reduction(| : c, d) reduction(* : e) thread_limit(f+g)
>From 5e65f078fb8dc9d4523e34616085a0b30e5243d8 Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Thu, 12 Feb 2026 08:46:53 -0800
Subject: [PATCH 7/9] Apply clang-format
---
clang/lib/AST/OpenMPClause.cpp | 11 +++++------
clang/lib/Parse/ParseOpenMP.cpp | 3 +--
2 files changed, 6 insertions(+), 8 deletions(-)
diff --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 72da1636e8d73..48ec1551d0607 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -2294,14 +2294,13 @@ void OMPClausePrinter::VisitOMPNumTeamsClause(OMPNumTeamsClause *Node) {
// Handle lower-bound:upper-bound syntax when there are exactly 2
// expressions
if (Node->varlist_size() == 2) {
- llvm::interleave(Node->varlist(), OS,
- [&](const auto *Expr) {
- Expr->printPretty(OS, nullptr, Policy, 0);
- },
- ":");
+ llvm::interleave(
+ Node->varlist(), OS,
+ [&](const auto *Expr) { Expr->printPretty(OS, nullptr, Policy, 0); },
+ ":");
} else {
// For single expression or other cases, use comma-separated list
- llvm::interleaveComma(Node->varlist(), OS, [&](const auto *Expr) {
+ llvm::interleaveComma(Node->varlist(), OS, [&](const auto *Expr) {
Expr->printPretty(OS, nullptr, Policy, 0);
});
}
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index db4a5e9d81eff..d28b0a17afae1 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -5097,8 +5097,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
Depth--;
} else if (Tok.is(tok::comma) && Depth == 0) {
break; // comma-separated syntax
- }
- else if (Tok.is(tok::colon) && Depth == 0) {
+ } else if (Tok.is(tok::colon) && Depth == 0) {
HasColon = true;
break;
}
>From 99560cbd16d586b38ffef74d15cea89cf8b9c9d0 Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Fri, 13 Feb 2026 11:06:17 -0800
Subject: [PATCH 8/9] Add test cases for nested parens
---
clang/lib/Parse/ParseOpenMP.cpp | 3 +-
clang/test/OpenMP/num_teams_clause_ast.cpp | 46 ++++++++++++++
.../test/OpenMP/teams_num_teams_messages.cpp | 60 +++++++++++++++++++
3 files changed, 108 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index d28b0a17afae1..4e5dcf0e2e1b2 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -5088,10 +5088,11 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
bool HasColon = false;
int Depth = 0;
- while (!Tok.is(tok::r_paren) && !Tok.is(tok::annot_pragma_openmp_end)) {
+ while (!Tok.is(tok::annot_pragma_openmp_end)) {
if (Tok.isOneOf(tok::l_paren, tok::l_square))
Depth++;
else if (Tok.isOneOf(tok::r_paren, tok::r_square)) {
+ // If depth is 0, this closing delimiter closes the num_teams clause
if (Depth == 0)
break;
Depth--;
diff --git a/clang/test/OpenMP/num_teams_clause_ast.cpp b/clang/test/OpenMP/num_teams_clause_ast.cpp
index 658320352c5cd..a1bcd96f56889 100644
--- a/clang/test/OpenMP/num_teams_clause_ast.cpp
+++ b/clang/test/OpenMP/num_teams_clause_ast.cpp
@@ -40,3 +40,49 @@ void test_various_directives() {
for (int i = 0; i < 100; ++i) { }
}
+// CHECK-LABEL: void test_nested_expressions()
+void test_nested_expressions() {
+ int arr[10][10];
+ int x = 5, y = 10;
+
+ // CHECK: #pragma omp teams num_teams(arr[0][0]:arr[1][1])
+ #pragma omp teams num_teams(arr[0][0]:arr[1][1])
+ { foo(); }
+
+ // CHECK: #pragma omp teams num_teams(arr[x][0]:arr[y][1])
+ #pragma omp teams num_teams(arr[x][0]:arr[y][1])
+ { foo(); }
+
+ // CHECK: #pragma omp teams num_teams((x + 1):(y - 1))
+ #pragma omp teams num_teams((x + 1):(y - 1))
+ { foo(); }
+
+}
+
+// CHECK-LABEL: void test_multi_level_matching_delimiters()
+void test_multi_level_matching_delimiters() {
+ int arr[10][10];
+ int x = 5, y = 10;
+
+ // CHECK: #pragma omp teams num_teams(((x + 1) * 2):((y - 1) * 3))
+ #pragma omp teams num_teams(((x + 1) * 2):((y - 1) * 3))
+ { foo(); }
+
+
+ // CHECK: #pragma omp teams num_teams(arr[arr[0][0]][0]:arr[arr[1][1]][1])
+ #pragma omp teams num_teams(arr[arr[0][0]][0]:arr[arr[1][1]][1])
+ { foo(); }
+
+ // CHECK: #pragma omp teams num_teams((arr[x][y] + 1):(arr[y][x] - 1))
+ #pragma omp teams num_teams((arr[x][y] + 1):(arr[y][x] - 1))
+ { foo(); }
+
+ // CHECK: #pragma omp teams num_teams((x + (y * 2)):((x * 2) + y))
+ #pragma omp teams num_teams((x + (y * 2)):((x * 2) + y))
+ { foo(); }
+
+ // CHECK: #pragma omp teams num_teams((arr[0][1] + arr[2][3]):(arr[4][5] + arr[6][7]))
+ #pragma omp teams num_teams((arr[0][1] + arr[2][3]):(arr[4][5] + arr[6][7]))
+ { foo(); }
+}
+
diff --git a/clang/test/OpenMP/teams_num_teams_messages.cpp b/clang/test/OpenMP/teams_num_teams_messages.cpp
index 5248cd0197f9a..6fb30af03dcb0 100644
--- a/clang/test/OpenMP/teams_num_teams_messages.cpp
+++ b/clang/test/OpenMP/teams_num_teams_messages.cpp
@@ -175,3 +175,63 @@ void test_invalid_syntax() {
#pragma omp target teams distribute simd num_teams(9:2)
for (int i = 0; i < 100; ++i) { }
}
+
+// Test non-matching parentheses and brackets
+void test_non_matching_delimiters() {
+ int arr[10];
+ int x = 5;
+
+ // expected-error at +4 {{expected ')'}}
+ // expected-error at +3 {{expected ')'}}
+ // expected-note at +2 {{to match this '('}}
+ // expected-note at +1 {{to match this '('}}
+ #pragma omp teams num_teams((x + 1:10)
+ { }
+
+ // expected-error at +2 {{expected ']'}}
+ // expected-note at +1 {{to match this '['}}
+ #pragma omp teams num_teams(arr[0:10)
+ { }
+
+ // expected-error at +2 {{expected ')'}}
+ // expected-note at +1 {{to match this '('}}
+ #pragma omp teams num_teams(x:((10 + 1))
+ { }
+}
+
+// Test multi-level non-matching parentheses and brackets
+void test_multi_level_non_matching_delimiters() {
+ int arr[10][10];
+ int x = 5, y = 10;
+
+ // expected-error at +4 {{expected ')'}}
+ // expected-note at +3 {{to match this '('}}
+ // expected-error at +2 {{expected ')'}}
+ // expected-note at +1 {{to match this '('}}
+ #pragma omp teams num_teams(((x + 1) * 2:10)
+ { }
+
+ // expected-error at +4 {{expected ')'}}
+ // expected-note at +3 {{to match this '('}}
+ // expected-error at +2 {{expected ')'}}
+ // expected-note at +1 {{to match this '('}}
+ #pragma omp teams num_teams((x + (y - 1):10)
+ { }
+
+ // expected-error at +2 {{expected ']'}}
+ // expected-note at +1 {{to match this '['}}
+ #pragma omp teams num_teams((arr[0 + 1):10)
+ { }
+
+ // expected-error at +2 {{expected ')'}}
+ // expected-note at +1 {{to match this '('}}
+ #pragma omp teams num_teams(x:((y + 1) * 2)
+ { }
+
+ // expected-error at +4 {{expected ']'}}
+ // expected-note at +3 {{to match this '['}}
+ // expected-error at +2 {{expected ']'}}
+ // expected-note at +1 {{to match this '['}}
+ #pragma omp teams num_teams(arr[0][1:arr[2][3)
+ { }
+}
>From 4bb43bc21fbf5b2ea3c60bf17597018b2c06c203 Mon Sep 17 00:00:00 2001
From: "Khatavkar, Yashasvi" <yashasvi.khatavkar at intel.com>
Date: Fri, 13 Feb 2026 12:49:59 -0800
Subject: [PATCH 9/9] Remove handling of token l_square
---
clang/lib/Parse/ParseOpenMP.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 4e5dcf0e2e1b2..03a347268998a 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -5089,10 +5089,10 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind,
int Depth = 0;
while (!Tok.is(tok::annot_pragma_openmp_end)) {
- if (Tok.isOneOf(tok::l_paren, tok::l_square))
+ if (Tok.is(tok::l_paren))
Depth++;
- else if (Tok.isOneOf(tok::r_paren, tok::r_square)) {
- // If depth is 0, this closing delimiter closes the num_teams clause
+ else if (Tok.is(tok::r_paren)) {
+ // If depth is 0, this closing paren closes the num_teams clause
if (Depth == 0)
break;
Depth--;
More information about the cfe-commits
mailing list