diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp --- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp +++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp @@ -85,6 +85,10 @@ }, c.u); }, + [&](const OpenMPSectionConstruct &c) -> SourcePosition { + const CharBlock &source{c.source}; + return (parsing->allCooked().GetSourcePositionRange(source))->first; + }, }, c.u); } @@ -134,6 +138,9 @@ }, c.u); }, + [&](const OpenMPSectionConstruct &c) -> std::string { + return "section"; + }, // OpenMPSectionsConstruct, OpenMPLoopConstruct, // OpenMPBlockConstruct, OpenMPCriticalConstruct Get the source from // the directive field of the begin directive or from the verbatim diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h --- a/flang/include/flang/Parser/dump-parse-tree.h +++ b/flang/include/flang/Parser/dump-parse-tree.h @@ -562,6 +562,7 @@ NODE(parser, OpenMPExecutableAllocate) NODE(parser, OpenMPSimpleStandaloneConstruct) NODE(parser, OpenMPStandaloneConstruct) + NODE(parser, OpenMPSectionConstruct) NODE(parser, OpenMPSectionsConstruct) NODE(parser, OpenMPThreadprivate) NODE(parser, OpenStmt) diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h --- a/flang/include/flang/Parser/parse-tree.h +++ b/flang/include/flang/Parser/parse-tree.h @@ -3515,7 +3515,15 @@ // [!$omp section // structured-block] // ... -WRAPPER_CLASS(OmpSectionBlocks, std::list); +struct OpenMPSectionConstruct { + WRAPPER_CLASS_BOILERPLATE(OpenMPSectionConstruct, Block); + CharBlock source; +}; + +// `OmpSectionBlocks` is a list of section constructs. The parser guarentees +// that the `OpenMPConstruct` here always encapsulates an +// `OpenMPSectionConstruct` and not any other OpenMP construct. +WRAPPER_CLASS(OmpSectionBlocks, std::list); struct OpenMPSectionsConstruct { TUPLE_CLASS_BOILERPLATE(OpenMPSectionsConstruct); @@ -3817,9 +3825,9 @@ struct OpenMPConstruct { UNION_CLASS_BOILERPLATE(OpenMPConstruct); std::variant + OpenMPSectionConstruct, OpenMPLoopConstruct, OpenMPBlockConstruct, + OpenMPAtomicConstruct, OpenMPDeclarativeAllocate, + OpenMPExecutableAllocate, OpenMPCriticalConstruct> u; }; diff --git a/flang/lib/Lower/OpenMP.cpp b/flang/lib/Lower/OpenMP.cpp --- a/flang/lib/Lower/OpenMP.cpp +++ b/flang/lib/Lower/OpenMP.cpp @@ -217,6 +217,9 @@ §ionsConstruct) { TODO(converter.getCurrentLocation(), "OpenMPSectionsConstruct"); }, + [&](const Fortran::parser::OpenMPSectionConstruct §ionConstruct) { + TODO(converter.getCurrentLocation(), "OpenMPSectionConstruct"); + }, [&](const Fortran::parser::OpenMPLoopConstruct &loopConstruct) { TODO(converter.getCurrentLocation(), "OpenMPLoopConstruct"); }, diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp --- a/flang/lib/Parser/openmp-parsers.cpp +++ b/flang/lib/Parser/openmp-parsers.cpp @@ -529,11 +529,15 @@ Parser{}))) // OMP SECTION-BLOCK + +TYPE_PARSER(construct(block)) + TYPE_PARSER(maybe(startOmpLine >> "SECTION"_tok / endOmpLine) >> - construct( - nonemptySeparated(block, startOmpLine >> "SECTION"_tok / endOmpLine))) + construct(nonemptySeparated( + construct(sourced(Parser{})), + startOmpLine >> "SECTION"_tok / endOmpLine))) -// OMP SECTIONS (2.7.2), PARALLEL SECTIONS (2.11.2) +// OMP SECTIONS (OpenMP 5.0 - 2.8.1), PARALLEL SECTIONS (OpenMP 5.0 - 2.13.3) TYPE_PARSER(construct( Parser{} / endOmpLine, Parser{}, Parser{} / endOmpLine)) diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp --- a/flang/lib/Parser/unparse.cpp +++ b/flang/lib/Parser/unparse.cpp @@ -2405,7 +2405,9 @@ Word("!$OMP SECTION"); Put("\n"); EndOpenMP(); - Walk(y, ""); // y is Block + // y.u is an OpenMPSectionConstruct + // (y.u).v is Block + Walk(std::get(y.u).v, ""); } } void Unparse(const OpenMPSectionsConstruct &x) { diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp --- a/flang/lib/Semantics/check-omp-structure.cpp +++ b/flang/lib/Semantics/check-omp-structure.cpp @@ -801,8 +801,9 @@ PushContextAndClauseSets(beginDir.source, beginDir.v); const auto §ionBlocks{std::get(x.t)}; - for (const auto &block : sectionBlocks.v) { - CheckNoBranching(block, beginDir.v, beginDir.source); + for (const parser::OpenMPConstruct &block : sectionBlocks.v) { + CheckNoBranching(std::get(block.u).v, + beginDir.v, beginDir.source); } HasInvalidWorksharingNesting( beginDir.source, llvm::omp::nestedWorkshareErrSet); diff --git a/flang/test/Examples/omp-sections.f90 b/flang/test/Examples/omp-sections.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Examples/omp-sections.f90 @@ -0,0 +1,30 @@ +! REQUIRES: plugins, examples, shell + +! RUN: %flang_fc1 -load %llvmshlibdir/flangOmpReport.so -plugin flang-omp-report -fopenmp %s -o - | FileCheck %s + +subroutine omp_sections() + integer :: x + !$omp sections private(x) + !$omp section + call f1() + !$omp section + call f2() + !$omp end sections nowait +end subroutine omp_sections + +!CHECK: - file: {{.*}} +!CHECK: line: 9 +!CHECK: construct: section +!CHECK: clauses: [] +!CHECK: - file: {{.*}} +!CHECK: line: 11 +!CHECK: construct: section +!CHECK: clauses: [] +!CHECK: - file: {{.*}} +!CHECK: line: 7 +!CHECK: construct: sections +!CHECK: clauses: +!CHECK: - clause: nowait +!CHECK: details: '' +!CHECK: - clause: private +!CHECK: details: x diff --git a/flang/test/Lower/OpenMP/sections-pft.f90 b/flang/test/Lower/OpenMP/sections-pft.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Lower/OpenMP/sections-pft.f90 @@ -0,0 +1,91 @@ +! RUN: %flang_fc1 -fdebug-pre-fir-tree -fopenmp %s | FileCheck %s + +subroutine openmp_sections(x, y) + + integer, intent(inout)::x, y + +!============================================================================== +! empty construct +!============================================================================== +!$omp sections +!$omp end sections + +!CHECK: OpenMPConstruct +!CHECK: End OpenMPConstruct + +!============================================================================== +! single section, without `!$omp section` +!============================================================================== +!$omp sections + call F1() +!$omp end sections + +!CHECK: OpenMPConstruct +!CHECK: OpenMPConstruct +!CHECK: CallStmt +!CHECK: End OpenMPConstruct +!CHECK: End OpenMPConstruct + +!============================================================================== +! single section with `!$omp section` +!============================================================================== +!$omp sections + !$omp section + call F1 +!$omp end sections + +!CHECK: OpenMPConstruct +!CHECK: OpenMPConstruct +!CHECK: CallStmt +!CHECK: End OpenMPConstruct +!CHECK: End OpenMPConstruct + +!============================================================================== +! multiple sections +!============================================================================== +!$omp sections + !$omp section + call F1 + !$omp section + call F2 + !$omp section + call F3 +!$omp end sections + +!CHECK: OpenMPConstruct +!CHECK: OpenMPConstruct +!CHECK: CallStmt +!CHECK: End OpenMPConstruct +!CHECK: OpenMPConstruct +!CHECK: CallStmt +!CHECK: End OpenMPConstruct +!CHECK: OpenMPConstruct +!CHECK: CallStmt +!CHECK: End OpenMPConstruct +!CHECK: End OpenMPConstruct + +!============================================================================== +! multiple sections with clauses +!============================================================================== +!$omp sections PRIVATE(x) FIRSTPRIVATE(y) + !$omp section + call F1 + !$omp section + call F2 + !$omp section + call F3 +!$omp end sections NOWAIT + +!CHECK: OpenMPConstruct +!CHECK: OpenMPConstruct +!CHECK: CallStmt +!CHECK: End OpenMPConstruct +!CHECK: OpenMPConstruct +!CHECK: CallStmt +!CHECK: End OpenMPConstruct +!CHECK: OpenMPConstruct +!CHECK: CallStmt +!CHECK: End OpenMPConstruct +!CHECK: End OpenMPConstruct + +end subroutine openmp_sections diff --git a/flang/test/Parser/omp-sections.f90 b/flang/test/Parser/omp-sections.f90 new file mode 100644 --- /dev/null +++ b/flang/test/Parser/omp-sections.f90 @@ -0,0 +1,121 @@ +! RUN: %flang_fc1 -fdebug-unparse -fopenmp %s | FileCheck --ignore-case %s +! RUN: %flang_fc1 -fdebug-dump-parse-tree -fopenmp %s | FileCheck --check-prefix="PARSE-TREE" %s + +subroutine openmp_sections(x, y) + + integer, intent(inout)::x, y + +!============================================================================== +! empty construct +!============================================================================== +!CHECK: !$omp sections +!$omp sections + !CHECK: !$omp section +!CHECK: !$omp end sections +!$omp end sections + +!PARSE-TREE: OpenMPConstruct -> OpenMPSectionsConstruct +!PARSE-TREE: OmpBeginSectionsDirective +!PARSE-TREE-NOT: ExecutionPartConstruct +!PARSE-TREE: OmpEndSectionsDirective + +!============================================================================== +! single section, without `!$omp section` +!============================================================================== +!CHECK: !$omp sections +!$omp sections + !CHECK: !$omp section + !CHECK: CALL + call F1() +!CHECK: !$omp end sections +!$omp end sections + +!PARSE-TREE: OpenMPConstruct -> OpenMPSectionsConstruct +!PARSE-TREE: OmpBeginSectionsDirective +!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block +!PARSE-TREE: CallStmt +!PARSE-TREE-NOT: ExecutionPartConstruct +!PARSE-TREE: OmpEndSectionsDirective + +!============================================================================== +! single section with `!$omp section` +!============================================================================== +!CHECK: !$omp sections +!$omp sections + !CHECK: !$omp section + !$omp section + !CHECK: CALL F1 + call F1 +!CHECK: !$omp end sections +!$omp end sections + +!PARSE-TREE: OpenMPConstruct -> OpenMPSectionsConstruct +!PARSE-TREE: OmpBeginSectionsDirective +!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block +!PARSE-TREE: CallStmt +!PARSE-TREE-NOT: ExecutionPartConstruct +!PARSE-TREE: OmpEndSectionsDirective + +!============================================================================== +! multiple sections +!============================================================================== +!CHECK: !$omp sections +!$omp sections + !CHECK: !$omp section + !$omp section + !CHECK: CALL F1 + call F1 + !CHECK: !$omp section + !$omp section + !CHECK: CALL F2 + call F2 + !CHECK: !$omp section + !$omp section + !CHECK: CALL F3 + call F3 +!CHECK: !$omp end sections +!$omp end sections + +!PARSE-TREE: OpenMPConstruct -> OpenMPSectionsConstruct +!PARSE-TREE: OmpBeginSectionsDirective +!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block +!PARSE-TREE: CallStmt +!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block +!PARSE-TREE: CallStmt +!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block +!PARSE-TREE: CallStmt +!PARSE-TREE-NOT: ExecutionPartConstruct +!PARSE-TREE: OmpEndSectionsDirective + +!============================================================================== +! multiple sections with clauses +!============================================================================== +!CHECK: !$omp sections PRIVATE(x) FIRSTPRIVATE(y) +!$omp sections PRIVATE(x) FIRSTPRIVATE(y) + !CHECK: !$omp section + !$omp section + !CHECK: CALL F1 + call F1 + !CHECK: !$omp section + !$omp section + !CHECK: CALL F2 + call F2 + !CHECK: !$omp section + !$omp section + !CHECK: CALL F3 + call F3 +!CHECK: !$omp end sections NOWAIT +!$omp end sections NOWAIT + +!PARSE-TREE: OpenMPConstruct -> OpenMPSectionsConstruct +!PARSE-TREE: OmpBeginSectionsDirective +!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block +!PARSE-TREE: CallStmt +!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block +!PARSE-TREE: CallStmt +!PARSE-TREE: OpenMPConstruct -> OpenMPSectionConstruct -> Block +!PARSE-TREE: CallStmt +!PARSE-TREE-NOT: ExecutionPartConstruct +!PARSE-TREE: OmpEndSectionsDirective + +END subroutine openmp_sections