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 | 5 | ||||
-rw-r--r-- | clang/lib/Basic/OpenMPKinds.cpp | 23 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmt.cpp | 3 | ||||
-rw-r--r-- | clang/lib/CodeGen/CGStmtOpenMP.cpp | 5 | ||||
-rw-r--r-- | clang/lib/CodeGen/CodeGenFunction.h | 1 | ||||
-rw-r--r-- | clang/lib/Parse/ParseOpenMP.cpp | 34 | ||||
-rw-r--r-- | clang/lib/Sema/SemaOpenMP.cpp | 151 | ||||
-rw-r--r-- | clang/lib/Sema/TreeTransform.h | 11 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTReaderStmt.cpp | 15 | ||||
-rw-r--r-- | clang/lib/Serialization/ASTWriterStmt.cpp | 8 | ||||
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngine.cpp | 1 |
13 files changed, 248 insertions, 40 deletions
diff --git a/clang/lib/AST/Stmt.cpp b/clang/lib/AST/Stmt.cpp index 102d14b475b..16e7d3c73f1 100644 --- a/clang/lib/AST/Stmt.cpp +++ b/clang/lib/AST/Stmt.cpp @@ -1478,3 +1478,29 @@ OMPSingleDirective *OMPSingleDirective::CreateEmpty(const ASTContext &C, return new (Mem) OMPSingleDirective(NumClauses); } +OMPParallelForDirective * +OMPParallelForDirective::Create(const ASTContext &C, SourceLocation StartLoc, + SourceLocation EndLoc, unsigned CollapsedNum, + ArrayRef<OMPClause *> Clauses, + Stmt *AssociatedStmt) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * Clauses.size() + sizeof(Stmt *)); + OMPParallelForDirective *Dir = new (Mem) + OMPParallelForDirective(StartLoc, EndLoc, CollapsedNum, Clauses.size()); + Dir->setClauses(Clauses); + Dir->setAssociatedStmt(AssociatedStmt); + return Dir; +} + +OMPParallelForDirective * +OMPParallelForDirective::CreateEmpty(const ASTContext &C, unsigned NumClauses, + unsigned CollapsedNum, EmptyShell) { + unsigned Size = llvm::RoundUpToAlignment(sizeof(OMPParallelForDirective), + llvm::alignOf<OMPClause *>()); + void *Mem = + C.Allocate(Size + sizeof(OMPClause *) * NumClauses + sizeof(Stmt *)); + return new (Mem) OMPParallelForDirective(CollapsedNum, NumClauses); +} + diff --git a/clang/lib/AST/StmtPrinter.cpp b/clang/lib/AST/StmtPrinter.cpp index 1d96c49c7bb..9e88ca91186 100644 --- a/clang/lib/AST/StmtPrinter.cpp +++ b/clang/lib/AST/StmtPrinter.cpp @@ -815,6 +815,11 @@ void StmtPrinter::VisitOMPSingleDirective(OMPSingleDirective *Node) { PrintOMPExecutableDirective(Node); } +void StmtPrinter::VisitOMPParallelForDirective(OMPParallelForDirective *Node) { + Indent() << "#pragma omp parallel for "; + PrintOMPExecutableDirective(Node); +} + //===----------------------------------------------------------------------===// // Expr printing methods. //===----------------------------------------------------------------------===// diff --git a/clang/lib/AST/StmtProfile.cpp b/clang/lib/AST/StmtProfile.cpp index f666be7008f..73ec8d733a6 100644 --- a/clang/lib/AST/StmtProfile.cpp +++ b/clang/lib/AST/StmtProfile.cpp @@ -380,6 +380,11 @@ void StmtProfiler::VisitOMPSingleDirective(const OMPSingleDirective *S) { VisitOMPExecutableDirective(S); } +void +StmtProfiler::VisitOMPParallelForDirective(const OMPParallelForDirective *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 07121215e70..6107de16726 100644 --- a/clang/lib/Basic/OpenMPKinds.cpp +++ b/clang/lib/Basic/OpenMPKinds.cpp @@ -23,6 +23,7 @@ using namespace clang; OpenMPDirectiveKind clang::getOpenMPDirectiveKind(StringRef Str) { return llvm::StringSwitch<OpenMPDirectiveKind>(Str) #define OPENMP_DIRECTIVE(Name) .Case(#Name, OMPD_##Name) +#define OPENMP_DIRECTIVE_EXT(Name, Str) .Case(Str, OMPD_##Name) #include "clang/Basic/OpenMPKinds.def" .Default(OMPD_unknown); } @@ -35,6 +36,9 @@ const char *clang::getOpenMPDirectiveName(OpenMPDirectiveKind Kind) { #define OPENMP_DIRECTIVE(Name) \ case OMPD_##Name: \ return #Name; +#define OPENMP_DIRECTIVE_EXT(Name, Str) \ + case OMPD_##Name: \ + return Str; #include "clang/Basic/OpenMPKinds.def" break; } @@ -213,6 +217,16 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, break; } break; + case OMPD_parallel_for: + switch (CKind) { +#define OPENMP_PARALLEL_FOR_CLAUSE(Name) \ + case OMPC_##Name: \ + return true; +#include "clang/Basic/OpenMPKinds.def" + default: + break; + } + break; case OMPD_unknown: case OMPD_threadprivate: case OMPD_task: @@ -223,16 +237,19 @@ bool clang::isAllowedClauseForDirective(OpenMPDirectiveKind DKind, } bool clang::isOpenMPLoopDirective(OpenMPDirectiveKind DKind) { - return DKind == OMPD_simd || DKind == OMPD_for; // TODO add next directives. + return DKind == OMPD_simd || DKind == OMPD_for || + DKind == OMPD_parallel_for; // TODO add next directives. } bool clang::isOpenMPWorksharingDirective(OpenMPDirectiveKind DKind) { return DKind == OMPD_for || DKind == OMPD_sections || DKind == OMPD_section || - DKind == OMPD_single; // TODO add next directives. + DKind == OMPD_single || + DKind == OMPD_parallel_for; // TODO add next directives. } bool clang::isOpenMPParallelDirective(OpenMPDirectiveKind DKind) { - return DKind == OMPD_parallel; // TODO add next directives. + return DKind == OMPD_parallel || + DKind == OMPD_parallel_for; // TODO add next directives. } bool clang::isOpenMPSimdDirective(OpenMPDirectiveKind DKind) { diff --git a/clang/lib/CodeGen/CGStmt.cpp b/clang/lib/CodeGen/CGStmt.cpp index 6fed5d3a9d4..72dd17f5195 100644 --- a/clang/lib/CodeGen/CGStmt.cpp +++ b/clang/lib/CodeGen/CGStmt.cpp @@ -194,6 +194,9 @@ void CodeGenFunction::EmitStmt(const Stmt *S) { case Stmt::OMPSingleDirectiveClass: EmitOMPSingleDirective(cast<OMPSingleDirective>(*S)); break; + case Stmt::OMPParallelForDirectiveClass: + EmitOMPParallelForDirective(cast<OMPParallelForDirective>(*S)); + break; } } diff --git a/clang/lib/CodeGen/CGStmtOpenMP.cpp b/clang/lib/CodeGen/CGStmtOpenMP.cpp index 02c73c9da0f..46c1d783c2e 100644 --- a/clang/lib/CodeGen/CGStmtOpenMP.cpp +++ b/clang/lib/CodeGen/CGStmtOpenMP.cpp @@ -90,3 +90,8 @@ void CodeGenFunction::EmitOMPSingleDirective(const OMPSingleDirective &) { llvm_unreachable("CodeGen for 'omp single' is not supported yet."); } +void +CodeGenFunction::EmitOMPParallelForDirective(const OMPParallelForDirective &) { + llvm_unreachable("CodeGen for 'omp parallel for' is not supported yet."); +} + diff --git a/clang/lib/CodeGen/CodeGenFunction.h b/clang/lib/CodeGen/CodeGenFunction.h index 055e9356842..2d6d99a8419 100644 --- a/clang/lib/CodeGen/CodeGenFunction.h +++ b/clang/lib/CodeGen/CodeGenFunction.h @@ -1903,6 +1903,7 @@ public: void EmitOMPSectionsDirective(const OMPSectionsDirective &S); void EmitOMPSectionDirective(const OMPSectionDirective &S); void EmitOMPSingleDirective(const OMPSingleDirective &S); + void EmitOMPParallelForDirective(const OMPParallelForDirective &S); //===--------------------------------------------------------------------===// // LValue Expression Emission diff --git a/clang/lib/Parse/ParseOpenMP.cpp b/clang/lib/Parse/ParseOpenMP.cpp index b35082e6c4f..a6bc3a2c332 100644 --- a/clang/lib/Parse/ParseOpenMP.cpp +++ b/clang/lib/Parse/ParseOpenMP.cpp @@ -25,6 +25,26 @@ using namespace clang; // OpenMP declarative directives. //===----------------------------------------------------------------------===// +static OpenMPDirectiveKind ParseOpenMPDirectiveKind(Parser &P) { + auto Tok = P.getCurToken(); + auto DKind = + Tok.isAnnotation() + ? OMPD_unknown + : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok)); + if (DKind == OMPD_parallel) { + Tok = P.getPreprocessor().LookAhead(0); + auto SDKind = + Tok.isAnnotation() + ? OMPD_unknown + : getOpenMPDirectiveKind(P.getPreprocessor().getSpelling(Tok)); + if (SDKind == OMPD_for) { + P.ConsumeToken(); + DKind = OMPD_parallel_for; + } + } + return DKind; +} + /// \brief Parsing of declarative OpenMP directives. /// /// threadprivate-directive: @@ -36,9 +56,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { SourceLocation Loc = ConsumeToken(); SmallVector<Expr *, 5> Identifiers; - OpenMPDirectiveKind DKind = Tok.isAnnotation() - ? OMPD_unknown - : getOpenMPDirectiveKind(PP.getSpelling(Tok)); + auto DKind = ParseOpenMPDirectiveKind(*this); switch (DKind) { case OMPD_threadprivate: @@ -66,6 +84,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { case OMPD_sections: case OMPD_section: case OMPD_single: + case OMPD_parallel_for: Diag(Tok, diag::err_omp_unexpected_directive) << getOpenMPDirectiveName(DKind); break; @@ -82,7 +101,7 @@ Parser::DeclGroupPtrTy Parser::ParseOpenMPDeclarativeDirective() { /// /// executable-directive: /// annot_pragma_openmp 'parallel' | 'simd' | 'for' | 'sections' | -/// 'section' | 'single' {clause} annot_pragma_openmp_end +/// 'section' | 'single' | 'parallel for' {clause} annot_pragma_openmp_end /// StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { assert(Tok.is(tok::annot_pragma_openmp) && "Not an OpenMP directive!"); @@ -94,9 +113,7 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { unsigned ScopeFlags = Scope::FnScope | Scope::DeclScope | Scope::OpenMPDirectiveScope; SourceLocation Loc = ConsumeToken(), EndLoc; - OpenMPDirectiveKind DKind = Tok.isAnnotation() - ? OMPD_unknown - : getOpenMPDirectiveKind(PP.getSpelling(Tok)); + auto DKind = ParseOpenMPDirectiveKind(*this); // Name of critical directive. DeclarationNameInfo DirName; StmtResult Directive = StmtError(); @@ -123,7 +140,8 @@ StmtResult Parser::ParseOpenMPDeclarativeOrExecutableDirective() { case OMPD_for: case OMPD_sections: case OMPD_single: - case OMPD_section: { + case OMPD_section: + case OMPD_parallel_for: { ConsumeToken(); if (isOpenMPLoopDirective(DKind)) diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp index b1786fed0bc..5ce0c84f84a 100644 --- a/clang/lib/Sema/SemaOpenMP.cpp +++ b/clang/lib/Sema/SemaOpenMP.cpp @@ -835,6 +835,7 @@ class DSAAttrChecker : public StmtVisitor<DSAAttrChecker, void> { bool ErrorFound; CapturedStmt *CS; llvm::SmallVector<Expr *, 8> ImplicitFirstprivate; + llvm::DenseMap<VarDecl *, Expr *> VarsWithInheritedDSA; public: void VisitDeclRefExpr(DeclRefExpr *E) { @@ -858,9 +859,9 @@ public: // 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)) { - ErrorFound = true; - SemaRef.Diag(ELoc, diag::err_omp_no_dsa_for_variable) << VD; + (isOpenMPParallelDirective(DKind) || DKind == OMPD_task) && + VarsWithInheritedDSA.count(VD) == 0) { + VarsWithInheritedDSA[VD] = E; return; } @@ -900,6 +901,9 @@ public: bool isErrorFound() { return ErrorFound; } ArrayRef<Expr *> getImplicitFirstprivate() { return ImplicitFirstprivate; } + llvm::DenseMap<VarDecl *, Expr *> &getVarsWithInheritedDSA() { + return VarsWithInheritedDSA; + } DSAAttrChecker(DSAStackTy *S, Sema &SemaRef, CapturedStmt *CS) : Stack(S), SemaRef(SemaRef), ErrorFound(false), CS(CS) {} @@ -960,6 +964,18 @@ void Sema::ActOnOpenMPRegionStart(OpenMPDirectiveKind DKind, Scope *CurScope) { Params); break; } + case OMPD_parallel_for: { + QualType KmpInt32Ty = Context.getIntTypeForBitwidth(32, 1); + QualType KmpInt32PtrTy = Context.getPointerType(KmpInt32Ty); + Sema::CapturedParamNameType Params[] = { + std::make_pair(".global_tid.", KmpInt32PtrTy), + std::make_pair(".bound_tid.", KmpInt32PtrTy), + 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"); @@ -981,6 +997,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | parallel | sections | * | // | parallel | section | + | // | parallel | single | * | + // | parallel | parallel for | * | // +------------------+-----------------+------------------------------------+ // | for | parallel | * | // | for | for | + | @@ -988,6 +1005,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | for | sections | + | // | for | section | + | // | for | single | + | + // | for | parallel for | * | // +------------------+-----------------+------------------------------------+ // | simd | parallel | | // | simd | for | | @@ -995,6 +1013,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | simd | sections | | // | simd | section | | // | simd | single | | + // | simd | parallel for | | // +------------------+-----------------+------------------------------------+ // | sections | parallel | * | // | sections | for | + | @@ -1002,6 +1021,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | sections | sections | + | // | sections | section | * | // | sections | single | + | + // | sections | parallel for | * | // +------------------+-----------------+------------------------------------+ // | section | parallel | * | // | section | for | + | @@ -1009,6 +1029,7 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | section | sections | + | // | section | section | + | // | section | single | + | + // | section | parallel for | * | // +------------------+-----------------+------------------------------------+ // | single | parallel | * | // | single | for | + | @@ -1016,6 +1037,15 @@ bool CheckNestingOfRegions(Sema &SemaRef, DSAStackTy *Stack, // | single | sections | + | // | single | section | + | // | single | single | + | + // | single | parallel for | * | + // +------------------+-----------------+------------------------------------+ + // | parallel for | parallel | * | + // | parallel for | for | + | + // | parallel for | simd | * | + // | parallel for | sections | + | + // | parallel for | section | + | + // | parallel for | single | + | + // | parallel for | parallel for | * | // +------------------+-----------------+------------------------------------+ if (Stack->getCurScope()) { auto ParentRegion = Stack->getParentDirective(); @@ -1079,6 +1109,7 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, if (DSAChecker.isErrorFound()) return StmtError(); // Generate list of implicitly defined firstprivate variables. + auto &VarsWithInheritedDSA = DSAChecker.getVarsWithInheritedDSA(); llvm::SmallVector<OMPClause *, 8> ClausesWithImplicit; ClausesWithImplicit.append(Clauses.begin(), Clauses.end()); @@ -1100,11 +1131,12 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, EndLoc); break; case OMPD_simd: - Res = - ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); + Res = ActOnOpenMPSimdDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, + VarsWithInheritedDSA); break; case OMPD_for: - Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); + Res = ActOnOpenMPForDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc, + VarsWithInheritedDSA); break; case OMPD_sections: Res = ActOnOpenMPSectionsDirective(ClausesWithImplicit, AStmt, StartLoc, @@ -1119,6 +1151,10 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, Res = ActOnOpenMPSingleDirective(ClausesWithImplicit, AStmt, StartLoc, EndLoc); break; + case OMPD_parallel_for: + Res = ActOnOpenMPParallelForDirective(ClausesWithImplicit, AStmt, StartLoc, + EndLoc, VarsWithInheritedDSA); + break; case OMPD_threadprivate: case OMPD_task: llvm_unreachable("OpenMP Directive is not allowed"); @@ -1126,6 +1162,13 @@ StmtResult Sema::ActOnOpenMPExecutableDirective(OpenMPDirectiveKind Kind, llvm_unreachable("Unknown OpenMP directive"); } + for (auto P : VarsWithInheritedDSA) { + Diag(P.second->getExprLoc(), diag::err_omp_no_dsa_for_variable) + << P.first << P.second->getSourceRange(); + } + if (!VarsWithInheritedDSA.empty()) + return StmtError(); + if (ErrorFound) return StmtError(); return Res; @@ -1512,11 +1555,11 @@ bool OpenMPIterationSpaceChecker::CheckInc(Expr *S) { /// \brief Called on a for stmt to check and extract its iteration space /// for further processing (such as collapsing). -static bool CheckOpenMPIterationSpace(OpenMPDirectiveKind DKind, Stmt *S, - Sema &SemaRef, DSAStackTy &DSA, - unsigned CurrentNestedLoopCount, - unsigned NestedLoopCount, - Expr *NestedLoopCountExpr) { +static bool CheckOpenMPIterationSpace( + OpenMPDirectiveKind DKind, Stmt *S, Sema &SemaRef, DSAStackTy &DSA, + unsigned CurrentNestedLoopCount, unsigned NestedLoopCount, + Expr *NestedLoopCountExpr, + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { // OpenMP [2.6, Canonical Loop Form] // for (init-expr; test-expr; incr-expr) structured-block auto For = dyn_cast_or_null<ForStmt>(S); @@ -1560,6 +1603,18 @@ static bool CheckOpenMPIterationSpace(OpenMPDirectiveKind DKind, Stmt *S, HasErrors = true; } + // OpenMP, 2.14.1.1 Data-sharing Attribute Rules for Variables Referenced in a + // Construct + // The loop iteration variable(s) in the associated for-loop(s) of a for or + // parallel for construct is (are) private. + // The loop iteration variable in the associated for-loop of a simd construct + // with just one associated for-loop is linear with a constant-linear-step + // that is the increment of the associated for-loop. + // Exclude loop var from the list of variables with implicitly defined data + // sharing attributes. + while (VarsWithImplicitDSA.count(Var) > 0) + VarsWithImplicitDSA.erase(Var); + // OpenMP [2.14.1.1, Data-sharing Attribute Rules for Variables Referenced in // a Construct, C/C++]. // The loop iteration variable in the associated for-loop of a simd construct @@ -1568,18 +1623,25 @@ static bool CheckOpenMPIterationSpace(OpenMPDirectiveKind DKind, Stmt *S, // 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); + auto PredeterminedCKind = + isOpenMPSimdDirective(DKind) + ? ((NestedLoopCount == 1) ? OMPC_linear : OMPC_lastprivate) + : OMPC_private; if (((isOpenMPSimdDirective(DKind) && DVar.CKind != OMPC_unknown && - DVar.CKind != OMPC_linear && DVar.CKind != OMPC_lastprivate) || + DVar.CKind != PredeterminedCKind) || (isOpenMPWorksharingDirective(DKind) && DVar.CKind != OMPC_unknown && DVar.CKind != OMPC_private && DVar.CKind != OMPC_lastprivate)) && (DVar.CKind != OMPC_private || DVar.RefExpr != nullptr)) { SemaRef.Diag(Init->getLocStart(), diag::err_omp_loop_var_dsa) - << getOpenMPClauseName(DVar.CKind); + << getOpenMPClauseName(DVar.CKind) << getOpenMPDirectiveName(DKind) + << getOpenMPClauseName(PredeterminedCKind); ReportOriginalDSA(SemaRef, &DSA, Var, DVar, true); HasErrors = true; } else { - // Make the loop iteration variable private by default. - DSA.addDSA(Var, nullptr, OMPC_private); + // Make the loop iteration variable private (for worksharing constructs), + // linear (for simd directives with the only one associated loop) or + // lastprivate (for simd directives with several collapsed loops). + DSA.addDSA(Var, nullptr, PredeterminedCKind); } assert(isOpenMPLoopDirective(DKind) && "DSA for non-loop vars"); @@ -1624,9 +1686,10 @@ static Stmt *IgnoreContainerStmts(Stmt *S, bool IgnoreCaptured) { /// \brief Called on a for stmt to check itself and nested loops (if any). /// \return Returns 0 if one of the collapsed stmts is not canonical for loop, /// number of collapsed loops otherwise. -static unsigned CheckOpenMPLoop(OpenMPDirectiveKind DKind, - Expr *NestedLoopCountExpr, Stmt *AStmt, - Sema &SemaRef, DSAStackTy &DSA) { +static unsigned +CheckOpenMPLoop(OpenMPDirectiveKind DKind, Expr *NestedLoopCountExpr, + Stmt *AStmt, Sema &SemaRef, DSAStackTy &DSA, + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { unsigned NestedLoopCount = 1; if (NestedLoopCountExpr) { // Found 'collapse' clause - calculate collapse number. @@ -1639,7 +1702,8 @@ static unsigned CheckOpenMPLoop(OpenMPDirectiveKind DKind, Stmt *CurStmt = IgnoreContainerStmts(AStmt, true); for (unsigned Cnt = 0; Cnt < NestedLoopCount; ++Cnt) { if (CheckOpenMPIterationSpace(DKind, CurStmt, SemaRef, DSA, Cnt, - NestedLoopCount, NestedLoopCountExpr)) + NestedLoopCount, NestedLoopCountExpr, + VarsWithImplicitDSA)) return 0; // Move on to the next nested for loop, or to the loop body. CurStmt = IgnoreContainerStmts(cast<ForStmt>(CurStmt)->getBody(), false); @@ -1661,12 +1725,14 @@ static Expr *GetCollapseNumberExpr(ArrayRef<OMPClause *> Clauses) { return nullptr; } -StmtResult Sema::ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> Clauses, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc) { +StmtResult Sema::ActOnOpenMPSimdDirective( + ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { // In presence of clause 'collapse', it will define the nested loops number. - unsigned NestedLoopCount = CheckOpenMPLoop( - OMPD_simd, GetCollapseNumberExpr(Clauses), AStmt, *this, *DSAStack); + unsigned NestedLoopCount = + CheckOpenMPLoop(OMPD_simd, GetCollapseNumberExpr(Clauses), AStmt, *this, + *DSAStack, VarsWithImplicitDSA); if (NestedLoopCount == 0) return StmtError(); @@ -1675,12 +1741,14 @@ StmtResult Sema::ActOnOpenMPSimdDirective(ArrayRef<OMPClause *> Clauses, Clauses, AStmt); } -StmtResult Sema::ActOnOpenMPForDirective(ArrayRef<OMPClause *> Clauses, - Stmt *AStmt, SourceLocation StartLoc, - SourceLocation EndLoc) { +StmtResult Sema::ActOnOpenMPForDirective( + ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { // In presence of clause 'collapse', it will define the nested loops number. - unsigned NestedLoopCount = CheckOpenMPLoop( - OMPD_for, GetCollapseNumberExpr(Clauses), AStmt, *this, *DSAStack); + unsigned NestedLoopCount = + CheckOpenMPLoop(OMPD_for, GetCollapseNumberExpr(Clauses), AStmt, *this, + *DSAStack, VarsWithImplicitDSA); if (NestedLoopCount == 0) return StmtError(); @@ -1741,6 +1809,31 @@ StmtResult Sema::ActOnOpenMPSingleDirective(ArrayRef<OMPClause *> Clauses, return OMPSingleDirective::Create(Context, StartLoc, EndLoc, Clauses, AStmt); } +StmtResult Sema::ActOnOpenMPParallelForDirective( + ArrayRef<OMPClause *> Clauses, Stmt *AStmt, SourceLocation StartLoc, + SourceLocation EndLoc, + llvm::DenseMap<VarDecl *, Expr *> &VarsWithImplicitDSA) { + 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(); + + // In presence of clause 'collapse', it will define the nested loops number. + unsigned NestedLoopCount = + CheckOpenMPLoop(OMPD_parallel_for, GetCollapseNumberExpr(Clauses), AStmt, + *this, *DSAStack, VarsWithImplicitDSA); + if (NestedLoopCount == 0) + return StmtError(); + + getCurFunction()->setHasBranchProtectedScope(); + return OMPParallelForDirective::Create(Context, StartLoc, EndLoc, + NestedLoopCount, Clauses, AStmt); +} + OMPClause *Sema::ActOnOpenMPSingleExprClause(OpenMPClauseKind Kind, Expr *Expr, SourceLocation StartLoc, SourceLocation LParenLoc, diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h index 64c717f570a..7a5cc3cb731 100644 --- a/clang/lib/Sema/TreeTransform.h +++ b/clang/lib/Sema/TreeTransform.h @@ -6483,6 +6483,17 @@ TreeTransform<Derived>::TransformOMPSingleDirective(OMPSingleDirective *D) { return Res; } +template <typename Derived> +StmtResult TreeTransform<Derived>::TransformOMPParallelForDirective( + OMPParallelForDirective *D) { + DeclarationNameInfo DirName; + getDerived().getSema().StartOpenMPDSABlock(OMPD_parallel_for, 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 a8cfe9e0006..249a4b23c9e 100644 --- a/clang/lib/Serialization/ASTReaderStmt.cpp +++ b/clang/lib/Serialization/ASTReaderStmt.cpp @@ -1943,6 +1943,13 @@ void ASTStmtReader::VisitOMPSingleDirective(OMPSingleDirective *D) { VisitOMPExecutableDirective(D); } +void ASTStmtReader::VisitOMPParallelForDirective(OMPParallelForDirective *D) { + VisitStmt(D); + // Two fields (NumClauses and CollapsedNum) were read in ReadStmtFromStream. + Idx += 2; + VisitOMPExecutableDirective(D); +} + //===----------------------------------------------------------------------===// // ASTReader Implementation //===----------------------------------------------------------------------===// @@ -2455,6 +2462,14 @@ Stmt *ASTReader::ReadStmtFromStream(ModuleFile &F) { Context, Record[ASTStmtReader::NumStmtFields], Empty); break; + case STMT_OMP_PARALLEL_FOR_DIRECTIVE: { + unsigned NumClauses = Record[ASTStmtReader::NumStmtFields]; + unsigned CollapsedNum = Record[ASTStmtReader::NumStmtFields + 1]; + S = OMPParallelForDirective::CreateEmpty(Context, NumClauses, + CollapsedNum, 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 11be3fdd6de..e1bce17c6fd 100644 --- a/clang/lib/Serialization/ASTWriterStmt.cpp +++ b/clang/lib/Serialization/ASTWriterStmt.cpp @@ -1851,6 +1851,14 @@ void ASTStmtWriter::VisitOMPSingleDirective(OMPSingleDirective *D) { Code = serialization::STMT_OMP_SINGLE_DIRECTIVE; } +void ASTStmtWriter::VisitOMPParallelForDirective(OMPParallelForDirective *D) { + VisitStmt(D); + Record.push_back(D->getNumClauses()); + Record.push_back(D->getCollapsedNumber()); + VisitOMPExecutableDirective(D); + Code = serialization::STMT_OMP_PARALLEL_FOR_DIRECTIVE; +} + //===----------------------------------------------------------------------===// // ASTWriter Implementation //===----------------------------------------------------------------------===// diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp index df05f625090..15913f52a72 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -737,6 +737,7 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred, case Stmt::OMPSectionsDirectiveClass: case Stmt::OMPSectionDirectiveClass: case Stmt::OMPSingleDirectiveClass: + case Stmt::OMPParallelForDirectiveClass: llvm_unreachable("Stmt should not be in analyzer evaluation loop"); case Stmt::ObjCSubscriptRefExprClass: |