aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2022-07-29 12:32:30 +0000
committerGitHub <noreply@github.com>2022-07-29 12:32:30 +0000
commit2d824b796cde571d270f4c20af8183dbd93614d5 (patch)
treead242172f61a255644b98e4f4fd73010b5d770b7
parent7f1685d7f60c29eeabbd3c556428b67142201df2 (diff)
parent5e63ca064ab52d026112166fd1b6601c61591778 (diff)
downloadgcc-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.cc27
-rw-r--r--gcc/rust/expand/rust-attribute-visitor.h42
-rw-r--r--gcc/testsuite/rust/compile/torture/macro-issue1403.rs23
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;
+ );
+}
+