@@ -84,52 +84,69 @@ class OmpWorkshareBlockChecker {
84
84
parser::CharBlock source_;
85
85
};
86
86
87
- class OmpCycleChecker {
87
+ class OmpCycleAndExitChecker {
88
88
public:
89
- OmpCycleChecker (SemanticsContext &context, std::int64_t cycleLevel )
90
- : context_{context}, cycleLevel_{cycleLevel } {}
89
+ OmpCycleAndExitChecker (SemanticsContext &context, std::int64_t level )
90
+ : context_{context}, level_{level } {}
91
91
92
92
template <typename T> bool Pre (const T &) { return true ; }
93
93
template <typename T> void Post (const T &) {}
94
94
95
95
bool Pre (const parser::DoConstruct &dc) {
96
- cycleLevel_ --;
96
+ level_ --;
97
97
const auto &constructName{std::get<0 >(std::get<0 >(dc.t ).statement .t )};
98
98
if (constructName) {
99
99
constructNamesAndLevels_.emplace (
100
- constructName.value ().ToString (), cycleLevel_ );
100
+ constructName.value ().ToString (), level_ );
101
101
}
102
102
return true ;
103
103
}
104
104
105
+ void Post (const parser::DoConstruct &dc) { level_++; }
106
+
105
107
bool Pre (const parser::CycleStmt &cyclestmt) {
106
108
std::map<std::string, std::int64_t >::iterator it;
107
109
bool err{false };
108
110
if (cyclestmt.v ) {
109
111
it = constructNamesAndLevels_.find (cyclestmt.v ->source .ToString ());
110
112
err = (it != constructNamesAndLevels_.end () && it->second > 0 );
111
- } else {
112
- // If there is no label then the cycle statement is associated with the
113
- // closest enclosing DO. Use its level for the checks.
114
- err = cycleLevel_ > 0 ;
113
+ } else { // If there is no label then use the level of the last enclosing DO
114
+ err = level_ > 0 ;
115
115
}
116
116
if (err) {
117
- context_.Say (*cycleSource_ ,
117
+ context_.Say (*source_ ,
118
118
" CYCLE statement to non-innermost associated loop of an OpenMP DO "
119
119
" construct" _err_en_US);
120
120
}
121
121
return true ;
122
122
}
123
123
124
+ bool Pre (const parser::ExitStmt &exitStmt) {
125
+ std::map<std::string, std::int64_t >::iterator it;
126
+ bool err{false };
127
+ if (exitStmt.v ) {
128
+ it = constructNamesAndLevels_.find (exitStmt.v ->source .ToString ());
129
+ err = (it != constructNamesAndLevels_.end () && it->second >= 0 );
130
+ } else { // If there is no label then use the level of the last enclosing DO
131
+ err = level_ >= 0 ;
132
+ }
133
+ if (err) {
134
+ context_.Say (*source_,
135
+ " EXIT statement terminates associated loop of an OpenMP DO "
136
+ " construct" _err_en_US);
137
+ }
138
+ return true ;
139
+ }
140
+
124
141
bool Pre (const parser::Statement<parser::ActionStmt> &actionstmt) {
125
- cycleSource_ = &actionstmt.source ;
142
+ source_ = &actionstmt.source ;
126
143
return true ;
127
144
}
128
145
129
146
private:
130
147
SemanticsContext &context_;
131
- const parser::CharBlock *cycleSource_ ;
132
- std::int64_t cycleLevel_ ;
148
+ const parser::CharBlock *source_ ;
149
+ std::int64_t level_ ;
133
150
std::map<std::string, std::int64_t > constructNamesAndLevels_;
134
151
};
135
152
@@ -657,8 +674,8 @@ std::int64_t OmpStructureChecker::GetOrdCollapseLevel(
657
674
void OmpStructureChecker::CheckCycleConstraints (
658
675
const parser::OpenMPLoopConstruct &x) {
659
676
std::int64_t ordCollapseLevel{GetOrdCollapseLevel (x)};
660
- OmpCycleChecker ompCycleChecker {context_, ordCollapseLevel};
661
- parser::Walk (x, ompCycleChecker );
677
+ OmpCycleAndExitChecker checker {context_, ordCollapseLevel};
678
+ parser::Walk (x, checker );
662
679
}
663
680
664
681
void OmpStructureChecker::CheckDistLinear (
0 commit comments