[flang-commits] [flang] [llvm] [flang][OpenMP] Move clause validity checks into OpenMP-specific code (PR #205607)

Abid Qadeer via flang-commits flang-commits at lists.llvm.org
Thu Jun 25 10:51:24 PDT 2026


================
@@ -878,6 +886,150 @@ void OmpStructureChecker::CheckDirectiveDeprecation(
   // one another, but only the top-level directive should cause a warning.
 }
 
+std::pair<const parser::OmpClause *, const parser::OmpClause *>
+OmpStructureChecker::FindMutuallyExclusiveClauses(
+    OmpClauseSet exclusive, const parser::OmpClauseList &clauses) {
+  const parser::OmpClause *first{nullptr};
+  for (const parser::OmpClause &clause : clauses.v) {
+    llvm::omp::Clause clauseId{clause.Id()};
+    if (!exclusive.test(clauseId)) {
+      continue;
+    }
+    if (first) {
+      llvm::omp::Clause firstId{first->Id()};
+      if (clauseId < firstId) {
+        return std::make_pair(&clause, first);
+      } else if (clauseId > firstId) {
+        return std::make_pair(first, &clause);
+      }
+    } else {
+      first = &clause;
+    }
+  }
+  return std::make_pair(nullptr, nullptr);
+}
+
+void OmpStructureChecker::CheckExclusiveClauses(
+    OmpClauseSet exclusive, const parser::OmpDirectiveSpecification &spec) {
+  unsigned version{context_.langOptions().OpenMPVersion};
+  auto pair{FindMutuallyExclusiveClauses(exclusive, spec.Clauses())};
+
+  if (pair.first && pair.second) {
+    std::string firstName{GetUpperName(pair.first->Id(), version)};
+    std::string secondName{GetUpperName(pair.second->Id(), version)};
+    context_
+        .Say(pair.second->source,
+            "%s and %s clauses are mutually exclusive and may not appear on the same %s directive"_err_en_US,
+            firstName, secondName, GetUpperName(spec.DirId(), version))
+        .Attach(pair.first->source, "%s clause was specified here"_en_US,
+            firstName);
+  }
+}
+
+void OmpStructureChecker::CheckClauses(parser::OmpDirectiveName dirName,
+    llvm::iterator_range<ClauseIterator> beginClauses,
+    llvm::iterator_range<ClauseIterator> endClauses) {
+  unsigned version{context_.langOptions().OpenMPVersion};
+  llvm::omp::Directive dirId{dirName.v};
+  std::vector<const parser::OmpClause *> allClauses;
+
+  auto addClause{[&](const parser::OmpClause &clause) {
+    llvm::omp::Clause clauseId{clause.Id()};
+    AddClauseToCrtContext(clauseId);
+    SetContextClause(clause);
+    SetContextClauseInfo(clauseId);
+    allClauses.push_back(&clause);
+  }};
+
+  for (const parser::OmpClause &clause : beginClauses) {
+    addClause(clause);
+  }
+  for (const parser::OmpClause &clause : endClauses) {
+    llvm::omp::Clause clauseId{clause.Id()};
+    if (llvm::omp::isEndClause(clauseId)) {
+      addClause(clause);
+    } else {
+      context_.Say(clause.source,
+          "%s clause is not allowed on an end-directive"_err_en_US,
----------------
abidh wrote:

Ultra nit: could we use the directive name with end instead of generic end-directive.

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


More information about the flang-commits mailing list