Skip to content

Commit 5ddc6d1

Browse files
committed
[OPENMP]Added check for non-random access types for the dependent loop
counters. According to the OpenMP 5.0, For any associated loop where the b or lb expression is not loop invariant with respect to the outermost loop, the var-outer that appears in the expression may not have a random access iterator type. llvm-svn: 359340
1 parent 93c05f0 commit 5ddc6d1

File tree

3 files changed

+108
-53
lines changed

3 files changed

+108
-53
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9177,8 +9177,10 @@ def err_omp_expected_private_copy_for_allocate : Error<
91779177
"the referenced item is not found in any private clause on the same directive">;
91789178
def err_omp_stmt_depends_on_loop_counter : Error<
91799179
"the loop %select{initializer|condition}0 expression depends on the current loop control variable">;
9180-
def err_omp_invariant_or_linear_dependancy : Error<
9180+
def err_omp_invariant_or_linear_dependency : Error<
91819181
"expected loop invariant expression or '<invariant1> * %0 + <invariant2>' kind of expression">;
9182+
def err_omp_wrong_dependency_iterator_type : Error<
9183+
"expected an integer or a pointer type of the outer loop counter '%0' for non-rectangular nests">;
91829184
} // end of OpenMP category
91839185

91849186
let CategoryName = "Related Result Type Issue" in {

clang/lib/Sema/SemaOpenMP.cpp

Lines changed: 78 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -4520,8 +4520,16 @@ class OpenMPIterationSpaceChecker {
45204520
bool TestIsStrictOp = false;
45214521
/// This flag is true when step is subtracted on each iteration.
45224522
bool SubtractStep = false;
4523+
/// The outer loop counter this loop depends on (if any).
4524+
const ValueDecl *DepDecl = nullptr;
4525+
/// Contains number of loop (starts from 1) on which loop counter init
4526+
/// expression of this loop depends on.
4527+
Optional<unsigned> InitDependOnLC;
4528+
/// Contains number of loop (starts from 1) on which loop counter condition
4529+
/// expression of this loop depends on.
4530+
Optional<unsigned> CondDependOnLC;
45234531
/// Checks if the provide statement depends on the loop counter.
4524-
bool doesDependOnLoopCounter(const Stmt *S, bool IsInitializer) const;
4532+
Optional<unsigned> doesDependOnLoopCounter(const Stmt *S, bool IsInitializer);
45254533

45264534
public:
45274535
OpenMPIterationSpaceChecker(Sema &SemaRef, DSAStackTy &Stack,
@@ -4622,7 +4630,7 @@ bool OpenMPIterationSpaceChecker::setLCDeclAndLB(ValueDecl *NewLCDecl,
46224630
NewLB = CE->getArg(0)->IgnoreParenImpCasts();
46234631
LB = NewLB;
46244632
if (EmitDiags)
4625-
(void)doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
4633+
InitDependOnLC = doesDependOnLoopCounter(LB, /*IsInitializer=*/true);
46264634
return false;
46274635
}
46284636

@@ -4641,7 +4649,7 @@ bool OpenMPIterationSpaceChecker::setUB(Expr *NewUB,
46414649
TestIsStrictOp = StrictOp;
46424650
ConditionSrcRange = SR;
46434651
ConditionLoc = SL;
4644-
(void)doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
4652+
CondDependOnLC = doesDependOnLoopCounter(UB, /*IsInitializer=*/false);
46454653
return false;
46464654
}
46474655

@@ -4716,58 +4724,62 @@ class LoopCounterRefChecker final
47164724
DSAStackTy &Stack;
47174725
const ValueDecl *CurLCDecl = nullptr;
47184726
const ValueDecl *DepDecl = nullptr;
4727+
const ValueDecl *PrevDepDecl = nullptr;
47194728
bool IsInitializer = true;
4729+
unsigned BaseLoopId = 0;
4730+
bool checkDecl(const Expr *E, const ValueDecl *VD) {
4731+
if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
4732+
SemaRef.Diag(E->getExprLoc(), diag::err_omp_stmt_depends_on_loop_counter)
4733+
<< (IsInitializer ? 0 : 1);
4734+
return false;
4735+
}
4736+
const auto &&Data = Stack.isLoopControlVariable(VD);
4737+
// OpenMP, 2.9.1 Canonical Loop Form, Restrictions.
4738+
// The type of the loop iterator on which we depend may not have a random
4739+
// access iterator type.
4740+
if (Data.first && VD->getType()->isRecordType()) {
4741+
SmallString<128> Name;
4742+
llvm::raw_svector_ostream OS(Name);
4743+
VD->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
4744+
/*Qualified=*/true);
4745+
SemaRef.Diag(E->getExprLoc(),
4746+
diag::err_omp_wrong_dependency_iterator_type)
4747+
<< OS.str();
4748+
SemaRef.Diag(VD->getLocation(), diag::note_previous_decl) << VD;
4749+
return false;
4750+
}
4751+
if (Data.first &&
4752+
(DepDecl || (PrevDepDecl &&
4753+
getCanonicalDecl(VD) != getCanonicalDecl(PrevDepDecl)))) {
4754+
if (!DepDecl && PrevDepDecl)
4755+
DepDecl = PrevDepDecl;
4756+
SmallString<128> Name;
4757+
llvm::raw_svector_ostream OS(Name);
4758+
DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
4759+
/*Qualified=*/true);
4760+
SemaRef.Diag(E->getExprLoc(),
4761+
diag::err_omp_invariant_or_linear_dependency)
4762+
<< OS.str();
4763+
return false;
4764+
}
4765+
if (Data.first) {
4766+
DepDecl = VD;
4767+
BaseLoopId = Data.first;
4768+
}
4769+
return Data.first;
4770+
}
47204771

