summaryrefslogtreecommitdiffstats
path: root/clang/lib/Sema
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/Sema')
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp224
-rw-r--r--clang/lib/Sema/TreeTransform.h5
2 files changed, 186 insertions, 43 deletions
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index 83329350f28..0ee0c3c9393 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -89,7 +89,7 @@ private:
};
typedef llvm::SmallDenseMap<VarDecl *, DSAInfo, 64> DeclSAMapTy;
typedef llvm::SmallDenseMap<VarDecl *, DeclRefExpr *, 64> AlignedMapTy;
- typedef llvm::DenseSet<VarDecl *> LoopControlVariablesSetTy;
+ typedef llvm::DenseMap<VarDecl *, unsigned> LoopControlVariablesMapTy;
typedef llvm::SmallDenseMap<VarDecl *, MapInfo, 64> MappedDeclsTy;
typedef llvm::StringMap<std::pair<OMPCriticalDirective *, llvm::APSInt>>
CriticalsWithHintsTy;
@@ -98,7 +98,7 @@ private:
DeclSAMapTy SharingMap;
AlignedMapTy AlignedMap;
MappedDeclsTy MappedDecls;
- LoopControlVariablesSetTy LCVSet;
+ LoopControlVariablesMapTy LCVMap;
DefaultDataSharingAttributes DefaultAttr;
SourceLocation DefaultAttrLoc;
OpenMPDirectiveKind Directive;
@@ -115,12 +115,12 @@ private:
SourceLocation InnerTeamsRegionLoc;
SharingMapTy(OpenMPDirectiveKind DKind, DeclarationNameInfo Name,
Scope *CurScope, SourceLocation Loc)
- : SharingMap(), AlignedMap(), LCVSet(), DefaultAttr(DSA_unspecified),
+ : SharingMap(), AlignedMap(), LCVMap(), DefaultAttr(DSA_unspecified),
Directive(DKind), DirectiveName(std::move(Name)), CurScope(CurScope),
ConstructLoc(Loc), OrderedRegion(), NowaitRegion(false),
CancelRegion(false), CollapseNumber(1), InnerTeamsRegionLoc() {}
SharingMapTy()
- : SharingMap(), AlignedMap(), LCVSet(), DefaultAttr(DSA_unspecified),
+ : SharingMap(), AlignedMap(), LCVMap(), DefaultAttr(DSA_unspecified),
Directive(OMPD_unknown), DirectiveName(), CurScope(nullptr),
ConstructLoc(), OrderedRegion(), NowaitRegion(false),
CancelRegion(false), CollapseNumber(1), InnerTeamsRegionLoc() {}
@@ -185,7 +185,17 @@ public:
void addLoopControlVariable(VarDecl *D);
/// \brief Check if the specified variable is a loop control variable for
/// current region.
- bool isLoopControlVariable(VarDecl *D);
+ /// \return The index of the loop control variable in the list of associated
+ /// for-loops (from outer to inner).
+ unsigned isLoopControlVariable(VarDecl *D);
+ /// \brief Check if the specified variable is a loop control variable for
+ /// parent region.
+ /// \return The index of the loop control variable in the list of associated
+ /// for-loops (from outer to inner).
+ unsigned isParentLoopControlVariable(VarDecl *D);
+ /// \brief Get the loop control variable for the I-th loop (or nullptr) in
+ /// parent directive.
+ VarDecl *getParentLoopControlVariable(unsigned I);
/// \brief Adds explicit data sharing attribute to the specified declaration.
void addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A);
@@ -486,13 +496,32 @@ DeclRefExpr *DSAStackTy::addUniqueAligned(VarDecl *D, DeclRefExpr *NewDE) {
void DSAStackTy::addLoopControlVariable(VarDecl *D) {
assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
D = D->getCanonicalDecl();
- Stack.back().LCVSet.insert(D);
+ Stack.back().LCVMap[D] = Stack.back().LCVMap.size() + 1;
}
-bool DSAStackTy::isLoopControlVariable(VarDecl *D) {
+unsigned DSAStackTy::isLoopControlVariable(VarDecl *D) {
assert(Stack.size() > 1 && "Data-sharing attributes stack is empty");
D = D->getCanonicalDecl();
- return Stack.back().LCVSet.count(D) > 0;
+ return Stack.back().LCVMap.count(D) > 0 ? Stack.back().LCVMap[D] : 0;
+}
+
+unsigned DSAStackTy::isParentLoopControlVariable(VarDecl *D) {
+ assert(Stack.size() > 2 && "Data-sharing attributes stack is empty");
+ D = D->getCanonicalDecl();
+ return Stack[Stack.size() - 2].LCVMap.count(D) > 0
+ ? Stack[Stack.size() - 2].LCVMap[D]
+ : 0;
+}
+
+VarDecl *DSAStackTy::getParentLoopControlVariable(unsigned I) {
+ assert(Stack.size() > 2 && "Data-sharing attributes stack is empty");
+ if (Stack[Stack.size() - 2].LCVMap.size() < I)
+ return nullptr;
+ for (auto &Pair : Stack[Stack.size() - 2].LCVMap) {
+ if (Pair.second == I)
+ return Pair.first;
+ }
+ return nullptr;
}
void DSAStackTy::addDSA(VarDecl *D, DeclRefExpr *E, OpenMPClauseKind A) {
@@ -4576,6 +4605,7 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
SourceLocation EndLoc) {
OMPClause *DependFound = nullptr;
OMPClause *DependSourceClause = nullptr;
+ OMPClause *DependSinkClause = nullptr;
bool ErrorFound = false;
OMPThreadsClause *TC = nullptr;
OMPSIMDClause *SC = nullptr;
@@ -4590,6 +4620,18 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
ErrorFound = true;
} else
DependSourceClause = C;
+ if (DependSinkClause) {
+ Diag(C->getLocStart(), diag::err_omp_depend_sink_source_not_allowed)
+ << 0;
+ ErrorFound = true;
+ }
+ } else if (DC->getDependencyKind() == OMPC_DEPEND_sink) {
+ if (DependSourceClause) {
+ Diag(C->getLocStart(), diag::err_omp_depend_sink_source_not_allowed)
+ << 1;
+ ErrorFound = true;
+ }
+ DependSinkClause = C;
}
} else if (C->getClauseKind() == OMPC_threads)
TC = cast<OMPThreadsClause>(C);
@@ -5753,7 +5795,8 @@ OMPClause *Sema::ActOnOpenMPNumThreadsClause(Expr *NumThreads,
}
ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
- OpenMPClauseKind CKind) {
+ OpenMPClauseKind CKind,
+ bool StrictlyPositive) {
if (!E)
return ExprError();
if (E->isValueDependent() || E->isTypeDependent() ||
@@ -5763,9 +5806,11 @@ ExprResult Sema::VerifyPositiveIntegerConstantInClause(Expr *E,
ExprResult ICE = VerifyIntegerConstantExpression(E, &Result);
if (ICE.isInvalid())
return ExprError();
- if (!Result.isStrictlyPositive()) {
+ if ((StrictlyPositive && !Result.isStrictlyPositive()) ||
+ (!StrictlyPositive && !Result.isNonNegative())) {
Diag(E->getExprLoc(), diag::err_omp_negative_expression_in_clause)
- << getOpenMPClauseName(CKind) << 1 << E->getSourceRange();
+ << getOpenMPClauseName(CKind) << (StrictlyPositive ? 1 : 0)
+ << E->getSourceRange();
return ExprError();
}
if (CKind == OMPC_aligned && !Result.isPowerOf2()) {
@@ -7990,29 +8035,32 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
ArrayRef<Expr *> VarList, SourceLocation StartLoc,
SourceLocation LParenLoc, SourceLocation EndLoc) {
if (DSAStack->getCurrentDirective() == OMPD_ordered &&
- DepKind != OMPC_DEPEND_source) {
+ DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
std::string Values = "'";
Values += getOpenMPSimpleClauseTypeName(OMPC_depend, OMPC_DEPEND_source);
+ Values += "' or '";
+ Values += getOpenMPSimpleClauseTypeName(OMPC_depend, OMPC_DEPEND_sink);
Values += "'";
Diag(DepLoc, diag::err_omp_unexpected_clause_value)
<< Values << getOpenMPClauseName(OMPC_depend);
return nullptr;
}
if (DSAStack->getCurrentDirective() != OMPD_ordered &&
- (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source)) {
+ (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
+ DepKind == OMPC_DEPEND_sink)) {
std::string Values;
std::string Sep(", ");
for (unsigned i = 0; i < OMPC_DEPEND_unknown; ++i) {
- if (i == OMPC_DEPEND_source)
+ if (i == OMPC_DEPEND_source || i == OMPC_DEPEND_sink)
continue;
Values += "'";
Values += getOpenMPSimpleClauseTypeName(OMPC_depend, i);
Values += "'";
switch (i) {
- case OMPC_DEPEND_unknown - 3:
+ case OMPC_DEPEND_unknown - 4:
Values += " or ";
break;
- case OMPC_DEPEND_unknown - 2:
+ case OMPC_DEPEND_unknown - 3:
break;
default:
Values += Sep;
@@ -8024,38 +8072,128 @@ Sema::ActOnOpenMPDependClause(OpenMPDependClauseKind DepKind,
return nullptr;
}
SmallVector<Expr *, 8> Vars;
- for (auto &RefExpr : VarList) {
- assert(RefExpr && "NULL expr in OpenMP shared clause.");
- if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
- // It will be analyzed later.
- Vars.push_back(RefExpr);
- continue;
- }
+ llvm::APSInt DepCounter(/*BitWidth=*/32);
+ llvm::APSInt TotalDepCount(/*BitWidth=*/32);
+ if (DepKind == OMPC_DEPEND_sink) {
+ if (auto *OrderedCountExpr = DSAStack->getParentOrderedRegionParam()) {
+ TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Context);
+ TotalDepCount.setIsUnsigned(/*Val=*/true);
+ }
+ }
+ if ((DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) ||
+ DSAStack->getParentOrderedRegionParam()) {
+ for (auto &RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP shared clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr) ||
+ (DepKind == OMPC_DEPEND_sink && CurContext->isDependentContext())) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ continue;
+ }
- SourceLocation ELoc = RefExpr->getExprLoc();
- // OpenMP [2.11.1.1, Restrictions, p.3]
- // A variable that is part of another variable (such as a field of a
- // structure) but is not an array element or an array section cannot appear
- // in a depend clause.
- auto *SimpleExpr = RefExpr->IgnoreParenCasts();
- auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr);
- auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
- auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr);
- if (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
- (!ASE && !DE && !OASE) || (DE && !isa<VarDecl>(DE->getDecl())) ||
- (ASE && !ASE->getBase()->getType()->isAnyPointerType() &&
- !ASE->getBase()->getType()->isArrayType())) {
- Diag(ELoc, diag::err_omp_expected_var_name_or_array_item)
- << RefExpr->getSourceRange();
- continue;
+ SourceLocation ELoc = RefExpr->getExprLoc();
+ auto *SimpleExpr = RefExpr->IgnoreParenCasts();
+ if (DepKind == OMPC_DEPEND_sink) {
+ if (DepCounter >= TotalDepCount) {
+ Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
+ continue;
+ }
+ ++DepCounter;
+ // OpenMP [2.13.9, Summary]
+ // depend(dependence-type : vec), where dependence-type is:
+ // 'sink' and where vec is the iteration vector, which has the form:
+ // x1 [+- d1], x2 [+- d2 ], . . . , xn [+- dn]
+ // where n is the value specified by the ordered clause in the loop
+ // directive, xi denotes the loop iteration variable of the i-th nested
+ // loop associated with the loop directive, and di is a constant
+ // non-negative integer.
+ SimpleExpr = SimpleExpr->IgnoreImplicit();
+ auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr);
+ if (!DE) {
+ OverloadedOperatorKind OOK = OO_None;
+ SourceLocation OOLoc;
+ Expr *LHS, *RHS;
+ if (auto *BO = dyn_cast<BinaryOperator>(SimpleExpr)) {
+ OOK = BinaryOperator::getOverloadedOperator(BO->getOpcode());
+ OOLoc = BO->getOperatorLoc();
+ LHS = BO->getLHS()->IgnoreParenImpCasts();
+ RHS = BO->getRHS()->IgnoreParenImpCasts();
+ } else if (auto *OCE = dyn_cast<CXXOperatorCallExpr>(SimpleExpr)) {
+ OOK = OCE->getOperator();
+ OOLoc = OCE->getOperatorLoc();
+ LHS = OCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
+ RHS = OCE->getArg(/*Arg=*/1)->IgnoreParenImpCasts();
+ } else if (auto *MCE = dyn_cast<CXXMemberCallExpr>(SimpleExpr)) {
+ OOK = MCE->getMethodDecl()
+ ->getNameInfo()
+ .getName()
+ .getCXXOverloadedOperator();
+ OOLoc = MCE->getCallee()->getExprLoc();
+ LHS = MCE->getImplicitObjectArgument()->IgnoreParenImpCasts();
+ RHS = MCE->getArg(/*Arg=*/0)->IgnoreParenImpCasts();
+ } else {
+ Diag(ELoc, diag::err_omp_depend_sink_wrong_expr);
+ continue;
+ }
+ DE = dyn_cast<DeclRefExpr>(LHS);
+ if (!DE) {
+ Diag(LHS->getExprLoc(),
+ diag::err_omp_depend_sink_expected_loop_iteration)
+ << DSAStack->getParentLoopControlVariable(
+ DepCounter.getZExtValue());
+ continue;
+ }
+ if (OOK != OO_Plus && OOK != OO_Minus) {
+ Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
+ continue;
+ }
+ ExprResult Res = VerifyPositiveIntegerConstantInClause(
+ RHS, OMPC_depend, /*StrictlyPositive=*/false);
+ if (Res.isInvalid())
+ continue;
+ }
+ auto *VD = dyn_cast<VarDecl>(DE->getDecl());
+ if (!CurContext->isDependentContext() &&
+ DSAStack->getParentOrderedRegionParam() &&
+ (!VD || DepCounter != DSAStack->isParentLoopControlVariable(VD))) {
+ Diag(DE->getExprLoc(),
+ diag::err_omp_depend_sink_expected_loop_iteration)
+ << DSAStack->getParentLoopControlVariable(
+ DepCounter.getZExtValue());
+ continue;
+ }
+ } else {
+ // OpenMP [2.11.1.1, Restrictions, p.3]
+ // A variable that is part of another variable (such as a field of a
+ // structure) but is not an array element or an array section cannot
+ // appear in a depend clause.
+ auto *DE = dyn_cast<DeclRefExpr>(SimpleExpr);
+ auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
+ auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr);
+ if (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
+ (!ASE && !DE && !OASE) || (DE && !isa<VarDecl>(DE->getDecl())) ||
+ (ASE && !ASE->getBase()->getType()->isAnyPointerType() &&
+ !ASE->getBase()->getType()->isArrayType())) {
+ Diag(ELoc, diag::err_omp_expected_var_name_or_array_item)
+ << RefExpr->getSourceRange();
+ continue;
+ }
+ }
+
+ Vars.push_back(RefExpr->IgnoreParenImpCasts());
}
- Vars.push_back(RefExpr->IgnoreParenImpCasts());
+ if (!CurContext->isDependentContext() && DepKind == OMPC_DEPEND_sink &&
+ TotalDepCount > VarList.size() &&
+ DSAStack->getParentOrderedRegionParam()) {
+ Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
+ << DSAStack->getParentLoopControlVariable(VarList.size() + 1);
+ }
+ if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
+ Vars.empty())
+ return nullptr;
}
- if (DepKind != OMPC_DEPEND_source && Vars.empty())
- return nullptr;
-
return OMPDependClause::Create(Context, StartLoc, LParenLoc, EndLoc, DepKind,
DepLoc, ColonLoc, Vars);
}
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index f11f135d462..e28b9dc8529 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -6275,6 +6275,11 @@ TreeTransform<Derived>::TransformForStmt(ForStmt *S) {
if (Init.isInvalid())
return StmtError();
+ // In OpenMP loop region loop control variable must be captured and be
+ // private. Perform analysis of first part (if any).
+ if (getSema().getLangOpts().OpenMP && Init.isUsable())
+ getSema().ActOnOpenMPLoopInitialization(S->getForLoc(), Init.get());
+
// Transform the condition
ExprResult Cond;
VarDecl *ConditionVar = nullptr;
OpenPOWER on IntegriCloud