@@ -336,6 +336,16 @@ class OmpUnitedTaskDesignatorChecker {
336336 SemanticsContext &context_;
337337};
338338
339+ bool OmpStructureChecker::IsAllowedClause (llvm::omp::Clause clauseId) {
340+ // Do not do clause checks while processing METADIRECTIVE.
341+ // See comment in CheckAllowedClause.
342+ if (GetDirectiveNest (ContextSelectorNest) > 0 ) {
343+ return true ;
344+ }
345+ return llvm::omp::isAllowedClauseForDirective (
346+ GetContext ().directive , clauseId, context_.langOptions ().OpenMPVersion );
347+ }
348+
339349bool OmpStructureChecker::CheckAllowedClause (llvmOmpClause clause) {
340350 // Do not do clause checks while processing METADIRECTIVE.
341351 // Context selectors can contain clauses that are not given as a part
@@ -772,6 +782,9 @@ void OmpStructureChecker::Enter(const parser::OpenMPConstruct &x) {
772782 return CheckDirectiveSpelling (source, id);
773783 });
774784 parser::Walk (x, visitor);
785+ if (GetOmpDirectiveName (x).v != llvm::omp::Directive::OMPD_section) {
786+ dirStack_.push_back (&GetOmpDirectiveSpecification (x));
787+ }
775788
776789 // Simd Construct with Ordered Construct Nesting check
777790 // We cannot use CurrentDirectiveIsNested() here because
@@ -788,12 +801,15 @@ void OmpStructureChecker::Enter(const parser::OpenMPConstruct &x) {
788801 }
789802}
790803
791- void OmpStructureChecker::Leave (const parser::OpenMPConstruct &) {
804+ void OmpStructureChecker::Leave (const parser::OpenMPConstruct &x ) {
792805 for (const auto &[sym, source] : deferredNonVariables_) {
793806 context_.SayWithDecl (
794807 *sym, source, " '%s' must be a variable" _err_en_US, sym->name ());
795808 }
796809 deferredNonVariables_.clear ();
810+ if (GetOmpDirectiveName (x).v != llvm::omp::Directive::OMPD_section) {
811+ dirStack_.pop_back ();
812+ }
797813}
798814
799815void OmpStructureChecker::Enter (const parser::OpenMPDeclarativeConstruct &x) {
@@ -803,11 +819,13 @@ void OmpStructureChecker::Enter(const parser::OpenMPDeclarativeConstruct &x) {
803819 });
804820 parser::Walk (x, visitor);
805821
822+ dirStack_.push_back (&GetOmpDirectiveSpecification (x));
806823 EnterDirectiveNest (DeclarativeNest);
807824}
808825
809826void OmpStructureChecker::Leave (const parser::OpenMPDeclarativeConstruct &x) {
810827 ExitDirectiveNest (DeclarativeNest);
828+ dirStack_.pop_back ();
811829}
812830
813831void OmpStructureChecker::AddEndDirectiveClauses (
@@ -2010,6 +2028,50 @@ void OmpStructureChecker::Enter(const parser::OmpClause::Allocate &x) {
20102028 }
20112029 }
20122030 }
2031+
2032+ // If the clause is not allowed, don't diagnose specific problems with it.
2033+ if (!IsAllowedClause (llvm::omp::Clause::OMPC_allocate)) {
2034+ return ;
2035+ }
2036+
2037+ llvm::omp::Directive dirId{GetContext ().directive };
2038+ // For any list item that is specified in the allocate clause on a directive
2039+ // other than the allocators directive, a data-sharing attribute clause that
2040+ // may create a private copy of that list item must be specified on the same
2041+ // directive.
2042+ if (dirId != llvm::omp::Directive::OMPD_allocators &&
2043+ dirId != llvm::omp::Directive::OMPD_section) {
2044+ static llvm::omp::Clause privatizingDSAClauses[] = {
2045+ llvm::omp::Clause::OMPC_private,
2046+ llvm::omp::Clause::OMPC_firstprivate,
2047+ llvm::omp::Clause::OMPC_lastprivate,
2048+ llvm::omp::Clause::OMPC_is_device_ptr,
2049+ llvm::omp::Clause::OMPC_use_device_ptr,
2050+ };
2051+ const parser::OmpDirectiveSpecification &spec{*dirStack_.back ()};
2052+
2053+ std::set<const Symbol *> privatized;
2054+ for (auto dsaClause : privatizingDSAClauses) {
2055+ if (auto *found{parser::omp::FindClause (spec, dsaClause)}) {
2056+ for (auto &object : GetOmpObjectList (*found)->v ) {
2057+ if (auto *symbol{GetObjectSymbol (object)}) {
2058+ privatized.insert (symbol);
2059+ }
2060+ }
2061+ }
2062+ }
2063+
2064+ for (auto &object : GetOmpObjectList (x)->v ) {
2065+ if (auto *symbol{GetObjectSymbol (object)}) {
2066+ if (!privatized.count (symbol)) {
2067+ context_.Say (
2068+ GetObjectSource (object).value_or (GetContext ().clauseSource ),
2069+ " The ALLOCATE clause requires that '%s' must be listed in a private data-sharing attribute clause on the same directive" _err_en_US,
2070+ symbol->name ());
2071+ }
2072+ }
2073+ }
2074+ }
20132075}
20142076
20152077void OmpStructureChecker::Enter (const parser::OpenMPDeclareMapperConstruct &x) {
0 commit comments