Author: CHANDRA GHALE
Date: 2025-03-21T14:19:08+05:30
New Revision: 6da8f5661961416c704061a9d401ea6ae480cbc1

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

LOG: [OpenMP 6.0] Parse/Sema support for reduction over private variable with 
reduction clause. (#129938)

Initial Parse/Sema support for reduction over private variable with
reduction clause.
Section 7.6.10 in  in OpenMP 6.0 spec. 
- list item in a reduction clause can now be private in the enclosing
context.
-  Added support for _original-sharing-modifier_  with reduction clause.

---------

Co-authored-by: Chandra Ghale <gh...@pe31.hpc.amslabs.hpecorp.net>

Added: 
    

Modified: 
    clang/docs/OpenMPSupport.rst
    clang/include/clang/AST/OpenMPClause.h
    clang/include/clang/Basic/OpenMPKinds.def
    clang/include/clang/Basic/OpenMPKinds.h
    clang/include/clang/Sema/SemaOpenMP.h
    clang/lib/AST/OpenMPClause.cpp
    clang/lib/Parse/ParseOpenMP.cpp
    clang/lib/Sema/SemaOpenMP.cpp
    clang/lib/Sema/TreeTransform.h
    clang/lib/Serialization/ASTReader.cpp
    clang/lib/Serialization/ASTWriter.cpp
    clang/test/OpenMP/for_reduction_messages.cpp
    clang/test/OpenMP/for_simd_reduction_messages.cpp
    clang/test/OpenMP/parallel_for_reduction_messages.cpp
    clang/test/OpenMP/sections_reduction_messages.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/OpenMPSupport.rst b/clang/docs/OpenMPSupport.rst
index dcee1db2a18e0..83d90ffef6bc7 100644
--- a/clang/docs/OpenMPSupport.rst
+++ b/clang/docs/OpenMPSupport.rst
@@ -405,8 +405,8 @@ implementation.
 | Extensions to depobj construct                              | 
:none:`unclaimed`         | :none:`unclaimed`         |                         
                                                 |
 
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
 | Extensions to atomic construct                              | 
:none:`unclaimed`         | :none:`unclaimed`         |                         
                                                 |
-+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
-| Private reductions                                          | 
:none:`unclaimed`         | :none:`unclaimed`         |                         
                                                 |
++-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
 
+| Private reductions                                          | 
:part:`partial`           | :none:`unclaimed`         | 
Parse/Sema:https://github.com/llvm/llvm-project/pull/129938              |
 
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+
 | Self maps                                                   | 
:part:`partial`           | :none:`unclaimed`         | parsing/sema done: 
https://github.com/llvm/llvm-project/pull/129888      |
 
+-------------------------------------------------------------+---------------------------+---------------------------+--------------------------------------------------------------------------+

diff  --git a/clang/include/clang/AST/OpenMPClause.h 
b/clang/include/clang/AST/OpenMPClause.h
index 46f34a7302847..572e62249b46f 100644
--- a/clang/include/clang/AST/OpenMPClause.h
+++ b/clang/include/clang/AST/OpenMPClause.h
@@ -3701,7 +3701,7 @@ class OMPSharedClause final
 class OMPReductionClause final
     : public OMPVarListClause<OMPReductionClause>,
       public OMPClauseWithPostUpdate,
-      private llvm::TrailingObjects<OMPReductionClause, Expr *> {
+      private llvm::TrailingObjects<OMPReductionClause, Expr *, bool> {
   friend class OMPClauseReader;
   friend OMPVarListClause;
   friend TrailingObjects;
@@ -3709,6 +3709,10 @@ class OMPReductionClause final
   /// Reduction modifier.
   OpenMPReductionClauseModifier Modifier = OMPC_REDUCTION_unknown;
 
+  /// Original Sharing  modifier.
+  OpenMPOriginalSharingModifier OriginalSharingModifier =
+      OMPC_ORIGINAL_SHARING_default;
+
   /// Reduction modifier location.
   SourceLocation ModifierLoc;
 
@@ -3734,12 +3738,14 @@ class OMPReductionClause final
   OMPReductionClause(SourceLocation StartLoc, SourceLocation LParenLoc,
                      SourceLocation ModifierLoc, SourceLocation ColonLoc,
                      SourceLocation EndLoc,
-                     OpenMPReductionClauseModifier Modifier, unsigned N,
-                     NestedNameSpecifierLoc QualifierLoc,
+                     OpenMPReductionClauseModifier Modifier,
+                     OpenMPOriginalSharingModifier OriginalSharingModifier,
+                     unsigned N, NestedNameSpecifierLoc QualifierLoc,
                      const DeclarationNameInfo &NameInfo)
       : OMPVarListClause<OMPReductionClause>(llvm::omp::OMPC_reduction,
                                              StartLoc, LParenLoc, EndLoc, N),
         OMPClauseWithPostUpdate(this), Modifier(Modifier),
+        OriginalSharingModifier(OriginalSharingModifier),
         ModifierLoc(ModifierLoc), ColonLoc(ColonLoc),
         QualifierLoc(QualifierLoc), NameInfo(NameInfo) {}
 
@@ -3755,6 +3761,11 @@ class OMPReductionClause final
   /// Sets reduction modifier.
   void setModifier(OpenMPReductionClauseModifier M) { Modifier = M; }
 
+  /// Sets Original Sharing  modifier.
+  void setOriginalSharingModifier(OpenMPOriginalSharingModifier M) {
+    OriginalSharingModifier = M;
+  }
+
   /// Sets location of the modifier.
   void setModifierLoc(SourceLocation Loc) { ModifierLoc = Loc; }
 
@@ -3800,6 +3811,31 @@ class OMPReductionClause final
   /// reduction copies.
   void setRHSExprs(ArrayRef<Expr *> RHSExprs);
 
+  /// Set the list private reduction flags
+  void setPrivateVariableReductionFlags(ArrayRef<bool> Flags) {
+    assert(Flags.size() == varlist_size() &&
+           "Number of private flags does not match vars");
+    llvm::copy(Flags, getTrailingObjects<bool>());
+  }
+
+  /// Get the list of help private variable reduction flags
+  MutableArrayRef<bool> getPrivateVariableReductionFlags() {
+    return MutableArrayRef(getTrailingObjects<bool>(), varlist_size());
+  }
+  ArrayRef<bool> getPrivateVariableReductionFlags() const {
+    return ArrayRef(getTrailingObjects<bool>(), varlist_size());
+  }
+
+  /// Returns the number of Expr* objects in trailing storage
+  size_t numTrailingObjects(OverloadToken<Expr *>) const {
+    return varlist_size() * (Modifier == OMPC_REDUCTION_inscan ? 8 : 5);
+  }
+
+  /// Returns the number of bool flags in trailing storage
+  size_t numTrailingObjects(OverloadToken<bool>) const {
+    return varlist_size();
+  }
+
   /// Get the list of helper destination expressions.
   MutableArrayRef<Expr *> getRHSExprs() {
     return MutableArrayRef<Expr *>(getLHSExprs().end(), varlist_size());
@@ -3897,6 +3933,7 @@ class OMPReductionClause final
   /// region with this clause.
   /// \param PostUpdate Expression that must be executed after exit from the
   /// OpenMP region with this clause.
+  /// \param IsPrivateVarReduction array for private variable reduction flags
   static OMPReductionClause *
   Create(const ASTContext &C, SourceLocation StartLoc, SourceLocation 
LParenLoc,
          SourceLocation ModifierLoc, SourceLocation ColonLoc,
@@ -3906,7 +3943,8 @@ class OMPReductionClause final
          ArrayRef<Expr *> LHSExprs, ArrayRef<Expr *> RHSExprs,
          ArrayRef<Expr *> ReductionOps, ArrayRef<Expr *> CopyOps,
          ArrayRef<Expr *> CopyArrayTemps, ArrayRef<Expr *> CopyArrayElems,
-         Stmt *PreInit, Expr *PostUpdate);
+         Stmt *PreInit, Expr *PostUpdate, ArrayRef<bool> IsPrivateVarReduction,
+         OpenMPOriginalSharingModifier OriginalSharingModifier);
 
   /// Creates an empty clause with the place for \a N variables.
   ///
@@ -3920,6 +3958,11 @@ class OMPReductionClause final
   /// Returns modifier.
   OpenMPReductionClauseModifier getModifier() const { return Modifier; }
 
+  /// Returns Original Sharing Modifier.
+  OpenMPOriginalSharingModifier getOriginalSharingModifier() const {
+    return OriginalSharingModifier;
+  }
+
   /// Returns modifier location.
   SourceLocation getModifierLoc() const { return ModifierLoc; }
 
@@ -3937,6 +3980,11 @@ class OMPReductionClause final
   using helper_expr_range = llvm::iterator_range<helper_expr_iterator>;
   using helper_expr_const_range =
       llvm::iterator_range<helper_expr_const_iterator>;
+  using helper_flag_iterator = MutableArrayRef<bool>::iterator;
+  using helper_flag_const_iterator = ArrayRef<bool>::iterator;
+  using helper_flag_range = llvm::iterator_range<helper_flag_iterator>;
+  using helper_flag_const_range =
+      llvm::iterator_range<helper_flag_const_iterator>;
 
   helper_expr_const_range privates() const {
     return helper_expr_const_range(getPrivates().begin(), getPrivates().end());
@@ -3962,6 +4010,16 @@ class OMPReductionClause final
     return helper_expr_range(getRHSExprs().begin(), getRHSExprs().end());
   }
 
+  helper_flag_const_range private_var_reduction_flags() const {
+    return helper_flag_const_range(getPrivateVariableReductionFlags().begin(),
+                                   getPrivateVariableReductionFlags().end());
+  }
+
+  helper_flag_range private_var_reduction_flags() {
+    return helper_flag_range(getPrivateVariableReductionFlags().begin(),
+                             getPrivateVariableReductionFlags().end());
+  }
+
   helper_expr_const_range reduction_ops() const {
     return helper_expr_const_range(getReductionOps().begin(),
                                    getReductionOps().end());

diff  --git a/clang/include/clang/Basic/OpenMPKinds.def 
b/clang/include/clang/Basic/OpenMPKinds.def
index c4a2cca731607..b0de65df7e397 100644
--- a/clang/include/clang/Basic/OpenMPKinds.def
+++ b/clang/include/clang/Basic/OpenMPKinds.def
@@ -71,6 +71,9 @@
 #ifndef OPENMP_REDUCTION_MODIFIER
 #define OPENMP_REDUCTION_MODIFIER(Name)
 #endif
+#ifndef OPENMP_ORIGINAL_SHARING_MODIFIER
+#define OPENMP_ORIGINAL_SHARING_MODIFIER(Name)
+#endif
 #ifndef OPENMP_ADJUST_ARGS_KIND
 #define OPENMP_ADJUST_ARGS_KIND(Name)
 #endif
@@ -203,6 +206,11 @@ OPENMP_REDUCTION_MODIFIER(default)
 OPENMP_REDUCTION_MODIFIER(inscan)
 OPENMP_REDUCTION_MODIFIER(task)
 
+// OpenMP 6.0 modifiers for 'reduction' clause.
+OPENMP_ORIGINAL_SHARING_MODIFIER(shared)
+OPENMP_ORIGINAL_SHARING_MODIFIER(private)
+OPENMP_ORIGINAL_SHARING_MODIFIER(default)
+
 // Adjust-op kinds for the 'adjust_args' clause.
 OPENMP_ADJUST_ARGS_KIND(nothing)
 OPENMP_ADJUST_ARGS_KIND(need_device_ptr)
@@ -234,6 +242,7 @@ OPENMP_DOACROSS_MODIFIER(source_omp_cur_iteration)
 #undef OPENMP_ADJUST_ARGS_KIND
 #undef OPENMP_REDUCTION_MODIFIER
 #undef OPENMP_DEVICE_MODIFIER
+#undef OPENMP_ORIGINAL_SHARING_MODIFIER
 #undef OPENMP_ORDER_KIND
 #undef OPENMP_ORDER_MODIFIER
 #undef OPENMP_LASTPRIVATE_KIND

diff  --git a/clang/include/clang/Basic/OpenMPKinds.h 
b/clang/include/clang/Basic/OpenMPKinds.h
index e80bce34a97e0..6ca9f9c550285 100644
--- a/clang/include/clang/Basic/OpenMPKinds.h
+++ b/clang/include/clang/Basic/OpenMPKinds.h
@@ -190,6 +190,13 @@ enum OpenMPReductionClauseModifier {
   OMPC_REDUCTION_unknown,
 };
 
+/// OpenMP 6.0 original sharing modifiers
+enum OpenMPOriginalSharingModifier {
+#define OPENMP_ORIGINAL_SHARING_MODIFIER(Name) OMPC_ORIGINAL_SHARING_##Name,
+#include "clang/Basic/OpenMPKinds.def"
+  OMPC_ORIGINAL_SHARING_unknown,
+};
+
 /// OpenMP adjust-op kinds for 'adjust_args' clause.
 enum OpenMPAdjustArgsOpKind {
 #define OPENMP_ADJUST_ARGS_KIND(Name) OMPC_ADJUST_ARGS_##Name,

diff  --git a/clang/include/clang/Sema/SemaOpenMP.h 
b/clang/include/clang/Sema/SemaOpenMP.h
index 7fc9b64f0ae65..6498390fe96f7 100644
--- a/clang/include/clang/Sema/SemaOpenMP.h
+++ b/clang/include/clang/Sema/SemaOpenMP.h
@@ -1146,6 +1146,7 @@ class SemaOpenMP : public SemaBase {
     DeclarationNameInfo ReductionOrMapperId;
     int ExtraModifier = -1; ///< Additional modifier for linear, map, depend or
                             ///< lastprivate clause.
+    int OriginalSharingModifier = 0; // Default is shared
     SmallVector<OpenMPMapModifierKind, NumberOfOMPMapClauseModifiers>
         MapTypeModifiers;
     SmallVector<SourceLocation, NumberOfOMPMapClauseModifiers>
@@ -1155,6 +1156,7 @@ class SemaOpenMP : public SemaBase {
     SmallVector<SourceLocation, NumberOfOMPMotionModifiers> MotionModifiersLoc;
     bool IsMapTypeImplicit = false;
     SourceLocation ExtraModifierLoc;
+    SourceLocation OriginalSharingModifierLoc;
     SourceLocation OmpAllMemoryLoc;
     SourceLocation
         StepModifierLoc; /// 'step' modifier location for linear clause
@@ -1164,6 +1166,12 @@ class SemaOpenMP : public SemaBase {
     SmallVector<SourceLocation, NumberOfOMPAllocateClauseModifiers>
         AllocClauseModifiersLoc;
     Expr *AllocateAlignment = nullptr;
+    struct OpenMPReductionClauseModifiers {
+      int ExtraModifier;
+      int OriginalSharingModifier;
+      OpenMPReductionClauseModifiers(int Extra, int Original)
+          : ExtraModifier(Extra), OriginalSharingModifier(Original) {}
+    };
   };
 
   OMPClause *ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
@@ -1212,7 +1220,8 @@ class SemaOpenMP : public SemaBase {
                                      SourceLocation EndLoc);
   /// Called on well-formed 'reduction' clause.
   OMPClause *ActOnOpenMPReductionClause(
-      ArrayRef<Expr *> VarList, OpenMPReductionClauseModifier Modifier,
+      ArrayRef<Expr *> VarList,
+      OpenMPVarListDataTy::OpenMPReductionClauseModifiers Modifiers,
       SourceLocation StartLoc, SourceLocation LParenLoc,
       SourceLocation ModifierLoc, SourceLocation ColonLoc,
       SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec,

diff  --git a/clang/lib/AST/OpenMPClause.cpp b/clang/lib/AST/OpenMPClause.cpp
index 648a273c4a2c6..2226791a70b6e 100644
--- a/clang/lib/AST/OpenMPClause.cpp
+++ b/clang/lib/AST/OpenMPClause.cpp
@@ -799,12 +799,14 @@ OMPReductionClause *OMPReductionClause::Create(
     ArrayRef<Expr *> Privates, ArrayRef<Expr *> LHSExprs,
     ArrayRef<Expr *> RHSExprs, ArrayRef<Expr *> ReductionOps,
     ArrayRef<Expr *> CopyOps, ArrayRef<Expr *> CopyArrayTemps,
-    ArrayRef<Expr *> CopyArrayElems, Stmt *PreInit, Expr *PostUpdate) {
-  void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(
-      (Modifier == OMPC_REDUCTION_inscan ? 8 : 5) * VL.size()));
-  auto *Clause = new (Mem)
-      OMPReductionClause(StartLoc, LParenLoc, ModifierLoc, EndLoc, ColonLoc,
-                         Modifier, VL.size(), QualifierLoc, NameInfo);
+    ArrayRef<Expr *> CopyArrayElems, Stmt *PreInit, Expr *PostUpdate,
+    ArrayRef<bool> IsPrivateVarReduction,
+    OpenMPOriginalSharingModifier OrignalSharingModifier) {
+  void *Mem = C.Allocate(totalSizeToAlloc<Expr *, bool>(
+      (Modifier == OMPC_REDUCTION_inscan ? 8 : 5) * VL.size(), VL.size()));
+  auto *Clause = new (Mem) OMPReductionClause(
+      StartLoc, LParenLoc, ModifierLoc, EndLoc, ColonLoc, Modifier,
+      OrignalSharingModifier, VL.size(), QualifierLoc, NameInfo);
   Clause->setVarRefs(VL);
   Clause->setPrivates(Privates);
   Clause->setLHSExprs(LHSExprs);
@@ -812,6 +814,7 @@ OMPReductionClause *OMPReductionClause::Create(
   Clause->setReductionOps(ReductionOps);
   Clause->setPreInitStmt(PreInit);
   Clause->setPostUpdateExpr(PostUpdate);
+  Clause->setPrivateVariableReductionFlags(IsPrivateVarReduction);
   if (Modifier == OMPC_REDUCTION_inscan) {
     Clause->setInscanCopyOps(CopyOps);
     Clause->setInscanCopyArrayTemps(CopyArrayTemps);
@@ -830,8 +833,8 @@ OMPReductionClause *OMPReductionClause::Create(
 OMPReductionClause *
 OMPReductionClause::CreateEmpty(const ASTContext &C, unsigned N,
                                 OpenMPReductionClauseModifier Modifier) {
-  void *Mem = C.Allocate(totalSizeToAlloc<Expr *>(
-      (Modifier == OMPC_REDUCTION_inscan ? 8 : 5) * N));
+  void *Mem = C.Allocate(totalSizeToAlloc<Expr *, bool>(
+      (Modifier == OMPC_REDUCTION_inscan ? 8 : 5) * N, N));
   auto *Clause = new (Mem) OMPReductionClause(N);
   Clause->setModifier(Modifier);
   return Clause;

diff  --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp
index 28386d2260a83..b0e6c2f07a1e7 100644
--- a/clang/lib/Parse/ParseOpenMP.cpp
+++ b/clang/lib/Parse/ParseOpenMP.cpp
@@ -4706,6 +4706,37 @@ bool Parser::ParseOpenMPVarList(OpenMPDirectiveKind 
DKind,
       assert(Tok.is(tok::comma) && "Expected comma.");
       (void)ConsumeToken();
     }
+    // Handle original(private / shared) Modifier
+    if (Kind == OMPC_reduction && getLangOpts().OpenMP >= 60 &&
+        Tok.is(tok::identifier) && PP.getSpelling(Tok) == "original" &&
+        NextToken().is(tok::l_paren)) {
+      // Parse original(private) modifier.
+      ConsumeToken();
+      BalancedDelimiterTracker ParenT(*this, tok::l_paren, tok::r_paren);
+      ParenT.consumeOpen();
+      if (Tok.is(tok::kw_private)) {
+        Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_private;
+        Data.OriginalSharingModifierLoc = Tok.getLocation();
+        ConsumeToken();
+      } else if (Tok.is(tok::identifier) &&
+                 (PP.getSpelling(Tok) == "shared" ||
+                  PP.getSpelling(Tok) == "default")) {
+        Data.OriginalSharingModifier = OMPC_ORIGINAL_SHARING_shared;
+        Data.OriginalSharingModifierLoc = Tok.getLocation();
+        ConsumeToken();
+      } else {
+        Diag(Tok.getLocation(), diag::err_expected)
+            << "'private or shared or default'";
+        SkipUntil(tok::r_paren);
+        return false;
+      }
+      ParenT.consumeClose();
+      if (!Tok.is(tok::comma)) {
+        Diag(Tok.getLocation(), diag::err_expected) << "',' (comma)";
+        return false;
+      }
+      (void)ConsumeToken();
+    }
     ColonProtectionRAIIObject ColonRAII(*this);
     if (getLangOpts().CPlusPlus)
       ParseOptionalCXXScopeSpecifier(Data.ReductionOrMapperIdScopeSpec,

diff  --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 890de834533a4..a5f12a1e077c8 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -17377,6 +17377,7 @@ OMPClause 
*SemaOpenMP::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
   SourceLocation EndLoc = Locs.EndLoc;
   OMPClause *Res = nullptr;
   int ExtraModifier = Data.ExtraModifier;
+  int OriginalSharingModifier = Data.OriginalSharingModifier;
   SourceLocation ExtraModifierLoc = Data.ExtraModifierLoc;
   SourceLocation ColonLoc = Data.ColonLoc;
   switch (Kind) {
@@ -17400,7 +17401,9 @@ OMPClause 
*SemaOpenMP::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
     assert(0 <= ExtraModifier && ExtraModifier <= OMPC_REDUCTION_unknown &&
            "Unexpected lastprivate modifier.");
     Res = ActOnOpenMPReductionClause(
-        VarList, static_cast<OpenMPReductionClauseModifier>(ExtraModifier),
+        VarList,
+        OpenMPVarListDataTy::OpenMPReductionClauseModifiers(
+            ExtraModifier, OriginalSharingModifier),
         StartLoc, LParenLoc, ExtraModifierLoc, ColonLoc, EndLoc,
         Data.ReductionOrMapperIdScopeSpec, Data.ReductionOrMapperId);
     break;
@@ -18582,14 +18585,20 @@ struct ReductionData {
   SmallVector<Expr *, 4> ExprPostUpdates;
   /// Reduction modifier.
   unsigned RedModifier = 0;
+  /// Original modifier.
+  unsigned OrigSharingModifier = 0;
+  /// Private Variable Reduction
+  SmallVector<bool, 8> IsPrivateVarReduction;
   ReductionData() = delete;
   /// Reserves required memory for the reduction data.
-  ReductionData(unsigned Size, unsigned Modifier = 0) : RedModifier(Modifier) {
+  ReductionData(unsigned Size, unsigned Modifier = 0, unsigned OrgModifier = 0)
+      : RedModifier(Modifier), OrigSharingModifier(OrgModifier) {
     Vars.reserve(Size);
     Privates.reserve(Size);
     LHSs.reserve(Size);
     RHSs.reserve(Size);
     ReductionOps.reserve(Size);
+    IsPrivateVarReduction.reserve(Size);
     if (RedModifier == OMPC_REDUCTION_inscan) {
       InscanCopyOps.reserve(Size);
       InscanCopyArrayTemps.reserve(Size);
@@ -18607,6 +18616,7 @@ struct ReductionData {
     LHSs.emplace_back(nullptr);
     RHSs.emplace_back(nullptr);
     ReductionOps.emplace_back(ReductionOp);
+    IsPrivateVarReduction.emplace_back(false);
     TaskgroupDescriptors.emplace_back(nullptr);
     if (RedModifier == OMPC_REDUCTION_inscan) {
       InscanCopyOps.push_back(nullptr);
@@ -18617,7 +18627,7 @@ struct ReductionData {
   /// Stores reduction data.
   void push(Expr *Item, Expr *Private, Expr *LHS, Expr *RHS, Expr *ReductionOp,
             Expr *TaskgroupDescriptor, Expr *CopyOp, Expr *CopyArrayTemp,
-            Expr *CopyArrayElem) {
+            Expr *CopyArrayElem, bool IsPrivate) {
     Vars.emplace_back(Item);
     Privates.emplace_back(Private);
     LHSs.emplace_back(LHS);
@@ -18633,6 +18643,7 @@ struct ReductionData {
              CopyArrayElem == nullptr &&
              "Copy operation must be used for inscan reductions only.");
     }
+    IsPrivateVarReduction.emplace_back(IsPrivate);
   }
 };
 } // namespace
@@ -18846,6 +18857,7 @@ static bool actOnOMPReductionKindClause(
     FirstIter = false;
     SourceLocation ELoc;
     SourceRange ERange;
+    bool IsPrivate = false;
     Expr *SimpleRefExpr = RefExpr;
     auto Res = getPrivateItem(S, SimpleRefExpr, ELoc, ERange,
                               /*AllowArraySection=*/true);
@@ -18945,12 +18957,34 @@ static bool actOnOMPReductionKindClause(
         reportOriginalDsa(S, Stack, D, DVar);
         continue;
       }
+      // OpenMP 6.0 [ 7.6.10 ]
+      // Support Reduction over private variables with reduction clause.
+      // A list item in a reduction clause can now be private in the enclosing
+      // context. For orphaned constructs it is assumed to be shared unless the
+      // original(private) modifier appears in the clause.
+      DVar = Stack->getImplicitDSA(D, true);
+      bool IsOrphaned = false;
+      OpenMPDirectiveKind CurrDir = Stack->getCurrentDirective();
+      OpenMPDirectiveKind ParentDir = Stack->getParentDirective();
+      // Check if the construct is orphaned (has no enclosing OpenMP context)
+      IsOrphaned = ParentDir == OMPD_unknown;
+      // OpenMP 6.0: Private DSA check
+      IsPrivate =
+          (S.getLangOpts().OpenMP > 52) &&
+          ((isOpenMPPrivate(DVar.CKind) && DVar.CKind != OMPC_reduction &&
+            isOpenMPWorksharingDirective(CurrDir) &&
+            !isOpenMPParallelDirective(CurrDir) &&
+            !isOpenMPTeamsDirective(CurrDir) &&
+            !isOpenMPSimdDirective(ParentDir)) ||
+           (IsOrphaned && DVar.CKind == OMPC_unknown) ||
+           RD.OrigSharingModifier != OMPC_ORIGINAL_SHARING_shared);
 
       // OpenMP [2.14.3.6, Restrictions, p.1]
       //  A list item that appears in a reduction clause of a worksharing
       //  construct must be shared in the parallel regions to which any of the
       //  worksharing regions arising from the worksharing construct bind.
-      if (isOpenMPWorksharingDirective(CurrDir) &&
+
+      if (!IsPrivate && isOpenMPWorksharingDirective(CurrDir) &&
           !isOpenMPParallelDirective(CurrDir) &&
           !isOpenMPTeamsDirective(CurrDir)) {
         DVar = Stack->getImplicitDSA(D, true);
@@ -19446,17 +19480,23 @@ static bool actOnOMPReductionKindClause(
     }
     RD.push(VarsExpr, PrivateDRE, LHSDRE, RHSDRE, ReductionOp.get(),
             TaskgroupDescriptor, CopyOpRes.get(), TempArrayRes.get(),
-            TempArrayElem.get());
+            TempArrayElem.get(), IsPrivate);
   }
   return RD.Vars.empty();
 }
 
 OMPClause *SemaOpenMP::ActOnOpenMPReductionClause(
-    ArrayRef<Expr *> VarList, OpenMPReductionClauseModifier Modifier,
+    ArrayRef<Expr *> VarList,
+    OpenMPVarListDataTy::OpenMPReductionClauseModifiers Modifiers,
     SourceLocation StartLoc, SourceLocation LParenLoc,
     SourceLocation ModifierLoc, SourceLocation ColonLoc, SourceLocation EndLoc,
     CXXScopeSpec &ReductionIdScopeSpec, const DeclarationNameInfo &ReductionId,
     ArrayRef<Expr *> UnresolvedReductions) {
+  OpenMPReductionClauseModifier Modifier =
+      static_cast<OpenMPReductionClauseModifier>(Modifiers.ExtraModifier);
+  OpenMPOriginalSharingModifier OriginalSharingModifier =
+      static_cast<OpenMPOriginalSharingModifier>(
+          Modifiers.OriginalSharingModifier);
   if (ModifierLoc.isValid() && Modifier == OMPC_REDUCTION_unknown) {
     Diag(LParenLoc, diag::err_omp_unexpected_clause_value)
         << getListOfPossibleValues(OMPC_reduction, /*First=*/0,
@@ -19478,8 +19518,7 @@ OMPClause *SemaOpenMP::ActOnOpenMPReductionClause(
     Diag(ModifierLoc, diag::err_omp_wrong_inscan_reduction);
     return nullptr;
   }
-
-  ReductionData RD(VarList.size(), Modifier);
+  ReductionData RD(VarList.size(), Modifier, OriginalSharingModifier);
   if (actOnOMPReductionKindClause(SemaRef, DSAStack, OMPC_reduction, VarList,
                                   StartLoc, LParenLoc, ColonLoc, EndLoc,
                                   ReductionIdScopeSpec, ReductionId,
@@ -19493,7 +19532,8 @@ OMPClause *SemaOpenMP::ActOnOpenMPReductionClause(
       RD.Privates, RD.LHSs, RD.RHSs, RD.ReductionOps, RD.InscanCopyOps,
       RD.InscanCopyArrayTemps, RD.InscanCopyArrayElems,
       buildPreInits(getASTContext(), RD.ExprCaptures),
-      buildPostUpdate(SemaRef, RD.ExprPostUpdates));
+      buildPostUpdate(SemaRef, RD.ExprPostUpdates), RD.IsPrivateVarReduction,
+      OriginalSharingModifier);
 }
 
 OMPClause *SemaOpenMP::ActOnOpenMPTaskReductionClause(

diff  --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index b5de98e3989ea..f0d198618e912 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -1913,14 +1913,16 @@ class TreeTransform {
   /// Subclasses may override this routine to provide 
diff erent behavior.
   OMPClause *RebuildOMPReductionClause(
       ArrayRef<Expr *> VarList, OpenMPReductionClauseModifier Modifier,
+      OpenMPOriginalSharingModifier OriginalSharingModifier,
       SourceLocation StartLoc, SourceLocation LParenLoc,
       SourceLocation ModifierLoc, SourceLocation ColonLoc,
       SourceLocation EndLoc, CXXScopeSpec &ReductionIdScopeSpec,
       const DeclarationNameInfo &ReductionId,
       ArrayRef<Expr *> UnresolvedReductions) {
     return getSema().OpenMP().ActOnOpenMPReductionClause(
-        VarList, Modifier, StartLoc, LParenLoc, ModifierLoc, ColonLoc, EndLoc,
-        ReductionIdScopeSpec, ReductionId, UnresolvedReductions);
+        VarList, {Modifier, OriginalSharingModifier}, StartLoc, LParenLoc,
+        ModifierLoc, ColonLoc, EndLoc, ReductionIdScopeSpec, ReductionId,
+        UnresolvedReductions);
   }
 
   /// Build a new OpenMP 'task_reduction' clause.
@@ -10993,8 +10995,8 @@ 
TreeTransform<Derived>::TransformOMPReductionClause(OMPReductionClause *C) {
       UnresolvedReductions.push_back(nullptr);
   }
   return getDerived().RebuildOMPReductionClause(
-      Vars, C->getModifier(), C->getBeginLoc(), C->getLParenLoc(),
-      C->getModifierLoc(), C->getColonLoc(), C->getEndLoc(),
+      Vars, C->getModifier(), C->getOriginalSharingModifier(), 
C->getBeginLoc(),
+      C->getLParenLoc(), C->getModifierLoc(), C->getColonLoc(), C->getEndLoc(),
       ReductionIdScopeSpec, NameInfo, UnresolvedReductions);
 }
 

diff  --git a/clang/lib/Serialization/ASTReader.cpp 
b/clang/lib/Serialization/ASTReader.cpp
index 2b03446aaa30e..930134bcd6501 100644
--- a/clang/lib/Serialization/ASTReader.cpp
+++ b/clang/lib/Serialization/ASTReader.cpp
@@ -11758,6 +11758,12 @@ void 
OMPClauseReader::VisitOMPReductionClause(OMPReductionClause *C) {
       Vars.push_back(Record.readSubExpr());
     C->setInscanCopyArrayElems(Vars);
   }
+  unsigned NumFlags = Record.readInt();
+  SmallVector<bool, 16> Flags;
+  Flags.reserve(NumFlags);
+  for (unsigned I : llvm::seq<unsigned>(NumFlags))
+    Flags.push_back(Record.readInt());
+  C->setPrivateVariableReductionFlags(Flags);
 }
 
 void OMPClauseReader::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) {

diff  --git a/clang/lib/Serialization/ASTWriter.cpp 
b/clang/lib/Serialization/ASTWriter.cpp
index 9e6da4de680e2..436d5213c70dc 100644
--- a/clang/lib/Serialization/ASTWriter.cpp
+++ b/clang/lib/Serialization/ASTWriter.cpp
@@ -8019,6 +8019,10 @@ void 
OMPClauseWriter::VisitOMPReductionClause(OMPReductionClause *C) {
     for (auto *E : C->copy_array_elems())
       Record.AddStmt(E);
   }
+  auto PrivateFlags = C->private_var_reduction_flags();
+  Record.push_back(std::distance(PrivateFlags.begin(), PrivateFlags.end()));
+  for (bool Flag : PrivateFlags)
+    Record.push_back(Flag);
 }
 
 void OMPClauseWriter::VisitOMPTaskReductionClause(OMPTaskReductionClause *C) {

diff  --git a/clang/test/OpenMP/for_reduction_messages.cpp 
b/clang/test/OpenMP/for_reduction_messages.cpp
index 1ef9726205abb..de28ba2c3be02 100644
--- a/clang/test/OpenMP/for_reduction_messages.cpp
+++ b/clang/test/OpenMP/for_reduction_messages.cpp
@@ -237,6 +237,7 @@ T tmain(T argc) {
 #pragma omp for reduction(max : j) // expected-error 2 {{argument of OpenMP 
clause 'reduction' must reference the same object in all threads}}
   for (int i = 0; i < 10; ++i)
     foo();
+#if defined(_OPENMP) && (_OPENMP <= 202111)
 #pragma omp parallel private(fl)  // expected-note 2 {{defined as private}}
 #pragma omp for reduction(+ : fl) // expected-error 2 {{reduction variable 
must be shared}}
   for (int i = 0; i < 10; ++i)
@@ -253,7 +254,7 @@ T tmain(T argc) {
 #pragma omp for reduction(+ : fl)      // expected-error 2 {{reduction 
variable must be shared}}
   for (int i = 0; i < 10; ++i)
     foo();
-
+#endif
   return T();
 }
 
@@ -402,10 +403,12 @@ int main(int argc, char **argv) {
 #pragma omp for reduction(max : j) // expected-error {{argument of OpenMP 
clause 'reduction' must reference the same object in all threads}}
   for (int i = 0; i < 10; ++i)
     foo();
+#if defined(_OPENMP) && (_OPENMP <= 202111)
 #pragma omp parallel private(fl)  // expected-note {{defined as private}}
 #pragma omp for reduction(+ : fl) // expected-error {{reduction variable must 
be shared}}
   for (int i = 0; i < 10; ++i)
     foo();
+#endif
 #pragma omp parallel private(argv)
 #pragma omp for reduction(+ : argv[1], get()[0]) // expected-error {{expected 
variable name as a base of the array subscript}} expected-error {{invalid 
operands to binary expression ('char *' and 'char *')}}
   for (int i = 0; i < 10; ++i)

diff  --git a/clang/test/OpenMP/for_simd_reduction_messages.cpp 
b/clang/test/OpenMP/for_simd_reduction_messages.cpp
index 2550cf481265f..96b3805b10a86 100644
--- a/clang/test/OpenMP/for_simd_reduction_messages.cpp
+++ b/clang/test/OpenMP/for_simd_reduction_messages.cpp
@@ -236,6 +236,7 @@ T tmain(T argc) {
 #pragma omp for simd reduction(max : j) // expected-error 2 {{argument of 
OpenMP clause 'reduction' must reference the same object in all threads}}
   for (int i = 0; i < 10; ++i)
     foo();
+#if defined(_OPENMP) && (_OPENMP <= 202111)
 #pragma omp parallel private(fl)  // expected-note 2 {{defined as private}}
 #pragma omp for simd reduction(+ : fl) // expected-error 2 {{reduction 
variable must be shared}}
   for (int i = 0; i < 10; ++i)
@@ -244,6 +245,7 @@ T tmain(T argc) {
 #pragma omp for simd reduction(+ : fl)      // expected-error 2 {{reduction 
variable must be shared}}
   for (int i = 0; i < 10; ++i)
     foo();
+#endif
 
   return T();
 }
@@ -389,10 +391,12 @@ int main(int argc, char **argv) {
 #pragma omp for simd reduction(max : j) // expected-error {{argument of OpenMP 
clause 'reduction' must reference the same object in all threads}}
   for (int i = 0; i < 10; ++i)
     foo();
+#if defined(_OPENMP) && (_OPENMP <= 202111)
 #pragma omp parallel private(fl)  // expected-note {{defined as private}}
 #pragma omp for simd reduction(+ : fl) // expected-error {{reduction variable 
must be shared}}
   for (int i = 0; i < 10; ++i)
     foo();
+#endif
 #pragma omp parallel reduction(* : fl) // expected-note {{defined as 
reduction}}
 #pragma omp for simd reduction(+ : fl)      // expected-error {{reduction 
