summaryrefslogtreecommitdiffstats
path: root/clang/lib
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib')
-rw-r--r--clang/lib/AST/Stmt.cpp26
-rw-r--r--clang/lib/AST/StmtPrinter.cpp5
-rw-r--r--clang/lib/AST/StmtProfile.cpp5
-rw-r--r--clang/lib/Basic/OpenMPKinds.cpp23
-rw-r--r--clang/lib/CodeGen/CGStmt.cpp3
-rw-r--r--clang/lib/CodeGen/CGStmtOpenMP.cpp5
-rw-r--r--clang/lib/CodeGen/CodeGenFunction.h1
-rw-r--r--clang/lib/Parse/ParseOpenMP.cpp34
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp151
-rw-r--r--clang/lib/Sema/TreeTransform.h11
-rw-r--r--clang/lib/Serialization/ASTReaderStmt.cpp15
-rw-r--r--clang/lib/Serialization/ASTWriterStmt.cpp8
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngine.cpp1
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:
OpenPOWER on IntegriCloud