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" <[email protected]> Date: Mon, 9 Feb 2026 12:39:08 -0800 Subject: [PATCH 01/20] 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@+1 {{only two expression allowed in 'num_teams' clause}} + #pragma omp teams num_teams(a, b, c) + { } + // expected-error@+1 {{lower bound is greater than upper bound in 'num_teams' clause}} + #pragma omp teams num_teams(10:5) + { } + + // expected-error@+1 {{only two expression allowed in 'num_teams' clause}} + #pragma omp target teams num_teams(a, b, c) + { } + // expected-error@+1 {{lower bound is greater than upper bound in 'num_teams' clause}} + #pragma omp target teams num_teams(8:3) + { } + + // expected-error@+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@+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@+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@+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@+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@+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@+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@+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" <[email protected]> Date: Mon, 9 Feb 2026 12:46:31 -0800 Subject: [PATCH 02/20] 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" <[email protected]> Date: Tue, 10 Feb 2026 14:15:39 -0800 Subject: [PATCH 03/20] 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@+1 {{only two expression allowed in 'num_teams' clause}} - #pragma omp teams num_teams(a, b, c) - { } - // expected-error@+1 {{lower bound is greater than upper bound in 'num_teams' clause}} - #pragma omp teams num_teams(10:5) - { } - - // expected-error@+1 {{only two expression allowed in 'num_teams' clause}} - #pragma omp target teams num_teams(a, b, c) - { } - // expected-error@+1 {{lower bound is greater than upper bound in 'num_teams' clause}} - #pragma omp target teams num_teams(8:3) - { } - - // expected-error@+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@+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@+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@+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@+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@+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@+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@+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@+1 {{only two expression allowed in 'num_teams' clause}} + #pragma omp teams num_teams(a, b, c) + { } + // expected-error@+1 {{lower bound is greater than upper bound in 'num_teams' clause}} + #pragma omp teams num_teams(10:5) + { } + + // expected-error@+1 {{only two expression allowed in 'num_teams' clause}} + #pragma omp target teams num_teams(a, b, c) + { } + // expected-error@+1 {{lower bound is greater than upper bound in 'num_teams' clause}} + #pragma omp target teams num_teams(8:3) + { } + + // expected-error@+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@+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@+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@+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@+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@+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@+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@+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" <[email protected]> Date: Tue, 10 Feb 2026 14:33:36 -0800 Subject: [PATCH 04/20] 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" <[email protected]> Date: Wed, 11 Feb 2026 10:50:20 -0800 Subject: [PATCH 05/20] 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@+1 {{only two expression allowed in 'num_teams' clause}} + // expected-error@+1 {{only two expressions allowed in 'num_teams' clause}} #pragma omp teams num_teams(a, b, c) { } // expected-error@+1 {{lower bound is greater than upper bound in 'num_teams' clause}} #pragma omp teams num_teams(10:5) { } - // expected-error@+1 {{only two expression allowed in 'num_teams' clause}} + // expected-error@+1 {{only two expressions allowed in 'num_teams' clause}} #pragma omp target teams num_teams(a, b, c) { } // expected-error@+1 {{lower bound is greater than upper bound in 'num_teams' clause}} #pragma omp target teams num_teams(8:3) { } - // expected-error@+1 {{only two expression allowed in 'num_teams' clause}} + // expected-error@+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@+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@+1 {{only two expression allowed in 'num_teams' clause}} + // expected-error@+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@+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@+1 {{only two expression allowed in 'num_teams' clause}} + // expected-error@+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@+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@+1 {{only two expression allowed in 'num_teams' clause}} + // expected-error@+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@+1 {{lower bound is greater than upper bound in 'num_teams' clause}} >From 457ca18bf7adb853e1d12e79c1c2ec1461d5db3f Mon Sep 17 00:00:00 2001 From: "Khatavkar, Yashasvi" <[email protected]> Date: Thu, 12 Feb 2026 08:41:20 -0800 Subject: [PATCH 06/20] 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" <[email protected]> Date: Thu, 12 Feb 2026 08:46:53 -0800 Subject: [PATCH 07/20] 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" <[email protected]> Date: Fri, 13 Feb 2026 11:06:17 -0800 Subject: [PATCH 08/20] 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@+4 {{expected ')'}} + // expected-error@+3 {{expected ')'}} + // expected-note@+2 {{to match this '('}} + // expected-note@+1 {{to match this '('}} + #pragma omp teams num_teams((x + 1:10) + { } + + // expected-error@+2 {{expected ']'}} + // expected-note@+1 {{to match this '['}} + #pragma omp teams num_teams(arr[0:10) + { } + + // expected-error@+2 {{expected ')'}} + // expected-note@+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@+4 {{expected ')'}} + // expected-note@+3 {{to match this '('}} + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp teams num_teams(((x + 1) * 2:10) + { } + + // expected-error@+4 {{expected ')'}} + // expected-note@+3 {{to match this '('}} + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp teams num_teams((x + (y - 1):10) + { } + + // expected-error@+2 {{expected ']'}} + // expected-note@+1 {{to match this '['}} + #pragma omp teams num_teams((arr[0 + 1):10) + { } + + // expected-error@+2 {{expected ')'}} + // expected-note@+1 {{to match this '('}} + #pragma omp teams num_teams(x:((y + 1) * 2) + { } + + // expected-error@+4 {{expected ']'}} + // expected-note@+3 {{to match this '['}} + // expected-error@+2 {{expected ']'}} + // expected-note@+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" <[email protected]> Date: Fri, 13 Feb 2026 12:49:59 -0800 Subject: [PATCH 09/20] 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--; >From b3bfc63a6a1f2ca525a4ab2b65d9aff18218ca39 Mon Sep 17 00:00:00 2001 From: "Khatavkar, Yashasvi" <[email protected]> Date: Tue, 17 Feb 2026 13:04:26 -0800 Subject: [PATCH 10/20] Use BalancedDelimiterTracker to track parens --- clang/lib/Parse/ParseOpenMP.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 03a347268998a..0e7b5159e689d 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -5086,23 +5086,24 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, // Look ahead to detect top-level colon TentativeParsingAction TPA(*this); bool HasColon = false; - int Depth = 0; while (!Tok.is(tok::annot_pragma_openmp_end)) { - if (Tok.is(tok::l_paren)) - Depth++; - else if (Tok.is(tok::r_paren)) { - // If depth is 0, this closing paren closes the num_teams clause - 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) { + if (Tok.is(tok::l_paren)) { + BalancedDelimiterTracker ParenTracker(*this, tok::l_paren, + tok::annot_pragma_openmp_end); + if (ParenTracker.consumeOpen()) + break; // Error consuming paren + ParenTracker.skipToEnd(); + } else if (Tok.is(tok::colon)) { + // Top-level colon found - this is colon syntax HasColon = true; break; + } else if (Tok.isOneOf(tok::r_paren, tok::comma)) { + // End of expression without colon + break; + } else { + ConsumeAnyToken(); } - ConsumeAnyToken(); } TPA.Revert(); >From 43d5f421bc07dcf701f53b4290d1c33d34353796 Mon Sep 17 00:00:00 2001 From: "Khatavkar, Yashasvi" <[email protected]> Date: Tue, 17 Feb 2026 13:07:45 -0800 Subject: [PATCH 11/20] Fix formatting --- clang/lib/Parse/ParseOpenMP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 0e7b5159e689d..b0ecacfbefc4f 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -5102,7 +5102,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, // End of expression without colon break; } else { - ConsumeAnyToken(); + ConsumeAnyToken(); } } TPA.Revert(); >From 56e8c3d9ebdabb015db5107af9d456ab166d5bd2 Mon Sep 17 00:00:00 2001 From: "Khatavkar, Yashasvi" <[email protected]> Date: Tue, 17 Feb 2026 17:02:11 -0800 Subject: [PATCH 12/20] Remove look-ahead logic --- clang/lib/Parse/ParseOpenMP.cpp | 77 +++++++++++++++++---------------- 1 file changed, 39 insertions(+), 38 deletions(-) diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index b0ecacfbefc4f..eb94ce38b8fe4 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -5083,48 +5083,49 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, } // 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; - - while (!Tok.is(tok::annot_pragma_openmp_end)) { - if (Tok.is(tok::l_paren)) { - BalancedDelimiterTracker ParenTracker(*this, tok::l_paren, - tok::annot_pragma_openmp_end); - if (ParenTracker.consumeOpen()) - break; // Error consuming paren - ParenTracker.skipToEnd(); - } else if (Tok.is(tok::colon)) { - // Top-level colon found - this is colon syntax - HasColon = true; - break; - } else if (Tok.isOneOf(tok::r_paren, tok::comma)) { - // End of expression without colon - break; - } else { - ConsumeAnyToken(); - } + ExprResult FirstExpr = ParseAssignmentExpression(); + if (FirstExpr.isInvalid()) { + SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); + Data.RLoc = Tok.getLocation(); + if (!T.consumeClose()) + Data.RLoc = T.getCloseLocation(); + return false; } - 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 { + if (Tok.is(tok::colon)) { + // Lower-bound:upper-bound syntax + ConsumeToken(); + ExprResult UpperBound = ParseAssignmentExpression(); + if (UpperBound.isInvalid()) { SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); + } else { + Vars.push_back(FirstExpr.get()); // lower-bound + Vars.push_back(UpperBound.get()); // upper-bound } - + Data.RLoc = Tok.getLocation(); + if (!T.consumeClose()) + Data.RLoc = T.getCloseLocation(); + return false; + } else if (Tok.is(tok::comma)) { + Vars.push_back(FirstExpr.get()); + while (Tok.is(tok::comma)) { + ConsumeToken(); + ExprResult NextExpr = ParseAssignmentExpression(); + if (NextExpr.isUsable()) { + Vars.push_back(NextExpr.get()); + } else { + SkipUntil(tok::comma, tok::r_paren, tok::annot_pragma_openmp_end, + StopBeforeMatch); + break; + } + } + Data.RLoc = Tok.getLocation(); + if (!T.consumeClose()) + Data.RLoc = T.getCloseLocation(); + return false; + } else { + // Single value or error - parse closing paren + Vars.push_back(FirstExpr.get()); Data.RLoc = Tok.getLocation(); if (!T.consumeClose()) Data.RLoc = T.getCloseLocation(); >From 852dae21faa69ece906524635138f525e8a70d00 Mon Sep 17 00:00:00 2001 From: "Khatavkar, Yashasvi" <[email protected]> Date: Wed, 18 Feb 2026 07:45:08 -0800 Subject: [PATCH 13/20] Address review comment --- clang/lib/Parse/ParseOpenMP.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index eb94ce38b8fe4..926f913bde2e7 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -5123,14 +5123,13 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, if (!T.consumeClose()) Data.RLoc = T.getCloseLocation(); return false; - } else { - // Single value or error - parse closing paren - Vars.push_back(FirstExpr.get()); - Data.RLoc = Tok.getLocation(); - if (!T.consumeClose()) - Data.RLoc = T.getCloseLocation(); - return false; } + // Single value or error - parse closing paren + Vars.push_back(FirstExpr.get()); + Data.RLoc = Tok.getLocation(); + if (!T.consumeClose()) + Data.RLoc = T.getCloseLocation(); + return false; } bool IsComma = >From 1851436702846ef2100ddc2cab8903606fa282d2 Mon Sep 17 00:00:00 2001 From: "Khatavkar, Yashasvi" <[email protected]> Date: Wed, 18 Feb 2026 07:49:56 -0800 Subject: [PATCH 14/20] Apply clang-format --- clang/lib/Parse/ParseOpenMP.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 926f913bde2e7..482ad7cfa1844 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -5124,12 +5124,12 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, Data.RLoc = T.getCloseLocation(); return false; } - // Single value or error - parse closing paren + // Single value or error - parse closing paren Vars.push_back(FirstExpr.get()); Data.RLoc = Tok.getLocation(); if (!T.consumeClose()) Data.RLoc = T.getCloseLocation(); - return false; + return false; } bool IsComma = >From 94879120363e5726699bfa11fcb816dabdc6237b Mon Sep 17 00:00:00 2001 From: "Khatavkar, Yashasvi" <[email protected]> Date: Wed, 18 Feb 2026 13:29:01 -0800 Subject: [PATCH 15/20] Address review comments --- clang/lib/Parse/ParseOpenMP.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 482ad7cfa1844..506d435d99967 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -5089,7 +5089,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, Data.RLoc = Tok.getLocation(); if (!T.consumeClose()) Data.RLoc = T.getCloseLocation(); - return false; + return true; } if (Tok.is(tok::colon)) { @@ -5098,14 +5098,17 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, ExprResult UpperBound = ParseAssignmentExpression(); if (UpperBound.isInvalid()) { SkipUntil(tok::r_paren, tok::annot_pragma_openmp_end, StopBeforeMatch); - } else { - Vars.push_back(FirstExpr.get()); // lower-bound - Vars.push_back(UpperBound.get()); // upper-bound + Data.RLoc = Tok.getLocation(); + if (!T.consumeClose()) + Data.RLoc = T.getCloseLocation(); + return true; } + Vars.push_back(FirstExpr.get()); // lower-bound + Vars.push_back(UpperBound.get()); // upper-bound Data.RLoc = Tok.getLocation(); if (!T.consumeClose()) Data.RLoc = T.getCloseLocation(); - return false; + return false; //Success } else if (Tok.is(tok::comma)) { Vars.push_back(FirstExpr.get()); while (Tok.is(tok::comma)) { @@ -5120,16 +5123,18 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, } } Data.RLoc = Tok.getLocation(); - if (!T.consumeClose()) + bool HadError = T.consumeClose(); + if (!HadError) Data.RLoc = T.getCloseLocation(); - return false; + return HadError; } - // Single value or error - parse closing paren + + // Single value - parse closing paren Vars.push_back(FirstExpr.get()); Data.RLoc = Tok.getLocation(); if (!T.consumeClose()) Data.RLoc = T.getCloseLocation(); - return false; + return false; //Success } bool IsComma = >From def9b611abddb8ba7c3005b01bfbc6c5c77ccaf6 Mon Sep 17 00:00:00 2001 From: "Khatavkar, Yashasvi" <[email protected]> Date: Wed, 18 Feb 2026 13:33:58 -0800 Subject: [PATCH 16/20] Apply clang-format --- clang/lib/Parse/ParseOpenMP.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 506d435d99967..f5e231bc7d4da 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -5108,7 +5108,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, Data.RLoc = Tok.getLocation(); if (!T.consumeClose()) Data.RLoc = T.getCloseLocation(); - return false; //Success + return false; // Success } else if (Tok.is(tok::comma)) { Vars.push_back(FirstExpr.get()); while (Tok.is(tok::comma)) { @@ -5134,7 +5134,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, Data.RLoc = Tok.getLocation(); if (!T.consumeClose()) Data.RLoc = T.getCloseLocation(); - return false; //Success + return false; // Success } bool IsComma = >From 53213d25651b9cac2e5cb168eb84deb2f2e28b20 Mon Sep 17 00:00:00 2001 From: "Khatavkar, Yashasvi" <[email protected]> Date: Thu, 19 Feb 2026 06:40:34 -0800 Subject: [PATCH 17/20] Address review comment --- clang/lib/Parse/ParseOpenMP.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index f5e231bc7d4da..7c0605b40482e 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -5109,7 +5109,8 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, if (!T.consumeClose()) Data.RLoc = T.getCloseLocation(); return false; // Success - } else if (Tok.is(tok::comma)) { + } + if (Tok.is(tok::comma)) { Vars.push_back(FirstExpr.get()); while (Tok.is(tok::comma)) { ConsumeToken(); >From 4bfa6364a384250bdd5ba7ebb9b796d77a48f36f Mon Sep 17 00:00:00 2001 From: "Khatavkar, Yashasvi" <[email protected]> Date: Thu, 19 Feb 2026 06:43:38 -0800 Subject: [PATCH 18/20] Apply clang-format --- clang/lib/Parse/ParseOpenMP.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index 7c0605b40482e..0bb503484299d 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -5109,7 +5109,7 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind DKind, if (!T.consumeClose()) Data.RLoc = T.getCloseLocation(); return false; // Success - } + } if (Tok.is(tok::comma)) { Vars.push_back(FirstExpr.get()); while (Tok.is(tok::comma)) { >From cbb0d12b23228e2c5850302690ef3ece13f6ef86 Mon Sep 17 00:00:00 2001 From: "Khatavkar, Yashasvi" <[email protected]> Date: Thu, 19 Feb 2026 07:14:40 -0800 Subject: [PATCH 19/20] Update test case to include template and serialization/de-serialization --- clang/test/OpenMP/num_teams_clause_ast.cpp | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/clang/test/OpenMP/num_teams_clause_ast.cpp b/clang/test/OpenMP/num_teams_clause_ast.cpp index a1bcd96f56889..2ef9de51e7dfd 100644 --- a/clang/test/OpenMP/num_teams_clause_ast.cpp +++ b/clang/test/OpenMP/num_teams_clause_ast.cpp @@ -1,6 +1,11 @@ // RUN: %clang_cc1 -verify -fopenmp -ast-print %s | FileCheck %s +// RUN: %clang_cc1 -fopenmp -x c++ -std=c++11 -emit-pch -o %t %s +// RUN: %clang_cc1 -fopenmp -std=c++11 -include-pch %t -verify %s -ast-print | FileCheck %s // expected-no-diagnostics +#ifndef HEADER +#define HEADER + void foo(); // CHECK-LABEL: void test_lower_upper_bound() @@ -86,3 +91,13 @@ void test_multi_level_matching_delimiters() { { foo(); } } +// Template tests + +template<typename T> +void test_template_type(T lower, T upper) { + // CHECK: #pragma omp teams num_teams(lower:upper) + #pragma omp teams num_teams(lower:upper) + {} +} + +#endif >From 1fd8533dfb6b7080d16ece9269c98f845cf7c3b3 Mon Sep 17 00:00:00 2001 From: "Khatavkar, Yashasvi" <[email protected]> Date: Thu, 19 Feb 2026 07:35:48 -0800 Subject: [PATCH 20/20] add check-label --- clang/test/OpenMP/num_teams_clause_ast.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clang/test/OpenMP/num_teams_clause_ast.cpp b/clang/test/OpenMP/num_teams_clause_ast.cpp index 2ef9de51e7dfd..c7addd6387f59 100644 --- a/clang/test/OpenMP/num_teams_clause_ast.cpp +++ b/clang/test/OpenMP/num_teams_clause_ast.cpp @@ -92,7 +92,7 @@ void test_multi_level_matching_delimiters() { } // Template tests - +// CHECK-LABEL: template <typename T> void test_template_type(T lower, T upper) template<typename T> void test_template_type(T lower, T upper) { // CHECK: #pragma omp teams num_teams(lower:upper) _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
