diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp index b0a632247fe10..5f351fb97e5aa 100644 --- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp +++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp @@ -143,6 +143,10 @@ std::string OpenMPCounterVisitor::getName(const OpenMPConstruct &c) { const CharBlock &source{std::get<0>(c.t).source}; return normalize_construct_name(source.ToString()); }, + [&](const OpenMPAssumeConstruct &c) -> std::string { + const CharBlock &source{std::get<0>(c.t).source}; + return normalize_construct_name(source.ToString()); + }, [&](const OpenMPAllocatorsConstruct &c) -> std::string { const CharBlock &source{std::get<0>(c.t).source}; return normalize_construct_name(source.ToString()); diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h index 75c11301285b3..30904a68ca611 100644 --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -510,6 +510,7 @@ class ParseTreeDumper { NODE_ENUM(OmpMapTypeModifier, Value) NODE(parser, OmpIteratorSpecifier) NODE(parser, OmpIterator) + NODE(parser, OmpAbsentClause) NODE(parser, OmpAffinityClause) NODE(OmpAffinityClause, Modifier) NODE(parser, OmpAlignment) @@ -543,6 +544,7 @@ class ParseTreeDumper { #define GEN_FLANG_DUMP_PARSE_TREE_CLAUSES #include "llvm/Frontend/OpenMP/OMP.inc" NODE(parser, OmpClauseList) + NODE(parser, OmpContainsClause) NODE(parser, OmpCriticalDirective) NODE(parser, OmpErrorDirective) NODE(parser, OmpNothingDirective) @@ -585,6 +587,7 @@ class ParseTreeDumper { NODE(parser, OmpExpectation) NODE_ENUM(OmpExpectation, Value) NODE(parser, OmpDirectiveNameModifier) + NODE(parser, OmpHoldsClause) NODE(parser, OmpIfClause) NODE(OmpIfClause, Modifier) NODE(parser, OmpLastprivateClause) @@ -608,6 +611,9 @@ class ParseTreeDumper { } NODE(parser, OmpObject) NODE(parser, OmpObjectList) + NODE(parser, OmpNoOpenMPClause) + NODE(parser, OmpNoOpenMPRoutinesClause) + NODE(parser, OmpNoParallelismClause) NODE(parser, OmpOrderClause) NODE(OmpOrderClause, Modifier) NODE_ENUM(OmpOrderClause, Ordering) @@ -672,6 +678,10 @@ class ParseTreeDumper { NODE(parser, OpenACCStandaloneDeclarativeConstruct) NODE(parser, OpenACCStandaloneConstruct) NODE(parser, OpenACCWaitConstruct) + NODE(parser, OpenMPAssumeConstruct) + NODE(parser, OpenMPDeclarativeAssumes) + NODE(parser, OmpAssumeDirective) + NODE(parser, OmpEndAssumeDirective) NODE(parser, OpenMPAtomicConstruct) NODE(parser, OpenMPBlockConstruct) NODE(parser, OpenMPCancelConstruct) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h index dafe46f65ed75..d3b3d69015bf3 100644 --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3953,6 +3953,16 @@ using OmpContextSelector = traits::OmpContextSelectorSpecification; // --- Clauses +using OmpDirectiveList = std::list; + +// Ref: [5.2:214] +// +// absent-clause -> +// ABSENT(directive-name[, directive-name]) +struct OmpAbsentClause { + WRAPPER_CLASS_BOILERPLATE(OmpAbsentClause, OmpDirectiveList); +}; + // Ref: [5.0:135-140], [5.1:161-166], [5.2:264-265] // // affinity-clause -> @@ -4026,6 +4036,14 @@ struct OmpBindClause { WRAPPER_CLASS_BOILERPLATE(OmpBindClause, Binding); }; +// Ref: [5.2:214] +// +// contains-clause -> +// CONTAINS(directive-name[, directive-name]) +struct OmpContainsClause { + WRAPPER_CLASS_BOILERPLATE(OmpContainsClause, OmpDirectiveList); +}; + // Ref: [4.5:46-50], [5.0:74-78], [5.1:92-96], [5.2:109] // // When used as a data-sharing clause: @@ -4198,6 +4216,14 @@ struct OmpGrainsizeClause { std::tuple t; }; +// Ref: [5.2: 214] +// +// holds-clause -> +// HOLDS(expr) +struct OmpHoldsClause { + WRAPPER_CLASS_BOILERPLATE(OmpHoldsClause, common::Indirection); +}; + // Ref: [5.2:72-73], in 4.5-5.1 it's scattered over individual directives // that allow the IF clause. // @@ -4279,6 +4305,21 @@ struct OmpMessageClause { WRAPPER_CLASS_BOILERPLATE(OmpMessageClause, Expr); }; +// Ref: [5.2: 214] +// +// no_openmp_clause -> NO_OPENMP +EMPTY_CLASS(OmpNoOpenMPClause); + +// Ref: [5.2: 214] +// +// no_openmp_routines_clause -> NO_OPENMP_ROUTINES +EMPTY_CLASS(OmpNoOpenMPRoutinesClause); + +// Ref: [5.2: 214] +// +// no_parallelism_clause -> NO_PARALELISM +EMPTY_CLASS(OmpNoParallelismClause); + // Ref: [4.5:87-91], [5.0:140-146], [5.1:166-171], [5.2:270] // // num-tasks-clause -> @@ -4473,6 +4514,41 @@ struct OpenMPUtilityConstruct { std::variant u; }; +// Ref: [5.2: 213-216] +// +// assumes-construct -> +// ASSUMES absent-clause | contains-clause | holds-clause | no-openmp-clause | +// no-openmp-routines-clause | no-parallelism-clause +struct OpenMPDeclarativeAssumes { + TUPLE_CLASS_BOILERPLATE(OpenMPDeclarativeAssumes); + std::tuple t; + CharBlock source; +}; + +struct OmpAssumeDirective { + TUPLE_CLASS_BOILERPLATE(OmpAssumeDirective); + std::tuple t; + CharBlock source; +}; + +struct OmpEndAssumeDirective { + WRAPPER_CLASS_BOILERPLATE(OmpEndAssumeDirective, Verbatim); + CharBlock source; +}; + +// Ref: [5.2: 213-216] +// +// assume-construct -> +// ASSUME absent-clause | contains-clause | holds_clause | no-openmp-clause +// no-openmp-routines-clause | no-parallelism-clause +// block +// [END ASSUME] +struct OpenMPAssumeConstruct { + TUPLE_CLASS_BOILERPLATE(OpenMPAssumeConstruct); + std::tuple> t; + CharBlock source; +}; + // 2.7.2 SECTIONS // 2.11.2 PARALLEL SECTIONS struct OmpSectionsDirective { @@ -4595,10 +4671,11 @@ struct OpenMPDeclarativeAllocate { struct OpenMPDeclarativeConstruct { UNION_CLASS_BOILERPLATE(OpenMPDeclarativeConstruct); CharBlock source; - std::variant + OmpMetadirectiveDirective> u; }; @@ -4885,7 +4962,7 @@ struct OpenMPConstruct { OpenMPSectionConstruct, OpenMPLoopConstruct, OpenMPBlockConstruct, OpenMPAtomicConstruct, OpenMPDeclarativeAllocate, OpenMPDispatchConstruct, OpenMPUtilityConstruct, OpenMPExecutableAllocate, - OpenMPAllocatorsConstruct, OpenMPCriticalConstruct> + OpenMPAllocatorsConstruct, OpenMPAssumeConstruct, OpenMPCriticalConstruct> u; }; diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp index e0d23fc53eeca..4be8614ca2acb 100644 --- a/flang/lib/Lower/OpenMP/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP/OpenMP.cpp @@ -367,6 +367,9 @@ extractOmpDirective(const parser::OpenMPConstruct &ompConstruct) { [](const parser::OpenMPAllocatorsConstruct &c) { return llvm::omp::OMPD_allocators; }, + [](const parser::OpenMPAssumeConstruct &c) { + return llvm::omp::OMPD_assume; + }, [](const parser::OpenMPAtomicConstruct &c) { return llvm::omp::OMPD_atomic; }, @@ -3101,6 +3104,13 @@ genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, TODO(converter.getCurrentLocation(), "OpenMPDeclarativeAllocate"); } +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPDeclarativeAssumes &assumesConstruct) { + TODO(converter.getCurrentLocation(), "OpenMP ASSUMES declaration"); +} + static void genOMP( lower::AbstractConverter &converter, lower::SymMap &symTable, semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, @@ -3445,6 +3455,14 @@ static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, queue.begin()); } +static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, + semantics::SemanticsContext &semaCtx, + lower::pft::Evaluation &eval, + const parser::OpenMPAssumeConstruct &assumeConstruct) { + mlir::Location clauseLocation = converter.genLocation(assumeConstruct.source); + TODO(clauseLocation, "OpenMP ASSUME construct"); +} + static void genOMP(lower::AbstractConverter &converter, lower::SymMap &symTable, semantics::SemanticsContext &semaCtx, lower::pft::Evaluation &eval, diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp index b39b8737b70c0..014b4f8c69574 100644 --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -773,7 +773,14 @@ TYPE_PARSER(construct( TYPE_PARSER(construct(expr)) -TYPE_PARSER( +TYPE_PARSER(construct(indirect(expr))) +TYPE_PARSER(construct(many(maybe(","_tok) >> + construct(OmpDirectiveNameParser{})))) +TYPE_PARSER(construct(many(maybe(","_tok) >> + construct(OmpDirectiveNameParser{})))) + +TYPE_PARSER("ABSENT" >> construct(construct( + parenthesized(Parser{}))) || "ACQUIRE" >> construct(construct()) || "ACQ_REL" >> construct(construct()) || "AFFINITY" >> construct(construct( @@ -795,6 +802,8 @@ TYPE_PARSER( parenthesized(Parser{}))) || "COLLAPSE" >> construct(construct( parenthesized(scalarIntConstantExpr))) || + "CONTAINS" >> construct(construct( + parenthesized(Parser{}))) || "COPYIN" >> construct(construct( parenthesized(Parser{}))) || "COPYPRIVATE" >> construct(construct( @@ -839,6 +848,8 @@ TYPE_PARSER( parenthesized(Parser{}))) || "HINT" >> construct( construct(parenthesized(constantExpr))) || + "HOLDS" >> construct(construct( + parenthesized(Parser{}))) || "IF" >> construct(construct( parenthesized(Parser{}))) || "INBRANCH" >> construct(construct()) || @@ -869,6 +880,11 @@ TYPE_PARSER( "NOVARIANTS" >> construct(construct( parenthesized(scalarLogicalExpr))) || "NOWAIT" >> construct(construct()) || + "NO_OPENMP"_id >> construct(construct()) || + "NO_OPENMP_ROUTINES" >> + construct(construct()) || + "NO_PARALLELISM" >> + construct(construct()) || "NUM_TASKS" >> construct(construct( parenthesized(Parser{}))) || "NUM_TEAMS" >> construct(construct( @@ -1299,28 +1315,45 @@ TYPE_PARSER( parenthesized(Parser{}), Parser{})) / lookAhead(endOmpLine / !statement(allocateStmt))) +// Assumes Construct +TYPE_PARSER(sourced(construct( + verbatim("ASSUMES"_tok), Parser{}))) + // Declarative constructs -TYPE_PARSER(startOmpLine >> - withMessage("expected OpenMP construct"_err_en_US, - sourced(construct( - Parser{}) || - construct( - Parser{}) || - construct( - Parser{}) || - construct( - Parser{}) || - construct( - Parser{}) || - construct( - Parser{}) || - construct( - Parser{}) || - construct( - Parser{}) || - construct( - Parser{})) / - endOmpLine)) +TYPE_PARSER( + startOmpLine >> withMessage("expected OpenMP construct"_err_en_US, + sourced(construct( + Parser{}) || + construct( + Parser{}) || + construct( + Parser{}) || + construct( + Parser{}) || + construct( + Parser{}) || + construct( + Parser{}) || + construct( + Parser{}) || + construct( + Parser{}) || + construct( + Parser{}) || + construct( + Parser{})) / + endOmpLine)) + +// Assume Construct +TYPE_PARSER(sourced(construct( + verbatim("ASSUME"_tok), Parser{}))) + +TYPE_PARSER(sourced(construct( + verbatim(startOmpLine >> "END ASSUME"_tok)))) + +TYPE_PARSER(sourced( + construct(Parser{} / endOmpLine, + block, maybe(Parser{} / endOmpLine)))) // Block Construct TYPE_PARSER(construct( @@ -1369,6 +1402,7 @@ TYPE_CONTEXT_PARSER("OpenMP construct"_en_US, construct(Parser{}), construct(Parser{}), construct(Parser{}), + construct(Parser{}), construct(Parser{})))) // END OMP Block directives diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp index 6260a01897527..960337b8a91b5 100644 --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2179,6 +2179,8 @@ class UnparseVisitor { Walk(std::get>>(x.t), ": "); Walk(std::get(x.t)); } + void Unparse(const OmpAbsentClause &x) { Walk("", x.v, ","); } + void Unparse(const OmpContainsClause &x) { Walk("", x.v, ","); } void Unparse(const OmpAffinityClause &x) { using Modifier = OmpAffinityClause::Modifier; Walk(std::get>>(x.t), ": "); @@ -2662,6 +2664,18 @@ class UnparseVisitor { Walk(*end); } } + void Unparse(const OmpAssumeDirective &x) { + BeginOpenMP(); + Word("!$OMP ASSUME"); + Walk(" ", std::get(x.t).v); + Put("\n"); + EndOpenMP(); + } + void Unparse(const OmpEndAssumeDirective &x) { + BeginOpenMP(); + Word("!$OMP END ASSUME\n"); + EndOpenMP(); + } void Unparse(const OmpCriticalDirective &x) { BeginOpenMP(); Word("!$OMP CRITICAL"); @@ -2700,7 +2714,13 @@ class UnparseVisitor { Put("\n"); EndOpenMP(); } - + void Unparse(const OpenMPDeclarativeAssumes &x) { + BeginOpenMP(); + Word("!$OMP ASSUMES "); + Walk(std::get(x.t)); + Put("\n"); + EndOpenMP(); + } void Unparse(const OpenMPDeclareMapperConstruct &z) { BeginOpenMP(); Word("!$OMP DECLARE MAPPER ("); @@ -2868,7 +2888,9 @@ class UnparseVisitor { Put("\n"); EndOpenMP(); } - void Unparse(const OmpClauseList &x) { Walk(" ", x.v, " "); } + void Unparse(const OmpClauseList &x, const char *sep = " ") { + Walk(" ", x.v, sep); + } void Unparse(const OpenMPSimpleStandaloneConstruct &x) { BeginOpenMP(); Word("!$OMP "); diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp index ef7204dcd9196..c95cf0d5921cf 100644 --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -1251,6 +1251,22 @@ void OmpStructureChecker::CheckMasterNesting( } } +void OmpStructureChecker::Enter(const parser::OpenMPAssumeConstruct &x) { + PushContextAndClauseSets(x.source, llvm::omp::Directive::OMPD_assume); +} + +void OmpStructureChecker::Leave(const parser::OpenMPAssumeConstruct &) { + dirContext_.pop_back(); +} + +void OmpStructureChecker::Enter(const parser::OpenMPDeclarativeAssumes &x) { + PushContextAndClauseSets(x.source, llvm::omp::Directive::OMPD_assumes); +} + +void OmpStructureChecker::Leave(const parser::OpenMPDeclarativeAssumes &) { + dirContext_.pop_back(); +} + void OmpStructureChecker::Leave(const parser::OpenMPBlockConstruct &) { if (GetDirectiveNest(TargetBlockOnlyTeams)) { ExitDirectiveNest(TargetBlockOnlyTeams); diff --git a/flang/lib/Semantics/check-omp-structure.h b/flang/lib/Semantics/check-omp-structure.h index a9ac93a9149d4..63278616bbf5b 100644 --- a/flang/lib/Semantics/check-omp-structure.h +++ b/flang/lib/Semantics/check-omp-structure.h @@ -81,6 +81,10 @@ class OmpStructureChecker void Enter(const parser::OmpEndLoopDirective &); void Leave(const parser::OmpEndLoopDirective &); + void Enter(const parser::OpenMPAssumeConstruct &); + void Leave(const parser::OpenMPAssumeConstruct &); + void Enter(const parser::OpenMPDeclarativeAssumes &); + void Leave(const parser::OpenMPDeclarativeAssumes &); void Enter(const parser::OpenMPBlockConstruct &); void Leave(const parser::OpenMPBlockConstruct &); void Leave(const parser::OmpBeginBlockDirective &); diff --git a/flang/test/Lower/OpenMP/Todo/assume.f90 b/flang/test/Lower/OpenMP/Todo/assume.f90 new file mode 100644 index 0000000000000..1216888efabd1 --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/assume.f90 @@ -0,0 +1,10 @@ +! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s + +! CHECK: not yet implemented: OpenMP ASSUME construct +program p + integer r + r = 1 +!$omp assume no_parallelism + print *,r +!$omp end assume +end program p diff --git a/flang/test/Lower/OpenMP/Todo/assumes.f90 b/flang/test/Lower/OpenMP/Todo/assumes.f90 new file mode 100644 index 0000000000000..ac26ed14ded3c --- /dev/null +++ b/flang/test/Lower/OpenMP/Todo/assumes.f90 @@ -0,0 +1,6 @@ +! RUN: %not_todo_cmd %flang_fc1 -emit-fir -fopenmp -fopenmp-version=51 -o - %s 2>&1 | FileCheck %s + +! CHECK: not yet implemented: OpenMP ASSUMES declaration +program p + !$omp assumes no_openmp +end program p diff --git a/flang/test/Parser/OpenMP/assumption.f90 b/flang/test/Parser/OpenMP/assumption.f90 new file mode 100644 index 0000000000000..f1cb0c87e1262 --- /dev/null +++ b/flang/test/Parser/OpenMP/assumption.f90 @@ -0,0 +1,59 @@ +! RUN: %flang_fc1 -fopenmp-version=51 -fopenmp -fdebug-unparse-no-sema %s 2>&1 | FileCheck %s +! RUN: %flang_fc1 -fopenmp-version=51 -fopenmp -fdebug-dump-parse-tree-no-sema %s 2>&1 | FileCheck %s --check-prefix="PARSE-TREE" +subroutine sub1 + integer :: r +!CHECK: !$OMP ASSUME NO_OPENMP +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAssumeConstruct +!PARSE-TREE: Verbatim +!PARSE-TREE: OmpClauseList -> OmpClause -> NoOpenmp + !$omp assume no_openmp +!CHECK: !$OMP ASSUME NO_PARALLELISM +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAssumeConstruct +!PARSE-TREE: Verbatim +!PARSE-TREE: OmpClauseList -> OmpClause -> NoParallelism + !$omp assume no_parallelism +!CHECK: !$OMP ASSUME NO_OPENMP_ROUTINES +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAssumeConstruct +!PARSE-TREE: Verbatim +!PARSE-TREE: OmpClauseList -> OmpClause -> NoOpenmpRoutines + !$omp assume no_openmp_routines +!CHECK: !$OMP ASSUME ABSENT(ALLOCATE), CONTAINS(WORKSHARE,TASK) +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAssumeConstruct +!PARSE-TREE: Verbatim +!PARSE-TREE: OmpClauseList -> OmpClause -> Absent -> OmpAbsentClause -> llvm::omp::Directive = allocate +!PARSE-TREE: OmpClause -> Contains -> OmpContainsClause -> llvm::omp::Directive = workshare +!PARSE-TREE: llvm::omp::Directive = task + !$omp assume absent(allocate), contains(workshare, task) +!CHECK: !$OMP ASSUME HOLDS(1==1) + !$omp assume holds(1.eq.1) + print *, r +end subroutine sub1 + +subroutine sub2 + integer :: r + integer :: v +!CHECK !$OMP ASSUME NO_OPENMP +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPAssumeConstruct +!PARSE-TREE: OmpAssumeDirective +!PARSE-TREE: Verbatim +!PARSE-TREE: OmpClauseList -> OmpClause -> NoOpenmp +!PARSE-TREE: Block +!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> AssignmentStmt +!PARSE-TREE: Expr -> Add +!PARSE-TREE: OmpEndAssumeDirective + v = 87 + !$omp assume no_openmp + r = r + 1 +!CHECK !$OMP END ASSUME + !$omp end assume +end subroutine sub2 + +program p +!CHECK !$OMP ASSUMES NO_OPENMP +!PARSE-TREE: SpecificationPart +!PARSE-TREE: OpenMPDeclarativeConstruct -> OpenMPDeclarativeAssumes +!PARSE-TREE: Verbatim +!PARSE-TREE: OmpClauseList -> OmpClause -> NoOpenmp + !$omp assumes no_openmp +end program p + diff --git a/llvm/include/llvm/Frontend/OpenMP/OMP.td b/llvm/include/llvm/Frontend/OpenMP/OMP.td index 210acbff5af20..39fd46bcbd4ee 100644 --- a/llvm/include/llvm/Frontend/OpenMP/OMP.td +++ b/llvm/include/llvm/Frontend/OpenMP/OMP.td @@ -34,6 +34,7 @@ def OpenMP : DirectiveLanguage { def OMPC_Absent : Clause<"absent"> { let clangClass = "OMPAbsentClause"; + let flangClass = "OmpAbsentClause"; } def OMPC_Acquire : Clause<"acquire"> { let clangClass = "OMPAcquireClause"; @@ -107,6 +108,7 @@ def OMPC_CancellationConstructType : Clause<"cancellation_construct_type"> { } def OMPC_Contains : Clause<"contains"> { let clangClass = "OMPContainsClause"; + let flangClass = "OmpContainsClause"; } def OMPC_Capture : Clause<"capture"> { let clangClass = "OMPCaptureClause"; @@ -225,6 +227,7 @@ def OMPC_Hint : Clause<"hint"> { } def OMPC_Holds : Clause<"holds"> { let clangClass = "OMPHoldsClause"; + let flangClass = "OmpHoldsClause"; } def OMPC_If : Clause<"if"> { let clangClass = "OMPIfClause"; @@ -562,6 +565,14 @@ def OMP_Allocators : Directive<"allocators"> { def OMP_Assumes : Directive<"assumes"> { let association = AS_None; let category = CA_Informational; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + ]; } def OMP_EndAssumes : Directive<"end assumes"> { let association = AS_Delimited; @@ -608,6 +619,14 @@ def OMP_Barrier : Directive<"barrier"> { def OMP_BeginAssumes : Directive<"begin assumes"> { let association = AS_Delimited; let category = CA_Informational; + let allowedOnceClauses = [ + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + VersionedClause, + ]; } def OMP_BeginDeclareTarget : Directive<"begin declare target"> { let allowedClauses = [