[OPENMP] Parsing and sema analysis for 'omp task' directive.
llvm-svn: 212804
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index a7ad809..f065014 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -139,21 +139,22 @@
/// \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 @@
/// \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 @@
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 @@
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 @@
DVar.CKind = OMPC_firstprivate;
return DVar;
}
- if (isOpenMPParallelDirective(I->Directive))
+ if (isParallelOrTaskRegion(I->Directive))
break;
}
DVar.DKind = OMPD_task;
@@ -328,7 +334,7 @@
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 @@
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 @@
// 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 @@
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 @@
!(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 @@
// 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 @@
}
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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
// 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 @@
}
// 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 @@
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 @@
// | parallel | single | * |
// | parallel | parallel for | * |
// | parallel |parallel sections| * |
+ // | parallel | task | * |
// +------------------+-----------------+------------------------------------+
// | for | parallel | * |
// | for | for | + |
@@ -1016,6 +1060,7 @@
// | for | single | + |
// | for | parallel for | * |
// | for |parallel sections| * |
+ // | for | task | * |
// +------------------+-----------------+------------------------------------+
// | simd | parallel | |
// | simd | for | |
@@ -1025,6 +1070,7 @@
// | simd | single | |
// | simd | parallel for | |
// | simd |parallel sections| |
+ // | simd | task | |
// +------------------+-----------------+------------------------------------+
// | sections | parallel | * |
// | sections | for | + |
@@ -1034,6 +1080,7 @@
// | sections | single | + |
// | sections | parallel for | * |
// | sections |parallel sections| * |
+ // | sections | task | * |
// +------------------+-----------------+------------------------------------+
// | section | parallel | * |
// | section | for | + |
@@ -1043,6 +1090,7 @@
// | section | single | + |
// | section | parallel for | * |
// | section |parallel sections| * |
+ // | section | task | * |
// +------------------+-----------------+------------------------------------+
// | single | parallel | * |
// | single | for | + |
@@ -1052,6 +1100,7 @@
// | single | single | + |
// | single | parallel for | * |
// | single |parallel sections| * |
+ // | single | task | * |
// +------------------+-----------------+------------------------------------+
// | parallel for | parallel | * |
// | parallel for | for | + |
@@ -1061,6 +1110,7 @@
// | parallel for | single | + |
// | parallel for | parallel for | * |
// | parallel for |parallel sections| * |
+ // | parallel for | task | * |
// +------------------+-----------------+------------------------------------+
// | parallel sections| parallel | * |
// | parallel sections| for | + |
@@ -1070,6 +1120,17 @@
// | 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 @@
// 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 @@
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 @@
// 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 @@
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 @@
// 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 @@
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 @@
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 @@
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 @@
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 @@
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 @@
}
}
- // 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
// 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 @@
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 @@
// 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 @@
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 @@
// 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 @@
// 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 @@
// 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)