From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 1643) id 9974C3857BB4; Fri, 29 Jul 2022 14:44:52 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 9974C3857BB4 Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Thomas Schwinge To: gcc-cvs@gcc.gnu.org Subject: [gcc/devel/rust/master] expand: further improves the handling of recursive macros ... X-Act-Checkin: gcc X-Git-Author: liushuyu X-Git-Refname: refs/heads/devel/rust/master X-Git-Oldrev: 0632b1aa5f0ea1d0c9c4411e9ff3d05336736fbb X-Git-Newrev: 5e63ca064ab52d026112166fd1b6601c61591778 Message-Id: <20220729144452.9974C3857BB4@sourceware.org> Date: Fri, 29 Jul 2022 14:44:52 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Fri, 29 Jul 2022 14:44:52 -0000 https://gcc.gnu.org/g:5e63ca064ab52d026112166fd1b6601c61591778 commit 5e63ca064ab52d026112166fd1b6601c61591778 Author: liushuyu Date: Thu Jul 28 01:37:07 2022 -0600 expand: further improves the handling of recursive macros ... ... now all the attribute visitor that expands the macro fragment will recursively expand the macro using the unified expanding function `expand_macro_fragment_recursive` instead of expanding the fragment only once. Signed-off-by: Zixing Liu Diff: --- gcc/rust/expand/rust-attribute-visitor.cc | 27 +++++--------- gcc/rust/expand/rust-attribute-visitor.h | 42 ++++++++++++++++++++-- .../rust/compile/torture/macro-issue1403.rs | 23 ++++++++++++ 3 files changed, 71 insertions(+), 21 deletions(-) diff --git a/gcc/rust/expand/rust-attribute-visitor.cc b/gcc/rust/expand/rust-attribute-visitor.cc index bbcf2cbadd0..8016f9430eb 100644 --- a/gcc/rust/expand/rust-attribute-visitor.cc +++ b/gcc/rust/expand/rust-attribute-visitor.cc @@ -1122,12 +1122,12 @@ AttrVisitor::visit (AST::CallExpr &expr) stmt->accept_vis (*this); - auto fragment = expander.take_expanded_fragment (*this); - if (fragment.should_expand ()) + auto final_fragment = expand_macro_fragment_recursive (); + if (final_fragment.should_expand ()) { // Remove the current expanded invocation it = params.erase (it); - for (auto &node : fragment.get_nodes ()) + for (auto &node : final_fragment.get_nodes ()) { it = params.insert (it, node.take_expr ()); it++; @@ -3430,25 +3430,16 @@ AttrVisitor::visit (AST::BareFunctionType &type) void AttrVisitor::maybe_expand_expr (std::unique_ptr &expr) { - auto fragment = expander.take_expanded_fragment (*this); - unsigned int original_depth = expander.expansion_depth; - while (fragment.should_expand ()) - { - expr = fragment.take_expression_fragment (); - expander.expansion_depth++; - auto new_fragment = expander.take_expanded_fragment (*this); - if (new_fragment.is_error ()) - break; - fragment = std::move (new_fragment); - } - expander.expansion_depth = original_depth; + auto final_fragment = expand_macro_fragment_recursive (); + if (final_fragment.should_expand ()) + expr = final_fragment.take_expression_fragment (); } void AttrVisitor::maybe_expand_type (std::unique_ptr &type) { - auto fragment = expander.take_expanded_fragment (*this); - if (fragment.should_expand ()) - type = fragment.take_type_fragment (); + auto final_fragment = expand_macro_fragment_recursive (); + if (final_fragment.should_expand ()) + type = final_fragment.take_type_fragment (); } } // namespace Rust diff --git a/gcc/rust/expand/rust-attribute-visitor.h b/gcc/rust/expand/rust-attribute-visitor.h index 02208c6a7c7..0f9d1065334 100644 --- a/gcc/rust/expand/rust-attribute-visitor.h +++ b/gcc/rust/expand/rust-attribute-visitor.h @@ -17,6 +17,7 @@ // . #include "rust-ast-visitor.h" +#include "rust-ast.h" #include "rust-macro-expand.h" namespace Rust { @@ -42,6 +43,39 @@ public: void expand_trait_function_decl (AST::TraitFunctionDecl &decl); void expand_trait_method_decl (AST::TraitMethodDecl &decl); + /** + * Expand The current macro fragment recursively until it could not be + * expanded further. + * + * The return value checking works because correctly + * expanded fragment can never be an error (if the fragment can not be + * expanded, a stand-in error fragment will be returned; for fragments that + * could not be further expanded: the fragment prior to the expansion failure + * will be returned). + * + * @return Either the expanded fragment or an empty errored-out fragment + * indicating an expansion failure. + */ + AST::ASTFragment expand_macro_fragment_recursive () + { + auto fragment = expander.take_expanded_fragment (*this); + unsigned int original_depth = expander.expansion_depth; + auto final_fragment = AST::ASTFragment ({}, true); + + while (fragment.should_expand ()) + { + final_fragment = std::move (fragment); + expander.expansion_depth++; + // further expand the previously expanded macro fragment + auto new_fragment = expander.take_expanded_fragment (*this); + if (new_fragment.is_error ()) + break; + fragment = std::move (new_fragment); + } + expander.expansion_depth = original_depth; + return final_fragment; + } + /** * Expand a set of values, erasing them if they are marked for strip, and * replacing them with expanded macro nodes if necessary. @@ -67,11 +101,13 @@ public: // mark for stripping if required value->accept_vis (*this); - auto fragment = expander.take_expanded_fragment (*this); - if (fragment.should_expand ()) + // recursively expand the children + auto final_fragment = expand_macro_fragment_recursive (); + + if (final_fragment.should_expand ()) { it = values.erase (it); - for (auto &node : fragment.get_nodes ()) + for (auto &node : final_fragment.get_nodes ()) { auto new_node = extractor (node); if (new_node != nullptr && !new_node->is_marked_for_strip ()) diff --git a/gcc/testsuite/rust/compile/torture/macro-issue1403.rs b/gcc/testsuite/rust/compile/torture/macro-issue1403.rs new file mode 100644 index 00000000000..7fe6c51053c --- /dev/null +++ b/gcc/testsuite/rust/compile/torture/macro-issue1403.rs @@ -0,0 +1,23 @@ +macro_rules! stmt { + ($s:stmt) => { + $s + }; + ($s:stmt, $($ss:stmt),*) => { + $s; + stmt!($($ss),*); + }; +} + +fn main() { + stmt!( + struct S; + ); + stmt!( + struct A;, + struct B;, + struct C;, + struct D;, + struct E; + ); +} +