variable must be shared}}
   for (int i = 0; i < 10; ++i)

diff  --git a/clang/test/OpenMP/parallel_for_reduction_messages.cpp 
b/clang/test/OpenMP/parallel_for_reduction_messages.cpp
index d4660ae43acf8..60742e5aa6b1d 100644
--- a/clang/test/OpenMP/parallel_for_reduction_messages.cpp
+++ b/clang/test/OpenMP/parallel_for_reduction_messages.cpp
@@ -89,10 +89,12 @@ class S5 {
 public:
   S5(int v) : a(v) {}
   void foo() {
+#if defined(_OPENMP) && (_OPENMP <= 202111)
 #pragma omp parallel private(a) // expected-note {{defined as private}}
 #pragma omp for reduction(+:a) // expected-error {{reduction variable must be 
shared}}
   for (int i = 0; i < 10; ++i)
     ::foo();
+#endif
 #pragma omp parallel for reduction(inscan, +:a)
   for (int i = 0; i < 10; ++i) {
 #pragma omp scan inclusive(a)
@@ -226,9 +228,96 @@ T tmain(T argc) {
 #pragma omp parallel for reduction(+ : fl)
   for (int i = 0; i < 10; ++i)
     foo();
-
+#if defined(_OPENMP) && (_OPENMP >= 202411)
+#pragma omp parallel private(fl)
+#pragma omp for reduction(original(abcxx),+:fl) // expected-error {{private or 
shared or default}} expected-warning {{extra tokens at the end of '#pragma omp 
for'}} 
+for (int i = 1; i <= 10; i++) 
+  foo();
+#endif
   return T();
 }
+namespace private_reduction_test{
+void test_original_modifier(){
+int fl;
+#if defined(_OPENMP) && (_OPENMP >= 202411)
+#pragma omp parallel private(fl)
+#pragma omp for reduction(original(privates),+:fl) // expected-error {{private 
or shared or default}} expected-warning {{extra tokens at the end of '#pragma 
omp for'}}
+for (int i = 1; i <= 10; i++)
+  ;
+
+#pragma omp parallel for reduction(original(private)+ : fl) // expected-error 
{{expected ',' (comma)}} expected-warning {{extra tokens at the end of '#pragma 
omp parallel for' }}
+for (int i = 0; i < 10; ++i)
+    ;
+
+#pragma omp parallel 
+#pragma omp for reduction(original(shared),+:fl) 
+for( int i = 0; i < 10; i++)
+;
+#pragma omp parallel for reduction(original(private),+: fl // expected-error 
{{expected ')'}} expected-note {{to match this '('}}
+for (int i = 0; i < 10; ++i)
+    ;
+#pragma omp parallel firstprivate(fl)
+#pragma omp for reduction(+:fl) 
+for( int i = 0; i < 10; i++)
+;
+
+#pragma omp parallel 
+#pragma omp for reduction(original(private),+:fl) 
+for( int i = 0; i < 10; i++)
+;
+
+#endif
+}
+void test_interaction(){
+int x;
+#if defined(_OPENMP) && (_OPENMP >= 202411)
+#pragma omp parallel private(x)
+#pragma omp for reduction(original(private),+:x) nowait 
+for (int i = 0; i < 10; ++i)
+  x += 1;
+#pragma omp parallel
+{
+#pragma omp for reduction(original(private),+:) // expected-error {{expected 
expression}}
+for( int i = 0; i < 10; ++i)
+;
+}
+#pragma omp parallel private(x)
+#pragma omp for reduction(original(private),+:x) ordered
+for (int i = 0; i < 10; ++i)
+  x += 1;
+#endif
+ }
+template<typename T>
+void test_template_reduction() {
+  T x = T();
+#if defined(_OPENMP) && (_OPENMP >= 202411)  
+  #pragma omp parallel private(x)
+  {
+    #pragma omp for reduction(original(private),+:x) 
+    for (int i = 0; i < 10; ++i) {
+      x += T(1);
+    }
+  }
+#endif
+}
+struct Custom {
+  int value;
+  Custom() : value(0) {}
+  Custom& operator+=(const Custom& other) {
+    value += other.value;
+    return *this;
+  }
+};
+void test_user_defined_type() {
+  Custom c;
+#if defined(_OPENMP) && (_OPENMP >= 202411)  
+  #pragma omp parallel private(c)
+  #pragma omp for reduction(original(private),+:c)
+    for (int i = 0; i < 10; ++i)
+      c.value += 1;
+#endif
+ }
+}
 
 namespace A {
 double x;

diff  --git a/clang/test/OpenMP/sections_reduction_messages.cpp 
b/clang/test/OpenMP/sections_reduction_messages.cpp
index f93b4dd016308..42ec3ed6d58e8 100644
--- a/clang/test/OpenMP/sections_reduction_messages.cpp
+++ b/clang/test/OpenMP/sections_reduction_messages.cpp
@@ -268,6 +268,7 @@ T tmain(T argc) {
   {
     foo();
   }
+#if defined(_OPENMP) && (_OPENMP <= 202111)
 #pragma omp parallel private(fl)       // expected-note 2 {{defined as 
private}}
 #pragma omp sections reduction(+ : fl) // expected-error 2 {{reduction 
variable must be shared}}
   {
@@ -278,6 +279,7 @@ T tmain(T argc) {
   {
     foo();
   }
+#endif
 
   return T();
 }
@@ -453,11 +455,13 @@ int main(int argc, char **argv) {
   {
     foo();
   }
+#if defined(_OPENMP) && (_OPENMP <= 202111)
 #pragma omp parallel private(fl)       // expected-note {{defined as private}}
 #pragma omp sections reduction(+ : fl) // expected-error {{reduction variable 
must be shared}}
   {
     foo();
   }
+#endif
 #pragma omp parallel reduction(* : fl) // expected-note {{defined as 
reduction}}
 #pragma omp sections reduction(+ : fl) // expected-error {{reduction variable 
must be shared}}
   {


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to