[llvm-branch-commits] [flang] [flang] Add traits to more AST nodes (PR #175566)

via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Mon Jan 12 07:44:47 PST 2026


llvmbot wrote:


<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-flang-parser

Author: Krzysztof Parzyszek (kparzysz)

<details>
<summary>Changes</summary>

Follow-up to PR175211.

There are still a few AST nodes that don't have any of the standard traits (Wrapper/Tuple/etc). Because of that they require special handling in the parse tree visitor.

Convert a subset of these nodes to the typical format, and remove the special cases from the parse tree visitor.

---

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


11 Files Affected:

- (modified) flang/include/flang/Parser/parse-tree-visitor.h (-110) 
- (modified) flang/include/flang/Parser/parse-tree.h (+16-37) 
- (modified) flang/lib/Lower/Bridge.cpp (+2-1) 
- (modified) flang/lib/Lower/PFTBuilder.cpp (+4-2) 
- (modified) flang/lib/Parser/parse-tree.cpp (+9-7) 
- (modified) flang/lib/Parser/unparse.cpp (+22-16) 
- (modified) flang/lib/Semantics/check-do-forall.cpp (+2-2) 
- (modified) flang/lib/Semantics/expression.cpp (+11-9) 
- (modified) flang/lib/Semantics/program-tree.cpp (+3-2) 
- (modified) flang/lib/Semantics/resolve-names.cpp (+49-23) 
- (modified) flang/lib/Semantics/tools.cpp (+3-3) 


``````````diff
diff --git a/flang/include/flang/Parser/parse-tree-visitor.h b/flang/include/flang/Parser/parse-tree-visitor.h
index 61470f8c30604..191e74ee89f1c 100644
--- a/flang/include/flang/Parser/parse-tree-visitor.h
+++ b/flang/include/flang/Parser/parse-tree-visitor.h
@@ -433,38 +433,6 @@ struct ParseTreeVisitorLookupScope {
         x, mutator);
   }
 
