Skip to content

Conversation

@kparzysz
Copy link
Contributor

No description provided.

Instead of having a variant with specific AST nodes that can contain
a reduction specifier, simply store the OpenMPDeclarativeConstruct.
It is used to emit the source code directive when generating a module
file, and unparsing the top-level AST node will work just fine.
This was checked in the visitor for OmpDirectiveSpecification, and is
not necessary anymore: the early exit (in case of not being inside of
a METADIRECTIVE) performs the same actions as the code that was skipped,
except it does so through a different sequence of function calls. The
net result ends up being the same in either case.

The processing of the mapper and reduction specifiers inside of
OmpDirectiveSpecification is necesary for the declare directives on
WHEN/OTHERWISE clauses, so it's the early exit that needs to be removed.
In fact, when the DECLARE_MAPPER/REDUCTION use OmpDirectiveSpecification,
this processing will automatically take over the handling of the contained
specifiers.
Fully resolve all arguments and clauses in OmpDirectiveSpecification
instead of just looking for special cases. Delegate resolution from
nodes that inherit from ODS to use the ODS resolution.
If it happens, it's a bug to be fixed.
@kparzysz kparzysz requested review from Stylie777 and tblah September 22, 2025 20:21
@llvmbot llvmbot added flang Flang issues not falling into any other category flang:openmp flang:semantics flang:parser labels Sep 22, 2025
@llvmbot
Copy link
Member

llvmbot commented Sep 22, 2025

@llvm/pr-subscribers-flang-openmp
@llvm/pr-subscribers-flang-semantics

@llvm/pr-subscribers-flang-parser

Author: Krzysztof Parzyszek (kparzysz)

Changes

Patch is 29.84 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/160192.diff

