@@ -213,6 +213,31 @@ class AssociatedLoopChecker {
213213 std::map<std::string, std::int64_t > constructNamesAndLevels_;
214214};
215215
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+
216241bool OmpStructureChecker::CheckAllowedClause (llvmOmpClause clause) {
217242 unsigned version{context_.langOptions ().OpenMPVersion };
218243 DirectiveContext &dirCtx = GetContext ();
@@ -1164,6 +1189,16 @@ void OmpStructureChecker::Enter(const parser::OpenMPBlockConstruct &x) {
11641189 HasInvalidWorksharingNesting (
11651190 beginDir.source , llvm::omp::nestedWorkshareErrSet);
11661191 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+ }
11671202 default :
11681203 break ;
11691204 }
0 commit comments