bool TestIsStrictOp = false;
/// This flag is true when step is subtracted on each iteration.
bool SubtractStep = false;
+ /// The outer loop counter this loop depends on (if any).
+ const ValueDecl *DepDecl = nullptr;
+ /// Contains number of loop (starts from 1) on which loop counter init
+ /// expression of this loop depends on.
+ Optional<unsigned> InitDependOnLC;
+ /// Contains number of loop (starts from 1) on which loop counter condition
+ /// expression of this loop depends on.
+ Optional<unsigned> CondDependOnLC;
/// Checks if the provide statement depends on the loop counter.
- bool doesDependOnLoopCounter(const Stmt *S, bool IsInitializer) const;
+ Optional<unsigned> doesDependOnLoopCounter(const Stmt *S, bool IsInitializer);
public:
OpenMPIterationSpaceChecker(Sema &SemaRef, DSAStackTy &Stack,
NewLB = CE->getArg(0)->IgnoreParenImpCasts();
LB = NewLB;
if (EmitDiags)
- (void)doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
+ InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
return false;
}
TestIsStrictOp = StrictOp;
ConditionSrcRange = SR;
ConditionLoc = SL;
- (void)doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
+ CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
return false;
}
DSAStackTy &Stack;
const ValueDecl *CurLCDecl = nullptr;
const ValueDecl *DepDecl = nullptr;
+ const ValueDecl *PrevDepDecl = nullptr;
bool IsInitializer = true;
+ unsigned BaseLoopId = 0;
+ bool checkDecl(const Expr *E, const ValueDecl *VD) {
+ if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
+ SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
+ << (IsInitializer ? 0 : 1);
+ return false;
+ }
+ const auto &&Data = Stack.isLoopControlVariable(VD);
+ // OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
+ // The type of the loop iterator on which we depend may not have a random
+ // access iterator type.
+ if (Data.first && VD->getType()->isRecordType()) {
+ SmallString<128> Name;
+ llvm::raw_svector_ostream OS(Name);
+ VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
+ /*Qualified=*/true);
+ SemaRef.Diag(E->getExprLoc(),
+ diag::err_omp_wrong_dependency_iterator_type)
+ << OS.str();
+ SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
+ return false;
+ }
+ if (Data.first &&
+ (DepDecl || (PrevDepDecl &&
+ getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
+ if (!DepDecl && PrevDepDecl)
+ DepDecl = PrevDepDecl;
+ SmallString<128> Name;
+ llvm::raw_svector_ostream OS(Name);
+ DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
+ /*Qualified=*/true);
+ SemaRef.Diag(E->getExprLoc(),
+ diag::err_omp_invariant_or_linear_dependency)
+ << OS.str();
+ return false;
+ }
+ if (Data.first) {
+ DepDecl = VD;
+ BaseLoopId = Data.first;
+ }
+ return Data.first;
+ }
public:
bool VisitDeclRefExpr(const DeclRefExpr *E) {
const ValueDecl *VD = E->getDecl();
- if (isa<VarDecl>(VD)) {
- if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
- SemaRef.Diag(E->getExprLoc(),
- diag::err_omp_stmt_depends_on_loop_counter)
- << (IsInitializer ? 0 : 1);
- return false;
- }
- const auto &&Data = Stack.isLoopControlVariable(VD);
- if (DepDecl && Data.first) {
- SmallString<128> Name;
- llvm::raw_svector_ostream OS(Name);
- DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
- /*Qualified=*/true);
- SemaRef.Diag(E->getExprLoc(),
- diag::err_omp_invariant_or_linear_dependancy)
- << OS.str();
- return false;
- }
- if (Data.first)
- DepDecl = VD;
- return Data.first;
- }
+ if (isa<VarDecl>(VD))
+ return checkDecl(E, VD);
return false;
}
bool VisitMemberExpr(const MemberExpr *E) {
if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
const ValueDecl *VD = E->getMemberDecl();
- if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
- SemaRef.Diag(E->getExprLoc(),
- diag::err_omp_stmt_depends_on_loop_counter)
- << (IsInitializer ? 0 : 1);
- return false;
- }
- const auto &&Data = Stack.isLoopControlVariable(VD);
- if (DepDecl && Data.first) {
- SmallString<128> Name;
- llvm::raw_svector_ostream OS(Name);
- DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
- /*Qualified=*/true);
- SemaRef.Diag(E->getExprLoc(),
- diag::err_omp_invariant_or_linear_dependancy)
- << OS.str();
- return false;
- }
- if (Data.first)
- DepDecl = VD;
- return Data.first;
+ return checkDecl(E, VD);
}
return false;
}
return Res;
}
explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
- const ValueDecl *CurLCDecl, bool IsInitializer)
+ const ValueDecl *CurLCDecl, bool IsInitializer,
+ const ValueDecl *PrevDepDecl = nullptr)
: SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
- IsInitializer(IsInitializer) {}
+ PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer) {}
+ unsigned getBaseLoopId() const {
+ assert(CurLCDecl && "Expected loop dependency.");
+ return BaseLoopId;
+ }
+ const ValueDecl *getDepDecl() const {
+ assert(CurLCDecl && "Expected loop dependency.");
+ return DepDecl;
+ }
};
} // namespace
-bool OpenMPIterationSpaceChecker::doesDependOnLoopCounter(
- const Stmt *S, bool IsInitializer) const {
+Optional<unsigned>
+OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
+ bool IsInitializer) {
// Check for the non-rectangular loops.
- LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer);
- return LoopStmtChecker.Visit(S);
+ LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
+ DepDecl);
+ if (LoopStmtChecker.Visit(S)) {
+ DepDecl = LoopStmtChecker.getDepDecl();
+ return LoopStmtChecker.getBaseLoopId();
+ }
+ return llvm::None;
}
bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
for (kk = ii * 10 + 25; kk < ii / ii - 23; kk += 1)
;
+// expected-error@+4 {{expected loop invariant expression or '<invariant1> * ii + <invariant2>' kind of expression}}
+#pragma omp for collapse(3)
+ for (ii = 10 + 25; ii < 1000; ii += 1)
+ for (jj = 10 + 25; jj < 1000; jj += 1)
+ for (kk = ii * 10 + 25; kk < jj - 23; kk += 1)
+ ;
+
#pragma omp parallel
// expected-note@+2 {{defined as firstprivate}}
// expected-error@+2 {{loop iteration variable in the associated loop of 'omp for' directive may not be firstprivate, predetermined as private}}
for (Iter1 I; I < end1; ++I) {
}
GoodIter1 I1, E1;
+// expected-error@+4 {{expected an integer or a pointer type of the outer loop counter 'I' for non-rectangular nests}}
+// expected-error@+4 {{expected an integer or a pointer type of the outer loop counter 'I' for non-rectangular nests}}
+#pragma omp for collapse(3)
+ for (GoodIter1 I = I1; I < E1; I++) // expected-note 2 {{'I' declared here}}
+ for (int i = (I - I1) * 10 + 25; i < 23; i += 1)
+ for (int j = 10 + 25; j < 23 + (I - E1); j += 1)
+ ;
+
#pragma omp for
for (GoodIter1 I = I1; I < E1; I++)
;
template <typename IT, int ST>
class TC {
- int ii, iii;
+ int ii, iii, kk;
public:
int dotest_lt(IT begin, IT end) {
#pragma omp parallel
for (iii = ii * 10 + 25; iii < ii / ii - 23; iii += 1)
;
+#pragma omp parallel
+// expected-error@+6 2 {{expected loop invariant expression or '<invariant1> * ii + <invariant2>' kind of expression}}
+// expected-error@+5 {{expected loop invariant expression or '<invariant1> * TC::ii + <invariant2>' kind of expression}}
+// expected-error@+5 2 {{expected loop invariant expression or '<invariant1> * ii + <invariant2>' kind of expression}}
+// expected-error@+4 {{expected loop invariant expression or '<invariant1> * TC::ii + <invariant2>' kind of expression}}
+#pragma omp for collapse(3)
+ for (ii = 10 + 25; ii < 1000; ii += 1)
+ for (iii = ii * 10 + 25; iii < ii / ii - 23; iii += 1)
+ for (kk = ii * 10 + 25; kk < iii - 23; kk += 1)
+ ;
+
#pragma omp parallel
// expected-note@+3 {{loop step is expected to be positive due to this condition}}
// expected-error@+2 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}