diff --git a/flang/lib/Semantics/resolve-directives.cpp b/flang/lib/Semantics/resolve-directives.cpp index 401d4d825b57..1fde0d62581e 100644 --- a/flang/lib/Semantics/resolve-directives.cpp +++ b/flang/lib/Semantics/resolve-directives.cpp @@ -421,6 +421,37 @@ public: ultSym.flags().test(Symbol::Flag::InCommonBlock); } + static const Symbol &GetStorageOwner(const Symbol &symbol) { + static auto getParent = [](const Symbol *s) -> const Symbol * { + if (auto *details{s->detailsIf()}) { + return &details->symbol(); + } else if (auto *details{s->detailsIf()}) { + return &details->symbol(); + } else { + return nullptr; + } + }; + static auto isPrivate = [](const Symbol &symbol) { + static const Symbol::Flags privatizing{Symbol::Flag::OmpPrivate, + Symbol::Flag::OmpFirstPrivate, Symbol::Flag::OmpLastPrivate, + Symbol::Flag::OmpLinear}; + return (symbol.flags() & privatizing).any(); + }; + + const Symbol *sym = &symbol; + while (true) { + if (isPrivate(*sym)) { + return *sym; + } + if (const Symbol *parent{getParent(sym)}) { + sym = parent; + } else { + return *sym; + } + } + llvm_unreachable("Error while looking for storage owning symbol"); + } + // Recognize symbols that are not created as a part of the OpenMP data- // sharing processing, and that are declared inside of the construct. // These symbols are predetermined private, but they shouldn't be marked @@ -428,8 +459,13 @@ public: // They are not symbols for which private copies need to be created, // they are already themselves private. static bool IsLocalInsideScope(const Symbol &symbol, const Scope &scope) { - return symbol.owner() != scope && scope.Contains(symbol.owner()) && - !HasStaticStorageDuration(symbol); + // A symbol that is marked with a DSA will be cloned in the construct + // scope and marked as host-associated. This applies to privatized symbols + // as well even though they will have their own storage. They should be + // considered local regardless of the status of the original symbol. + const Symbol &actual{GetStorageOwner(symbol)}; + return actual.owner() != scope && scope.Contains(actual.owner()) && + !HasStaticStorageDuration(actual); } template void Walk(const A &x) { parser::Walk(x, *this); } diff --git a/flang/test/Semantics/OpenMP/local-variables.f90 b/flang/test/Semantics/OpenMP/local-variables-1.f90 similarity index 100% rename from flang/test/Semantics/OpenMP/local-variables.f90 rename to flang/test/Semantics/OpenMP/local-variables-1.f90 diff --git a/flang/test/Semantics/OpenMP/local-variables-2.f90 b/flang/test/Semantics/OpenMP/local-variables-2.f90 new file mode 100644 index 000000000000..1924b5782d16 --- /dev/null +++ b/flang/test/Semantics/OpenMP/local-variables-2.f90 @@ -0,0 +1,52 @@ +!RUN: %flang_fc1 -fdebug-unparse-with-symbols -fopenmp -fopenmp-version=60 %s | FileCheck %s + +! Shortened version of Fujitsu/Fortran/0160/0160_0000.f90 +! Make sure that j is privatized. + +!CHECK-LABEL: !DEF: /MAIN MainProgram +!CHECK-NEXT: program MAIN +!CHECK-NEXT: implicit none +!CHECK-NEXT: !DEF: /MAIN/j ObjectEntity INTEGER(4) +!CHECK-NEXT: !DEF: /MAIN/k ObjectEntity INTEGER(4) +!CHECK-NEXT: !DEF: /MAIN/ndim ObjectEntity INTEGER(4) +!CHECK-NEXT: integer j, k, ndim +!CHECK-NEXT: !DEF: /MAIN/flux (Subroutine) Subprogram +!CHECK-NEXT: call flux +!CHECK-NEXT: contains +!CHECK-NEXT: !REF: /MAIN/flux +!CHECK-NEXT: subroutine flux +!CHECK-NEXT: !$omp parallel +!CHECK-NEXT: !$omp do +!CHECK-NEXT: !DEF: /MAIN/flux/OtherConstruct1/OtherConstruct1/k (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) +!CHECK-NEXT: !DEF: /MAIN/flux/OtherConstruct1/OtherConstruct1/ndim HostAssoc INTEGER(4) +!CHECK-NEXT: do k=-1,ndim+1 +!CHECK-NEXT: !DEF: /MAIN/flux/OtherConstruct1/OtherConstruct1/j (OmpPrivate, OmpPreDetermined) HostAssoc INTEGER(4) +!CHECK-NEXT: !REF: /MAIN/flux/OtherConstruct1/OtherConstruct1/ndim +!CHECK-NEXT: do j=-1,ndim+1 +!CHECK-NEXT: end do +!CHECK-NEXT: end do +!CHECK-NEXT: !$omp end do +!CHECK-NEXT: !$omp end parallel +!CHECK-NEXT: end subroutine flux +!CHECK-NEXT: end program MAIN + +program main + implicit none + integer :: j, k, ndim + + call flux() + + contains + + subroutine flux + !$omp parallel + !$omp do + do k = -1, ndim + 1 + do j = -1, ndim + 1 + enddo + enddo + !$omp end do + !$omp end parallel + end subroutine flux + +end program main