@@ -305,6 +305,12 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
305
305
}
306
306
void Post (const parser::Name &);
307
307
308
+ const parser::OmpClause *associatedClause{nullptr };
309
+ void SetAssociatedClause (const parser::OmpClause &c) {
310
+ associatedClause = &c;
311
+ }
312
+ const parser::OmpClause *GetAssociatedClause () { return associatedClause; }
313
+
308
314
private:
309
315
std::int64_t GetAssociatedLoopLevelFromClauses (const parser::OmpClauseList &);
310
316
@@ -344,7 +350,8 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
344
350
}
345
351
346
352
// Predetermined DSA rules
347
- void PrivatizeAssociatedLoopIndex (const parser::OpenMPLoopConstruct &);
353
+ void PrivatizeAssociatedLoopIndexAndCheckLoopLevel (
354
+ const parser::OpenMPLoopConstruct &);
348
355
void ResolveSeqLoopIndexInParallelOrTaskConstruct (const parser::Name &);
349
356
350
357
void ResolveOmpObjectList (const parser::OmpObjectList &, Symbol::Flag);
@@ -362,6 +369,8 @@ class OmpAttributeVisitor : DirectiveAttributeVisitor<llvm::omp::Directive> {
362
369
363
370
void CheckDataCopyingClause (
364
371
const parser::Name &, const Symbol &, Symbol::Flag);
372
+
373
+ void CheckAssocLoopLevel (std::int64_t level, const parser::OmpClause *clause);
365
374
};
366
375
367
376
template <typename T>
@@ -777,7 +786,7 @@ bool OmpAttributeVisitor::Pre(const parser::OpenMPLoopConstruct &x) {
777
786
}
778
787
ClearDataSharingAttributeObjects ();
779
788
SetContextAssociatedLoopLevel (GetAssociatedLoopLevelFromClauses (clauseList));
780
- PrivatizeAssociatedLoopIndex (x);
789
+ PrivatizeAssociatedLoopIndexAndCheckLoopLevel (x);
781
790
return true ;
782
791
}
783
792
@@ -824,24 +833,32 @@ std::int64_t OmpAttributeVisitor::GetAssociatedLoopLevelFromClauses(
824
833
const parser::OmpClauseList &x) {
825
834
std::int64_t orderedLevel{0 };
826
835
std::int64_t collapseLevel{0 };
836
+
837
+ const parser::OmpClause *ordClause{nullptr };
838
+ const parser::OmpClause *collClause{nullptr };
839
+
827
840
for (const auto &clause : x.v ) {
828
841
if (const auto *orderedClause{
829
842
std::get_if<parser::OmpClause::Ordered>(&clause.u )}) {
830
843
if (const auto v{EvaluateInt64 (context_, orderedClause->v )}) {
831
844
orderedLevel = *v;
832
845
}
846
+ ordClause = &clause;
833
847
}
834
848
if (const auto *collapseClause{
835
849
std::get_if<parser::OmpClause::Collapse>(&clause.u )}) {
836
850
if (const auto v{EvaluateInt64 (context_, collapseClause->v )}) {
837
851
collapseLevel = *v;
838
852
}
853
+ collClause = &clause;
839
854
}
840
855
}
841
856
842
857
if (orderedLevel && (!collapseLevel || orderedLevel >= collapseLevel)) {
858
+ SetAssociatedClause (*ordClause);
843
859
return orderedLevel;
844
860
} else if (!orderedLevel && collapseLevel) {
861
+ SetAssociatedClause (*collClause);
845
862
return collapseLevel;
846
863
} // orderedLevel < collapseLevel is an error handled in structural checks
847
864
return 1 ; // default is outermost loop
@@ -855,10 +872,7 @@ std::int64_t OmpAttributeVisitor::GetAssociatedLoopLevelFromClauses(
855
872
// increment of the associated do-loop.
856
873
// - The loop iteration variables in the associated do-loops of a simd
857
874
// construct with multiple associated do-loops are lastprivate.
858
- //
859
- // TODO: revisit after semantics checks are completed for do-loop association of
860
- // collapse and ordered
861
- void OmpAttributeVisitor::PrivatizeAssociatedLoopIndex (
875
+ void OmpAttributeVisitor::PrivatizeAssociatedLoopIndexAndCheckLoopLevel (
862
876
const parser::OpenMPLoopConstruct &x) {
863
877
std::int64_t level{GetContext ().associatedLoopLevel };
864
878
if (level <= 0 ) {
@@ -887,7 +901,16 @@ void OmpAttributeVisitor::PrivatizeAssociatedLoopIndex(
887
901
const auto it{block.begin ()};
888
902
loop = it != block.end () ? GetDoConstructIf (*it) : nullptr ;
889
903
}
890
- CHECK (level == 0 );
904
+ CheckAssocLoopLevel (level, GetAssociatedClause ());
905
+ }
906
+ void OmpAttributeVisitor::CheckAssocLoopLevel (
907
+ std::int64_t level, const parser::OmpClause *clause) {
908
+ if (clause && level != 0 ) {
909
+ context_.Say (clause->source ,
910
+ " The value of the parameter in the COLLAPSE or ORDERED clause must"
911
+ " not be larger than the number of nested loops"
912
+ " following the construct." _err_en_US);
913
+ }
891
914
}
892
915
893
916
bool OmpAttributeVisitor::Pre (const parser::OpenMPSectionsConstruct &x) {
0 commit comments