// limitations under the License.
#include "check-omp-structure.h"
+#include "tools.h"
#include "../parser/parse-tree.h"
namespace Fortran::semantics {
}
if (auto *clause{FindClause(OmpClause::ORDERED)}) {
- if (FindClause(OmpClause::LINEAR)) {
- // only one ordered clause is allowed
- const auto &orderedClause{
- std::get<parser::OmpClause::Ordered>(clause->u)};
- if (orderedClause.v.has_value()) {
+ // only one ordered clause is allowed
+ const auto &orderedClause{
+ std::get<parser::OmpClause::Ordered>(clause->u)};
+
+ if (orderedClause.v.has_value()) {
+ if (FindClause(OmpClause::LINEAR)) {
context_.Say(clause->source,
"A loop directive may not have both a LINEAR clause and "
"an ORDERED clause with a parameter"_err_en_US);
}
+
+ if (auto *clause2{FindClause(OmpClause::COLLAPSE)}) {
+ const auto &collapseClause{
+ std::get<parser::OmpClause::Collapse>(clause2->u)};
+ // ordered and collapse both have parameters
+ if (const auto orderedValue{GetIntValue(orderedClause.v)}) {
+ if (const auto collapseValue{GetIntValue(collapseClause.v)}) {
+ if (*orderedValue > 0 && *orderedValue < *collapseValue) {
+ context_.Say(clause->source,
+ "The parameter of the ORDERED clause must be "
+ "greater than or equal to "
+ "the parameter of the COLLAPSE clause"_err_en_US);
+ }
+ }
+ }
+ }
}
// TODO: ordered region binding check (requires nesting implementation)
void OmpStructureChecker::Enter(const parser::OmpClause::Untied &) {
CheckAllowed(OmpClause::UNTIED);
}
-void OmpStructureChecker::Enter(const parser::OmpClause::Collapse &) {
+
+void OmpStructureChecker::Enter(const parser::OmpClause::Collapse &x) {
CheckAllowed(OmpClause::COLLAPSE);
+ // collapse clause must have a parameter
+ if (const auto v{GetIntValue(x.v)}) {
+ if (*v <= 0) {
+ context_.Say(GetContext().clauseSource,
+ "The parameter of the COLLAPSE clause must be "
+ "a constant positive integer expression"_err_en_US);
+ }
+ }
}
+
void OmpStructureChecker::Enter(const parser::OmpClause::Copyin &) {
CheckAllowed(OmpClause::COPYIN);
}
void OmpStructureChecker::Enter(const parser::OmpClause::NumTeams &) {
CheckAllowed(OmpClause::NUM_TEAMS);
}
-void OmpStructureChecker::Enter(const parser::OmpClause::NumThreads &) {
+void OmpStructureChecker::Enter(const parser::OmpClause::NumThreads &x) {
CheckAllowed(OmpClause::NUM_THREADS);
+ if (const auto v{GetIntValue(x.v)}) {
+ if (*v <= 0) {
+ context_.Say(GetContext().clauseSource,
+ "The parameter of the NUM_THREADS clause must be "
+ "a positive integer expression"_err_en_US);
+ }
+ }
+ // if parameter is variable, defer to Expression Analysis
}
-void OmpStructureChecker::Enter(const parser::OmpClause::Ordered &) {
+
+void OmpStructureChecker::Enter(const parser::OmpClause::Ordered &x) {
CheckAllowed(OmpClause::ORDERED);
+ // the parameter of ordered clause is optional
+ if (const auto &expr{x.v}) {
+ if (const auto v{GetIntValue(expr)}) {
+ if (*v <= 0) {
+ context_.Say(GetContext().clauseSource,
+ "The parameter of the ORDERED clause must be "
+ "a constant positive integer expression"_err_en_US);
+ }
+ }
+ }
}
void OmpStructureChecker::Enter(const parser::OmpClause::Priority &) {
CheckAllowed(OmpClause::PRIORITY);
! ...
integer :: b = 128
+ integer, parameter :: num = 16
N = 1024
! 2.5 parallel-clause -> if-clause |
enddo
!$omp end parallel
+ !ERROR: The parameter of the NUM_THREADS clause must be a positive integer expression
+ !$omp parallel num_threads(1-4)
+ do i = 1, N
+ a = 3.14
+ enddo
+ !$omp end parallel
+
+ !$omp parallel num_threads(num-10)
+ do i = 1, N
+ a = 3.14
+ enddo
+ !$omp end parallel
+
+ !$omp parallel num_threads(b+1)
+ do i = 1, N
+ a = 3.14
+ enddo
+ !$omp end parallel
+
! 2.7.1 do-clause -> private-clause |
! firstprivate-clause |
! lastprivate-clause |
a = 3.14
enddo
+ !ERROR: The parameter of the ORDERED clause must be a constant positive integer expression
!ERROR: A loop directive may not have both a LINEAR clause and an ORDERED clause with a parameter
!ERROR: Internal: no symbol found for 'b'
!ERROR: Internal: no symbol found for 'a'
- !$omp do ordered(1) private(b) linear(b) linear(a)
+ !$omp do ordered(1-1) private(b) linear(b) linear(a)
do i = 1, N
a = 3.14
enddo
+
+ !ERROR: The parameter of the ORDERED clause must be greater than or equal to the parameter of the COLLAPSE clause
+ !$omp do collapse(num) ordered(1+2+3+4)
+ do i = 1, N
+ do j = 1, N
+ do k = 1, N
+ a = 3.14
+ enddo
+ enddo
+ enddo
end