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 @@ -82,6 +82,17 @@ Directive::OMPD_teams_distribute_parallel_do, Directive::OMPD_teams_distribute_parallel_do_simd, Directive::OMPD_teams_distribute_simd}; +static OmpDirectiveSet distributeSet{Directive::OMPD_distribute, + Directive::OMPD_distribute_parallel_do, + Directive::OMPD_distribute_parallel_do_simd, + Directive::OMPD_distribute_simd, Directive::OMPD_target_teams_distribute, + Directive::OMPD_target_teams_distribute_parallel_do, + Directive::OMPD_target_teams_distribute_parallel_do_simd, + Directive::OMPD_target_teams_distribute_simd, + Directive::OMPD_teams_distribute, + Directive::OMPD_teams_distribute_parallel_do, + Directive::OMPD_teams_distribute_parallel_do_simd, + Directive::OMPD_teams_distribute_simd}; static OmpDirectiveSet taskGeneratingSet{ OmpDirectiveSet{Directive::OMPD_task} | taskloopSet}; static OmpDirectiveSet nestedOrderedErrSet{Directive::OMPD_critical, diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -1866,6 +1866,17 @@ "clauses on a TARGET DATA construct"_err_en_US, symbol->name()); } + if (llvm::omp::distributeSet.test(GetContext().directive) && + (((ompFlag == Symbol::Flag::OmpFirstPrivate) && + symbol->test(Symbol::Flag::OmpLastPrivate)) || + ((ompFlag == Symbol::Flag::OmpLastPrivate) && + symbol->test(Symbol::Flag::OmpFirstPrivate)))) { + context_.Say(designator.source, + "Variable '%s' may not " + "appear on both FIRSTPRIVATE and LASTPRIVATE " + "clauses on a DISTRIBUTE construct"_err_en_US, + symbol->name()); + } } } else { // Array sections to be changed to substrings as needed diff --git a/flang/test/Semantics/OpenMP/firstprivate01.f90 b/flang/test/Semantics/OpenMP/firstprivate01.f90 --- a/flang/test/Semantics/OpenMP/firstprivate01.f90 +++ b/flang/test/Semantics/OpenMP/firstprivate01.f90 @@ -4,6 +4,9 @@ ! Variables that appear in a firstprivate clause on a distribute or ! worksharing constructs must not appear in the private or ! reduction clause in a teams or parallel constructs in the outer context +! +! A list item may appear in a firstprivate or lastprivate clause but not both on +! a distribute directive program omp_firstprivate integer :: i, a(10), b(10), c(10) @@ -29,6 +32,38 @@ end do !$omp end distribute !$omp end teams + + !$omp teams distribute firstprivate(a) lastprivate(b) + do i = 1, 10 + a(i) = a(i) + b(i) - i + end do + !$omp end teams distribute + !ERROR: Variable 'b' may not appear on both FIRSTPRIVATE and LASTPRIVATE clauses on a DISTRIBUTE construct + !$omp teams distribute firstprivate(a,b) lastprivate(b) + do i = 1, 10 + a(i) = a(i) + b(i) - i + end do + !$omp end teams distribute + !ERROR: Variable 'a' may not appear on both FIRSTPRIVATE and LASTPRIVATE clauses on a DISTRIBUTE construct + !ERROR: Variable 'b' may not appear on both FIRSTPRIVATE and LASTPRIVATE clauses on a DISTRIBUTE construct + !$omp teams distribute firstprivate(a,b) lastprivate(a,b) + do i = 1, 10 + a(i) = a(i) + b(i) - i + end do + !$omp end teams distribute + !ERROR: Variable 'b' may not appear on both FIRSTPRIVATE and LASTPRIVATE clauses on a DISTRIBUTE construct + !$omp teams distribute lastprivate(a,b) firstprivate(b) + do i = 1, 10 + a(i) = a(i) + b(i) - i + end do + !$omp end teams distribute + !ERROR: Variable 'b' may not appear on both FIRSTPRIVATE and LASTPRIVATE clauses on a DISTRIBUTE construct + !ERROR: Variable 'a' may not appear on both FIRSTPRIVATE and LASTPRIVATE clauses on a DISTRIBUTE construct + !$omp teams distribute lastprivate(a,b) firstprivate(b,a) + do i = 1, 10 + a(i) = a(i) + b(i) - i + end do + !$omp end teams distribute !$omp end target print *, a, b