}
void Post(const parser::Name &);
+ const parser::OmpClause *associatedClause{nullptr};
+ void SetAssociatedClause(const parser::OmpClause &c) {
+ associatedClause = &c;
+ }
+ const parser::OmpClause *GetAssociatedClause() { return associatedClause; }
+
private:
std::int64_t GetAssociatedLoopLevelFromClauses(const parser::OmpClauseList &);
}
// Predetermined DSA rules
- void PrivatizeAssociatedLoopIndex(const parser::OpenMPLoopConstruct &);
+ void PrivatizeAssociatedLoopIndexAndCheckLoopLevel(
+ const parser::OpenMPLoopConstruct &);
void ResolveSeqLoopIndexInParallelOrTaskConstruct(const parser::Name &);
void ResolveOmpObjectList(const parser::OmpObjectList &, Symbol::Flag);
void CheckDataCopyingClause(
const parser::Name &, const Symbol &, Symbol::Flag);
+
+ void CheckAssocLoopLevel(std::int64_t level, const parser::OmpClause *clause);
};
template <typename T>
}
ClearDataSharingAttributeObjects();
SetContextAssociatedLoopLevel(GetAssociatedLoopLevelFromClauses(clauseList));
- PrivatizeAssociatedLoopIndex(x);
+ PrivatizeAssociatedLoopIndexAndCheckLoopLevel(x);
return true;
}
const parser::OmpClauseList &x) {
std::int64_t orderedLevel{0};
std::int64_t collapseLevel{0};
+
+ const parser::OmpClause *ordClause{nullptr};
+ const parser::OmpClause *collClause{nullptr};
+
for (const auto &clause : x.v) {
if (const auto *orderedClause{
std::get_if<parser::OmpClause::Ordered>(&clause.u)}) {
if (const auto v{EvaluateInt64(context_, orderedClause->v)}) {
orderedLevel = *v;
}
+ ordClause = &clause;
}
if (const auto *collapseClause{
std::get_if<parser::OmpClause::Collapse>(&clause.u)}) {
if (const auto v{EvaluateInt64(context_, collapseClause->v)}) {
collapseLevel = *v;
}
+ collClause = &clause;
}
}
if (orderedLevel && (!collapseLevel || orderedLevel >= collapseLevel)) {
+ SetAssociatedClause(*ordClause);
return orderedLevel;
} else if (!orderedLevel && collapseLevel) {
+ SetAssociatedClause(*collClause);
return collapseLevel;
} // orderedLevel < collapseLevel is an error handled in structural checks
return 1; // default is outermost loop
// increment of the associated do-loop.
// - The loop iteration variables in the associated do-loops of a simd
// construct with multiple associated do-loops are lastprivate.
-//
-// TODO: revisit after semantics checks are completed for do-loop association of
-// collapse and ordered
-void OmpAttributeVisitor::PrivatizeAssociatedLoopIndex(
+void OmpAttributeVisitor::PrivatizeAssociatedLoopIndexAndCheckLoopLevel(
const parser::OpenMPLoopConstruct &x) {
std::int64_t level{GetContext().associatedLoopLevel};
if (level <= 0) {
const auto it{block.begin()};
loop = it != block.end() ? GetDoConstructIf(*it) : nullptr;
}
- CHECK(level == 0);
+ CheckAssocLoopLevel(level, GetAssociatedClause());
+}
+void OmpAttributeVisitor::CheckAssocLoopLevel(
+ std::int64_t level, const parser::OmpClause *clause) {
+ if (clause && level != 0) {
+ context_.Say(clause->source,
+ "The value of the parameter in the COLLAPSE or ORDERED clause must"
+ " not be larger than the number of nested loops"
+ " following the construct."_err_en_US);
+ }
}
bool OmpAttributeVisitor::Pre(const parser::OpenMPSectionsConstruct &x) {
--- /dev/null
+!RUN: %S/test_errors.sh %s %t %f18 -fopenmp
+! OpenMP Version 4.5
+! 2.7.1 Collapse Clause Positive cases
+
+!DEF: /omp_docollapse MainProgram
+program omp_docollapse
+ !DEF: /omp_docollapse/i ObjectEntity INTEGER(4)
+ !DEF: /omp_docollapse/j ObjectEntity INTEGER(4)
+ !DEF: /omp_docollapse/k ObjectEntity INTEGER(4)
+ integer i, j, k
+ !$omp do collapse(2)
+ !DEF: /omp_docollapse/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+ do i=1,10
+ !DEF: /omp_docollapse/Block1/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+ do j=1,10
+ !REF: /omp_docollapse/k
+ do k=1,10
+ print *, "hello"
+ end do
+ end do
+ end do
+ !$omp end do
+
+ !REF: /omp_docollapse/i
+ do i=1,10
+ !$omp do collapse(2)
+ !DEF: /omp_docollapse/Block1/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+ do j=1,10
+ !DEF: /omp_docollapse/Block1/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+ do k=1,10
+ print *, "hello"
+ end do
+ end do
+ !$omp end do
+ end do
+end program omp_docollapse
--- /dev/null
+!RUN: %S/test_errors.sh %s %t %f18 -fopenmp
+! OpenMP Version 4.5
+! 2.7.1 Ordered Clause positive cases.
+
+!DEF: /omp_doordered MainProgram
+program omp_doordered
+ !DEF: /omp_doordered/i ObjectEntity INTEGER(4)
+ !DEF: /omp_doordered/j ObjectEntity INTEGER(4)
+ integer i, j
+ !$omp do ordered(2)
+ !DEF: /omp_doordered/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+ do i=1,10
+ !DEF: /omp_doordered/Block1/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+ do j=1,10
+ print *, "hello"
+ end do
+ end do
+ !$omp end do
+
+ !REF: /omp_doordered/i
+ do i=1,10
+ !REF: /omp_doordered/j
+ do j=1,10
+ !$omp do ordered(1)
+ !DEF: /omp_doordered/Block2/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+ do k=1,10
+ print *, "hello"
+ end do
+ !$omp end do
+ end do
+ end do
+
+ !$omp do ordered(1)
+ !DEF: /omp_doordered/Block3/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+ do i=1,10
+ !$omp ordered
+ !REF: /omp_doordered/j
+ do j=1,10
+ print *, "hello"
+ end do
+ !$omp end ordered
+ end do
+ !$omp end do
+
+ !$omp do collapse(1) ordered(2)
+ !DEF: /omp_doordered/Block4/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+ do i=1,10
+ !DEF: /omp_doordered/Block4/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+ do j=1,10
+ print *, "hello"
+ end do
+ end do
+ !$omp end do
+
+ !$omp parallel num_threads(4)
+ !$omp do ordered(1) collapse(1)
+ !DEF: /omp_doordered/Block5/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+ do i=1,10
+ !$omp ordered
+ !DEF: /omp_doordered/Block5/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4)
+ do j=1,10
+ print *, "hello"
+ end do
+ !$omp end ordered
+ end do
+ !$omp end parallel
+end program omp_doordered
--- /dev/null
+!RUN: %S/test_errors.sh %s %t %f18 -fopenmp
+! OpenMP Version 4.5
+! 2.7.1 Ordered Clause
+
+program omp_doOrdered
+ integer:: i,j
+ !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+ !$omp do ordered(3)
+ do i = 1,10
+ do j = 1, 10
+ print *, "hello"
+ end do
+ end do
+ !$omp end do
+
+ do i = 1,10
+ do j = 1, 10
+ !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+ !$omp do ordered(2)
+ do k = 1, 10
+ print *, "hello"
+ end do
+ !$omp end do
+ end do
+ end do
+
+ !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+ !$omp do ordered(2)
+ do i = 1,10
+ !$omp ordered
+ do j = 1, 10
+ print *, "hello"
+ end do
+ !$omp end ordered
+ end do
+ !$omp end do
+
+ !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+ !$omp do collapse(1) ordered(3)
+ do i = 1,10
+ do j = 1, 10
+ print *, "hello"
+ end do
+ end do
+ !$omp end do
+
+ !$omp parallel num_threads(4)
+ !ERROR: The value of the parameter in the COLLAPSE or ORDERED clause must not be larger than the number of nested loops following the construct.
+ !$omp do ordered(2) collapse(1)
+ do i = 1,10
+ !$omp ordered
+ do j = 1, 10
+ print *, "hello"
+ end do
+ !$omp end ordered
+ end do
+ !$omp end parallel
+end program omp_doOrdered