aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/Sema/SemaOpenMP.cpp
diff options
context:
space:
mode:
authorJennifer Yu <jennifer.yu@intel.com>2023-06-21 16:26:35 -0700
committerJennifer Yu <jennifer.yu@intel.com>2023-06-29 11:58:17 -0700
commit085845a2acbefd26d5c229338225dfd76e2c2df3 (patch)
treecdd3eed208d328509c8e2e873bd884867026f6f2 /clang/lib/Sema/SemaOpenMP.cpp
parent41a1625e07e8b20dafec11f0d138031106abfad0 (diff)
downloadllvm-085845a2acbefd26d5c229338225dfd76e2c2df3.zip
llvm-085845a2acbefd26d5c229338225dfd76e2c2df3.tar.gz
llvm-085845a2acbefd26d5c229338225dfd76e2c2df3.tar.bz2
[OMP5.2] Initial support for doacross clause.
Diffstat (limited to 'clang/lib/Sema/SemaOpenMP.cpp')
-rw-r--r--clang/lib/Sema/SemaOpenMP.cpp510
1 files changed, 312 insertions, 198 deletions
diff --git a/clang/lib/Sema/SemaOpenMP.cpp b/clang/lib/Sema/SemaOpenMP.cpp
index e22425b..2d7d6cf 100644
--- a/clang/lib/Sema/SemaOpenMP.cpp
+++ b/clang/lib/Sema/SemaOpenMP.cpp
@@ -88,8 +88,7 @@ public:
};
using OperatorOffsetTy =
llvm::SmallVector<std::pair<Expr *, OverloadedOperatorKind>, 4>;
- using DoacrossDependMapTy =
- llvm::DenseMap<OMPDependClause *, OperatorOffsetTy>;
+ using DoacrossClauseMapTy = llvm::DenseMap<OMPClause *, OperatorOffsetTy>;
/// Kind of the declaration used in the uses_allocators clauses.
enum class UsesAllocatorsDeclKind {
/// Predefined allocator
@@ -170,7 +169,7 @@ private:
/// Set of 'depend' clauses with 'sink|source' dependence kind. Required to
/// get the data (loop counters etc.) about enclosing loop-based construct.
/// This data is required during codegen.
- DoacrossDependMapTy DoacrossDepends;
+ DoacrossClauseMapTy DoacrossDepends;
/// First argument (Expr *) contains optional argument of the
/// 'ordered' clause, the second one is true if the regions has 'ordered'
/// clause, false otherwise.
@@ -1055,17 +1054,16 @@ public:
assert(!isStackEmpty());
return getStackSize() - 1;
}
- void addDoacrossDependClause(OMPDependClause *C,
- const OperatorOffsetTy &OpsOffs) {
+ void addDoacrossDependClause(OMPClause *C, const OperatorOffsetTy &OpsOffs) {
SharingMapTy *Parent = getSecondOnStackOrNull();
assert(Parent && isOpenMPWorksharingDirective(Parent->Directive));
Parent->DoacrossDepends.try_emplace(C, OpsOffs);
}
- llvm::iterator_range<DoacrossDependMapTy::const_iterator>
+ llvm::iterator_range<DoacrossClauseMapTy::const_iterator>
getDoacrossDependClauses() const {
const SharingMapTy &StackElem = getTopOfStack();
if (isOpenMPWorksharingDirective(StackElem.Directive)) {
- const DoacrossDependMapTy &Ref = StackElem.DoacrossDepends;
+ const DoacrossClauseMapTy &Ref = StackElem.DoacrossDepends;
return llvm::make_range(Ref.begin(), Ref.end());
}
return llvm::make_range(StackElem.DoacrossDepends.end(),
@@ -9335,30 +9333,45 @@ static bool checkOpenMPIterationSpace(
}
}
for (auto &Pair : DSA.getDoacrossDependClauses()) {
- if (CurrentNestedLoopCount >= Pair.first->getNumLoops()) {
+ auto *DependC = dyn_cast<OMPDependClause>(Pair.first);
+ auto *DoacrossC = dyn_cast<OMPDoacrossClause>(Pair.first);
+ unsigned NumLoops =
+ DependC ? DependC->getNumLoops() : DoacrossC->getNumLoops();
+ if (CurrentNestedLoopCount >= NumLoops) {
// Erroneous case - clause has some problems.
continue;
}
- if (Pair.first->getDependencyKind() == OMPC_DEPEND_sink &&
+ if (DependC && DependC->getDependencyKind() == OMPC_DEPEND_sink &&
Pair.second.size() <= CurrentNestedLoopCount) {
// Erroneous case - clause has some problems.
- Pair.first->setLoopData(CurrentNestedLoopCount, nullptr);
+ DependC->setLoopData(CurrentNestedLoopCount, nullptr);
+ continue;
+ }
+ if (DoacrossC && DoacrossC->getDependenceType() == OMPC_DOACROSS_sink &&
+ Pair.second.size() <= CurrentNestedLoopCount) {
+ // Erroneous case - clause has some problems.
+ DoacrossC->setLoopData(CurrentNestedLoopCount, nullptr);
continue;
}
Expr *CntValue;
- if (Pair.first->getDependencyKind() == OMPC_DEPEND_source)
+ SourceLocation DepLoc =
+ DependC ? DependC->getDependencyLoc() : DoacrossC->getDependenceLoc();
+ if ((DependC && DependC->getDependencyKind() == OMPC_DEPEND_source) ||
+ (DoacrossC && DoacrossC->getDependenceType() == OMPC_DOACROSS_source))
CntValue = ISC.buildOrderedLoopData(
DSA.getCurScope(),
ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
- Pair.first->getDependencyLoc());
+ DepLoc);
else
CntValue = ISC.buildOrderedLoopData(
DSA.getCurScope(),
ResultIterSpaces[CurrentNestedLoopCount].CounterVar, Captures,
- Pair.first->getDependencyLoc(),
- Pair.second[CurrentNestedLoopCount].first,
+ DepLoc, Pair.second[CurrentNestedLoopCount].first,
Pair.second[CurrentNestedLoopCount].second);
- Pair.first->setLoopData(CurrentNestedLoopCount, CntValue);
+ if (DependC)
+ DependC->setLoopData(CurrentNestedLoopCount, CntValue);
+ else
+ DoacrossC->setLoopData(CurrentNestedLoopCount, CntValue);
}
}
@@ -11274,33 +11287,47 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
const OMPClause *DependFound = nullptr;
const OMPClause *DependSourceClause = nullptr;
const OMPClause *DependSinkClause = nullptr;
+ const OMPClause *DoacrossFound = nullptr;
+ const OMPClause *DoacrossSourceClause = nullptr;
+ const OMPClause *DoacrossSinkClause = nullptr;
bool ErrorFound = false;
const OMPThreadsClause *TC = nullptr;
const OMPSIMDClause *SC = nullptr;
for (const OMPClause *C : Clauses) {
- if (auto *DC = dyn_cast<OMPDependClause>(C)) {
- DependFound = C;
- if (DC->getDependencyKind() == OMPC_DEPEND_source) {
- if (DependSourceClause) {
+ auto DOC = dyn_cast<OMPDoacrossClause>(C);
+ auto DC = dyn_cast<OMPDependClause>(C);
+ if (DC || DOC) {
+ DependFound = DC ? C : nullptr;
+ DoacrossFound = DOC ? C : nullptr;
+ if ((DC && DC->getDependencyKind() == OMPC_DEPEND_source) ||
+ (DOC && DOC->getDependenceType() == OMPC_DOACROSS_source)) {
+ if ((DC && DependSourceClause) || (DOC && DoacrossSourceClause)) {
Diag(C->getBeginLoc(), diag::err_omp_more_one_clause)
<< getOpenMPDirectiveName(OMPD_ordered)
- << getOpenMPClauseName(OMPC_depend) << 2;
+ << getOpenMPClauseName(DC ? OMPC_depend : OMPC_doacross) << 2;
ErrorFound = true;
} else {
- DependSourceClause = C;
+ if (DC)
+ DependSourceClause = C;
+ else
+ DoacrossSourceClause = C;
}
- if (DependSinkClause) {
- Diag(C->getBeginLoc(), diag::err_omp_depend_sink_source_not_allowed)
- << 0;
+ if ((DC && DependSinkClause) || (DOC && DoacrossSinkClause)) {
+ Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
+ << (DC ? "depend" : "doacross") << 0;
ErrorFound = true;
}
- } else if (DC->getDependencyKind() == OMPC_DEPEND_sink) {
- if (DependSourceClause) {
- Diag(C->getBeginLoc(), diag::err_omp_depend_sink_source_not_allowed)
- << 1;
+ } else if ((DC && DC->getDependencyKind() == OMPC_DEPEND_sink) ||
+ (DOC && DOC->getDependenceType() == OMPC_DOACROSS_sink)) {
+ if (DependSourceClause || DoacrossSourceClause) {
+ Diag(C->getBeginLoc(), diag::err_omp_sink_and_source_not_allowed)
+ << (DC ? "depend" : "doacross") << 1;
ErrorFound = true;
}
- DependSinkClause = C;
+ if (DC)
+ DependSinkClause = C;
+ else
+ DoacrossSinkClause = C;
}
} else if (C->getClauseKind() == OMPC_threads) {
TC = cast<OMPThreadsClause>(C);
@@ -11316,13 +11343,19 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
Diag(StartLoc, diag::err_omp_prohibited_region_simd)
<< (LangOpts.OpenMP >= 50 ? 1 : 0);
ErrorFound = true;
- } else if (DependFound && (TC || SC)) {
- Diag(DependFound->getBeginLoc(), diag::err_omp_depend_clause_thread_simd)
+ } else if ((DependFound || DoacrossFound) && (TC || SC)) {
+ SourceLocation Loc =
+ DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
+ Diag(Loc, diag::err_omp_depend_clause_thread_simd)
+ << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross)
<< getOpenMPClauseName(TC ? TC->getClauseKind() : SC->getClauseKind());
ErrorFound = true;
- } else if (DependFound && !DSAStack->getParentOrderedRegionParam().first) {
- Diag(DependFound->getBeginLoc(),
- diag::err_omp_ordered_directive_without_param);
+ } else if ((DependFound || DoacrossFound) &&
+ !DSAStack->getParentOrderedRegionParam().first) {
+ SourceLocation Loc =
+ DependFound ? DependFound->getBeginLoc() : DoacrossFound->getBeginLoc();
+ Diag(Loc, diag::err_omp_ordered_directive_without_param)
+ << getOpenMPClauseName(DependFound ? OMPC_depend : OMPC_doacross);
ErrorFound = true;
} else if (TC || Clauses.empty()) {
if (const Expr *Param = DSAStack->getParentOrderedRegionParam().first) {
@@ -11333,7 +11366,7 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
ErrorFound = true;
}
}
- if ((!AStmt && !DependFound) || ErrorFound)
+ if ((!AStmt && !DependFound && !DoacrossFound) || ErrorFound)
return StmtError();
// OpenMP 5.0, 2.17.9, ordered Construct, Restrictions.
@@ -11341,7 +11374,7 @@ StmtResult Sema::ActOnOpenMPOrderedDirective(ArrayRef<OMPClause *> Clauses,
// within a worksharing-loop, simd, or worksharing-loop SIMD region, a thread
// must not execute more than one ordered region corresponding to an ordered
// construct without a depend clause.
- if (!DependFound) {
+ if (!DependFound && !DoacrossFound) {
if (DSAStack->doesParentHasOrderedDirective()) {
Diag(StartLoc, diag::err_omp_several_directives_in_region) << "ordered";
Diag(DSAStack->getParentOrderedDirectiveLoc(),
@@ -17904,6 +17937,11 @@ OMPClause *Sema::ActOnOpenMPVarListClause(OpenMPClauseKind Kind,
Res = ActOnOpenMPAffinityClause(StartLoc, LParenLoc, ColonLoc, EndLoc,
Data.DepModOrTailExpr, VarList);
break;
+ case OMPC_doacross:
+ Res = ActOnOpenMPDoacrossClause(
+ static_cast<OpenMPDoacrossClauseModifier>(ExtraModifier),
+ ExtraModifierLoc, ColonLoc, VarList, StartLoc, LParenLoc, EndLoc);
+ break;
case OMPC_if:
case OMPC_depobj:
case OMPC_final:
@@ -20525,71 +20563,35 @@ OMPClause *Sema::ActOnOpenMPDepobjClause(Expr *Depobj, SourceLocation StartLoc,
return OMPDepobjClause::Create(Context, StartLoc, LParenLoc, EndLoc, Depobj);
}
-OMPClause *
-Sema::ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data,
- Expr *DepModifier, ArrayRef<Expr *> VarList,
- SourceLocation StartLoc, SourceLocation LParenLoc,
- SourceLocation EndLoc) {
- OpenMPDependClauseKind DepKind = Data.DepKind;
- SourceLocation DepLoc = Data.DepLoc;
- if (DSAStack->getCurrentDirective() == OMPD_ordered &&
- DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
- Diag(DepLoc, diag::err_omp_unexpected_clause_value)
- << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
- return nullptr;
- }
- if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
- DepKind == OMPC_DEPEND_mutexinoutset) {
- Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
- return nullptr;
- }
- if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
- DSAStack->getCurrentDirective() == OMPD_depobj) &&
- (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
- DepKind == OMPC_DEPEND_sink ||
- ((LangOpts.OpenMP < 50 ||
- DSAStack->getCurrentDirective() == OMPD_depobj) &&
- DepKind == OMPC_DEPEND_depobj))) {
- SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
- OMPC_DEPEND_outallmemory,
- OMPC_DEPEND_inoutallmemory};
- if (LangOpts.OpenMP < 50 || DSAStack->getCurrentDirective() == OMPD_depobj)
- Except.push_back(OMPC_DEPEND_depobj);
- if (LangOpts.OpenMP < 51)
- Except.push_back(OMPC_DEPEND_inoutset);
- std::string Expected = (LangOpts.OpenMP >= 50 && !DepModifier)
- ? "depend modifier(iterator) or "
- : "";
- Diag(DepLoc, diag::err_omp_unexpected_clause_value)
- << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
- /*Last=*/OMPC_DEPEND_unknown,
- Except)
- << getOpenMPClauseName(OMPC_depend);
- return nullptr;
- }
- if (DepModifier &&
- (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
- Diag(DepModifier->getExprLoc(),
- diag::err_omp_depend_sink_source_with_modifier);
- return nullptr;
- }
- if (DepModifier &&
- !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
- Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
+namespace {
+// Utility struct that gathers the related info for doacross clause.
+struct DoacrossDataInfoTy {
+ // The list of expressions.
+ SmallVector<Expr *, 8> Vars;
+ // The OperatorOffset for doacross loop.
+ DSAStackTy::OperatorOffsetTy OpsOffs;
+ // The depended loop count.
+ llvm::APSInt TotalDepCount;
+};
+} // namespace
+static DoacrossDataInfoTy
+ProcessOpenMPDoacrossClauseCommon(Sema &SemaRef, bool IsSource,
+ ArrayRef<Expr *> VarList, DSAStackTy *Stack,
+ SourceLocation EndLoc) {
SmallVector<Expr *, 8> Vars;
DSAStackTy::OperatorOffsetTy OpsOffs;
llvm::APSInt DepCounter(/*BitWidth=*/32);
llvm::APSInt TotalDepCount(/*BitWidth=*/32);
- if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
- if (const Expr *OrderedCountExpr =
- DSAStack->getParentOrderedRegionParam().first) {
- TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(Context);
- TotalDepCount.setIsUnsigned(/*Val=*/true);
- }
+
+ if (const Expr *OrderedCountExpr =
+ Stack->getParentOrderedRegionParam().first) {
+ TotalDepCount = OrderedCountExpr->EvaluateKnownConstInt(SemaRef.Context);
+ TotalDepCount.setIsUnsigned(/*Val=*/true);
}
+
for (Expr *RefExpr : VarList) {
- assert(RefExpr && "NULL expr in OpenMP shared clause.");
+ assert(RefExpr && "NULL expr in OpenMP doacross clause.");
if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
// It will be analyzed later.
Vars.push_back(RefExpr);
@@ -20598,10 +20600,10 @@ Sema::ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data,
SourceLocation ELoc = RefExpr->getExprLoc();
Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
- if (DepKind == OMPC_DEPEND_sink) {
- if (DSAStack->getParentOrderedRegionParam().first &&
+ if (!IsSource) {
+ if (Stack->getParentOrderedRegionParam().first &&
DepCounter >= TotalDepCount) {
- Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
+ SemaRef.Diag(ELoc, diag::err_omp_depend_sink_unexpected_expr);
continue;
}
++DepCounter;
@@ -20613,7 +20615,7 @@ Sema::ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data,
// 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.
- if (CurContext->isDependentContext()) {
+ if (SemaRef.CurContext->isDependentContext()) {
// It will be analyzed later.
Vars.push_back(RefExpr);
continue;
@@ -20644,7 +20646,7 @@ Sema::ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data,
}
SourceLocation ELoc;
SourceRange ERange;
- auto Res = getPrivateItem(*this, LHS, ELoc, ERange);
+ auto Res = getPrivateItem(SemaRef, LHS, ELoc, ERange);
if (Res.second) {
// It will be analyzed later.
Vars.push_back(RefExpr);
@@ -20654,129 +20656,213 @@ Sema::ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data,
continue;
if (OOK != OO_Plus && OOK != OO_Minus && (RHS || OOK != OO_None)) {
- Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
+ SemaRef.Diag(OOLoc, diag::err_omp_depend_sink_expected_plus_minus);
continue;
}
if (RHS) {
- ExprResult RHSRes = VerifyPositiveIntegerConstantInClause(
+ ExprResult RHSRes = SemaRef.VerifyPositiveIntegerConstantInClause(
RHS, OMPC_depend, /*StrictlyPositive=*/false);
if (RHSRes.isInvalid())
continue;
}
- if (!CurContext->isDependentContext() &&
- DSAStack->getParentOrderedRegionParam().first &&
- DepCounter != DSAStack->isParentLoopControlVariable(D).first) {
+ if (!SemaRef.CurContext->isDependentContext() &&
+ Stack->getParentOrderedRegionParam().first &&
+ DepCounter != Stack->isParentLoopControlVariable(D).first) {
const ValueDecl *VD =
- DSAStack->getParentLoopControlVariable(DepCounter.getZExtValue());
+ Stack->getParentLoopControlVariable(DepCounter.getZExtValue());
if (VD)
- Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
+ SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
<< 1 << VD;
else
- Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration) << 0;
+ SemaRef.Diag(ELoc, diag::err_omp_depend_sink_expected_loop_iteration)
+ << 0;
continue;
}
OpsOffs.emplace_back(RHS, OOK);
- } else {
- bool OMPDependTFound = LangOpts.OpenMP >= 50;
- if (OMPDependTFound)
- OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStack,
- DepKind == OMPC_DEPEND_depobj);
- if (DepKind == OMPC_DEPEND_depobj) {
- // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
- // List items used in depend clauses with the depobj dependence type
- // must be expressions of the omp_depend_t type.
- if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
- !RefExpr->isInstantiationDependent() &&
- !RefExpr->containsUnexpandedParameterPack() &&
- (OMPDependTFound &&
- !Context.hasSameUnqualifiedType(DSAStack->getOMPDependT(),
- RefExpr->getType()))) {
- Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
- << 0 << RefExpr->getType() << RefExpr->getSourceRange();
- continue;
- }
- if (!RefExpr->isLValue()) {
- Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
- << 1 << RefExpr->getType() << RefExpr->getSourceRange();
- continue;
- }
- } else {
- // OpenMP 5.0 [2.17.11, Restrictions]
- // List items used in depend clauses cannot be zero-length array
- // sections.
- QualType ExprTy = RefExpr->getType().getNonReferenceType();
- const auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr);
- if (OASE) {
- QualType BaseType =
- OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
- if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
- ExprTy = ATy->getElementType();
- else
- ExprTy = BaseType->getPointeeType();
- ExprTy = ExprTy.getNonReferenceType();
- const Expr *Length = OASE->getLength();
- Expr::EvalResult Result;
- if (Length && !Length->isValueDependent() &&
- Length->EvaluateAsInt(Result, Context) &&
- Result.Val.getInt().isZero()) {
- Diag(ELoc,
- diag::err_omp_depend_zero_length_array_section_not_allowed)
- << SimpleExpr->getSourceRange();
+ }
+ Vars.push_back(RefExpr->IgnoreParenImpCasts());
+ }
+ if (!SemaRef.CurContext->isDependentContext() && !IsSource &&
+ TotalDepCount > VarList.size() &&
+ Stack->getParentOrderedRegionParam().first &&
+ Stack->getParentLoopControlVariable(VarList.size() + 1)) {
+ SemaRef.Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
+ << 1 << Stack->getParentLoopControlVariable(VarList.size() + 1);
+ }
+ return {Vars, OpsOffs, TotalDepCount};
+}
+
+OMPClause *
+Sema::ActOnOpenMPDependClause(const OMPDependClause::DependDataTy &Data,
+ Expr *DepModifier, ArrayRef<Expr *> VarList,
+ SourceLocation StartLoc, SourceLocation LParenLoc,
+ SourceLocation EndLoc) {
+ OpenMPDependClauseKind DepKind = Data.DepKind;
+ SourceLocation DepLoc = Data.DepLoc;
+ if (DSAStack->getCurrentDirective() == OMPD_ordered &&
+ DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink) {
+ Diag(DepLoc, diag::err_omp_unexpected_clause_value)
+ << "'source' or 'sink'" << getOpenMPClauseName(OMPC_depend);
+ return nullptr;
+ }
+ if (DSAStack->getCurrentDirective() == OMPD_taskwait &&
+ DepKind == OMPC_DEPEND_mutexinoutset) {
+ Diag(DepLoc, diag::err_omp_taskwait_depend_mutexinoutset_not_allowed);
+ return nullptr;
+ }
+ if ((DSAStack->getCurrentDirective() != OMPD_ordered ||
+ DSAStack->getCurrentDirective() == OMPD_depobj) &&
+ (DepKind == OMPC_DEPEND_unknown || DepKind == OMPC_DEPEND_source ||
+ DepKind == OMPC_DEPEND_sink ||
+ ((LangOpts.OpenMP < 50 ||
+ DSAStack->getCurrentDirective() == OMPD_depobj) &&
+ DepKind == OMPC_DEPEND_depobj))) {
+ SmallVector<unsigned, 6> Except = {OMPC_DEPEND_source, OMPC_DEPEND_sink,
+ OMPC_DEPEND_outallmemory,
+ OMPC_DEPEND_inoutallmemory};
+ if (LangOpts.OpenMP < 50 || DSAStack->getCurrentDirective() == OMPD_depobj)
+ Except.push_back(OMPC_DEPEND_depobj);
+ if (LangOpts.OpenMP < 51)
+ Except.push_back(OMPC_DEPEND_inoutset);
+ std::string Expected = (LangOpts.OpenMP >= 50 && !DepModifier)
+ ? "depend modifier(iterator) or "
+ : "";
+ Diag(DepLoc, diag::err_omp_unexpected_clause_value)
+ << Expected + getListOfPossibleValues(OMPC_depend, /*First=*/0,
+ /*Last=*/OMPC_DEPEND_unknown,
+ Except)
+ << getOpenMPClauseName(OMPC_depend);
+ return nullptr;
+ }
+ if (DepModifier &&
+ (DepKind == OMPC_DEPEND_source || DepKind == OMPC_DEPEND_sink)) {
+ Diag(DepModifier->getExprLoc(),
+ diag::err_omp_depend_sink_source_with_modifier);
+ return nullptr;
+ }
+ if (DepModifier &&
+ !DepModifier->getType()->isSpecificBuiltinType(BuiltinType::OMPIterator))
+ Diag(DepModifier->getExprLoc(), diag::err_omp_depend_modifier_not_iterator);
+
+ SmallVector<Expr *, 8> Vars;
+ DSAStackTy::OperatorOffsetTy OpsOffs;
+ llvm::APSInt TotalDepCount(/*BitWidth=*/32);
+
+ if (DepKind == OMPC_DEPEND_sink || DepKind == OMPC_DEPEND_source) {
+ DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
+ *this, DepKind == OMPC_DEPEND_source, VarList, DSAStack, EndLoc);
+ Vars = VarOffset.Vars;
+ OpsOffs = VarOffset.OpsOffs;
+ TotalDepCount = VarOffset.TotalDepCount;
+ } else {
+ for (Expr *RefExpr : VarList) {
+ assert(RefExpr && "NULL expr in OpenMP shared clause.");
+ if (isa<DependentScopeDeclRefExpr>(RefExpr)) {
+ // It will be analyzed later.
+ Vars.push_back(RefExpr);
+ continue;
+ }
+
+ SourceLocation ELoc = RefExpr->getExprLoc();
+ Expr *SimpleExpr = RefExpr->IgnoreParenCasts();
+ if (DepKind != OMPC_DEPEND_sink && DepKind != OMPC_DEPEND_source) {
+ bool OMPDependTFound = LangOpts.OpenMP >= 50;
+ if (OMPDependTFound)
+ OMPDependTFound = findOMPDependT(*this, StartLoc, DSAStack,
+ DepKind == OMPC_DEPEND_depobj);
+ if (DepKind == OMPC_DEPEND_depobj) {
+ // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
+ // List items used in depend clauses with the depobj dependence type
+ // must be expressions of the omp_depend_t type.
+ if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
+ !RefExpr->isInstantiationDependent() &&
+ !RefExpr->containsUnexpandedParameterPack() &&
+ (OMPDependTFound &&
+ !Context.hasSameUnqualifiedType(DSAStack->getOMPDependT(),
+ RefExpr->getType()))) {
+ Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
+ << 0 << RefExpr->getType() << RefExpr->getSourceRange();
continue;
}
- }
+ if (!RefExpr->isLValue()) {
+ Diag(ELoc, diag::err_omp_expected_omp_depend_t_lvalue)
+ << 1 << RefExpr->getType() << RefExpr->getSourceRange();
+ continue;
+ }
+ } else {
+ // OpenMP 5.0 [2.17.11, Restrictions]
+ // List items used in depend clauses cannot be zero-length array
+ // sections.
+ QualType ExprTy = RefExpr->getType().getNonReferenceType();
+ const auto *OASE = dyn_cast<OMPArraySectionExpr>(SimpleExpr);
+ if (OASE) {
+ QualType BaseType =
+ OMPArraySectionExpr::getBaseOriginalType(OASE->getBase());
+ if (const auto *ATy = BaseType->getAsArrayTypeUnsafe())
+ ExprTy = ATy->getElementType();
+ else
+ ExprTy = BaseType->getPointeeType();
+ ExprTy = ExprTy.getNonReferenceType();
+ const Expr *Length = OASE->getLength();
+ Expr::EvalResult Result;
+ if (Length && !Length->isValueDependent() &&
+ Length->EvaluateAsInt(Result, Context) &&
+ Result.Val.getInt().isZero()) {
+ Diag(ELoc,
+ diag::err_omp_depend_zero_length_array_section_not_allowed)
+ << SimpleExpr->getSourceRange();
+ continue;
+ }
+ }
- // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
- // List items used in depend clauses with the in, out, inout,
- // inoutset, or mutexinoutset dependence types cannot be
- // expressions of the omp_depend_t type.
- if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
- !RefExpr->isInstantiationDependent() &&
- !RefExpr->containsUnexpandedParameterPack() &&
- (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
- (OMPDependTFound &&
- DSAStack->getOMPDependT().getTypePtr() == ExprTy.getTypePtr()))) {
- Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
- << (LangOpts.OpenMP >= 50 ? 1 : 0)
- << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
- continue;
- }
+ // OpenMP 5.0, 2.17.11 depend Clause, Restrictions, C/C++
+ // List items used in depend clauses with the in, out, inout,
+ // inoutset, or mutexinoutset dependence types cannot be
+ // expressions of the omp_depend_t type.
+ if (!RefExpr->isValueDependent() && !RefExpr->isTypeDependent() &&
+ !RefExpr->isInstantiationDependent() &&
+ !RefExpr->containsUnexpandedParameterPack() &&
+ (!RefExpr->IgnoreParenImpCasts()->isLValue() ||
+ (OMPDependTFound && DSAStack->getOMPDependT().getTypePtr() ==
+ ExprTy.getTypePtr()))) {
+ Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
+ << (LangOpts.OpenMP >= 50 ? 1 : 0)
+ << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
+ continue;
+ }
- auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
- if (ASE && !ASE->getBase()->isTypeDependent() &&
- !ASE->getBase()->getType().getNonReferenceType()->isPointerType() &&
- !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
- Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
- << (LangOpts.OpenMP >= 50 ? 1 : 0)
- << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
- continue;
- }
+ auto *ASE = dyn_cast<ArraySubscriptExpr>(SimpleExpr);
+ if (ASE && !ASE->getBase()->isTypeDependent() &&
+ !ASE->getBase()
+ ->getType()
+ .getNonReferenceType()
+ ->isPointerType() &&
+ !ASE->getBase()->getType().getNonReferenceType()->isArrayType()) {
+ Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
+ << (LangOpts.OpenMP >= 50 ? 1 : 0)
+ << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
+ continue;
+ }
- ExprResult Res;
- {
- Sema::TentativeAnalysisScope Trap(*this);
- Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
- RefExpr->IgnoreParenImpCasts());
- }
- if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
- !isa<OMPArrayShapingExpr>(SimpleExpr)) {
- Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
- << (LangOpts.OpenMP >= 50 ? 1 : 0)
- << (LangOpts.OpenMP >= 50 ? 1 : 0) << RefExpr->getSourceRange();
- continue;
+ ExprResult Res;
+ {
+ Sema::TentativeAnalysisScope Trap(*this);
+ Res = CreateBuiltinUnaryOp(ELoc, UO_AddrOf,
+ RefExpr->IgnoreParenImpCasts());
+ }
+ if (!Res.isUsable() && !isa<OMPArraySectionExpr>(SimpleExpr) &&
+ !isa<OMPArrayShapingExpr>(SimpleExpr)) {
+ Diag(ELoc, diag::err_omp_expected_addressable_lvalue_or_array_item)
+ << (LangOpts.OpenMP >= 50 ? 1 : 0)
+ << (LangOpts.OpenMP >= 50 ? 1 : 0) << 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().first &&
- DSAStack->getParentLoopControlVariable(VarList.size() + 1)) {
- Diag(EndLoc, diag::err_omp_depend_sink_expected_loop_iteration)
- << 1 << DSAStack->getParentLoopControlVariable(VarList.size() + 1);
- }
if (DepKind != OMPC_DEPEND_source && DepKind != OMPC_DEPEND_sink &&
DepKind != OMPC_DEPEND_outallmemory &&
DepKind != OMPC_DEPEND_inoutallmemory && Vars.empty())
@@ -23947,3 +24033,31 @@ OMPClause *Sema::ActOnOpenMPXDynCGroupMemClause(Expr *Size,
return new (Context) OMPXDynCGroupMemClause(
ValExpr, HelperValStmt, CaptureRegion, StartLoc, LParenLoc, EndLoc);
}
+
+OMPClause *Sema::ActOnOpenMPDoacrossClause(
+ OpenMPDoacrossClauseModifier DepType, SourceLocation DepLoc,
+ SourceLocation ColonLoc, ArrayRef<Expr *> VarList, SourceLocation StartLoc,
+ SourceLocation LParenLoc, SourceLocation EndLoc) {
+
+ if (DSAStack->getCurrentDirective() == OMPD_ordered &&
+ DepType != OMPC_DOACROSS_source && DepType != OMPC_DOACROSS_sink) {
+ Diag(DepLoc, diag::err_omp_unexpected_clause_value)
+ << "'source' or 'sink'" << getOpenMPClauseName(OMPC_doacross);
+ return nullptr;
+ }
+
+ SmallVector<Expr *, 8> Vars;
+ DSAStackTy::OperatorOffsetTy OpsOffs;
+ llvm::APSInt TotalDepCount(/*BitWidth=*/32);
+ DoacrossDataInfoTy VarOffset = ProcessOpenMPDoacrossClauseCommon(
+ *this, DepType == OMPC_DOACROSS_source, VarList, DSAStack, EndLoc);
+ Vars = VarOffset.Vars;
+ OpsOffs = VarOffset.OpsOffs;
+ TotalDepCount = VarOffset.TotalDepCount;
+ auto *C = OMPDoacrossClause::Create(Context, StartLoc, LParenLoc, EndLoc,
+ DepType, DepLoc, ColonLoc, Vars,
+ TotalDepCount.getZExtValue());
+ if (DSAStack->isParentOrderedRegion())
+ DSAStack->addDoacrossDependClause(C, OpsOffs);
+ return C;
+}