11 Files Affected:

  • (modified) flang/include/flang/Parser/parse-tree.h (+2-4)
  • (modified) flang/lib/Parser/openmp-parsers.cpp (+3-3)
  • (modified) flang/lib/Parser/unparse.cpp (+2-5)
  • (modified) flang/lib/Semantics/check-omp-structure.cpp (+15-8)
  • (modified) flang/lib/Semantics/resolve-names.cpp (+10-12)
  • (modified) flang/test/Parser/OpenMP/declare-reduction-multi.f90 (+87-71)
  • (modified) flang/test/Parser/OpenMP/declare-reduction-operator.f90 (+22-16)
  • (modified) flang/test/Parser/OpenMP/declare-reduction-unparse-with-symbols.f90 (+1-1)
  • (modified) flang/test/Parser/OpenMP/declare-reduction-unparse.f90 (+35-16)
  • (modified) flang/test/Parser/OpenMP/openmp6-directive-spellings.f90 (+5-4)
  • (modified) flang/test/Semantics/OpenMP/declare-reduction-modfile.f90 (+6-6)
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 73f8fbdbbb467..2063eccf8b7f4 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -4960,11 +4960,9 @@ struct OpenMPDeclareMapperConstruct {
 // 2.16 declare-reduction -> DECLARE REDUCTION (reduction-identifier : type-list
 //                                              : combiner) [initializer-clause]
 struct OpenMPDeclareReductionConstruct {
-  TUPLE_CLASS_BOILERPLATE(OpenMPDeclareReductionConstruct);
+  WRAPPER_CLASS_BOILERPLATE(
+      OpenMPDeclareReductionConstruct, OmpDirectiveSpecification);
   CharBlock source;
-  std::tuple<Verbatim, common::Indirection<OmpReductionSpecifier>,
-      std::optional<OmpClauseList>>
-      t;
 };
 
 // 2.8.2 declare-simd -> DECLARE SIMD [(proc-name)] [declare-simd-clause[ [,]
diff --git a/flang/lib/Parser/openmp-parsers.cpp b/flang/lib/Parser/openmp-parsers.cpp
index dc638ca9d00fe..57b812665073a 100644
--- a/flang/lib/Parser/openmp-parsers.cpp
+++ b/flang/lib/Parser/openmp-parsers.cpp
@@ -1708,9 +1708,9 @@ TYPE_PARSER(sourced(construct<OmpDeclareVariantDirective>(
 
 // 2.16 Declare Reduction Construct
 TYPE_PARSER(sourced(construct<OpenMPDeclareReductionConstruct>(
-    verbatim("DECLARE REDUCTION"_tok) || verbatim("DECLARE_REDUCTION"_tok),
-    "(" >> indirect(Parser<OmpReductionSpecifier>{}) / ")",
-    maybe(Parser<OmpClauseList>{}))))
+    predicated(Parser<OmpDirectiveName>{},
+        IsDirective(llvm::omp::Directive::OMPD_declare_reduction)) >=
+    Parser<OmpDirectiveSpecification>{})))
 
 // declare-target with list
 TYPE_PARSER(sourced(construct<OmpDeclareTargetWithList>(
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 01b0e32a1164e..750f1258be2fc 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -2495,11 +2495,8 @@ class UnparseVisitor {
   }
   void Unparse(const OpenMPDeclareReductionConstruct &x) {
     BeginOpenMP();
-    Word("!$OMP DECLARE REDUCTION ");
-    Put("(");
-    Walk(std::get<common::Indirection<OmpReductionSpecifier>>(x.t));
-    Put(")");
-    Walk(std::get<std::optional<OmpClauseList>>(x.t));
+    Word("!$OMP ");
+    Walk(x.v);
     Put("\n");
     EndOpenMP();
   }
diff --git a/flang/lib/Semantics/check-omp-structure.cpp b/flang/lib/Semantics/check-omp-structure.cpp
index 17954b5826586..bff5c2498344a 100644
--- a/flang/lib/Semantics/check-omp-structure.cpp
+++ b/flang/lib/Semantics/check-omp-structure.cpp
@@ -629,11 +629,6 @@ template <typename Checker> struct DirectiveSpellingVisitor {
     checker_(std::get<parser::Verbatim>(x.t).source, Directive::OMPD_assumes);
     return false;
   }
-  bool Pre(const parser::OpenMPDeclareReductionConstruct &x) {
-    checker_(std::get<parser::Verbatim>(x.t).source,
-        Directive::OMPD_declare_reduction);
-    return false;
-  }
   bool Pre(const parser::OpenMPDeclareSimdConstruct &x) {
     checker_(
         std::get<parser::Verbatim>(x.t).source, Directive::OMPD_declare_simd);
@@ -1618,9 +1613,21 @@ void OmpStructureChecker::Leave(const parser::OpenMPDeclareMapperConstruct &) {
 
 void OmpStructureChecker::Enter(
     const parser::OpenMPDeclareReductionConstruct &x) {
-  const auto &dir{std::get<parser::Verbatim>(x.t)};
-  PushContextAndClauseSets(
-      dir.source, llvm::omp::Directive::OMPD_declare_reduction);
+  const parser::OmpDirectiveName &dirName{x.v.DirName()};
+  PushContextAndClauseSets(dirName.source, dirName.v);
+
+  const parser::OmpArgumentList &args{x.v.Arguments()};
+  if (args.v.size() != 1) {
+    context_.Say(args.source,
+        "DECLARE_REDUCTION directive should have a single argument"_err_en_US);
+    return;
+  }
+
+  const parser::OmpArgument &arg{args.v.front()};
+  if (!std::holds_alternative<parser::OmpReductionSpecifier>(arg.u)) {
+    context_.Say(arg.source,
+        "The argument to the DECLARE_REDUCTION directive should be a reduction-specifier"_err_en_US);
+  }
 }
 
 void OmpStructureChecker::Leave(
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 86ada0f8cdc85..3b6140429f9ed 100644
--- a/flang/lib/Semantics/resolve-names.cpp
+++ b/flang/lib/Semantics/resolve-names.cpp
@@ -1559,12 +1559,7 @@ class OmpVisitor : public virtual DeclarationVisitor {
 
   bool Pre(const parser::OpenMPDeclareReductionConstruct &x) {
     AddOmpSourceRange(x.source);
-    parser::OmpClauseList empty(std::list<parser::OmpClause>{});
-    auto &maybeClauses{std::get<std::optional<parser::OmpClauseList>>(x.t)};
-    ProcessReductionSpecifier(
-        std::get<Indirection<parser::OmpReductionSpecifier>>(x.t).value(),
-        maybeClauses ? *maybeClauses : empty, declaratives_.back());
-    return false;
+    return true;
   }
   bool Pre(const parser::OmpMapClause &);
 
@@ -1689,6 +1684,11 @@ class OmpVisitor : public virtual DeclarationVisitor {
     // should not reach a point where it calls this function.
     llvm_unreachable("This function should not be reached by AST traversal");
   }
+  bool Pre(const parser::OmpReductionSpecifier &x) {
+    // OmpReductionSpecifier is handled explicitly, and the AST traversal
+    // should not reach a point where it calls this function.
+    llvm_unreachable("This function should not be reached by AST traversal");
+  }
   bool Pre(const parser::OmpDirectiveSpecification &x);
   void Post(const parser::OmpDirectiveSpecification &) {
     messageHandler().set_currStmtSource(std::nullopt);
@@ -1716,8 +1716,7 @@ class OmpVisitor : public virtual DeclarationVisitor {
   void ProcessMapperSpecifier(const parser::OmpMapperSpecifier &spec,
       const parser::OmpClauseList &clauses);
   void ProcessReductionSpecifier(const parser::OmpReductionSpecifier &spec,
-      const parser::OmpClauseList &clauses,
-      const parser::OpenMPDeclarativeConstruct *wholeConstruct);
+      const parser::OmpClauseList &clauses);
 
   void ResolveCriticalName(const parser::OmpArgument &arg);
 
@@ -1848,8 +1847,7 @@ std::string MangleDefinedOperator(const parser::CharBlock &name) {
 
 void OmpVisitor::ProcessReductionSpecifier(
     const parser::OmpReductionSpecifier &spec,
-    const parser::OmpClauseList &clauses,
-    const parser::OpenMPDeclarativeConstruct *construct) {
+    const parser::OmpClauseList &clauses) {
   const parser::Name *name{nullptr};
   parser::CharBlock mangledName;
   UserReductionDetails reductionDetailsTemp;
@@ -1936,7 +1934,7 @@ void OmpVisitor::ProcessReductionSpecifier(
     PopScope();
   }
 
-  reductionDetails->AddDecl(construct);
+  reductionDetails->AddDecl(declaratives_.back());
 
   if (!symbol) {
     symbol = &MakeSymbol(mangledName, Attrs{}, std::move(*reductionDetails));
@@ -1989,7 +1987,7 @@ bool OmpVisitor::Pre(const parser::OmpDirectiveSpecification &x) {
               visitClauses = false;
             },
             [&](const parser::OmpReductionSpecifier &spec) {
-              ProcessReductionSpecifier(spec, clauses, declaratives_.back());
+              ProcessReductionSpecifier(spec, clauses);
               visitClauses = false;
             },
             [&](const parser::OmpLocator &locator) {
diff --git a/flang/test/Parser/OpenMP/declare-reduction-multi.f90 b/flang/test/Parser/OpenMP/declare-reduction-multi.f90
index 693e69d8896be..19266aca9db03 100644
--- a/flang/test/Parser/OpenMP/declare-reduction-multi.f90
+++ b/flang/test/Parser/OpenMP/declare-reduction-multi.f90
@@ -26,111 +26,127 @@ program omp_examples
   type(tt) :: values(n), sum, prod, big, small
 
   !$omp declare reduction(+:tt:omp_out%r = omp_out%r + omp_in%r) initializer(omp_priv%r = 0)
-!CHECK: !$OMP DECLARE REDUCTION (+:tt: omp_out%r=omp_out%r+omp_in%r
+!CHECK: !$OMP DECLARE REDUCTION(+:tt: omp_out%r=omp_out%r+omp_in%r
 !CHECK-NEXT: ) INITIALIZER(omp_priv%r=0_4)
-!PARSE-TREE:  DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct
-!PARSE-TREE:  Verbatim
-!PARSE-TREE: OmpReductionSpecifier
-!PARSE-TREE-NEXT: OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add
-!PARSE-TREE: OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec
-!PARSE-TREE-NEXT:  Name = 'tt'
-!PARSE-TREE: OmpReductionCombiner -> AssignmentStmt = 'omp_out%r=omp_out%r+omp_in%r'
-!PARSE-TREE: OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> AssignmentStmt = 'omp_priv%r=0._4
+
+!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -> OmpDirectiveSpecification
+!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare reduction
+!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpReductionSpecifier
+!PARSE-TREE: | | OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add
+!PARSE-TREE: | | OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec
+!PARSE-TREE: | | | Name = 'tt'
+!PARSE-TREE: | | OmpReductionCombiner -> AssignmentStmt = 'omp_out%r=omp_out%r+omp_in%r'
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> AssignmentStmt = 'omp_priv%r=0._4'
+
   !$omp declare reduction(*:tt:omp_out%r = omp_out%r * omp_in%r) initializer(omp_priv%r = 1)
-!CHECK-NEXT: !$OMP DECLARE REDUCTION (*:tt: omp_out%r=omp_out%r*omp_in%r
+!CHECK-NEXT: !$OMP DECLARE REDUCTION(*:tt: omp_out%r=omp_out%r*omp_in%r
 !CHECK-NEXT: ) INITIALIZER(omp_priv%r=1_4)
-!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct
-!PARSE-TREE: Verbatim
-!PARSE-TREE: OmpReductionSpecifier
-!PARSE-TREE: OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Multiply
-!PARSE-TREE: OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec
-!PARSE-TREE-NEXT:  Name = 'tt'
-!PARSE-TREE: OmpReductionCombiner -> AssignmentStmt = 'omp_out%r=omp_out%r*omp_in%r'
-!PARSE-TREE: OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> AssignmentStmt = 'omp_priv%r=1._4'
+
+!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -> OmpDirectiveSpecification
+!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare reduction
+!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpReductionSpecifier
+!PARSE-TREE: | | OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Multiply
+!PARSE-TREE: | | OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec
+!PARSE-TREE: | | | Name = 'tt'
+!PARSE-TREE: | | OmpReductionCombiner -> AssignmentStmt = 'omp_out%r=omp_out%r*omp_in%r'
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> AssignmentStmt = 'omp_priv%r=1._4'
+
   !$omp declare reduction(max:tt:omp_out = mymax(omp_out, omp_in)) initializer(omp_priv%r = 0)
-!CHECK-NEXT: !$OMP DECLARE REDUCTION (max:tt: omp_out=mymax(omp_out,omp_in)
+!CHECK-NEXT: !$OMP DECLARE REDUCTION(max:tt: omp_out=mymax(omp_out,omp_in)
 !CHECK-NEXT: ) INITIALIZER(omp_priv%r=0_4)
-!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct
-!PARSE-TREE: Verbatim
-!PARSE-TREE: OmpReductionSpecifier
-!PARSE-TREE: OmpReductionIdentifier -> ProcedureDesignator -> Name = 'max'
-!PARSE-TREE: OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec
-!PARSE-TREE: Name = 'tt'
-!PARSE-TREE: OmpReductionCombiner -> AssignmentStmt = 'omp_out=mymax(omp_out,omp_in)'
-!PARSE-TREE: OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> AssignmentStmt = 'omp_priv%r=0._4'
+
+!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -> OmpDirectiveSpecification
+!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare reduction
+!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpReductionSpecifier
+!PARSE-TREE: | | OmpReductionIdentifier -> ProcedureDesignator -> Name = 'max'
+!PARSE-TREE: | | OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec
+!PARSE-TREE: | | | Name = 'tt'
+!PARSE-TREE: | | OmpReductionCombiner -> AssignmentStmt = 'omp_out=mymax(omp_out,omp_in)'
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> AssignmentStmt = 'omp_priv%r=0._4'
+
   !$omp declare reduction(min:tt:omp_out%r = min(omp_out%r, omp_in%r)) initializer(omp_priv%r = 1)
-!CHECK-NEXT: !$OMP DECLARE REDUCTION (min:tt: omp_out%r=min(omp_out%r,omp_in%r)
+!CHECK-NEXT: !$OMP DECLARE REDUCTION(min:tt: omp_out%r=min(omp_out%r,omp_in%r)
 !CHECK-NEXT: ) INITIALIZER(omp_priv%r=1_4)
-!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct
-!PARSE-TREE: Verbatim
-!PARSE-TREE: OmpReductionSpecifier
-!PARSE-TREE: OmpReductionIdentifier -> ProcedureDesignator -> Name = 'min'
-!PARSE-TREE: OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec
-!PARSE-TREE: Name = 'tt'
-!PARSE-TREE: OmpReductionCombiner -> AssignmentStmt = 'omp_out%r=min(omp_out%r,omp_in%r)'
-!PARSE-TREE: OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> AssignmentStmt = 'omp_priv%r=1._4'
+
+!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -> OmpDirectiveSpecification
+!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare reduction
+!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpReductionSpecifier
+!PARSE-TREE: | | OmpReductionIdentifier -> ProcedureDesignator -> Name = 'min'
+!PARSE-TREE: | | OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> DerivedTypeSpec
+!PARSE-TREE: | | | Name = 'tt'
+!PARSE-TREE: | | OmpReductionCombiner -> AssignmentStmt = 'omp_out%r=min(omp_out%r,omp_in%r)'
+!PARSE-TREE: | OmpClauseList -> OmpClause -> Initializer -> OmpInitializerClause -> AssignmentStmt = 'omp_priv%r=1._4'
+
   call random_number(values%r)
 
   sum%r = 0
   !$omp parallel do reduction(+:sum)
-!CHECK: !$OMP PARALLEL DO  REDUCTION(+: sum) 
+!CHECK: !$OMP PARALLEL DO REDUCTION(+: sum)
+
 !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct
-!PARSE-TREE: OmpBeginLoopDirective
-!PARSE-TREE: OmpDirectiveName -> llvm::omp::Directive = parallel do
-!PARSE-TREE: OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause
-!PARSE-TREE: Modifier -> OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add
-!PARSE-TREE: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'sum
-!PARSE-TREE: Flags = None
-!PARSE-TREE: DoConstruct
+!PARSE-TREE: | OmpBeginLoopDirective
+!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = parallel do
+!PARSE-TREE: | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause
+!PARSE-TREE: | | | Modifier -> OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add
+!PARSE-TREE: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'sum'
+!PARSE-TREE: | | Flags = None
+!PARSE-TREE: | DoConstruct
+
   do i = 1, n
      sum%r = sum%r + values(i)%r
   end do
 
   prod%r = 1
   !$omp parallel do reduction(*:prod)
-!CHECK: !$OMP PARALLEL DO  REDUCTION(*: prod)
-!PARSE-TREE:  ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct
-!PARSE-TREE: OmpBeginLoopDirective
-!PARSE-TREE: OmpDirectiveName -> llvm::omp::Directive = parallel do
-!PARSE-TREE: OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause
-!PARSE-TREE: Modifier -> OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Multiply
-!PARSE-TREE: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'prod'
-!PARSE-TREE: Flags = None
-!PARSE-TREE: DoConstruct
+!CHECK: !$OMP PARALLEL DO REDUCTION(*: prod)
+
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct
+!PARSE-TREE: | OmpBeginLoopDirective
+!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = parallel do
+!PARSE-TREE: | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause
+!PARSE-TREE: | | | Modifier -> OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Multiply
+!PARSE-TREE: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'prod'
+!PARSE-TREE: | | Flags = None
+!PARSE-TREE: | DoConstruct
+
   do i = 1, n
      prod%r = prod%r * (values(i)%r+0.6)
   end do
 
   big%r = 0
   !$omp parallel do reduction(max:big)
-!CHECK:  $OMP PARALLEL DO  REDUCTION(max: big) 
+!CHECK:  $OMP PARALLEL DO REDUCTION(max: big)
+
 !PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct
-!PARSE-TREE: OmpBeginLoopDirective
-!PARSE-TREE: OmpDirectiveName -> llvm::omp::Directive = parallel do
-!PARSE-TREE: OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause
-!PARSE-TREE: Modifier -> OmpReductionIdentifier -> ProcedureDesignator -> Name = 'max'
-!PARSE-TREE: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'big'
-!PARSE-TREE: Flags = None
-!PARSE-TREE: DoConstruct
+!PARSE-TREE: | OmpBeginLoopDirective
+!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = parallel do
+!PARSE-TREE: | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause
+!PARSE-TREE: | | | Modifier -> OmpReductionIdentifier -> ProcedureDesignator -> Name = 'max'
+!PARSE-TREE: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'big'
+!PARSE-TREE: | | Flags = None
+!PARSE-TREE: | DoConstruct
+
   do i = 1, n
      big = mymax(values(i), big)
   end do
 
   small%r = 1
   !$omp parallel do reduction(min:small)
-!CHECK: !$OMP PARALLEL DO  REDUCTION(min: small)
-!CHECK-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct
-!CHECK-TREE: OmpBeginLoopDirective
-!CHECK-TREE: OmpDirectiveName -> llvm::omp::Directive = parallel do
-!CHECK-TREE: OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause
-!CHECK-TREE: Modifier -> OmpReductionIdentifier -> ProcedureDesignator -> Name = 'min'
-!CHECK-TREE: OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'small'
-!PARSE-TREE: Flags = None
-!CHECK-TREE: DoConstruct
+!CHECK: !$OMP PARALLEL DO REDUCTION(min: small)
+
+!PARSE-TREE: ExecutionPartConstruct -> ExecutableConstruct -> OpenMPConstruct -> OpenMPLoopConstruct
+!PARSE-TREE: | OmpBeginLoopDirective
+!PARSE-TREE: | | OmpDirectiveName -> llvm::omp::Directive = parallel do
+!PARSE-TREE: | | OmpClauseList -> OmpClause -> Reduction -> OmpReductionClause
+!PARSE-TREE: | | | Modifier -> OmpReductionIdentifier -> ProcedureDesignator -> Name = 'min'
+!PARSE-TREE: | | | OmpObjectList -> OmpObject -> Designator -> DataRef -> Name = 'small'
+!PARSE-TREE: | | Flags = None
+!PARSE-TREE: | DoConstruct
+
   do i = 1, n
      small%r = min(values(i)%r, small%r)
   end do
-  
+
   print *, values%r
   print *, "sum=", sum%r
   print *, "prod=", prod%r
diff --git a/flang/test/Parser/OpenMP/declare-reduction-operator.f90 b/flang/test/Parser/OpenMP/declare-reduction-operator.f90
index 7bfb78115b10d..c41daa596d2d0 100644
--- a/flang/test/Parser/OpenMP/declare-reduction-operator.f90
+++ b/flang/test/Parser/OpenMP/declare-reduction-operator.f90
@@ -16,27 +16,33 @@ subroutine reduce_1 ( n, tts )
   type(tt) :: tts(n)
   type(tt2) :: tts2(n)
 
-!CHECK: !$OMP DECLARE REDUCTION (+:tt: omp_out=tt(x=omp_out%x-omp_in%x,y=omp_out%y-omp_in%y)
+!CHECK: !$OMP DECLARE REDUCTION(+:tt: omp_out=tt(x=omp_out%x-omp_in%x,y=omp_out%y-omp_in%y)
 !CHECK: ) INITIALIZER(omp_priv=tt(x=0_4,y=0_4))
-!PARSE-TREE:  DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct
-!PARSE-TREE: Verbatim
-!PARSE-TREE: OmpReductionSpecifier
-!PARSE-TREE: OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add
-!PARSE-TREE: OmpReductionCombiner -> AssignmentStmt = 'omp_out=tt(x=omp_out%x-omp_in%x,y=omp_out%y-omp_in%y)'
-!PARSE-TREE:    OmpInitializerClause -> AssignmentStmt = 'omp_priv=tt(x=0_4,y=0_4)'
-  
+
+!PARSE-TREE: DeclarationConstruct -> SpecificationConstruct -> OpenMPDeclarativeConstruct -> OpenMPDeclareReductionConstruct -> OmpDirectiveSpecification
+!PARSE-TREE: | OmpDirectiveName -> llvm::omp::Directive = declare reduction
+!PARSE-TREE: | OmpArgumentList -> OmpArgument -> OmpReductionSpecifier
+!PARSE-TREE: | | OmpReductionIdentifier -> DefinedOperator -> IntrinsicOperator = Add
+!PARSE-TREE: | | OmpTypeNameList -> OmpTypeSpecifier -> TypeSpec -> ...
[truncated]

AddOmpSourceRange(x.source);
parser::OmpClauseList empty(std::list<parser::OmpClause>{});
auto &maybeClauses{std::get<std::optional<parser::OmpClauseList>>(x.t)};
ProcessReductionSpecifier(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where does ProcessReductionSpecifier get called now this has been removed?

Copy link
Contributor Author

@kparzysz kparzysz Sep 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

From "Pre(OmpDirectiveSpecification)": https://github.com/llvm/llvm-project/pull/160192/files#diff-811aa8b10475f6ccddbcb8e4e746c4ee840eac6ebd73c0152b5d33be961f07ecR1989-R1992

The only way to encounter OmpReductionSpecifier is as an argument to the DECLARE MAPPER DECLARE_REDUCTION directive, and the directive arguments are now resolved in the handler for OmpDirectiveSpecification.

Edit: fixed directive name.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Got it, thanks (for the benefit anyone else reading this, it is DECLARE REDUCTION not DECLARE MAPPER).

Base automatically changed from users/kparzysz/r04-declare-mapper to main September 23, 2025 13:50
Copy link
Contributor

@tblah tblah left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, thanks

@kparzysz kparzysz merged commit a4168a6 into main Sep 23, 2025
9 checks passed
@kparzysz kparzysz deleted the users/kparzysz/r05-declare-reduction branch September 23, 2025 17:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

flang:openmp flang:parser flang:semantics flang Flang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants