[clang] cac3894 - [OpenMP 5.2] New syntax for 'uses_allocators' clause (#157025)

via cfe-commits cfe-commits at lists.llvm.org
Thu Sep 18 01:12:11 PDT 2025


Author: Urvi Rav
Date: 2025-09-18T13:42:06+05:30
New Revision: cac389405455659a150caf2402d1541d7009cab0

URL: https://github.com/llvm/llvm-project/commit/cac389405455659a150caf2402d1541d7009cab0
DIFF: https://github.com/llvm/llvm-project/commit/cac389405455659a150caf2402d1541d7009cab0.diff

LOG: [OpenMP 5.2] New syntax for 'uses_allocators' clause (#157025)

This patch updates the parsing changes to handle the new syntax of the
`uses_allocators` clause as defined in OpenMP 5.2(Section 6.8).

```
// Case 1: Allocator without traits
// < 5.2 → error
// ≥ 5.2 → OK, empty traits set
#pragma omp target teams uses_allocators(cgroup_alloc)

// Case 2: Allocator with traits
// Old syntax (< 5.2):
#pragma omp target teams uses_allocators(cgroup_alloc(cgroup_traits))
// New syntax (≥ 5.2):
#pragma omp target teams uses_allocators(traits(cgroup_traits) : cgroup_alloc)

// Case 3: Multiple allocators
// Old syntax (< 5.2), comma-separated:
#pragma omp target teams uses_allocators(cgroup_alloc(cgroup_traits), aligned_alloc(aligned_traits))
// New syntax (≥ 5.2), semicolon-separated:
#pragma omp target teams uses_allocators(traits(cgroup_traits) : cgroup_alloc; traits(aligned_traits) : aligned_alloc) 
```

---------

Co-authored-by: urvi-rav <urvi.rav at hpe.com>

Added: 
    

Modified: 
    clang/docs/OpenMPSupport.rst
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticParseKinds.td
    clang/lib/Parse/ParseOpenMP.cpp
    clang/lib/Sema/SemaOpenMP.cpp
    clang/test/OpenMP/target_uses_allocators_messages.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst
index 8a627d1f0b92d..c92686b05a238 100644
--- a/clang/docs/OpenMPSupport.rst
+++ b/clang/docs/OpenMPSupport.rst
@@ -153,7 +153,7 @@ implementation.
 +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
 | device                       | clause: extended device                                      | :good:`done`             |                                                                       |
 +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
-| device                       | clause: uses_allocators clause                               | :good:`done`             |                                                                       |
+| device                       | clause: uses_allocators clause                               | :good:`done`             | https://github.com/llvm/llvm-project/pull/157025                      |
 +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+
 | device                       | clause: in_reduction                                         | :part:`worked on`        | r308768                                                               |
 +------------------------------+--------------------------------------------------------------+--------------------------+-----------------------------------------------------------------------+

diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 60dd2b4c0c6ef..2bb2f7537ddd3 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -562,6 +562,7 @@ OpenMP Support
 - Allow array length to be omitted in array section subscript expression.
 - Fixed non-contiguous strided update in the ``omp target update`` directive with the ``from`` clause.
 - Properly handle array section/assumed-size array privatization in C/C++.
+- Added support to handle new syntax of the ``uses_allocators`` clause.
 - Added support for ``variable-category`` modifier in ``default clause``.
 - Added support for ``defaultmap`` directive implicit-behavior ``storage``.
 - Added support for ``defaultmap`` directive implicit-behavior ``private``.

diff  --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index 968a7c5b0dc8e..4d9e123eb4ef1 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -1497,6 +1497,8 @@ def err_omp_multiple_step_or_linear_modifier : Error<
   "multiple %select{'step size'|'linear modifier'}0 found in linear clause">;
 def err_omp_deprecate_old_syntax: Error<
   "old syntax '%0' on '%1' clause was deprecated, use new syntax '%2'">;
+def err_omp_allocator_comma_separator :
+  Error<"',' not allowed as separator in 'uses_allocators' clause, use ';' instead">;
 def warn_omp_future_directive_spelling: Warning<
   "directive spelling '%0' is introduced in a later OpenMP version">,
   InGroup<OpenMPFuture>;

diff  --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 7dceb2d208352..aba0066dc42e1 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -2959,6 +2959,73 @@ OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
     return nullptr;
   SmallVector<SemaOpenMP::UsesAllocatorsData, 4> Data;
   do {
+    // Parse 'traits(expr) : Allocator' for >=5.2
+    if (getLangOpts().OpenMP >= 52 && Tok.is(tok::identifier) &&
+        Tok.getIdentifierInfo()->getName() == "traits") {
+
+      SemaOpenMP::UsesAllocatorsData &D = Data.emplace_back();
+
+      ConsumeToken();
+
+      // Parse '(' <expr> ')'
+      BalancedDelimiterTracker TraitParens(*this, tok::l_paren,
+                                           tok::annot_pragma_openmp_end);
+      TraitParens.consumeOpen();
+      ExprResult AllocatorTraits =
+          getLangOpts().CPlusPlus ? ParseCXXIdExpression() : ParseExpression();
+      TraitParens.consumeClose();
+
+      if (AllocatorTraits.isInvalid()) {
+        SkipUntil(
+            {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},
+            StopBeforeMatch);
+        break;
+      }
+
+      // Expect ':'
+      if (Tok.isNot(tok::colon)) {
+        Diag(Tok, diag::err_expected) << tok::colon;
+        SkipUntil(
+            {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},
+            StopBeforeMatch);
+        continue;
+      }
+      ConsumeToken();
+
+      CXXScopeSpec SS;
+      Token Replacement;
+      ExprResult AllocatorExpr =
+          getLangOpts().CPlusPlus
+              ? ParseCXXIdExpression()
+              : tryParseCXXIdExpression(SS, /*isAddressOfOperand=*/false,
+                                        Replacement);
+
+      if (AllocatorExpr.isInvalid()) {
+        SkipUntil(
+            {tok::comma, tok::semi, tok::r_paren, tok::annot_pragma_openmp_end},
+            StopBeforeMatch);
+        break;
+      }
+
+      D.Allocator = AllocatorExpr.get();
+      D.AllocatorTraits = AllocatorTraits.get();
+      D.LParenLoc = TraitParens.getOpenLocation();
+      D.RParenLoc = TraitParens.getCloseLocation();
+
+      // Separator handling(;)
+      if (Tok.is(tok::comma)) {
+        // In 5.2, comma is invalid
+        Diag(Tok.getLocation(), diag::err_omp_allocator_comma_separator)
+            << FixItHint::CreateReplacement(Tok.getLocation(), ";");
+        ConsumeAnyToken();
+      } else if (Tok.is(tok::semi)) {
+        ConsumeAnyToken(); // valid separator
+      }
+
+      continue;
+    }
+
+    // Parse 'Allocator(expr)' for <5.2
     CXXScopeSpec SS;
     Token Replacement;
     ExprResult Allocator =
@@ -2988,6 +3055,14 @@ OMPClause *Parser::ParseOpenMPUsesAllocatorClause(OpenMPDirectiveKind DKind) {
       D.AllocatorTraits = AllocatorTraits.get();
       D.LParenLoc = T.getOpenLocation();
       D.RParenLoc = T.getCloseLocation();
+
+      // Deprecation diagnostic in >= 5.2
+      if (getLangOpts().OpenMP >= 52) {
+        Diag(Loc, diag::err_omp_deprecate_old_syntax)
+            << "allocator(expr)"      // %0: old form
+            << "uses_allocators"      // %1: clause name
+            << "traits(expr): alloc"; // %2: suggested new form
+      }
     }
     if (Tok.isNot(tok::comma) && Tok.isNot(tok::r_paren))
       Diag(Tok, diag::err_omp_expected_punc) << "uses_allocators" << 0;

diff  --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 6a7a5a9a4303a..b767767b07673 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -24184,10 +24184,12 @@ OMPClause *SemaOpenMP::ActOnOpenMPUsesAllocatorClause(
       // OpenMP [2.12.5, target Construct]
       // Non-predefined allocators appearing in a uses_allocators clause must
       // have traits specified.
-      if (!IsPredefinedAllocator && !D.AllocatorTraits) {
-        Diag(D.Allocator->getExprLoc(),
-             diag::err_omp_nonpredefined_allocator_without_traits);
-        continue;
+      if (getLangOpts().OpenMP < 52) {
+        if (!IsPredefinedAllocator && !D.AllocatorTraits) {
+          Diag(D.Allocator->getExprLoc(),
+               diag::err_omp_nonpredefined_allocator_without_traits);
+          continue;
+        }
       }
       // No allocator traits - just convert it to rvalue.
       if (!D.AllocatorTraits)

diff  --git a/clang/test/OpenMP/target_uses_allocators_messages.cpp b/clang/test/OpenMP/target_uses_allocators_messages.cpp
index b145c4d9501cf..538ee6b798df4 100644
--- a/clang/test/OpenMP/target_uses_allocators_messages.cpp
+++ b/clang/test/OpenMP/target_uses_allocators_messages.cpp
@@ -2,6 +2,10 @@
 
 // RUN: %clang_cc1 -verify -fopenmp-simd %s -Wuninitialized
 
+// RUN: %clang_cc1 -DOMP52 -verify=omp52 -fopenmp -fopenmp-version=52 %s -Wuninitialized
+
+// RUN: %clang_cc1 -DOMP52 -verify=omp52 -fopenmp-simd  -fopenmp-version=52 %s -Wuninitialized
+
 struct omp_alloctrait_t {};
 
 typedef void **omp_allocator_handle_t;
@@ -16,10 +20,15 @@ extern const omp_allocator_handle_t omp_pteam_mem_alloc;
 extern const omp_allocator_handle_t omp_thread_mem_alloc;
 
 int main(int argc, char **argv) {
-  omp_alloctrait_t traits[10];
+  omp_alloctrait_t my_traits[10];
   omp_alloctrait_t *ptraits;
   omp_allocator_handle_t my_alloc = nullptr;
   const omp_allocator_handle_t c_my_alloc = my_alloc;
+  omp_alloctrait_t aligned_traits[10];
+  omp_allocator_handle_t aligned_alloc;
+
+#ifndef OMP52
+
 #pragma omp target uses_allocators // expected-error {{expected '(' after 'uses_allocator'}}
 {}
 #pragma omp target uses_allocators( // expected-error {{expected ')'}} expected-note {{to match this '('}} expected-error {{expected unqualified-id}}
@@ -34,7 +43,7 @@ int main(int argc, char **argv) {
 {}
 #pragma omp target uses_allocators(omp_default_mem_alloc, omp_large_cap_mem_alloc, omp_const_mem_alloc, omp_high_bw_mem_alloc, omp_low_lat_mem_alloc, omp_cgroup_mem_alloc, omp_pteam_mem_alloc, omp_thread_mem_alloc)
 {}
-#pragma omp target uses_allocators(omp_default_mem_alloc(traits), omp_large_cap_mem_alloc(traits), omp_const_mem_alloc(traits), omp_high_bw_mem_alloc(traits), omp_low_lat_mem_alloc(traits), omp_cgroup_mem_alloc(traits), omp_pteam_mem_alloc(traits), omp_thread_mem_alloc(traits)) // expected-error 8 {{predefined allocator cannot have traits specified}} expected-note-re 8 {{predefined trait '{{omp_default_mem_alloc|omp_large_cap_mem_alloc|omp_const_mem_alloc|omp_high_bw_mem_alloc|omp_low_lat_mem_alloc|omp_cgroup_mem_alloc|omp_pteam_mem_alloc|omp_thread_mem_alloc}}' used here}}
+#pragma omp target uses_allocators(omp_default_mem_alloc(my_traits), omp_large_cap_mem_alloc(my_traits), omp_const_mem_alloc(my_traits), omp_high_bw_mem_alloc(my_traits), omp_low_lat_mem_alloc(my_traits), omp_cgroup_mem_alloc(my_traits), omp_pteam_mem_alloc(my_traits), omp_thread_mem_alloc(my_traits)) // expected-error 8 {{predefined allocator cannot have traits specified}} expected-note-re 8 {{predefined trait '{{omp_default_mem_alloc|omp_large_cap_mem_alloc|omp_const_mem_alloc|omp_high_bw_mem_alloc|omp_low_lat_mem_alloc|omp_cgroup_mem_alloc|omp_pteam_mem_alloc|omp_thread_mem_alloc}}' used here}}
 {}
 #pragma omp target uses_allocators(my_alloc, c_my_alloc) // expected-error {{non-predefined allocator must have traits specified}} expected-error {{expected variable of the 'omp_allocator_handle_t' type, not 'const omp_allocator_handle_t' (aka 'void **const')}}
 {}
@@ -46,10 +55,20 @@ int main(int argc, char **argv) {
 {}
 #pragma omp target uses_allocators(my_alloc(ptraits)) // expected-error {{expected constant sized array of 'omp_alloctrait_t' elements, not 'omp_alloctrait_t *'}}
 {}
-#pragma omp target uses_allocators(my_alloc(traits)) private(my_alloc) // expected-error {{allocators used in 'uses_allocators' clause cannot appear in other data-sharing or data-mapping attribute clauses}} expected-note {{defined as private}}
+#pragma omp target uses_allocators(my_alloc(my_traits)) private(my_alloc) // expected-error {{allocators used in 'uses_allocators' clause cannot appear in other data-sharing or data-mapping attribute clauses}} expected-note {{defined as private}}
+{}
+#pragma omp target map(my_alloc, my_traits) uses_allocators(my_alloc(my_traits)) // expected-error {{allocators used in 'uses_allocators' clause cannot appear in other data-sharing or data-mapping attribute clauses}} expected-note {{used here}}
+{}
+#else
+#pragma omp target teams uses_allocators(traits(my_traits): my_alloc; traits(aligned_traits): aligned_alloc)
+{}
+#pragma omp target teams uses_allocators(my_alloc)
+{}
+#pragma omp target teams uses_allocators(traits(my_traits): my_alloc, traits(aligned_traits): aligned_alloc) // omp52-error {{',' not allowed as separator in 'uses_allocators' clause, use ';' instead}}
 {}
-#pragma omp target map(my_alloc, traits) uses_allocators(my_alloc(traits)) // expected-error {{allocators used in 'uses_allocators' clause cannot appear in other data-sharing or data-mapping attribute clauses}} expected-note {{used here}}
+#pragma omp target teams uses_allocators(my_alloc(my_traits), aligned_alloc(aligned_traits)) // omp52-error {{old syntax 'allocator(expr)' on 'uses_allocators' clause was deprecated, use new syntax 'traits(expr): alloc'}} //omp52-error {{old syntax 'allocator(expr)' on 'uses_allocators' clause was deprecated, use new syntax 'traits(expr): alloc'}}
 {}
+#endif
   return 0;
 }
 


        


More information about the cfe-commits mailing list