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 @@ -152,6 +152,9 @@ void Post(const parser::AccDefaultClause &); + bool Pre(const parser::AccClause::Attach &); + bool Pre(const parser::AccClause::Detach &); + bool Pre(const parser::AccClause::Copy &x) { ResolveAccObjectList(x.v, Symbol::Flag::AccCopyIn); ResolveAccObjectList(x.v, Symbol::Flag::AccCopyOut); @@ -222,6 +225,8 @@ const parser::Name &, const Symbol &, Symbol::Flag); void AllowOnlyArrayAndSubArray(const parser::AccObjectList &objectList); void DoNotAllowAssumedSizedArray(const parser::AccObjectList &objectList); + void EnsureAllocatableOrPointer( + const llvm::acc::Clause clause, const parser::AccObjectList &objectList); }; // Data-sharing and Data-mapping attributes for data-refs in OpenMP construct @@ -849,6 +854,46 @@ CHECK(level == 0); } +void AccAttributeVisitor::EnsureAllocatableOrPointer( + const llvm::acc::Clause clause, const parser::AccObjectList &objectList) { + for (const auto &accObject : objectList.v) { + std::visit( + common::visitors{ + [&](const parser::Designator &designator) { + const auto &lastName{GetLastName(designator)}; + if (!IsAllocatableOrPointer(*lastName.symbol)) + context_.Say(designator.source, + "Variable `%s` on the %s clause must be a variable or " + "array with the POINTER or ALLOCATABLE attribute"_err_en_US, + lastName.symbol->name(), + parser::ToUpperCaseLetters( + llvm::acc::getOpenACCClauseName(clause).str())); + }, + [&](const auto &name) { + context_.Say(name.source, + "Variable `%s` on the %s clause must be a variable or " + "array with the POINTER or ALLOCATABLE attribute"_err_en_US, + name.symbol->name(), + parser::ToUpperCaseLetters( + llvm::acc::getOpenACCClauseName(clause).str())); + }, + }, + accObject.u); + } +} + +bool AccAttributeVisitor::Pre(const parser::AccClause::Attach &x) { + // Restriction - line 1708-1709 + EnsureAllocatableOrPointer(llvm::acc::Clause::ACCC_attach, x.v); + return true; +} + +bool AccAttributeVisitor::Pre(const parser::AccClause::Detach &x) { + // Restriction - line 1715-1717 + EnsureAllocatableOrPointer(llvm::acc::Clause::ACCC_detach, x.v); + return true; +} + void AccAttributeVisitor::Post(const parser::AccDefaultClause &x) { if (!dirContext_.empty()) { switch (x.v) { diff --git a/flang/test/Semantics/OpenACC/acc-data.f90 b/flang/test/Semantics/OpenACC/acc-data.f90 --- a/flang/test/Semantics/OpenACC/acc-data.f90 +++ b/flang/test/Semantics/OpenACC/acc-data.f90 @@ -23,6 +23,8 @@ real :: reduction_r logical :: reduction_l real(8), dimension(N, N) :: aa, bb, cc + real(8), dimension(:), allocatable :: dd + real(8), pointer :: p logical :: ifCondition = .TRUE. type(atype) :: t type(atype), dimension(10) :: ta @@ -65,6 +67,7 @@ !$acc enter data create(aa) wait(wait1) wait(wait2) + !ERROR: Variable `bb` on the ATTACH clause must be a variable or array with the POINTER or ALLOCATABLE attribute !$acc enter data attach(bb) !ERROR: At least one of COPYOUT, DELETE, DETACH clause must appear on the EXIT DATA directive @@ -80,6 +83,7 @@ !ERROR: At most one FINALIZE clause can appear on the EXIT DATA directive !$acc exit data delete(aa) finalize finalize + !ERROR: Variable `cc` on the DETACH clause must be a variable or array with the POINTER or ALLOCATABLE attribute !$acc exit data detach(cc) !$acc exit data copyout(bb) @@ -144,7 +148,7 @@ !$acc data no_create(aa) present(bb, cc) !$acc end data - !$acc data deviceptr(aa) attach(bb, cc) + !$acc data deviceptr(aa) attach(dd, p) !$acc end data !$acc data copy(aa, bb) default(none) diff --git a/flang/test/Semantics/OpenACC/acc-kernels-loop.f90 b/flang/test/Semantics/OpenACC/acc-kernels-loop.f90 --- a/flang/test/Semantics/OpenACC/acc-kernels-loop.f90 +++ b/flang/test/Semantics/OpenACC/acc-kernels-loop.f90 @@ -21,6 +21,8 @@ real :: reduction_r logical :: reduction_l real(8), dimension(N, N) :: aa, bb, cc + real(8), dimension(:), allocatable :: dd + real(8), pointer :: p logical :: ifCondition = .TRUE. type(atype) :: t type(atype), dimension(10) :: ta @@ -218,7 +220,8 @@ a(i) = 3.14 end do - !$acc kernels loop attach(aa, bb, cc) + !ERROR: Variable `aa` on the ATTACH clause must be a variable or array with the POINTER or ALLOCATABLE attribute + !$acc kernels loop attach(aa, dd, p) do i = 1, N a(i) = 3.14 end do diff --git a/flang/test/Semantics/OpenACC/acc-kernels.f90 b/flang/test/Semantics/OpenACC/acc-kernels.f90 --- a/flang/test/Semantics/OpenACC/acc-kernels.f90 +++ b/flang/test/Semantics/OpenACC/acc-kernels.f90 @@ -21,6 +21,8 @@ real :: reduction_r logical :: reduction_l real(8), dimension(N, N) :: aa, bb, cc + real(8), dimension(:), allocatable :: dd + real(8), pointer :: p logical :: ifCondition = .TRUE. type(atype) :: t type(atype), dimension(10) :: ta @@ -99,7 +101,8 @@ !$acc kernels deviceptr(aa, bb) no_create(cc) !$acc end kernels - !$acc kernels attach(aa, bb, cc) + !ERROR: Variable `aa` on the ATTACH clause must be a variable or array with the POINTER or ALLOCATABLE attribute + !$acc kernels attach(dd, p, aa) !$acc end kernels !ERROR: PRIVATE clause is not allowed on the KERNELS directive diff --git a/flang/test/Semantics/OpenACC/acc-parallel.f90 b/flang/test/Semantics/OpenACC/acc-parallel.f90 --- a/flang/test/Semantics/OpenACC/acc-parallel.f90 +++ b/flang/test/Semantics/OpenACC/acc-parallel.f90 @@ -16,6 +16,8 @@ real :: reduction_r logical :: reduction_l real(8), dimension(N, N) :: aa, bb, cc + real(8), dimension(:), allocatable :: dd + real(8), pointer :: p logical :: ifCondition = .TRUE. real(8), dimension(N) :: a, f, g, h @@ -89,7 +91,8 @@ !$acc parallel deviceptr(aa, bb) no_create(cc) !$acc end parallel - !$acc parallel attach(aa, bb, cc) + !ERROR: Variable `cc` on the ATTACH clause must be a variable or array with the POINTER or ALLOCATABLE attribute + !$acc parallel attach(dd, p, cc) !$acc end parallel !$acc parallel private(aa) firstprivate(bb, cc) diff --git a/flang/test/Semantics/OpenACC/acc-serial.f90 b/flang/test/Semantics/OpenACC/acc-serial.f90 --- a/flang/test/Semantics/OpenACC/acc-serial.f90 +++ b/flang/test/Semantics/OpenACC/acc-serial.f90 @@ -21,6 +21,8 @@ real :: reduction_r logical :: reduction_l real(8), dimension(N, N) :: aa, bb, cc + real(8), dimension(:), allocatable :: dd + real(8), pointer :: p logical :: ifCondition = .TRUE. type(atype) :: t type(atype), dimension(10) :: ta @@ -128,7 +130,8 @@ !$acc serial deviceptr(aa, bb) no_create(cc) !$acc end serial - !$acc serial attach(aa, bb, cc) + !ERROR: Variable `aa` on the ATTACH clause must be a variable or array with the POINTER or ALLOCATABLE attribute + !$acc serial attach(aa, dd, p) !$acc end serial !$acc serial firstprivate(bb, cc)