[flang-commits] [flang] [llvm] [Flang][OpenMP] Implement variable-category for default clause (OMP 6.0) (PR #223476)

via flang-commits flang-commits at lists.llvm.org
Mon Sep 14 10:53:29 PDT 2026


llvmorg-github-actions[bot] wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-fir-hlfir

Author: Phoebe Linck (phi-bee)

<details>
<summary>Changes</summary>

Implements the `variable-category` modifier for the `default` clause, a feature introduced in OpenMP 6.0.

---

Patch is 25.02 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/223476.diff


14 Files Affected:

- (modified) flang/include/flang/Parser/dump-parse-tree.h (+1) 
- (modified) flang/include/flang/Parser/parse-tree.h (+4-2) 
- (modified) flang/include/flang/Semantics/openmp-utils.h (+8) 
- (modified) flang/lib/Lower/OpenMP/Clauses.cpp (+19-2) 
- (modified) flang/lib/Lower/OpenMP/DataSharingProcessor.cpp (+62-5) 
- (modified) flang/lib/Parser/openmp-parsers.cpp (+5-1) 
- (modified) flang/lib/Semantics/check-omp-structure.cpp (+21) 
- (modified) flang/lib/Semantics/check-omp-structure.h (+1) 
- (modified) flang/lib/Semantics/check-omp-variant.cpp (+2-1) 
- (modified) flang/lib/Semantics/openmp-utils.cpp (+61) 
- (modified) flang/lib/Semantics/resolve-directives.cpp (+47-81) 
- (added) flang/test/Semantics/OpenMP/default-category.f90 (+14) 
- (added) flang/test/Semantics/OpenMP/default-none-category.f90 (+53) 
- (modified) llvm/include/llvm/Frontend/OpenMP/ClauseT.h (+3-2) 


``````````diff
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 3b4d467f143455..2758ea64d4306b 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -602,6 +602,7 @@ class ParseTreeDumper {
   NODE(parser, OmpDeclareVariantDirective)
   NODE(parser, OmpDefaultClause)
   NODE_ENUM(OmpDefaultClause, DataSharingAttribute)
+  NODE(OmpDefaultClause, Modifier)
   NODE(parser, OmpDefaultmapClause)
   NODE(parser, OmpDefaultVariantClause)
   NODE(OmpDefaultmapClause, Modifier)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 3e9a035d0bfee5..06146cbc6a8cc6 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4604,8 +4604,10 @@ struct OmpApplyClause {
 //    SHARED | NONE |                               // since 4.5
 //    PRIVATE | FIRSTPRIVATE                        // since 5.0
 struct OmpDefaultClause {
-  ENUM_CLASS(DataSharingAttribute, Private, Firstprivate, Shared, None)
-  WRAPPER_CLASS_BOILERPLATE(OmpDefaultClause, DataSharingAttribute);
+  ENUM_CLASS(DataSharingAttribute, Private, Firstprivate, Shared, None);
+  TUPLE_CLASS_BOILERPLATE(OmpDefaultClause);
+  MODIFIER_BOILERPLATE(OmpVariableCategory);
+  std::tuple<DataSharingAttribute, MODIFIERS()> t;
 };
 
 // Ref: [4.5:103-107], [5.0:324-325], [5.1:357-358], [5.2:161-162]
diff --git a/flang/include/flang/Semantics/openmp-utils.h b/flang/include/flang/Semantics/openmp-utils.h
index 769140a3147edf..4973a4599d5e22 100644
--- a/flang/include/flang/Semantics/openmp-utils.h
+++ b/flang/include/flang/Semantics/openmp-utils.h
@@ -48,6 +48,14 @@ using Fortran::parser::omp::is_range_v;
 using Fortran::parser::omp::LoopNestIterator;
 using Fortran::parser::omp::LoopRange;
 
+bool DefaultMapCategoryMatchesSymbol(
+    parser::OmpVariableCategory::Value category, const Symbol &symbol);
+
+bool IsOpenMPPointer(const Symbol &symbol);
+
+bool IsOpenMPAggregate(const Symbol &symbol);
+bool IsOpenMPScalar(const Symbol &symbol);
+
 template <typename T, typename U = std::remove_const_t<T>> U AsRvalue(T &t) {
   return U(t);
 }
diff --git a/flang/lib/Lower/OpenMP/Clauses.cpp b/flang/lib/Lower/OpenMP/Clauses.cpp
index ee16ae55af30f3..4933b53a4a9461 100644
--- a/flang/lib/Lower/OpenMP/Clauses.cpp
+++ b/flang/lib/Lower/OpenMP/Clauses.cpp
@@ -661,7 +661,7 @@ Default make(const parser::OmpClause::Default &inp,
   using wrapped = parser::OmpDefaultClause;
 
   CLAUSET_ENUM_CONVERT( //
-      convert, wrapped::DataSharingAttribute, Default::DataSharingAttribute,
+      convert1, wrapped::DataSharingAttribute, Default::DataSharingAttribute,
       // clang-format off
       MS(Firstprivate, Firstprivate)
       MS(None,         None)
@@ -670,7 +670,24 @@ Default make(const parser::OmpClause::Default &inp,
       // clang-format on
   );
 
-  return Default{/*DataSharingAttribute=*/convert(inp.v.v)};
+  CLAUSET_ENUM_CONVERT( //
+      convert2, parser::OmpVariableCategory::Value, Default::VariableCategory,
+      // clang-format off
+        MS(Aggregate,    Aggregate)
+        MS(All,          All)
+        MS(Allocatable,  Allocatable)
+        MS(Pointer,      Pointer)
+        MS(Scalar,       Scalar)
+      // clang-format on
+  );
+
+  auto &mods = semantics::OmpGetModifiers(inp.v);
+  auto &t0 = std::get<wrapped::DataSharingAttribute>(inp.v.t);
+  auto *t1 = semantics::OmpGetUniqueModifier<parser::OmpVariableCategory>(mods);
+
+  auto category = t1 ? convert2(t1->v) : Default::VariableCategory::All;
+
+  return Default{/*DataSharingAttribute=*/{convert1(t0), category}};
 }
 
 // Lower the DefaultVariant (specific to OpenMP 5.0 and 5.1) directly to
diff --git a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
index 8d0d191058cfb8..d9ff057f0e69c5 100644
--- a/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
+++ b/flang/lib/Lower/OpenMP/DataSharingProcessor.cpp
@@ -684,14 +684,71 @@ void DataSharingProcessor::collectSymbols(
 
 void DataSharingProcessor::collectDefaultSymbols() {
   using DataSharingAttribute = omp::clause::Default::DataSharingAttribute;
+  using VariableCategory = omp::clause::Default::VariableCategory;
   for (const omp::Clause &clause : clauses) {
     if (const auto *defaultClause =
             std::get_if<omp::clause::Default>(&clause.u)) {
-      if (defaultClause->v == DataSharingAttribute::Private)
-        collectSymbols(semantics::Symbol::Flag::OmpPrivate, &defaultSymbols);
-      else if (defaultClause->v == DataSharingAttribute::Firstprivate)
-        collectSymbols(semantics::Symbol::Flag::OmpFirstPrivate,
-                       &defaultSymbols);
+      auto &dsa{std::get<DataSharingAttribute>(defaultClause->t)};
+      auto &varcat{std::get<1>(defaultClause->t)};
+
+      llvm::SetVector<const semantics::Symbol *> allSymbols;
+      semantics::Symbol::Flag flag;
+      if (dsa == DataSharingAttribute::Private) {
+        flag = semantics::Symbol::Flag::OmpPrivate;
+        converter.collectSymbolSet(eval, allSymbols,
+                                   semantics::Symbol::Flag::OmpPrivate,
+                                   /*collectSymbols=*/true,
+                                   /*collectHostAssociatedSymbols=*/true);
+      } else if (dsa == DataSharingAttribute::Firstprivate) {
+
+        flag = semantics::Symbol::Flag::OmpFirstPrivate;
+        converter.collectSymbolSet(eval, allSymbols,
+                                   semantics::Symbol::Flag::OmpFirstPrivate,
+                                   /*collectSymbols=*/true,
+                                   /*collectHostAssociatedSymbols=*/true);
+      }
+      if (!allSymbols.empty()) {
+        for (const auto *symbol : allSymbols) {
+          switch (varcat.value_or(VariableCategory::All)) {
+          case VariableCategory::All:
+            break;
+          case VariableCategory::Scalar:
+            if (!semantics::omp::DefaultMapCategoryMatchesSymbol(
+                    parser::OmpVariableCategory::Value::Scalar, *symbol)) {
+              allSymbols.remove(symbol);
+            }
+            break;
+          case VariableCategory::Aggregate:
+            if (!semantics::omp::DefaultMapCategoryMatchesSymbol(
+                    parser::OmpVariableCategory::Value::Aggregate, *symbol)) {
+              allSymbols.remove(symbol);
+            }
+            break;
+          case VariableCategory::Allocatable:
+            if (!semantics::omp::DefaultMapCategoryMatchesSymbol(
+                    parser::OmpVariableCategory::Value::Allocatable, *symbol)) {
+              allSymbols.remove(symbol);
+            }
+            break;
+          case VariableCategory::Pointer:
+            if (!semantics::omp::DefaultMapCategoryMatchesSymbol(
+                    parser::OmpVariableCategory::Value::Pointer, *symbol)) {
+              allSymbols.remove(symbol);
+            }
+            break;
+          }
+        }
+      } else {
+        continue;
+      }
+      llvm::SetVector<const semantics::Symbol *> symbolsInNestedRegions;
+      collectSymbolsInNestedRegions(eval, flag, symbolsInNestedRegions);
+      for (auto *symbol : allSymbols) {
+        if (visitor.isSymbolDefineBy(symbol, eval)) {
+          symbolsInNestedRegions.remove(symbol);
+        }
+      }
+      collectPrivatizedSymbols(flag, allSymbols, symbolsInNestedRegions);
     }
   }
 }
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 5e80af0cfc634f..9a0436ca32cce4 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -1114,6 +1114,9 @@ TYPE_PARSER(sourced(
 TYPE_PARSER(
     sourced(construct<OmpDoacross::Modifier>(Parser<OmpDependenceType>{})))
 
+TYPE_PARSER(sourced(
+    construct<OmpDefaultClause::Modifier>(Parser<OmpVariableCategory>{})))
+
 TYPE_PARSER(sourced( //
     construct<OmpDependClause::TaskDep::Modifier>(Parser<OmpIterator>{}) ||
     construct<OmpDependClause::TaskDep::Modifier>(
@@ -1340,7 +1343,8 @@ TYPE_PARSER(construct<OmpDefaultClause::DataSharingAttribute>(
     "NONE" >> pure(OmpDefaultClause::DataSharingAttribute::None)))
 
 TYPE_PARSER(construct<OmpDefaultClause>(
-    Parser<OmpDefaultClause::DataSharingAttribute>{}))
+    Parser<OmpDefaultClause::DataSharingAttribute>{},
+    maybe(":" >> nonemptyList(Parser<OmpDefaultClause::Modifier>{}))))
 
 TYPE_PARSER(construct<OmpDefaultVariantClause>(
     indirect(OmpDirectiveSpecificationParser(/*allowCommas=*/false))))
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index dffece95796cc6..68e4ec4216cc43 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -4598,6 +4598,27 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Aligned &x) {
   // 2.8.1 TODO: list-item attribute check
 }
 
+void OmpStructureChecker::Enter(const parser::OmpClause::Default &x) {
+  llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
+  auto &modifiers{OmpGetModifiers(x.v)};
+  auto *maybeCategory{
+      OmpGetUniqueModifier<parser::OmpVariableCategory>(modifiers)};
+  if (maybeCategory) {
+    using VariableCategory = parser::OmpVariableCategory;
+    VariableCategory::Value category{maybeCategory->v};
+    llvm::omp::Version tryVersion;
+    if (version < 60) {
+      tryVersion = llvm::omp::Version(60);
+    }
+    if (tryVersion) {
+      context_.Say(GetContext().clauseSource,
+          "%s is not allowed in %s, %s"_warn_en_US,
+          parser::ToUpperCaseLetters(VariableCategory::EnumToString(category)),
+          ThisVersion(version), TryVersion(tryVersion));
+    }
+  }
+}
+
 void OmpStructureChecker::Enter(const parser::OmpClause::Defaultmap &x) {
   llvm::omp::Version version{context_.langOptions().getOpenMPVersion()};
   using ImplicitBehavior = parser::OmpDefaultmapClause::ImplicitBehavior;
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 41b866337c4f1b..ec0d05715399da 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -211,6 +211,7 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
   void Enter(const parser::OmpClause::Collapse &x);
   void Enter(const parser::OmpClause::Copyin &x);
   void Enter(const parser::OmpClause::Copyprivate &x);
+  void Enter(const parser::OmpClause::Default &x);
   void Enter(const parser::OmpClause::Defaultmap &x);
   void Enter(const parser::OmpClause::Depend &x);
   void Enter(const parser::OmpClause::Depth &x);
diff --git a/flang/lib/Semantics/check-omp-variant.cpp b/flang/lib/Semantics/check-omp-variant.cpp
index 5526b5cc3d08ae..09a0b8058d72b0 100644
--- a/flang/lib/Semantics/check-omp-variant.cpp
+++ b/flang/lib/Semantics/check-omp-variant.cpp
@@ -54,7 +54,8 @@ bool HasDefaultNone(const parser::OmpDirectiveSpecification &spec) {
     return false;
   }
   const auto &defaultClause{std::get<parser::OmpClause::Default>(clause->u)};
-  return defaultClause.v.v == DataSharingAttribute::None;
+  return std::get<DataSharingAttribute>(defaultClause.v.t) ==
+      DataSharingAttribute::None;
 }
 
 bool HasNestedPrivateDSA(const Symbol &symbol, const Scope &scope) {
diff --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp
index a341cf4fa17065..d37f762680ae6d 100644
--- a/flang/lib/Semantics/openmp-utils.cpp
+++ b/flang/lib/Semantics/openmp-utils.cpp
@@ -59,6 +59,67 @@
 namespace Fortran::semantics::omp {
 using namespace Fortran::parser::omp;
 
+bool IsOpenMPPointer(const Symbol &symbol) {
+  if (IsPointer(symbol) || IsBuiltinCPtr(symbol))
+    return true;
+  return false;
+}
+
+bool IsOpenMPAggregate(const Symbol &symbol) {
+  if (IsAllocatable(symbol) || IsOpenMPPointer(symbol))
+    return false;
+
+  const auto *type{symbol.GetType()};
+  // OpenMP categorizes Fortran characters as aggregates.
+  if (type->category() == Fortran::semantics::DeclTypeSpec::Category::Character)
+    return true;
+
+  if (const auto *det{symbol.GetUltimate()
+              .detailsIf<Fortran::semantics::ObjectEntityDetails>()})
+    if (det->IsArray())
+      return true;
+
+  if (type->AsDerived())
+    return true;
+
+  if (IsDeferredShape(symbol) || IsAssumedRank(symbol) ||
+      IsAssumedShape(symbol))
+    return true;
+  return false;
+}
+
+bool IsOpenMPScalar(const Symbol &symbol) {
+  if (IsOpenMPAggregate(symbol) || IsOpenMPPointer(symbol) ||
+      IsAllocatable(symbol))
+    return false;
+  const auto *type{symbol.GetType()};
+  if ((!symbol.GetShape() || symbol.GetShape()->empty()) &&
+      (type->category() ==
+              Fortran::semantics::DeclTypeSpec::Category::Numeric ||
+          type->category() ==
+              Fortran::semantics::DeclTypeSpec::Category::Logical))
+    return true;
+  return false;
+}
+
+bool DefaultMapCategoryMatchesSymbol(
+    parser::OmpVariableCategory::Value category, const Symbol &symbol) {
+  using VarCat = parser::OmpVariableCategory::Value;
+  switch (category) {
+  case VarCat::Scalar:
+    return IsOpenMPScalar(symbol);
+  case VarCat::Allocatable:
+    return IsAllocatable(symbol);
+  case VarCat::Aggregate:
+    return IsOpenMPAggregate(symbol);
+  case VarCat::Pointer:
+    return IsOpenMPPointer(symbol);
+  case VarCat::All:
+    return true;
+  }
+  return false;
+}
+
 const Scope &GetScopingUnit(const Scope &scope) {
   const Scope *iter{&scope};
   for (; !iter->IsTopLevel(); iter = &iter->parent()) {
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 143fe385768d79..879dde5671ba18 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -59,7 +59,8 @@ template <typename T> class DirectiveAttributeVisitor {
     parser::CharBlock directiveSource;
     T directive;
     Scope &scope;
-    Symbol::Flag defaultDSA{Symbol::Flag::AccShared}; // TODOACC
+    std::map<parser::OmpVariableCategory::Value, Symbol::Flag> defaultDSA{
+        {parser::OmpVariableCategory::Value::All, Symbol::Flag::AccShared}};
     std::map<const Symbol *, Symbol::Flag> objectWithDSA;
     std::map<const Symbol *, Symbol::Flags> commonBlockClauseFlags;
     std::map<parser::OmpVariableCategory::Value,
@@ -105,8 +106,18 @@ template <typename T> class DirectiveAttributeVisitor {
       parser::OmpDefaultmapClause::ImplicitBehavior ImpBehav) {
     GetContext().defaultMap[VarCat] = ImpBehav;
   }
-  void SetContextDefaultDSA(Symbol::Flag flag) {
-    GetContext().defaultDSA = flag;
+  void SetContextDefaultDSA(Symbol::Flag flag,
+      parser::OmpVariableCategory::Value VarCat =
+          parser::OmpVariableCategory::Value::All) {
+    GetContext().defaultDSA = {{VarCat, flag}};
+  }
+  Symbol::Flag DefaultDSAForSymbol(
+      const DirContext &dirContext, const Symbol &symbol) {
+    for (auto defaults : dirContext.defaultDSA) {
+      if (omp::DefaultMapCategoryMatchesSymbol(defaults.first, symbol)) {
+        return defaults.second;
+      }
+    }
   }
   void AddToContextObjectWithDSA(
       const Symbol &symbol, Symbol::Flag flag, DirContext &context) {
@@ -1870,9 +1881,10 @@ void AccAttributeVisitor::Post(const parser::Name &name) {
           // adjust the symbol within the region
           // TODO: why didn't name resolution set the right name originally?
           name.symbol = found;
-        } else if (GetContext().defaultDSA == Symbol::Flag::AccNone) {
-          // 2.5.14. Pre-OpenACC-3.2 behavior: implicit scalars warn instead of
-          // error unless strict mode is enabled.
+        } else if (DefaultDSAForSymbol(GetContext(), symbol) ==
+            Symbol::Flag::AccNone) {
+          // 2.5.14. Pre-OpenACC-3.2 behavior: implicit scalars warn instead
+          // of error unless strict mode is enabled.
           if (IsAccScalar(symbol) &&
               !context_.IsEnabled(
                   common::LanguageFeature::OpenAccDefaultNoneScalarsStrict)) {
@@ -2540,20 +2552,32 @@ void OmpAttributeVisitor::Post(const parser::OmpClause::Defaultmap &x) {
 void OmpAttributeVisitor::Post(const parser::OmpDefaultClause &x) {
   // The DEFAULT clause may also be used on METADIRECTIVE. In that case
   // there is nothing to do.
+  using VariableCategory = parser::OmpVariableCategory;
   using DataSharingAttribute = parser::OmpDefaultClause::DataSharingAttribute;
+  VariableCategory::Value varCategory;
+
+  auto dsa{std::get<DataSharingAttribute>(x.t)};
+  auto &modifiers{OmpGetModifiers(x)};
+  auto *maybeCategory{
+      OmpGetUniqueModifier<parser::OmpVariableCategory>(modifiers)};
+  if (maybeCategory)
+    varCategory = maybeCategory->v;
+  else
+    varCategory = VariableCategory::Value::All;
+
   if (!dirContext_.empty()) {
-    switch (x.v) {
+    switch (dsa) {
     case DataSharingAttribute::Private:
-      SetContextDefaultDSA(Symbol::Flag::OmpPrivate);
+      SetContextDefaultDSA(Symbol::Flag::OmpPrivate, varCategory);
       break;
     case DataSharingAttribute::Firstprivate:
-      SetContextDefaultDSA(Symbol::Flag::OmpFirstPrivate);
+      SetContextDefaultDSA(Symbol::Flag::OmpFirstPrivate, varCategory);
       break;
     case DataSharingAttribute::Shared:
-      SetContextDefaultDSA(Symbol::Flag::OmpShared);
+      SetContextDefaultDSA(Symbol::Flag::OmpShared, varCategory);
       break;
     case DataSharingAttribute::None:
-      SetContextDefaultDSA(Symbol::Flag::OmpNone);
+      SetContextDefaultDSA(Symbol::Flag::OmpNone, varCategory);
       break;
     }
   }
@@ -2752,7 +2776,7 @@ void OmpAttributeVisitor::CreateImplicitSymbols(
       }
     }
     if (dsa.none() && crayPtrDSA.none() &&
-        dirContext.defaultDSA == Symbol::Flag::OmpNone) {
+        DefaultDSAForSymbol(dirContext, *symbol) == Symbol::Flag::OmpNone) {
       checkDefaultNone = true;
     }
     bool hasDefaultNoneError{false};
@@ -2825,18 +2849,19 @@ void OmpAttributeVisitor::CreateImplicitSymbols(
     //      Ideally, lowering should be changed and all implicit symbols
     //      should be marked with OmpImplicit.
 
-    if (dirContext.defaultDSA == Symbol::Flag::OmpPrivate ||
-        dirContext.defaultDSA == Symbol::Flag::OmpFirstPrivate ||
-        dirContext.defaultDSA == Symbol::Flag::OmpShared ||
-        (dirContext.defaultDSA == Symbol::Flag::OmpNone &&
+    if (DefaultDSAForSymbol(dirContext, *symbol) == Symbol::Flag::OmpPrivate ||
+        DefaultDSAForSymbol(dirContext, *symbol) ==
+            Symbol::Flag::OmpFirstPrivate ||
+        DefaultDSAForSymbol(dirContext, *symbol) == Symbol::Flag::OmpShared ||
+        (DefaultDSAForSymbol(dirContext, *symbol) == Symbol::Flag::OmpNone &&
             !hasDefaultNoneError)) {
       // 1) default
       // Allowed only with parallel, teams and task generating constructs.
       if (!parallelDir && !taskGenDir && !teamsDir) {
         return;
       }
-      dsa = {dirContext.defaultDSA};
-      if (dirContext.defaultDSA != Symbol::Flag::OmpNone) {
+      dsa = {DefaultDSAForSymbol(dirContext, *symbol)};
+      if (DefaultDSAForSymbol(dirContext, *symbol) != Symbol::Flag::OmpNone) {
         makeSymbol(dsa);
       }
       PRINT_IMPLICIT_RULE("1) default");
@@ -2890,67 +2915,6 @@ void OmpAttributeVisitor::CreateImplicitSymbols(
   }
 }
 
-static bool IsOpenMPPointer(const Symbol &symbol) {
-  if (IsPointer(symbol) || IsBuiltinCPtr(symbol))
-    return true;
-  return false;
-}
-
-static bool IsOpenMPAggregate(const Symbol &symbol) {
-  if (IsAllocatable(symbol) || IsOpenMPPointer(symbol))
-    return false;
-
-  const auto *type{symbol.GetType()};
-  // OpenMP categorizes Fortran characters as aggregates.
-  if (type->category() == Fortran::semantics::DeclTypeSpec::Category::Character)
-    return true;
-
-  if (const auto *det{symbol.GetUltimate()
-              .detailsIf<Fortran::semantics::ObjectEntityDetails>()})
-    if (det->IsArray())
-      return true;
-
-  if (type->AsDerived())
-    return true;
-
-  if (IsDeferredShape(symbol) || IsAssumedRank(symbol) ||
-      IsAssumedShape(symbol))
-    return true;
-  return false;
-}
-
-static bool IsOpenMPScalar(const Symbol &symbol) {
-  if (IsOpenMPAggregate(symbol) || IsOpenMPPointer(symbol) ||
-      IsAllocatable(symbol))
-    return false;
-  const auto *type{symbol.GetType()};
-  if ((!symbol.GetShape() || symbol.GetShape()->e...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/223476


More information about the flang-commits mailing list