-  template <typename V> static void Walk(const CallStmt &x, V &visitor) {
-    if (visitor.Pre(x)) {
-      Walk(x.source, visitor);
-      Walk(x.call, visitor);
-      Walk(x.chevrons, visitor);
-      visitor.Post(x);
-    }
-  }
-  template <typename M> static void Walk(CallStmt &x, M &mutator) {
-    if (mutator.Pre(x)) {
-      Walk(x.source, mutator);
-      Walk(x.call, mutator);
-      Walk(x.chevrons, mutator);
-      mutator.Post(x);
-    }
-  }
-  template <typename V> static void Walk(const PartRef &x, V &visitor) {
-    if (visitor.Pre(x)) {
-      Walk(x.name, visitor);
-      Walk(x.subscripts, visitor);
-      Walk(x.imageSelector, visitor);
-      visitor.Post(x);
-    }
-  }
-  template <typename M> static void Walk(PartRef &x, M &mutator) {
-    if (mutator.Pre(x)) {
-      Walk(x.name, mutator);
-      Walk(x.subscripts, mutator);
-      Walk(x.imageSelector, mutator);
-      mutator.Post(x);
-    }
-  }
   template <typename V> static void Walk(const ReadStmt &x, V &visitor) {
     if (visitor.Pre(x)) {
       Walk(x.iounit, visitor);
@@ -484,35 +452,6 @@ struct ParseTreeVisitorLookupScope {
     }
   }
   template <typename V>
-  static void Walk(const RealLiteralConstant &x, V &visitor) {
-    if (visitor.Pre(x)) {
-      Walk(x.real, visitor);
-      Walk(x.kind, visitor);
-      visitor.Post(x);
-    }
-  }
-  template <typename M> static void Walk(RealLiteralConstant &x, M &mutator) {
-    if (mutator.Pre(x)) {
-      Walk(x.real, mutator);
-      Walk(x.kind, mutator);
-      mutator.Post(x);
-    }
-  }
-  template <typename V>
-  static void Walk(const RealLiteralConstant::Real &x, V &visitor) {
-    if (visitor.Pre(x)) {
-      Walk(x.source, visitor);
-      visitor.Post(x);
-    }
-  }
-  template <typename M>
-  static void Walk(RealLiteralConstant::Real &x, M &mutator) {
-    if (mutator.Pre(x)) {
-      Walk(x.source, mutator);
-      mutator.Post(x);
-    }
-  }
-  template <typename V>
   static void Walk(const StructureComponent &x, V &visitor) {
     if (visitor.Pre(x)) {
       Walk(x.base, visitor);
@@ -527,55 +466,6 @@ struct ParseTreeVisitorLookupScope {
       mutator.Post(x);
     }
   }
-  template <typename V> static void Walk(const Suffix &x, V &visitor) {
-    if (visitor.Pre(x)) {
-      Walk(x.binding, visitor);
-      Walk(x.resultName, visitor);
-      visitor.Post(x);
-    }
-  }
-  template <typename M> static void Walk(Suffix &x, M &mutator) {
-    if (mutator.Pre(x)) {
-      Walk(x.binding, mutator);
-      Walk(x.resultName, mutator);
-      mutator.Post(x);
-    }
-  }
-  template <typename V>
-  static void Walk(const TypeBoundProcedureStmt::WithInterface &x, V &visitor) {
-    if (visitor.Pre(x)) {
-      Walk(x.interfaceName, visitor);
-      Walk(x.attributes, visitor);
-      Walk(x.bindingNames, visitor);
-      visitor.Post(x);
-    }
-  }
-  template <typename M>
-  static void Walk(TypeBoundProcedureStmt::WithInterface &x, M &mutator) {
-    if (mutator.Pre(x)) {
-      Walk(x.interfaceName, mutator);
-      Walk(x.attributes, mutator);
-      Walk(x.bindingNames, mutator);
-      mutator.Post(x);
-    }
-  }
-  template <typename V>
-  static void Walk(
-      const TypeBoundProcedureStmt::WithoutInterface &x, V &visitor) {
-    if (visitor.Pre(x)) {
-      Walk(x.attributes, visitor);
-      Walk(x.declarations, visitor);
-      visitor.Post(x);
-    }
-  }
-  template <typename M>
-  static void Walk(TypeBoundProcedureStmt::WithoutInterface &x, M &mutator) {
-    if (mutator.Pre(x)) {
-      Walk(x.attributes, mutator);
-      Walk(x.declarations, mutator);
-      mutator.Post(x);
-    }
-  }
   template <typename V> static void Walk(const UseStmt &x, V &visitor) {
     if (visitor.Pre(x)) {
       Walk(x.nature, visitor);
diff --git a/flang/include/flang/Parser/parse-tree.h b/flang/include/flang/Parser/parse-tree.h
index 37c0f699361eb..1d72c1cb1c80e 100644
--- a/flang/include/flang/Parser/parse-tree.h
+++ b/flang/include/flang/Parser/parse-tree.h
@@ -807,16 +807,14 @@ enum class Sign { Positive, Negative };
 // R715 significand -> digit-string . [digit-string] | . digit-string
 // R717 exponent -> signed-digit-string
 struct RealLiteralConstant {
-  BOILERPLATE(RealLiteralConstant);
+  TUPLE_CLASS_BOILERPLATE(RealLiteralConstant);
   struct Real {
+    using EmptyTrait = std::true_type;
     COPY_AND_ASSIGN_BOILERPLATE(Real);
     Real() {}
     CharBlock source;
   };
-  RealLiteralConstant(Real &&r, std::optional<KindParam> &&k)
-      : real{std::move(r)}, kind{std::move(k)} {}
-  Real real;
-  std::optional<KindParam> kind;
+  std::tuple<Real, std::optional<KindParam>> t;
 };
 
 // R713 signed-real-literal-constant -> [sign] real-literal-constant
@@ -1133,21 +1131,12 @@ struct TypeBoundProcDecl {
 struct TypeBoundProcedureStmt {
   UNION_CLASS_BOILERPLATE(TypeBoundProcedureStmt);
   struct WithoutInterface {
-    BOILERPLATE(WithoutInterface);
-    WithoutInterface(
-        std::list<BindAttr> &&as, std::list<TypeBoundProcDecl> &&ds)
-        : attributes(std::move(as)), declarations(std::move(ds)) {}
-    std::list<BindAttr> attributes;
-    std::list<TypeBoundProcDecl> declarations;
+    TUPLE_CLASS_BOILERPLATE(WithoutInterface);
+    std::tuple<std::list<BindAttr>, std::list<TypeBoundProcDecl>> t;
   };
   struct WithInterface {
-    BOILERPLATE(WithInterface);
-    WithInterface(Name &&n, std::list<BindAttr> &&as, std::list<Name> &&bs)
-        : interfaceName(std::move(n)), attributes(std::move(as)),
-          bindingNames(std::move(bs)) {}
-    Name interfaceName;
-    std::list<BindAttr> attributes;
-    std::list<Name> bindingNames;
+    TUPLE_CLASS_BOILERPLATE(WithInterface);
+    std::tuple<Name, std::list<BindAttr>, std::list<Name>> t;
   };
   std::variant<WithoutInterface, WithInterface> u;
 };
@@ -1794,14 +1783,8 @@ struct Expr {
 
 // R912 part-ref -> part-name [( section-subscript-list )] [image-selector]
 struct PartRef {
-  BOILERPLATE(PartRef);
-  PartRef(Name &&n, std::list<SectionSubscript> &&ss,
-      std::optional<ImageSelector> &&is)
-      : name{std::move(n)}, subscripts(std::move(ss)),
-        imageSelector{std::move(is)} {}
-  Name name;
-  std::list<SectionSubscript> subscripts;
-  std::optional<ImageSelector> imageSelector;
+  TUPLE_CLASS_BOILERPLATE(PartRef);
+  std::tuple<Name, std::list<SectionSubscript>, std::optional<ImageSelector>> t;
 };
 
 // R911 data-ref -> part-ref [% part-ref]...
@@ -3121,13 +3104,10 @@ struct PrefixSpec {
 //         proc-language-binding-spec [RESULT ( result-name )] |
 //         RESULT ( result-name ) [proc-language-binding-spec]
 struct Suffix {
-  BOILERPLATE(Suffix);
+  TUPLE_CLASS_BOILERPLATE(Suffix);
   Suffix(LanguageBindingSpec &&lbs, std::optional<Name> &&rn)
-      : binding(std::move(lbs)), resultName(std::move(rn)) {}
-  Suffix(Name &&rn, std::optional<LanguageBindingSpec> &&lbs)
-      : binding(std::move(lbs)), resultName(std::move(rn)) {}
-  std::optional<LanguageBindingSpec> binding;
-  std::optional<Name> resultName;
+      : t(std::move(rn), std::move(lbs)) {}
+  std::tuple<std::optional<Name>, std::optional<LanguageBindingSpec>> t;
 };
 
 // R1530 function-stmt ->
@@ -3262,7 +3242,7 @@ struct FunctionReference {
 // (CUDA) chevrons -> <<< * | scalar-expr, scalar-expr [,
 //          scalar-expr [, scalar-int-expr ] ] >>>
 struct CallStmt {
-  BOILERPLATE(CallStmt);
+  TUPLE_CLASS_BOILERPLATE(CallStmt);
   WRAPPER_CLASS(StarOrExpr, std::optional<ScalarExpr>);
   struct Chevrons {
     TUPLE_CLASS_BOILERPLATE(Chevrons);
@@ -3271,10 +3251,9 @@ struct CallStmt {
         t;
   };
   explicit CallStmt(ProcedureDesignator &&pd, std::optional<Chevrons> &&ch,
-      std::list<ActualArgSpec> &&args)
-      : call{std::move(pd), std::move(args)}, chevrons{std::move(ch)} {}
-  Call call;
-  std::optional<Chevrons> chevrons;
+      std::list<ActualArgSpec> &&args) :
+      CallStmt(Call{std::move(pd), std::move(args)}, std::move(ch)) {}
+  std::tuple<Call, std::optional<Chevrons>> t;
   CharBlock source;
   mutable TypedCall typedCall; // filled by semantics
 };
diff --git a/flang/lib/Lower/Bridge.cpp b/flang/lib/Lower/Bridge.cpp
index 9224bc2be1028..609050511f6c9 100644
--- a/flang/lib/Lower/Bridge.cpp
+++ b/flang/lib/Lower/Bridge.cpp
@@ -2048,8 +2048,9 @@ class FirConverter : public Fortran::lower::AbstractConverter {
     llvm::SmallVector<int64_t> indexList;
     llvm::SmallVector<Fortran::parser::Label> labelList;
     int64_t index = 0;
+    const auto &call{std::get<Fortran::parser::Call>(stmt.t)};
     for (const Fortran::parser::ActualArgSpec &arg :
-         std::get<std::list<Fortran::parser::ActualArgSpec>>(stmt.call.t)) {
+         std::get<std::list<Fortran::parser::ActualArgSpec>>(call.t)) {
       const auto &actual = std::get<Fortran::parser::ActualArg>(arg.t);
       if (const auto *altReturn =
               std::get_if<Fortran::parser::AltReturnSpec>(&actual.u)) {
diff --git a/flang/lib/Lower/PFTBuilder.cpp b/flang/lib/Lower/PFTBuilder.cpp
index 2dc7032b85f42..1a7fb41f3273c 100644
--- a/flang/lib/Lower/PFTBuilder.cpp
+++ b/flang/lib/Lower/PFTBuilder.cpp
@@ -142,8 +142,9 @@ class PFTBuilder {
   ///  - 17.4p5 (The rounding modes)
   ///  - 17.6p1 (Halting)
   void checkForFPEnvironmentCalls(const parser::CallStmt &callStmt) {
+    const auto &call = std::get<parser::Call>(callStmt.t);
     const auto *callName = std::get_if<parser::Name>(
-        &std::get<parser::ProcedureDesignator>(callStmt.call.t).u);
+        &std::get<parser::ProcedureDesignator>(call.t).u);
     if (!callName)
       return;
     const Fortran::semantics::Symbol &procSym = callName->symbol->GetUltimate();
@@ -919,8 +920,9 @@ class PFTBuilder {
           // Action statements (except IO statements)
           [&](const parser::CallStmt &s) {
             // Look for alternate return specifiers.
+            const auto &call = std::get<parser::Call>(s.t);
             const auto &args =
-                std::get<std::list<parser::ActualArgSpec>>(s.call.t);
+                std::get<std::list<parser::ActualArgSpec>>(call.t);
             for (const auto &arg : args) {
               const auto &actual = std::get<parser::ActualArg>(arg.t);
               if (const auto *altReturn =
diff --git a/flang/lib/Parser/parse-tree.cpp b/flang/lib/Parser/parse-tree.cpp
index dae1912afa99e..819470a43b0c8 100644
--- a/flang/lib/Parser/parse-tree.cpp
+++ b/flang/lib/Parser/parse-tree.cpp
@@ -50,20 +50,22 @@ bool Designator::EndsInBareName() const {
 }
 
 // R911 data-ref -> part-ref [% part-ref]...
-DataRef::DataRef(std::list<PartRef> &&prl) : u{std::move(prl.front().name)} {
+DataRef::DataRef(std::list<PartRef> &&prl)
+    : u{std::move(std::get<Name>(prl.front().t))} {
   for (bool first{true}; !prl.empty(); first = false, prl.pop_front()) {
-    PartRef &pr{prl.front()};
+    auto &&[name, subscripts, imageSelector]{prl.front().t};
+    // PartRef &pr{prl.front()};
     if (!first) {
       u = common::Indirection<StructureComponent>::Make(
-          std::move(*this), std::move(pr.name));
+          std::move(*this), std::move(name));
     }
-    if (!pr.subscripts.empty()) {
+    if (!subscripts.empty()) {
       u = common::Indirection<ArrayElement>::Make(
-          std::move(*this), std::move(pr.subscripts));
+          std::move(*this), std::move(subscripts));
     }
-    if (pr.imageSelector) {
+    if (imageSelector) {
       u = common::Indirection<CoindexedNamedObject>::Make(
-          std::move(*this), std::move(*pr.imageSelector));
+          std::move(*this), std::move(*imageSelector));
     }
   }
 }
diff --git a/flang/lib/Parser/unparse.cpp b/flang/lib/Parser/unparse.cpp
index 9b31454537df5..0465b67aed08d 100644
--- a/flang/lib/Parser/unparse.cpp
+++ b/flang/lib/Parser/unparse.cpp
@@ -198,7 +198,8 @@ class UnparseVisitor {
     Put(x == Sign::Negative ? '-' : '+');
   }
   void Unparse(const RealLiteralConstant &x) { // R714, R715
-    Put(x.real.source.ToString()), Walk("_", x.kind);
+    const auto &[real, kind]{x.t};
+    Put(real.source.ToString()), Walk("_", kind);
   }
   void Unparse(const ComplexLiteralConstant &x) { // R718 - R720
     Put('('), Walk(x.t, ","), Put(')');
@@ -371,13 +372,15 @@ class UnparseVisitor {
     Word("PRIVATE");
   }
   void Unparse(const TypeBoundProcedureStmt::WithoutInterface &x) { // R749
-    Word("PROCEDURE"), Walk(", ", x.attributes, ", ");
-    Put(" :: "), Walk(x.declarations, ", ");
+    const auto &[attributes, declarations]{x.t};
+    Word("PROCEDURE"), Walk(", ", attributes, ", ");
+    Put(" :: "), Walk(declarations, ", ");
   }
   void Unparse(const TypeBoundProcedureStmt::WithInterface &x) {
-    Word("PROCEDURE("), Walk(x.interfaceName), Put("), ");
-    Walk(x.attributes);
-    Put(" :: "), Walk(x.bindingNames, ", ");
+    const auto &[interfaceName, attributes, bindingNames]{x.t};
+    Word("PROCEDURE("), Walk(interfaceName), Put("), ");
+    Walk(attributes);
+    Put(" :: "), Walk(bindingNames, ", ");
   }
   void Unparse(const TypeBoundProcDecl &x) { // R750
     Walk(std::get<Name>(x.t));
@@ -789,9 +792,10 @@ class UnparseVisitor {
     Walk(x.t, ":");
   }
   void Unparse(const PartRef &x) { // R912
-    Walk(x.name);
-    Walk("(", x.subscripts, ",", ")");
-    Walk(x.imageSelector);
+    const auto &[name, subscripts, imageSelector]{x.t};
+    Walk(name);
+    Walk("(", subscripts, ",", ")");
+    Walk(imageSelector);
   }
   void Unparse(const StructureComponent &x) { // R913
     Walk(x.base);
@@ -1692,15 +1696,16 @@ class UnparseVisitor {
     Put('('), Walk(std::get<std::list<ActualArgSpec>>(x.v.t), ", "), Put(')');
   }
   void Unparse(const CallStmt &x) { // R1521
+    const auto &[call, chevrons]{x.t};
     if (asFortran_ && x.typedCall.get()) {
       Put(' ');
       asFortran_->call(out_, *x.typedCall);
       Put('\n');
     } else {
-      const auto &pd{std::get<ProcedureDesignator>(x.call.t)};
+      const auto &pd{std::get<ProcedureDesignator>(call.t)};
       Word("CALL "), Walk(pd);
-      Walk("<<<", x.chevrons, ">>>");
-      const auto &args{std::get<std::list<ActualArgSpec>>(x.call.t)};
+      Walk("<<<", chevrons, ">>>");
+      const auto &args{std::get<std::list<ActualArgSpec>>(call.t)};
       if (args.empty()) {
         if (std::holds_alternative<ProcComponentRef>(pd.u)) {
           Put("()"); // pgf90 crashes on CALL to tbp without parentheses
@@ -1745,11 +1750,12 @@ class UnparseVisitor {
     Walk(" ", std::get<std::optional<Suffix>>(x.t)), Indent();
   }
   void Unparse(const Suffix &x) { // R1532
-    if (x.resultName) {
-      Word("RESULT("), Walk(x.resultName), Put(')');
-      Walk(" ", x.binding);
+    const auto &[resultName, binding]{x.t};
+    if (resultName) {
+      Word("RESULT("), Walk(resultName), Put(')');
+      Walk(" ", binding);
     } else {
-      Walk(x.binding);
+      Walk(binding);
     }
   }
   void Unparse(const EndFunctionStmt &x) { // R1533
diff --git a/flang/lib/Semantics/check-do-forall.cpp b/flang/lib/Semantics/check-do-forall.cpp
index 8a473406b8200..c90479d9e352e 100644
--- a/flang/lib/Semantics/check-do-forall.cpp
+++ b/flang/lib/Semantics/check-do-forall.cpp
@@ -1101,8 +1101,8 @@ static void CheckIfArgIsDoVar(const evaluate::ActualArgument &arg,
 // messages.
 void DoForallChecker::Leave(const parser::CallStmt &callStmt) {
   if (const auto &typedCall{callStmt.typedCall}) {
-    const auto &parsedArgs{
-        std::get<std::list<parser::ActualArgSpec>>(callStmt.call.t)};
+    const auto &call{std::get<parser::Call>(callStmt.t)};
+    const auto &parsedArgs{std::get<std::list<parser::ActualArgSpec>>(call.t)};
     auto parsedArgIter{parsedArgs.begin()};
     const evaluate::ActualArguments &checkedArgs{typedCall->arguments()};
     for (const auto &checkedOptionalArg : checkedArgs) {
diff --git a/flang/lib/Semantics/expression.cpp b/flang/lib/Semantics/expression.cpp
index b3643e0d35d5f..ece5d23bb59d2 100644
--- a/flang/lib/Semantics/expression.cpp
+++ b/flang/lib/Semantics/expression.cpp
@@ -869,19 +869,20 @@ struct RealTypeVisitor {
 
 // Reads a real literal constant and encodes it with the right kind.
 MaybeExpr ExpressionAnalyzer::Analyze(const parser::RealLiteralConstant &x) {
+  const auto &[xreal, xkind](x.t);
   // Use a local message context around the real literal for better
   // provenance on any messages.
-  auto restorer{GetContextualMessages().SetLocation(x.real.source)};
+  auto restorer{GetContextualMessages().SetLocation(xreal.source)};
   // If a kind parameter appears, it defines the kind of the literal and the
   // letter used in an exponent part must be 'E' (e.g., the 'E' in
   // "6.02214E+23").  In the absence of an explicit kind parameter, any
   // exponent letter determines the kind.  Otherwise, defaults apply.
   auto &defaults{context_.defaultKinds()};
   int defaultKind{defaults.GetDefaultKind(TypeCategory::Real)};
-  const char *end{x.real.source.end()};
+  const char *end{xreal.source.end()};
   char expoLetter{' '};
   std::optional<int> letterKind;
-  for (const char *p{x.real.source.begin()}; p < end; ++p) {
+  for (const char *p{xreal.source.begin()}; p < end; ++p) {
     if (parser::IsLetter(*p)) {
       expoLetter = *p;
       switch (expoLetter) {
@@ -905,20 +906,20 @@ MaybeExpr ExpressionAnalyzer::Analyze(const parser::RealLiteralConstant &x) {
   }
   // C716 requires 'E' as an exponent.
   // Extension: allow exponent-letter matching the kind-param.
-  auto kind{AnalyzeKindParam(x.kind, defaultKind)};
+  auto kind{AnalyzeKindParam(xkind, defaultKind)};
   if (letterKind && expoLetter != 'e') {
     if (kind != *letterKind) {
       Warn(common::LanguageFeature::ExponentMatchingKindParam,
           "Explicit kind parameter on real constant disagrees with exponent letter '%c'"_warn_en_US,
           expoLetter);
-    } else if (x.kind) {
+    } else if (xkind) {
       Warn(common::LanguageFeature::ExponentMatchingKindParam,
           "Explicit kind parameter together with non-'E' exponent letter is not standard"_port_en_US);
     }
   }
-  bool isDefaultKind{!x.kind && letterKind.value_or('e') == 'e'};
+  bool isDefaultKind{!xkind && letterKind.value_or('e') == 'e'};
   auto result{common::SearchTypes(RealTypeVisitor{
-      kind, x.real.source, GetFoldingContext(), isDefaultKind})};
+      kind, xreal.source, GetFoldingContext(), isDefaultKind})};
   if (!result) { // C717
     Say("Unsupported REAL(KIND=%d)"_err_en_US, kind);
   }
@@ -3404,7 +3405,8 @@ std::optional<Chevrons> ExpressionAnalyzer::AnalyzeChevrons(
         which);
     return false;
   }};
-  if (const auto &chevrons{call.chevrons}) {
+  if (const auto &chevrons{
+          std::get<std::optional<parser::CallStmt::Chevrons>>(call.t)}) {
     auto &starOrExpr{std::get<0>(chevrons->t)};
     if (starOrExpr.v) {
       if (auto expr{Analyze(*starOrExpr.v)};
@@ -3504,7 +3506,7 @@ static bool HasAlternateReturns(const evaluate::ActualArguments &args) {
 }
 
 void ExpressionAnalyzer::Analyze(const parser::CallStmt &callStmt) {
-  const parser::Call &call{callStmt.call};
+  const auto &call{std::get<parser::Call>(callStmt.t)};
   auto restorer{GetContextualMessages().SetLocation(callStmt.source)};
   ArgumentAnalyzer analyzer{*this, callStmt.source, true /* isProcedureCall */};
   const auto &actualArgList{std::get<std::list<parser::ActualArgSpec>>(call.t)};
diff --git a/flang/lib/Semantics/program-tree.cpp b/flang/lib/Semantics/program-tree.cpp
index 86085e78803a2..89517982de67c 100644
--- a/flang/lib/Semantics/program-tree.cpp
+++ b/flang/lib/Semantics/program-tree.cpp
@@ -161,8 +161,9 @@ std::optional<ProgramTree> ProgramTree::Build(
   const parser::LanguageBindingSpec *bindingSpec{};
   if (const auto &suffix{
           std::get<std::optional<parser::Suffix>>(stmt.statement.t)}) {
-    if (suffix->binding) {
-      bindingSpec = &*suffix->binding;
+    if (const auto &binding{
+            std::get<std::optional<parser::LanguageBindingSpec>>(suffix->t)}) {
+      bindingSpec = &*binding;
     }
   }
   return BuildSubprogramTree(name, context, x)
diff --git a/flang/lib/Semantics/resolve-names.cpp b/flang/lib/Semantics/resolve-names.cpp
index 527be8645ff81..04d7...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/175566


More information about the llvm-branch-commits mailing list