diff --git a/flang/include/flang/Semantics/symbol.h b/flang/include/flang/Semantics/symbol.h --- a/flang/include/flang/Semantics/symbol.h +++ b/flang/include/flang/Semantics/symbol.h @@ -501,9 +501,9 @@ // OpenMP data-mapping attribute OmpMapTo, OmpMapFrom, OmpMapAlloc, OmpMapRelease, OmpMapDelete, // OpenMP miscellaneous flags - OmpCommonBlock, OmpReduction, OmpDeclareSimd, OmpDeclareTarget, - OmpThreadprivate, OmpDeclareReduction, OmpFlushed, OmpCriticalLock, - OmpIfSpecified, OmpNone, OmpPreDetermined); + OmpCommonBlock, OmpReduction, OmpAllocate, OmpDeclareSimd, + OmpDeclareTarget, OmpThreadprivate, OmpDeclareReduction, OmpFlushed, + OmpCriticalLock, OmpIfSpecified, OmpNone, OmpPreDetermined); using Flags = common::EnumSet; const Scope &owner() const { return *owner_; } diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -145,6 +145,7 @@ void Enter(const parser::OmpClause::IsDevicePtr &); void Enter(const parser::OmpAlignedClause &); + void Enter(const parser::OmpAllocateClause &); void Enter(const parser::OmpDefaultClause &); void Enter(const parser::OmpDefaultmapClause &); void Enter(const parser::OmpDependClause &); diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -544,6 +544,9 @@ } // 2.8.1 TODO: list-item attribute check } +void OmpStructureChecker::Enter(const parser::OmpAllocateClause &) { + CheckAllowed(llvm::omp::Clause::OMPC_allocate); +} void OmpStructureChecker::Enter(const parser::OmpDefaultClause &) { CheckAllowed(llvm::omp::Clause::OMPC_default); } diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -13,6 +13,7 @@ #include "resolve-names-utils.h" #include "flang/Common/idioms.h" #include "flang/Evaluate/fold.h" +#include "flang/Evaluate/type.h" #include "flang/Parser/parse-tree-visitor.h" #include "flang/Parser/parse-tree.h" #include "flang/Parser/tools.h" @@ -87,6 +88,7 @@ void AddDataSharingAttributeObject(SymbolRef object) { dataSharingAttributeObjects_.insert(object); } + void ClearDataSharingAttributeObjects() { dataSharingAttributeObjects_.clear(); } @@ -226,7 +228,8 @@ } bool Pre(const parser::OpenMPBlockConstruct &); - void Post(const parser::OpenMPBlockConstruct &) { PopContext(); } + void Post(const parser::OpenMPBlockConstruct &); + void Post(const parser::OmpBeginBlockDirective &) { GetContext().withinConstruct = true; } @@ -254,6 +257,11 @@ ResolveOmpObjectList(x.v, Symbol::Flag::OmpPrivate); return false; } + bool Pre(const parser::OmpAllocateClause &x) { + const auto &objectList{std::get(x.t)}; + ResolveOmpObjectList(objectList, Symbol::Flag::OmpAllocate); + return false; + } bool Pre(const parser::OmpClause::Firstprivate &x) { ResolveOmpObjectList(x.v, Symbol::Flag::OmpFirstPrivate); return false; @@ -273,6 +281,10 @@ Symbol::Flag::OmpFirstPrivate, Symbol::Flag::OmpLastPrivate, Symbol::Flag::OmpReduction, Symbol::Flag::OmpLinear}; + static constexpr Symbol::Flags privateDataSharingAttributeFlags{ + Symbol::Flag::OmpPrivate, Symbol::Flag::OmpFirstPrivate, + Symbol::Flag::OmpLastPrivate}; + static constexpr Symbol::Flags ompFlagsRequireNewSymbol{ Symbol::Flag::OmpPrivate, Symbol::Flag::OmpLinear, Symbol::Flag::OmpFirstPrivate, Symbol::Flag::OmpLastPrivate, @@ -281,6 +293,19 @@ static constexpr Symbol::Flags ompFlagsRequireMark{ Symbol::Flag::OmpThreadprivate}; + SymbolSet allocateObjects_; // on one directive + SymbolSet privateDataSharingAttributeObjects_; // on one directive + + void AddAllocateObject(SymbolRef object) { allocateObjects_.insert(object); } + void ClearAllocateObjects() { allocateObjects_.clear(); } + + void AddPrivateDataSharingAttributeObjects(SymbolRef object) { + privateDataSharingAttributeObjects_.insert(object); + } + void ClearPrivateDataSharingAttributeObjects() { + privateDataSharingAttributeObjects_.clear(); + } + // Predetermined DSA rules void PrivatizeAssociatedLoopIndex(const parser::OpenMPLoopConstruct &); void ResolveSeqLoopIndexInParallelOrTaskConstruct(const parser::Name &); @@ -632,9 +657,125 @@ break; } ClearDataSharingAttributeObjects(); + ClearPrivateDataSharingAttributeObjects(); + ClearAllocateObjects(); return true; } +void OmpAttributeVisitor::Post(const parser::OpenMPBlockConstruct &x) { + const auto &beginBlockDir{std::get(x.t)}; + const auto &beginDir{std::get(beginBlockDir.t)}; + switch (beginDir.v) { + case llvm::omp::Directive::OMPD_parallel: { + std::set::iterator itAllocate = allocateObjects_.begin(); + std::set::iterator itPrivate; + bool hasPrivate; + while (itAllocate != allocateObjects_.end()) { + itPrivate = privateDataSharingAttributeObjects_.begin(); + hasPrivate = false; + const Symbol &symbolAllocate{*itAllocate}; + while (itPrivate != privateDataSharingAttributeObjects_.end()) { + const Symbol &symbolPrivate{*itPrivate}; + if (symbolAllocate.name() == symbolPrivate.name()) { + hasPrivate = true; + } + itPrivate++; + } + if (!hasPrivate) { + context_.Say(symbolAllocate.name(), + "The ALLOCATE clause requires that '%s' must be listed in a " + "private " + "data-sharing attribute clause on the same directive"_err_en_US, + symbolAllocate.name().ToString()); + } + itAllocate++; + } + break; + } + case llvm::omp::Directive::OMPD_target: { + std::set::iterator itAllocate = allocateObjects_.begin(); + std::set::iterator itPrivate; + bool hasPrivate; + while (itAllocate != allocateObjects_.end()) { + itPrivate = privateDataSharingAttributeObjects_.begin(); + hasPrivate = false; + const Symbol &symbolAllocate{*itAllocate}; + while (itPrivate != privateDataSharingAttributeObjects_.end()) { + const Symbol &symbolPrivate{*itPrivate}; + if (symbolAllocate.name() == symbolPrivate.name()) { + hasPrivate = true; + } + itPrivate++; + } + if (!hasPrivate) { + context_.Say(symbolAllocate.name(), + "The ALLOCATE clause requires that '%s' must be listed in a " + "private " + "data-sharing attribute clause on the same directive"_err_en_US, + symbolAllocate.name().ToString()); + } + itAllocate++; + } + break; + } + case llvm::omp::Directive::OMPD_task: { + std::set::iterator itAllocate = allocateObjects_.begin(); + std::set::iterator itPrivate; + bool hasPrivate; + while (itAllocate != allocateObjects_.end()) { + itPrivate = privateDataSharingAttributeObjects_.begin(); + hasPrivate = false; + const Symbol &symbolAllocate{*itAllocate}; + while (itPrivate != privateDataSharingAttributeObjects_.end()) { + const Symbol &symbolPrivate{*itPrivate}; + if (symbolAllocate.name() == symbolPrivate.name()) { + hasPrivate = true; + } + itPrivate++; + } + if (!hasPrivate) { + context_.Say(symbolAllocate.name(), + "The ALLOCATE clause requires that '%s' must be listed in a " + "private " + "data-sharing attribute clause on the same directive"_err_en_US, + symbolAllocate.name().ToString()); + } + itAllocate++; + } + break; + } + case llvm::omp::Directive::OMPD_teams: { + std::set::iterator itAllocate = allocateObjects_.begin(); + std::set::iterator itPrivate; + bool hasPrivate; + while (itAllocate != allocateObjects_.end()) { + itPrivate = privateDataSharingAttributeObjects_.begin(); + hasPrivate = false; + const Symbol &symbolAllocate{*itAllocate}; + while (itPrivate != privateDataSharingAttributeObjects_.end()) { + const Symbol &symbolPrivate{*itPrivate}; + if (symbolAllocate.name() == symbolPrivate.name()) { + hasPrivate = true; + } + itPrivate++; + } + if (!hasPrivate) { + context_.Say(symbolAllocate.name(), + "The ALLOCATE clause requires that '%s' must be listed in a " + "private " + "data-sharing attribute clause on the same directive"_err_en_US, + symbolAllocate.name().ToString()); + } + itAllocate++; + } + break; + } + default: + break; + } + PopContext(); +} + bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) { const auto &beginLoopDir{std::get(x.t)}; const auto &beginDir{std::get(beginLoopDir.t)}; @@ -879,6 +1020,9 @@ if (dataSharingAttributeFlags.test(ompFlag)) { CheckMultipleAppearances(*name, *symbol, ompFlag); } + if (ompFlag == Symbol::Flag::OmpAllocate) { + AddAllocateObject(*symbol); + } } } else { // Array sections to be changed to substrings as needed @@ -976,6 +1120,9 @@ name.ToString()); } else { AddDataSharingAttributeObject(*target); + if (privateDataSharingAttributeFlags.test(ompFlag)) { + AddPrivateDataSharingAttributeObjects(*target); + } } } diff --git a/flang/test/Semantics/omp-clause-validity01.f90 b/flang/test/Semantics/omp-clause-validity01.f90 --- a/flang/test/Semantics/omp-clause-validity01.f90 +++ b/flang/test/Semantics/omp-clause-validity01.f90 @@ -9,7 +9,7 @@ ! TODO: all the internal errors integer :: b = 128 - integer :: c = 32 + integer :: z, c = 32 integer, parameter :: num = 16 real(8) :: arrayA(256), arrayB(512) @@ -39,29 +39,54 @@ enddo !$omp end parallel - !$omp parallel allocate(b) + !$omp parallel private(b) allocate(b) do i = 1, N a = 3.14 enddo !$omp end parallel - !$omp parallel allocate(omp_default_mem_space : b, c) + !$omp parallel private(c, b) allocate(omp_default_mem_space : b, c) do i = 1, N a = 3.14 enddo !$omp end parallel - !$omp parallel allocate(b) allocate(c) + !$omp parallel allocate(b) allocate(c) private(b, c) do i = 1, N a = 3.14 enddo !$omp end parallel - !$omp parallel allocate(xy_alloc :b) + !$omp parallel allocate(xy_alloc :b) private(b) do i = 1, N a = 3.14 enddo !$omp end parallel + + !$omp task private(b) allocate(b) + do i = 1, N + z = 2 + end do + !$omp end task + + !$omp teams private(b) allocate(b) + do i = 1, N + z = 2 + end do + !$omp end teams + + !$omp target private(b) allocate(b) + do i = 1, N + z = 2 + end do + !$omp end target + + !ERROR: ALLOCATE clause is not allowed on the TARGET DATA directive + !$omp target data map(from: b) allocate(b) + do i = 1, N + z = 2 + enddo + !$omp end target data !ERROR: SCHEDULE clause is not allowed on the PARALLEL directive !$omp parallel schedule(static) diff --git a/flang/test/Semantics/omp-resolve06.f90 b/flang/test/Semantics/omp-resolve06.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/omp-resolve06.f90 @@ -0,0 +1,39 @@ +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp +use omp_lib +!2.11.4 Allocate Clause +!For any list item that is specified in the allocate +!clause on a directive, a data-sharing attribute clause +!that may create a private copy of that list item must be +!specified on the same directive. + + integer :: N = 2 + + !ERROR: The ALLOCATE clause requires that 'x' must be listed in a private data-sharing attribute clause on the same directive + !$omp parallel allocate(omp_default_mem_space : x) + do i = 1, N + x = 2 + enddo + !$omp end parallel + + !ERROR: The ALLOCATE clause requires that 'y' must be listed in a private data-sharing attribute clause on the same directive + !$omp parallel allocate(omp_default_mem_space : y) firstprivate(x) + do i = 1, N + x = 2 + enddo + !$omp end parallel + + !ERROR: The ALLOCATE clause requires that 'q' must be listed in a private data-sharing attribute clause on the same directive + !$omp parallel private(t) allocate(omp_default_mem_space : z, t, q, r) firstprivate(z, r) + do i = 1, N + x = 2 + enddo + !$omp end parallel + + !ERROR: The ALLOCATE clause requires that 'b' must be listed in a private data-sharing attribute clause on the same directive + !ERROR: The ALLOCATE clause requires that 'c' must be listed in a private data-sharing attribute clause on the same directive + !$omp parallel allocate(omp_default_mem_space : a, b, c, d) firstprivate(a, d) + do i = 1, N + x = 2 + enddo + !$omp end parallel +end diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -208,7 +208,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause + VersionedClause ]; let allowedOnceClauses = [ VersionedClause, @@ -226,7 +226,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause ]; @@ -243,7 +243,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause ]; @@ -265,7 +265,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause ]; } @@ -291,7 +291,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause + VersionedClause ]; } def OMP_Section : Directive<"section"> {} @@ -301,7 +301,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause + VersionedClause ]; } def OMP_Master : Directive<"master"> {} @@ -363,7 +363,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause ]; let allowedOnceClauses = [ @@ -378,7 +378,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause + VersionedClause ]; let allowedOnceClauses = [ VersionedClause, @@ -450,7 +450,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause ]; let allowedOnceClauses = [ @@ -482,7 +482,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause ]; @@ -542,7 +542,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause ]; } @@ -585,7 +585,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause ]; @@ -627,7 +627,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause + VersionedClause ]; } def OMP_ParallelSections : Directive<"parallel sections"> { @@ -641,7 +641,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause + VersionedClause ]; let allowedOnceClauses = [ VersionedClause @@ -661,7 +661,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -718,7 +718,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause + VersionedClause ]; let allowedOnceClauses = [ VersionedClause, @@ -734,7 +734,7 @@ def OMP_TaskLoopSimd : Directive<"taskloop simd"> { let allowedClauses = [ VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -767,7 +767,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause + VersionedClause ]; let allowedOnceClauses = [ VersionedClause, @@ -791,7 +791,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause ]; } @@ -837,7 +837,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause ]; @@ -869,7 +869,7 @@ def OMP_DistributeSimd : Directive<"distribute simd"> { let allowedClauses = [ VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -917,7 +917,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause, VersionedClause @@ -956,7 +956,7 @@ def OMP_TargetSimd : Directive<"target simd"> { let allowedClauses = [ VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -995,13 +995,13 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause + VersionedClause ]; } def OMP_TeamsDistributeSimd : Directive<"teams distribute simd"> { let allowedClauses = [ VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -1044,7 +1044,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause ]; @@ -1095,7 +1095,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause ]; } @@ -1107,7 +1107,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause ]; @@ -1134,7 +1134,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause ]; @@ -1157,7 +1157,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause, VersionedClause @@ -1197,7 +1197,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause ]; @@ -1262,7 +1262,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause, VersionedClause @@ -1309,7 +1309,7 @@ Directive<"target teams distribute simd"> { let allowedClauses = [ VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -1364,7 +1364,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause + VersionedClause ]; } def OMP_ParallelMasterTaskloop : @@ -1385,7 +1385,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause, VersionedClause @@ -1413,7 +1413,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause ]; @@ -1436,7 +1436,7 @@ VersionedClause, VersionedClause, VersionedClause, - VersionedClause, + VersionedClause, VersionedClause, VersionedClause, VersionedClause, @@ -1468,7 +1468,7 @@ def OMP_EndDeclareVariant : Directive<"end declare variant"> {} def OMP_ParallelWorkshare : Directive<"parallel workshare"> { let allowedClauses = [ - VersionedClause, + VersionedClause, VersionedClause, VersionedClause, VersionedClause,