@@ -14128,42 +14128,43 @@ StmtResult SemaOpenMP::ActOnOpenMPTargetTeamsDistributeSimdDirective(
14128
14128
}
14129
14129
14130
14130
// Overloaded base case function
14131
- template <typename T, typename F>
14132
- static bool tryHandleAs(T *t, F &&) {
14133
- return false;
14131
+ template <typename T, typename F> static bool tryHandleAs(T *t, F &&) {
14132
+ return false;
14134
14133
}
14135
14134
14136
14135
/**
14137
- * Tries to recursively cast `t` to one of the given types and invokes `f` if successful.
14136
+ * Tries to recursively cast `t` to one of the given types and invokes `f` if
14137
+ * successful.
14138
14138
*
14139
14139
* @tparam Class The first type to check.
14140
14140
* @tparam Rest The remaining types to check.
14141
14141
* @tparam T The base type of `t`.
14142
- * @tparam F The callable type for the function to invoke upon a successful cast.
14142
+ * @tparam F The callable type for the function to invoke upon a successful
14143
+ * cast.
14143
14144
* @param t The object to be checked.
14144
14145
* @param f The function to invoke if `t` matches `Class`.
14145
14146
* @return `true` if `t` matched any type and `f` was called, otherwise `false`.
14146
14147
*/
14147
14148
template <typename Class, typename... Rest, typename T, typename F>
14148
14149
static bool tryHandleAs(T *t, F &&f) {
14149
- if (Class *c = dyn_cast<Class>(t)) {
14150
- f(c);
14151
- return true;
14152
- } else {
14153
- return tryHandleAs<Rest...>(t, std::forward<F>(f));
14154
- }
14150
+ if (Class *c = dyn_cast<Class>(t)) {
14151
+ f(c);
14152
+ return true;
14153
+ } else {
14154
+ return tryHandleAs<Rest...>(t, std::forward<F>(f));
14155
+ }
14155
14156
}
14156
14157
14157
14158
// Updates OriginalInits by checking Transform against loop transformation
14158
14159
// directives and appending their pre-inits if a match is found.
14159
14160
static void updatePreInits(OMPLoopBasedDirective *Transform,
14160
14161
SmallVectorImpl<SmallVector<Stmt *, 0>> &PreInits) {
14161
- if (!tryHandleAs<OMPTileDirective, OMPUnrollDirective, OMPReverseDirective,
14162
- OMPInterchangeDirective, OMPFuseDirective>(
14163
- Transform, [&PreInits](auto *Dir) {
14164
- appendFlattenedStmtList(PreInits.back(), Dir->getPreInits());
14165
- }))
14166
- llvm_unreachable("Unhandled loop transformation");
14162
+ if (!tryHandleAs<OMPTileDirective, OMPUnrollDirective, OMPReverseDirective,
14163
+ OMPInterchangeDirective, OMPFuseDirective>(
14164
+ Transform, [&PreInits](auto *Dir) {
14165
+ appendFlattenedStmtList(PreInits.back(), Dir->getPreInits());
14166
+ }))
14167
+ llvm_unreachable("Unhandled loop transformation");
14167
14168
}
14168
14169
14169
14170
bool SemaOpenMP::checkTransformableLoopNest(
@@ -14241,43 +14242,42 @@ class NestedLoopCounterVisitor : public DynamicRecursiveASTVisitor {
14241
14242
unsigned getNestedLoopCount() const { return NestedLoopCount; }
14242
14243
14243
14244
bool VisitForStmt(ForStmt *FS) override {
14244
- ++NestedLoopCount;
14245
- return true;
14245
+ ++NestedLoopCount;
14246
+ return true;
14246
14247
}
14247
14248
14248
14249
bool VisitCXXForRangeStmt(CXXForRangeStmt *FRS) override {
14249
- ++NestedLoopCount;
14250
- return true;
14250
+ ++NestedLoopCount;
14251
+ return true;
14251
14252
}
14252
14253
14253
14254
bool TraverseStmt(Stmt *S) override {
14254
- if (!S)
14255
+ if (!S)
14255
14256
return true;
14256
14257
14257
- // Skip traversal of all expressions, including special cases like
14258
- // LambdaExpr, StmtExpr, BlockExpr, and RequiresExpr. These expressions
14259
- // may contain inner statements (and even loops), but they are not part
14260
- // of the syntactic body of the surrounding loop structure.
14261
- // Therefore must not be counted
14262
- if (isa<Expr>(S))
14258
+ // Skip traversal of all expressions, including special cases like
14259
+ // LambdaExpr, StmtExpr, BlockExpr, and RequiresExpr. These expressions
14260
+ // may contain inner statements (and even loops), but they are not part
14261
+ // of the syntactic body of the surrounding loop structure.
14262
+ // Therefore must not be counted
14263
+ if (isa<Expr>(S))
14263
14264
return true;
14264
14265
14265
- // Only recurse into CompoundStmt (block {}) and loop bodies
14266
- if (isa<CompoundStmt>(S) || isa<ForStmt>(S) ||
14267
- isa<CXXForRangeStmt>(S)) {
14266
+ // Only recurse into CompoundStmt (block {}) and loop bodies
14267
+ if (isa<CompoundStmt>(S) || isa<ForStmt>(S) || isa<CXXForRangeStmt>(S)) {
14268
14268
return DynamicRecursiveASTVisitor::TraverseStmt(S);
14269
- }
14269
+ }
14270
14270
14271
- // Stop traversal of the rest of statements, that break perfect
14272
- // loop nesting, such as control flow (IfStmt, SwitchStmt...)
14273
- return true;
14271
+ // Stop traversal of the rest of statements, that break perfect
14272
+ // loop nesting, such as control flow (IfStmt, SwitchStmt...)
14273
+ return true;
14274
14274
}
14275
14275
14276
14276
bool TraverseDecl(Decl *D) override {
14277
- // Stop in the case of finding a declaration, it is not important
14278
- // in order to find nested loops (Possible CXXRecordDecl, RecordDecl,
14279
- // FunctionDecl...)
14280
- return true;
14277
+ // Stop in the case of finding a declaration, it is not important
14278
+ // in order to find nested loops (Possible CXXRecordDecl, RecordDecl,
14279
+ // FunctionDecl...)
14280
+ return true;
14281
14281
}
14282
14282
};
14283
14283
@@ -14435,15 +14435,14 @@ bool SemaOpenMP::analyzeLoopSequence(
14435
14435
return isa<OMPLoopTransformationDirective>(Child);
14436
14436
};
14437
14437
14438
-
14439
14438
// High level grammar validation
14440
14439
for (auto *Child : LoopSeqStmt->children()) {
14441
14440
14442
- if (!Child)
14441
+ if (!Child)
14443
14442
continue;
14444
14443
14445
- // Skip over non-loop-sequence statements
14446
- if (!isLoopSequenceDerivation(Child)) {
14444
+ // Skip over non-loop-sequence statements
14445
+ if (!isLoopSequenceDerivation(Child)) {
14447
14446
Child = Child->IgnoreContainers();
14448
14447
14449
14448
// Ignore empty compound statement
@@ -14461,9 +14460,9 @@ bool SemaOpenMP::analyzeLoopSequence(
14461
14460
// Already been treated, skip this children
14462
14461
continue;
14463
14462
}
14464
- }
14465
- // Regular loop sequence handling
14466
- if (isLoopSequenceDerivation(Child)) {
14463
+ }
14464
+ // Regular loop sequence handling
14465
+ if (isLoopSequenceDerivation(Child)) {
14467
14466
if (isLoopGeneratingStmt(Child)) {
14468
14467
if (!analyzeLoopGeneration(Child)) {
14469
14468
return false;
@@ -14477,12 +14476,12 @@ bool SemaOpenMP::analyzeLoopSequence(
14477
14476
// Update the Loop Sequence size by one
14478
14477
++LoopSeqSize;
14479
14478
}
14480
- } else {
14479
+ } else {
14481
14480
// Report error for invalid statement inside canonical loop sequence
14482
14481
Diag(Child->getBeginLoc(), diag::err_omp_not_for)
14483
14482
<< 0 << getOpenMPDirectiveName(Kind);
14484
14483
return false;
14485
- }
14484
+ }
14486
14485
}
14487
14486
return true;
14488
14487
}
@@ -14499,9 +14498,9 @@ bool SemaOpenMP::checkTransformableLoopSequence(
14499
14498
14500
14499
// Checks whether the given statement is a compound statement
14501
14500
if (!isa<CompoundStmt>(AStmt)) {
14502
- Diag(AStmt->getBeginLoc(), diag::err_omp_not_a_loop_sequence)
14503
- << getOpenMPDirectiveName(Kind);
14504
- return false;
14501
+ Diag(AStmt->getBeginLoc(), diag::err_omp_not_a_loop_sequence)
14502
+ << getOpenMPDirectiveName(Kind);
14503
+ return false;
14505
14504
}
14506
14505
// Number of top level canonical loop nests observed (And acts as index)
14507
14506
LoopSeqSize = 0;
@@ -14532,7 +14531,7 @@ bool SemaOpenMP::checkTransformableLoopSequence(
14532
14531
OriginalInits, TransformsPreInits,
14533
14532
LoopSequencePreInits, LoopCategories, Context,
14534
14533
Kind)) {
14535
- return false;
14534
+ return false;
14536
14535
}
14537
14536
if (LoopSeqSize <= 0) {
14538
14537
Diag(AStmt->getBeginLoc(), diag::err_omp_empty_loop_sequence)
@@ -15233,7 +15232,7 @@ StmtResult SemaOpenMP::ActOnOpenMPUnrollDirective(ArrayRef<OMPClause *> Clauses,
15233
15232
Stmt *LoopStmt = nullptr;
15234
15233
collectLoopStmts(AStmt, {LoopStmt});
15235
15234
15236
- // Determine the PreInit declarations.e
15235
+ // Determine the PreInit declarations.
15237
15236
SmallVector<Stmt *, 4> PreInits;
15238
15237
addLoopPreInits(Context, LoopHelper, LoopStmt, OriginalInits[0], PreInits);
15239
15238
@@ -15848,13 +15847,18 @@ StmtResult SemaOpenMP::ActOnOpenMPFuseDirective(ArrayRef<OMPClause *> Clauses,
15848
15847
CountVal = CountInt.getZExtValue();
15849
15848
};
15850
15849
15851
- // Checks if the loop range is valid
15850
+ // OpenMP [6.0, Restrictions]
15851
+ // first + count - 1 must not evaluate to a value greater than the
15852
+ // loop sequence length of the associated canonical loop sequence.
15852
15853
auto ValidLoopRange = [](uint64_t FirstVal, uint64_t CountVal,
15853
15854
unsigned NumLoops) -> bool {
15854
15855
return FirstVal + CountVal - 1 <= NumLoops;
15855
15856
};
15856
15857
uint64_t FirstVal = 1, CountVal = 0, LastVal = LoopSeqSize;
15857
15858
15859
+ // Validates the loop range after evaluating the semantic information
15860
+ // and ensures that the range is valid for the given loop sequence size.
15861
+ // Expressions are evaluated at compile time to obtain constant values.
15858
15862
if (LRC) {
15859
15863
EvaluateLoopRangeArguments(LRC->getFirst(), LRC->getCount(), FirstVal,
15860
15864
CountVal);
0 commit comments