Prince781 created this revision. Prince781 added reviewers: ABataev, rsmith. Prince781 added projects: clang, OpenMP. Herald added subscribers: cfe-commits, jdoerfert, guansong.
The following example compiles incorrectly since at least clang 8.0.0: #include <stdio.h> #include <omp.h> #define N 100 int main(void) { int i; int arr[N]; #pragma omp parallel // shared(i) shared(arr) #pragma omp for // private(i) for (i = 0; i < N; i++) { #pragma omp task // firstprivate(i) shared(arr) { printf("[thread %2d] i = %d\n", omp_get_thread_num(), i); arr[i] = i; } } for (i = 0; i < N; i++) { if (arr[i] != i) { fprintf(stderr, "FAIL: arr[%d] == %d\n", i, arr[i]); } } } The iteration variable, `i`, should become `private` at the `omp for` construct and then become implicit `firstprivate` within the task region. What happens instead is that `i` is never privatized within the task construct. As the task construct is parsed, when a reference to `i` is determined, the implicit data-sharing attributes are computed incorrectly. Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D64889 Files: clang/lib/Sema/SemaOpenMP.cpp Index: clang/lib/Sema/SemaOpenMP.cpp =================================================================== --- clang/lib/Sema/SemaOpenMP.cpp +++ clang/lib/Sema/SemaOpenMP.cpp @@ -424,6 +424,11 @@ /// for-loops (from outer to inner). const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const; /// Check if the specified variable is a loop control variable for + /// given region. + /// \return The index of the loop control variable in the list of associated + /// for-loops (from outer to inner). + const LCDeclInfo isLoopControlVariable(const ValueDecl *D, const SharingMapTy &Region) const; + /// Check if the specified variable is a loop control variable for /// parent region. /// \return The index of the loop control variable in the list of associated /// for-loops (from outer to inner). @@ -946,11 +951,24 @@ case DSA_none: return DVar; case DSA_unspecified: + DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct, implicitly determined] + // The loop iteration variable(s) in the associated for-loop(s) of a for or + // parallel for construct is (are) private. + // OpenMP 5.0 includes taskloop and distribute directives + if (!isOpenMPSimdDirective(DVar.DKind) && + isOpenMPLoopDirective(DVar.DKind) && + isLoopControlVariable(D, *Iter).first) { + DVar.CKind = OMPC_private; + // TODO: OpenMP 5.0: if (Dvar.DKind == OMPD_loop) DVar.CKind = OMPC_lastprivate; + return DVar; + } + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct, implicitly determined, p.2] // In a parallel construct, if no default clause is present, these // variables are shared. - DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; if (isOpenMPParallelDirective(DVar.DKind) || isOpenMPTeamsDirective(DVar.DKind)) { DVar.CKind = OMPC_shared; @@ -1018,8 +1036,13 @@ const DSAStackTy::LCDeclInfo DSAStackTy::isLoopControlVariable(const ValueDecl *D) const { assert(!isStackEmpty() && "Data-sharing attributes stack is empty"); + return isLoopControlVariable(D, getTopOfStack()); +} + +const DSAStackTy::LCDeclInfo +DSAStackTy::isLoopControlVariable(const ValueDecl *D, const SharingMapTy &Region) const { D = getCanonicalDecl(D); - const SharingMapTy &StackElem = getTopOfStack(); + const SharingMapTy &StackElem = Region; auto It = StackElem.LCVMap.find(D); if (It != StackElem.LCVMap.end()) return It->second;
Index: clang/lib/Sema/SemaOpenMP.cpp =================================================================== --- clang/lib/Sema/SemaOpenMP.cpp +++ clang/lib/Sema/SemaOpenMP.cpp @@ -424,6 +424,11 @@ /// for-loops (from outer to inner). const LCDeclInfo isLoopControlVariable(const ValueDecl *D) const; /// Check if the specified variable is a loop control variable for + /// given region. + /// \return The index of the loop control variable in the list of associated + /// for-loops (from outer to inner). + const LCDeclInfo isLoopControlVariable(const ValueDecl *D, const SharingMapTy &Region) const; + /// Check if the specified variable is a loop control variable for /// parent region. /// \return The index of the loop control variable in the list of associated /// for-loops (from outer to inner). @@ -946,11 +951,24 @@ case DSA_none: return DVar; case DSA_unspecified: + DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced + // in a Construct, implicitly determined] + // The loop iteration variable(s) in the associated for-loop(s) of a for or + // parallel for construct is (are) private. + // OpenMP 5.0 includes taskloop and distribute directives + if (!isOpenMPSimdDirective(DVar.DKind) && + isOpenMPLoopDirective(DVar.DKind) && + isLoopControlVariable(D, *Iter).first) { + DVar.CKind = OMPC_private; + // TODO: OpenMP 5.0: if (Dvar.DKind == OMPD_loop) DVar.CKind = OMPC_lastprivate; + return DVar; + } + // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced // in a Construct, implicitly determined, p.2] // In a parallel construct, if no default clause is present, these // variables are shared. - DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; if (isOpenMPParallelDirective(DVar.DKind) || isOpenMPTeamsDirective(DVar.DKind)) { DVar.CKind = OMPC_shared; @@ -1018,8 +1036,13 @@ const DSAStackTy::LCDeclInfo DSAStackTy::isLoopControlVariable(const ValueDecl *D) const { assert(!isStackEmpty() && "Data-sharing attributes stack is empty"); + return isLoopControlVariable(D, getTopOfStack()); +} + +const DSAStackTy::LCDeclInfo +DSAStackTy::isLoopControlVariable(const ValueDecl *D, const SharingMapTy &Region) const { D = getCanonicalDecl(D); - const SharingMapTy &StackElem = getTopOfStack(); + const SharingMapTy &StackElem = Region; auto It = StackElem.LCVMap.find(D); if (It != StackElem.LCVMap.end()) return It->second;
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits