@@ -14197,42 +14197,43 @@ StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeSimdDirective(
14197
14197
}
14198
14198
14199
14199
// Overloaded base case function
14200
- template <typename T, typename F>
14201
- static bool tryHandleAs(T *t, F &&) {
14202
- return false;
14200
+ template <typename T, typename F> static bool tryHandleAs(T *t, F &&) {
14201
+ return false;
14203
14202
}
14204
14203
14205
14204
/**
14206
- * Tries to recursively cast `t` to one of the given types and invokes `f` if successful.
14205
+ * Tries to recursively cast `t` to one of the given types and invokes `f` if
14206
+ * successful.
14207
14207
*
14208
14208
* @tparam Class The first type to check.
14209
14209
* @tparam Rest The remaining types to check.
14210
14210
* @tparam T The base type of `t`.
14211
- * @tparam F The callable type for the function to invoke upon a successful cast.
14211
+ * @tparam F The callable type for the function to invoke upon a successful
14212
+ * cast.
14212
14213
* @param t The object to be checked.
14213
14214
* @param f The function to invoke if `t` matches `Class`.
14214
14215
* @return `true` if `t` matched any type and `f` was called, otherwise `false`.
14215
14216
*/
14216
14217
template <typename Class, typename... Rest, typename T, typename F>
14217
14218
static bool tryHandleAs(T *t, F &&f) {
14218
- if (Class *c = dyn_cast<Class>(t)) {
14219
- f(c);
14220
- return true;
14221
- } else {
14222
- return tryHandleAs<Rest...>(t, std::forward<F>(f));
14223
- }
14219
+ if (Class *c = dyn_cast<Class>(t)) {
14220
+ f(c);
14221
+ return true;
14222
+ } else {
14223
+ return tryHandleAs<Rest...>(t, std::forward<F>(f));
14224
+ }
14224
14225
}
14225
14226
14226
14227
// Updates OriginalInits by checking Transform against loop transformation
14227
14228
// directives and appending their pre-inits if a match is found.
14228
14229
static void updatePreInits(OMPLoopBasedDirective *Transform,
14229
14230
SmallVectorImpl<SmallVector<Stmt *, 0>> &PreInits) {
14230
- if (!tryHandleAs<OMPTileDirective, OMPUnrollDirective, OMPReverseDirective,
14231
- OMPInterchangeDirective, OMPFuseDirective>(
14232
- Transform, [&PreInits](auto *Dir) {
14233
- appendFlattenedStmtList(PreInits.back(), Dir->getPreInits());
14234
- }))
14235
- llvm_unreachable("Unhandled loop transformation");
14231
+ if (!tryHandleAs<OMPTileDirective, OMPUnrollDirective, OMPReverseDirective,
14232
+ OMPInterchangeDirective, OMPFuseDirective>(
14233
+ Transform, [&PreInits](auto *Dir) {
14234
+ appendFlattenedStmtList(PreInits.back(), Dir->getPreInits());
14235
+ }))
14236
+ llvm_unreachable("Unhandled loop transformation");
14236
14237
}
14237
14238
14238
14239
bool SemaOpenMP::checkTransformableLoopNest(
@@ -14310,43 +14311,42 @@ class NestedLoopCounterVisitor : public DynamicRecursiveASTVisitor {
14310
14311
unsigned getNestedLoopCount() const { return NestedLoopCount; }
14311
14312
14312
14313
bool VisitForStmt(ForStmt *FS) override {
14313
- ++NestedLoopCount;
14314
- return true;
14314
+ ++NestedLoopCount;
14315
+ return true;
14315
14316
}
14316
14317
14317
14318
bool VisitCXXForRangeStmt(CXXForRangeStmt *FRS) override {
14318
- ++NestedLoopCount;
14319
- return true;
14319
+ ++NestedLoopCount;
14320
+ return true;
14320
14321
}
14321
14322
14322
14323
bool TraverseStmt(Stmt *S) override {
14323
- if (!S)
14324
+ if (!S)
14324
14325
return true;
14325
14326
14326
- // Skip traversal of all expressions, including special cases like
14327
- // LambdaExpr, StmtExpr, BlockExpr, and RequiresExpr. These expressions
14328
- // may contain inner statements (and even loops), but they are not part
14329
- // of the syntactic body of the surrounding loop structure.
14330
- // Therefore must not be counted
14331
- if (isa<Expr>(S))
14327
+ // Skip traversal of all expressions, including special cases like
14328
+ // LambdaExpr, StmtExpr, BlockExpr, and RequiresExpr. These expressions
14329
+ // may contain inner statements (and even loops), but they are not part
14330
+ // of the syntactic body of the surrounding loop structure.
14331
+ // Therefore must not be counted
14332
+ if (isa<Expr>(S))
14332
14333
return true;
14333
14334
14334
- // Only recurse into CompoundStmt (block {}) and loop bodies
14335
- if (isa<CompoundStmt>(S) || isa<ForStmt>(S) ||
14336
- isa<CXXForRangeStmt>(S)) {
14335
+ // Only recurse into CompoundStmt (block {}) and loop bodies
14336
+ if (isa<CompoundStmt>(S) || isa<ForStmt>(S) || isa<CXXForRangeStmt>(S)) {
14337
14337
return DynamicRecursiveASTVisitor::TraverseStmt(S);
14338
- }
14338
+ }
14339
14339
14340
- // Stop traversal of the rest of statements, that break perfect
14341
- // loop nesting, such as control flow (IfStmt, SwitchStmt...)
14342
- return true;
14340
+ // Stop traversal of the rest of statements, that break perfect
14341
+ // loop nesting, such as control flow (IfStmt, SwitchStmt...)
14342
+ return true;
14343
14343
}
14344
14344
14345
14345
bool TraverseDecl(Decl *D) override {
14346
- // Stop in the case of finding a declaration, it is not important
14347
- // in order to find nested loops (Possible CXXRecordDecl, RecordDecl,
14348
- // FunctionDecl...)
14349
- return true;
14346
+ // Stop in the case of finding a declaration, it is not important
14347
+ // in order to find nested loops (Possible CXXRecordDecl, RecordDecl,
14348
+ // FunctionDecl...)
14349
+ return true;
14350
14350
}
14351
14351
};
14352
14352
@@ -14504,15 +14504,14 @@ bool SemaOpenMP::analyzeLoopSequence(
14504
14504
return isa<OMPLoopTransformationDirective>(Child);
14505
14505
};
14506
14506
14507
-
14508
14507
// High level grammar validation
14509
14508
for (auto *Child : LoopSeqStmt->children()) {
14510
14509
14511
- if (!Child)
14510
+ if (!Child)
14512
14511
continue;
14513
14512
14514
- // Skip over non-loop-sequence statements
14515
- if (!isLoopSequenceDerivation(Child)) {
14513
+ // Skip over non-loop-sequence statements
14514
+ if (!isLoopSequenceDerivation(Child)) {
14516
14515
Child = Child->IgnoreContainers();
14517
14516
14518
14517
// Ignore empty compound statement
@@ -14530,9 +14529,9 @@ bool SemaOpenMP::analyzeLoopSequence(
14530
14529
// Already been treated, skip this children
14531
14530
continue;
14532
14531
}
14533
- }
14534
- // Regular loop sequence handling
14535
- if (isLoopSequenceDerivation(Child)) {
14532
+ }
14533
+ // Regular loop sequence handling
14534
+ if (isLoopSequenceDerivation(Child)) {
14536
14535
if (isLoopGeneratingStmt(Child)) {
14537
14536
if (!analyzeLoopGeneration(Child)) {
14538
14537
return false;
@@ -14546,12 +14545,12 @@ bool SemaOpenMP::analyzeLoopSequence(
14546
14545
// Update the Loop Sequence size by one
14547
14546
++LoopSeqSize;
14548
14547
}
14549
- } else {
14548
+ } else {
14550
14549
// Report error for invalid statement inside canonical loop sequence
14551
14550
Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14552
14551
<< 0 << getOpenMPDirectiveName(Kind);
14553
14552
return false;
14554
- }
14553
+ }
14555
14554
}
14556
14555
return true;
14557
14556
}
@@ -14568,9 +14567,9 @@ bool SemaOpenMP::checkTransformableLoopSequence(
14568
14567
14569
14568
// Checks whether the given statement is a compound statement
14570
14569
if (!isa<CompoundStmt>(AStmt)) {
14571
- Diag(AStmt->getBeginLoc(), diag::err_omp_not_a_loop_sequence)
14572
- << getOpenMPDirectiveName(Kind);
14573
- return false;
14570
+ Diag(AStmt->getBeginLoc(), diag::err_omp_not_a_loop_sequence)
14571
+ << getOpenMPDirectiveName(Kind);
14572
+ return false;
14574
14573
}
14575
14574
// Number of top level canonical loop nests observed (And acts as index)
14576
14575
LoopSeqSize = 0;
@@ -14601,7 +14600,7 @@ bool SemaOpenMP::checkTransformableLoopSequence(
14601
14600
OriginalInits, TransformsPreInits,
14602
14601
LoopSequencePreInits, LoopCategories, Context,
14603
14602
Kind)) {
14604
- return false;
14603
+ return false;
14605
14604
}
14606
14605
if (LoopSeqSize <= 0) {
14607
14606
Diag(AStmt->getBeginLoc(), diag::err_omp_empty_loop_sequence)
@@ -15315,7 +15314,7 @@ StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
15315
15314
Stmt *LoopStmt = nullptr;
15316
15315
collectLoopStmts(AStmt, {LoopStmt});
15317
15316
15318
- // Determine the PreInit declarations.e
15317
+ // Determine the PreInit declarations.
15319
15318
SmallVector<Stmt *, 4> PreInits;
15320
15319
addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15321
15320
@@ -15931,13 +15930,18 @@ StmtResult SemaOpenMP::ActOnOpenMPFuseDirective(ArrayRef<OMPClause *> Clauses,
15931
15930
CountVal = CountInt.getZExtValue();
15932
15931
};
15933
15932
15934
- // Checks if the loop range is valid
15933
+ // OpenMP [6.0, Restrictions]
15934
+ // first + count - 1 must not evaluate to a value greater than the
15935
+ // loop sequence length of the associated canonical loop sequence.
15935
15936
auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
15936
15937
unsigned NumLoops) -> bool {
15937
15938
return FirstVal + CountVal - 1 <= NumLoops;
15938
15939
};
15939
15940
uint64_t FirstVal = 1, CountVal = 0, LastVal = LoopSeqSize;
15940
15941
15942
+ // Validates the loop range after evaluating the semantic information
15943
+ // and ensures that the range is valid for the given loop sequence size.
15944
+ // Expressions are evaluated at compile time to obtain constant values.
15941
15945
if (LRC) {
15942
15946
EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
15943
15947
CountVal);
0 commit comments