21
21
#include "clang/AST/DeclCXX.h"
22
22
#include "clang/AST/DeclOpenMP.h"
23
23
#include "clang/AST/OpenMPClause.h"
24
+ #include "clang/AST/RecursiveASTVisitor.h"
24
25
#include "clang/AST/StmtCXX.h"
25
26
#include "clang/AST/StmtOpenMP.h"
26
27
#include "clang/AST/StmtVisitor.h"
@@ -7668,6 +7669,47 @@ struct LoopIterationSpace final {
7668
7669
Expr *FinalCondition = nullptr;
7669
7670
};
7670
7671
7672
+ class ForSubExprChecker : public RecursiveASTVisitor<ForSubExprChecker> {
7673
+ const llvm::SmallSet<Decl *, 4> *CollapsedLoopVarDecls;
7674
+ VarDecl *ForbiddenVar;
7675
+ SourceRange ErrLoc;
7676
+
7677
+ public:
7678
+ explicit ForSubExprChecker(
7679
+ const llvm::SmallSet<Decl *, 4> *CollapsedLoopVarDecls)
7680
+ : CollapsedLoopVarDecls(CollapsedLoopVarDecls), ForbiddenVar(nullptr) {}
7681
+
7682
+ bool shouldVisitImplicitCode() const { return true; }
7683
+
7684
+ bool VisitDeclRefExpr(DeclRefExpr *E) {
7685
+ ValueDecl *VD = E->getDecl();
7686
+ if (!isa<VarDecl, BindingDecl>(VD))
7687
+ return true;
7688
+ VarDecl *V = VD->getPotentiallyDecomposedVarDecl();
7689
+ if (V->getType()->isReferenceType()) {
7690
+ VarDecl *VD = V->getDefinition();
7691
+ if (VD->hasInit()) {
7692
+ Expr *I = VD->getInit();
7693
+ DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(I);
7694
+ if (!DRE)
7695
+ return true;
7696
+ V = DRE->getDecl()->getPotentiallyDecomposedVarDecl();
7697
+ }
7698
+ }
7699
+ Decl *Canon = V->getCanonicalDecl();
7700
+ if (CollapsedLoopVarDecls->contains(Canon)) {
7701
+ ForbiddenVar = V;
7702
+ ErrLoc = E->getSourceRange();
7703
+ return false;
7704
+ }
7705
+
7706
+ return true;
7707
+ }
7708
+
7709
+ VarDecl *getForbiddenVar() { return ForbiddenVar; }
7710
+ SourceRange &getErrRange() { return ErrLoc; }
7711
+ };
7712
+
7671
7713
/// Helper class for checking canonical form of the OpenMP loops and
7672
7714
/// extracting iteration space of each loop in the loop nest, that will be used
7673
7715
/// for IR generation.
@@ -7682,6 +7724,8 @@ class OpenMPIterationSpaceChecker {
7682
7724
SourceLocation DefaultLoc;
7683
7725
/// A location for diagnostics (when increment is not compatible).
7684
7726
SourceLocation ConditionLoc;
7727
+ /// The set of variables declared within the (to be collapsed) loop nest.
7728
+ const llvm::SmallSet<Decl *, 4> *CollapsedLoopVarDecls;
7685
7729
/// A source location for referring to loop init later.
7686
7730
SourceRange InitSrcRange;
7687
7731
/// A source location for referring to condition later.
@@ -7725,10 +7769,13 @@ class OpenMPIterationSpaceChecker {
7725
7769
Expr *Condition = nullptr;
7726
7770
7727
7771
public:
7728
- OpenMPIterationSpaceChecker(Sema &SemaRef, bool SupportsNonRectangular,
7729
- DSAStackTy &Stack, SourceLocation DefaultLoc)
7772
+ OpenMPIterationSpaceChecker(
7773
+ Sema &SemaRef, bool SupportsNonRectangular, DSAStackTy &Stack,
7774
+ SourceLocation DefaultLoc,
7775
+ const llvm::SmallSet<Decl *, 4> *CollapsedLoopDecls)
7730
7776
: SemaRef(SemaRef), SupportsNonRectangular(SupportsNonRectangular),
7731
- Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc) {}
7777
+ Stack(Stack), DefaultLoc(DefaultLoc), ConditionLoc(DefaultLoc),
7778
+ CollapsedLoopVarDecls(CollapsedLoopDecls) {}
7732
7779
/// Check init-expr for canonical loop form and save loop counter
7733
7780
/// variable - #Var and its initialization value - #LB.
7734
7781
bool checkAndSetInit(Stmt *S, bool EmitDiags = true);
@@ -8049,6 +8096,16 @@ bool OpenMPIterationSpaceChecker::checkAndSetInit(Stmt *S, bool EmitDiags) {
8049
8096
if (!ExprTemp->cleanupsHaveSideEffects())
8050
8097
S = ExprTemp->getSubExpr();
8051
8098
8099
+ if (CollapsedLoopVarDecls) {
8100
+ ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8101
+ if (!FSEC.TraverseStmt(S)) {
8102
+ SourceRange &Range = FSEC.getErrRange();
8103
+ SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8104
+ << Range.getEnd() << 0 << FSEC.getForbiddenVar();
8105
+ return true;
8106
+ }
8107
+ }
8108
+
8052
8109
InitSrcRange = S->getSourceRange();
8053
8110
if (Expr *E = dyn_cast<Expr>(S))
8054
8111
S = E->IgnoreParens();
@@ -8152,6 +8209,17 @@ bool OpenMPIterationSpaceChecker::checkAndSetCond(Expr *S) {
8152
8209
}
8153
8210
Condition = S;
8154
8211
S = getExprAsWritten(S);
8212
+
8213
+ if (CollapsedLoopVarDecls) {
8214
+ ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8215
+ if (!FSEC.TraverseStmt(S)) {
8216
+ SourceRange &Range = FSEC.getErrRange();
8217
+ SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8218
+ << Range.getEnd() << 1 << FSEC.getForbiddenVar();
8219
+ return true;
8220
+ }
8221
+ }
8222
+
8155
8223
SourceLocation CondLoc = S->getBeginLoc();
8156
8224
auto &&CheckAndSetCond =
8157
8225
[this, IneqCondIsCanonical](BinaryOperatorKind Opcode, const Expr *LHS,
@@ -8250,6 +8318,16 @@ bool OpenMPIterationSpaceChecker::checkAndSetInc(Expr *S) {
8250
8318
if (!ExprTemp->cleanupsHaveSideEffects())
8251
8319
S = ExprTemp->getSubExpr();
8252
8320
8321
+ if (CollapsedLoopVarDecls) {
8322
+ ForSubExprChecker FSEC{CollapsedLoopVarDecls};
8323
+ if (!FSEC.TraverseStmt(S)) {
8324
+ SourceRange &Range = FSEC.getErrRange();
8325
+ SemaRef.Diag(Range.getBegin(), diag::err_omp_loop_bad_collapse_var)
8326
+ << Range.getEnd() << 2 << FSEC.getForbiddenVar();
8327
+ return true;
8328
+ }
8329
+ }
8330
+
8253
8331
IncrementSrcRange = S->getSourceRange();
8254
8332
S = S->IgnoreParens();
8255
8333
if (auto *UO = dyn_cast<UnaryOperator>(S)) {
@@ -8972,7 +9050,7 @@ void SemaOpenMP::ActOnOpenMPLoopInitialization(SourceLocation ForLoc,
8972
9050
8973
9051
DSAStack->loopStart();
8974
9052
OpenMPIterationSpaceChecker ISC(SemaRef, /*SupportsNonRectangular=*/true,
8975
- *DSAStack, ForLoc);
9053
+ *DSAStack, ForLoc, nullptr );
8976
9054
if (!ISC.checkAndSetInit(Init, /*EmitDiags=*/false)) {
8977
9055
if (ValueDecl *D = ISC.getLoopDecl()) {
8978
9056
auto *VD = dyn_cast<VarDecl>(D);
@@ -9069,7 +9147,8 @@ static bool checkOpenMPIterationSpace(
9069
9147
Expr *OrderedLoopCountExpr,
9070
9148
SemaOpenMP::VarsWithInheritedDSAType &VarsWithImplicitDSA,
9071
9149
llvm::MutableArrayRef<LoopIterationSpace> ResultIterSpaces,
9072
- llvm::MapVector<const Expr *, DeclRefExpr *> &Captures) {
9150
+ llvm::MapVector<const Expr *, DeclRefExpr *> &Captures,
9151
+ const llvm::SmallSet<Decl *, 4> *CollapsedLoopVarDecls) {
9073
9152
bool SupportsNonRectangular = !isOpenMPLoopTransformationDirective(DKind);
9074
9153
// OpenMP [2.9.1, Canonical Loop Form]
9075
9154
// for (init-expr; test-expr; incr-expr) structured-block
@@ -9108,7 +9187,8 @@ static bool checkOpenMPIterationSpace(
9108
9187
return false;
9109
9188
9110
9189
OpenMPIterationSpaceChecker ISC(SemaRef, SupportsNonRectangular, DSA,
9111
- For ? For->getForLoc() : CXXFor->getForLoc());
9190
+ For ? For->getForLoc() : CXXFor->getForLoc(),
9191
+ CollapsedLoopVarDecls);
9112
9192
9113
9193
// Check init.
9114
9194
Stmt *Init = For ? For->getInit() : CXXFor->getBeginStmt();
@@ -9475,6 +9555,36 @@ static Expr *buildPostUpdate(Sema &S, ArrayRef<Expr *> PostUpdates) {
9475
9555
return PostUpdate;
9476
9556
}
9477
9557
9558
+ class ForVarDeclFinder : public RecursiveASTVisitor<ForVarDeclFinder> {
9559
+ int NestingDepth;
9560
+ llvm::SmallSet<Decl *, 4> &VarDecls;
9561
+
9562
+ public:
9563
+ explicit ForVarDeclFinder(llvm::SmallSet<Decl *, 4> &VD)
9564
+ : NestingDepth(0), VarDecls(VD) {}
9565
+
9566
+ bool VisitForStmt(ForStmt *F) {
9567
+ ++NestingDepth;
9568
+ TraverseStmt(F->getBody());
9569
+ --NestingDepth;
9570
+ return false;
9571
+ }
9572
+
9573
+ bool VisitCXXForRangeStmt(CXXForRangeStmt *RF) {
9574
+ ++NestingDepth;
9575
+ TraverseStmt(RF->getBody());
9576
+ --NestingDepth;
9577
+ return false;
9578
+ }
9579
+
9580
+ bool VisitVarDecl(VarDecl *D) {
9581
+ Decl *C = D->getCanonicalDecl();
9582
+ if (NestingDepth > 0)
9583
+ VarDecls.insert(C);
9584
+ return true;
9585
+ }
9586
+ };
9587
+
9478
9588
/// Called on a for stmt to check itself and nested loops (if any).
9479
9589
/// \return Returns 0 if one of the collapsed stmts is not canonical for loop,
9480
9590
/// number of collapsed loops otherwise.
@@ -9487,13 +9597,17 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9487
9597
unsigned NestedLoopCount = 1;
9488
9598
bool SupportsNonPerfectlyNested = (SemaRef.LangOpts.OpenMP >= 50) &&
9489
9599
!isOpenMPLoopTransformationDirective(DKind);
9600
+ llvm::SmallSet<Decl *, 4> CollapsedLoopVarDecls{};
9490
9601
9491
9602
if (CollapseLoopCountExpr) {
9492
9603
// Found 'collapse' clause - calculate collapse number.
9493
9604
Expr::EvalResult Result;
9494
9605
if (!CollapseLoopCountExpr->isValueDependent() &&
9495
9606
CollapseLoopCountExpr->EvaluateAsInt(Result, SemaRef.getASTContext())) {
9496
9607
NestedLoopCount = Result.Val.getInt().getLimitedValue();
9608
+
9609
+ ForVarDeclFinder FVDF{CollapsedLoopVarDecls};
9610
+ FVDF.TraverseStmt(AStmt);
9497
9611
} else {
9498
9612
Built.clear(/*Size=*/1);
9499
9613
return 1;
@@ -9531,11 +9645,13 @@ checkOpenMPLoop(OpenMPDirectiveKind DKind, Expr *CollapseLoopCountExpr,
9531
9645
SupportsNonPerfectlyNested, NumLoops,
9532
9646
[DKind, &SemaRef, &DSA, NumLoops, NestedLoopCount,
9533
9647
CollapseLoopCountExpr, OrderedLoopCountExpr, &VarsWithImplicitDSA,
9534
- &IterSpaces, &Captures](unsigned Cnt, Stmt *CurStmt) {
9648
+ &IterSpaces, &Captures,
9649
+ CollapsedLoopVarDecls](unsigned Cnt, Stmt *CurStmt) {
9535
9650
if (checkOpenMPIterationSpace(
9536
9651
DKind, CurStmt, SemaRef, DSA, Cnt, NestedLoopCount,
9537
9652
NumLoops, CollapseLoopCountExpr, OrderedLoopCountExpr,
9538
- VarsWithImplicitDSA, IterSpaces, Captures))
9653
+ VarsWithImplicitDSA, IterSpaces, Captures,
9654
+ &CollapsedLoopVarDecls))
9539
9655
return true;
9540
9656
if (Cnt > 0 && Cnt >= NestedLoopCount &&
9541
9657
IterSpaces[Cnt].CounterVar) {
0 commit comments