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 @@ -265,6 +265,7 @@ bool Pre(const parser::ModuleSubprogram &) { // Clear the labels being tracked in the previous scope + ClearThreadPrivateSymbols(); ClearLabels(); return true; } @@ -475,6 +476,10 @@ sourceLabels_.clear(); targetLabels_.clear(); }; + + void ClearThreadPrivateSymbols() { threadPrivateSymbols.clear(); } + std::set threadPrivateSymbols; + std::int64_t ordCollapseLevel{0}; }; template @@ -1071,6 +1076,7 @@ ClearDataSharingAttributeObjects(); SetContextAssociatedLoopLevel(GetAssociatedLoopLevelFromClauses(clauseList)); PrivatizeAssociatedLoopIndexAndCheckLoopLevel(x); + ordCollapseLevel = GetAssociatedLoopLevelFromClauses(clauseList) + 1; return true; } @@ -1114,6 +1120,16 @@ } else { // TODO: conflict checks with explicitly determined DSA } + ordCollapseLevel--; + if (ordCollapseLevel) { + for (const auto *tps : threadPrivateSymbols) { + if (iv.symbol->name() == tps->name()) { + context_.Say(iv.source, + "Loop iteration variable %s is not allowed in THREADPRIVATE."_err_en_US, + iv.ToString()); + } + } + } } } } @@ -1231,6 +1247,13 @@ PushContext(x.source, llvm::omp::Directive::OMPD_threadprivate); const auto &list{std::get(x.t)}; ResolveOmpObjectList(list, Symbol::Flag::OmpThreadprivate); + for (const auto &ompObject : list.v) { + if (const auto *name{parser::Unwrap(ompObject)}) { + if (name->symbol) { + threadPrivateSymbols.emplace(name->symbol); + } + } + } return true; } diff --git a/flang/test/Semantics/omp-do04-positivecase.f90 b/flang/test/Semantics/omp-do04-positivecase.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Semantics/omp-do04-positivecase.f90 @@ -0,0 +1,22 @@ +! RUN: %S/test_symbols.sh %s %t %f18 -fopenmp +! OpenMP Version 4.5 +! 2.7.1 Do Loop Constructs + +!DEF: /omp_do1 MainProgram +program omp_do1 + !DEF: /omp_do1/i ObjectEntity INTEGER(4) + !DEF: /omp_do1/j ObjectEntity INTEGER(4) + !DEF: /omp_do1/k (OmpThreadprivate) ObjectEntity INTEGER(4) + !DEF: /omp_do1/n (OmpThreadprivate) ObjectEntity INTEGER(4) + integer i, j, k, n + !$omp threadprivate (k,n) + !$omp do + !DEF: /omp_do1/Block1/i (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) + do i=1,10 + !REF: /omp_do1/j + do j=1,10 + print *, "Hello" + end do + end do + !$omp end do +end program omp_do1 diff --git a/flang/test/Semantics/omp-do04.f90 b/flang/test/Semantics/omp-do04.f90 --- a/flang/test/Semantics/omp-do04.f90 +++ b/flang/test/Semantics/omp-do04.f90 @@ -1,15 +1,27 @@ -! RUN: %S/test_errors.sh %s %t %flang -fopenmp -! XFAIL: * - +! RUN: %S/test_errors.sh %s %t %f18 -fopenmp ! OpenMP Version 4.5 ! 2.7.1 Loop Construct ! The loop iteration variable may not appear in a threadprivate directive. + program omp_do - integer i, j, k + integer, save:: i, j, k,n + !$omp threadprivate(k,j,i) + !$omp do collapse(2) + !ERROR: Loop iteration variable i is not allowed in THREADPRIVATE. + do i = 1, 10 + !ERROR: Loop iteration variable j is not allowed in THREADPRIVATE. + do j = 1, 10 + print *, "Hello" + end do + end do + !$omp end do +end program omp_do - !$omp do firstprivate(i) - !ERROR: !$OMP DO iteration variable i is not allowed in threadprivate +program omp_do1 + !$omp threadprivate(k,j,i) + !$omp do + !ERROR: Loop iteration variable i is not allowed in THREADPRIVATE. do i = 1, 10 do j = 1, 10 print *, "Hello" @@ -17,4 +29,38 @@ end do !$omp end do -end program omp_do +end program omp_do1 + +program omp_do2 + !$omp threadprivate(k) + !$omp threadprivate(j) + call compute() + contains + subroutine compute() + !$omp do ordered(1) collapse(1) + !ERROR: Loop iteration variable k is not allowed in THREADPRIVATE. + foo: do k = 1, 10 + do i = 1, 10 + print *, "Hello" + end do + end do foo + !$omp end do + end subroutine + +end program omp_do2 + +program omp_do3 + !$omp threadprivate(i) + !$omp parallel + print *, "parallel" + !$omp end parallel + !$omp do + !ERROR: Loop iteration variable i is not allowed in THREADPRIVATE. + do i = 1, 10 + do j = 1, 10 + print *, "Hello" + end do + end do + !$omp end do + +end program omp_do3