GetContext().withinConstruct = true;
}
+ bool Pre(const parser::OpenACCCacheConstruct &);
+ void Post(const parser::OpenACCCacheConstruct &) { PopContext(); }
+
void Post(const parser::AccDefaultClause &);
bool Pre(const parser::AccClause::Copy &x) {
Symbol *DeclareOrMarkOtherAccessEntity(Symbol &, Symbol::Flag);
void CheckMultipleAppearances(
const parser::Name &, const Symbol &, Symbol::Flag);
+ void AllowOnlyArrayAndSubArray(const parser::AccObjectList &objectList);
};
// Data-sharing and Data-mapping attributes for data-refs in OpenMP construct
bool AccAttributeVisitor::Pre(const parser::OpenACCStandaloneConstruct &x) {
const auto &standaloneDir{std::get<parser::AccStandaloneDirective>(x.t)};
switch (standaloneDir.v) {
- case llvm::acc::Directive::ACCD_cache:
case llvm::acc::Directive::ACCD_enter_data:
case llvm::acc::Directive::ACCD_exit_data:
case llvm::acc::Directive::ACCD_init:
return true;
}
+static bool IsLastNameArray(const parser::Designator &designator) {
+ const auto &name{GetLastName(designator)};
+ const evaluate::DataRef dataRef{*(name.symbol)};
+ return std::visit(
+ common::visitors{
+ [](const evaluate::SymbolRef &ref) { return ref->Rank() > 0; },
+ [](const evaluate::ArrayRef &aref) {
+ return aref.base().IsSymbol() ||
+ aref.base().GetComponent().base().Rank() == 0;
+ },
+ [](const auto &) { return false; },
+ },
+ dataRef.u);
+}
+
+void AccAttributeVisitor::AllowOnlyArrayAndSubArray(
+ const parser::AccObjectList &objectList) {
+ for (const auto &accObject : objectList.v) {
+ std::visit(
+ common::visitors{
+ [&](const parser::Designator &designator) {
+ if (!IsLastNameArray(designator))
+ context_.Say(designator.source,
+ "Only array element or subarray are allowed in %s directive"_err_en_US,
+ parser::ToUpperCaseLetters(
+ llvm::acc::getOpenACCDirectiveName(
+ GetContext().directive)
+ .str()));
+ },
+ [&](const auto &name) {
+ context_.Say(name.source,
+ "Only array element or subarray are allowed in %s directive"_err_en_US,
+ parser::ToUpperCaseLetters(
+ llvm::acc::getOpenACCDirectiveName(GetContext().directive)
+ .str()));
+ },
+ },
+ accObject.u);
+ }
+}
+
+bool AccAttributeVisitor::Pre(const parser::OpenACCCacheConstruct &x) {
+ const auto &verbatim{std::get<parser::Verbatim>(x.t)};
+ PushContext(verbatim.source, llvm::acc::Directive::ACCD_cache);
+ ClearDataSharingAttributeObjects();
+
+ const auto &objectListWithModifier =
+ std::get<parser::AccObjectListWithModifier>(x.t);
+ const auto &objectList =
+ std::get<Fortran::parser::AccObjectList>(objectListWithModifier.t);
+
+ // 2.10 Cache directive restriction: A var in a cache directive must be a
+ // single array element or a simple subarray.
+ AllowOnlyArrayAndSubArray(objectList);
+
+ return true;
+}
+
std::int64_t AccAttributeVisitor::GetAssociatedLoopLevelFromClauses(
const parser::AccClauseList &x) {
std::int64_t collapseLevel{0};
! 2.14.3 Set
! 2.14.4 Update
! 2.15.1 Routine
+! 2.10 Cache
! 2.11 Parallel Loop
! 2.11 Kernels Loop
! 2.11 Serial Loop
implicit none
+ type atype
+ real(8), dimension(10) :: arr
+ real(8) :: s
+ end type atype
+
integer :: i, j, b, gang_size, vector_size, worker_size
integer, parameter :: N = 256
integer, dimension(N) :: c
logical :: reduction_l
real(8), dimension(N, N) :: aa, bb, cc
logical :: ifCondition = .TRUE.
+ type(atype) :: t
+ type(atype), dimension(10) :: ta
!ERROR: At least one clause is required on the DECLARE directive
!$acc declare
i = i + 1
!$acc end atomic
!$acc end parallel
+ t%arr(i) = 2.0
+
+ !$acc cache(a(i))
+ !$acc cache(a(1:2,3:4))
+ !$acc cache(a)
+ !$acc cache(readonly: a, aa)
+ !$acc cache(readonly: a(i), aa(i, i))
+ !$acc cache(t%arr)
+ !$acc cache(ta(1:2)%arr)
+ !$acc cache(ta(1:2)%arr(1:4))
+
+ !ERROR: Only array element or subarray are allowed in CACHE directive
+ !$acc cache(ta(1:2)%s)
+
+ !ERROR: Only array element or subarray are allowed in CACHE directive
+ !$acc cache(i)
+
+ !ERROR: Only array element or subarray are allowed in CACHE directive
+ !$acc cache(t%s)
+
+ !ERROR: Only array element or subarray are allowed in CACHE directive
+ !$acc cache(/i/)
contains