public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc/devel/rust/master] expand: further improves the handling of recursive macros ...
@ 2022-07-29 14:44 Thomas Schwinge
0 siblings, 0 replies; only message in thread
From: Thomas Schwinge @ 2022-07-29 14:44 UTC (permalink / raw)
To: gcc-cvs
https://gcc.gnu.org/g:5e63ca064ab52d026112166fd1b6601c61591778
commit 5e63ca064ab52d026112166fd1b6601c61591778
Author: liushuyu <liushuyu011@gmail.com>
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 <liushuyu011@gmail.com>
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<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 02208c6a7c7..0f9d1065334 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 {
@@ -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;
+ );
+}
+
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2022-07-29 14:44 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-07-29 14:44 [gcc/devel/rust/master] expand: further improves the handling of recursive macros Thomas Schwinge
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).