[flang-commits] [flang] [flang][OpenMP] Refactor semantic check of SINGLE construct (PR #204339)

Thirumalai Shaktivel via flang-commits flang-commits at lists.llvm.org
Sun Jun 21 21:37:55 PDT 2026


================
@@ -1386,6 +1330,78 @@ void OmpStructureChecker::Enter(const parser::OmpBlockConstruct &x) {
   }
 }
 
+void OmpStructureChecker::CheckSingleConstruct(
+    const parser::OmpBlockConstruct &x) {
+  const parser::OmpDirectiveSpecification &beginSpec{x.BeginDir()};
+  unsigned version{context_.langOptions().OpenMPVersion};
+  SymbolSourceMap copyPrivateSyms;
+  parser::CharBlock nowaitSource1, nowaitSource2;
+
+  auto catchCopyPrivateNowaitClauses =
+      [&](const parser::OmpDirectiveSpecification &spec,
+          parser::CharBlock &nowaitSource) {
+        for (auto &clause : spec.Clauses().v) {
+          llvm::omp::Clause clauseId{clause.Id()};
+          if (clauseId == llvm::omp::Clause::OMPC_copyprivate) {
+            GetSymbolsInObjectList(*GetOmpObjectList(clause), copyPrivateSyms);
+          } else if (clauseId == llvm::omp::Clause::OMPC_nowait) {
+            if (nowaitSource.empty()) {
+              nowaitSource = clause.source;
+            }
+          }
+        }
+      };
+
+  catchCopyPrivateNowaitClauses(beginSpec, nowaitSource1);
+  if (auto &endSpec{x.EndDir()}) {
+    catchCopyPrivateNowaitClauses(*endSpec, nowaitSource2);
+  }
+
+  std::string nowaitName{//
+      GetUpperName(llvm::omp::Clause::OMPC_nowait, version)};
+  std::string copyPrivateName{
+      GetUpperName(llvm::omp::Clause::OMPC_copyprivate, version)};
+  std::string singleName{
+      GetUpperName(llvm::omp::Directive::OMPD_single, version)};
+
+  std::pair<const Symbol *, parser::CharBlock> last{nullptr, {}};
+  bool reported{false};
+
+  for (auto [symbol, source] : copyPrivateSyms) {
+    if (symbol == last.first) {
+      if (!reported) {
+        context_
+            .Say(source, "'%s' appears more than once in a %s clause"_err_en_US,
+                symbol->name().ToString(), copyPrivateName)
+            .Attach(last.second, "Previous occurrence of '%s'"_en_US,
+                symbol->name().ToString());
+        reported = true;
+      }
+    } else {
+      reported = false;
+    }
+    last = std::make_pair(symbol, source);
+  }
+
+  if (!nowaitSource1.empty() && !nowaitSource2.empty()) {
+    context_
+        .Say(nowaitSource2,
+            // Match the message text with the one emitted by "CheckAllowed".
+            "At most one %s clause can appear on the %s directive"_err_en_US,
+            nowaitName, singleName)
+        .Attach(nowaitSource1, "Previous occurrence of %s"_en_US, nowaitName);
+  }
+
+  if (version < 52 && !copyPrivateSyms.empty() &&
----------------
Thirumalai-Shaktivel wrote:

This excludes the 5.2 version for the semantic restriction
OpenMP 5.2 doc: 11.1
```
The copyprivate clause must not be used with the nowait clause
```
Example in godbolt: https://godbolt.org/z/4GbP19hjf

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


More information about the flang-commits mailing list