@@ -213,6 +213,31 @@ class AssociatedLoopChecker {
213
213
std::map<std::string, std::int64_t > constructNamesAndLevels_;
214
214
};
215
215
216
+ // `OmpDesignatorChecker` is used to check if the designator
217
+ // can appear within the OpenMP construct
218
+ class OmpDesignatorChecker {
219
+ public:
220
+ OmpDesignatorChecker (SemanticsContext &context, parser::CharBlock source)
221
+ : context_{context}, source_{source} {}
222
+
223
+ template <typename T> bool Pre (const T &) { return true ; }
224
+ template <typename T> void Post (const T &) {}
225
+
226
+ bool Pre (const parser::Name &name) {
227
+ if (name.symbol ->test (Symbol::Flag::OmpThreadprivate)) {
228
+ // OpenMP 6.0: 7.3 threadprivate directive restriction
229
+ context_.Say (source_,
230
+ " A THREADPRIVATE variable `%s` cannot appear in a UNTIED TASK region" _err_en_US,
231
+ name.source );
232
+ }
233
+ return true ;
234
+ }
235
+
236
+ private:
237
+ SemanticsContext &context_;
238
+ parser::CharBlock source_;
239
+ };
240
+
216
241
bool OmpStructureChecker::CheckAllowedClause (llvmOmpClause clause) {
217
242
unsigned version{context_.langOptions ().OpenMPVersion };
218
243
DirectiveContext &dirCtx = GetContext ();
@@ -1164,6 +1189,16 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
1164
1189
HasInvalidWorksharingNesting (
1165
1190
beginDir.source , llvm::omp::nestedWorkshareErrSet);
1166
1191
break ;
1192
+ case llvm::omp::Directive::OMPD_task: {
1193
+ const auto &clauses{std::get<parser::OmpClauseList>(beginBlockDir.t )};
1194
+ for (const auto &clause : clauses.v ) {
1195
+ if (std::get_if<parser::OmpClause::Untied>(&clause.u )) {
1196
+ OmpDesignatorChecker ompDesignatorChecker{context_, beginDir.source };
1197
+ parser::Walk (block, ompDesignatorChecker);
1198
+ }
1199
+ }
1200
+ break ;
1201
+ }
1167
1202
default :
1168
1203
break ;
1169
1204
}
0 commit comments