Index: flang/lib/Semantics/check-omp-structure.h =================================================================== --- flang/lib/Semantics/check-omp-structure.h +++ flang/lib/Semantics/check-omp-structure.h @@ -76,6 +76,9 @@ static OmpDirectiveSet nestedOrderedErrSet{Directive::OMPD_critical, Directive::OMPD_ordered, Directive::OMPD_atomic, Directive::OMPD_task, Directive::OMPD_taskloop}; +static OmpDirectiveSet nestedMasterErrSet{ + OmpDirectiveSet{Directive::OMPD_atomic} | taskGeneratingSet | parallelSet | + doSet}; static OmpClauseSet privateSet{ Clause::OMPC_private, Clause::OMPC_firstprivate, Clause::OMPC_lastprivate}; static OmpClauseSet privateReductionSet{ @@ -200,6 +203,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); Index: flang/lib/Semantics/check-omp-structure.cpp =================================================================== --- flang/lib/Semantics/check-omp-structure.cpp +++ flang/lib/Semantics/check-omp-structure.cpp @@ -366,8 +366,10 @@ HasInvalidWorksharingNesting( beginDir.source, {llvm::omp::Directive::OMPD_do}); } - if (CurrentDirectiveIsNested()) + if (CurrentDirectiveIsNested()) { CheckIfDoOrderedClause(beginDir); + CheckMasterNesting(x); + } CheckNoBranching(block, beginDir.v, beginDir.source); @@ -381,6 +383,22 @@ } } +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 (GetContext().directive == llvm::omp::Directive::OMPD_master) { + 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) { Index: flang/test/Semantics/omp-clause-validity01.f90 =================================================================== --- flang/test/Semantics/omp-clause-validity01.f90 +++ flang/test/Semantics/omp-clause-validity01.f90 @@ -461,12 +461,14 @@ ! 2.13.1 master !$omp parallel + !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region. !$omp master a=3.14 !$omp end master !$omp end parallel !$omp parallel + !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region. !ERROR: NUM_THREADS clause is not allowed on the MASTER directive !$omp master num_threads(4) a=3.14 Index: flang/test/Semantics/omp-flush02.f90 =================================================================== --- flang/test/Semantics/omp-flush02.f90 +++ flang/test/Semantics/omp-flush02.f90 @@ -78,6 +78,7 @@ !$omp parallel num_threads(4) array = (/1, 2, 3, 4, 5, 6, 7, 8, 9, 10/) + !ERROR: `MASTER` region may not be closely nested inside of `WORKSHARING`, `LOOP`, `TASK`, `TASKLOOP`, or `ATOMIC` region. !$omp master !$omp flush (array) !$omp end master Index: flang/test/Semantics/omp-nested-master.f90 =================================================================== --- /dev/null +++ flang/test/Semantics/omp-nested-master.f90 @@ -0,0 +1,147 @@ +! 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 do simd + 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 parallel 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 parallel do simd + 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 parallel + 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 parallel + + !$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 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 distribute + do k =1, 10 + print *, "hello" + !$omp master + j = j -1 + !$omp end master + end do + !$omp end distribute + end do + !$omp end ordered + + !$omp critical + do i = 1, 10 + !$omp distribute + do k =1, 10 + print *, "hello" + !$omp master + j = j -1 + !$omp end master + end do + !$omp end distribute + end do + !$omp end critical + + !$omp taskloop + do i = 1, 10 + !$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 + end do + !$omp end taskloop + + !$omp task + do i = 1, 10 + !$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 + end do + !$omp end task + +end program omp_nest_master