diff options
-rw-r--r-- | gcc/rust/Make-lang.in | 1 | ||||
-rw-r--r-- | gcc/rust/expand/rust-attribute-visitor.cc | 252 | ||||
-rw-r--r-- | gcc/rust/expand/rust-attribute-visitor.h | 64 | ||||
-rw-r--r-- | gcc/rust/expand/rust-expand-visitor.cc | 1340 | ||||
-rw-r--r-- | gcc/rust/expand/rust-expand-visitor.h | 320 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 8 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.h | 2 | ||||
-rw-r--r-- | gcc/rust/rust-session-manager.cc | 7 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/macro49.rs | 9 | ||||
-rw-r--r-- | gcc/testsuite/rust/compile/macro50.rs | 10 |
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> ¶ms) { - expander.push_context (MacroExpander::ContextType::TYPE); - for (auto it = params.begin (); it != params.end ();) { auto ¶m = *it; @@ -233,8 +239,6 @@ AttrVisitor::expand_function_params (std::vector<AST::FunctionParam> ¶ms) 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> ¶ms) // 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 ¯o_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 ¶ms = 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 ¶m) 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 ¶m : 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 ¶m : 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> ¶ms) +{ + for (auto ¶m : 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> ¶ms) +{ + for (auto ¶m : 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 ¶m : 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 ¶m : 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 ¯o_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 ¶m : expr.get_params ()) + maybe_expand_expr (param); +} + +void +ExpandVisitor::visit (AST::MethodCallExpr &expr) +{ + visit (expr.get_receiver_expr ()); + + for (auto ¶m : 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 ¶m) +{ + 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 ¶m : 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 ¶m : 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 ¶m : 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 ¶m : 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 ¶m : 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 ¶m : 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> ¶ms); + + /** + * 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> ¶ms); + 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 ¯o_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 ¶m) 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!(); +} |