47214772
public:
47224773
bool VisitDeclRefExpr(const DeclRefExpr *E) {
47234774
const ValueDecl *VD = E->getDecl();
4724-
if (isa<VarDecl>(VD)) {
4725-
if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
4726-
SemaRef.Diag(E->getExprLoc(),
4727-
diag::err_omp_stmt_depends_on_loop_counter)
4728-
<< (IsInitializer ? 0 : 1);
4729-
return false;
4730-
}
4731-
const auto &&Data = Stack.isLoopControlVariable(VD);
4732-
if (DepDecl && Data.first) {
4733-
SmallString<128> Name;
4734-
llvm::raw_svector_ostream OS(Name);
4735-
DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
4736-
/*Qualified=*/true);
4737-
SemaRef.Diag(E->getExprLoc(),
4738-
diag::err_omp_invariant_or_linear_dependancy)
4739-
<< OS.str();
4740-
return false;
4741-
}
4742-
if (Data.first)
4743-
DepDecl = VD;
4744-
return Data.first;
4745-
}
4775+
if (isa<VarDecl>(VD))
4776+
return checkDecl(E, VD);
47464777
return false;
47474778
}
47484779
bool VisitMemberExpr(const MemberExpr *E) {
47494780
if (isa<CXXThisExpr>(E->getBase()->IgnoreParens())) {
47504781
const ValueDecl *VD = E->getMemberDecl();
4751-
if (getCanonicalDecl(VD) == getCanonicalDecl(CurLCDecl)) {
4752-
SemaRef.Diag(E->getExprLoc(),
4753-
diag::err_omp_stmt_depends_on_loop_counter)
4754-
<< (IsInitializer ? 0 : 1);
4755-
return false;
4756-
}
4757-
const auto &&Data = Stack.isLoopControlVariable(VD);
4758-
if (DepDecl && Data.first) {
4759-
SmallString<128> Name;
4760-
llvm::raw_svector_ostream OS(Name);
4761-
DepDecl->getNameForDiagnostic(OS, SemaRef.getPrintingPolicy(),
4762-
/*Qualified=*/true);
4763-
SemaRef.Diag(E->getExprLoc(),
4764-
diag::err_omp_invariant_or_linear_dependancy)
4765-
<< OS.str();
4766-
return false;
4767-
}
4768-
if (Data.first)
4769-
DepDecl = VD;
4770-
return Data.first;
4782+
return checkDecl(E, VD);
47714783
}
47724784
return false;
47734785
}
@@ -4778,17 +4790,32 @@ class LoopCounterRefChecker final
47784790
return Res;
47794791
}
47804792
explicit LoopCounterRefChecker(Sema &SemaRef, DSAStackTy &Stack,
4781-
const ValueDecl *CurLCDecl, bool IsInitializer)
4793+
const ValueDecl *CurLCDecl, bool IsInitializer,
4794+
const ValueDecl *PrevDepDecl = nullptr)
47824795
: SemaRef(SemaRef), Stack(Stack), CurLCDecl(CurLCDecl),
4783-
IsInitializer(IsInitializer) {}
4796+
PrevDepDecl(PrevDepDecl), IsInitializer(IsInitializer) {}
4797+
unsigned getBaseLoopId() const {
4798+
assert(CurLCDecl && "Expected loop dependency.");
4799+
return BaseLoopId;
4800+
}
4801+
const ValueDecl *getDepDecl() const {
4802+
assert(CurLCDecl && "Expected loop dependency.");
4803+
return DepDecl;
4804+
}
47844805
};
47854806
} // namespace
47864807

