aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorArthur Cohen <arthur.cohen@embecosm.com>2023-03-20 04:17:04 +0100
committerArthur Cohen <arthur.cohen@embecosm.com>2024-01-16 18:28:38 +0100
commitd85089ea28c99eabbee89fd434bea748d1623427 (patch)
treea7f1831df6209fa97509abd8ac30309ce527e39d /gcc
parenta7382ca757ed535e7bc74782038104ef5ac59694 (diff)
downloadgcc-d85089ea28c99eabbee89fd434bea748d1623427.zip
gcc-d85089ea28c99eabbee89fd434bea748d1623427.tar.gz
gcc-d85089ea28c99eabbee89fd434bea748d1623427.tar.bz2
gccrs: expand: Add new ExpandVisitor class
This class takes care of actually performing the macro expansion by calling into the MacroExpander for each node of a given AST, leaving the job of cfg-stripping nodes to the AttrVisitor. gcc/rust/ChangeLog: * Make-lang.in: Add new object file. * expand/rust-attribute-visitor.cc (AttrVisitor::go): Visit all items of a crate. (AttrVisitor::expand_struct_fields): Do not perform macro expansion anymore. (AttrVisitor::expand_function_params): Likewise. (AttrVisitor::expand_generic_args): Likewise. (AttrVisitor::expand_qualified_path_type): Likewise. (AttrVisitor::expand_self_param): Likewise. (AttrVisitor::expand_trait_function_decl): Likewise. (AttrVisitor::expand_trait_method_decl): Likewise. (AttrVisitor::visit): Likewise. (AttrVisitor::maybe_expand_expr): Remove function. (AttrVisitor::maybe_expand_type): Likewise. * expand/rust-attribute-visitor.h: Do not keep MacroExpander inside AttrVisitor anymore. * expand/rust-macro-expand.h (struct MacroExpander): Turn ContextType into an enum class for more type safety. * expand/rust-macro-expand.cc (MacroExpander::expand_crate): Use new ContextType API. * rust-session-manager.cc (Session::expansion): Call into ExpandVisitor. * expand/rust-expand-visitor.cc: New file. * expand/rust-expand-visitor.h: New file. gcc/testsuite/ChangeLog: * rust/compile/macro49.rs: New test. * rust/compile/macro50.rs: New test.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/Make-lang.in1
-rw-r--r--gcc/rust/expand/rust-attribute-visitor.cc252
-rw-r--r--gcc/rust/expand/rust-attribute-visitor.h64
-rw-r--r--gcc/rust/expand/rust-expand-visitor.cc1340
-rw-r--r--gcc/rust/expand/rust-expand-visitor.h320
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc8
-rw-r--r--gcc/rust/expand/rust-macro-expand.h2
-rw-r--r--gcc/rust/rust-session-manager.cc7
-rw-r--r--gcc/testsuite/rust/compile/macro49.rs9
-rw-r--r--gcc/testsuite/rust/compile/macro50.rs10
10 files changed, 1711 insertions, 302 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in
index 8f48390..083a44e 100644
--- a/gcc/rust/Make-lang.in
+++ b/gcc/rust/Make-lang.in
@@ -82,6 +82,7 @@ GRS_OBJS = \
rust/rust-compile-resolve-path.o \
rust/rust-macro-expand.o \
rust/rust-attribute-visitor.o \
+ rust/rust-expand-visitor.o \
rust/rust-macro-invoc-lexer.o \
rust/rust-macro-substitute-ctx.o \
rust/rust-macro-builtins.o \
diff --git a/gcc/rust/expand/rust-attribute-visitor.cc b/gcc/rust/expand/rust-attribute-visitor.cc
index cad07a4..6178428 100644
--- a/gcc/rust/expand/rust-attribute-visitor.cc
+++ b/gcc/rust/expand/rust-attribute-visitor.cc
@@ -141,6 +141,20 @@ AttrVisitor::go (AST::Crate &crate)
crate.strip_crate ();
// TODO: maybe create warning here? probably not desired behaviour
}
+
+ auto &items = crate.items;
+
+ for (auto it = items.begin (); it != items.end ();)
+ {
+ auto &item = *it;
+ item->accept_vis (*this);
+
+ if (item->is_marked_for_strip ())
+ it = items.erase (it);
+ else
+ it++;
+ }
+
// expand module attributes?
}
@@ -160,20 +174,14 @@ AttrVisitor::expand_struct_fields (std::vector<AST::StructField> &fields)
continue;
}
- expander.push_context (MacroExpander::ContextType::TYPE);
-
// expand sub-types of type, but can't strip type itself
auto &type = field.get_field_type ();
type->accept_vis (*this);
- maybe_expand_type (type);
-
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (),
"cannot strip type in this position");
- expander.pop_context ();
-
// if nothing else happens, increment
++it;
}
@@ -209,8 +217,6 @@ AttrVisitor::expand_tuple_fields (std::vector<AST::TupleField> &fields)
void
AttrVisitor::expand_function_params (std::vector<AST::FunctionParam> &params)
{
- expander.push_context (MacroExpander::ContextType::TYPE);
-
for (auto it = params.begin (); it != params.end ();)
{
auto &param = *it;
@@ -233,8 +239,6 @@ AttrVisitor::expand_function_params (std::vector<AST::FunctionParam> &params)
auto &type = param.get_type ();
type->accept_vis (*this);
- maybe_expand_type (type);
-
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (),
"cannot strip type in this position");
@@ -242,8 +246,6 @@ AttrVisitor::expand_function_params (std::vector<AST::FunctionParam> &params)
// increment
++it;
}
-
- expander.pop_context ();
}
void
@@ -252,8 +254,6 @@ AttrVisitor::expand_generic_args (AST::GenericArgs &args)
// lifetime args can't be expanded
// FIXME: Can we have macro invocations for lifetimes?
- expander.push_context (MacroExpander::ContextType::TYPE);
-
// expand type args - strip sub-types only
for (auto &arg : args.get_generic_args ())
{
@@ -262,7 +262,6 @@ AttrVisitor::expand_generic_args (AST::GenericArgs &args)
case AST::GenericArg::Kind::Type: {
auto &type = arg.get_type ();
type->accept_vis (*this);
- maybe_expand_type (type);
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (),
@@ -272,7 +271,6 @@ AttrVisitor::expand_generic_args (AST::GenericArgs &args)
case AST::GenericArg::Kind::Const: {
auto &expr = arg.get_expression ();
expr->accept_vis (*this);
- maybe_expand_expr (expr);
if (expr->is_marked_for_strip ())
rust_error_at (expr->get_locus (),
@@ -289,8 +287,6 @@ AttrVisitor::expand_generic_args (AST::GenericArgs &args)
}
}
- expander.pop_context ();
-
// FIXME: Can we have macro invocations in generic type bindings?
// expand binding args - strip sub-types only
for (auto &binding : args.get_binding_args ())
@@ -307,15 +303,9 @@ AttrVisitor::expand_generic_args (AST::GenericArgs &args)
void
AttrVisitor::expand_qualified_path_type (AST::QualifiedPathType &path_type)
{
- expander.push_context (MacroExpander::ContextType::TYPE);
-
auto &type = path_type.get_type ();
type->accept_vis (*this);
- maybe_expand_type (type);
-
- expander.pop_context ();
-
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (), "cannot strip type in this position");
@@ -353,17 +343,12 @@ AttrVisitor::AttrVisitor::expand_closure_params (
if (param.has_type_given ())
{
- expander.push_context (MacroExpander::ContextType::TYPE);
auto &type = param.get_type ();
type->accept_vis (*this);
- maybe_expand_type (type);
-
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (),
"cannot strip type in this position");
-
- expander.pop_context ();
}
// increment if found nothing else so far
@@ -376,17 +361,12 @@ AttrVisitor::expand_self_param (AST::SelfParam &self_param)
{
if (self_param.has_type ())
{
- expander.push_context (MacroExpander::ContextType::TYPE);
auto &type = self_param.get_type ();
type->accept_vis (*this);
- maybe_expand_type (type);
-
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (),
"cannot strip type in this position");
-
- expander.pop_context ();
}
/* TODO: maybe check for invariants being violated - e.g. both type and
* lifetime? */
@@ -413,18 +393,12 @@ AttrVisitor::expand_trait_function_decl (AST::TraitFunctionDecl &decl)
if (decl.has_return_type ())
{
- expander.push_context (MacroExpander::ContextType::TYPE);
-
auto &return_type = decl.get_return_type ();
return_type->accept_vis (*this);
- maybe_expand_type (return_type);
-
if (return_type->is_marked_for_strip ())
rust_error_at (return_type->get_locus (),
"cannot strip type in this position");
-
- expander.pop_context ();
}
if (decl.has_where_clause ())
@@ -449,18 +423,12 @@ AttrVisitor::expand_trait_method_decl (AST::TraitMethodDecl &decl)
if (decl.has_return_type ())
{
- expander.push_context (MacroExpander::ContextType::TYPE);
-
auto &return_type = decl.get_return_type ();
return_type->accept_vis (*this);
- maybe_expand_type (return_type);
-
if (return_type->is_marked_for_strip ())
rust_error_at (return_type->get_locus (),
"cannot strip type in this position");
-
- expander.pop_context ();
}
if (decl.has_where_clause ())
@@ -525,7 +493,6 @@ AttrVisitor::visit (AST::MacroInvocation &macro_invoc)
// I don't think any macro token trees can be stripped in any way
// TODO: maybe have cfg! macro stripping behaviour here?
- expander.expand_invoc (macro_invoc, macro_invoc.has_semicolon ());
}
void
@@ -575,18 +542,12 @@ AttrVisitor::visit (AST::TypePathSegmentFunction &segment)
if (type_path_function.has_return_type ())
{
- expander.push_context (MacroExpander::ContextType::TYPE);
-
auto &return_type = type_path_function.get_return_type ();
return_type->accept_vis (*this);
- maybe_expand_type (return_type);
-
if (return_type->is_marked_for_strip ())
rust_error_at (return_type->get_locus (),
"cannot strip type in this position");
-
- expander.pop_context ();
}
}
void
@@ -745,13 +706,11 @@ AttrVisitor::visit (AST::ArithmeticOrLogicalExpr &expr)
* with outer expr */
auto &l_expr = expr.get_left_expr ();
l_expr->accept_vis (*this);
- maybe_expand_expr (l_expr);
/* should syntactically not have outer attributes, though this may
* not have worked in practice */
auto &r_expr = expr.get_right_expr ();
r_expr->accept_vis (*this);
- maybe_expand_expr (r_expr);
// ensure that they are not marked for strip
if (expr.get_left_expr ()->is_marked_for_strip ())
@@ -774,13 +733,11 @@ AttrVisitor::visit (AST::ComparisonExpr &expr)
* with outer expr */
auto &l_expr = expr.get_left_expr ();
l_expr->accept_vis (*this);
- maybe_expand_expr (l_expr);
/* should syntactically not have outer attributes, though this may
* not have worked in practice */
auto &r_expr = expr.get_right_expr ();
r_expr->accept_vis (*this);
- maybe_expand_expr (r_expr);
// ensure that they are not marked for strip
if (expr.get_left_expr ()->is_marked_for_strip ())
@@ -803,13 +760,11 @@ AttrVisitor::visit (AST::LazyBooleanExpr &expr)
* with outer expr */
auto &l_expr = expr.get_left_expr ();
l_expr->accept_vis (*this);
- maybe_expand_expr (l_expr);
/* should syntactically not have outer attributes, though this may
* not have worked in practice */
auto &r_expr = expr.get_right_expr ();
r_expr->accept_vis (*this);
- maybe_expand_expr (r_expr);
// ensure that they are not marked for strip
if (expr.get_left_expr ()->is_marked_for_strip ())
@@ -859,13 +814,11 @@ AttrVisitor::visit (AST::AssignmentExpr &expr)
* with outer expr */
auto &l_expr = expr.get_left_expr ();
l_expr->accept_vis (*this);
- maybe_expand_expr (l_expr);
/* should syntactically not have outer attributes, though this may
* not have worked in practice */
auto &r_expr = expr.get_right_expr ();
r_expr->accept_vis (*this);
- maybe_expand_expr (r_expr);
// ensure that they are not marked for strip
if (expr.get_left_expr ()->is_marked_for_strip ())
@@ -888,13 +841,11 @@ AttrVisitor::visit (AST::CompoundAssignmentExpr &expr)
* with outer expr */
auto &l_expr = expr.get_left_expr ();
l_expr->accept_vis (*this);
- maybe_expand_expr (l_expr);
/* should syntactically not have outer attributes, though this may
* not have worked in practice */
auto &r_expr = expr.get_right_expr ();
r_expr->accept_vis (*this);
- maybe_expand_expr (r_expr);
// ensure that they are not marked for strip
if (expr.get_left_expr ()->is_marked_for_strip ())
@@ -1238,29 +1189,6 @@ AttrVisitor::visit (AST::CallExpr &expr)
// FIXME: Arthur: Figure out how to refactor this - This is similar to
// expanding items in the crate or stmts in blocks
expand_pointer_allow_strip (expr.get_params ());
- auto &params = expr.get_params ();
- for (auto it = params.begin (); it != params.end ();)
- {
- auto &stmt = *it;
-
- stmt->accept_vis (*this);
-
- auto final_fragment = expander.take_expanded_fragment ();
- if (final_fragment.should_expand ())
- {
- // Remove the current expanded invocation
- it = params.erase (it);
- for (auto &node : final_fragment.get_nodes ())
- {
- it = params.insert (it, node.take_expr ());
- it++;
- }
- }
- else if (stmt->is_marked_for_strip ())
- it = params.erase (it);
- else
- it++;
- }
}
void
AttrVisitor::visit (AST::MethodCallExpr &expr)
@@ -1356,13 +1284,7 @@ AttrVisitor::visit (AST::BlockExpr &expr)
return;
}
- std::function<std::unique_ptr<AST::Stmt> (AST::SingleASTNode)> extractor
- = [] (AST::SingleASTNode node) { return node.take_stmt (); };
-
- expand_macro_children (MacroExpander::ContextType::BLOCK,
- expr.get_statements (), extractor);
-
- expander.push_context (MacroExpander::ContextType::BLOCK);
+ expand_pointer_allow_strip (expr.get_statements ());
// strip tail expression if exists - can actually fully remove it
if (expr.has_tail_expr ())
@@ -1370,12 +1292,10 @@ AttrVisitor::visit (AST::BlockExpr &expr)
auto &tail_expr = expr.get_tail_expr ();
tail_expr->accept_vis (*this);
- maybe_expand_expr (tail_expr);
if (tail_expr->is_marked_for_strip ())
expr.strip_tail_expr ();
}
- expander.pop_context ();
}
void
@@ -1393,19 +1313,13 @@ AttrVisitor::visit (AST::ClosureExprInnerTyped &expr)
* allowed by spec */
expand_closure_params (expr.get_params ());
- expander.push_context (MacroExpander::ContextType::TYPE);
-
// can't strip return type, but can strip sub-types
auto &type = expr.get_return_type ();
type->accept_vis (*this);
- maybe_expand_type (type);
-
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (), "cannot strip type in this position");
- expander.pop_context ();
-
// can't strip expression itself, but can strip sub-expressions
auto &definition_block = expr.get_definition_block ();
definition_block->accept_vis (*this);
@@ -1737,7 +1651,6 @@ AttrVisitor::visit (AST::IfExpr &expr)
// can't strip condition expr itself, but can strip sub-expressions
auto &condition_expr = expr.get_condition_expr ();
condition_expr->accept_vis (*this);
- maybe_expand_expr (condition_expr);
if (condition_expr->is_marked_for_strip ())
rust_error_at (condition_expr->get_locus (),
"cannot strip expression in this position - outer "
@@ -1765,7 +1678,6 @@ AttrVisitor::visit (AST::IfExprConseqElse &expr)
// can't strip condition expr itself, but can strip sub-expressions
auto &condition_expr = expr.get_condition_expr ();
condition_expr->accept_vis (*this);
- maybe_expand_expr (condition_expr);
if (condition_expr->is_marked_for_strip ())
rust_error_at (condition_expr->get_locus (),
"cannot strip expression in this position - outer "
@@ -1801,7 +1713,6 @@ AttrVisitor::visit (AST::IfExprConseqIf &expr)
// can't strip condition expr itself, but can strip sub-expressions
auto &condition_expr = expr.get_condition_expr ();
condition_expr->accept_vis (*this);
- maybe_expand_expr (condition_expr);
if (condition_expr->is_marked_for_strip ())
rust_error_at (condition_expr->get_locus (),
"cannot strip expression in this position - outer "
@@ -1837,7 +1748,6 @@ AttrVisitor::visit (AST::IfExprConseqIfLet &expr)
// can't strip condition expr itself, but can strip sub-expressions
auto &condition_expr = expr.get_condition_expr ();
condition_expr->accept_vis (*this);
- maybe_expand_expr (condition_expr);
if (condition_expr->is_marked_for_strip ())
rust_error_at (condition_expr->get_locus (),
"cannot strip expression in this position - outer "
@@ -2156,17 +2066,12 @@ AttrVisitor::visit (AST::TypeParam &param)
if (param.has_type ())
{
- expander.push_context (MacroExpander::ContextType::TYPE);
auto &type = param.get_type ();
type->accept_vis (*this);
- maybe_expand_type (type);
-
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (),
"cannot strip type in this position");
-
- expander.pop_context ();
}
}
void
@@ -2179,18 +2084,12 @@ AttrVisitor::visit (AST::TypeBoundWhereClauseItem &item)
{
// for lifetimes shouldn't require
- expander.push_context (MacroExpander::ContextType::TYPE);
-
auto &type = item.get_type ();
type->accept_vis (*this);
- maybe_expand_type (type);
-
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (), "cannot strip type in this position");
- expander.pop_context ();
-
// don't strip directly, only components of bounds
for (auto &bound : item.get_type_param_bounds ())
bound->accept_vis (*this);
@@ -2221,18 +2120,12 @@ AttrVisitor::visit (AST::Method &method)
if (method.has_return_type ())
{
- expander.push_context (MacroExpander::ContextType::TYPE);
-
auto &return_type = method.get_return_type ();
return_type->accept_vis (*this);
- maybe_expand_type (return_type);
-
if (return_type->is_marked_for_strip ())
rust_error_at (return_type->get_locus (),
"cannot strip type in this position");
-
- expander.pop_context ();
}
if (method.has_where_clause ())
@@ -2339,18 +2232,12 @@ AttrVisitor::visit (AST::Function &function)
if (function.has_return_type ())
{
- expander.push_context (MacroExpander::ContextType::TYPE);
-
auto &return_type = function.get_return_type ();
return_type->accept_vis (*this);
- maybe_expand_type (return_type);
-
if (return_type->is_marked_for_strip ())
rust_error_at (return_type->get_locus (),
"cannot strip type in this position");
-
- expander.pop_context ();
}
if (function.has_where_clause ())
@@ -2406,10 +2293,6 @@ AttrVisitor::visit (AST::StructStruct &struct_item)
if (struct_item.has_where_clause ())
expand_where_clause (struct_item.get_where_clause ());
-
- /* strip struct fields if required - this is presumably
- * allowed by spec */
- expand_struct_fields (struct_item.get_fields ());
}
void
AttrVisitor::visit (AST::TupleStruct &tuple_struct)
@@ -2550,19 +2433,13 @@ AttrVisitor::visit (AST::ConstantItem &const_item)
return;
}
- expander.push_context (MacroExpander::ContextType::TYPE);
-
// strip any sub-types
auto &type = const_item.get_type ();
type->accept_vis (*this);
- maybe_expand_type (type);
-
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (), "cannot strip type in this position");
- expander.pop_context ();
-
/* strip any internal sub-expressions - expression itself isn't
* allowed to have external attributes in this position so can't be
* stripped. */
@@ -2584,19 +2461,13 @@ AttrVisitor::visit (AST::StaticItem &static_item)
return;
}
- expander.push_context (MacroExpander::ContextType::TYPE);
-
// strip any sub-types
auto &type = static_item.get_type ();
type->accept_vis (*this);
- maybe_expand_type (type);
-
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (), "cannot strip type in this position");
- expander.pop_context ();
-
/* strip any internal sub-expressions - expression itself isn't
* allowed to have external attributes in this position so can't be
* stripped. */
@@ -2670,19 +2541,13 @@ AttrVisitor::visit (AST::TraitItemConst &item)
return;
}
- expander.push_context (MacroExpander::ContextType::TYPE);
-
// strip any sub-types
auto &type = item.get_type ();
type->accept_vis (*this);
- maybe_expand_type (type);
-
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (), "cannot strip type in this position");
- expander.pop_context ();
-
/* strip any internal sub-expressions - expression itself isn't
* allowed to have external attributes in this position so can't be
* stripped */
@@ -2747,11 +2612,7 @@ AttrVisitor::visit (AST::Trait &trait)
if (trait.has_where_clause ())
expand_where_clause (trait.get_where_clause ());
- std::function<std::unique_ptr<AST::TraitItem> (AST::SingleASTNode)> extractor
- = [] (AST::SingleASTNode node) { return node.take_trait_item (); };
-
- expand_macro_children (MacroExpander::ContextType::TRAIT,
- trait.get_trait_items (), extractor);
+ expand_pointer_allow_strip (trait.get_trait_items ());
}
void
AttrVisitor::visit (AST::InherentImpl &impl)
@@ -2776,26 +2637,16 @@ AttrVisitor::visit (AST::InherentImpl &impl)
for (auto &param : impl.get_generic_params ())
param->accept_vis (*this);
- expander.push_context (MacroExpander::ContextType::ITEM);
-
auto &type = impl.get_type ();
type->accept_vis (*this);
- maybe_expand_type (type);
-
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (), "cannot strip type in this position");
- expander.pop_context ();
-
if (impl.has_where_clause ())
expand_where_clause (impl.get_where_clause ());
- std::function<std::unique_ptr<AST::InherentImplItem> (AST::SingleASTNode)>
- extractor = [] (AST::SingleASTNode node) { return node.take_impl_item (); };
-
- expand_macro_children (MacroExpander::ContextType::IMPL,
- impl.get_impl_items (), extractor);
+ expand_pointer_allow_strip (impl.get_impl_items ());
}
void
AttrVisitor::visit (AST::TraitImpl &impl)
@@ -2820,18 +2671,12 @@ AttrVisitor::visit (AST::TraitImpl &impl)
for (auto &param : impl.get_generic_params ())
param->accept_vis (*this);
- expander.push_context (MacroExpander::ContextType::ITEM);
-
auto &type = impl.get_type ();
type->accept_vis (*this);
- maybe_expand_type (type);
-
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (), "cannot strip type in this position");
- expander.pop_context ();
-
auto &trait_path = impl.get_trait_path ();
visit (trait_path);
if (trait_path.is_marked_for_strip ())
@@ -2841,12 +2686,7 @@ AttrVisitor::visit (AST::TraitImpl &impl)
if (impl.has_where_clause ())
expand_where_clause (impl.get_where_clause ());
- std::function<std::unique_ptr<AST::TraitImplItem> (AST::SingleASTNode)>
- extractor
- = [] (AST::SingleASTNode node) { return node.take_trait_impl_item (); };
-
- expand_macro_children (MacroExpander::ContextType::TRAIT_IMPL,
- impl.get_impl_items (), extractor);
+ expand_pointer_allow_strip (impl.get_impl_items ());
}
void
@@ -2873,17 +2713,11 @@ AttrVisitor::visit (AST::ExternalStaticItem &item)
return;
}
- expander.push_context (MacroExpander::ContextType::TYPE);
-
auto &type = item.get_type ();
type->accept_vis (*this);
- maybe_expand_type (type);
-
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (), "cannot strip type in this position");
-
- expander.pop_context ();
}
void
@@ -2916,19 +2750,13 @@ AttrVisitor::visit (AST::ExternalFunctionItem &item)
continue;
}
- expander.push_context (MacroExpander::ContextType::TYPE);
-
auto &type = param.get_type ();
type->accept_vis (*this);
- maybe_expand_type (type);
-
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (),
"cannot strip type in this position");
- expander.pop_context ();
-
// increment if nothing else happens
++it;
}
@@ -2941,18 +2769,12 @@ AttrVisitor::visit (AST::ExternalFunctionItem &item)
if (item.has_return_type ())
{
- expander.push_context (MacroExpander::ContextType::TYPE);
-
auto &return_type = item.get_return_type ();
return_type->accept_vis (*this);
- maybe_expand_type (return_type);
-
if (return_type->is_marked_for_strip ())
rust_error_at (return_type->get_locus (),
"cannot strip type in this position");
-
- expander.pop_context ();
}
if (item.has_where_clause ())
@@ -2978,12 +2800,7 @@ AttrVisitor::visit (AST::ExternBlock &block)
return;
}
- std::function<std::unique_ptr<AST::ExternalItem> (AST::SingleASTNode)>
- extractor
- = [] (AST::SingleASTNode node) { return node.take_external_item (); };
-
- expand_macro_children (MacroExpander::ContextType::EXTERN,
- block.get_extern_items (), extractor);
+ expand_pointer_allow_strip (block.get_extern_items ());
}
// I don't think it would be possible to strip macros without expansion
@@ -3327,18 +3144,12 @@ AttrVisitor::visit (AST::LetStmt &stmt)
// similar for type
if (stmt.has_type ())
{
- expander.push_context (MacroExpander::ContextType::TYPE);
-
auto &type = stmt.get_type ();
type->accept_vis (*this);
- maybe_expand_type (type);
-
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (),
"cannot strip type in this position");
-
- expander.pop_context ();
}
/* strip any internal sub-expressions - expression itself isn't
@@ -3353,8 +3164,6 @@ AttrVisitor::visit (AST::LetStmt &stmt)
rust_error_at (init_expr->get_locus (),
"cannot strip expression in this position - outer "
"attributes not allowed");
-
- maybe_expand_expr (init_expr);
}
}
void
@@ -3531,19 +3340,13 @@ AttrVisitor::visit (AST::BareFunctionType &type)
continue;
}
- expander.push_context (MacroExpander::ContextType::TYPE);
-
auto &type = param.get_type ();
type->accept_vis (*this);
- maybe_expand_type (type);
-
if (type->is_marked_for_strip ())
rust_error_at (type->get_locus (),
"cannot strip type in this position");
- expander.pop_context ();
-
// increment if nothing else happens
++it;
}
@@ -3566,21 +3369,4 @@ AttrVisitor::visit (AST::BareFunctionType &type)
// no where clause, apparently
}
-void
-AttrVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr)
-{
- auto final_fragment = expander.take_expanded_fragment ();
- if (final_fragment.should_expand ()
- && final_fragment.is_expression_fragment ())
- expr = final_fragment.take_expression_fragment ();
-}
-
-void
-AttrVisitor::maybe_expand_type (std::unique_ptr<AST::Type> &type)
-{
- auto final_fragment = expander.take_expanded_fragment ();
- if (final_fragment.should_expand () && final_fragment.is_type_fragment ())
- 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 1ad425a..734d607 100644
--- a/gcc/rust/expand/rust-attribute-visitor.h
+++ b/gcc/rust/expand/rust-attribute-visitor.h
@@ -25,12 +25,8 @@ namespace Rust {
class AttrVisitor : public AST::ASTVisitor
{
private:
- MacroExpander &expander;
- void maybe_expand_expr (std::unique_ptr<AST::Expr> &expr);
- void maybe_expand_type (std::unique_ptr<AST::Type> &expr);
-
public:
- AttrVisitor (MacroExpander &expander) : expander (expander) {}
+ AttrVisitor () {}
/* Run the AttrVisitor on an entire crate */
void go (AST::Crate &crate);
@@ -47,58 +43,10 @@ public:
void expand_trait_method_decl (AST::TraitMethodDecl &decl);
/**
- * 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
- * it can only be called in certain expansion contexts - where macro
- * invocations are allowed.
+ * Expand a set of values, erasing them if they are marked for strip.
*
- * @param ctx Context to use for macro expansion
* @param values Iterable reference over values to replace or erase
- * @param extractor Function to call when replacing values with the content
- * of an expanded AST node
*/
- template <typename T, typename U>
- void expand_macro_children (MacroExpander::ContextType ctx, T &values,
- std::function<U (AST::SingleASTNode)> extractor)
- {
- expander.push_context (ctx);
-
- for (auto it = values.begin (); it != values.end ();)
- {
- auto &value = *it;
-
- // mark for stripping if required
- value->accept_vis (*this);
-
- auto final_fragment = expander.take_expanded_fragment ();
-
- if (final_fragment.should_expand ())
- {
- it = values.erase (it);
- for (auto &node : final_fragment.get_nodes ())
- {
- auto new_node = extractor (node);
- if (new_node != nullptr && !new_node->is_marked_for_strip ())
- {
- it = values.insert (it, std::move (new_node));
- it++;
- }
- }
- }
- else if (value->is_marked_for_strip ())
- {
- it = values.erase (it);
- }
- else
- {
- ++it;
- }
- }
-
- expander.pop_context ();
- }
-
template <typename T> void expand_pointer_allow_strip (T &values)
{
for (auto it = values.begin (); it != values.end ();)
@@ -108,13 +56,9 @@ public:
// mark for stripping if required
value->accept_vis (*this);
if (value->is_marked_for_strip ())
- {
- it = values.erase (it);
- }
+ it = values.erase (it);
else
- {
- ++it;
- }
+ ++it;
}
}
diff --git a/gcc/rust/expand/rust-expand-visitor.cc b/gcc/rust/expand/rust-expand-visitor.cc
new file mode 100644
index 0000000..2a5dc79
--- /dev/null
+++ b/gcc/rust/expand/rust-expand-visitor.cc
@@ -0,0 +1,1340 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-expand-visitor.h"
+
+namespace Rust {
+
+/* Expand all of the macro invocations currently contained in a crate */
+void
+ExpandVisitor::go (AST::Crate &crate)
+{
+ expander.push_context (MacroExpander::ContextType::ITEM);
+
+ // expand attributes recursively and strip items if required
+ // AttrVisitor attr_visitor (*this);
+ auto &items = crate.items;
+ for (auto it = items.begin (); it != items.end ();)
+ {
+ auto &item = *it;
+ item->accept_vis (*this);
+
+ auto fragment = expander.take_expanded_fragment ();
+ if (fragment.should_expand ())
+ {
+ // Remove the current expanded invocation
+ it = items.erase (it);
+ for (auto &node : fragment.get_nodes ())
+ {
+ it = items.insert (it, node.take_item ());
+ it++;
+ }
+ }
+ else
+ it++;
+ }
+
+ expander.pop_context ();
+}
+
+void
+ExpandVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr)
+{
+ // FIXME: ARTHUR: Why isn't there a ContextType::EXPR? We can only
+ // reach `parse_expr` once in MacroExpander::transcribe_rule(), but it
+ // would make things clearer wouldn't it?
+ expr->accept_vis (*this);
+
+ auto final_fragment = expander.take_expanded_fragment ();
+ if (final_fragment.should_expand ()
+ && final_fragment.is_expression_fragment ())
+ expr = final_fragment.take_expression_fragment ();
+}
+
+void
+ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::Type> &type)
+{
+ expander.push_context (MacroExpander::ContextType::TYPE);
+
+ type->accept_vis (*this);
+ auto final_fragment = expander.take_expanded_fragment ();
+ if (final_fragment.should_expand () && final_fragment.is_type_fragment ())
+ type = final_fragment.take_type_fragment ();
+
+ expander.pop_context ();
+}
+
+// FIXME: Can this be refactored into a `scoped` method? Which takes a
+// ContextType as parameter and a lambda? And maybe just an std::vector<T>&?
+void
+ExpandVisitor::expand_struct_fields (std::vector<AST::StructField> &fields)
+{
+ for (auto &field : fields)
+ maybe_expand_type (field.get_field_type ());
+}
+
+void
+ExpandVisitor::expand_tuple_fields (std::vector<AST::TupleField> &fields)
+{
+ for (auto &field : fields)
+ maybe_expand_type (field.get_field_type ());
+}
+
+// FIXME: This can definitely be refactored with the method above
+void
+ExpandVisitor::expand_function_params (std::vector<AST::FunctionParam> &params)
+{
+ for (auto &param : params)
+ maybe_expand_type (param.get_type ());
+}
+
+void
+ExpandVisitor::expand_generic_args (AST::GenericArgs &args)
+{
+ for (auto &arg : args.get_generic_args ())
+ {
+ switch (arg.get_kind ())
+ {
+ case AST::GenericArg::Kind::Type:
+ maybe_expand_type (arg.get_type ());
+ break;
+ case AST::GenericArg::Kind::Const:
+ maybe_expand_expr (arg.get_expression ());
+ break;
+ default:
+ break;
+ // FIXME: Figure out what to do here if there is ambiguity. Since the
+ // resolver comes after the expansion, we need to figure out a way to
+ // strip ambiguous values here
+ // TODO: ARTHUR: Probably add a `mark_as_strip` method to `GenericArg`
+ // or something. This would clean up this whole thing
+ }
+ }
+
+ // FIXME: Can we have macro invocations in generic type bindings?
+ // expand binding args - strip sub-types only
+ // FIXME: ARTHUR: This needs a test! Foo<Item = macro!()>
+ for (auto &binding : args.get_binding_args ())
+ maybe_expand_type (binding.get_type ());
+}
+
+void
+ExpandVisitor::expand_qualified_path_type (AST::QualifiedPathType &path_type)
+{
+ maybe_expand_type (path_type.get_type ());
+
+ // FIXME: ARTHUR: Can we do macro expansion in there? Needs a test!
+ if (path_type.has_as_clause ())
+ path_type.get_as_type_path ().accept_vis (*this);
+}
+
+void
+ExpandVisitor::expand_closure_params (std::vector<AST::ClosureParam> &params)
+{
+ for (auto &param : params)
+ if (param.has_type_given ())
+ maybe_expand_type (param.get_type ());
+}
+
+void
+ExpandVisitor::expand_self_param (AST::SelfParam &self_param)
+{
+ if (self_param.has_type ())
+ maybe_expand_type (self_param.get_type ());
+
+ /* TODO: maybe check for invariants being violated - e.g. both type and
+ * lifetime? */
+}
+
+void
+ExpandVisitor::expand_where_clause (AST::WhereClause &where_clause)
+{
+ for (auto &item : where_clause.get_items ())
+ visit (item);
+}
+
+void
+ExpandVisitor::expand_trait_function_decl (AST::TraitFunctionDecl &decl)
+{
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto &param : decl.get_generic_params ())
+ visit (param);
+
+ /* strip function parameters if required - this is specifically
+ * allowed by spec */
+ expand_function_params (decl.get_function_params ());
+
+ if (decl.has_return_type ())
+ maybe_expand_type (decl.get_return_type ());
+
+ if (decl.has_where_clause ())
+ expand_where_clause (decl.get_where_clause ());
+}
+
+void
+ExpandVisitor::expand_trait_method_decl (AST::TraitMethodDecl &decl)
+{
+ for (auto &param : decl.get_generic_params ())
+ visit (param);
+
+ /* assuming you can't strip self param - wouldn't be a method
+ * anymore. spec allows outer attrs on self param, but doesn't
+ * specify whether cfg is used. */
+ expand_self_param (decl.get_self_param ());
+
+ /* strip function parameters if required - this is specifically
+ * allowed by spec */
+ expand_function_params (decl.get_function_params ());
+
+ if (decl.has_return_type ())
+
+ maybe_expand_type (decl.get_return_type ());
+
+ if (decl.has_where_clause ())
+ expand_where_clause (decl.get_where_clause ());
+}
+
+void
+ExpandVisitor::visit (AST::Token &)
+{}
+
+void
+ExpandVisitor::visit (AST::DelimTokenTree &)
+{}
+
+void
+ExpandVisitor::visit (AST::AttrInputMetaItemContainer &)
+{}
+
+void
+ExpandVisitor::visit (AST::IdentifierExpr &ident_expr)
+{}
+
+void
+ExpandVisitor::visit (AST::Lifetime &)
+{}
+
+void
+ExpandVisitor::visit (AST::LifetimeParam &)
+{}
+
+void
+ExpandVisitor::visit (AST::ConstGenericParam &)
+{}
+
+void
+ExpandVisitor::visit (AST::MacroInvocation &macro_invoc)
+{
+ // TODO: Can we do the AST fragment replacing here? Probably not, right?
+ expander.expand_invoc (macro_invoc, macro_invoc.has_semicolon ());
+}
+
+void
+ExpandVisitor::visit (AST::PathInExpression &path)
+{
+ for (auto &segment : path.get_segments ())
+ if (segment.has_generic_args ())
+ expand_generic_args (segment.get_generic_args ());
+}
+
+void
+ExpandVisitor::visit (AST::TypePathSegment &)
+{}
+
+void
+ExpandVisitor::visit (AST::TypePathSegmentGeneric &segment)
+{}
+
+void
+ExpandVisitor::visit (AST::TypePathSegmentFunction &segment)
+{
+ auto &type_path_function = segment.get_type_path_function ();
+
+ for (auto &type : type_path_function.get_params ())
+ visit (type);
+
+ if (type_path_function.has_return_type ())
+ maybe_expand_type (type_path_function.get_return_type ());
+}
+
+void
+ExpandVisitor::visit (AST::TypePath &path)
+{
+ for (auto &segment : path.get_segments ())
+ visit (segment);
+}
+
+void
+ExpandVisitor::visit (AST::QualifiedPathInExpression &path)
+{
+ expand_qualified_path_type (path.get_qualified_path_type ());
+
+ for (auto &segment : path.get_segments ())
+ if (segment.has_generic_args ())
+ expand_generic_args (segment.get_generic_args ());
+}
+
+void
+ExpandVisitor::visit (AST::QualifiedPathInType &path)
+{
+ expand_qualified_path_type (path.get_qualified_path_type ());
+
+ // this shouldn't strip any segments, but can strip inside them
+ for (auto &segment : path.get_segments ())
+ visit (segment);
+}
+
+void
+ExpandVisitor::visit (AST::LiteralExpr &expr)
+{}
+
+void
+ExpandVisitor::visit (AST::AttrInputLiteral &)
+{}
+
+void
+ExpandVisitor::visit (AST::MetaItemLitExpr &)
+{}
+
+void
+ExpandVisitor::visit (AST::MetaItemPathLit &)
+{}
+
+void
+ExpandVisitor::visit (AST::BorrowExpr &expr)
+{
+ visit (expr.get_borrowed_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::DereferenceExpr &expr)
+{
+ visit (expr.get_dereferenced_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::ErrorPropagationExpr &expr)
+{
+ visit (expr.get_propagating_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::NegationExpr &expr)
+{
+ visit (expr.get_negated_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::ArithmeticOrLogicalExpr &expr)
+{
+ maybe_expand_expr (expr.get_left_expr ());
+ maybe_expand_expr (expr.get_right_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::ComparisonExpr &expr)
+{
+ maybe_expand_expr (expr.get_left_expr ());
+ maybe_expand_expr (expr.get_right_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::LazyBooleanExpr &expr)
+{
+ maybe_expand_expr (expr.get_left_expr ());
+ maybe_expand_expr (expr.get_right_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::TypeCastExpr &expr)
+{
+ visit (expr.get_casted_expr ());
+
+ visit (expr.get_type_to_cast_to ());
+}
+
+void
+ExpandVisitor::visit (AST::AssignmentExpr &expr)
+{
+ maybe_expand_expr (expr.get_left_expr ());
+ maybe_expand_expr (expr.get_right_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::CompoundAssignmentExpr &expr)
+{
+ maybe_expand_expr (expr.get_left_expr ());
+ maybe_expand_expr (expr.get_right_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::GroupedExpr &expr)
+{
+ visit (expr.get_expr_in_parens ());
+}
+
+void
+ExpandVisitor::visit (AST::ArrayElemsValues &elems)
+{
+ for (auto &elem : elems.get_values ())
+ visit (elem);
+}
+
+void
+ExpandVisitor::visit (AST::ArrayElemsCopied &elems)
+{
+ visit (elems.get_elem_to_copy ());
+ visit (elems.get_num_copies ());
+}
+
+void
+ExpandVisitor::visit (AST::ArrayExpr &expr)
+{
+ visit (expr.get_array_elems ());
+}
+
+void
+ExpandVisitor::visit (AST::ArrayIndexExpr &expr)
+{
+ visit (expr.get_array_expr ());
+ visit (expr.get_index_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::TupleExpr &expr)
+{
+ for (auto &element : expr.get_tuple_elems ())
+ visit (element);
+}
+
+void
+ExpandVisitor::visit (AST::TupleIndexExpr &expr)
+{
+ visit (expr.get_tuple_expr ());
+
+ // We can't have macro invocations for tuple indexes, right? Need a test!
+}
+
+void
+ExpandVisitor::visit (AST::StructExprStruct &expr)
+{}
+
+void
+ExpandVisitor::visit (AST::StructExprFieldIdentifier &)
+{}
+
+void
+ExpandVisitor::visit (AST::StructExprFieldIdentifierValue &field)
+{
+ visit (field.get_value ());
+}
+
+void
+ExpandVisitor::visit (AST::StructExprFieldIndexValue &field)
+{
+ visit (field.get_value ());
+}
+
+void
+ExpandVisitor::visit (AST::StructExprStructFields &expr)
+{
+ for (auto &field : expr.get_fields ())
+ visit (field);
+
+ if (expr.has_struct_base ())
+ visit (expr.get_struct_base ().get_base_struct ());
+}
+
+void
+ExpandVisitor::visit (AST::StructExprStructBase &expr)
+{
+ visit (expr.get_struct_base ().get_base_struct ());
+}
+
+void
+ExpandVisitor::visit (AST::CallExpr &expr)
+{
+ visit (expr.get_function_expr ());
+
+ for (auto &param : expr.get_params ())
+ maybe_expand_expr (param);
+}
+
+void
+ExpandVisitor::visit (AST::MethodCallExpr &expr)
+{
+ visit (expr.get_receiver_expr ());
+
+ for (auto &param : expr.get_params ())
+ maybe_expand_expr (param);
+}
+
+void
+ExpandVisitor::visit (AST::FieldAccessExpr &expr)
+{
+ visit (expr.get_receiver_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::ClosureExprInner &expr)
+{
+ expand_closure_params (expr.get_params ());
+
+ visit (expr.get_definition_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::BlockExpr &expr)
+{
+ std::function<std::unique_ptr<AST::Stmt> (AST::SingleASTNode)> extractor
+ = [] (AST::SingleASTNode node) { return node.take_stmt (); };
+
+ expand_macro_children (MacroExpander::ContextType::BLOCK,
+ expr.get_statements (), extractor);
+
+ expander.push_context (MacroExpander::ContextType::BLOCK);
+
+ if (expr.has_tail_expr ())
+ maybe_expand_expr (expr.get_tail_expr ());
+
+ expander.pop_context ();
+}
+
+void
+ExpandVisitor::visit (AST::ClosureExprInnerTyped &expr)
+{
+ expand_closure_params (expr.get_params ());
+
+ maybe_expand_type (expr.get_return_type ());
+
+ visit (expr.get_definition_block ());
+}
+
+void
+ExpandVisitor::visit (AST::ContinueExpr &expr)
+{}
+
+void
+ExpandVisitor::visit (AST::BreakExpr &expr)
+{
+ if (expr.has_break_expr ())
+ visit (expr.get_break_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::RangeFromToExpr &expr)
+{
+ visit (expr.get_from_expr ());
+ visit (expr.get_to_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::RangeFromExpr &expr)
+{
+ visit (expr.get_from_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::RangeToExpr &expr)
+{
+ visit (expr.get_to_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::RangeFullExpr &)
+{}
+
+void
+ExpandVisitor::visit (AST::RangeFromToInclExpr &expr)
+{
+ visit (expr.get_from_expr ());
+ visit (expr.get_to_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::RangeToInclExpr &expr)
+{
+ visit (expr.get_to_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::ReturnExpr &expr)
+{
+ if (expr.has_returned_expr ())
+ visit (expr.get_returned_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::UnsafeBlockExpr &expr)
+{
+ visit (expr.get_block_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::LoopExpr &expr)
+{
+ visit (expr.get_loop_block ());
+}
+
+void
+ExpandVisitor::visit (AST::WhileLoopExpr &expr)
+{
+ visit (expr.get_predicate_expr ());
+ visit (expr.get_loop_block ());
+}
+
+void
+ExpandVisitor::visit (AST::WhileLetLoopExpr &expr)
+{
+ for (auto &pattern : expr.get_patterns ())
+ visit (pattern);
+
+ visit (expr.get_scrutinee_expr ());
+ visit (expr.get_loop_block ());
+}
+
+void
+ExpandVisitor::visit (AST::ForLoopExpr &expr)
+{
+ visit (expr.get_pattern ());
+ visit (expr.get_iterator_expr ());
+ visit (expr.get_loop_block ());
+}
+
+void
+ExpandVisitor::visit (AST::IfExpr &expr)
+{
+ maybe_expand_expr (expr.get_condition_expr ());
+
+ visit (expr.get_if_block ());
+}
+
+void
+ExpandVisitor::visit (AST::IfExprConseqElse &expr)
+{
+ maybe_expand_expr (expr.get_condition_expr ());
+
+ visit (expr.get_if_block ());
+ visit (expr.get_else_block ());
+}
+
+void
+ExpandVisitor::visit (AST::IfExprConseqIf &expr)
+{
+ maybe_expand_expr (expr.get_condition_expr ());
+
+ visit (expr.get_if_block ());
+ visit (expr.get_conseq_if_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::IfExprConseqIfLet &expr)
+{
+ maybe_expand_expr (expr.get_condition_expr ());
+
+ visit (expr.get_if_block ());
+ visit (expr.get_conseq_if_let_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::IfLetExpr &expr)
+{
+ maybe_expand_expr (expr.get_value_expr ());
+
+ visit (expr.get_if_block ());
+}
+
+void
+ExpandVisitor::visit (AST::IfLetExprConseqElse &expr)
+{
+ maybe_expand_expr (expr.get_value_expr ());
+
+ visit (expr.get_if_block ());
+ visit (expr.get_else_block ());
+}
+
+void
+ExpandVisitor::visit (AST::IfLetExprConseqIf &expr)
+{
+ maybe_expand_expr (expr.get_value_expr ());
+
+ visit (expr.get_if_block ());
+ visit (expr.get_conseq_if_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::IfLetExprConseqIfLet &expr)
+{
+ maybe_expand_expr (expr.get_value_expr ());
+
+ visit (expr.get_if_block ());
+ visit (expr.get_conseq_if_let_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::MatchExpr &expr)
+{
+ visit (expr.get_scrutinee_expr ());
+
+ for (auto &match_case : expr.get_match_cases ())
+ {
+ auto &arm = match_case.get_arm ();
+
+ for (auto &pattern : arm.get_patterns ())
+ visit (pattern);
+
+ if (arm.has_match_arm_guard ())
+ visit (arm.get_guard_expr ());
+
+ visit (match_case.get_expr ());
+ }
+}
+
+void
+ExpandVisitor::visit (AST::AwaitExpr &expr)
+{
+ visit (expr.get_awaited_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::AsyncBlockExpr &expr)
+{
+ visit (expr.get_block_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::TypeParam &param)
+{
+ for (auto &bound : param.get_type_param_bounds ())
+ visit (bound);
+
+ if (param.has_type ())
+ maybe_expand_type (param.get_type ());
+}
+
+void
+ExpandVisitor::visit (AST::LifetimeWhereClauseItem &)
+{}
+
+void
+ExpandVisitor::visit (AST::TypeBoundWhereClauseItem &item)
+{
+ maybe_expand_type (item.get_type ());
+
+ for (auto &bound : item.get_type_param_bounds ())
+ visit (bound);
+}
+
+void
+ExpandVisitor::visit (AST::Method &method)
+{
+ for (auto &param : method.get_generic_params ())
+ visit (param);
+
+ expand_self_param (method.get_self_param ());
+ expand_function_params (method.get_function_params ());
+
+ if (method.has_return_type ())
+ visit (method.get_return_type ());
+
+ if (method.has_where_clause ())
+ expand_where_clause (method.get_where_clause ());
+
+ visit (method.get_definition ());
+}
+
+void
+ExpandVisitor::visit (AST::Module &module)
+{
+ if (module.get_kind () == AST::Module::ModuleKind::LOADED)
+ for (auto &item : module.get_items ())
+ visit (item);
+}
+
+void
+ExpandVisitor::visit (AST::ExternCrate &crate)
+{}
+
+void
+ExpandVisitor::visit (AST::UseTreeGlob &)
+{}
+
+void
+ExpandVisitor::visit (AST::UseTreeList &)
+{}
+
+void
+ExpandVisitor::visit (AST::UseTreeRebind &)
+{}
+
+void
+ExpandVisitor::visit (AST::UseDeclaration &use_decl)
+{}
+
+void
+ExpandVisitor::visit (AST::Function &function)
+{
+ for (auto &param : function.get_generic_params ())
+ visit (param);
+
+ expand_function_params (function.get_function_params ());
+
+ if (function.has_return_type ())
+ maybe_expand_type (function.get_return_type ());
+
+ if (function.has_where_clause ())
+ expand_where_clause (function.get_where_clause ());
+
+ visit (function.get_definition ());
+}
+
+void
+ExpandVisitor::visit (AST::TypeAlias &type_alias)
+{
+ visit (type_alias.get_type_aliased ());
+}
+
+void
+ExpandVisitor::visit (AST::StructStruct &struct_item)
+{
+ for (auto &generic : struct_item.get_generic_params ())
+ visit (generic);
+
+ if (struct_item.has_where_clause ())
+ expand_where_clause (struct_item.get_where_clause ());
+
+ expand_struct_fields (struct_item.get_fields ());
+}
+
+void
+ExpandVisitor::visit (AST::TupleStruct &tuple_struct)
+{
+ for (auto &generic : tuple_struct.get_generic_params ())
+ visit (generic);
+
+ if (tuple_struct.has_where_clause ())
+ expand_where_clause (tuple_struct.get_where_clause ());
+
+ expand_tuple_fields (tuple_struct.get_fields ());
+}
+
+void
+ExpandVisitor::visit (AST::EnumItem &item)
+{}
+
+void
+ExpandVisitor::visit (AST::EnumItemTuple &item)
+{
+ expand_tuple_fields (item.get_tuple_fields ());
+}
+
+void
+ExpandVisitor::visit (AST::EnumItemStruct &item)
+{
+ expand_struct_fields (item.get_struct_fields ());
+}
+
+void
+ExpandVisitor::visit (AST::EnumItemDiscriminant &item)
+{
+ visit (item.get_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::Enum &enum_item)
+{
+ for (auto &generic : enum_item.get_generic_params ())
+ visit (generic);
+
+ for (auto &variant : enum_item.get_variants ())
+ visit (variant);
+}
+
+void
+ExpandVisitor::visit (AST::Union &union_item)
+{
+ for (auto &generic : union_item.get_generic_params ())
+ visit (generic);
+
+ expand_struct_fields (union_item.get_variants ());
+}
+
+void
+ExpandVisitor::visit (AST::ConstantItem &const_item)
+{
+ maybe_expand_type (const_item.get_type ());
+
+ visit (const_item.get_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::StaticItem &static_item)
+{
+ maybe_expand_type (static_item.get_type ());
+
+ visit (static_item.get_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::TraitItemFunc &item)
+{
+ expand_trait_function_decl (item.get_trait_function_decl ());
+
+ if (item.has_definition ())
+ visit (item.get_definition ());
+}
+
+void
+ExpandVisitor::visit (AST::TraitItemMethod &item)
+{
+ expand_trait_method_decl (item.get_trait_method_decl ());
+
+ if (item.has_definition ())
+ visit (item.get_definition ());
+}
+
+void
+ExpandVisitor::visit (AST::TraitItemConst &const_item)
+{
+ maybe_expand_type (const_item.get_type ());
+
+ if (const_item.has_expr ())
+ visit (const_item.get_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::TraitItemType &item)
+{
+ for (auto &type : item.get_type_param_bounds ())
+ visit (type);
+}
+
+void
+ExpandVisitor::visit (AST::Trait &trait)
+{
+ for (auto &generic : trait.get_generic_params ())
+ visit (generic);
+
+ for (auto &bound : trait.get_type_param_bounds ())
+ visit (bound);
+
+ if (trait.has_where_clause ())
+ expand_where_clause (trait.get_where_clause ());
+
+ expander.push_context (MacroExpander::ContextType::TRAIT);
+
+ std::function<std::unique_ptr<AST::TraitItem> (AST::SingleASTNode)> extractor
+ = [] (AST::SingleASTNode node) { return node.take_trait_item (); };
+
+ expand_macro_children (MacroExpander::ContextType::TRAIT,
+ trait.get_trait_items (), extractor);
+
+ expander.pop_context ();
+}
+
+void
+ExpandVisitor::visit (AST::InherentImpl &impl)
+{
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto &generic : impl.get_generic_params ())
+ visit (generic);
+
+ // FIXME: Is that correct? How do we test that?
+ expander.push_context (MacroExpander::ContextType::ITEM);
+
+ maybe_expand_type (impl.get_type ());
+
+ expander.pop_context ();
+
+ if (impl.has_where_clause ())
+ expand_where_clause (impl.get_where_clause ());
+
+ std::function<std::unique_ptr<AST::InherentImplItem> (AST::SingleASTNode)>
+ extractor = [] (AST::SingleASTNode node) { return node.take_impl_item (); };
+
+ expand_macro_children (MacroExpander::ContextType::IMPL,
+ impl.get_impl_items (), extractor);
+}
+
+void
+ExpandVisitor::visit (AST::TraitImpl &impl)
+{
+ // just expand sub-stuff - can't actually strip generic params themselves
+ for (auto &param : impl.get_generic_params ())
+ visit (param);
+
+ // FIXME: Is that correct? How do we test that?
+ expander.push_context (MacroExpander::ContextType::ITEM);
+
+ maybe_expand_type (impl.get_type ());
+
+ expander.pop_context ();
+
+ visit (impl.get_trait_path ());
+
+ if (impl.has_where_clause ())
+ expand_where_clause (impl.get_where_clause ());
+
+ std::function<std::unique_ptr<AST::TraitImplItem> (AST::SingleASTNode)>
+ extractor
+ = [] (AST::SingleASTNode node) { return node.take_trait_impl_item (); };
+
+ expand_macro_children (MacroExpander::ContextType::TRAIT_IMPL,
+ impl.get_impl_items (), extractor);
+}
+
+void
+ExpandVisitor::visit (AST::ExternalTypeItem &item)
+{}
+
+void
+ExpandVisitor::visit (AST::ExternalStaticItem &static_item)
+{
+ maybe_expand_type (static_item.get_type ());
+}
+
+void
+ExpandVisitor::visit (AST::ExternalFunctionItem &item)
+{
+ for (auto &param : item.get_generic_params ())
+ visit (param);
+
+ // FIXME: Should this work? What is the difference between NamedFunctionParam
+ // and FunctionParam?
+ // expand_function_params (item.get_function_params ());
+
+ for (auto &param : item.get_function_params ())
+ maybe_expand_type (param.get_type ());
+
+ if (item.has_return_type ())
+ maybe_expand_type (item.get_return_type ());
+
+ if (item.has_where_clause ())
+ expand_where_clause (item.get_where_clause ());
+}
+
+void
+ExpandVisitor::visit (AST::ExternBlock &block)
+{
+ std::function<std::unique_ptr<AST::ExternalItem> (AST::SingleASTNode)>
+ extractor
+ = [] (AST::SingleASTNode node) { return node.take_external_item (); };
+
+ expand_macro_children (MacroExpander::ContextType::EXTERN,
+ block.get_extern_items (), extractor);
+}
+
+// I don't think it would be possible to strip macros without expansion
+void
+ExpandVisitor::visit (AST::MacroMatchFragment &)
+{}
+
+void
+ExpandVisitor::visit (AST::MacroMatchRepetition &)
+{}
+
+void
+ExpandVisitor::visit (AST::MacroMatcher &)
+{}
+
+void
+ExpandVisitor::visit (AST::MacroRulesDefinition &rules_def)
+{}
+
+void
+ExpandVisitor::visit (AST::MetaItemPath &)
+{}
+
+void
+ExpandVisitor::visit (AST::MetaItemSeq &)
+{}
+
+void
+ExpandVisitor::visit (AST::MetaWord &)
+{}
+
+void
+ExpandVisitor::visit (AST::MetaNameValueStr &)
+{}
+
+void
+ExpandVisitor::visit (AST::MetaListPaths &)
+{}
+
+void
+ExpandVisitor::visit (AST::MetaListNameValueStr &)
+{}
+
+void
+ExpandVisitor::visit (AST::LiteralPattern &)
+{}
+
+void
+ExpandVisitor::visit (AST::IdentifierPattern &pattern)
+{
+ if (pattern.has_pattern_to_bind ())
+ visit (pattern.get_pattern_to_bind ());
+}
+
+void
+ExpandVisitor::visit (AST::WildcardPattern &)
+{}
+
+void
+ExpandVisitor::visit (AST::RestPattern &)
+{}
+
+void
+ExpandVisitor::visit (AST::RangePatternBoundLiteral &)
+{}
+
+void
+ExpandVisitor::visit (AST::RangePatternBoundPath &bound)
+{
+ visit (bound.get_path ());
+}
+
+void
+ExpandVisitor::visit (AST::RangePatternBoundQualPath &bound)
+{
+ visit (bound.get_qualified_path ());
+}
+
+void
+ExpandVisitor::visit (AST::RangePattern &pattern)
+{
+ visit (pattern.get_lower_bound ());
+ visit (pattern.get_upper_bound ());
+}
+
+void
+ExpandVisitor::visit (AST::ReferencePattern &pattern)
+{
+ visit (pattern.get_referenced_pattern ());
+}
+
+void
+ExpandVisitor::visit (AST::StructPatternFieldTuplePat &field)
+{
+ visit (field.get_index_pattern ());
+}
+
+void
+ExpandVisitor::visit (AST::StructPatternFieldIdentPat &field)
+{
+ visit (field.get_ident_pattern ());
+}
+
+void
+ExpandVisitor::visit (AST::StructPatternFieldIdent &field)
+{}
+
+void
+ExpandVisitor::visit (AST::StructPattern &pattern)
+{
+ visit (pattern.get_path ());
+
+ for (auto &inner :
+ pattern.get_struct_pattern_elems ().get_struct_pattern_fields ())
+ visit (inner);
+}
+
+void
+ExpandVisitor::visit (AST::TupleStructItemsNoRange &tuple_items)
+{
+ for (auto &pattern : tuple_items.get_patterns ())
+ visit (pattern);
+}
+
+void
+ExpandVisitor::visit (AST::TupleStructItemsRange &tuple_items)
+{
+ for (auto &lower_pattern : tuple_items.get_lower_patterns ())
+ visit (lower_pattern);
+ for (auto &upper_pattern : tuple_items.get_upper_patterns ())
+ visit (upper_pattern);
+}
+
+void
+ExpandVisitor::visit (AST::TupleStructPattern &pattern)
+{
+ visit (pattern.get_path ());
+
+ if (pattern.has_items ())
+ visit (pattern.get_items ());
+}
+
+void
+ExpandVisitor::visit (AST::TuplePatternItemsMultiple &tuple_items)
+{
+ for (auto &pattern : tuple_items.get_patterns ())
+ visit (pattern);
+}
+
+void
+ExpandVisitor::visit (AST::TuplePatternItemsRanged &tuple_items)
+{
+ for (auto &pattern : tuple_items.get_lower_patterns ())
+ visit (pattern);
+ for (auto &pattern : tuple_items.get_upper_patterns ())
+ visit (pattern);
+}
+
+void
+ExpandVisitor::visit (AST::TuplePattern &pattern)
+{
+ if (pattern.has_tuple_pattern_items ())
+ visit (pattern.get_items ());
+}
+
+void
+ExpandVisitor::visit (AST::GroupedPattern &pattern)
+{
+ visit (pattern.get_pattern_in_parens ());
+}
+
+void
+ExpandVisitor::visit (AST::SlicePattern &pattern)
+{
+ for (auto &item : pattern.get_items ())
+ visit (item);
+}
+
+void
+ExpandVisitor::visit (AST::AltPattern &pattern)
+{
+ for (auto &alt : pattern.get_alts ())
+ visit (alt);
+}
+
+void
+ExpandVisitor::visit (AST::EmptyStmt &)
+{}
+
+void
+ExpandVisitor::visit (AST::LetStmt &stmt)
+{
+ visit (stmt.get_pattern ());
+
+ if (stmt.has_type ())
+ maybe_expand_type (stmt.get_type ());
+
+ if (stmt.has_init_expr ())
+ maybe_expand_expr (stmt.get_init_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::ExprStmtWithoutBlock &stmt)
+{
+ visit (stmt.get_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::ExprStmtWithBlock &stmt)
+{
+ visit (stmt.get_expr ());
+}
+
+void
+ExpandVisitor::visit (AST::TraitBound &bound)
+{
+ visit (bound.get_type_path ());
+}
+
+void
+ExpandVisitor::visit (AST::ImplTraitType &type)
+{
+ for (auto &bound : type.get_type_param_bounds ())
+ visit (bound);
+}
+
+void
+ExpandVisitor::visit (AST::TraitObjectType &type)
+{
+ for (auto &bound : type.get_type_param_bounds ())
+ visit (bound);
+}
+
+void
+ExpandVisitor::visit (AST::ParenthesisedType &type)
+{
+ visit (type.get_type_in_parens ());
+}
+
+void
+ExpandVisitor::visit (AST::ImplTraitTypeOneBound &type)
+{
+ visit (type.get_trait_bound ());
+}
+
+void
+ExpandVisitor::visit (AST::TraitObjectTypeOneBound &type)
+{
+ visit (type.get_trait_bound ());
+}
+
+void
+ExpandVisitor::visit (AST::TupleType &type)
+{
+ for (auto &elem : type.get_elems ())
+ visit (elem);
+}
+
+void
+ExpandVisitor::visit (AST::NeverType &)
+{}
+
+void
+ExpandVisitor::visit (AST::RawPointerType &type)
+{
+ visit (type.get_type_pointed_to ());
+}
+
+void
+ExpandVisitor::visit (AST::ReferenceType &type)
+{
+ visit (type.get_type_referenced ());
+}
+
+void
+ExpandVisitor::visit (AST::ArrayType &type)
+{
+ visit (type.get_elem_type ());
+}
+
+void
+ExpandVisitor::visit (AST::SliceType &type)
+{
+ visit (type.get_elem_type ());
+}
+
+void
+ExpandVisitor::visit (AST::InferredType &)
+{}
+
+void
+ExpandVisitor::visit (AST::BareFunctionType &type)
+{
+ for (auto &param : type.get_function_params ())
+ maybe_expand_type (param.get_type ());
+
+ if (type.has_return_type ())
+ visit (type.get_return_type ());
+}
+
+} // namespace Rust
diff --git a/gcc/rust/expand/rust-expand-visitor.h b/gcc/rust/expand/rust-expand-visitor.h
new file mode 100644
index 0000000..e832d4a
--- /dev/null
+++ b/gcc/rust/expand/rust-expand-visitor.h
@@ -0,0 +1,320 @@
+// Copyright (C) 2020-2023 Free Software Foundation, Inc.
+
+// This file is part of GCC.
+
+// GCC is free software; you can redistribute it and/or modify it under
+// the terms of the GNU General Public License as published by the Free
+// Software Foundation; either version 3, or (at your option) any later
+// version.
+
+// GCC is distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+// for more details.
+
+// You should have received a copy of the GNU General Public License
+// along with GCC; see the file COPYING3. If not see
+// <http://www.gnu.org/licenses/>.
+
+#include "rust-ast-visitor.h"
+#include "rust-macro-expand.h"
+
+namespace Rust {
+
+class ExpandVisitor : public AST::ASTVisitor
+{
+public:
+ ExpandVisitor (MacroExpander &expander) : expander (expander) {}
+
+ /* Expand all of the macro invocations currently contained in a crate */
+ void go (AST::Crate &crate);
+
+ /* Maybe expand a macro invocation in lieu of an expression */
+ void maybe_expand_expr (std::unique_ptr<AST::Expr> &expr);
+
+ /* Maybe expand a macro invocation in lieu of a type */
+ void maybe_expand_type (std::unique_ptr<AST::Type> &type);
+
+ /**
+ * Expand all macro invocations in lieu of types within a vector of struct
+ * fields
+ */
+ void expand_struct_fields (std::vector<AST::StructField> &fields);
+
+ /**
+ * Expand all macro invocations in lieu of types within a vector of tuple
+ * fields
+ */
+ void expand_tuple_fields (std::vector<AST::TupleField> &fields);
+
+ /**
+ * Expand all macro invocations in lieu of types within a list of function
+ * parameters
+ */
+ void expand_function_params (std::vector<AST::FunctionParam> &params);
+
+ /**
+ * Expand all macro invocations in lieu of types within a list of generic
+ * arguments
+ */
+ void expand_generic_args (AST::GenericArgs &args);
+
+ /**
+ * Expand a macro invocation in lieu of a qualified path type
+ */
+ void expand_qualified_path_type (AST::QualifiedPathType &path_type);
+
+ void expand_closure_params (std::vector<AST::ClosureParam> &params);
+ void expand_self_param (AST::SelfParam &self_param);
+ void expand_where_clause (AST::WhereClause &where_clause);
+ void expand_trait_function_decl (AST::TraitFunctionDecl &decl);
+ void expand_trait_method_decl (AST::TraitMethodDecl &decl);
+
+ /**
+ * 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
+ * it can only be called in certain expansion contexts - where macro
+ * invocations are allowed.
+ *
+ * @param ctx Context to use for macro expansion
+ * @param values Iterable reference over values to replace or erase
+ * @param extractor Function to call when replacing values with the content
+ * of an expanded AST node
+ */
+ template <typename T, typename U>
+ void expand_macro_children (MacroExpander::ContextType ctx, T &values,
+ std::function<U (AST::SingleASTNode)> extractor)
+ {
+ expander.push_context (ctx);
+
+ for (auto it = values.begin (); it != values.end ();)
+ {
+ auto &value = *it;
+
+ // Perform expansion
+ value->accept_vis (*this);
+
+ auto final_fragment = expander.take_expanded_fragment ();
+
+ // FIXME: Is that correct? It seems *extremely* dodgy
+ if (final_fragment.should_expand ())
+ {
+ it = values.erase (it);
+ for (auto &node : final_fragment.get_nodes ())
+ {
+ auto new_node = extractor (node);
+ if (new_node != nullptr)
+ {
+ it = values.insert (it, std::move (new_node));
+ it++;
+ }
+ }
+ }
+ else
+ {
+ ++it;
+ }
+ }
+
+ expander.pop_context ();
+ }
+
+ // TODO: See if possible to make more specialization for Impl items, Block
+ // stmts etc? This could allow us to remove expand_macro_children or at least
+ // its extractor parameter
+ /**
+ * These functions allow to easily visit `std::unique_ptr`s as well as
+ * _replace_ them when necessary, e.g when expanding macro invocations in a
+ * list of expressions or types. The most generic version of the function will
+ * simply call the visitor again on the pointer, but there are two
+ * specializations for `std::unique_ptr<Expr>` and `std::unique_ptr<Type>` to
+ * enable replacing as well.
+ */
+ template <typename T> void visit (std::unique_ptr<T> &value)
+ {
+ value->accept_vis (*this);
+ }
+
+ template <typename T> void visit (std::unique_ptr<AST::Expr> &expr)
+ {
+ maybe_expand_expr (expr);
+ }
+
+ template <typename T> void visit (std::unique_ptr<AST::Type> &type)
+ {
+ maybe_expand_type (type);
+ }
+
+ void visit (AST::Token &) override;
+ void visit (AST::DelimTokenTree &) override;
+ void visit (AST::AttrInputMetaItemContainer &) override;
+ void visit (AST::IdentifierExpr &ident_expr) override;
+ void visit (AST::Lifetime &) override;
+ void visit (AST::LifetimeParam &) override;
+ void visit (AST::ConstGenericParam &) override;
+
+ void visit (AST::MacroInvocation &macro_invoc) override;
+
+ void visit (AST::PathInExpression &path) override;
+ void visit (AST::TypePathSegment &) override;
+ void visit (AST::TypePathSegmentGeneric &segment) override;
+ void visit (AST::TypePathSegmentFunction &segment) override;
+ void visit (AST::TypePath &path) override;
+ void visit (AST::QualifiedPathInExpression &path) override;
+ void visit (AST::QualifiedPathInType &path) override;
+
+ void visit (AST::LiteralExpr &expr) override;
+ void visit (AST::AttrInputLiteral &) override;
+ void visit (AST::MetaItemLitExpr &) override;
+ void visit (AST::MetaItemPathLit &) override;
+ void visit (AST::BorrowExpr &expr) override;
+ void visit (AST::DereferenceExpr &expr) override;
+ void visit (AST::ErrorPropagationExpr &expr) override;
+ void visit (AST::NegationExpr &expr) override;
+ void visit (AST::ArithmeticOrLogicalExpr &expr) override;
+ void visit (AST::ComparisonExpr &expr) override;
+ void visit (AST::LazyBooleanExpr &expr) override;
+ void visit (AST::TypeCastExpr &expr) override;
+ void visit (AST::AssignmentExpr &expr) override;
+ void visit (AST::CompoundAssignmentExpr &expr) override;
+ void visit (AST::GroupedExpr &expr) override;
+ void visit (AST::ArrayElemsValues &elems) override;
+ void visit (AST::ArrayElemsCopied &elems) override;
+ void visit (AST::ArrayExpr &expr) override;
+ void visit (AST::ArrayIndexExpr &expr) override;
+ void visit (AST::TupleExpr &expr) override;
+ void visit (AST::TupleIndexExpr &expr) override;
+ void visit (AST::StructExprStruct &expr) override;
+ void visit (AST::StructExprFieldIdentifier &) override;
+ void visit (AST::StructExprFieldIdentifierValue &field) override;
+
+ void visit (AST::StructExprFieldIndexValue &field) override;
+ void visit (AST::StructExprStructFields &expr) override;
+ void visit (AST::StructExprStructBase &expr) override;
+ void visit (AST::CallExpr &expr) override;
+ void visit (AST::MethodCallExpr &expr) override;
+ void visit (AST::FieldAccessExpr &expr) override;
+ void visit (AST::ClosureExprInner &expr) override;
+
+ void visit (AST::BlockExpr &expr) override;
+
+ void visit (AST::ClosureExprInnerTyped &expr) override;
+ void visit (AST::ContinueExpr &expr) override;
+ void visit (AST::BreakExpr &expr) override;
+ void visit (AST::RangeFromToExpr &expr) override;
+ void visit (AST::RangeFromExpr &expr) override;
+ void visit (AST::RangeToExpr &expr) override;
+ void visit (AST::RangeFullExpr &) override;
+ void visit (AST::RangeFromToInclExpr &expr) override;
+ void visit (AST::RangeToInclExpr &expr) override;
+ void visit (AST::ReturnExpr &expr) override;
+ void visit (AST::UnsafeBlockExpr &expr) override;
+ void visit (AST::LoopExpr &expr) override;
+ void visit (AST::WhileLoopExpr &expr) override;
+ void visit (AST::WhileLetLoopExpr &expr) override;
+ void visit (AST::ForLoopExpr &expr) override;
+ void visit (AST::IfExpr &expr) override;
+ void visit (AST::IfExprConseqElse &expr) override;
+ void visit (AST::IfExprConseqIf &expr) override;
+ void visit (AST::IfExprConseqIfLet &expr) override;
+ void visit (AST::IfLetExpr &expr) override;
+ void visit (AST::IfLetExprConseqElse &expr) override;
+ void visit (AST::IfLetExprConseqIf &expr) override;
+ void visit (AST::IfLetExprConseqIfLet &expr) override;
+ void visit (AST::MatchExpr &expr) override;
+ void visit (AST::AwaitExpr &expr) override;
+ void visit (AST::AsyncBlockExpr &expr) override;
+ void visit (AST::TypeParam &param) override;
+ void visit (AST::LifetimeWhereClauseItem &) override;
+ void visit (AST::TypeBoundWhereClauseItem &item) override;
+ void visit (AST::Method &method) override;
+ void visit (AST::Module &module) override;
+ void visit (AST::ExternCrate &crate) override;
+ void visit (AST::UseTreeGlob &) override;
+ void visit (AST::UseTreeList &) override;
+ void visit (AST::UseTreeRebind &) override;
+ void visit (AST::UseDeclaration &use_decl) override;
+ void visit (AST::Function &function) override;
+ void visit (AST::TypeAlias &type_alias) override;
+ void visit (AST::StructStruct &struct_item) override;
+ void visit (AST::TupleStruct &tuple_struct) override;
+ void visit (AST::EnumItem &item) override;
+ void visit (AST::EnumItemTuple &item) override;
+ void visit (AST::EnumItemStruct &item) override;
+ void visit (AST::EnumItemDiscriminant &item) override;
+ void visit (AST::Enum &enum_item) override;
+ void visit (AST::Union &union_item) override;
+ void visit (AST::ConstantItem &const_item) override;
+ void visit (AST::StaticItem &static_item) override;
+ void visit (AST::TraitItemFunc &item) override;
+ void visit (AST::TraitItemMethod &item) override;
+ void visit (AST::TraitItemConst &item) override;
+ void visit (AST::TraitItemType &item) override;
+ void visit (AST::Trait &trait) override;
+ void visit (AST::InherentImpl &impl) override;
+ void visit (AST::TraitImpl &impl) override;
+ void visit (AST::ExternalTypeItem &item) override;
+ void visit (AST::ExternalStaticItem &item) override;
+ void visit (AST::ExternalFunctionItem &item) override;
+ void visit (AST::ExternBlock &block) override;
+
+ // I don't think it would be possible to strip macros without expansion
+ void visit (AST::MacroMatchFragment &) override;
+ void visit (AST::MacroMatchRepetition &) override;
+ void visit (AST::MacroMatcher &) override;
+ void visit (AST::MacroRulesDefinition &rules_def) override;
+ void visit (AST::MetaItemPath &) override;
+ void visit (AST::MetaItemSeq &) override;
+ void visit (AST::MetaWord &) override;
+ void visit (AST::MetaNameValueStr &) override;
+ void visit (AST::MetaListPaths &) override;
+ void visit (AST::MetaListNameValueStr &) override;
+ void visit (AST::LiteralPattern &) override;
+ void visit (AST::IdentifierPattern &pattern) override;
+ void visit (AST::WildcardPattern &) override;
+ void visit (AST::RestPattern &) override;
+ void visit (AST::RangePatternBoundLiteral &) override;
+ void visit (AST::RangePatternBoundPath &bound) override;
+ void visit (AST::RangePatternBoundQualPath &bound) override;
+ void visit (AST::RangePattern &pattern) override;
+ void visit (AST::ReferencePattern &pattern) override;
+ void visit (AST::StructPatternFieldTuplePat &field) override;
+ void visit (AST::StructPatternFieldIdentPat &field) override;
+ void visit (AST::StructPatternFieldIdent &field) override;
+ void visit (AST::StructPattern &pattern) override;
+ void visit (AST::TupleStructItemsNoRange &tuple_items) override;
+ void visit (AST::TupleStructItemsRange &tuple_items) override;
+ void visit (AST::TupleStructPattern &pattern) override;
+ void visit (AST::TuplePatternItemsMultiple &tuple_items) override;
+ void visit (AST::TuplePatternItemsRanged &tuple_items) override;
+ void visit (AST::TuplePattern &pattern) override;
+ void visit (AST::GroupedPattern &pattern) override;
+ void visit (AST::SlicePattern &pattern) override;
+ void visit (AST::AltPattern &pattern) override;
+
+ void visit (AST::EmptyStmt &) override;
+ void visit (AST::LetStmt &stmt) override;
+ void visit (AST::ExprStmtWithoutBlock &stmt) override;
+ void visit (AST::ExprStmtWithBlock &stmt) override;
+
+ void visit (AST::TraitBound &bound) override;
+ void visit (AST::ImplTraitType &type) override;
+ void visit (AST::TraitObjectType &type) override;
+ void visit (AST::ParenthesisedType &type) override;
+ void visit (AST::ImplTraitTypeOneBound &type) override;
+ void visit (AST::TraitObjectTypeOneBound &type) override;
+ void visit (AST::TupleType &type) override;
+ void visit (AST::NeverType &) override;
+ void visit (AST::RawPointerType &type) override;
+ void visit (AST::ReferenceType &type) override;
+ void visit (AST::ArrayType &type) override;
+ void visit (AST::SliceType &type) override;
+ void visit (AST::InferredType &) override;
+ void visit (AST::BareFunctionType &type) override;
+
+private:
+ MacroExpander &expander;
+};
+
+} // namespace Rust
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index 5a16d43..45ea076 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -26,6 +26,7 @@
#include "rust-early-name-resolver.h"
namespace Rust {
+
AST::Fragment
MacroExpander::expand_decl_macro (Location invoc_locus,
AST::MacroInvocData &invoc,
@@ -297,18 +298,15 @@ MacroExpander::expand_crate ()
// TODO: does cfg apply for inner attributes? research.
// the apparent answer (from playground test) is yes
- push_context (ITEM);
+ push_context (ContextType::ITEM);
// expand attributes recursively and strip items if required
- AttrVisitor attr_visitor (*this);
+ // AttrVisitor attr_visitor (*this);
auto &items = crate.items;
for (auto it = items.begin (); it != items.end ();)
{
auto &item = *it;
- // mark for stripping if required
- item->accept_vis (attr_visitor);
-
auto fragment = take_expanded_fragment ();
if (fragment.should_expand ())
{
diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h
index 03d05d6..ceac8e6 100644
--- a/gcc/rust/expand/rust-macro-expand.h
+++ b/gcc/rust/expand/rust-macro-expand.h
@@ -213,7 +213,7 @@ private:
// Object used to store shared data (between functions) for macro expansion.
struct MacroExpander
{
- enum ContextType
+ enum class ContextType
{
ITEM,
BLOCK,
diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc
index 639b45a..2388964 100644
--- a/gcc/rust/rust-session-manager.cc
+++ b/gcc/rust/rust-session-manager.cc
@@ -40,6 +40,8 @@
#include "rust-extern-crate.h"
#include "rust-attributes.h"
#include "rust-early-name-resolver.h"
+#include "rust-attribute-visitor.h"
+#include "rust-expand-visitor.h"
#include "diagnostic.h"
#include "input.h"
@@ -846,10 +848,9 @@ Session::expansion (AST::Crate &crate)
while (!fixed_point_reached && iterations < cfg.recursion_limit)
{
- /* We need to name resolve macros and imports here */
+ AttrVisitor ().go (crate);
Resolver::EarlyNameResolver ().go (crate);
-
- expander.expand_crate ();
+ ExpandVisitor (expander).go (crate);
fixed_point_reached = !expander.has_changed ();
expander.reset_changed_state ();
diff --git a/gcc/testsuite/rust/compile/macro49.rs b/gcc/testsuite/rust/compile/macro49.rs
new file mode 100644
index 0000000..0900f7c
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro49.rs
@@ -0,0 +1,9 @@
+macro_rules! closure {
+ () => {{
+ 14 + 15
+ }};
+}
+
+fn main() {
+ let _ = || closure!();
+}
diff --git a/gcc/testsuite/rust/compile/macro50.rs b/gcc/testsuite/rust/compile/macro50.rs
new file mode 100644
index 0000000..e85afa7
--- /dev/null
+++ b/gcc/testsuite/rust/compile/macro50.rs
@@ -0,0 +1,10 @@
+macro_rules! foo {
+ () => {
+ u32
+ };
+}
+
+fn main() {
+ let _a = 15i32;
+ let _b = _a as foo!();
+}