[flang-commits] [flang] a2ec5c6 - [flang][OpenMP] More detailed checks for argument list items in clauses (#201334)

via flang-commits flang-commits at lists.llvm.org
Tue Jun 9 08:11:29 PDT 2026


Author: Krzysztof Parzyszek
Date: 2026-06-09T10:11:24-05:00
New Revision: a2ec5c68ba8767c5dc1266946663c8715389da66

URL: https://github.com/llvm/llvm-project/commit/a2ec5c68ba8767c5dc1266946663c8715389da66
DIFF: https://github.com/llvm/llvm-project/commit/a2ec5c68ba8767c5dc1266946663c8715389da66.diff

LOG: [flang][OpenMP] More detailed checks for argument list items in clauses (#201334)

For clauses that take list of variable, locator, and extended list
items, perform checks that the actual arguments meet the corresponding
requirements. This is version-based, since clause requirements have
changed over time.

Added: 
    

Modified: 
    flang/include/flang/Semantics/openmp-utils.h
    flang/lib/Semantics/check-omp-structure.cpp
    flang/lib/Semantics/check-omp-structure.h
    flang/lib/Semantics/openmp-utils.cpp
    flang/test/Semantics/OpenMP/copyprivate04.f90
    flang/test/Semantics/OpenMP/copyprivate05.f90
    flang/test/Semantics/OpenMP/declare-target01.f90
    flang/test/Semantics/OpenMP/from-clause-v45.f90
    flang/test/Semantics/OpenMP/from-clause-v51.f90
    flang/test/Semantics/OpenMP/in-reduction.f90
    flang/test/Semantics/OpenMP/lastprivate01.f90
    flang/test/Semantics/OpenMP/name-conflict.f90
    flang/test/Semantics/OpenMP/named-constants.f90
    flang/test/Semantics/OpenMP/reduction04.f90
    flang/test/Semantics/OpenMP/reduction16.f90
    flang/test/Semantics/OpenMP/task-reduction.f90
    flang/test/Semantics/OpenMP/to-clause-v45.f90
    flang/test/Semantics/OpenMP/to-clause-v51.f90

Removed: 
    


################################################################################
diff  --git a/flang/include/flang/Semantics/openmp-utils.h b/flang/include/flang/Semantics/openmp-utils.h
index 1ef8f9616ce64..7d7aa788e3f4d 100644
--- a/flang/include/flang/Semantics/openmp-utils.h
+++ b/flang/include/flang/Semantics/openmp-utils.h
@@ -97,12 +97,20 @@ bool IsCommonBlock(const Symbol &sym);
 bool IsExtendedListItem(const Symbol &sym);
 bool IsVariableListItem(const Symbol &sym);
 bool IsTypeParamInquiry(const Symbol &sym);
+bool IsComplexPart(const Symbol &sym);
 bool IsStructureComponent(const Symbol &sym);
 bool IsPrivatizable(const Symbol &sym);
 bool IsVarOrFunctionRef(const MaybeExpr &expr);
 
 bool IsWholeAssumedSizeArray(const parser::OmpObject &object);
 
+bool IsExtendedListItem(
+    const parser::OmpObject &object, SemanticsContext *semaCtx);
+bool IsLocatorListItem(
+    const parser::OmpObject &object, SemanticsContext *semaCtx);
+bool IsVariableListItem(
+    const parser::OmpObject &object, SemanticsContext *semaCtx);
+
 const Symbol *GetHostSymbol(const Symbol &sym);
 
 bool IsMapEnteringType(parser::OmpMapType::Value type);
@@ -161,6 +169,23 @@ bool IsPointerAssignment(const evaluate::Assignment &x);
 
 MaybeExpr MakeEvaluateExpr(const parser::OmpStylizedInstance &inp);
 
+enum struct ListItemKind : uint32_t {
+  Depend,
+  DirectiveName,
+  DirectiveSpecification,
+  Extended,
+  IntegerExpression,
+  Interop,
+  Locator,
+  Operation,
+  Parameter,
+  ProcedureArgument,
+  Variable,
+};
+
+std::optional<ListItemKind> GetArgumentListItemKind(
+    llvm::omp::Clause clause, unsigned version);
+
 bool IsLoopTransforming(llvm::omp::Directive dir);
 bool HasDataEnvironment(llvm::omp::Directive dir);
 

diff  --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index b6d64475c6c77..ea15d199192e7 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -424,12 +424,6 @@ void OmpStructureChecker::AnalyzeObject(const parser::OmpObject &object) {
       object.u);
 }
 
-void OmpStructureChecker::AnalyzeObjects(const parser::OmpObjectList &objects) {
-  for (const parser::OmpObject &object : objects.v) {
-    AnalyzeObject(object);
-  }
-}
-
 const parser::OpenMPConstruct *
 OmpStructureChecker::GetCurrentConstruct() const {
   for (const LoopOrConstruct &c : llvm::reverse(constructStack_)) {
@@ -622,12 +616,119 @@ bool OmpStructureChecker::HasRequires(llvm::omp::Clause req) {
       DEREF(unit.symbol()).details());
 }
 
-void OmpStructureChecker::CheckVariableListItem(
-    const SymbolSourceMap &symbols) {
-  for (auto &[symbol, source] : symbols) {
-    if (!IsVariableListItem(*symbol)) {
-      context_.SayWithDecl(
-          *symbol, source, "'%s' must be a variable"_err_en_US, symbol->name());
+void OmpStructureChecker::CheckArgumentObjectKind(const parser::OmpClause &x) {
+  unsigned version{context_.langOptions().OpenMPVersion};
+  llvm::omp::Directive dirId{GetContext().directive};
+  llvm::omp::Clause clauseId{x.Id()};
+
+  // Filter out clauses that don't take OmpObjectList.
+  auto argType{GetArgumentListItemKind(clauseId, version)};
+  if (!argType) {
+    return;
+  }
+  switch (*argType) {
+  case ListItemKind::Extended:
+  case ListItemKind::Locator:
+  case ListItemKind::Variable:
+    break;
+  default:
+    return;
+  }
+
+  // Corner cases:
+  if (clauseId == llvm::omp::Clause::OMPC_to) {
+    //                      4.5       5+
+    // TO (declare target)  extended  extended
+    // TO (target update)   variable  locator
+    if (dirId == llvm::omp::Directive::OMPD_declare_target) {
+      argType = ListItemKind::Extended;
+    } else {
+      assert(dirId == llvm::omp::Directive::OMPD_target_update &&
+          "Unexpected directive");
+      argType = version < 50 ? ListItemKind::Variable : ListItemKind::Locator;
+    }
+  } else if (clauseId == llvm::omp::Clause::OMPC_uniform) {
+    //          4.5       5+
+    // UNIFORM  variable  parameter
+    // The uniform clause takes std::list<Name> at the moment and cannot
+    // be verified here.
+    return;
+  } else if (clauseId == llvm::omp::Clause::OMPC_depend) {
+    //          6.0-              6.1+
+    // DEPEND   locator/doacross  depend
+    if (version >= 61) {
+      return;
+    }
+    // The DEPEND clause with SINK/SOURCE will not have an object list.
+    if (auto *depend{parser::Unwrap<parser::OmpDependClause>(x)}) {
+      if (parser::Unwrap<parser::OmpDoacross>(*depend)) {
+        return;
+      }
+    }
+  }
+
+  // Named constants are OK to be used within 'shared' and 'firstprivate'
+  // clauses. The check for this happens a few lines below.
+  bool NamedConstantAllowed{false};
+  switch (clauseId) {
+  case llvm::omp::Clause::OMPC_shared:
+  case llvm::omp::Clause::OMPC_firstprivate:
+    NamedConstantAllowed = true;
+    break;
+  default:
+    break;
+  }
+
+  for (auto &object : DEREF(GetOmpObjectList(x)).v) {
+    AnalyzeObject(object);
+    // substring
+    const Symbol *symbol{GetObjectSymbol(object, /*ultimate=*/true)};
+    if (symbol == nullptr) {
+      // This may happen with a blank common block. Skip these cases.
+      continue;
+    }
+    auto source{*parser::omp::GetObjectSource(object)};
+    if (NamedConstantAllowed && IsNamedConstant(*symbol)) {
+      continue;
+    }
+    // Emit a more user-friendly diagnostic than "'kind' must be a variable
+    // list item" for x%kind, or for cplx%re.
+    if (IsTypeParamInquiry(*symbol)) {
+      context_.Say(source,
+          "Type parameter inquiry is not allowed as a list item on %s clause"_err_en_US,
+          parser::omp::GetUpperName(clauseId, version));
+      continue;
+    }
+    if (IsComplexPart(*symbol)) {
+      // We have been tolerating complex part designators.
+      continue;
+    }
+
+    const char *neededType{nullptr};
+
+    switch (*argType) {
+    case ListItemKind::Extended:
+      if (!IsExtendedListItem(object, &context_)) {
+        neededType = "an extended";
+      }
+      break;
+    case ListItemKind::Locator:
+      if (!IsLocatorListItem(object, &context_)) {
+        neededType = "a locator";
+      }
+      break;
+    case ListItemKind::Variable:
+      if (!IsVariableListItem(object, &context_)) {
+        neededType = "a variable";
+      }
+      break;
+    default:
+      break;
+    }
+
+    if (neededType) {
+      context_.SayWithDecl(*symbol, source,
+          "'%s' must be %s list item"_err_en_US, symbol->name(), neededType);
     }
   }
 }
@@ -2383,7 +2484,6 @@ void OmpStructureChecker::Leave(const parser::OmpDeclareTargetDirective &x) {
                   std::is_same_v<TypeC, parser::OmpClause::To>) {
                 auto &objList{*GetOmpObjectList(c)};
                 CheckSymbolNames(dirName.source, objList);
-                CheckTypeParamInquiry(dirName.source, objList);
                 CheckVarIsNotPartOfAnotherVar(dirName.source, objList);
                 CheckThreadprivateOrDeclareTargetVar(objList);
               }
@@ -3625,44 +3725,7 @@ void OmpStructureChecker::Leave(const parser::OmpClauseList &x) {
 
 void OmpStructureChecker::Enter(const parser::OmpClause &x) {
   SetContextClause(x);
-
-  llvm::omp::Clause id{x.Id()};
-  // The visitors for these clauses do their own checks.
-  switch (id) {
-  case llvm::omp::Clause::OMPC_copyprivate:
-  case llvm::omp::Clause::OMPC_enter:
-  case llvm::omp::Clause::OMPC_lastprivate:
-  case llvm::omp::Clause::OMPC_reduction:
-  case llvm::omp::Clause::OMPC_to:
-    return;
-  default:
-    break;
-  }
-
-  // Named constants are OK to be used within 'shared' and 'firstprivate'
-  // clauses.  The check for this happens a few lines below.
-  bool SharedOrFirstprivate = false;
-  switch (id) {
-  case llvm::omp::Clause::OMPC_shared:
-  case llvm::omp::Clause::OMPC_firstprivate:
-    SharedOrFirstprivate = true;
-    break;
-  default:
-    break;
-  }
-
-  if (const parser::OmpObjectList *objList{GetOmpObjectList(x)}) {
-    AnalyzeObjects(*objList);
-    SymbolSourceMap symbols;
-    GetSymbolsInObjectList(*objList, symbols);
-    for (const auto &[symbol, source] : symbols) {
-      if (!IsVariableListItem(*symbol) &&
-          !(IsNamedConstant(*symbol) && SharedOrFirstprivate)) {
-        context_.SayWithDecl(*symbol, source,
-            "'%s' must be a variable"_err_en_US, symbol->name());
-      }
-    }
-  }
+  CheckArgumentObjectKind(x);
 }
 
 // Restrictions specific to each clause are implemented apart from the
@@ -3882,17 +3945,6 @@ void OmpStructureChecker::CheckReductionObjects(
         }
       }
     }
-    // Type parameter inquiries are not allowed.
-    for (const parser::OmpObject &object : objects.v) {
-      if (auto *symbol{GetObjectSymbol(object)}) {
-        if (IsTypeParamInquiry(*symbol)) {
-          auto source{GetObjectSource(object)};
-          context_.Say(source ? *source : GetContext().clauseSource,
-              "Type parameter inquiry is not permitted in %s clause"_err_en_US,
-              parser::omp::GetUpperName(clauseId, version));
-        }
-      }
-    }
   }
 }
 
@@ -4174,15 +4226,14 @@ void OmpStructureChecker::CheckSharedBindingInOuterContext(
 
 void OmpStructureChecker::Enter(const parser::OmpClause::Shared &x) {
   CheckAllowedClause(llvm::omp::Clause::OMPC_shared);
-  CheckTypeParamInquiry(GetContext().clauseSource, x.v);
   CheckVarIsNotPartOfAnotherVar(GetContext().clauseSource, x.v, "SHARED");
   CheckCrayPointee(x.v, "SHARED");
 }
+
 void OmpStructureChecker::Enter(const parser::OmpClause::Private &x) {
   SymbolSourceMap symbols;
   GetSymbolsInObjectList(x.v, symbols);
   CheckAllowedClause(llvm::omp::Clause::OMPC_private);
-  CheckTypeParamInquiry(GetContext().clauseSource, x.v);
   CheckVarIsNotPartOfAnotherVar(GetContext().clauseSource, x.v, "PRIVATE");
   CheckIntentInPointer(symbols, llvm::omp::Clause::OMPC_private);
   CheckCrayPointee(x.v, "PRIVATE");
@@ -4231,7 +4282,8 @@ void OmpStructureChecker::CheckVarIsNotPartOfAnotherVar(
   }
 
   if (report || parser::Unwrap<parser::ArrayElement>(object)) {
-    if (llvm::omp::nonPartialVarSet.test(GetContext().directive)) {
+    if (clause.empty() &&
+        llvm::omp::nonPartialVarSet.test(GetContext().directive)) {
       context_.Say(source,
           "A variable that is part of another variable (as an array or structure element) cannot appear on the %s directive"_err_en_US,
           ContextDirectiveAsFortran());
@@ -4246,7 +4298,6 @@ void OmpStructureChecker::CheckVarIsNotPartOfAnotherVar(
 void OmpStructureChecker::Enter(const parser::OmpClause::Firstprivate &x) {
   CheckAllowedClause(llvm::omp::Clause::OMPC_firstprivate);
 
-  CheckTypeParamInquiry(GetContext().clauseSource, x.v);
   CheckVarIsNotPartOfAnotherVar(GetContext().clauseSource, x.v, "FIRSTPRIVATE");
   CheckCrayPointee(x.v, "FIRSTPRIVATE");
 
@@ -4451,7 +4502,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Detach &x) {
     CheckAllowedClause(llvm::omp::Clause::OMPC_detach);
   }
 
-  CheckTypeParamInquiry(GetContext().clauseSource, x.v.v);
   // OpenMP 5.2: 12.5.2 Detach clause restrictions
   if (version >= 52) {
     CheckVarIsNotPartOfAnotherVar(GetContext().clauseSource, x.v.v, "DETACH");
@@ -4907,7 +4957,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Copyprivate &x) {
   CheckAllowedClause(llvm::omp::Clause::OMPC_copyprivate);
   SymbolSourceMap symbols;
   GetSymbolsInObjectList(x.v, symbols);
-  CheckVariableListItem(symbols);
   CheckIntentInPointer(symbols, llvm::omp::Clause::OMPC_copyprivate);
   CheckCopyingPolymorphicAllocatable(
       symbols, llvm::omp::Clause::OMPC_copyprivate);
@@ -4917,7 +4966,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
   CheckAllowedClause(llvm::omp::Clause::OMPC_lastprivate);
 
   const auto &objectList{*GetOmpObjectList(x)};
-  CheckTypeParamInquiry(GetContext().clauseSource, objectList);
   CheckVarIsNotPartOfAnotherVar(
       GetContext().clauseSource, objectList, "LASTPRIVATE");
   CheckCrayPointee(objectList, "LASTPRIVATE");
@@ -5159,18 +5207,8 @@ void OmpStructureChecker::Enter(const parser::OmpClause::HasDeviceAddr &x) {
 
 void OmpStructureChecker::Enter(const parser::OmpClause::Enter &x) {
   CheckAllowedClause(llvm::omp::Clause::OMPC_enter);
-  if (!OmpVerifyModifiers(
-          x.v, llvm::omp::OMPC_enter, GetContext().clauseSource, context_)) {
-    return;
-  }
-  SymbolSourceMap symbols;
-  GetSymbolsInObjectList(*GetOmpObjectList(x), symbols);
-  for (const auto &[symbol, source] : symbols) {
-    if (!IsExtendedListItem(*symbol)) {
-      context_.SayWithDecl(*symbol, source,
-          "'%s' must be a variable or a procedure"_err_en_US, symbol->name());
-    }
-  }
+  OmpVerifyModifiers(
+      x.v, llvm::omp::OMPC_enter, GetContext().clauseSource, context_);
 }
 
 void OmpStructureChecker::Enter(const parser::OmpClause::From &x) {
@@ -5188,10 +5226,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::From &x) {
   }
 
   const auto &objList{*GetOmpObjectList(x)};
-  SymbolSourceMap symbols;
-  GetSymbolsInObjectList(objList, symbols);
-  CheckVariableListItem(symbols);
-
   // Ref: [4.5:109:19]
   // If a list item is an array section it must specify contiguous storage.
   if (version <= 45) {
@@ -5228,10 +5262,6 @@ void OmpStructureChecker::Enter(const parser::OmpClause::To &x) {
   }
 
   const auto &objList{*GetOmpObjectList(x)};
-  SymbolSourceMap symbols;
-  GetSymbolsInObjectList(objList, symbols);
-  CheckVariableListItem(symbols);
-
   // Ref: [4.5:109:19]
   // If a list item is an array section it must specify contiguous storage.
   if (version <= 45) {
@@ -5465,6 +5495,9 @@ void OmpStructureChecker::CheckDefinableObjects(
     SymbolSourceMap &symbols, const llvm::omp::Clause clause) {
   unsigned version{context_.langOptions().OpenMPVersion};
   for (auto &[symbol, source] : symbols) {
+    if (!IsVariableListItem(*symbol)) {
+      continue;
+    }
     if (auto msg{WhyNotDefinable(source, context_.FindScope(source),
             DefinabilityFlags{}, *symbol)}) {
       context_

diff  --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 8a85f489eeb4c..fecacf0f891f2 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -289,12 +289,11 @@ class OmpStructureChecker : public OmpStructureCheckerBase {
   // check-omp-structure.cpp
   bool IsAllowedClause(llvm::omp::Clause clauseId);
   bool CheckAllowedClause(llvm::omp::Clause clause);
-  void CheckVariableListItem(const SymbolSourceMap &symbols);
+  void CheckArgumentObjectKind(const parser::OmpClause &x);
   void CheckDirectiveSpelling(
       parser::CharBlock spelling, llvm::omp::Directive id);
   void CheckDirectiveDeprecation(const parser::OpenMPConstruct &x);
   void AnalyzeObject(const parser::OmpObject &object);
-  void AnalyzeObjects(const parser::OmpObjectList &objects);
 
   const parser::OpenMPConstruct *GetCurrentConstruct() const;
   void CheckSourceLabel(const parser::Label &);

diff  --git a/flang/lib/Semantics/openmp-utils.cpp b/flang/lib/Semantics/openmp-utils.cpp
index 633ec2ae45aaa..a747bde8d3346 100644
--- a/flang/lib/Semantics/openmp-utils.cpp
+++ b/flang/lib/Semantics/openmp-utils.cpp
@@ -156,7 +156,8 @@ bool IsCommonBlock(const Symbol &sym) {
 }
 
 bool IsVariableListItem(const Symbol &sym) {
-  return evaluate::IsVariable(sym) || sym.attrs().test(Attr::POINTER);
+  return evaluate::IsVariable(sym) || IsCommonBlock(sym) ||
+      sym.attrs().test(Attr::POINTER);
 }
 
 bool IsExtendedListItem(const Symbol &sym) {
@@ -176,6 +177,14 @@ bool IsTypeParamInquiry(const Symbol &sym) {
       sym.details());
 }
 
+bool IsComplexPart(const Symbol &sym) {
+  if (auto *misc{sym.detailsIf<MiscDetails>()}) {
+    return misc->kind() == MiscDetails::Kind::ComplexPartRe ||
+        misc->kind() == MiscDetails::Kind::ComplexPartIm;
+  }
+  return false;
+}
+
 bool IsStructureComponent(const Symbol &sym) {
   return sym.owner().kind() == Scope::Kind::DerivedType;
 }
@@ -219,6 +228,38 @@ bool IsWholeAssumedSizeArray(const parser::OmpObject &object) {
   return false;
 }
 
+bool IsExtendedListItem(
+    const parser::OmpObject &object, SemanticsContext *semaCtx) {
+  if (IsVariableListItem(object, semaCtx)) {
+    return true;
+  }
+  if (auto *sym{GetObjectSymbol(object, /*ultimate=*/true)}) {
+    return IsProcedure(*sym);
+  }
+  return false;
+}
+
+bool IsLocatorListItem(
+    const parser::OmpObject &object, SemanticsContext *semaCtx) {
+  if (IsVariableListItem(object, semaCtx)) {
+    return true;
+  }
+  if (auto *desg{parser::Unwrap<parser::Designator>(object)}) {
+    evaluate::ExpressionAnalyzer ea(*semaCtx);
+    auto restorer{ea.GetContextualMessages().DiscardMessages()};
+    return IsVarOrFunctionRef(ea.Analyze(*desg));
+  }
+  return false;
+}
+
+bool IsVariableListItem(
+    const parser::OmpObject &object, SemanticsContext *semaCtx) {
+  if (auto *sym{GetObjectSymbol(object, /*ultimate=*/true)}) {
+    return IsVariableListItem(*sym);
+  }
+  return false;
+}
+
 const Symbol *GetHostSymbol(const Symbol &sym) {
   if (auto *details{sym.detailsIf<HostAssocDetails>()}) {
     return &details->symbol();
@@ -556,6 +597,188 @@ MaybeExpr MakeEvaluateExpr(const parser::OmpStylizedInstance &inp) {
       instance.u);
 }
 
+/// For clauses that take argument lists, return the type of the argument
+/// list item. For other clauses return std::nullopt.
+std::optional<ListItemKind> GetArgumentListItemKind(
+    llvm::omp::Clause clause, unsigned version) {
+  switch (clause) {
+  case llvm::omp::Clause::OMPC_absent:
+    if (version >= 51) {
+      return ListItemKind::DirectiveName;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_adjust_args:
+    if (version >= 61) {
+      return ListItemKind::ProcedureArgument;
+    }
+    if (version >= 51) {
+      return ListItemKind::Parameter;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_affinity:
+    if (version >= 50) {
+      return ListItemKind::Locator;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_aligned:
+    return ListItemKind::Variable;
+  case llvm::omp::Clause::OMPC_allocate:
+    if (version >= 50) {
+      return ListItemKind::Variable;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_append_args:
+    if (version >= 51) {
+      return ListItemKind::Operation;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_apply:
+    if (version >= 60) {
+      return ListItemKind::DirectiveSpecification;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_contains:
+    if (version >= 51) {
+      return ListItemKind::DirectiveName;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_copyin:
+    return ListItemKind::Variable;
+  case llvm::omp::Clause::OMPC_copyprivate:
+    return ListItemKind::Variable;
+  case llvm::omp::Clause::OMPC_counts:
+    if (version >= 60) {
+      return ListItemKind::IntegerExpression;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_depend:
+    if (version >= 61) {
+      return ListItemKind::Depend;
+    }
+    if (version >= 50) {
+      return ListItemKind::Locator;
+    }
+    return ListItemKind::Variable;
+  case llvm::omp::Clause::OMPC_enter:
+    if (version >= 52) {
+      return ListItemKind::Extended;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_exclusive:
+    if (version >= 50) {
+      return ListItemKind::Variable;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_firstprivate:
+    return ListItemKind::Variable;
+  case llvm::omp::Clause::OMPC_from:
+    if (version >= 50) {
+      return ListItemKind::Locator;
+    }
+    return ListItemKind::Variable;
+  case llvm::omp::Clause::OMPC_has_device_addr:
+    if (version >= 51) {
+      return ListItemKind::Variable;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_in_reduction:
+    if (version >= 50) {
+      return ListItemKind::Variable;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_inclusive:
+    if (version >= 50) {
+      return ListItemKind::Variable;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_induction:
+    if (version >= 60) {
+      return ListItemKind::Variable;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_interop:
+    if (version >= 60) {
+      return ListItemKind::Interop;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_is_device_ptr:
+    return ListItemKind::Variable;
+  case llvm::omp::Clause::OMPC_lastprivate:
+    return ListItemKind::Variable;
+  case llvm::omp::Clause::OMPC_linear:
+    return ListItemKind::Variable;
+  case llvm::omp::Clause::OMPC_link:
+    return ListItemKind::Variable;
+  case llvm::omp::Clause::OMPC_local:
+    if (version >= 60) {
+      return ListItemKind::Variable;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_map:
+    if (version >= 50) {
+      return ListItemKind::Locator;
+    }
+    return ListItemKind::Variable;
+  case llvm::omp::Clause::OMPC_nontemporal:
+    if (version >= 50) {
+      return ListItemKind::Variable;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_num_threads:
+    if (version >= 60) {
+      return ListItemKind::IntegerExpression;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_permutation:
+    if (version >= 60) {
+      return ListItemKind::IntegerExpression;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_private:
+    return ListItemKind::Variable;
+  case llvm::omp::Clause::OMPC_reduction:
+    return ListItemKind::Variable;
+  case llvm::omp::Clause::OMPC_shared:
+    return ListItemKind::Variable;
+  // TODO 6.1
+  // case llvm::omp::Clause::OMPC_shift:
+  //   if (version >= 61) {
+  //     return ListItemKind::IntegerExpression;
+  //   }
+  //   break;
+  case llvm::omp::Clause::OMPC_sizes:
+    if (version >= 51) {
+      return ListItemKind::IntegerExpression;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_task_reduction:
+    if (version >= 50) {
+      return ListItemKind::Variable;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_to:
+    if (version >= 50) {
+      return ListItemKind::Locator;
+    }
+    return ListItemKind::Extended;
+  case llvm::omp::Clause::OMPC_uniform:
+    if (version >= 50) {
+      return ListItemKind::Parameter;
+    }
+    return ListItemKind::Variable;
+  case llvm::omp::Clause::OMPC_use_device_addr:
+    if (version >= 50) {
+      return ListItemKind::Variable;
+    }
+    break;
+  case llvm::omp::Clause::OMPC_use_device_ptr:
+    return ListItemKind::Variable;
+  default:
+    break;
+  }
+  return std::nullopt;
+}
+
 bool IsLoopTransforming(llvm::omp::Directive dir) {
   switch (dir) {
   // TODO case llvm::omp::Directive::OMPD_flatten:

diff  --git a/flang/test/Semantics/OpenMP/copyprivate04.f90 b/flang/test/Semantics/OpenMP/copyprivate04.f90
index 8d7800229bc5f..56e37c3a5df1c 100644
--- a/flang/test/Semantics/OpenMP/copyprivate04.f90
+++ b/flang/test/Semantics/OpenMP/copyprivate04.f90
@@ -70,7 +70,7 @@ program omp_copyprivate
   ! Named constants are shared.
   !$omp single
   !ERROR: COPYPRIVATE variable 'pi' is not PRIVATE or THREADPRIVATE in outer context
-  !ERROR: 'pi' must be a variable
+  !ERROR: 'pi' must be a variable list item
   !$omp end single copyprivate(pi)
 
   !$omp parallel do

diff  --git a/flang/test/Semantics/OpenMP/copyprivate05.f90 b/flang/test/Semantics/OpenMP/copyprivate05.f90
index 129f8f0b5144e..222628d3e65d9 100644
--- a/flang/test/Semantics/OpenMP/copyprivate05.f90
+++ b/flang/test/Semantics/OpenMP/copyprivate05.f90
@@ -6,7 +6,7 @@ subroutine f00
   type t
   end type
 
-!ERROR: 't' must be a variable
+!ERROR: 't' must be a variable list item
 !$omp single copyprivate(t)
 !$omp end single
 end

diff  --git a/flang/test/Semantics/OpenMP/declare-target01.f90 b/flang/test/Semantics/OpenMP/declare-target01.f90
index 9bbd66ad5ec43..ddd48c5a96820 100644
--- a/flang/test/Semantics/OpenMP/declare-target01.f90
+++ b/flang/test/Semantics/OpenMP/declare-target01.f90
@@ -75,18 +75,18 @@ module declare_target01
   !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
   !$omp declare target enter (my_var%t_arr)
 
-  !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+  !ERROR: Type parameter inquiry is not allowed as a list item on TO clause
   !WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-usage]
   !$omp declare target to (my_var%kind_param)
 
-  !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+  !ERROR: Type parameter inquiry is not allowed as a list item on ENTER clause
   !$omp declare target enter (my_var%kind_param)
 
-  !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+  !ERROR: Type parameter inquiry is not allowed as a list item on TO clause
   !WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-usage]
   !$omp declare target to (my_var%len_param)
 
-  !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+  !ERROR: Type parameter inquiry is not allowed as a list item on ENTER clause
   !$omp declare target enter (my_var%len_param)
 
   !WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-usage]
@@ -113,25 +113,25 @@ module declare_target01
   !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
   !$omp declare target enter (arr(1:2))
 
-  !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+  !ERROR: Type parameter inquiry is not allowed as a list item on TO clause
   !WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-usage]
   !$omp declare target to (x%KIND)
 
-  !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+  !ERROR: Type parameter inquiry is not allowed as a list item on ENTER clause
   !$omp declare target enter (x%KIND)
 
-  !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+  !ERROR: Type parameter inquiry is not allowed as a list item on TO clause
   !WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-usage]
   !$omp declare target to (w%LEN)
 
-  !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+  !ERROR: Type parameter inquiry is not allowed as a list item on ENTER clause
   !$omp declare target enter (w%LEN)
 
-  !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+  !ERROR: Type parameter inquiry is not allowed as a list item on TO clause
   !WARNING: The usage of TO clause on DECLARE TARGET directive has been deprecated. Use ENTER clause instead. [-Wopenmp-usage]
   !$omp declare target to (y%KIND)
 
-  !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+  !ERROR: Type parameter inquiry is not allowed as a list item on ENTER clause
   !$omp declare target enter (y%KIND)
 
   !$omp declare target link (my_var2)
@@ -144,10 +144,10 @@ module declare_target01
   !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
   !$omp declare target link (my_var2%t_arr)
 
-  !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+  !ERROR: Type parameter inquiry is not allowed as a list item on LINK clause
   !$omp declare target link (my_var2%kind_param)
 
-  !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+  !ERROR: Type parameter inquiry is not allowed as a list item on LINK clause
   !$omp declare target link (my_var2%len_param)
 
   !$omp declare target link (arr2)
@@ -158,12 +158,12 @@ module declare_target01
   !ERROR: A variable that is part of another variable (as an array or structure element) cannot appear on the DECLARE TARGET directive
   !$omp declare target link (arr2(1:2))
 
-  !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+  !ERROR: Type parameter inquiry is not allowed as a list item on LINK clause
   !$omp declare target link (x2%KIND)
 
-  !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+  !ERROR: Type parameter inquiry is not allowed as a list item on LINK clause
   !$omp declare target link (w2%LEN)
 
-  !ERROR: A type parameter inquiry cannot appear on the DECLARE TARGET directive
+  !ERROR: Type parameter inquiry is not allowed as a list item on LINK clause
   !$omp declare target link (y2%KIND)
 end

diff  --git a/flang/test/Semantics/OpenMP/from-clause-v45.f90 b/flang/test/Semantics/OpenMP/from-clause-v45.f90
index 201128fc3031c..654af4b7dd9b7 100644
--- a/flang/test/Semantics/OpenMP/from-clause-v45.f90
+++ b/flang/test/Semantics/OpenMP/from-clause-v45.f90
@@ -28,6 +28,6 @@ subroutine f03(x)
 end
 
 subroutine f04
-!ERROR: 'f04' must be a variable
+!ERROR: 'f04' must be a variable list item
   !$omp target update from(f04)
 end

diff  --git a/flang/test/Semantics/OpenMP/from-clause-v51.f90 b/flang/test/Semantics/OpenMP/from-clause-v51.f90
index 70c00823d073e..8771f519fec03 100644
--- a/flang/test/Semantics/OpenMP/from-clause-v51.f90
+++ b/flang/test/Semantics/OpenMP/from-clause-v51.f90
@@ -13,6 +13,6 @@ subroutine f03(x)
 end
 
 subroutine f04
-!ERROR: 'f04' must be a variable
+!ERROR: 'f04' must be a locator list item
   !$omp target update from(f04)
 end

diff  --git a/flang/test/Semantics/OpenMP/in-reduction.f90 b/flang/test/Semantics/OpenMP/in-reduction.f90
index c3fe7fee73c24..0472774704334 100644
--- a/flang/test/Semantics/OpenMP/in-reduction.f90
+++ b/flang/test/Semantics/OpenMP/in-reduction.f90
@@ -66,7 +66,7 @@ subroutine f07
 
 subroutine f08
   integer :: x
-!ERROR: Type parameter inquiry is not permitted in IN_REDUCTION clause
+!ERROR: Type parameter inquiry is not allowed as a list item on IN_REDUCTION clause
 !$omp target in_reduction(+: x%kind)
 !$omp end target
 end

diff  --git a/flang/test/Semantics/OpenMP/lastprivate01.f90 b/flang/test/Semantics/OpenMP/lastprivate01.f90
index 4fae4829d8862..4248a34e702c7 100644
--- a/flang/test/Semantics/OpenMP/lastprivate01.f90
+++ b/flang/test/Semantics/OpenMP/lastprivate01.f90
@@ -15,8 +15,7 @@ program omp_lastprivate
   a = 10
   b = 20
 
-  !ERROR: Variable 'k' on the LASTPRIVATE clause is not definable
-  !BECAUSE: 'k' is not a variable
+  !ERROR: 'k' must be a variable list item
   !$omp parallel do lastprivate(k)
   do i = 1, 10
     c(i) = a(i) + b(i) + k

diff  --git a/flang/test/Semantics/OpenMP/name-conflict.f90 b/flang/test/Semantics/OpenMP/name-conflict.f90
index 5babc3c6d3886..267e9774e3e4b 100644
--- a/flang/test/Semantics/OpenMP/name-conflict.f90
+++ b/flang/test/Semantics/OpenMP/name-conflict.f90
@@ -5,7 +5,7 @@ module m
 
 subroutine foo1()
   integer :: baz1
-!ERROR: 'baz1' must be a variable
+!ERROR: 'baz1' must be a variable list item
 !$omp parallel do shared(baz1)
   baz1: do i = 1, 100
   enddo baz1
@@ -14,7 +14,7 @@ subroutine foo1()
 
 subroutine foo2()
   !implicit baz2
-!ERROR: 'baz2' must be a variable
+!ERROR: 'baz2' must be a variable list item
 !$omp parallel do shared(baz2)
   baz2: do i = 1, 100
   enddo baz2

diff  --git a/flang/test/Semantics/OpenMP/named-constants.f90 b/flang/test/Semantics/OpenMP/named-constants.f90
index ac0850066cebe..759560e0a495c 100644
--- a/flang/test/Semantics/OpenMP/named-constants.f90
+++ b/flang/test/Semantics/OpenMP/named-constants.f90
@@ -33,10 +33,10 @@ subroutine prvt()
         real, parameter :: m = 7.0
         logical, parameter :: l = .false.
         integer, dimension(3), parameter :: a = [1, 2, 3]
-        !ERROR: 'n' must be a variable
-        !ERROR: 'm' must be a variable
-        !ERROR: 'l' must be a variable
-        !ERROR: 'a' must be a variable
+        !ERROR: 'n' must be a variable list item
+        !ERROR: 'm' must be a variable list item
+        !ERROR: 'l' must be a variable list item
+        !ERROR: 'a' must be a variable list item
         !$omp parallel private(n, m, l, a)
             print *, n, m, l, a
         !$omp end parallel

diff  --git a/flang/test/Semantics/OpenMP/reduction04.f90 b/flang/test/Semantics/OpenMP/reduction04.f90
index e86b67b6efa96..f1c8a0de6cb19 100644
--- a/flang/test/Semantics/OpenMP/reduction04.f90
+++ b/flang/test/Semantics/OpenMP/reduction04.f90
@@ -6,8 +6,7 @@ program omp_Reduction
   integer, parameter :: k = 10
   common /c/ a, b
 
-  !ERROR: Variable 'k' on the REDUCTION clause is not definable
-  !BECAUSE: 'k' is not a variable
+  !ERROR: 'k' must be a variable list item
   !$omp parallel do reduction(+:k)
   do i = 1, 10
     l = k + 1

diff  --git a/flang/test/Semantics/OpenMP/reduction16.f90 b/flang/test/Semantics/OpenMP/reduction16.f90
index 6bb218e306128..0c92a5b9d2d6d 100644
--- a/flang/test/Semantics/OpenMP/reduction16.f90
+++ b/flang/test/Semantics/OpenMP/reduction16.f90
@@ -5,7 +5,7 @@
 
 subroutine f00
   integer :: x
-!ERROR: Type parameter inquiry is not permitted in REDUCTION clause
+!ERROR: Type parameter inquiry is not allowed as a list item on REDUCTION clause
 !$omp do reduction (+ : x%kind)
   do i = 1, 10
   end do

diff  --git a/flang/test/Semantics/OpenMP/task-reduction.f90 b/flang/test/Semantics/OpenMP/task-reduction.f90
index baa363bdd00ad..7e43332d53fe1 100644
--- a/flang/test/Semantics/OpenMP/task-reduction.f90
+++ b/flang/test/Semantics/OpenMP/task-reduction.f90
@@ -66,7 +66,7 @@ subroutine f07
 
 subroutine f08
   integer :: x
-!ERROR: Type parameter inquiry is not permitted in TASK_REDUCTION clause
+!ERROR: Type parameter inquiry is not allowed as a list item on TASK_REDUCTION clause
 !$omp taskgroup task_reduction(+: x%kind)
 !$omp end taskgroup
 end

diff  --git a/flang/test/Semantics/OpenMP/to-clause-v45.f90 b/flang/test/Semantics/OpenMP/to-clause-v45.f90
index 9797c06cdeddf..7e56817e1ff7c 100644
--- a/flang/test/Semantics/OpenMP/to-clause-v45.f90
+++ b/flang/test/Semantics/OpenMP/to-clause-v45.f90
@@ -28,6 +28,6 @@ subroutine f03(x)
 end
 
 subroutine f04
-!ERROR: 'f04' must be a variable
+!ERROR: 'f04' must be a variable list item
   !$omp target update to(f04)
 end

diff  --git a/flang/test/Semantics/OpenMP/to-clause-v51.f90 b/flang/test/Semantics/OpenMP/to-clause-v51.f90
index 8abbca3bb07cd..0db292a22238b 100644
--- a/flang/test/Semantics/OpenMP/to-clause-v51.f90
+++ b/flang/test/Semantics/OpenMP/to-clause-v51.f90
@@ -13,6 +13,6 @@ subroutine f03(x)
 end
 
 subroutine f04
-!ERROR: 'f04' must be a variable
+!ERROR: 'f04' must be a locator list item
   !$omp target update to(f04)
 end


        


More information about the flang-commits mailing list