summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema/SemaOpenMP.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema/SemaOpenMP.cpp')
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp144
1 files changed, 75 insertions, 69 deletions
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index d7a6d2e5885..c384d5f16af 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -118,6 +118,7 @@ private:
typedef SmallVector<SharingMapTy, 4> StackTy;
/// \brief Stack of used declaration and their data-sharing attributes.
+ DeclSAMapTy Threadprivates;
StackTy Stack;
/// \brief true, if check for DSA must be from parent directive, false, if
/// from current directive.
@@ -134,7 +135,7 @@ private:
bool isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter);
public:
- explicit DSAStackTy(Sema &S) : Stack(1), SemaRef(S) {}
+ explicit DSAStackTy(Sema &S) : SemaRef(S) {}
bool isClauseParsingMode() const { return ClauseKindMode != OMPC_unknown; }
void setClauseParsingMode(OpenMPClauseKind K) { ClauseKindMode = K; }
@@ -149,7 +150,7 @@ public:
}
void pop() {
- assert(Stack.size() > 1 && "Data-sharing attributes stack is empty!");
+ assert(!Stack.empty() && "Data-sharing attributes stack is empty!");
Stack.pop_back();
}
@@ -229,11 +230,11 @@ public:
/// \brief Returns currently analyzed directive.
OpenMPDirectiveKind getCurrentDirective() const {
- return Stack.back().Directive;
+ return Stack.empty() ? OMPD_unknown : Stack.back().Directive;
}
/// \brief Returns parent directive.
OpenMPDirectiveKind getParentDirective() const {
- if (Stack.size() > 2)
+ if (Stack.size() > 1)
return Stack[Stack.size() - 2].Directive;
return OMPD_unknown;
}
@@ -250,10 +251,10 @@ public:
}
DefaultDataSharingAttributes getDefaultDSA() const {
- return Stack.back().DefaultAttr;
+ return Stack.empty() ? DSA_unspecified : Stack.back().DefaultAttr;
}
SourceLocation getDefaultDSALocation() const {
- return Stack.back().DefaultAttrLoc;
+ return Stack.empty() ? SourceLocation() : Stack.back().DefaultAttrLoc;
}
/// \brief Checks if the specified variable is a threadprivate.
@@ -270,13 +271,13 @@ public:
/// \brief Returns true, if parent region is ordered (has associated
/// 'ordered' clause), false - otherwise.
bool isParentOrderedRegion() const {
- if (Stack.size() > 2)
+ if (Stack.size() > 1)
return Stack[Stack.size() - 2].OrderedRegion.getInt();
return false;
}
/// \brief Returns optional parameter for the ordered region.
Expr *getParentOrderedRegionParam() const {
- if (Stack.size() > 2)
+ if (Stack.size() > 1)
return Stack[Stack.size() - 2].OrderedRegion.getPointer();
return nullptr;
}
@@ -287,28 +288,32 @@ public:
/// \brief Returns true, if parent region is nowait (has associated
/// 'nowait' clause), false - otherwise.
bool isParentNowaitRegion() const {
- if (Stack.size() > 2)
+ if (Stack.size() > 1)
return Stack[Stack.size() - 2].NowaitRegion;
return false;
}
/// \brief Marks parent region as cancel region.
void setParentCancelRegion(bool Cancel = true) {
- if (Stack.size() > 2)
+ if (Stack.size() > 1)
Stack[Stack.size() - 2].CancelRegion =
Stack[Stack.size() - 2].CancelRegion || Cancel;
}
/// \brief Return true if current region has inner cancel construct.
- bool isCancelRegion() const { return Stack.back().CancelRegion; }
+ bool isCancelRegion() const {
+ return Stack.empty() ? false : Stack.back().CancelRegion;
+ }
/// \brief Set collapse value for the region.
void setAssociatedLoops(unsigned Val) { Stack.back().AssociatedLoops = Val; }
/// \brief Return collapse value for region.
- unsigned getAssociatedLoops() const { return Stack.back().AssociatedLoops; }
+ unsigned getAssociatedLoops() const {
+ return Stack.empty() ? 0 : Stack.back().AssociatedLoops;
+ }
/// \brief Marks current target region as one with closely nested teams
/// region.
void setParentTeamsRegionLoc(SourceLocation TeamsRegionLoc) {
- if (Stack.size() > 2)
+ if (Stack.size() > 1)
Stack[Stack.size() - 2].InnerTeamsRegionLoc = TeamsRegionLoc;
}
/// \brief Returns true, if current region has closely nested teams region.
@@ -317,14 +322,18 @@ public:
}
/// \brief Returns location of the nested teams region (if any).
SourceLocation getInnerTeamsRegionLoc() const {
- if (Stack.size() > 1)
- return Stack.back().InnerTeamsRegionLoc;
- return SourceLocation();
+ return Stack.empty() ? SourceLocation() : Stack.back().InnerTeamsRegionLoc;
}
- Scope *getCurScope() const { return Stack.back().CurScope; }
- Scope *getCurScope() { return Stack.back().CurScope; }
- SourceLocation getConstructLoc() { return Stack.back().ConstructLoc; }
+ Scope *getCurScope() const {
+ return Stack.empty() ? nullptr : Stack.back().CurScope;
+ }
+ Scope *getCurScope() {
+ return Stack.empty() ? nullptr : Stack.back().CurScope;
+ }
+ SourceLocation getConstructLoc() {
+ return Stack.empty() ? SourceLocation() : Stack.back().ConstructLoc;
+ }
/// Do the check specified in \a Check to all component lists and return true
/// if any issue is found.
@@ -361,7 +370,7 @@ public:
ValueDecl *VD,
OMPClauseMappableExprCommon::MappableExprComponentListRef Components,
OpenMPClauseKind WhereFoundClauseKind) {
- assert(Stack.size() > 1 &&
+ assert(!Stack.empty() &&
"Not expecting to retrieve components from a empty stack!");
auto &MEC = Stack.back().MappedExprComponents[VD];
// Create new entry and append the new components there.
@@ -371,23 +380,23 @@ public:
}
unsigned getNestingLevel() const {
- assert(Stack.size() > 1);
- return Stack.size() - 2;
+ assert(!Stack.empty());
+ return Stack.size() - 1;
}
void addDoacrossDependClause(OMPDependClause *C, OperatorOffsetTy &OpsOffs) {
- assert(Stack.size() > 2);
+ assert(Stack.size() > 1);
assert(isOpenMPWorksharingDirective(Stack[Stack.size() - 2].Directive));
Stack[Stack.size() - 2].DoacrossDepends.insert({C, OpsOffs});
}
llvm::iterator_range<DoacrossDependMapTy::const_iterator>
getDoacrossDependClauses() const {
- assert(Stack.size() > 1);
- if (isOpenMPWorksharingDirective(Stack[Stack.size() - 1].Directive)) {
- auto &Ref = Stack[Stack.size() - 1].DoacrossDepends;
+ assert(!Stack.empty());
+ if (isOpenMPWorksharingDirective(Stack.back().Directive)) {
+ auto &Ref = Stack.back().DoacrossDepends;
return llvm::make_range(Ref.begin(), Ref.end());
}
- return llvm::make_range(Stack[0].DoacrossDepends.end(),
- Stack[0].DoacrossDepends.end());
+ return llvm::make_range(Stack.back().DoacrossDepends.end(),
+ Stack.back().DoacrossDepends.end());
}
};
bool isParallelOrTaskRegion(OpenMPDirectiveKind DKind) {
@@ -416,7 +425,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter,
auto *VD = dyn_cast<VarDecl>(D);
auto *FD = dyn_cast<FieldDecl>(D);
DSAVarData DVar;
- if (Iter == std::prev(Stack.rend())) {
+ if (Iter == Stack.rend()) {
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a region but not in construct]
// File-scope or namespace-scope variables referenced in called routines
@@ -490,8 +499,9 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter,
// bound to the current team is shared.
if (isOpenMPTaskingDirective(DVar.DKind)) {
DSAVarData DVarTemp;
- for (StackTy::reverse_iterator I = std::next(Iter), EE = Stack.rend();
- I != EE; ++I) {
+ auto I = Iter, E = Stack.rend();
+ do {
+ ++I;
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables
// Referenced in a Construct, implicitly determined, p.6]
// In a task construct, if no default clause is present, a variable
@@ -503,9 +513,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter,
DVar.CKind = OMPC_firstprivate;
return DVar;
}
- if (isParallelOrTaskRegion(I->Directive))
- break;
- }
+ } while (I != E && !isParallelOrTaskRegion(I->Directive));
DVar.CKind =
(DVarTemp.CKind == OMPC_unknown) ? OMPC_firstprivate : OMPC_shared;
return DVar;
@@ -520,7 +528,7 @@ DSAStackTy::DSAVarData DSAStackTy::getDSA(StackTy::reverse_iterator &Iter,
}
Expr *DSAStackTy::addUniqueAligned(ValueDecl *D, Expr *NewDE) {
- assert(Stack.size() > 1 && "Data sharing attributes stack is empty");
+ assert(!Stack.empty() && "Data sharing attributes stack is empty");
D = getCanonicalDecl(D);
auto It = Stack.back().AlignedMap.find(D);
if (It == Stack.back().AlignedMap.end()) {
@@ -535,21 +543,21 @@ Expr *DSAStackTy::addUniqueAligned(ValueDecl *D, Expr *NewDE) {
}
void DSAStackTy::addLoopControlVariable(ValueDecl *D, VarDecl *Capture) {
- assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
+ assert(!Stack.empty() && "Data-sharing attributes stack is empty");
D = getCanonicalDecl(D);
Stack.back().LCVMap.insert(
- std::make_pair(D, LCDeclInfo(Stack.back().LCVMap.size() + 1, Capture)));
+ {D, LCDeclInfo(Stack.back().LCVMap.size() + 1, Capture)});
}
DSAStackTy::LCDeclInfo DSAStackTy::isLoopControlVariable(ValueDecl *D) {
- assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
+ assert(!Stack.empty() && "Data-sharing attributes stack is empty");
D = getCanonicalDecl(D);
return Stack.back().LCVMap.count(D) > 0 ? Stack.back().LCVMap[D]
: LCDeclInfo(0, nullptr);
}
DSAStackTy::LCDeclInfo DSAStackTy::isParentLoopControlVariable(ValueDecl *D) {
- assert(Stack.size() > 2 && "Data-sharing attributes stack is empty");
+ assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
D = getCanonicalDecl(D);
return Stack[Stack.size() - 2].LCVMap.count(D) > 0
? Stack[Stack.size() - 2].LCVMap[D]
@@ -557,7 +565,7 @@ DSAStackTy::LCDeclInfo DSAStackTy::isParentLoopControlVariable(ValueDecl *D) {
}
ValueDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) {
- assert(Stack.size() > 2 && "Data-sharing attributes stack is empty");
+ assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
if (Stack[Stack.size() - 2].LCVMap.size() < I)
return nullptr;
for (auto &Pair : Stack[Stack.size() - 2].LCVMap) {
@@ -571,12 +579,12 @@ void DSAStackTy::addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
DeclRefExpr *PrivateCopy) {
D = getCanonicalDecl(D);
if (A == OMPC_threadprivate) {
- auto &Data = Stack[0].SharingMap[D];
+ auto &Data = Threadprivates[D];
Data.Attributes = A;
Data.RefExpr.setPointer(E);
Data.PrivateCopy = nullptr;
} else {
- assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
+ assert(!Stack.empty() && "Data-sharing attributes stack is empty");
auto &Data = Stack.back().SharingMap[D];
assert(Data.Attributes == OMPC_unknown || (A == Data.Attributes) ||
(A == OMPC_firstprivate && Data.Attributes == OMPC_lastprivate) ||
@@ -602,19 +610,17 @@ void DSAStackTy::addDSA(ValueDecl *D, Expr *E, OpenMPClauseKind A,
bool DSAStackTy::isOpenMPLocal(VarDecl *D, StackTy::reverse_iterator Iter) {
D = D->getCanonicalDecl();
- if (Stack.size() > 2) {
- reverse_iterator I = Iter, E = std::prev(Stack.rend());
+ if (Stack.size() > 1) {
+ reverse_iterator I = Iter, E = Stack.rend();
Scope *TopScope = nullptr;
- while (I != E && !isParallelOrTaskRegion(I->Directive)) {
+ while (I != E && !isParallelOrTaskRegion(I->Directive))
++I;
- }
if (I == E)
return false;
TopScope = I->CurScope ? I->CurScope->getParent() : nullptr;
Scope *CurScope = getCurScope();
- while (CurScope != TopScope && !CurScope->isDeclScope(D)) {
+ while (CurScope != TopScope && !CurScope->isDeclScope(D))
CurScope = CurScope->getParent();
- }
return CurScope != TopScope;
}
return false;
@@ -665,16 +671,16 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) {
D->getLocation()),
OMPC_threadprivate);
}
- if (Stack[0].SharingMap.count(D)) {
- DVar.RefExpr = Stack[0].SharingMap[D].RefExpr.getPointer();
+ auto TI = Threadprivates.find(D);
+ if (TI != Threadprivates.end()) {
+ DVar.RefExpr = TI->getSecond().RefExpr.getPointer();
DVar.CKind = OMPC_threadprivate;
return DVar;
}
- if (Stack.size() == 1) {
+ if (Stack.empty())
// Not in OpenMP execution region and top scope was already checked.
return DVar;
- }
// OpenMP [2.9.1.1, Data-sharing Attribute Rules for Variables Referenced
// in a Construct, C/C++, predetermined, p.4]
@@ -723,10 +729,9 @@ DSAStackTy::DSAVarData DSAStackTy::getTopDSA(ValueDecl *D, bool FromParent) {
// Explicitly specified attributes and local variables with predetermined
// attributes.
auto StartI = std::next(Stack.rbegin());
- auto EndI = std::prev(Stack.rend());
- if (FromParent && StartI != EndI) {
+ auto EndI = Stack.rend();
+ if (FromParent && StartI != EndI)
StartI = std::next(StartI);
- }
auto I = std::prev(StartI);
if (I->SharingMap.count(D)) {
DVar.RefExpr = I->SharingMap[D].RefExpr.getPointer();
@@ -742,10 +747,9 @@ DSAStackTy::DSAVarData DSAStackTy::getImplicitDSA(ValueDecl *D,
bool FromParent) {
D = getCanonicalDecl(D);
auto StartI = Stack.rbegin();
- auto EndI = std::prev(Stack.rend());
- if (FromParent && StartI != EndI) {
+ auto EndI = Stack.rend();
+ if (FromParent && StartI != EndI)
StartI = std::next(StartI);
- }
return getDSA(StartI, D);
}
@@ -757,17 +761,20 @@ DSAStackTy::hasDSA(ValueDecl *D,
D = getCanonicalDecl(D);
auto StartI = std::next(Stack.rbegin());
auto EndI = Stack.rend();
- if (FromParent && StartI != EndI) {
+ if (FromParent && StartI != EndI)
StartI = std::next(StartI);
- }
- for (auto I = StartI, EE = EndI; I != EE; ++I) {
+ if (StartI == EndI)
+ return {};
+ auto I = std::prev(StartI);
+ do {
+ ++I;
if (!DPred(I->Directive) && !isParallelOrTaskRegion(I->Directive))
continue;
DSAVarData DVar = getDSA(I, D);
if (CPred(DVar.CKind))
return DVar;
- }
- return DSAVarData();
+ } while (I != EndI);
+ return {};
}
DSAStackTy::DSAVarData DSAStackTy::hasInnermostDSA(
@@ -791,7 +798,7 @@ bool DSAStackTy::hasExplicitDSA(
if (CPred(ClauseKindMode))
return true;
D = getCanonicalDecl(D);
- auto StartI = std::next(Stack.begin());
+ auto StartI = Stack.begin();
auto EndI = Stack.end();
if (std::distance(StartI, EndI) <= (int)Level)
return false;
@@ -805,7 +812,7 @@ bool DSAStackTy::hasExplicitDSA(
bool DSAStackTy::hasExplicitDirective(
const llvm::function_ref<bool(OpenMPDirectiveKind)> &DPred,
unsigned Level) {
- auto StartI = std::next(Stack.begin());
+ auto StartI = Stack.begin();
auto EndI = Stack.end();
if (std::distance(StartI, EndI) <= (int)Level)
return false;
@@ -819,13 +826,12 @@ bool DSAStackTy::hasDirective(
&DPred,
bool FromParent) {
// We look only in the enclosing region.
- if (Stack.size() < 2)
+ if (Stack.size() < 1)
return false;
auto StartI = std::next(Stack.rbegin());
- auto EndI = std::prev(Stack.rend());
- if (FromParent && StartI != EndI) {
+ auto EndI = Stack.rend();
+ if (FromParent && StartI != EndI)
StartI = std::next(StartI);
- }
for (auto I = StartI, EE = EndI; I != EE; ++I) {
if (DPred(I->Directive, I->DirectiveName, I->ConstructLoc))
return true;
OpenPOWER on IntegriCloud