4787-
bool OpenMPIterationSpaceChecker::doesDependOnLoopCounter(
4788-
const Stmt *S, bool IsInitializer) const {
4808+
Optional<unsigned>
4809+
OpenMPIterationSpaceChecker::doesDependOnLoopCounter(const Stmt *S,
4810+
bool IsInitializer) {
47894811
// Check for the non-rectangular loops.
4790-
LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer);
4791-
return LoopStmtChecker.Visit(S);
4812+
LoopCounterRefChecker LoopStmtChecker(SemaRef, Stack, LCDecl, IsInitializer,
4813+
DepDecl);
4814+
if (LoopStmtChecker.Visit(S)) {
4815+
DepDecl = LoopStmtChecker.getDepDecl();
4816+
return LoopStmtChecker.getBaseLoopId();
4817+
}
4818+
return llvm::None;
47924819
}
47934820

47944821
bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {

clang/test/OpenMP/for_loop_messages.cpp

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,6 +299,13 @@ int test_iteration_spaces() {
299299
for (kk = ii * 10 + 25; kk < ii / ii - 23; kk += 1)
300300
;
301301

302+
// expected-error@+4 {{expected loop invariant expression or '<invariant1> * ii + <invariant2>' kind of expression}}
303+
#pragma omp for collapse(3)
304+
for (ii = 10 + 25; ii < 1000; ii += 1)
305+
for (jj = 10 + 25; jj < 1000; jj += 1)
306+
for (kk = ii * 10 + 25; kk < jj - 23; kk += 1)
307+
;
308+
302309
#pragma omp parallel
303310
// expected-note@+2 {{defined as firstprivate}}
304311
// expected-error@+2 {{loop iteration variable in the associated loop of 'omp for' directive may not be firstprivate, predetermined as private}}
@@ -601,6 +608,14 @@ int test_with_random_access_iterator() {
601608
for (Iter1 I; I < end1; ++I) {
602609
}
603610
GoodIter1 I1, E1;
611+
// expected-error@+4 {{expected an integer or a pointer type of the outer loop counter 'I' for non-rectangular nests}}
612+
// expected-error@+4 {{expected an integer or a pointer type of the outer loop counter 'I' for non-rectangular nests}}
613+
#pragma omp for collapse(3)
614+
for (GoodIter1 I = I1; I < E1; I++) // expected-note 2 {{'I' declared here}}
615+
for (int i = (I - I1) * 10 + 25; i < 23; i += 1)
616+
for (int j = 10 + 25; j < 23 + (I - E1); j += 1)
617+
;
618+
604619
#pragma omp for
605620
for (GoodIter1 I = I1; I < E1; I++)
606621
;
@@ -609,7 +624,7 @@ int test_with_random_access_iterator() {
609624

610625
template <typename IT, int ST>
611626
class TC {
612-
int ii, iii;
627+
int ii, iii, kk;
613628
public:
614629
int dotest_lt(IT begin, IT end) {
615630
#pragma omp parallel
@@ -627,6 +642,17 @@ class TC {
627642
for (iii = ii * 10 + 25; iii < ii / ii - 23; iii += 1)
628643
;
629644

645+
#pragma omp parallel
646+
// expected-error@+6 2 {{expected loop invariant expression or '<invariant1> * ii + <invariant2>' kind of expression}}
647+
// expected-error@+5 {{expected loop invariant expression or '<invariant1> * TC::ii + <invariant2>' kind of expression}}
648+
// expected-error@+5 2 {{expected loop invariant expression or '<invariant1> * ii + <invariant2>' kind of expression}}
649+
// expected-error@+4 {{expected loop invariant expression or '<invariant1> * TC::ii + <invariant2>' kind of expression}}
650+
#pragma omp for collapse(3)
651+
for (ii = 10 + 25; ii < 1000; ii += 1)
652+
for (iii = ii * 10 + 25; iii < ii / ii - 23; iii += 1)
653+
for (kk = ii * 10 + 25; kk < iii - 23; kk += 1)
654+
;
655+
630656
#pragma omp parallel
631657
// expected-note@+3 {{loop step is expected to be positive due to this condition}}
632658
// expected-error@+2 {{increment expression must cause 'I' to increase on each iteration of OpenMP for loop}}

0 commit comments

Comments
 (0)