-
Notifications
You must be signed in to change notification settings - Fork 14.4k
[flang][OpenMP] Add version checks for clauses #110015
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
The information in LangOptions is not tied to any frontend code, and could be used by any other component.
The motivation for this is to make OpenMP settings visible in the semantic checks (OpenMP version in particular).
If there is a clause that is allowed on a given directive in a later version of the OpenMP spec, report an error and provide the minimal spec version that allows the clause. The case where a clause is not allowed on a directive at all is already handled elsewhere.
@llvm/pr-subscribers-flang-semantics @llvm/pr-subscribers-flang-parser Author: Krzysztof Parzyszek (kparzysz) ChangesIf there is a clause that is allowed on a given directive in a later version of the OpenMP spec, report an error and provide the minimal spec version that allows the clause. The case where a clause is not allowed on a directive at all is already handled elsewhere. Patch is 41.30 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/110015.diff 43 Files Affected:
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index dfc3f3290a81be..976c159e252f12 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -16,25 +16,25 @@ namespace Fortran::semantics {
// Use when clause falls under 'struct OmpClause' in 'parse-tree.h'.
#define CHECK_SIMPLE_CLAUSE(X, Y) \
void OmpStructureChecker::Enter(const parser::OmpClause::X &) { \
- CheckAllowed(llvm::omp::Clause::Y); \
+ CheckAllowedClause(llvm::omp::Clause::Y); \
}
#define CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(X, Y) \
void OmpStructureChecker::Enter(const parser::OmpClause::X &c) { \
- CheckAllowed(llvm::omp::Clause::Y); \
+ CheckAllowedClause(llvm::omp::Clause::Y); \
RequiresConstantPositiveParameter(llvm::omp::Clause::Y, c.v); \
}
#define CHECK_REQ_SCALAR_INT_CLAUSE(X, Y) \
void OmpStructureChecker::Enter(const parser::OmpClause::X &c) { \
- CheckAllowed(llvm::omp::Clause::Y); \
+ CheckAllowedClause(llvm::omp::Clause::Y); \
RequiresPositiveParameter(llvm::omp::Clause::Y, c.v); \
}
// Use when clause don't falls under 'struct OmpClause' in 'parse-tree.h'.
#define CHECK_SIMPLE_PARSER_CLAUSE(X, Y) \
void OmpStructureChecker::Enter(const parser::X &) { \
- CheckAllowed(llvm::omp::Y); \
+ CheckAllowedClause(llvm::omp::Y); \
}
// 'OmpWorkshareBlockChecker' is used to check the validity of the assignment
@@ -163,6 +163,43 @@ class AssociatedLoopChecker {
std::map<std::string, std::int64_t> constructNamesAndLevels_;
};
+bool OmpStructureChecker::CheckAllowedClause(llvmOmpClause clause) {
+ unsigned version{context_.langOptions().OpenMPVersion};
+ DirectiveContext &dirCtx = GetContext();
+ llvm::omp::Directive dir{dirCtx.directive};
+
+ if (!llvm::omp::isAllowedClauseForDirective(dir, clause, version)) {
+ unsigned allowedInVersion{[&] {
+ for (unsigned v : {45, 50, 51, 52, 60}) {
+ if (v <= version) {
+ continue;
+ }
+ if (llvm::omp::isAllowedClauseForDirective(dir, clause, v)) {
+ return v;
+ }
+ }
+ return 0u;
+ }()};
+
+ auto clauseName{parser::ToUpperCaseLetters(getClauseName(clause).str())};
+ auto dirName{parser::ToUpperCaseLetters(getDirectiveName(dir).str())};
+
+ // Only report it if there is a later version that allows it.
+ // If it's not allowed at all, it will be reported by CheckAllowed.
+ if (allowedInVersion != 0) {
+ std::string thisVersion{std::to_string(version / 10) + "." +
+ std::to_string(version % 10)};
+ std::string goodVersion{std::to_string(allowedInVersion)};
+
+ context_.Say(dirCtx.clauseSource,
+ "%s clause is not allowed on directive %s in OpenMP v%s, "
+ "try -fopenmp-version=%d"_err_en_US,
+ clauseName, dirName, thisVersion, allowedInVersion);
+ }
+ }
+ return CheckAllowed(clause);
+}
+
bool OmpStructureChecker::IsCloselyNestedRegion(const OmpDirectiveSet &set) {
// Definition of close nesting:
//
@@ -1156,7 +1193,7 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclarativeAllocate &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Allocator &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_allocator);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_allocator);
// Note: Predefined allocators are stored in ScalarExpr as numbers
// whereas custom allocators are stored as strings, so if the ScalarExpr
// actually has an int value, then it must be a predefined allocator
@@ -1165,7 +1202,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Allocator &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Allocate &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_allocate);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_allocate);
if (const auto &modifier{
std::get<std::optional<parser::OmpAllocateClause::AllocateModifier>>(
x.v.t)}) {
@@ -2362,7 +2399,7 @@ CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(Simdlen, OMPC_simdlen)
// Restrictions specific to each clause are implemented apart from the
// generalized restrictions.
void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_reduction);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_reduction);
if (CheckReductionOperators(x)) {
CheckReductionTypeList(x);
}
@@ -2686,7 +2723,7 @@ void OmpStructureChecker::CheckSharedBindingInOuterContext(
}
void OmpStructureChecker::Enter(const parser::OmpClause::Ordered &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_ordered);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_ordered);
// the parameter of ordered clause is optional
if (const auto &expr{x.v}) {
RequiresConstantPositiveParameter(llvm::omp::Clause::OMPC_ordered, *expr);
@@ -2701,17 +2738,17 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Ordered &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Shared &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_shared);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_shared);
CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "SHARED");
}
void OmpStructureChecker::Enter(const parser::OmpClause::Private &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_private);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_private);
CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "PRIVATE");
CheckIntentInPointer(x.v, llvm::omp::Clause::OMPC_private);
}
void OmpStructureChecker::Enter(const parser::OmpClause::Nowait &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_nowait);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_nowait);
if (llvm::omp::noWaitClauseNotAllowedSet.test(GetContext().directive)) {
context_.Say(GetContext().clauseSource,
"%s clause is not allowed on the OMP %s directive,"
@@ -2784,7 +2821,7 @@ void OmpStructureChecker::CheckIsVarPartOfAnotherVar(
}
void OmpStructureChecker::Enter(const parser::OmpClause::Firstprivate &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_firstprivate);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_firstprivate);
CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "FIRSTPRIVATE");
CheckIsLoopIvPartOfClause(llvmOmpClause::OMPC_firstprivate, x.v);
@@ -2871,7 +2908,7 @@ void OmpStructureChecker::Leave(const parser::OmpAtomic &) {
// Restrictions specific to each clause are implemented apart from the
// generalized restrictions.
void OmpStructureChecker::Enter(const parser::OmpClause::Aligned &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_aligned);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_aligned);
if (const auto &expr{
std::get<std::optional<parser::ScalarIntConstantExpr>>(x.v.t)}) {
@@ -2880,7 +2917,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Aligned &x) {
// 2.8.1 TODO: list-item attribute check
}
void OmpStructureChecker::Enter(const parser::OmpClause::Defaultmap &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_defaultmap);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_defaultmap);
using VariableCategory = parser::OmpDefaultmapClause::VariableCategory;
if (!std::get<std::optional<VariableCategory>>(x.v.t)) {
context_.Say(GetContext().clauseSource,
@@ -2889,7 +2926,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Defaultmap &x) {
}
}
void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_if);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_if);
using dirNameModifier = parser::OmpIfClause::DirectiveNameModifier;
// TODO Check that, when multiple 'if' clauses are applied to a combined
// construct, at most one of them applies to each directive.
@@ -2925,7 +2962,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_linear);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_linear);
// 2.7 Loop Construct Restriction
if ((llvm::omp::allDoSet | llvm::omp::allSimdSet)
@@ -2959,7 +2996,7 @@ void OmpStructureChecker::CheckAllowedMapTypes(
}
void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_map);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_map);
if (const auto &maptype{std::get<std::optional<parser::OmpMapType>>(x.v.t)}) {
using Type = parser::OmpMapType::Type;
@@ -3005,7 +3042,7 @@ bool OmpStructureChecker::ScheduleModifierHasType(
return false;
}
void OmpStructureChecker::Enter(const parser::OmpClause::Schedule &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_schedule);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_schedule);
const parser::OmpScheduleClause &scheduleClause = x.v;
// 2.7 Loop Construct Restriction
@@ -3041,7 +3078,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Schedule &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Device &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_device);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_device);
const parser::OmpDeviceClause &deviceClause = x.v;
const auto &device{std::get<1>(deviceClause.t)};
RequiresPositiveParameter(
@@ -3060,7 +3097,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Device &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_depend);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_depend);
if ((std::holds_alternative<parser::OmpDependClause::Source>(x.v.u) ||
std::holds_alternative<parser::OmpDependClause::Sink>(x.v.u)) &&
GetContext().directive != llvm::omp::OMPD_ordered) {
@@ -3103,7 +3140,7 @@ void OmpStructureChecker::CheckCopyingPolymorphicAllocatable(
}
void OmpStructureChecker::Enter(const parser::OmpClause::Copyprivate &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_copyprivate);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_copyprivate);
CheckIntentInPointer(x.v, llvm::omp::Clause::OMPC_copyprivate);
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(x.v, currSymbols);
@@ -3121,7 +3158,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Copyprivate &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_lastprivate);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_lastprivate);
CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "LASTPRIVATE");
@@ -3145,7 +3182,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Copyin &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_copyin);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_copyin);
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(x.v, currSymbols);
@@ -3180,7 +3217,7 @@ void OmpStructureChecker::CheckStructureElement(
void OmpStructureChecker::Enter(const parser::OmpClause::UseDevicePtr &x) {
CheckStructureElement(x.v, llvm::omp::Clause::OMPC_use_device_ptr);
- CheckAllowed(llvm::omp::Clause::OMPC_use_device_ptr);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_use_device_ptr);
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(x.v, currSymbols);
semantics::UnorderedSymbolSet listVars;
@@ -3213,7 +3250,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::UseDevicePtr &x) {
void OmpStructureChecker::Enter(const parser::OmpClause::UseDeviceAddr &x) {
CheckStructureElement(x.v, llvm::omp::Clause::OMPC_use_device_addr);
- CheckAllowed(llvm::omp::Clause::OMPC_use_device_addr);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_use_device_addr);
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(x.v, currSymbols);
semantics::UnorderedSymbolSet listVars;
@@ -3238,7 +3275,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::UseDeviceAddr &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::IsDevicePtr &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_is_device_ptr);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_is_device_ptr);
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(x.v, currSymbols);
semantics::UnorderedSymbolSet listVars;
@@ -3276,7 +3313,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::IsDevicePtr &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::HasDeviceAddr &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_has_device_addr);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_has_device_addr);
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(x.v, currSymbols);
semantics::UnorderedSymbolSet listVars;
@@ -3621,7 +3658,7 @@ void OmpStructureChecker::Enter(
}
void OmpStructureChecker::CheckAllowedRequiresClause(llvmOmpClause clause) {
- CheckAllowed(clause);
+ CheckAllowedClause(clause);
if (clause != llvm::omp::Clause::OMPC_atomic_default_mem_order) {
// Check that it does not appear after a device construct
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 8bfd4d594b028e..605f3f05b4bc83 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -139,6 +139,7 @@ class OmpStructureChecker
}
private:
+ bool CheckAllowedClause(llvmOmpClause clause);
void CheckMultipleOccurrence(semantics::UnorderedSymbolSet &listVars,
const std::list<parser::Name> &nameList, const parser::CharBlock &item,
const std::string &clauseName);
diff --git a/flang/test/Lower/OpenMP/atomic-capture.f90 b/flang/test/Lower/OpenMP/atomic-capture.f90
index 667ae8ed7a133b..af82e4b2a20eb2 100644
--- a/flang/test/Lower/OpenMP/atomic-capture.f90
+++ b/flang/test/Lower/OpenMP/atomic-capture.f90
@@ -2,8 +2,8 @@
! This test checks the lowering of atomic capture
-! RUN: bbc %openmp_flags -emit-hlfir %s -o - | FileCheck %s
-! RUN: %flang_fc1 -emit-hlfir %openmp_flags %s -o - | FileCheck %s
+! RUN: bbc %openmp_flags -fopenmp-version=50 -emit-hlfir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir %openmp_flags -fopenmp-version=50 %s -o - | FileCheck %s
program OmpAtomicCapture
diff --git a/flang/test/Lower/OpenMP/atomic-read.f90 b/flang/test/Lower/OpenMP/atomic-read.f90
index d578df959a474d..c3270dd6c1d670 100644
--- a/flang/test/Lower/OpenMP/atomic-read.f90
+++ b/flang/test/Lower/OpenMP/atomic-read.f90
@@ -1,6 +1,6 @@
! REQUIRES: openmp_runtime
-! RUN: bbc %openmp_flags -emit-hlfir %s -o - | FileCheck %s
+! RUN: bbc %openmp_flags -fopenmp-version=50 -emit-hlfir %s -o - | FileCheck %s
! This test checks the lowering of atomic read
diff --git a/flang/test/Lower/OpenMP/atomic-update.f90 b/flang/test/Lower/OpenMP/atomic-update.f90
index 85edfdf4de84d5..16dae9d5f301c1 100644
--- a/flang/test/Lower/OpenMP/atomic-update.f90
+++ b/flang/test/Lower/OpenMP/atomic-update.f90
@@ -1,8 +1,8 @@
! REQUIRES: openmp_runtime
! This test checks lowering of atomic and atomic update constructs
-! RUN: bbc %openmp_flags -emit-hlfir %s -o - | FileCheck %s
-! RUN: %flang_fc1 -emit-hlfir %openmp_flags %s -o - | FileCheck %s
+! RUN: bbc %openmp_flags -fopenmp-version=50 -emit-hlfir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir %openmp_flags -fopenmp-version=50 %s -o - | FileCheck %s
program OmpAtomicUpdate
use omp_lib
diff --git a/flang/test/Lower/OpenMP/atomic-write.f90 b/flang/test/Lower/OpenMP/atomic-write.f90
index 8867dc59211922..b30dc483e6b845 100644
--- a/flang/test/Lower/OpenMP/atomic-write.f90
+++ b/flang/test/Lower/OpenMP/atomic-write.f90
@@ -1,6 +1,6 @@
! REQUIRES: openmp_runtime
-! RUN: bbc %openmp_flags -emit-hlfir %s -o - | FileCheck %s
+! RUN: bbc %openmp_flags -fopenmp-version=50 -emit-hlfir %s -o - | FileCheck %s
! This test checks the lowering of atomic write
diff --git a/flang/test/Lower/OpenMP/declare-target-data.f90 b/flang/test/Lower/OpenMP/declare-target-data.f90
index d86f74d18b6df0..154853a0fa20c4 100644
--- a/flang/test/Lower/OpenMP/declare-target-data.f90
+++ b/flang/test/Lower/OpenMP/declare-target-data.f90
@@ -1,5 +1,5 @@
-!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
-!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -fopenmp-is-target-device %s -o - | FileCheck %s
module test_0
implicit none
diff --git a/flang/test/Lower/OpenMP/declare-target-deferred-marking.f90 b/flang/test/Lower/OpenMP/declare-target-deferred-marking.f90
index 1998c3da23af5f..079d43e309028d 100644
--- a/flang/test/Lower/OpenMP/declare-target-deferred-marking.f90
+++ b/flang/test/Lower/OpenMP/declare-target-deferred-marking.f90
@@ -1,5 +1,5 @@
-!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s --check-prefixes ALL,HOST
-!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-device %s -o - | FileCheck %s --check-prefixes ALL
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s --check-prefixes ALL,HOST
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -fopenmp-is-device %s -o - | FileCheck %s --check-prefixes ALL
program main
use, intrinsic :: iso_c_binding
diff --git a/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90 b/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90
index 0d138321445ce6..8182e468928e22 100644
--- a/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90
+++ b/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90
@@ -1,5 +1,5 @@
-!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s --check-prefixes ALL,HOST
-!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-device %s -o - | FileCheck %s --check-prefixes ALL,DEVICE
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s --check-prefixes ALL,HOST
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -fopenmp-is-device %s -o - | FileCheck %s --check-prefixes ALL,DEVICE
! Check specification valid forms of declare target with functions
! utilising device_type and to clauses as well as the default
diff --git a/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90 b/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90
index 0ca2bcbd66a960..8035f1a65880b7 100644
--- a/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90
+++ b/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90
@@ -1,7 +1,7 @@
-!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
-!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefix=DEVICE
-!RUN: bbc -emit-hlfir -fopenmp %s -o - | FileCheck %s
-!RUN: bbc -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefix=DEVICE
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefix=DEVICE
+!RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s
+!RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=52 -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefix=DEVICE
! CHECK-LABEL: func.func @_QPimplicitly_captured_twice
! CHECK-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter)>{{.*}}}
diff --git a/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap.f90 b/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap.f90
index ffca5c3ff25000..70e4ac22f8974e 100644
--- a/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap.f90
+++ b/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap.f90
@@ -1,7 +1,7 @@
-!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
-!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefix=DEVICE
-!RUN: bbc -emit-hlfir -fopenmp %s -o - | FileCheck %s
-!RUN: bbc -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefix=DEVICE
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 %s -o - | FileCheck %s
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -fopenmp-is-target-device %s -o - | FileCheck %s --c...
[truncated]
|
@llvm/pr-subscribers-flang-openmp Author: Krzysztof Parzyszek (kparzysz) ChangesIf there is a clause that is allowed on a given directive in a later version of the OpenMP spec, report an error and provide the minimal spec version that allows the clause. The case where a clause is not allowed on a directive at all is already handled elsewhere. Patch is 41.30 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/110015.diff 43 Files Affected:
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index dfc3f3290a81be..976c159e252f12 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -16,25 +16,25 @@ namespace Fortran::semantics {
// Use when clause falls under 'struct OmpClause' in 'parse-tree.h'.
#define CHECK_SIMPLE_CLAUSE(X, Y) \
void OmpStructureChecker::Enter(const parser::OmpClause::X &) { \
- CheckAllowed(llvm::omp::Clause::Y); \
+ CheckAllowedClause(llvm::omp::Clause::Y); \
}
#define CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(X, Y) \
void OmpStructureChecker::Enter(const parser::OmpClause::X &c) { \
- CheckAllowed(llvm::omp::Clause::Y); \
+ CheckAllowedClause(llvm::omp::Clause::Y); \
RequiresConstantPositiveParameter(llvm::omp::Clause::Y, c.v); \
}
#define CHECK_REQ_SCALAR_INT_CLAUSE(X, Y) \
void OmpStructureChecker::Enter(const parser::OmpClause::X &c) { \
- CheckAllowed(llvm::omp::Clause::Y); \
+ CheckAllowedClause(llvm::omp::Clause::Y); \
RequiresPositiveParameter(llvm::omp::Clause::Y, c.v); \
}
// Use when clause don't falls under 'struct OmpClause' in 'parse-tree.h'.
#define CHECK_SIMPLE_PARSER_CLAUSE(X, Y) \
void OmpStructureChecker::Enter(const parser::X &) { \
- CheckAllowed(llvm::omp::Y); \
+ CheckAllowedClause(llvm::omp::Y); \
}
// 'OmpWorkshareBlockChecker' is used to check the validity of the assignment
@@ -163,6 +163,43 @@ class AssociatedLoopChecker {
std::map<std::string, std::int64_t> constructNamesAndLevels_;
};
+bool OmpStructureChecker::CheckAllowedClause(llvmOmpClause clause) {
+ unsigned version{context_.langOptions().OpenMPVersion};
+ DirectiveContext &dirCtx = GetContext();
+ llvm::omp::Directive dir{dirCtx.directive};
+
+ if (!llvm::omp::isAllowedClauseForDirective(dir, clause, version)) {
+ unsigned allowedInVersion{[&] {
+ for (unsigned v : {45, 50, 51, 52, 60}) {
+ if (v <= version) {
+ continue;
+ }
+ if (llvm::omp::isAllowedClauseForDirective(dir, clause, v)) {
+ return v;
+ }
+ }
+ return 0u;
+ }()};
+
+ auto clauseName{parser::ToUpperCaseLetters(getClauseName(clause).str())};
+ auto dirName{parser::ToUpperCaseLetters(getDirectiveName(dir).str())};
+
+ // Only report it if there is a later version that allows it.
+ // If it's not allowed at all, it will be reported by CheckAllowed.
+ if (allowedInVersion != 0) {
+ std::string thisVersion{std::to_string(version / 10) + "." +
+ std::to_string(version % 10)};
+ std::string goodVersion{std::to_string(allowedInVersion)};
+
+ context_.Say(dirCtx.clauseSource,
+ "%s clause is not allowed on directive %s in OpenMP v%s, "
+ "try -fopenmp-version=%d"_err_en_US,
+ clauseName, dirName, thisVersion, allowedInVersion);
+ }
+ }
+ return CheckAllowed(clause);
+}
+
bool OmpStructureChecker::IsCloselyNestedRegion(const OmpDirectiveSet &set) {
// Definition of close nesting:
//
@@ -1156,7 +1193,7 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclarativeAllocate &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Allocator &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_allocator);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_allocator);
// Note: Predefined allocators are stored in ScalarExpr as numbers
// whereas custom allocators are stored as strings, so if the ScalarExpr
// actually has an int value, then it must be a predefined allocator
@@ -1165,7 +1202,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Allocator &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Allocate &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_allocate);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_allocate);
if (const auto &modifier{
std::get<std::optional<parser::OmpAllocateClause::AllocateModifier>>(
x.v.t)}) {
@@ -2362,7 +2399,7 @@ CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(Simdlen, OMPC_simdlen)
// Restrictions specific to each clause are implemented apart from the
// generalized restrictions.
void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_reduction);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_reduction);
if (CheckReductionOperators(x)) {
CheckReductionTypeList(x);
}
@@ -2686,7 +2723,7 @@ void OmpStructureChecker::CheckSharedBindingInOuterContext(
}
void OmpStructureChecker::Enter(const parser::OmpClause::Ordered &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_ordered);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_ordered);
// the parameter of ordered clause is optional
if (const auto &expr{x.v}) {
RequiresConstantPositiveParameter(llvm::omp::Clause::OMPC_ordered, *expr);
@@ -2701,17 +2738,17 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Ordered &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Shared &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_shared);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_shared);
CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "SHARED");
}
void OmpStructureChecker::Enter(const parser::OmpClause::Private &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_private);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_private);
CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "PRIVATE");
CheckIntentInPointer(x.v, llvm::omp::Clause::OMPC_private);
}
void OmpStructureChecker::Enter(const parser::OmpClause::Nowait &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_nowait);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_nowait);
if (llvm::omp::noWaitClauseNotAllowedSet.test(GetContext().directive)) {
context_.Say(GetContext().clauseSource,
"%s clause is not allowed on the OMP %s directive,"
@@ -2784,7 +2821,7 @@ void OmpStructureChecker::CheckIsVarPartOfAnotherVar(
}
void OmpStructureChecker::Enter(const parser::OmpClause::Firstprivate &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_firstprivate);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_firstprivate);
CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "FIRSTPRIVATE");
CheckIsLoopIvPartOfClause(llvmOmpClause::OMPC_firstprivate, x.v);
@@ -2871,7 +2908,7 @@ void OmpStructureChecker::Leave(const parser::OmpAtomic &) {
// Restrictions specific to each clause are implemented apart from the
// generalized restrictions.
void OmpStructureChecker::Enter(const parser::OmpClause::Aligned &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_aligned);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_aligned);
if (const auto &expr{
std::get<std::optional<parser::ScalarIntConstantExpr>>(x.v.t)}) {
@@ -2880,7 +2917,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Aligned &x) {
// 2.8.1 TODO: list-item attribute check
}
void OmpStructureChecker::Enter(const parser::OmpClause::Defaultmap &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_defaultmap);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_defaultmap);
using VariableCategory = parser::OmpDefaultmapClause::VariableCategory;
if (!std::get<std::optional<VariableCategory>>(x.v.t)) {
context_.Say(GetContext().clauseSource,
@@ -2889,7 +2926,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Defaultmap &x) {
}
}
void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_if);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_if);
using dirNameModifier = parser::OmpIfClause::DirectiveNameModifier;
// TODO Check that, when multiple 'if' clauses are applied to a combined
// construct, at most one of them applies to each directive.
@@ -2925,7 +2962,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_linear);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_linear);
// 2.7 Loop Construct Restriction
if ((llvm::omp::allDoSet | llvm::omp::allSimdSet)
@@ -2959,7 +2996,7 @@ void OmpStructureChecker::CheckAllowedMapTypes(
}
void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_map);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_map);
if (const auto &maptype{std::get<std::optional<parser::OmpMapType>>(x.v.t)}) {
using Type = parser::OmpMapType::Type;
@@ -3005,7 +3042,7 @@ bool OmpStructureChecker::ScheduleModifierHasType(
return false;
}
void OmpStructureChecker::Enter(const parser::OmpClause::Schedule &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_schedule);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_schedule);
const parser::OmpScheduleClause &scheduleClause = x.v;
// 2.7 Loop Construct Restriction
@@ -3041,7 +3078,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Schedule &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Device &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_device);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_device);
const parser::OmpDeviceClause &deviceClause = x.v;
const auto &device{std::get<1>(deviceClause.t)};
RequiresPositiveParameter(
@@ -3060,7 +3097,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Device &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_depend);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_depend);
if ((std::holds_alternative<parser::OmpDependClause::Source>(x.v.u) ||
std::holds_alternative<parser::OmpDependClause::Sink>(x.v.u)) &&
GetContext().directive != llvm::omp::OMPD_ordered) {
@@ -3103,7 +3140,7 @@ void OmpStructureChecker::CheckCopyingPolymorphicAllocatable(
}
void OmpStructureChecker::Enter(const parser::OmpClause::Copyprivate &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_copyprivate);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_copyprivate);
CheckIntentInPointer(x.v, llvm::omp::Clause::OMPC_copyprivate);
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(x.v, currSymbols);
@@ -3121,7 +3158,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Copyprivate &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_lastprivate);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_lastprivate);
CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "LASTPRIVATE");
@@ -3145,7 +3182,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Copyin &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_copyin);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_copyin);
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(x.v, currSymbols);
@@ -3180,7 +3217,7 @@ void OmpStructureChecker::CheckStructureElement(
void OmpStructureChecker::Enter(const parser::OmpClause::UseDevicePtr &x) {
CheckStructureElement(x.v, llvm::omp::Clause::OMPC_use_device_ptr);
- CheckAllowed(llvm::omp::Clause::OMPC_use_device_ptr);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_use_device_ptr);
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(x.v, currSymbols);
semantics::UnorderedSymbolSet listVars;
@@ -3213,7 +3250,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::UseDevicePtr &x) {
void OmpStructureChecker::Enter(const parser::OmpClause::UseDeviceAddr &x) {
CheckStructureElement(x.v, llvm::omp::Clause::OMPC_use_device_addr);
- CheckAllowed(llvm::omp::Clause::OMPC_use_device_addr);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_use_device_addr);
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(x.v, currSymbols);
semantics::UnorderedSymbolSet listVars;
@@ -3238,7 +3275,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::UseDeviceAddr &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::IsDevicePtr &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_is_device_ptr);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_is_device_ptr);
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(x.v, currSymbols);
semantics::UnorderedSymbolSet listVars;
@@ -3276,7 +3313,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::IsDevicePtr &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::HasDeviceAddr &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_has_device_addr);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_has_device_addr);
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(x.v, currSymbols);
semantics::UnorderedSymbolSet listVars;
@@ -3621,7 +3658,7 @@ void OmpStructureChecker::Enter(
}
void OmpStructureChecker::CheckAllowedRequiresClause(llvmOmpClause clause) {
- CheckAllowed(clause);
+ CheckAllowedClause(clause);
if (clause != llvm::omp::Clause::OMPC_atomic_default_mem_order) {
// Check that it does not appear after a device construct
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 8bfd4d594b028e..605f3f05b4bc83 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -139,6 +139,7 @@ class OmpStructureChecker
}
private:
+ bool CheckAllowedClause(llvmOmpClause clause);
void CheckMultipleOccurrence(semantics::UnorderedSymbolSet &listVars,
const std::list<parser::Name> &nameList, const parser::CharBlock &item,
const std::string &clauseName);
diff --git a/flang/test/Lower/OpenMP/atomic-capture.f90 b/flang/test/Lower/OpenMP/atomic-capture.f90
index 667ae8ed7a133b..af82e4b2a20eb2 100644
--- a/flang/test/Lower/OpenMP/atomic-capture.f90
+++ b/flang/test/Lower/OpenMP/atomic-capture.f90
@@ -2,8 +2,8 @@
! This test checks the lowering of atomic capture
-! RUN: bbc %openmp_flags -emit-hlfir %s -o - | FileCheck %s
-! RUN: %flang_fc1 -emit-hlfir %openmp_flags %s -o - | FileCheck %s
+! RUN: bbc %openmp_flags -fopenmp-version=50 -emit-hlfir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir %openmp_flags -fopenmp-version=50 %s -o - | FileCheck %s
program OmpAtomicCapture
diff --git a/flang/test/Lower/OpenMP/atomic-read.f90 b/flang/test/Lower/OpenMP/atomic-read.f90
index d578df959a474d..c3270dd6c1d670 100644
--- a/flang/test/Lower/OpenMP/atomic-read.f90
+++ b/flang/test/Lower/OpenMP/atomic-read.f90
@@ -1,6 +1,6 @@
! REQUIRES: openmp_runtime
-! RUN: bbc %openmp_flags -emit-hlfir %s -o - | FileCheck %s
+! RUN: bbc %openmp_flags -fopenmp-version=50 -emit-hlfir %s -o - | FileCheck %s
! This test checks the lowering of atomic read
diff --git a/flang/test/Lower/OpenMP/atomic-update.f90 b/flang/test/Lower/OpenMP/atomic-update.f90
index 85edfdf4de84d5..16dae9d5f301c1 100644
--- a/flang/test/Lower/OpenMP/atomic-update.f90
+++ b/flang/test/Lower/OpenMP/atomic-update.f90
@@ -1,8 +1,8 @@
! REQUIRES: openmp_runtime
! This test checks lowering of atomic and atomic update constructs
-! RUN: bbc %openmp_flags -emit-hlfir %s -o - | FileCheck %s
-! RUN: %flang_fc1 -emit-hlfir %openmp_flags %s -o - | FileCheck %s
+! RUN: bbc %openmp_flags -fopenmp-version=50 -emit-hlfir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir %openmp_flags -fopenmp-version=50 %s -o - | FileCheck %s
program OmpAtomicUpdate
use omp_lib
diff --git a/flang/test/Lower/OpenMP/atomic-write.f90 b/flang/test/Lower/OpenMP/atomic-write.f90
index 8867dc59211922..b30dc483e6b845 100644
--- a/flang/test/Lower/OpenMP/atomic-write.f90
+++ b/flang/test/Lower/OpenMP/atomic-write.f90
@@ -1,6 +1,6 @@
! REQUIRES: openmp_runtime
-! RUN: bbc %openmp_flags -emit-hlfir %s -o - | FileCheck %s
+! RUN: bbc %openmp_flags -fopenmp-version=50 -emit-hlfir %s -o - | FileCheck %s
! This test checks the lowering of atomic write
diff --git a/flang/test/Lower/OpenMP/declare-target-data.f90 b/flang/test/Lower/OpenMP/declare-target-data.f90
index d86f74d18b6df0..154853a0fa20c4 100644
--- a/flang/test/Lower/OpenMP/declare-target-data.f90
+++ b/flang/test/Lower/OpenMP/declare-target-data.f90
@@ -1,5 +1,5 @@
-!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
-!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -fopenmp-is-target-device %s -o - | FileCheck %s
module test_0
implicit none
diff --git a/flang/test/Lower/OpenMP/declare-target-deferred-marking.f90 b/flang/test/Lower/OpenMP/declare-target-deferred-marking.f90
index 1998c3da23af5f..079d43e309028d 100644
--- a/flang/test/Lower/OpenMP/declare-target-deferred-marking.f90
+++ b/flang/test/Lower/OpenMP/declare-target-deferred-marking.f90
@@ -1,5 +1,5 @@
-!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s --check-prefixes ALL,HOST
-!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-device %s -o - | FileCheck %s --check-prefixes ALL
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s --check-prefixes ALL,HOST
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -fopenmp-is-device %s -o - | FileCheck %s --check-prefixes ALL
program main
use, intrinsic :: iso_c_binding
diff --git a/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90 b/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90
index 0d138321445ce6..8182e468928e22 100644
--- a/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90
+++ b/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90
@@ -1,5 +1,5 @@
-!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s --check-prefixes ALL,HOST
-!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-device %s -o - | FileCheck %s --check-prefixes ALL,DEVICE
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s --check-prefixes ALL,HOST
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -fopenmp-is-device %s -o - | FileCheck %s --check-prefixes ALL,DEVICE
! Check specification valid forms of declare target with functions
! utilising device_type and to clauses as well as the default
diff --git a/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90 b/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90
index 0ca2bcbd66a960..8035f1a65880b7 100644
--- a/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90
+++ b/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90
@@ -1,7 +1,7 @@
-!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
-!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefix=DEVICE
-!RUN: bbc -emit-hlfir -fopenmp %s -o - | FileCheck %s
-!RUN: bbc -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefix=DEVICE
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefix=DEVICE
+!RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s
+!RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=52 -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefix=DEVICE
! CHECK-LABEL: func.func @_QPimplicitly_captured_twice
! CHECK-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter)>{{.*}}}
diff --git a/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap.f90 b/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap.f90
index ffca5c3ff25000..70e4ac22f8974e 100644
--- a/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap.f90
+++ b/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap.f90
@@ -1,7 +1,7 @@
-!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
-!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefix=DEVICE
-!RUN: bbc -emit-hlfir -fopenmp %s -o - | FileCheck %s
-!RUN: bbc -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefix=DEVICE
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 %s -o - | FileCheck %s
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -fopenmp-is-target-device %s -o - | FileCheck %s --c...
[truncated]
|
@llvm/pr-subscribers-flang-fir-hlfir Author: Krzysztof Parzyszek (kparzysz) ChangesIf there is a clause that is allowed on a given directive in a later version of the OpenMP spec, report an error and provide the minimal spec version that allows the clause. The case where a clause is not allowed on a directive at all is already handled elsewhere. Patch is 41.30 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/110015.diff 43 Files Affected:
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index dfc3f3290a81be..976c159e252f12 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -16,25 +16,25 @@ namespace Fortran::semantics {
// Use when clause falls under 'struct OmpClause' in 'parse-tree.h'.
#define CHECK_SIMPLE_CLAUSE(X, Y) \
void OmpStructureChecker::Enter(const parser::OmpClause::X &) { \
- CheckAllowed(llvm::omp::Clause::Y); \
+ CheckAllowedClause(llvm::omp::Clause::Y); \
}
#define CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(X, Y) \
void OmpStructureChecker::Enter(const parser::OmpClause::X &c) { \
- CheckAllowed(llvm::omp::Clause::Y); \
+ CheckAllowedClause(llvm::omp::Clause::Y); \
RequiresConstantPositiveParameter(llvm::omp::Clause::Y, c.v); \
}
#define CHECK_REQ_SCALAR_INT_CLAUSE(X, Y) \
void OmpStructureChecker::Enter(const parser::OmpClause::X &c) { \
- CheckAllowed(llvm::omp::Clause::Y); \
+ CheckAllowedClause(llvm::omp::Clause::Y); \
RequiresPositiveParameter(llvm::omp::Clause::Y, c.v); \
}
// Use when clause don't falls under 'struct OmpClause' in 'parse-tree.h'.
#define CHECK_SIMPLE_PARSER_CLAUSE(X, Y) \
void OmpStructureChecker::Enter(const parser::X &) { \
- CheckAllowed(llvm::omp::Y); \
+ CheckAllowedClause(llvm::omp::Y); \
}
// 'OmpWorkshareBlockChecker' is used to check the validity of the assignment
@@ -163,6 +163,43 @@ class AssociatedLoopChecker {
std::map<std::string, std::int64_t> constructNamesAndLevels_;
};
+bool OmpStructureChecker::CheckAllowedClause(llvmOmpClause clause) {
+ unsigned version{context_.langOptions().OpenMPVersion};
+ DirectiveContext &dirCtx = GetContext();
+ llvm::omp::Directive dir{dirCtx.directive};
+
+ if (!llvm::omp::isAllowedClauseForDirective(dir, clause, version)) {
+ unsigned allowedInVersion{[&] {
+ for (unsigned v : {45, 50, 51, 52, 60}) {
+ if (v <= version) {
+ continue;
+ }
+ if (llvm::omp::isAllowedClauseForDirective(dir, clause, v)) {
+ return v;
+ }
+ }
+ return 0u;
+ }()};
+
+ auto clauseName{parser::ToUpperCaseLetters(getClauseName(clause).str())};
+ auto dirName{parser::ToUpperCaseLetters(getDirectiveName(dir).str())};
+
+ // Only report it if there is a later version that allows it.
+ // If it's not allowed at all, it will be reported by CheckAllowed.
+ if (allowedInVersion != 0) {
+ std::string thisVersion{std::to_string(version / 10) + "." +
+ std::to_string(version % 10)};
+ std::string goodVersion{std::to_string(allowedInVersion)};
+
+ context_.Say(dirCtx.clauseSource,
+ "%s clause is not allowed on directive %s in OpenMP v%s, "
+ "try -fopenmp-version=%d"_err_en_US,
+ clauseName, dirName, thisVersion, allowedInVersion);
+ }
+ }
+ return CheckAllowed(clause);
+}
+
bool OmpStructureChecker::IsCloselyNestedRegion(const OmpDirectiveSet &set) {
// Definition of close nesting:
//
@@ -1156,7 +1193,7 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclarativeAllocate &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Allocator &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_allocator);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_allocator);
// Note: Predefined allocators are stored in ScalarExpr as numbers
// whereas custom allocators are stored as strings, so if the ScalarExpr
// actually has an int value, then it must be a predefined allocator
@@ -1165,7 +1202,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Allocator &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Allocate &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_allocate);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_allocate);
if (const auto &modifier{
std::get<std::optional<parser::OmpAllocateClause::AllocateModifier>>(
x.v.t)}) {
@@ -2362,7 +2399,7 @@ CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(Simdlen, OMPC_simdlen)
// Restrictions specific to each clause are implemented apart from the
// generalized restrictions.
void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_reduction);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_reduction);
if (CheckReductionOperators(x)) {
CheckReductionTypeList(x);
}
@@ -2686,7 +2723,7 @@ void OmpStructureChecker::CheckSharedBindingInOuterContext(
}
void OmpStructureChecker::Enter(const parser::OmpClause::Ordered &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_ordered);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_ordered);
// the parameter of ordered clause is optional
if (const auto &expr{x.v}) {
RequiresConstantPositiveParameter(llvm::omp::Clause::OMPC_ordered, *expr);
@@ -2701,17 +2738,17 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Ordered &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Shared &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_shared);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_shared);
CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "SHARED");
}
void OmpStructureChecker::Enter(const parser::OmpClause::Private &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_private);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_private);
CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "PRIVATE");
CheckIntentInPointer(x.v, llvm::omp::Clause::OMPC_private);
}
void OmpStructureChecker::Enter(const parser::OmpClause::Nowait &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_nowait);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_nowait);
if (llvm::omp::noWaitClauseNotAllowedSet.test(GetContext().directive)) {
context_.Say(GetContext().clauseSource,
"%s clause is not allowed on the OMP %s directive,"
@@ -2784,7 +2821,7 @@ void OmpStructureChecker::CheckIsVarPartOfAnotherVar(
}
void OmpStructureChecker::Enter(const parser::OmpClause::Firstprivate &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_firstprivate);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_firstprivate);
CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "FIRSTPRIVATE");
CheckIsLoopIvPartOfClause(llvmOmpClause::OMPC_firstprivate, x.v);
@@ -2871,7 +2908,7 @@ void OmpStructureChecker::Leave(const parser::OmpAtomic &) {
// Restrictions specific to each clause are implemented apart from the
// generalized restrictions.
void OmpStructureChecker::Enter(const parser::OmpClause::Aligned &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_aligned);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_aligned);
if (const auto &expr{
std::get<std::optional<parser::ScalarIntConstantExpr>>(x.v.t)}) {
@@ -2880,7 +2917,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Aligned &x) {
// 2.8.1 TODO: list-item attribute check
}
void OmpStructureChecker::Enter(const parser::OmpClause::Defaultmap &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_defaultmap);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_defaultmap);
using VariableCategory = parser::OmpDefaultmapClause::VariableCategory;
if (!std::get<std::optional<VariableCategory>>(x.v.t)) {
context_.Say(GetContext().clauseSource,
@@ -2889,7 +2926,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Defaultmap &x) {
}
}
void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_if);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_if);
using dirNameModifier = parser::OmpIfClause::DirectiveNameModifier;
// TODO Check that, when multiple 'if' clauses are applied to a combined
// construct, at most one of them applies to each directive.
@@ -2925,7 +2962,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::If &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Linear &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_linear);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_linear);
// 2.7 Loop Construct Restriction
if ((llvm::omp::allDoSet | llvm::omp::allSimdSet)
@@ -2959,7 +2996,7 @@ void OmpStructureChecker::CheckAllowedMapTypes(
}
void OmpStructureChecker::Enter(const parser::OmpClause::Map &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_map);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_map);
if (const auto &maptype{std::get<std::optional<parser::OmpMapType>>(x.v.t)}) {
using Type = parser::OmpMapType::Type;
@@ -3005,7 +3042,7 @@ bool OmpStructureChecker::ScheduleModifierHasType(
return false;
}
void OmpStructureChecker::Enter(const parser::OmpClause::Schedule &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_schedule);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_schedule);
const parser::OmpScheduleClause &scheduleClause = x.v;
// 2.7 Loop Construct Restriction
@@ -3041,7 +3078,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Schedule &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Device &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_device);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_device);
const parser::OmpDeviceClause &deviceClause = x.v;
const auto &device{std::get<1>(deviceClause.t)};
RequiresPositiveParameter(
@@ -3060,7 +3097,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Device &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Depend &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_depend);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_depend);
if ((std::holds_alternative<parser::OmpDependClause::Source>(x.v.u) ||
std::holds_alternative<parser::OmpDependClause::Sink>(x.v.u)) &&
GetContext().directive != llvm::omp::OMPD_ordered) {
@@ -3103,7 +3140,7 @@ void OmpStructureChecker::CheckCopyingPolymorphicAllocatable(
}
void OmpStructureChecker::Enter(const parser::OmpClause::Copyprivate &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_copyprivate);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_copyprivate);
CheckIntentInPointer(x.v, llvm::omp::Clause::OMPC_copyprivate);
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(x.v, currSymbols);
@@ -3121,7 +3158,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Copyprivate &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_lastprivate);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_lastprivate);
CheckIsVarPartOfAnotherVar(GetContext().clauseSource, x.v, "LASTPRIVATE");
@@ -3145,7 +3182,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Lastprivate &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::Copyin &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_copyin);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_copyin);
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(x.v, currSymbols);
@@ -3180,7 +3217,7 @@ void OmpStructureChecker::CheckStructureElement(
void OmpStructureChecker::Enter(const parser::OmpClause::UseDevicePtr &x) {
CheckStructureElement(x.v, llvm::omp::Clause::OMPC_use_device_ptr);
- CheckAllowed(llvm::omp::Clause::OMPC_use_device_ptr);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_use_device_ptr);
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(x.v, currSymbols);
semantics::UnorderedSymbolSet listVars;
@@ -3213,7 +3250,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::UseDevicePtr &x) {
void OmpStructureChecker::Enter(const parser::OmpClause::UseDeviceAddr &x) {
CheckStructureElement(x.v, llvm::omp::Clause::OMPC_use_device_addr);
- CheckAllowed(llvm::omp::Clause::OMPC_use_device_addr);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_use_device_addr);
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(x.v, currSymbols);
semantics::UnorderedSymbolSet listVars;
@@ -3238,7 +3275,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::UseDeviceAddr &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::IsDevicePtr &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_is_device_ptr);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_is_device_ptr);
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(x.v, currSymbols);
semantics::UnorderedSymbolSet listVars;
@@ -3276,7 +3313,7 @@ void OmpStructureChecker::Enter(const parser::OmpClause::IsDevicePtr &x) {
}
void OmpStructureChecker::Enter(const parser::OmpClause::HasDeviceAddr &x) {
- CheckAllowed(llvm::omp::Clause::OMPC_has_device_addr);
+ CheckAllowedClause(llvm::omp::Clause::OMPC_has_device_addr);
SymbolSourceMap currSymbols;
GetSymbolsInObjectList(x.v, currSymbols);
semantics::UnorderedSymbolSet listVars;
@@ -3621,7 +3658,7 @@ void OmpStructureChecker::Enter(
}
void OmpStructureChecker::CheckAllowedRequiresClause(llvmOmpClause clause) {
- CheckAllowed(clause);
+ CheckAllowedClause(clause);
if (clause != llvm::omp::Clause::OMPC_atomic_default_mem_order) {
// Check that it does not appear after a device construct
diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h
index 8bfd4d594b028e..605f3f05b4bc83 100644
--- a/flang/lib/Semantics/check-omp-structure.h
+++ b/flang/lib/Semantics/check-omp-structure.h
@@ -139,6 +139,7 @@ class OmpStructureChecker
}
private:
+ bool CheckAllowedClause(llvmOmpClause clause);
void CheckMultipleOccurrence(semantics::UnorderedSymbolSet &listVars,
const std::list<parser::Name> &nameList, const parser::CharBlock &item,
const std::string &clauseName);
diff --git a/flang/test/Lower/OpenMP/atomic-capture.f90 b/flang/test/Lower/OpenMP/atomic-capture.f90
index 667ae8ed7a133b..af82e4b2a20eb2 100644
--- a/flang/test/Lower/OpenMP/atomic-capture.f90
+++ b/flang/test/Lower/OpenMP/atomic-capture.f90
@@ -2,8 +2,8 @@
! This test checks the lowering of atomic capture
-! RUN: bbc %openmp_flags -emit-hlfir %s -o - | FileCheck %s
-! RUN: %flang_fc1 -emit-hlfir %openmp_flags %s -o - | FileCheck %s
+! RUN: bbc %openmp_flags -fopenmp-version=50 -emit-hlfir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir %openmp_flags -fopenmp-version=50 %s -o - | FileCheck %s
program OmpAtomicCapture
diff --git a/flang/test/Lower/OpenMP/atomic-read.f90 b/flang/test/Lower/OpenMP/atomic-read.f90
index d578df959a474d..c3270dd6c1d670 100644
--- a/flang/test/Lower/OpenMP/atomic-read.f90
+++ b/flang/test/Lower/OpenMP/atomic-read.f90
@@ -1,6 +1,6 @@
! REQUIRES: openmp_runtime
-! RUN: bbc %openmp_flags -emit-hlfir %s -o - | FileCheck %s
+! RUN: bbc %openmp_flags -fopenmp-version=50 -emit-hlfir %s -o - | FileCheck %s
! This test checks the lowering of atomic read
diff --git a/flang/test/Lower/OpenMP/atomic-update.f90 b/flang/test/Lower/OpenMP/atomic-update.f90
index 85edfdf4de84d5..16dae9d5f301c1 100644
--- a/flang/test/Lower/OpenMP/atomic-update.f90
+++ b/flang/test/Lower/OpenMP/atomic-update.f90
@@ -1,8 +1,8 @@
! REQUIRES: openmp_runtime
! This test checks lowering of atomic and atomic update constructs
-! RUN: bbc %openmp_flags -emit-hlfir %s -o - | FileCheck %s
-! RUN: %flang_fc1 -emit-hlfir %openmp_flags %s -o - | FileCheck %s
+! RUN: bbc %openmp_flags -fopenmp-version=50 -emit-hlfir %s -o - | FileCheck %s
+! RUN: %flang_fc1 -emit-hlfir %openmp_flags -fopenmp-version=50 %s -o - | FileCheck %s
program OmpAtomicUpdate
use omp_lib
diff --git a/flang/test/Lower/OpenMP/atomic-write.f90 b/flang/test/Lower/OpenMP/atomic-write.f90
index 8867dc59211922..b30dc483e6b845 100644
--- a/flang/test/Lower/OpenMP/atomic-write.f90
+++ b/flang/test/Lower/OpenMP/atomic-write.f90
@@ -1,6 +1,6 @@
! REQUIRES: openmp_runtime
-! RUN: bbc %openmp_flags -emit-hlfir %s -o - | FileCheck %s
+! RUN: bbc %openmp_flags -fopenmp-version=50 -emit-hlfir %s -o - | FileCheck %s
! This test checks the lowering of atomic write
diff --git a/flang/test/Lower/OpenMP/declare-target-data.f90 b/flang/test/Lower/OpenMP/declare-target-data.f90
index d86f74d18b6df0..154853a0fa20c4 100644
--- a/flang/test/Lower/OpenMP/declare-target-data.f90
+++ b/flang/test/Lower/OpenMP/declare-target-data.f90
@@ -1,5 +1,5 @@
-!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
-!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -fopenmp-is-target-device %s -o - | FileCheck %s
module test_0
implicit none
diff --git a/flang/test/Lower/OpenMP/declare-target-deferred-marking.f90 b/flang/test/Lower/OpenMP/declare-target-deferred-marking.f90
index 1998c3da23af5f..079d43e309028d 100644
--- a/flang/test/Lower/OpenMP/declare-target-deferred-marking.f90
+++ b/flang/test/Lower/OpenMP/declare-target-deferred-marking.f90
@@ -1,5 +1,5 @@
-!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s --check-prefixes ALL,HOST
-!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-device %s -o - | FileCheck %s --check-prefixes ALL
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s --check-prefixes ALL,HOST
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -fopenmp-is-device %s -o - | FileCheck %s --check-prefixes ALL
program main
use, intrinsic :: iso_c_binding
diff --git a/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90 b/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90
index 0d138321445ce6..8182e468928e22 100644
--- a/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90
+++ b/flang/test/Lower/OpenMP/declare-target-func-and-subr.f90
@@ -1,5 +1,5 @@
-!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s --check-prefixes ALL,HOST
-!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-device %s -o - | FileCheck %s --check-prefixes ALL,DEVICE
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s --check-prefixes ALL,HOST
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -fopenmp-is-device %s -o - | FileCheck %s --check-prefixes ALL,DEVICE
! Check specification valid forms of declare target with functions
! utilising device_type and to clauses as well as the default
diff --git a/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90 b/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90
index 0ca2bcbd66a960..8035f1a65880b7 100644
--- a/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90
+++ b/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap-enter.f90
@@ -1,7 +1,7 @@
-!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
-!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefix=DEVICE
-!RUN: bbc -emit-hlfir -fopenmp %s -o - | FileCheck %s
-!RUN: bbc -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefix=DEVICE
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=52 -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefix=DEVICE
+!RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=52 %s -o - | FileCheck %s
+!RUN: bbc -emit-hlfir -fopenmp -fopenmp-version=52 -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefix=DEVICE
! CHECK-LABEL: func.func @_QPimplicitly_captured_twice
! CHECK-SAME: {{.*}}attributes {omp.declare_target = #omp.declaretarget<device_type = (any), capture_clause = (enter)>{{.*}}}
diff --git a/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap.f90 b/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap.f90
index ffca5c3ff25000..70e4ac22f8974e 100644
--- a/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap.f90
+++ b/flang/test/Lower/OpenMP/declare-target-implicit-func-and-subr-cap.f90
@@ -1,7 +1,7 @@
-!RUN: %flang_fc1 -emit-hlfir -fopenmp %s -o - | FileCheck %s
-!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefix=DEVICE
-!RUN: bbc -emit-hlfir -fopenmp %s -o - | FileCheck %s
-!RUN: bbc -emit-hlfir -fopenmp -fopenmp-is-target-device %s -o - | FileCheck %s --check-prefix=DEVICE
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 %s -o - | FileCheck %s
+!RUN: %flang_fc1 -emit-hlfir -fopenmp -fopenmp-version=50 -fopenmp-is-target-device %s -o - | FileCheck %s --c...
[truncated]
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
…zysz/spr/a02-langopts-semactx
…rzysz/spr/a03-omp-version-checks
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nice! LGTM!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you Krzysztof, LGTM.
auto clauseName{parser::ToUpperCaseLetters(getClauseName(clause).str())}; | ||
auto dirName{parser::ToUpperCaseLetters(getDirectiveName(dir).str())}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: Perhaps move this into the if
below to avoid evaluating it when it's not going to be needed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks!
If there is a clause that is allowed on a given directive in a later version of the OpenMP spec, report an error and provide the minimal spec version that allows the clause. The case where a clause is not allowed on a directive at all is already handled elsewhere.
If there is a clause that is allowed on a given directive in a later version of the OpenMP spec, report an error and provide the minimal spec version that allows the clause.
The case where a clause is not allowed on a directive at all is already handled elsewhere.