diff options
author | Alexey Bataev <a.bataev@hotmail.com> | 2014-07-11 11:25:16 +0000 |
---|---|---|
committer | Alexey Bataev <a.bataev@hotmail.com> | 2014-07-11 11:25:16 +0000 |
commit | 9c2e8ee72fe8c99a016a204a2f2b167cd17e188a (patch) | |
tree | 813773957814bc63d730a1a0476cb5fa60cf8d2f /clang/lib/Sema | |
parent | 83442bb8b2e5284276d3eb5a97457401ed61d3f7 (diff) | |
download | bcm5719-llvm-9c2e8ee72fe8c99a016a204a2f2b167cd17e188a.tar.gz bcm5719-llvm-9c2e8ee72fe8c99a016a204a2f2b167cd17e188a.zip |
[OPENMP] Parsing and sema analysis for 'omp task' directive.
llvm-svn: 212804
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 298 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 11 |
2 files changed, 222 insertions, 87 deletions
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index a7ad809778d..f0650148873 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -139,21 +139,22 @@ public: /// \brief Returns data sharing attributes from top of the stack for the /// specified declaration. - DSAVarData getTopDSA(VarDecl *D); + DSAVarData getTopDSA(VarDecl *D, bool FromParent); /// \brief Returns data-sharing attributes for the specified declaration. - DSAVarData getImplicitDSA(VarDecl *D); + DSAVarData getImplicitDSA(VarDecl *D, bool FromParent); /// \brief Checks if the specified variables has data-sharing attributes which /// match specified \a CPred predicate in any directive which matches \a DPred /// predicate. template <class ClausesPredicate, class DirectivesPredicate> DSAVarData hasDSA(VarDecl *D, ClausesPredicate CPred, - DirectivesPredicate DPred); + DirectivesPredicate DPred, bool FromParent); /// \brief Checks if the specified variables has data-sharing attributes which /// match specified \a CPred predicate in any innermost directive which /// matches \a DPred predicate. template <class ClausesPredicate, class DirectivesPredicate> DSAVarData hasInnermostDSA(VarDecl *D, ClausesPredicate CPred, - DirectivesPredicate DPred); + DirectivesPredicate DPred, + bool FromParent); /// \brief Returns currently analyzed directive. OpenMPDirectiveKind getCurrentDirective() const { @@ -186,7 +187,7 @@ public: /// \brief Checks if the specified variable is a threadprivate. bool isThreadPrivate(VarDecl *D) { - DSAVarData DVar = getTopDSA(D); + DSAVarData DVar = getTopDSA(D, false); return isOpenMPThreadPrivate(DVar.CKind); } @@ -194,6 +195,10 @@ public: Scope *getCurScope() { return Stack.back().CurScope; } SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; } }; +bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) { + return isOpenMPParallelDirective(DKind) || DKind == OMPD_task || + DKind == OMPD_unknown; +} } // namespace DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter, @@ -234,6 +239,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter, if (Iter->SharingMap.count(D)) { DVar.RefExpr = Iter->SharingMap[D].RefExpr; DVar.CKind = Iter->SharingMap[D].Attributes; + DVar.ImplicitDSALoc = Iter->DefaultAttrLoc; return DVar; } @@ -282,7 +288,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator Iter, DVar.CKind = OMPC_firstprivate; return DVar; } - if (isOpenMPParallelDirective(I->Directive)) + if (isParallelOrTaskRegion(I->Directive)) break; } DVar.DKind = OMPD_task; @@ -328,7 +334,7 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) { if (Stack.size() > 2) { reverse_iterator I = Iter, E = std::prev(Stack.rend()); Scope *TopScope = nullptr; - while (I != E && !isOpenMPParallelDirective(I->Directive)) { + while (I != E && !isParallelOrTaskRegion(I->Directive)) { ++I; } if (I == E) @@ -343,7 +349,7 @@ bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) { return false; } -DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) { +DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D, bool FromParent) { DSAVarData DVar; // OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced @@ -363,9 +369,15 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) { // in a Construct, C/C++, predetermined, p.1] // Variables with automatic storage duration that are declared in a scope // inside the construct are private. - OpenMPDirectiveKind Kind = getCurrentDirective(); - if (!isOpenMPParallelDirective(Kind)) { - if (isOpenMPLocal(D, std::next(Stack.rbegin())) && D->isLocalVarDecl() && + OpenMPDirectiveKind Kind = + FromParent ? getParentDirective() : getCurrentDirective(); + auto StartI = std::next(Stack.rbegin()); + auto EndI = std::prev(Stack.rend()); + if (FromParent && StartI != EndI) { + StartI = std::next(StartI); + } + if (!isParallelOrTaskRegion(Kind)) { + if (isOpenMPLocal(D, StartI) && D->isLocalVarDecl() && (D->getStorageClass() == SC_Auto || D->getStorageClass() == SC_None)) { DVar.CKind = OMPC_private; return DVar; @@ -378,8 +390,8 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) { if (D->isStaticDataMember()) { // Variables with const-qualified type having no mutable member may be // listed in a firstprivate clause, even if they are static data members. - DSAVarData DVarTemp = - hasDSA(D, MatchesAnyClause(OMPC_firstprivate), MatchesAlways()); + DSAVarData DVarTemp = hasDSA(D, MatchesAnyClause(OMPC_firstprivate), + MatchesAlways(), FromParent); if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr) return DVar; @@ -403,8 +415,8 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) { !(SemaRef.getLangOpts().CPlusPlus && RD && RD->hasMutableFields())) { // Variables with const-qualified type having no mutable member may be // listed in a firstprivate clause, even if they are static data members. - DSAVarData DVarTemp = - hasDSA(D, MatchesAnyClause(OMPC_firstprivate), MatchesAlways()); + DSAVarData DVarTemp = hasDSA(D, MatchesAnyClause(OMPC_firstprivate), + MatchesAlways(), FromParent); if (DVarTemp.CKind == OMPC_firstprivate && DVarTemp.RefExpr) return DVar; @@ -423,25 +435,36 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(VarDecl *D) { // Explicitly specified attributes and local variables with predetermined // attributes. - if (Stack.back().SharingMap.count(D)) { - DVar.RefExpr = Stack.back().SharingMap[D].RefExpr; - DVar.CKind = Stack.back().SharingMap[D].Attributes; + auto I = std::prev(StartI); + if (I->SharingMap.count(D)) { + DVar.RefExpr = I->SharingMap[D].RefExpr; + DVar.CKind = I->SharingMap[D].Attributes; + DVar.ImplicitDSALoc = I->DefaultAttrLoc; } return DVar; } -DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(VarDecl *D) { - return getDSA(std::next(Stack.rbegin()), D); +DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(VarDecl *D, bool FromParent) { + auto StartI = Stack.rbegin(); + auto EndI = std::prev(Stack.rend()); + if (FromParent && StartI != EndI) { + StartI = std::next(StartI); + } + return getDSA(StartI, D); } template <class ClausesPredicate, class DirectivesPredicate> DSAStackTy::DSAVarData DSAStackTy::hasDSA(VarDecl *D, ClausesPredicate CPred, - DirectivesPredicate DPred) { - for (StackTy::reverse_iterator I = std::next(Stack.rbegin()), - E = std::prev(Stack.rend()); - I != E; ++I) { - if (!DPred(I->Directive)) + DirectivesPredicate DPred, + bool FromParent) { + auto StartI = std::next(Stack.rbegin()); + auto EndI = std::prev(Stack.rend()); + if (FromParent && StartI != EndI) { + StartI = std::next(StartI); + } + for (auto I = StartI, EE = EndI; I != EE; ++I) { + if (!DPred(I->Directive) && !isParallelOrTaskRegion(I->Directive)) continue; DSAVarData DVar = getDSA(I, D); if (CPred(DVar.CKind)) @@ -451,12 +474,17 @@ DSAStackTy::DSAVarData DSAStackTy::hasDSA(VarDecl *D, ClausesPredicate CPred, } template <class ClausesPredicate, class DirectivesPredicate> -DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(VarDecl *D, - ClausesPredicate CPred, - DirectivesPredicate DPred) { - for (auto I = Stack.rbegin(), EE = std::prev(Stack.rend()); I != EE; ++I) { +DSAStackTy::DSAVarData +DSAStackTy::hasInnermostDSA(VarDecl *D, ClausesPredicate CPred, + DirectivesPredicate DPred, bool FromParent) { + auto StartI = std::next(Stack.rbegin()); + auto EndI = std::prev(Stack.rend()); + if (FromParent && StartI != EndI) { + StartI = std::next(StartI); + } + for (auto I = StartI, EE = EndI; I != EE; ++I) { if (!DPred(I->Directive)) - continue; + break; DSAVarData DVar = getDSA(I, D); if (CPred(DVar.CKind)) return DVar; @@ -493,7 +521,7 @@ void Sema::EndOpenMPDSABlock(Stmt *CurDirective) { if (VarRef->isValueDependent() || VarRef->isTypeDependent()) continue; auto VD = cast<VarDecl>(cast<DeclRefExpr>(VarRef)->getDecl()); - auto DVar = DSAStack->getTopDSA(VD); + auto DVar = DSAStack->getTopDSA(VD, false); if (DVar.CKind == OMPC_lastprivate) { SourceLocation ELoc = VarRef->getExprLoc(); auto Type = VarRef->getType(); @@ -795,10 +823,12 @@ static void ReportOriginalDSA(Sema &SemaRef, DSAStackTy *Stack, PDSA_LoopIterVarLastprivate, PDSA_ConstVarShared, PDSA_GlobalVarShared, + PDSA_TaskVarFirstprivate, PDSA_LocalVarPrivate, PDSA_Implicit } Reason = PDSA_Implicit; bool ReportHint = false; + auto ReportLoc = VD->getLocation(); if (IsLoopIterVar) { if (DVar.CKind == OMPC_private) Reason = PDSA_LoopIterVarPrivate; @@ -806,6 +836,9 @@ static void ReportOriginalDSA(Sema &SemaRef, DSAStackTy *Stack, Reason = PDSA_LoopIterVarLastprivate; else Reason = PDSA_LoopIterVarLinear; + } else if (DVar.DKind == OMPD_task && DVar.CKind == OMPC_firstprivate) { + Reason = PDSA_TaskVarFirstprivate; + ReportLoc = DVar.ImplicitDSALoc; } else if (VD->isStaticLocal()) Reason = PDSA_StaticLocalVarShared; else if (VD->isStaticDataMember()) @@ -819,7 +852,7 @@ static void ReportOriginalDSA(Sema &SemaRef, DSAStackTy *Stack, Reason = PDSA_LocalVarPrivate; } if (Reason != PDSA_Implicit) { - SemaRef.Diag(VD->getLocation(), diag::note_omp_predetermined_dsa) + SemaRef.Diag(ReportLoc, diag::note_omp_predetermined_dsa) << Reason << ReportHint << getOpenMPDirectiveName(Stack->getCurrentDirective()); } else if (DVar.ImplicitDSALoc.isValid()) { @@ -839,27 +872,23 @@ class DSAAttrChecker : public StmtVisitor<DSAAttrChecker, void> { public: void VisitDeclRefExpr(DeclRefExpr *E) { - if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) { + if (auto *VD = dyn_cast<VarDecl>(E->getDecl())) { // Skip internally declared variables. if (VD->isLocalVarDecl() && !CS->capturesVariable(VD)) return; - SourceLocation ELoc = E->getExprLoc(); + auto DVar = Stack->getTopDSA(VD, false); + // Check if the variable has explicit DSA set and stop analysis if it so. + if (DVar.RefExpr) return; - OpenMPDirectiveKind DKind = Stack->getCurrentDirective(); - DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD); - if (DVar.CKind != OMPC_unknown) { - if (DKind == OMPD_task && DVar.CKind != OMPC_shared && - !Stack->isThreadPrivate(VD) && !DVar.RefExpr) - ImplicitFirstprivate.push_back(DVar.RefExpr); - return; - } + auto ELoc = E->getExprLoc(); + auto DKind = Stack->getCurrentDirective(); // The default(none) clause requires that each variable that is referenced // in the construct, and does not have a predetermined data-sharing // attribute, must have its data-sharing attribute explicitly determined // by being listed in a data-sharing attribute clause. if (DVar.CKind == OMPC_unknown && Stack->getDefaultDSA() == DSA_none && - (isOpenMPParallelDirective(DKind) || DKind == OMPD_task) && + isParallelOrTaskRegion(DKind) && VarsWithInheritedDSA.count(VD) == 0) { VarsWithInheritedDSA[VD] = E; return; @@ -870,7 +899,11 @@ public: // enclosing worksharing or parallel construct may not be accessed in an // explicit task. DVar = Stack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_reduction), - MatchesAlways()); + [](OpenMPDirectiveKind K) -> bool { + return isOpenMPParallelDirective(K) || + isOpenMPWorksharingDirective(K); + }, + false); if (DKind == OMPD_task && DVar.CKind == OMPC_reduction) { ErrorFound = true; SemaRef.Diag(ELoc, diag::err_omp_reduction_in_task); @@ -879,24 +912,27 @@ public: } // Define implicit data-sharing attributes for task. - DVar = Stack->getImplicitDSA(VD); + DVar = Stack->getImplicitDSA(VD, false); if (DKind == OMPD_task && DVar.CKind != OMPC_shared) - ImplicitFirstprivate.push_back(DVar.RefExpr); + ImplicitFirstprivate.push_back(E); } } void VisitOMPExecutableDirective(OMPExecutableDirective *S) { - for (auto C : S->clauses()) - if (C) - for (StmtRange R = C->children(); R; ++R) - if (Stmt *Child = *R) - Visit(Child); + for (auto *C : S->clauses()) { + // Skip analysis of arguments of implicitly defined firstprivate clause + // for task directives. + if (C && (!isa<OMPFirstprivateClause>(C) || C->getLocStart().isValid())) + for (auto *CC : C->children()) { + if (CC) + Visit(CC); + } + } } void VisitStmt(Stmt *S) { - for (Stmt::child_iterator I = S->child_begin(), E = S->child_end(); I != E; - ++I) - if (Stmt *Child = *I) - if (!isa<OMPExecutableDirective>(Child)) - Visit(Child); + for (auto *C : S->children()) { + if (C && !isa<OMPExecutableDirective>(C)) + Visit(C); + } } bool isErrorFound() { return ErrorFound; } @@ -984,8 +1020,15 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { Params); break; } + case OMPD_task: { + Sema::CapturedParamNameType Params[] = { + std::make_pair(StringRef(), QualType()) // __context with shared vars + }; + ActOnCapturedRegionStart(DSAStack->getConstructLoc(), CurScope, CR_OpenMP, + Params); + break; + } case OMPD_threadprivate: - case OMPD_task: llvm_unreachable("OpenMP Directive is not allowed"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -1007,6 +1050,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel | single | * | // | parallel | parallel for | * | // | parallel |parallel sections| * | + // | parallel | task | * | // +------------------+-----------------+------------------------------------+ // | for | parallel | * | // | for | for | + | @@ -1016,6 +1060,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | for | single | + | // | for | parallel for | * | // | for |parallel sections| * | + // | for | task | * | // +------------------+-----------------+------------------------------------+ // | simd | parallel | | // | simd | for | | @@ -1025,6 +1070,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | simd | single | | // | simd | parallel for | | // | simd |parallel sections| | + // | simd | task | | // +------------------+-----------------+------------------------------------+ // | sections | parallel | * | // | sections | for | + | @@ -1034,6 +1080,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | sections | single | + | // | sections | parallel for | * | // | sections |parallel sections| * | + // | sections | task | * | // +------------------+-----------------+------------------------------------+ // | section | parallel | * | // | section | for | + | @@ -1043,6 +1090,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | section | single | + | // | section | parallel for | * | // | section |parallel sections| * | + // | section | task | * | // +------------------+-----------------+------------------------------------+ // | single | parallel | * | // | single | for | + | @@ -1052,6 +1100,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | single | single | + | // | single | parallel for | * | // | single |parallel sections| * | + // | single | task | * | // +------------------+-----------------+------------------------------------+ // | parallel for | parallel | * | // | parallel for | for | + | @@ -1061,6 +1110,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel for | single | + | // | parallel for | parallel for | * | // | parallel for |parallel sections| * | + // | parallel for | task | * | // +------------------+-----------------+------------------------------------+ // | parallel sections| parallel | * | // | parallel sections| for | + | @@ -1070,6 +1120,17 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel sections| single | + | // | parallel sections| parallel for | * | // | parallel sections|parallel sections| * | + // | parallel sections| task | * | + // +------------------+-----------------+------------------------------------+ + // | task | parallel | * | + // | task | for | + | + // | task | simd | * | + // | task | sections | + | + // | task | section | + | + // | task | single | + | + // | task | parallel for | * | + // | task |parallel sections| * | + // | task | task | * | // +------------------+-----------------+------------------------------------+ if (Stack->getCurScope()) { auto ParentRegion = Stack->getParentDirective(); @@ -1103,8 +1164,9 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // A worksharing region may not be closely nested inside a worksharing, // explicit task, critical, ordered, atomic, or master region. // TODO - NestingProhibited = isOpenMPWorksharingDirective(ParentRegion) && - !isOpenMPSimdDirective(ParentRegion); + NestingProhibited = (isOpenMPWorksharingDirective(ParentRegion) && + !isOpenMPSimdDirective(ParentRegion)) || + ParentRegion == OMPD_task; ShouldBeInParallelRegion = true; } if (NestingProhibited) { @@ -1184,8 +1246,11 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, Res = ActOnOpenMPParallelSectionsDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); break; - case OMPD_threadprivate: case OMPD_task: + Res = + ActOnOpenMPTaskDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); + break; + case OMPD_threadprivate: llvm_unreachable("OpenMP Directive is not allowed"); case OMPD_unknown: llvm_unreachable("Unknown OpenMP directive"); @@ -1651,7 +1716,7 @@ static bool CheckOpenMPIterationSpace( // constant-linear-step that is the increment of the associated for-loop. // The loop iteration variable(s) in the associated for-loop(s) of a for or // parallel for construct may be listed in a private or lastprivate clause. - DSAStackTy::DSAVarData DVar = DSA.getTopDSA(Var); + DSAStackTy::DSAVarData DVar = DSA.getTopDSA(Var, false); auto PredeterminedCKind = isOpenMPSimdDirective(DKind) ? ((NestedLoopCount == 1) ? OMPC_linear : OMPC_lastprivate) @@ -1898,6 +1963,23 @@ Sema::ActOnOpenMPParallelSectionsDirective(ArrayRef<OMPClause *> Clauses, Clauses, AStmt); } +StmtResult Sema::ActOnOpenMPTaskDirective(ArrayRef<OMPClause *> Clauses, + Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc) { + assert(AStmt && isa<CapturedStmt>(AStmt) && "Captured statement expected"); + CapturedStmt *CS = cast<CapturedStmt>(AStmt); + // 1.2.2 OpenMP Language Terminology + // Structured block - An executable statement with a single entry at the + // top and a single exit at the bottom. + // The point of exit cannot be a branch out of the structured block. + // longjmp() and throw() must not violate the entry/exit criteria. + CS->getCapturedDecl()->setNothrow(); + + getCurFunction()->setHasBranchProtectedScope(); + + return OMPTaskDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt); +} + OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, @@ -2494,7 +2576,7 @@ OMPClause *Sema::ActOnOpenMPPrivateClause(ArrayRef<Expr *> VarList, // listed below. For these exceptions only, listing a predetermined // variable in a data-sharing attribute clause is allowed and overrides // the variable's predetermined data-sharing attributes. - DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD); + DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private) { Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) << getOpenMPClauseName(OMPC_private); @@ -2517,6 +2599,10 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, SourceLocation LParenLoc, SourceLocation EndLoc) { SmallVector<Expr *, 8> Vars; + bool IsImplicitClause = + StartLoc.isInvalid() && LParenLoc.isInvalid() && EndLoc.isInvalid(); + auto ImplicitClauseLoc = DSAStack->getConstructLoc(); + for (auto &RefExpr : VarList) { assert(RefExpr && "NULL expr in OpenMP firstprivate clause."); if (isa<DependentScopeDeclRefExpr>(RefExpr)) { @@ -2525,7 +2611,8 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, continue; } - SourceLocation ELoc = RefExpr->getExprLoc(); + SourceLocation ELoc = IsImplicitClause ? ImplicitClauseLoc + : RefExpr->getExprLoc(); // OpenMP [2.1, C/C++] // A list item is a variable name. // OpenMP [2.9.3.3, Restrictions, p.1] @@ -2554,8 +2641,15 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, continue; } if (Type->isReferenceType()) { - Diag(ELoc, diag::err_omp_clause_ref_type_arg) - << getOpenMPClauseName(OMPC_firstprivate) << Type; + if (IsImplicitClause) { + Diag(ImplicitClauseLoc, + diag::err_omp_task_predetermined_firstprivate_ref_type_arg) + << Type; + Diag(RefExpr->getExprLoc(), diag::note_used_here); + } else { + Diag(ELoc, diag::err_omp_clause_ref_type_arg) + << getOpenMPClauseName(OMPC_firstprivate) << Type; + } bool IsDecl = VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; Diag(VD->getLocation(), @@ -2583,8 +2677,15 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, InitializedEntity::InitializeTemporary(Type), CD->getAccess(), PD) == AR_inaccessible || CD->isDeleted()) { - Diag(ELoc, diag::err_omp_required_method) - << getOpenMPClauseName(OMPC_firstprivate) << 1; + if (IsImplicitClause) { + Diag(ImplicitClauseLoc, + diag::err_omp_task_predetermined_firstprivate_required_method) + << 0; + Diag(RefExpr->getExprLoc(), diag::note_used_here); + } else { + Diag(ELoc, diag::err_omp_required_method) + << getOpenMPClauseName(OMPC_firstprivate) << 1; + } bool IsDecl = VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; Diag(VD->getLocation(), @@ -2600,8 +2701,15 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, if (DD) { if (CheckDestructorAccess(ELoc, DD, PD) == AR_inaccessible || DD->isDeleted()) { - Diag(ELoc, diag::err_omp_required_method) - << getOpenMPClauseName(OMPC_firstprivate) << 4; + if (IsImplicitClause) { + Diag(ImplicitClauseLoc, + diag::err_omp_task_predetermined_firstprivate_required_method) + << 1; + Diag(RefExpr->getExprLoc(), diag::note_used_here); + } else { + Diag(ELoc, diag::err_omp_required_method) + << getOpenMPClauseName(OMPC_firstprivate) << 4; + } bool IsDecl = VD->isThisDeclarationADefinition(Context) == VarDecl::DeclarationOnly; Diag(VD->getLocation(), @@ -2615,10 +2723,9 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, } } - // If StartLoc and EndLoc are invalid - this is an implicit firstprivate - // variable and it was checked already. - if (StartLoc.isValid() && EndLoc.isValid()) { - DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD); + // If an implicit firstprivate variable found it was checked already. + if (!IsImplicitClause) { + DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); Type = Type.getNonReferenceType().getCanonicalType(); bool IsConstant = Type.isConstant(Context); Type = Context.getBaseElementType(Type); @@ -2663,8 +2770,10 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, // to any of the parallel regions arising from the parallel construct. if (isOpenMPWorksharingDirective(CurrDir) && !isOpenMPParallelDirective(CurrDir)) { - DVar = DSAStack->getImplicitDSA(VD); - if (DVar.CKind != OMPC_shared) { + DVar = DSAStack->getImplicitDSA(VD, true); + if (DVar.CKind != OMPC_shared && + (isOpenMPParallelDirective(DVar.DKind) || + DVar.DKind == OMPD_unknown)) { Diag(ELoc, diag::err_omp_required_access) << getOpenMPClauseName(OMPC_firstprivate) << getOpenMPClauseName(OMPC_shared); @@ -2678,13 +2787,28 @@ OMPClause *Sema::ActOnOpenMPFirstprivateClause(ArrayRef<Expr *> VarList, // construct if any of the worksharing or task regions arising from the // worksharing or task construct ever bind to any of the parallel regions // arising from the parallel construct. - // TODO // OpenMP [2.9.3.4, Restrictions, p.4] // A list item that appears in a reduction clause in worksharing // construct must not appear in a firstprivate clause in a task construct // encountered during execution of any of the worksharing regions arising // from the worksharing construct. - // TODO + if (CurrDir == OMPD_task) { + DVar = + DSAStack->hasInnermostDSA(VD, MatchesAnyClause(OMPC_reduction), + [](OpenMPDirectiveKind K) -> bool { + return isOpenMPParallelDirective(K) || + isOpenMPWorksharingDirective(K); + }, + false); + if (DVar.CKind == OMPC_reduction && + (isOpenMPParallelDirective(DVar.DKind) || + isOpenMPWorksharingDirective(DVar.DKind))) { + Diag(ELoc, diag::err_omp_parallel_reduction_in_task_firstprivate) + << getOpenMPDirectiveName(DVar.DKind); + ReportOriginalDSA(*this, DSAStack, VD, DVar); + continue; + } + } } DSAStack->addDSA(VD, DE, OMPC_firstprivate); @@ -2755,7 +2879,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, // Variables with the predetermined data-sharing attributes may not be // listed in data-sharing attributes clauses, except for the cases // listed below. - DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD); + DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_lastprivate && DVar.CKind != OMPC_firstprivate && (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) { @@ -2775,7 +2899,7 @@ OMPClause *Sema::ActOnOpenMPLastprivateClause(ArrayRef<Expr *> VarList, // regions. if (isOpenMPWorksharingDirective(CurrDir) && !isOpenMPParallelDirective(CurrDir)) { - DVar = DSAStack->getImplicitDSA(VD); + DVar = DSAStack->getImplicitDSA(VD, true); if (DVar.CKind != OMPC_shared) { Diag(ELoc, diag::err_omp_required_access) << getOpenMPClauseName(OMPC_lastprivate) @@ -2895,7 +3019,7 @@ OMPClause *Sema::ActOnOpenMPSharedClause(ArrayRef<Expr *> VarList, // listed below. For these exceptions only, listing a predetermined // variable in a data-sharing attribute clause is allowed and overrides // the variable's predetermined data-sharing attributes. - DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD); + DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); if (DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_shared && DVar.RefExpr) { Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) @@ -2921,13 +3045,13 @@ class DSARefChecker : public StmtVisitor<DSARefChecker, bool> { public: bool VisitDeclRefExpr(DeclRefExpr *E) { if (VarDecl *VD = dyn_cast<VarDecl>(E->getDecl())) { - DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD); + DSAStackTy::DSAVarData DVar = Stack->getTopDSA(VD, false); if (DVar.CKind == OMPC_shared && !DVar.RefExpr) return false; if (DVar.CKind != OMPC_unknown) return true; DSAStackTy::DSAVarData DVarPrivate = - Stack->hasDSA(VD, isOpenMPPrivate, MatchesAlways()); + Stack->hasDSA(VD, isOpenMPPrivate, MatchesAlways(), false); if (DVarPrivate.CKind != OMPC_unknown) return true; return false; @@ -3145,7 +3269,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause( // Any number of reduction clauses can be specified on the directive, // but a list item can appear only once in the reduction clauses for that // directive. - DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD); + DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); if (DVar.CKind == OMPC_reduction) { Diag(ELoc, diag::err_omp_once_referenced) << getOpenMPClauseName(OMPC_reduction); @@ -3167,7 +3291,7 @@ OMPClause *Sema::ActOnOpenMPReductionClause( OpenMPDirectiveKind CurrDir = DSAStack->getCurrentDirective(); if (isOpenMPWorksharingDirective(CurrDir) && !isOpenMPParallelDirective(CurrDir)) { - DVar = DSAStack->getImplicitDSA(VD); + DVar = DSAStack->getImplicitDSA(VD, true); if (DVar.CKind != OMPC_shared) { Diag(ELoc, diag::err_omp_required_access) << getOpenMPClauseName(OMPC_reduction) @@ -3275,7 +3399,7 @@ OMPClause *Sema::ActOnOpenMPLinearClause(ArrayRef<Expr *> VarList, Expr *Step, // A list-item cannot appear in more than one linear clause. // A list-item that appears in a linear clause cannot appear in any // other data-sharing attribute clause. - DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD); + DSAStackTy::DSAVarData DVar = DSAStack->getTopDSA(VD, false); if (DVar.RefExpr) { Diag(ELoc, diag::err_omp_wrong_dsa) << getOpenMPClauseName(DVar.CKind) << getOpenMPClauseName(OMPC_linear); @@ -3558,7 +3682,7 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, // A list item that appears in a copyprivate clause may not appear in a // private or firstprivate clause on the single construct. if (!DSAStack->isThreadPrivate(VD)) { - auto DVar = DSAStack->getTopDSA(VD); + auto DVar = DSAStack->getTopDSA(VD, false); if (DVar.CKind != OMPC_copyprivate && DVar.CKind != OMPC_unknown && !(DVar.CKind == OMPC_private && !DVar.RefExpr)) { Diag(ELoc, diag::err_omp_wrong_dsa) @@ -3572,7 +3696,7 @@ OMPClause *Sema::ActOnOpenMPCopyprivateClause(ArrayRef<Expr *> VarList, // All list items that appear in a copyprivate clause must be either // threadprivate or private in the enclosing context. if (DVar.CKind == OMPC_unknown) { - DVar = DSAStack->getImplicitDSA(VD); + DVar = DSAStack->getImplicitDSA(VD, false); if (DVar.CKind == OMPC_shared) { Diag(ELoc, diag::err_omp_required_access) << getOpenMPClauseName(OMPC_copyprivate) diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 269a3bd8a84..dc0b5c288c5 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -6512,6 +6512,17 @@ StmtResult TreeTransform<Derived>::TransformOMPParallelSectionsDirective( return Res; } +template <typename Derived> +StmtResult +TreeTransform<Derived>::TransformOMPTaskDirective(OMPTaskDirective *D) { + DeclarationNameInfo DirName; + getDerived().getSema().StartOpenMPDSABlock(OMPD_task, DirName, nullptr, + D->getLocStart()); + StmtResult Res = getDerived().TransformOMPExecutableDirective(D); + getDerived().getSema().EndOpenMPDSABlock(Res.get()); + return Res; +} + //===----------------------------------------------------------------------===// // OpenMP clause transformation //===----------------------------------------------------------------------===// |