diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -93,6 +93,9 @@ Directive::OMPD_critical, Directive::OMPD_ordered, Directive::OMPD_atomic, Directive::OMPD_master} | workShareSet}; +static OmpDirectiveSet nestedMasterErrSet{ + OmpDirectiveSet{llvm::omp::Directive::OMPD_atomic} | taskGeneratingSet | + workShareSet}; static OmpClauseSet privateSet{ Clause::OMPC_private, Clause::OMPC_firstprivate, Clause::OMPC_lastprivate}; static OmpClauseSet privateReductionSet{ @@ -222,6 +225,7 @@ bool CheckIntrinsicOperator( const parser::DefinedOperator::IntrinsicOperator &); void CheckReductionTypeList(const parser::OmpClause::Reduction &); + void CheckMasterNesting(const parser::OpenMPBlockConstruct &x); void CheckReductionArraySection(const parser::OmpObjectList &ompObjectList); void CheckIntentInPointerAndDefinable( const parser::OmpObjectList &, const llvm::omp::Clause); diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -504,6 +504,9 @@ if (llvm::omp::teamSet.test(GetContextParent().directive)) { HasInvalidTeamsNesting(beginDir.v, beginDir.source); } + if (GetContext().directive == llvm::omp::Directive::OMPD_master) { + CheckMasterNesting(x); + } } CheckNoBranching(block, beginDir.v, beginDir.source); @@ -526,6 +529,20 @@ } } +void OmpStructureChecker::CheckMasterNesting( + const parser::OpenMPBlockConstruct &x) { + // A MASTER region may not be `closely nested` inside a worksharing, loop, + // task, taskloop, or atomic region. + // TODO: Expand the check to include `LOOP` construct as well when it is + // supported. + if (IsCloselyNestedRegion(llvm::omp::nestedMasterErrSet)) { + context_.Say(parser::FindSourceLocation(x), + "`MASTER` region may not be closely nested inside of `WORKSHARING`, " + "`LOOP`, `TASK`, `TASKLOOP`," + " or `ATOMIC` region."_err_en_US); + } +} + void OmpStructureChecker::CheckIfDoOrderedClause( const parser::OmpBlockDirective &blkDirective) { if (blkDirective.v == llvm::omp::OMPD_ordered) { diff --git a/flang/test/Semantics/omp-nested-master.f90 b/flang/test/Semantics/omp-nested-master.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/omp-nested-master.f90 @@ -0,0 +1,149 @@ +! RUN: %S/test_errors.sh %s %t %flang_fc1 -fopenmp +! OpenMP Version 4.5 +! Various checks with the nesting of MASTER construct + +program omp_nest_master + integer i, k, j + k = 0; + + !$omp do + do i = 1, 10 + k = k + 1 + !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region. + !$omp master + j = j -1 + !$omp end master + end do + + !$omp sections + !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region. + !$omp master + do i = 1, 10 + k = k + 1 + end do + !$omp end master + !$omp end sections + + !$omp single + !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region. + !$omp master + do i = 1, 10 + k = k + 1 + end do + !$omp end master + !$omp end single + + + + !$omp task + do i = 1, 10 + k = k + 1 + !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region. + !$omp master + j = j -1 + !$omp end master + end do + !$omp end task + + !$omp taskloop + do i = 1, 10 + k = k + 1 + !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region. + !$omp master + j = j -1 + !$omp end master + end do + !$omp end taskloop + + !$omp target parallel do simd + do i = 1, 10 + k = k + 1 + !ERROR: The only OpenMP constructs that can be encountered during execution of a 'SIMD' region are the `ATOMIC` construct, the `LOOP` construct, the `SIMD` construct and the `ORDERED` construct with the `SIMD` clause. + !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region. + !$omp master + j = j -1 + !$omp end master + end do + !$omp end target parallel do simd + + !$omp critical + do i = 1, 10 + k = k + 1 + !$omp master + j = j -1 + !$omp end master + end do + !$omp end critical + + !$omp ordered + do i = 1, 10 + k = k + 1 + !$omp master + j = j -1 + !$omp end master + end do + !$omp end ordered + + !$omp ordered + do i = 1, 10 + !$omp teams + !$omp distribute + do k =1, 10 + print *, "hello" + !$omp master + j = j -1 + !$omp end master + end do + !$omp end distribute + !$omp end teams + end do + !$omp end ordered + + !$omp critical + do i = 1, 10 + !$omp teams + !$omp distribute + do k =1, 10 + print *, "hello" + !$omp master + j = j -1 + !$omp end master + end do + !$omp end distribute + !$omp end teams + end do + !$omp end critical + + !$omp taskloop + do i = 1, 10 + !$omp teams + !$omp distribute + do k =1, 10 + print *, "hello" + !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region. + !$omp master + j = j -1 + !$omp end master + end do + !$omp end distribute + !$omp end teams + end do + !$omp end taskloop + + !$omp task + do i = 1, 10 + !$omp teams + !$omp distribute + do k =1, 10 + print *, "hello" + !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region. + !$omp master + j = j -1 + !$omp end master + end do + !$omp end distribute + !$omp end teams + end do + !$omp end task + +end program omp_nest_master diff --git a/flang/test/Semantics/omp-ordered-simd.f90 b/flang/test/Semantics/omp-ordered-simd.f90 --- a/flang/test/Semantics/omp-ordered-simd.f90 +++ b/flang/test/Semantics/omp-ordered-simd.f90 @@ -119,6 +119,7 @@ !$OMP TASK C = C - A * B + !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region. !$OMP MASTER DO I = 1,N !ERROR: `ORDERED` region may not be closely nested inside of `CRITICAL`, `ORDERED`, explicit `TASK` or `TASKLOOP` region. @@ -132,6 +133,7 @@ !$OMP TASKLOOP DO J= 1,N C = C - A * B + !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region. !$OMP MASTER DO I = 1,N !ERROR: `ORDERED` region may not be closely nested inside of `CRITICAL`, `ORDERED`, explicit `TASK` or `TASKLOOP` region.