llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-flang-fir-hlfir 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 _______________________________________________ llvm-branch-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits
