This patch fixes a bug to allow ordered construct within a non-worksharing loop, also adds more sema checks.
Reviewed By: kiranchandramohan
Differential Revision: https://reviews.llvm.org/D98733
void OmpStructureChecker::CheckIfDoOrderedClause(
const parser::OmpBlockDirective &blkDirective) {
if (blkDirective.v == llvm::omp::OMPD_ordered) {
- if (!FindClauseParent(llvm::omp::Clause::OMPC_ordered)) {
+ // Loops
+ if (llvm::omp::doSet.test(GetContextParent().directive) &&
+ !FindClauseParent(llvm::omp::Clause::OMPC_ordered)) {
context_.Say(blkDirective.source,
"The ORDERED clause must be present on the loop"
" construct if any ORDERED region ever binds"
" to a loop region arising from the loop construct."_err_en_US);
}
+ // Other disallowed nestings, these directives do not support
+ // ordered clause in them, so no need to check
+ else if (llvm::omp::nestedOrderedErrSet.test(
+ GetContextParent().directive)) {
+ context_.Say(blkDirective.source,
+ "`ORDERED` region may not be closely nested inside of "
+ "`CRITICAL`, `ORDERED`, explicit `TASK` or `TASKLOOP` region."_err_en_US);
+ }
}
}
Directive::OMPD_teams_distribute_simd};
static OmpDirectiveSet taskGeneratingSet{
OmpDirectiveSet{Directive::OMPD_task} | taskloopSet};
+static OmpDirectiveSet nestedOrderedErrSet{Directive::OMPD_critical,
+ Directive::OMPD_ordered, Directive::OMPD_atomic, Directive::OMPD_task,
+ Directive::OMPD_taskloop};
static OmpClauseSet privateSet{
Clause::OMPC_private, Clause::OMPC_firstprivate, Clause::OMPC_lastprivate};
static OmpClauseSet privateReductionSet{
--- /dev/null
+! RUN: %S/test_errors.sh %s %t %flang -fopenmp
+! OpenMP Version 4.5
+! Various checks with the ordered construct
+
+SUBROUTINE WORK(I)
+ INTEGER I
+END SUBROUTINE WORK
+
+SUBROUTINE ORDERED_GOOD(N)
+ INTEGER N, I, A(10), B(10), C(10)
+ !$OMP SIMD
+ DO I = 1,N
+ IF (I <= 10) THEN
+ !$OMP ORDERED SIMD
+ CALL WORK(I)
+ !$OMP END ORDERED
+ ENDIF
+ END DO
+ !$OMP END SIMD
+END SUBROUTINE ORDERED_GOOD
+
+SUBROUTINE ORDERED_BAD(N)
+ INTEGER N, I, A(10), B(10), C(10)
+
+ !$OMP DO SIMD
+ DO I = 1,N
+ IF (I <= 10) THEN
+ !ERROR: The ORDERED clause must be present on the loop construct if any ORDERED region ever binds to a loop region arising from the loop construct.
+ !$OMP ORDERED
+ CALL WORK(I)
+ !$OMP END ORDERED
+ ENDIF
+ END DO
+ !$OMP END DO SIMD
+
+ !$OMP PARALLEL DO
+ DO I = 1,N
+ IF (I <= 10) THEN
+ !ERROR: The ORDERED clause must be present on the loop construct if any ORDERED region ever binds to a loop region arising from the loop construct.
+ !$OMP ORDERED
+ CALL WORK(I)
+ !$OMP END ORDERED
+ ENDIF
+ END DO
+ !$OMP END PARALLEL DO
+
+ !$OMP CRITICAL
+ DO I = 1,N
+ IF (I <= 10) THEN
+ !ERROR: `ORDERED` region may not be closely nested inside of `CRITICAL`, `ORDERED`, explicit `TASK` or `TASKLOOP` region.
+ !$OMP ORDERED
+ CALL WORK(I)
+ !$OMP END ORDERED
+ ENDIF
+ END DO
+ !$OMP END CRITICAL
+
+ !$OMP CRITICAL
+ WRITE(*,*) I
+ !ERROR: `ORDERED` region may not be closely nested inside of `CRITICAL`, `ORDERED`, explicit `TASK` or `TASKLOOP` region.
+ !$OMP ORDERED
+ CALL WORK(I)
+ !$OMP END ORDERED
+ !$OMP END CRITICAL
+
+ !$OMP ORDERED
+ WRITE(*,*) I
+ IF (I <= 10) THEN
+ !ERROR: `ORDERED` region may not be closely nested inside of `CRITICAL`, `ORDERED`, explicit `TASK` or `TASKLOOP` region.
+ !$OMP ORDERED
+ CALL WORK(I)
+ !$OMP END ORDERED
+ ENDIF
+ !$OMP END ORDERED
+
+ !$OMP TASK
+ C = C - A * B
+ !ERROR: `ORDERED` region may not be closely nested inside of `CRITICAL`, `ORDERED`, explicit `TASK` or `TASKLOOP` region.
+ !$OMP ORDERED
+ CALL WORK(I)
+ !$OMP END ORDERED
+ !$OMP END TASK
+
+ !$OMP TASKLOOP
+ DO I = 1,N
+ IF (I <= 10) THEN
+ !ERROR: `ORDERED` region may not be closely nested inside of `CRITICAL`, `ORDERED`, explicit `TASK` or `TASKLOOP` region.
+ !$OMP ORDERED
+ CALL WORK(I)
+ !$OMP END ORDERED
+ ENDIF
+ END DO
+ !$OMP END TASKLOOP
+
+END SUBROUTINE ORDERED_BAD