[llvm-branch-commits] [flang] [flang][OpenMP] Store directive information in OpenMPSectionConstruct (PR #150804)

Krzysztof Parzyszek via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Sat Jul 26 15:14:55 PDT 2025


https://github.com/kparzysz created https://github.com/llvm/llvm-project/pull/150804

The OpenMPSectionConstruct corresponds to the `!$omp section` directive, but there is nothing in the AST node that stores the directive information. Even though the only possibility (at the moment) is "section" without any clauses, for improved generality it is helpful to have that information anyway.

>From 4f48c1cfef2a5e75055aaaa6a1a2bace5ae0c871 Mon Sep 17 00:00:00 2001
From: Krzysztof Parzyszek <Krzysztof.Parzyszek at amd.com>
Date: Fri, 25 Jul 2025 13:30:31 -0500
Subject: [PATCH] [flang][OpenMP] Store directive information in
 OpenMPSectionConstruct

The OpenMPSectionConstruct corresponds to `!$omp section` directive, but
there is nothing in the AST node that stores the directive information.
Even though the only possibility (at the moment) is "section" without any
clauses, for improved generality it is helpful to have that information
anyway.
---
 flang/examples/FeatureList/FeatureList.cpp    |   1 -
 .../FlangOmpReport/FlangOmpReportVisitor.cpp  |  57 +------
 flang/include/flang/Parser/dump-parse-tree.h  |   1 -
 flang/include/flang/Parser/openmp-utils.h     |   8 +
 flang/include/flang/Parser/parse-tree.h       |  13 +-
 flang/lib/Lower/OpenMP/OpenMP.cpp             |   4 +-
 flang/lib/Parser/openmp-parsers.cpp           |  54 +++++--
 flang/lib/Parser/unparse.cpp                  |  14 +-
 flang/lib/Semantics/check-omp-structure.cpp   |   9 +-
 flang/test/Examples/omp-sections.f90          |   4 +-
 flang/test/Parser/OpenMP/sections.f90         | 144 +++++++++++++-----
 11 files changed, 183 insertions(+), 126 deletions(-)

diff --git a/flang/examples/FeatureList/FeatureList.cpp b/flang/examples/FeatureList/FeatureList.cpp
index e9aeed18ab0b7..64b57b633feaf 100644
--- a/flang/examples/FeatureList/FeatureList.cpp
+++ b/flang/examples/FeatureList/FeatureList.cpp
@@ -529,7 +529,6 @@ struct NodeVisitor {
   READ_FEATURE(OmpChunkModifier::Value)
   READ_FEATURE(OmpOrderingModifier)
   READ_FEATURE(OmpOrderingModifier::Value)
-  READ_FEATURE(OmpSectionBlocks)
   READ_FEATURE(OmpSectionsDirective)
   READ_FEATURE(Only)
   READ_FEATURE(OpenACCAtomicConstruct)
diff --git a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
index feb7b4eced9e9..5c64870b74be2 100644
--- a/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
+++ b/flang/examples/FlangOmpReport/FlangOmpReportVisitor.cpp
@@ -7,6 +7,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "FlangOmpReportVisitor.h"
+#include "flang/Parser/openmp-utils.h"
 #include "llvm/ADT/StringExtras.h"
 #include "llvm/Frontend/OpenMP/OMP.h"
 
@@ -118,60 +119,8 @@ std::string OpenMPCounterVisitor::getName(const OpenMPDeclarativeConstruct &c) {
       c.u);
 }
 std::string OpenMPCounterVisitor::getName(const OpenMPConstruct &c) {
-  return std::visit(
-      Fortran::common::visitors{
-          [&](const OpenMPStandaloneConstruct &c) -> std::string {
-            return common::visit(
-                common::visitors{
-                    [&](const OmpMetadirectiveDirective &d) {
-                      return normalize_construct_name(d.source.ToString());
-                    },
-                    [&](auto &&d) {
-                      const CharBlock &source{
-                          std::get<OmpDirectiveName>(d.v.t).source};
-                      return normalize_construct_name(source.ToString());
-                    },
-                },
-                c.u);
-          },
-          [&](const OpenMPExecutableAllocate &c) -> std::string {
-            const CharBlock &source{std::get<0>(c.t).source};
-            return normalize_construct_name(source.ToString());
-          },
-          [&](const OpenMPDeclarativeAllocate &c) -> std::string {
-            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());
-          },
-          [&](const OpenMPAtomicConstruct &c) -> std::string {
-            auto &dirSpec = std::get<OmpDirectiveSpecification>(c.t);
-            auto &dirName = std::get<OmpDirectiveName>(dirSpec.t);
-            return normalize_construct_name(dirName.source.ToString());
-          },
-          [&](const OpenMPUtilityConstruct &c) -> std::string {
-            const CharBlock &source{c.source};
-            return normalize_construct_name(source.ToString());
-          },
-          [&](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
-          // field of the begin directive in Critical
-          [&](const auto &c) -> std::string {
-            const CharBlock &source{std::get<0>(std::get<0>(c.t).t).source};
-            return normalize_construct_name(source.ToString());
-          },
-      },
-      c.u);
+  return normalize_construct_name(
+      omp::GetOmpDirectiveName(c).source.ToString());
 }
 
 bool OpenMPCounterVisitor::Pre(const OpenMPDeclarativeConstruct &c) {
diff --git a/flang/include/flang/Parser/dump-parse-tree.h b/flang/include/flang/Parser/dump-parse-tree.h
index 23e35d106c077..ebac54f6e29ba 100644
--- a/flang/include/flang/Parser/dump-parse-tree.h
+++ b/flang/include/flang/Parser/dump-parse-tree.h
@@ -681,7 +681,6 @@ class ParseTreeDumper {
   NODE_ENUM(OmpChunkModifier, Value)
   NODE(parser, OmpOrderingModifier)
   NODE_ENUM(OmpOrderingModifier, Value)
-  NODE(parser, OmpSectionBlocks)
   NODE(parser, OmpSectionsDirective)
   NODE(parser, OmpToClause)
   NODE(OmpToClause, Modifier)
diff --git a/flang/include/flang/Parser/openmp-utils.h b/flang/include/flang/Parser/openmp-utils.h
index 579ea7d74957f..41c04424e91c6 100644
--- a/flang/include/flang/Parser/openmp-utils.h
+++ b/flang/include/flang/Parser/openmp-utils.h
@@ -78,6 +78,14 @@ struct DirectiveNameScope {
     return MakeName(dir.source, dir.v);
   }
 
+  static OmpDirectiveName GetOmpDirectiveName(const OpenMPSectionConstruct &x) {
+    if (auto &spec{std::get<std::optional<OmpDirectiveSpecification>>(x.t)}) {
+      return spec->DirName();
+    } else {
+      return MakeName({}, llvm::omp::Directive::OMPD_section);
+    }
+  }
+
   static OmpDirectiveName GetOmpDirectiveName(
       const OmpBeginSectionsDirective &x) {
     auto &dir{std::get<OmpSectionsDirective>(x.t)};
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 0fb66c9f683e4..da0a3632b8a63 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4818,18 +4818,17 @@ struct OmpEndSectionsDirective {
 //    structured-block]
 // ...
 struct OpenMPSectionConstruct {
-  WRAPPER_CLASS_BOILERPLATE(OpenMPSectionConstruct, Block);
+  TUPLE_CLASS_BOILERPLATE(OpenMPSectionConstruct);
+  std::tuple<std::optional<OmpDirectiveSpecification>, Block> t;
   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<OpenMPConstruct>);
-
 struct OpenMPSectionsConstruct {
   TUPLE_CLASS_BOILERPLATE(OpenMPSectionsConstruct);
-  std::tuple<OmpBeginSectionsDirective, OmpSectionBlocks,
+  CharBlock source;
+  // Each of the OpenMPConstructs in the list below contains an
+  // OpenMPSectionConstruct. This is guaranteed by the parser.
+  std::tuple<OmpBeginSectionsDirective, std::list<OpenMPConstruct>,
       OmpEndSectionsDirective>
       t;
 };
diff --git a/flang/lib/Lower/OpenMP/OpenMP.cpp b/flang/lib/Lower/OpenMP/OpenMP.cpp
index 12089d6caa5fe..6dd4b16a1fb55 100644
--- a/flang/lib/Lower/OpenMP/OpenMP.cpp
+++ b/flang/lib/Lower/OpenMP/OpenMP.cpp
@@ -2329,7 +2329,7 @@ genSectionsOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
   assert(sectionsConstruct && "Missing additional parsing information");
 
   const auto &sectionBlocks =
-      std::get<parser::OmpSectionBlocks>(sectionsConstruct->t);
+      std::get<std::list<parser::OpenMPConstruct>>(sectionsConstruct->t);
   mlir::omp::SectionsOperands clauseOps;
   llvm::SmallVector<const semantics::Symbol *> reductionSyms;
   genSectionsClauses(converter, semaCtx, item->clauses, loc, clauseOps,
@@ -2382,7 +2382,7 @@ genSectionsOp(lower::AbstractConverter &converter, lower::SymMap &symTable,
   // because we need to run genReductionVars on each omp.section so that the
   // reduction variable gets mapped to the private version
   for (auto [construct, nestedEval] :
-       llvm::zip(sectionBlocks.v, eval.getNestedEvaluations())) {
+       llvm::zip(sectionBlocks, eval.getNestedEvaluations())) {
     const auto *sectionConstruct =
         std::get_if<parser::OpenMPSectionConstruct>(&construct.u);
     if (!sectionConstruct) {
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index 9abec5aef8329..8c780388b9cb1 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -34,6 +34,39 @@ namespace Fortran::parser {
 constexpr auto startOmpLine = skipStuffBeforeStatement >> "!$OMP "_sptok;
 constexpr auto endOmpLine = space >> endOfLine;
 
+// Given a parser for a single element, and a parser for a list of elements
+// of the same type, create a parser that constructs the entire list by having
+// the single element be the head of the list, and the rest be the tail.
+template <typename ParserH, typename ParserT> struct ConsParser {
+  static_assert(std::is_same_v<std::list<typename ParserH::resultType>,
+      typename ParserT::resultType>);
+
+  using resultType = typename ParserT::resultType;
+  constexpr ConsParser(ParserH h, ParserT t) : head_(h), tail_(t) {}
+
+  std::optional<resultType> Parse(ParseState &state) const {
+    if (auto &&first{head_.Parse(state)}) {
+      if (auto rest{tail_.Parse(state)}) {
+        rest->push_front(std::move(*first));
+        return std::move(*rest);
+      }
+    }
+    return std::nullopt;
+  }
+
+private:
+  const ParserH head_;
+  const ParserT tail_;
+};
+
+template <typename ParserH, typename ParserT,
+    typename ValueH = typename ParserH::resultType,
+    typename ValueT = typename ParserT::resultType,
+    typename = std::enable_if_t<std::is_same_v<std::list<ValueH>, ValueT>>>
+constexpr auto cons(ParserH head, ParserT tail) {
+  return ConsParser<ParserH, ParserT>(head, tail);
+}
+
 // Given a parser P for a wrapper class, invoke P, and if it succeeds return
 // the wrapped object.
 template <typename Parser> struct UnwrapParser {
@@ -1831,19 +1864,20 @@ TYPE_PARSER(
                         sourced("END"_tok >> Parser<OmpSectionsDirective>{}),
                         Parser<OmpClauseList>{})))
 
-// OMP SECTION-BLOCK
-
-TYPE_PARSER(construct<OpenMPSectionConstruct>(block))
-
-TYPE_PARSER(maybe(startOmpLine >> "SECTION"_tok / endOmpLine) >>
-    construct<OmpSectionBlocks>(nonemptySeparated(
-        construct<OpenMPConstruct>(sourced(Parser<OpenMPSectionConstruct>{})),
-        startOmpLine >> "SECTION"_tok / endOmpLine)))
+static constexpr auto sectionDir{
+    startOmpLine >> (predicated(OmpDirectiveNameParser{},
+                         IsDirective(llvm::omp::Directive::OMPD_section)) >=
+                        Parser<OmpDirectiveSpecification>{})};
 
 // OMP SECTIONS (OpenMP 5.0 - 2.8.1), PARALLEL SECTIONS (OpenMP 5.0 - 2.13.3)
-TYPE_PARSER(construct<OpenMPSectionsConstruct>(
+TYPE_PARSER(sourced(construct<OpenMPSectionsConstruct>(
     Parser<OmpBeginSectionsDirective>{} / endOmpLine,
-    Parser<OmpSectionBlocks>{}, Parser<OmpEndSectionsDirective>{} / endOmpLine))
+    cons( //
+        construct<OpenMPConstruct>(sourced(
+            construct<OpenMPSectionConstruct>(maybe(sectionDir), block))),
+        many(construct<OpenMPConstruct>(
+            sourced(construct<OpenMPSectionConstruct>(sectionDir, block))))),
+    Parser<OmpEndSectionsDirective>{} / endOmpLine)))
 
 static bool IsExecutionPart(const OmpDirectiveName &name) {
   return name.IsExecutionPart();
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index fc15d46a8c727..1d4d53de1491d 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2801,16 +2801,16 @@ class UnparseVisitor {
       break;
     }
   }
-  void Unparse(const OmpSectionBlocks &x) {
-    for (const auto &y : x.v) {
+  void Unparse(const OpenMPSectionConstruct &x) {
+    if (auto &&dirSpec{
+            std::get<std::optional<OmpDirectiveSpecification>>(x.t)}) {
       BeginOpenMP();
-      Word("!$OMP SECTION");
+      Word("!$OMP ");
+      Walk(*dirSpec);
       Put("\n");
       EndOpenMP();
-      // y.u is an OpenMPSectionConstruct
-      // (y.u).v is Block
-      Walk(std::get<OpenMPSectionConstruct>(y.u).v, "");
     }
+    Walk(std::get<Block>(x.t), "");
   }
   void Unparse(const OpenMPSectionsConstruct &x) {
     BeginOpenMP();
@@ -2818,7 +2818,7 @@ class UnparseVisitor {
     Walk(std::get<OmpBeginSectionsDirective>(x.t));
     Put("\n");
     EndOpenMP();
-    Walk(std::get<OmpSectionBlocks>(x.t));
+    Walk(std::get<std::list<OpenMPConstruct>>(x.t), "");
     BeginOpenMP();
     Word("!$OMP END ");
     Walk(std::get<OmpEndSectionsDirective>(x.t));
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index d214d222e7c90..c191ad8d088d3 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -1057,10 +1057,11 @@ void OmpStructureChecker::Enter(const parser::OpenMPSectionsConstruct &x) {
   PushContextAndClauseSets(beginDir.source, beginDir.v);
   AddEndDirectiveClauses(std::get<parser::OmpClauseList>(endSectionsDir.t));
 
-  const auto &sectionBlocks{std::get<parser::OmpSectionBlocks>(x.t)};
-  for (const parser::OpenMPConstruct &block : sectionBlocks.v) {
-    CheckNoBranching(std::get<parser::OpenMPSectionConstruct>(block.u).v,
-        beginDir.v, beginDir.source);
+  const auto &sectionBlocks{std::get<std::list<parser::OpenMPConstruct>>(x.t)};
+  for (const parser::OpenMPConstruct &construct : sectionBlocks) {
+    auto &section{std::get<parser::OpenMPSectionConstruct>(construct.u)};
+    CheckNoBranching(
+        std::get<parser::Block>(section.t), 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
index 41e6e8fd9e5ab..a6d28065c8001 100644
--- a/flang/test/Examples/omp-sections.f90
+++ b/flang/test/Examples/omp-sections.f90
@@ -13,11 +13,11 @@ subroutine omp_sections()
 end subroutine omp_sections
 
 !CHECK: - file:            {{.*}}
-!CHECK:   line:            9
+!CHECK:   line:            8
 !CHECK:   construct:       section
 !CHECK:   clauses:         []
 !CHECK: - file:            {{.*}}
-!CHECK:   line:            11
+!CHECK:   line:            10
 !CHECK:   construct:       section
 !CHECK:   clauses:         []
 !CHECK: - file:            {{.*}}
diff --git a/flang/test/Parser/OpenMP/sections.f90 b/flang/test/Parser/OpenMP/sections.f90
index 3752cef624329..8ba2294fb0faa 100644
--- a/flang/test/Parser/OpenMP/sections.f90
+++ b/flang/test/Parser/OpenMP/sections.f90
@@ -10,32 +10,41 @@ subroutine openmp_sections(x, y)
 !==============================================================================
 !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
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct
+!PARSE-TREE: | OmpBeginSectionsDirective
+!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
+!PARSE-TREE: | | OmpClauseList ->
+!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct
+!PARSE-TREE: | | Block
+!PARSE-TREE: | OmpEndSectionsDirective
+!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
+!PARSE-TREE: | | OmpClauseList ->
 
 !==============================================================================
 ! 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
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct
+!PARSE-TREE: | OmpBeginSectionsDirective
+!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
+!PARSE-TREE: | | OmpClauseList ->
+!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct
+!PARSE-TREE: | | Block
+!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f1()'
+!PARSE-TREE: | | | | Call
+!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f1'
+!PARSE-TREE: | OmpEndSectionsDirective
+!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
+!PARSE-TREE: | | OmpClauseList ->
 
 !==============================================================================
 ! single section with `!$omp section`
@@ -49,12 +58,22 @@ subroutine openmp_sections(x, y)
 !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
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct
+!PARSE-TREE: | OmpBeginSectionsDirective
+!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
+!PARSE-TREE: | | OmpClauseList ->
+!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct
+!PARSE-TREE: | | OmpDirectiveSpecification
+!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section
+!PARSE-TREE: | | | OmpClauseList ->
+!PARSE-TREE: | | | Flags = None
+!PARSE-TREE: | | Block
+!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f1()'
+!PARSE-TREE: | | | | Call
+!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f1'
+!PARSE-TREE: | OmpEndSectionsDirective
+!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
+!PARSE-TREE: | | OmpClauseList ->
 
 !==============================================================================
 ! multiple sections
@@ -76,16 +95,40 @@ subroutine openmp_sections(x, y)
 !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
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct
+!PARSE-TREE: | OmpBeginSectionsDirective
+!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
+!PARSE-TREE: | | OmpClauseList ->
+!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct
+!PARSE-TREE: | | OmpDirectiveSpecification
+!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section
+!PARSE-TREE: | | | OmpClauseList ->
+!PARSE-TREE: | | | Flags = None
+!PARSE-TREE: | | Block
+!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f1()'
+!PARSE-TREE: | | | | Call
+!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f1'
+!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct
+!PARSE-TREE: | | OmpDirectiveSpecification
+!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section
+!PARSE-TREE: | | | OmpClauseList ->
+!PARSE-TREE: | | | Flags = None
+!PARSE-TREE: | | Block
+!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f2()'
+!PARSE-TREE: | | | | Call
+!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f2'
+!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct
+!PARSE-TREE: | | OmpDirectiveSpecification
+!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section
+!PARSE-TREE: | | | OmpClauseList ->
+!PARSE-TREE: | | | Flags = None
+!PARSE-TREE: | | Block
+!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f3()'
+!PARSE-TREE: | | | | Call
+!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f3'
+!PARSE-TREE: | OmpEndSectionsDirective
+!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
+!PARSE-TREE: | | OmpClauseList ->
 
 !==============================================================================
 ! multiple sections with clauses
@@ -107,15 +150,40 @@ subroutine openmp_sections(x, y)
 !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
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPSectionsConstruct
+!PARSE-TREE: | OmpBeginSectionsDirective
+!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
+!PARSE-TREE: | | OmpClauseList -> OmpClause -> Private -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'x'
+!PARSE-TREE: | | OmpClause -> Firstprivate -> OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'y'
+!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct
+!PARSE-TREE: | | OmpDirectiveSpecification
+!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section
+!PARSE-TREE: | | | OmpClauseList ->
+!PARSE-TREE: | | | Flags = None
+!PARSE-TREE: | | Block
+!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f1()'
+!PARSE-TREE: | | | | Call
+!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f1'
+!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct
+!PARSE-TREE: | | OmpDirectiveSpecification
+!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section
+!PARSE-TREE: | | | OmpClauseList ->
+!PARSE-TREE: | | | Flags = None
+!PARSE-TREE: | | Block
+!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f2()'
+!PARSE-TREE: | | | | Call
+!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f2'
+!PARSE-TREE: | OpenMPConstruct -> OpenMPSectionConstruct
+!PARSE-TREE: | | OmpDirectiveSpecification
+!PARSE-TREE: | | | OmpDirectiveName -> llvm::omp::Directive = section
+!PARSE-TREE: | | | OmpClauseList ->
+!PARSE-TREE: | | | Flags = None
+!PARSE-TREE: | | Block
+!PARSE-TREE: | | | ExecutionPartConstruct -> ExecutableConstruct -> ActionStmt -> CallStmt = 'CALL f3()'
+!PARSE-TREE: | | | | Call
+!PARSE-TREE: | | | | | ProcedureDesignator -> Name = 'f3'
+!PARSE-TREE: | OmpEndSectionsDirective
+!PARSE-TREE: | | OmpSectionsDirective -> llvm::omp::Directive = sections
+!PARSE-TREE: | | OmpClauseList -> OmpClause -> Nowait
 
 END subroutine openmp_sections



More information about the llvm-branch-commits mailing list