[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