[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