Index: flang/lib/Semantics/check-directive-structure.h =================================================================== --- flang/lib/Semantics/check-directive-structure.h +++ flang/lib/Semantics/check-directive-structure.h @@ -347,6 +347,9 @@ void RequiresPositiveParameter(const C &clause, const parser::ScalarIntExpr &i, llvm::StringRef paramName = "parameter"); + void RequiresNonNegativeParameter(const C &clause, + const parser::ScalarIntExpr &i, llvm::StringRef paramName = "parameter"); + void OptionalConstantPositiveParameter( const C &clause, const std::optional &o); @@ -561,6 +564,22 @@ } } +// Check the value of the clause is a non negative parameter. +template +void DirectiveStructureChecker::RequiresNonNegativeParameter(const C &clause, + const parser::ScalarIntExpr &i, llvm::StringRef paramName) { + if (const auto v{GetIntValue(i)}) { + if (*v < 0) { + context_.Say(GetContext().clauseSource, + "The %s of the %s clause must be " + "a non-negative integer expression"_err_en_US, + paramName.str(), + parser::ToUpperCaseLetters(getClauseName(clause).str())); + } + } +} + } // namespace Fortran::semantics #endif // FORTRAN_SEMANTICS_CHECK_DIRECTIVE_STRUCTURE_H_ Index: flang/lib/Semantics/check-omp-structure.cpp =================================================================== --- flang/lib/Semantics/check-omp-structure.cpp +++ flang/lib/Semantics/check-omp-structure.cpp @@ -31,6 +31,14 @@ RequiresPositiveParameter(llvm::omp::Clause::Y, c.v); \ } +#define CHECK_REQ_NON_NEGATIVE_SCALAR_INT_CLAUSE(X, Y) \ + \ + void \ + OmpStructureChecker::Enter(const parser::OmpClause::X &c) { \ + CheckAllowed(llvm::omp::Clause::Y); \ + RequiresNonNegativeParameter(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 &) { \ @@ -1656,7 +1664,6 @@ CHECK_SIMPLE_CLAUSE(Depobj, OMPC_depobj) CHECK_SIMPLE_CLAUSE(Destroy, OMPC_destroy) CHECK_SIMPLE_CLAUSE(Detach, OMPC_detach) -CHECK_SIMPLE_CLAUSE(Device, OMPC_device) CHECK_SIMPLE_CLAUSE(DeviceType, OMPC_device_type) CHECK_SIMPLE_CLAUSE(DistSchedule, OMPC_dist_schedule) CHECK_SIMPLE_CLAUSE(DynamicAllocators, OMPC_dynamic_allocators) @@ -1721,11 +1728,12 @@ CHECK_REQ_SCALAR_INT_CLAUSE(NumThreads, OMPC_num_threads) CHECK_REQ_SCALAR_INT_CLAUSE(Priority, OMPC_priority) CHECK_REQ_SCALAR_INT_CLAUSE(ThreadLimit, OMPC_thread_limit) - CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(Collapse, OMPC_collapse) CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(Safelen, OMPC_safelen) CHECK_REQ_CONSTANT_SCALAR_INT_CLAUSE(Simdlen, OMPC_simdlen) +CHECK_REQ_NON_NEGATIVE_SCALAR_INT_CLAUSE(Device, OMPC_device) + // Restrictions specific to each clause are implemented apart from the // generalized restrictions. void OmpStructureChecker::Enter(const parser::OmpClause::Reduction &x) { Index: flang/test/Semantics/omp-device-constructs.f90 =================================================================== --- flang/test/Semantics/omp-device-constructs.f90 +++ flang/test/Semantics/omp-device-constructs.f90 @@ -29,6 +29,12 @@ enddo !$omp end target + !ERROR: The parameter of the DEVICE clause must be a non-negative integer expression + !$omp target enter data map(alloc:A) device(-2) + + !ERROR: The parameter of the DEVICE clause must be a non-negative integer expression + !$omp target exit data map(delete:A) device(-2) + !ERROR: SCHEDULE clause is not allowed on the TARGET directive !$omp target schedule(static) do i = 1, N