[flang-commits] [flang] [flang][OpenMP] Detect conflicting data-sharing clauses for common blocks (PR #213913)

via flang-commits flang-commits at lists.llvm.org
Wed Aug 5 00:16:50 PDT 2026


https://github.com/ejose02 updated https://github.com/llvm/llvm-project/pull/213913

>From fd355b023167407eea6aa7a12b8460886b9618a1 Mon Sep 17 00:00:00 2001
From: ejose <ejose at amd.com>
Date: Wed, 5 Aug 2026 07:04:49 +0000
Subject: [PATCH] [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    | 54 ++++++++++++++++---
 .../OpenMP/common-block-data-sharing.f90      | 11 ++++
 2 files changed, 59 insertions(+), 6 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..bdb5a4e34aba5 100644
--- a/flang/lib/Semantics/resolve-directives.cpp
+++ b/flang/lib/Semantics/resolve-directives.cpp
@@ -3194,7 +3194,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
@@ -3295,14 +3295,31 @@ Symbol *OmpAttributeVisitor::DeclareOrMarkOtherAccessEntity(
   return &object;
 }
 
-static bool WithMultipleAppearancesOmpException(
-    const Symbol &symbol, Symbol::Flag flag) {
+static bool IsFirstPrivateLastPrivatePair(Symbol::Flag a, Symbol::Flag b) {
+  return (a == Symbol::Flag::OmpFirstPrivate &&
+             b == Symbol::Flag::OmpLastPrivate) ||
+      (a == Symbol::Flag::OmpLastPrivate &&
+          b == Symbol::Flag::OmpFirstPrivate);
+}
+
+static bool WithMultipleAppearancesOmpException(const Symbol &symbol,
+    Symbol::Flag flag, std::optional<Symbol::Flag> prevFlag = std::nullopt) {
+  if (prevFlag && IsFirstPrivateLastPrivatePair(flag, *prevFlag)) {
+    return true;
+  }
   return (flag == Symbol::Flag::OmpFirstPrivate &&
              symbol.test(Symbol::Flag::OmpLastPrivate)) ||
       (flag == Symbol::Flag::OmpLastPrivate &&
           symbol.test(Symbol::Flag::OmpFirstPrivate));
 }
 
+static bool HasConflictingDataSharingAppearance(const Symbol &sym,
+    Symbol::Flag flag, const std::optional<Symbol::Flag> &prevFlag,
+    bool alreadyListed) {
+  return alreadyListed &&
+      !WithMultipleAppearancesOmpException(sym, flag, prevFlag);
+}
+
 void OmpAttributeVisitor::CheckMultipleAppearances(
     const parser::Name &name, const Symbol &symbol, Symbol::Flag ompFlag) {
   const auto *target{&symbol};
@@ -3311,14 +3328,39 @@ void OmpAttributeVisitor::CheckMultipleAppearances(
       target = &details->symbol();
     }
   }
-  if (HasDataSharingAttributeObject(target->GetUltimate()) &&
-      !WithMultipleAppearancesOmpException(symbol, ompFlag)) {
+  const Symbol &ultimate = target->GetUltimate();
+  bool conflicts{HasConflictingDataSharingAppearance(symbol, ompFlag,
+      GetContext().FindSymbolWithDSA(ultimate),
+      HasDataSharingAttributeObject(ultimate))};
+  if (!conflicts) {
+    if (const Symbol *commonBlock = FindCommonBlockContaining(ultimate)) {
+      conflicts = HasConflictingDataSharingAppearance(*commonBlock, ompFlag,
+          GetContext().FindSymbolWithDSA(*commonBlock),
+          HasDataSharingAttributeObject(*commonBlock));
+    } else if (const auto *details = ultimate.detailsIf<CommonBlockDetails>()) {
+      for (const auto &object : details->objects()) {
+        const Symbol &member{object->GetUltimate()};
+        if (HasConflictingDataSharingAppearance(member, ompFlag,
+                GetContext().FindSymbolWithDSA(member),
+                HasDataSharingAttributeObject(member))) {
+          conflicts = true;
+          break;
+        }
+      }
+    }
+  }
+  if (conflicts) {
     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



More information about the flang-commits mailing list