diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2022-07-29 12:32:30 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2022-07-29 12:32:30 +0000 |
commit | 2d824b796cde571d270f4c20af8183dbd93614d5 (patch) | |
tree | ad242172f61a255644b98e4f4fd73010b5d770b7 | |
parent | 7f1685d7f60c29eeabbd3c556428b67142201df2 (diff) | |
parent | 5e63ca064ab52d026112166fd1b6601c61591778 (diff) | |
download | gcc-2d824b796cde571d270f4c20af8183dbd93614d5.zip gcc-2d824b796cde571d270f4c20af8183dbd93614d5.tar.gz gcc-2d824b796cde571d270f4c20af8183dbd93614d5.tar.bz2 |
Merge #1421
1421: expand: further improves the handling of recursive macros r=CohenArthur a=liushuyu
- 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.
Fixes #1403
Co-authored-by: liushuyu <liushuyu011@gmail.com>
-rw-r--r-- | gcc/rust/expand/rust-attribute-visitor.cc | 27 | ||||
-rw-r--r-- | gcc/rust/expand/rust-attribute-visitor.h | 42 | ||||
-rw-r--r-- | gcc/testsuite/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 bbcf2cb..8016f94 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<AST::Expr> &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<AST::Type> &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 02208c6..0f9d106 100644 --- a/gcc/rust/expand/rust-attribute-visitor.h +++ b/gcc/rust/expand/rust-attribute-visitor.h @@ -17,6 +17,7 @@ // <http://www.gnu.org/licenses/>. #include "rust-ast-visitor.h" +#include "rust-ast.h" #include "rust-macro-expand.h" namespace Rust { @@ -43,6 +44,39 @@ public: 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. * This function is slightly different from `expand_pointer_allow_strip` as @@ -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 0000000..7fe6c51 --- /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; + ); +} + |