[flang-commits] [flang] [flang][OpenMP] Detect conflicting data-sharing clauses for common blocks (PR #213913)
via flang-commits
flang-commits at lists.llvm.org
Mon Aug 17 23:52:27 PDT 2026
https://github.com/ejose02 updated https://github.com/llvm/llvm-project/pull/213913
>From eea925fe1dd74476f1a64170494055c673880789 Mon Sep 17 00:00:00 2001
From: ejose <ejose at amd.com>
Date: Wed, 5 Aug 2026 07:04:49 +0000
Subject: [PATCH 1/3] [flang][OpenMP] Detect conflicting data-sharing clauses
for common blocks
OpenMP 2.15.3 treats a named common block in a data-sharing clause as equivalent to listing every explicit member. Extend CheckMultipleAppearances to detect overlap between a common block and its members, register explicit members when a common block is listed, and consult FindSymbolWithDSA in the existing firstprivate/lastprivate multiple-appearance exception. Added a regression test.
Fixes #205779
---
flang/lib/Semantics/resolve-directives.cpp | 57 +++++++++++++++++--
.../OpenMP/common-block-data-sharing.f90 | 11 ++++
2 files changed, 64 insertions(+), 4 deletions(-)
create mode 100644 flang/test/Semantics/OpenMP/common-block-data-sharing.f90
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 15bb84d7e486f..9c1db92dbe221 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -72,6 +72,19 @@ template <typename T> class DirectiveAttributeVisitor {
return std::nullopt;
}
+ std::optional<Symbol::Flag> FindExplicitDSAForMember(const Symbol &symbol) {
+ if (auto flag{FindSymbolWithDSA(symbol)}) {
+ return flag;
+ }
+ const Symbol &ultimate{symbol.GetUltimate()};
+ for (const auto &entry : objectWithDSA) {
+ if (entry.first->GetUltimate() == ultimate) {
+ return entry.second;
+ }
+ }
+ return std::nullopt;
+ }
+
bool withinConstruct{false};
std::int64_t associatedLoopLevel{0};
};
@@ -602,6 +615,7 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
bool Pre(const parser::OmpDeclareSimdDirective &x) {
PushContext(x.source, llvm::omp::Directive::OMPD_declare_simd);
+ ClearDataSharingAttributeObjects();
for (const parser::OmpArgument &arg : x.v.Arguments().v) {
if (auto *object{parser::omp::GetArgumentObject(arg)}) {
ResolveOmpObject(*object, Symbol::Flag::OmpDeclareSimd);
@@ -3194,7 +3208,7 @@ void OmpAttributeVisitor::ResolveOmpCommonBlock(
Symbol *originalCB{ResolveOmpCommonBlockName(&cbName)};
if (auto *symbol{cbResolved ? name.symbol : originalCB}) {
if (!dataCopyingAttributeFlags.test(ompFlag)) {
- CheckMultipleAppearances(name, *symbol, Symbol::Flag::OmpCommonBlock);
+ CheckMultipleAppearances(name, *symbol, ompFlag);
}
// 2.15.3 When a named common block appears in a list, it has the
// same meaning as if every explicit member of the common block
@@ -3303,6 +3317,14 @@ static bool WithMultipleAppearancesOmpException(
symbol.test(Symbol::Flag::OmpFirstPrivate));
}
+static bool IsFirstPrivateLastPrivatePair(
+ Symbol::Flag flag, Symbol::Flag prevFlag) {
+ return (flag == Symbol::Flag::OmpFirstPrivate &&
+ prevFlag == Symbol::Flag::OmpLastPrivate) ||
+ (flag == Symbol::Flag::OmpLastPrivate &&
+ prevFlag == Symbol::Flag::OmpFirstPrivate);
+}
+
void OmpAttributeVisitor::CheckMultipleAppearances(
const parser::Name &name, const Symbol &symbol, Symbol::Flag ompFlag) {
const auto *target{&symbol};
@@ -3311,14 +3333,41 @@ void OmpAttributeVisitor::CheckMultipleAppearances(
target = &details->symbol();
}
}
- if (HasDataSharingAttributeObject(target->GetUltimate()) &&
- !WithMultipleAppearancesOmpException(symbol, ompFlag)) {
+ const Symbol &ultimate{target->GetUltimate()};
+ bool conflicts{HasDataSharingAttributeObject(ultimate)};
+ if (!conflicts) {
+ if (const Symbol *commonBlock{FindCommonBlockContaining(ultimate)}) {
+ conflicts = HasDataSharingAttributeObject(*commonBlock);
+ } else if (const auto *details{ultimate.detailsIf<CommonBlockDetails>()}) {
+ for (const auto &object : details->objects()) {
+ const Symbol &member{object->GetUltimate()};
+ if (HasDataSharingAttributeObject(member)) {
+ bool allowed{WithMultipleAppearancesOmpException(member, ompFlag)};
+ if (!allowed) {
+ if (auto prevFlag{GetContext().FindExplicitDSAForMember(member)}) {
+ allowed = IsFirstPrivateLastPrivatePair(ompFlag, *prevFlag);
+ }
+ }
+ if (!allowed) {
+ conflicts = true;
+ break;
+ }
+ }
+ }
+ }
+ }
+ if (conflicts && !WithMultipleAppearancesOmpException(symbol, ompFlag)) {
context_.Say(name.source,
"'%s' appears in more than one data-sharing clause "
"on the same OpenMP directive"_err_en_US,
name.ToString());
} else {
- AddDataSharingAttributeObject(target->GetUltimate());
+ AddDataSharingAttributeObject(ultimate);
+ if (const auto *details{ultimate.detailsIf<CommonBlockDetails>()}) {
+ for (const auto &object : details->objects()) {
+ AddDataSharingAttributeObject(object->GetUltimate());
+ }
+ }
}
}
diff --git a/flang/test/Semantics/OpenMP/common-block-data-sharing.f90 b/flang/test/Semantics/OpenMP/common-block-data-sharing.f90
new file mode 100644
index 0000000000000..f0ddf8e048441
--- /dev/null
+++ b/flang/test/Semantics/OpenMP/common-block-data-sharing.f90
@@ -0,0 +1,11 @@
+! RUN: %python %S/../test_errors.py %s %flang -fopenmp
+
+! a common block in a data-sharing clause is equivalent to
+! listing every explicit member of the common block.
+
+subroutine common_block_dsa()
+ common /c/ x, y
+ !ERROR: 'x' appears in more than one data-sharing clause on the same OpenMP directive
+ !$omp parallel private(/c/) shared(x)
+ !$omp end parallel
+end subroutine
>From ea59dc42d7b087f44ca8779c3c1200b04e03fcb1 Mon Sep 17 00:00:00 2001
From: ejose <ejose at amd.com>
Date: Mon, 17 Aug 2026 11:25:31 +0000
Subject: [PATCH 2/3] Fold the firstprivate/lastprivate exception into
WithMultipleAppearancesOmpException via an optional prevFlag, remove the
duplicate helper, and simplify the common-block member loop using
FindObjectWithDSAByUltimate for scoped ultimate-symbol DSA lookup.
---
flang/lib/Semantics/resolve-directives.cpp | 38 +++++++++-------------
1 file changed, 16 insertions(+), 22 deletions(-)
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 9c1db92dbe221..15bb72b61225a 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -72,7 +72,8 @@ template <typename T> class DirectiveAttributeVisitor {
return std::nullopt;
}
- std::optional<Symbol::Flag> FindExplicitDSAForMember(const Symbol &symbol) {
+ std::optional<Symbol::Flag> FindObjectWithDSAByUltimate(
+ const Symbol &symbol) {
if (auto flag{FindSymbolWithDSA(symbol)}) {
return flag;
}
@@ -3309,22 +3310,21 @@ Symbol *OmpAttributeVisitor::DeclareOrMarkOtherAccessEntity(
return &object;
}
-static bool WithMultipleAppearancesOmpException(
- const Symbol &symbol, Symbol::Flag flag) {
+static bool WithMultipleAppearancesOmpException(const Symbol &symbol,
+ Symbol::Flag flag, std::optional<Symbol::Flag> prevFlag = std::nullopt) {
+ if (prevFlag &&
+ ((flag == Symbol::Flag::OmpFirstPrivate &&
+ *prevFlag == Symbol::Flag::OmpLastPrivate) ||
+ (flag == Symbol::Flag::OmpLastPrivate &&
+ *prevFlag == Symbol::Flag::OmpFirstPrivate))) {
+ return true;
+ }
return (flag == Symbol::Flag::OmpFirstPrivate &&
symbol.test(Symbol::Flag::OmpLastPrivate)) ||
(flag == Symbol::Flag::OmpLastPrivate &&
symbol.test(Symbol::Flag::OmpFirstPrivate));
}
-static bool IsFirstPrivateLastPrivatePair(
- Symbol::Flag flag, Symbol::Flag prevFlag) {
- return (flag == Symbol::Flag::OmpFirstPrivate &&
- prevFlag == Symbol::Flag::OmpLastPrivate) ||
- (flag == Symbol::Flag::OmpLastPrivate &&
- prevFlag == Symbol::Flag::OmpFirstPrivate);
-}
-
void OmpAttributeVisitor::CheckMultipleAppearances(
const parser::Name &name, const Symbol &symbol, Symbol::Flag ompFlag) {
const auto *target{&symbol};
@@ -3341,17 +3341,11 @@ void OmpAttributeVisitor::CheckMultipleAppearances(
} else if (const auto *details{ultimate.detailsIf<CommonBlockDetails>()}) {
for (const auto &object : details->objects()) {
const Symbol &member{object->GetUltimate()};
- if (HasDataSharingAttributeObject(member)) {
- bool allowed{WithMultipleAppearancesOmpException(member, ompFlag)};
- if (!allowed) {
- if (auto prevFlag{GetContext().FindExplicitDSAForMember(member)}) {
- allowed = IsFirstPrivateLastPrivatePair(ompFlag, *prevFlag);
- }
- }
- if (!allowed) {
- conflicts = true;
- break;
- }
+ if (HasDataSharingAttributeObject(member) &&
+ !WithMultipleAppearancesOmpException(member, ompFlag,
+ GetContext().FindObjectWithDSAByUltimate(member))) {
+ conflicts = true;
+ break;
}
}
}
>From 68c44f43f2f5344508df7278ffc6e3c8221c4a8e Mon Sep 17 00:00:00 2001
From: ejose <ejose at amd.com>
Date: Tue, 18 Aug 2026 06:51:07 +0000
Subject: [PATCH 3/3] Simplify CheckMultipleAppearances per review Use
symbol.GetUltimate() directly and drop redundant GetUltimate() calls on
common-block members.
---
flang/lib/Semantics/resolve-directives.cpp | 17 +++++------------
1 file changed, 5 insertions(+), 12 deletions(-)
diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp
index 15bb72b61225a..41e9030b49896 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -3327,23 +3327,16 @@ static bool WithMultipleAppearancesOmpException(const Symbol &symbol,
void OmpAttributeVisitor::CheckMultipleAppearances(
const parser::Name &name, const Symbol &symbol, Symbol::Flag ompFlag) {
- const auto *target{&symbol};
- if (ompFlagsRequireNewSymbol.test(ompFlag)) {
- if (const auto *details{symbol.detailsIf<HostAssocDetails>()}) {
- target = &details->symbol();
- }
- }
- const Symbol &ultimate{target->GetUltimate()};
+ const Symbol &ultimate{symbol.GetUltimate()};
bool conflicts{HasDataSharingAttributeObject(ultimate)};
if (!conflicts) {
if (const Symbol *commonBlock{FindCommonBlockContaining(ultimate)}) {
conflicts = HasDataSharingAttributeObject(*commonBlock);
} else if (const auto *details{ultimate.detailsIf<CommonBlockDetails>()}) {
for (const auto &object : details->objects()) {
- const Symbol &member{object->GetUltimate()};
- if (HasDataSharingAttributeObject(member) &&
- !WithMultipleAppearancesOmpException(member, ompFlag,
- GetContext().FindObjectWithDSAByUltimate(member))) {
+ if (HasDataSharingAttributeObject(*object) &&
+ !WithMultipleAppearancesOmpException(*object, ompFlag,
+ GetContext().FindObjectWithDSAByUltimate(*object))) {
conflicts = true;
break;
}
@@ -3359,7 +3352,7 @@ void OmpAttributeVisitor::CheckMultipleAppearances(
AddDataSharingAttributeObject(ultimate);
if (const auto *details{ultimate.detailsIf<CommonBlockDetails>()}) {
for (const auto &object : details->objects()) {
- AddDataSharingAttributeObject(object->GetUltimate());
+ AddDataSharingAttributeObject(*object);
}
}
}
More information about the flang-commits
mailing list