diff options
Diffstat (limited to 'clang/lib')
| -rw-r--r-- | clang/lib/AST/Stmt.cpp | 26 | ||||
| -rw-r--r-- | clang/lib/AST/StmtPrinter.cpp | 5 | ||||
| -rw-r--r-- | clang/lib/AST/StmtProfile.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/Basic/OpenMPKinds.cpp | 11 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGStmt.cpp | 3 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CGStmtOpenMP.cpp | 4 | ||||
| -rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 1 | ||||
| -rw-r--r-- | clang/lib/Parse/ParseOpenMP.cpp | 12 | ||||
| -rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 298 | ||||
| -rw-r--r-- | clang/lib/Sema/TreeTransform.h | 11 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 12 | ||||
| -rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 7 | ||||
| -rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 1 |
13 files changed, 299 insertions, 96 deletions
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 9cd3831bf26..b415e9201e5 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -1528,3 +1528,29 @@ OMPParallelSectionsDirective::CreateEmpty(const ASTContext &C, return new (Mem) OMPParallelSectionsDirective(NumClauses); } +OMPTaskDirective *OMPTaskDirective::Create(const ASTContext &C, + SourceLocation StartLoc, + SourceLocation EndLoc, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + OMPTaskDirective *Dir = + new (Mem) OMPTaskDirective(StartLoc, EndLoc, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPTaskDirective *OMPTaskDirective::CreateEmpty(const ASTContext &C, + unsigned NumClauses, + EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPTaskDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPTaskDirective(NumClauses); +} + diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 1d01e655655..03515718323 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -826,6 +826,11 @@ void StmtPrinter::VisitOMPParallelSectionsDirective( PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPTaskDirective(OMPTaskDirective *Node) { + Indent() << "#pragma omp task "; + PrintOMPExecutableDirective(Node); +} + //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index db691a93edb..a364f68e305 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -390,6 +390,10 @@ void StmtProfiler::VisitOMPParallelSectionsDirective( VisitOMPExecutableDirective(S); } +void StmtProfiler::VisitOMPTaskDirective(const OMPTaskDirective *S) { + VisitOMPExecutableDirective(S); +} + void StmtProfiler::VisitExpr(const Expr *S) { VisitStmt(S); } diff --git a/clang/lib/Basic/OpenMPKinds.cpp b/clang/lib/Basic/OpenMPKinds.cpp index b48c02ca266..188bd2dbfd5 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -237,9 +237,18 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, break; } break; + case OMPD_task: + switch (CKind) { +#define OPENMP_TASK_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; case OMPD_unknown: case OMPD_threadprivate: - case OMPD_task: case OMPD_section: break; } diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index b9d74b675a6..39adf9b7130 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -200,6 +200,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { case Stmt::OMPParallelSectionsDirectiveClass: EmitOMPParallelSectionsDirective(cast<OMPParallelSectionsDirective>(*S)); break; + case Stmt::OMPTaskDirectiveClass: + EmitOMPTaskDirective(cast<OMPTaskDirective>(*S)); + break; } } diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index e253efc2cb3..3d36dbb1b1a 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -100,3 +100,7 @@ void CodeGenFunction::EmitOMPParallelSectionsDirective( llvm_unreachable("CodeGen for 'omp parallel sections' is not supported yet."); } +void CodeGenFunction::EmitOMPTaskDirective(const OMPTaskDirective &) { + llvm_unreachable("CodeGen for 'omp task' is not supported yet."); +} + diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index a2d92ff18cc..f6dd39f8fbd 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1918,6 +1918,7 @@ public: void EmitOMPSingleDirective(const OMPSingleDirective &S); void EmitOMPParallelForDirective(const OMPParallelForDirective &S); void EmitOMPParallelSectionsDirective(const OMPParallelSectionsDirective &S); + void EmitOMPTaskDirective(const OMPTaskDirective &S); //===--------------------------------------------------------------------===// // LValue Expression Emission diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index b3a1063ed23..caa8d8f782c 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -105,8 +105,8 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { /// /// executable-directive: /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | -/// 'section' | 'single' | 'parallel for' | 'parallel sections' {clause} -/// annot_pragma_openmp_end +/// 'section' | 'single' | 'parallel for' | 'parallel sections' | 'task' +/// {clause} annot_pragma_openmp_end /// StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); @@ -147,7 +147,8 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { case OMPD_single: case OMPD_section: case OMPD_parallel_for: - case OMPD_parallel_sections: { + case OMPD_parallel_sections: + case OMPD_task: { ConsumeToken(); if (isOpenMPLoopDirective(DKind)) @@ -209,11 +210,6 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { Diag(Tok, diag::err_omp_unknown_directive); SkipUntil(tok::annot_pragma_openmp_end); break; - case OMPD_task: - Diag(Tok, diag::err_omp_unexpected_directive) - << getOpenMPDirectiveName(DKind); - SkipUntil(tok::annot_pragma_openmp_end); - break; } return Directive; } 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 //===----------------------------------------------------------------------===// diff --git a/clang/lib/Serialization/ASTReaderStmt.cpp b/clang/lib/Serialization/ASTReaderStmt.cpp index cee2aa23b98..8239f4761c2 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1958,6 +1958,13 @@ void ASTStmtReader::VisitOMPParallelSectionsDirective( VisitOMPExecutableDirective(D); } +void ASTStmtReader::VisitOMPTaskDirective(OMPTaskDirective *D) { + VisitStmt(D); + // The NumClauses field was read in ReadStmtFromStream. + ++Idx; + VisitOMPExecutableDirective(D); +} + //===----------------------------------------------------------------------===// // ASTReader Implementation //===----------------------------------------------------------------------===// @@ -2483,6 +2490,11 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { Context, Record[ASTStmtReader::NumStmtFields], Empty); break; + case STMT_OMP_TASK_DIRECTIVE: + S = OMPTaskDirective::CreateEmpty( + Context, Record[ASTStmtReader::NumStmtFields], Empty); + break; + case EXPR_CXX_OPERATOR_CALL: S = new (Context) CXXOperatorCallExpr(Context, Empty); break; diff --git a/clang/lib/Serialization/ASTWriterStmt.cpp b/clang/lib/Serialization/ASTWriterStmt.cpp index 8f0c69e4318..30ee76934e3 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1867,6 +1867,13 @@ void ASTStmtWriter::VisitOMPParallelSectionsDirective( Code = serialization::STMT_OMP_PARALLEL_SECTIONS_DIRECTIVE; } +void ASTStmtWriter::VisitOMPTaskDirective(OMPTaskDirective *D) { + VisitStmt(D); + Record.push_back(D->getNumClauses()); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_TASK_DIRECTIVE; +} + //===----------------------------------------------------------------------===// // ASTWriter Implementation //===----------------------------------------------------------------------===// diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index 9b7e746b1c6..dec4d46b153 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -739,6 +739,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OMPSingleDirectiveClass: case Stmt::OMPParallelForDirectiveClass: case Stmt::OMPParallelSectionsDirectiveClass: + case Stmt::OMPTaskDirectiveClass: llvm_unreachable("Stmt should not be in analyzer evaluation loop"); case Stmt::ObjCSubscriptRefExprClass: |

