LCOV - code coverage report
Current view: top level - gcc/rust/expand - rust-expand-visitor.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 81.3 % 508 413
Test Date: 2026-04-20 14:57:17 Functions: 81.1 % 90 73
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
       2              : 
       3              : // This file is part of GCC.
       4              : 
       5              : // GCC is free software; you can redistribute it and/or modify it under
       6              : // the terms of the GNU General Public License as published by the Free
       7              : // Software Foundation; either version 3, or (at your option) any later
       8              : // version.
       9              : 
      10              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : // for more details.
      14              : 
      15              : // You should have received a copy of the GNU General Public License
      16              : // along with GCC; see the file COPYING3.  If not see
      17              : // <http://www.gnu.org/licenses/>.
      18              : 
      19              : #include "rust-expand-visitor.h"
      20              : #include "rust-ast-fragment.h"
      21              : #include "rust-hir-map.h"
      22              : #include "rust-item.h"
      23              : #include "rust-proc-macro.h"
      24              : #include "rust-attributes.h"
      25              : #include "rust-ast.h"
      26              : #include "rust-type.h"
      27              : #include "rust-derive.h"
      28              : 
      29              : namespace Rust {
      30              : 
      31              : bool
      32        13182 : is_builtin (AST::Attribute &attr)
      33              : {
      34        13182 :   auto &segments = attr.get_path ().get_segments ();
      35        13182 :   return !segments.empty ()
      36        13182 :          && !Analysis::BuiltinAttributeMappings::get ()
      37        13182 :                ->lookup_builtin (segments[0].get_segment_name ())
      38        13182 :                .is_error ();
      39              : }
      40              : 
      41              : /* Expand all of the macro invocations currently contained in a crate */
      42              : void
      43        10738 : ExpandVisitor::go (AST::Crate &crate)
      44              : {
      45        10738 :   visit (crate);
      46        10738 : }
      47              : 
      48              : static std::vector<std::unique_ptr<AST::Item>>
      49          297 : builtin_derive_item (AST::Item &item, const AST::Attribute &derive,
      50              :                      BuiltinMacro to_derive)
      51              : {
      52          297 :   auto items = AST::DeriveVisitor::derive (item, derive, to_derive);
      53          730 :   for (auto &item : items)
      54          433 :     Analysis::Mappings::get ().add_derived_node (item->get_node_id ());
      55          297 :   return items;
      56              : }
      57              : 
      58              : static std::vector<std::unique_ptr<AST::Item>>
      59            5 : derive_item (AST::Item &item, AST::SimplePath &to_derive,
      60              :              MacroExpander &expander)
      61              : {
      62            5 :   std::vector<std::unique_ptr<AST::Item>> result;
      63            5 :   auto frag = expander.expand_derive_proc_macro (item, to_derive);
      64            5 :   if (!frag.is_error ())
      65              :     {
      66            0 :       for (auto &node : frag.get_nodes ())
      67              :         {
      68            0 :           switch (node.get_kind ())
      69              :             {
      70            0 :             case AST::SingleASTNode::Kind::Item:
      71            0 :               Analysis::Mappings::get ().add_derived_node (
      72            0 :                 node.get_item ()->get_node_id ());
      73            0 :               result.push_back (node.take_item ());
      74            0 :               break;
      75            0 :             default:
      76            0 :               rust_unreachable ();
      77              :             }
      78              :         }
      79              :     }
      80            5 :   return result;
      81            5 : }
      82              : 
      83              : static std::vector<std::unique_ptr<AST::Item>>
      84            0 : expand_item_attribute (AST::Item &item, AST::SimplePath &name,
      85              :                        MacroExpander &expander)
      86              : {
      87            0 :   std::vector<std::unique_ptr<AST::Item>> result;
      88            0 :   auto frag = expander.expand_attribute_proc_macro (item, name);
      89            0 :   if (!frag.is_error ())
      90              :     {
      91            0 :       for (auto &node : frag.get_nodes ())
      92              :         {
      93            0 :           switch (node.get_kind ())
      94              :             {
      95            0 :             case AST::SingleASTNode::Kind::Item:
      96            0 :               result.push_back (node.take_item ());
      97            0 :               break;
      98            0 :             default:
      99            0 :               rust_unreachable ();
     100              :             }
     101              :         }
     102              :     }
     103            0 :   return result;
     104            0 : }
     105              : 
     106              : /* Helper function to expand a given attribute on a statement and collect back
     107              :  * statements.
     108              :  * T should be anything that can be used as a statement accepting outer
     109              :  * attributes.
     110              :  */
     111              : template <typename T>
     112              : static std::vector<std::unique_ptr<AST::Stmt>>
     113            1 : expand_stmt_attribute (T &statement, AST::SimplePath &attribute,
     114              :                        MacroExpander &expander)
     115              : {
     116            1 :   std::vector<std::unique_ptr<AST::Stmt>> result;
     117            1 :   auto frag = expander.expand_attribute_proc_macro (statement, attribute);
     118            1 :   if (!frag.is_error ())
     119              :     {
     120            0 :       for (auto &node : frag.get_nodes ())
     121              :         {
     122            0 :           switch (node.get_kind ())
     123              :             {
     124            0 :             case AST::SingleASTNode::Kind::Stmt:
     125            0 :               result.push_back (node.take_stmt ());
     126              :               break;
     127            0 :             default:
     128            0 :               rust_unreachable ();
     129              :             }
     130              :         }
     131              :     }
     132            1 :   return result;
     133            1 : }
     134              : 
     135              : void
     136        54876 : expand_tail_expr (AST::BlockExpr &block_expr, MacroExpander &expander)
     137              : {
     138        54876 :   if (block_expr.has_tail_expr ())
     139              :     {
     140        40346 :       auto tail = block_expr.take_tail_expr ();
     141        40346 :       auto attrs = tail->get_outer_attrs ();
     142        40346 :       bool changed = false;
     143        41224 :       for (auto it = attrs.begin (); it != attrs.end ();)
     144              :         {
     145          878 :           auto current = *it;
     146          878 :           if (is_builtin (current))
     147              :             {
     148          878 :               it++;
     149              :             }
     150              :           else
     151              :             {
     152            0 :               it = attrs.erase (it);
     153            0 :               changed = true;
     154            0 :               auto new_stmts
     155              :                 = expand_stmt_attribute (block_expr, current.get_path (),
     156            0 :                                          expander);
     157            0 :               auto &stmts = block_expr.get_statements ();
     158            0 :               std::move (new_stmts.begin (), new_stmts.end (),
     159              :                          std::inserter (stmts, stmts.end ()));
     160            0 :             }
     161          878 :         }
     162        40346 :       if (changed)
     163            0 :         block_expr.normalize_tail_expr ();
     164              :       else
     165        40346 :         block_expr.set_tail_expr (std::move (tail));
     166        40346 :     }
     167        54876 : }
     168              : 
     169              : void
     170        13927 : ExpandVisitor::expand_inner_items (
     171              :   std::vector<std::unique_ptr<AST::Item>> &items)
     172              : {
     173        13927 :   expander.push_context (MacroExpander::ContextType::ITEM);
     174              : 
     175        71990 :   for (auto it = items.begin (); it != items.end (); it++)
     176              :     {
     177        58063 :       Rust::AST::Item &item = **it;
     178        58063 :       if (item.has_outer_attrs ())
     179              :         {
     180         9320 :           auto &attrs = item.get_outer_attrs ();
     181              : 
     182        21782 :           for (auto attr_it = attrs.begin (); attr_it != attrs.end ();
     183              :                /* erase => No increment*/)
     184              :             {
     185        12462 :               auto current = *attr_it;
     186              : 
     187        12462 :               if (current.is_derive ())
     188              :                 {
     189          168 :                   current.parse_attr_to_meta_item ();
     190          168 :                   attr_it = attrs.erase (attr_it);
     191              :                   // Get traits to derive in the current attribute
     192          168 :                   auto traits_to_derive = current.get_traits_to_derive ();
     193          470 :                   for (auto &to_derive : traits_to_derive)
     194              :                     {
     195          302 :                       auto maybe_builtin = MacroBuiltin::builtins.lookup (
     196          302 :                         to_derive.get ().as_string ());
     197          302 :                       if (maybe_builtin.has_value ())
     198              :                         {
     199          297 :                           auto new_items
     200              :                             = builtin_derive_item (item, current,
     201          297 :                                                    maybe_builtin.value ());
     202              : 
     203          730 :                           for (auto &&new_item : new_items)
     204          433 :                             it = items.insert (it, std::move (new_item));
     205          297 :                         }
     206              :                       else
     207              :                         {
     208              :                           // Macro is not a builtin, so it must be a
     209              :                           // user-defined derive macro.
     210            5 :                           auto new_items
     211            5 :                             = derive_item (item, to_derive, expander);
     212            5 :                           std::move (new_items.begin (), new_items.end (),
     213              :                                      std::inserter (items, it));
     214            5 :                         }
     215              :                     }
     216          168 :                 }
     217              :               else /* Attribute */
     218              :                 {
     219        12294 :                   if (is_builtin (current))
     220              :                     {
     221        12294 :                       visit (*attr_it);
     222        12294 :                       attr_it++;
     223              :                     }
     224              :                   else
     225              :                     {
     226            0 :                       attr_it = attrs.erase (attr_it);
     227            0 :                       auto new_items
     228              :                         = expand_item_attribute (item, current.get_path (),
     229            0 :                                                  expander);
     230            0 :                       it = items.erase (it);
     231            0 :                       std::move (new_items.begin (), new_items.end (),
     232              :                                  std::inserter (items, it));
     233              :                       // TODO: Improve this ?
     234              :                       // item is invalid since it refers to now deleted,
     235              :                       // cancel the loop increment and break.
     236            0 :                       it--;
     237            0 :                       break;
     238            0 :                     }
     239              :                 }
     240        12462 :             }
     241              :         }
     242              :     }
     243              : 
     244        13927 :   expand_macro_children (items, &AST::SingleASTNode::take_item);
     245              : 
     246        13927 :   expander.pop_context ();
     247        13927 : }
     248              : 
     249              : void
     250        54876 : ExpandVisitor::expand_inner_stmts (AST::BlockExpr &expr)
     251              : {
     252        54876 :   auto &stmts = expr.get_statements ();
     253        54876 :   expander.push_context (MacroExpander::ContextType::STMT);
     254              : 
     255       106477 :   for (auto it = stmts.begin (); it != stmts.end (); it++)
     256              :     {
     257        51601 :       auto &stmt = *it;
     258              : 
     259              :       // skip all non-item statements
     260        51601 :       if (stmt->get_stmt_kind () != AST::Stmt::Kind::Item)
     261        49986 :         continue;
     262              : 
     263         1615 :       auto &item = static_cast<AST::Item &> (*stmt.get ());
     264              : 
     265         1615 :       if (item.has_outer_attrs ())
     266              :         {
     267           10 :           auto &attrs = item.get_outer_attrs ();
     268              : 
     269           19 :           for (auto attr_it = attrs.begin (); attr_it != attrs.end ();
     270              :                /* erase => No increment*/)
     271              :             {
     272           10 :               auto current = *attr_it;
     273              : 
     274           10 :               if (current.is_derive ())
     275              :                 {
     276            0 :                   attr_it = attrs.erase (attr_it);
     277              :                   // Get traits to derive in the current attribute
     278            0 :                   auto traits_to_derive = current.get_traits_to_derive ();
     279            0 :                   for (auto &to_derive : traits_to_derive)
     280              :                     {
     281            0 :                       auto maybe_builtin = MacroBuiltin::builtins.lookup (
     282            0 :                         to_derive.get ().as_string ());
     283            0 :                       if (maybe_builtin.has_value ())
     284              :                         {
     285            0 :                           auto new_items
     286              :                             = builtin_derive_item (item, current,
     287            0 :                                                    maybe_builtin.value ());
     288              : 
     289              :                           // this inserts the derive *before* the item - is it a
     290              :                           // problem?
     291            0 :                           for (auto &&new_item : new_items)
     292            0 :                             it = stmts.insert (it, std::move (new_item));
     293            0 :                         }
     294              :                       else
     295              :                         {
     296            0 :                           auto new_items
     297            0 :                             = derive_item (item, to_derive, expander);
     298            0 :                           std::move (new_items.begin (), new_items.end (),
     299              :                                      std::inserter (stmts, it));
     300            0 :                         }
     301              :                     }
     302            0 :                 }
     303              :               else /* Attribute */
     304              :                 {
     305           10 :                   if (is_builtin (current))
     306              :                     {
     307            9 :                       visit (*attr_it);
     308            9 :                       attr_it++;
     309              :                     }
     310              :                   else
     311              :                     {
     312            1 :                       attr_it = attrs.erase (attr_it);
     313            1 :                       auto new_items
     314              :                         = expand_stmt_attribute (item, current.get_path (),
     315            1 :                                                  expander);
     316            1 :                       it = stmts.erase (it);
     317            1 :                       std::move (new_items.begin (), new_items.end (),
     318              :                                  std::inserter (stmts, it));
     319              :                       // TODO: Improve this ?
     320              :                       // item is invalid since it refers to now deleted,
     321              :                       // cancel the loop increment and break.
     322            1 :                       it--;
     323            1 :                       break;
     324            1 :                     }
     325              :                 }
     326           10 :             }
     327              :         }
     328              :     }
     329              : 
     330        54876 :   if (!expr.has_tail_expr ())
     331        14589 :     expr.normalize_tail_expr ();
     332              : 
     333        54876 :   expand_macro_children (stmts, &AST::SingleASTNode::take_stmt);
     334              : 
     335        54876 :   expander.pop_context ();
     336        54876 : }
     337              : 
     338              : void
     339        13157 : ExpandVisitor::visit (AST::Attribute &attr)
     340              : {
     341              :   // An attribute input containing a macro may have been expanded to a literal
     342        13157 :   if (attr.has_attr_input ()
     343        13157 :       && attr.get_attr_input ().get_attr_input_type ()
     344              :            == AST::AttrInput::AttrInputType::EXPR)
     345              :     {
     346            6 :       auto &expr = static_cast<AST::AttrInputExpr &> (attr.get_attr_input ());
     347            6 :       if (expr.get_expr ().is_literal ())
     348              :         {
     349            2 :           auto &lit = static_cast<AST::LiteralExpr &> (expr.get_expr ());
     350            2 :           attr.set_attr_input (std::make_unique<AST::AttrInputLiteral> (lit));
     351              :         }
     352              :     }
     353        13157 :   AST::DefaultASTVisitor::visit (attr);
     354        13157 : }
     355              : 
     356              : void
     357      1325232 : ExpandVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr)
     358              : {
     359      1325232 :   NodeId old_expect = expr->get_node_id ();
     360      1325232 :   std::swap (macro_invoc_expect_id, old_expect);
     361              : 
     362      1325232 :   expander.push_context (MacroExpander::ContextType::EXPR);
     363      1325232 :   expr->accept_vis (*this);
     364      1325232 :   expander.pop_context ();
     365              : 
     366      1325232 :   std::swap (macro_invoc_expect_id, old_expect);
     367              : 
     368      1325232 :   auto final_fragment = expander.take_expanded_fragment ();
     369      1325232 :   if (final_fragment.should_expand ()
     370      1325232 :       && final_fragment.is_expression_fragment ())
     371         1900 :     expr = final_fragment.take_expression_fragment ();
     372      1325232 : }
     373              : 
     374              : void
     375       105489 : ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::Type> &type)
     376              : {
     377       105489 :   NodeId old_expect = type->get_node_id ();
     378       105489 :   std::swap (macro_invoc_expect_id, old_expect);
     379              : 
     380       210978 :   expander.push_context (MacroExpander::ContextType::TYPE);
     381       105489 :   type->accept_vis (*this);
     382       105489 :   expander.pop_context ();
     383              : 
     384       105489 :   std::swap (macro_invoc_expect_id, old_expect);
     385              : 
     386       105489 :   auto final_fragment = expander.take_expanded_fragment ();
     387       105489 :   if (final_fragment.should_expand () && final_fragment.is_type_fragment ())
     388           28 :     type = final_fragment.take_type_fragment ();
     389       105489 : }
     390              : 
     391              : // HACK: maybe we shouldn't have TypeNoBounds as a base class
     392              : void
     393        37316 : ExpandVisitor::maybe_expand_type (std::unique_ptr<AST::TypeNoBounds> &type)
     394              : {
     395        37316 :   NodeId old_expect = type->get_node_id ();
     396        37316 :   std::swap (macro_invoc_expect_id, old_expect);
     397              : 
     398        37316 :   expander.push_context (MacroExpander::ContextType::TYPE);
     399        37316 :   type->accept_vis (*this);
     400        37316 :   expander.pop_context ();
     401              : 
     402        37316 :   std::swap (macro_invoc_expect_id, old_expect);
     403              : 
     404        37316 :   auto final_fragment = expander.take_expanded_fragment ();
     405        37316 :   if (final_fragment.should_expand () && final_fragment.is_type_fragment ())
     406            2 :     type = std::make_unique<AST::ParenthesisedType> (
     407            3 :       final_fragment.take_type_fragment (), BUILTINS_LOCATION);
     408        37316 : }
     409              : 
     410              : void
     411        69184 : ExpandVisitor::maybe_expand_pattern (std::unique_ptr<AST::Pattern> &pattern)
     412              : {
     413        69184 :   NodeId old_expect = pattern->get_node_id ();
     414        69184 :   std::swap (macro_invoc_expect_id, old_expect);
     415              : 
     416        69184 :   expander.push_context (MacroExpander::ContextType::PATTERN);
     417        69184 :   pattern->accept_vis (*this);
     418        69184 :   expander.pop_context ();
     419              : 
     420        69184 :   std::swap (macro_invoc_expect_id, old_expect);
     421              : 
     422        69184 :   auto final_fragment = expander.take_expanded_fragment ();
     423        69184 :   if (final_fragment.should_expand () && final_fragment.is_pattern_fragment ())
     424            1 :     pattern = final_fragment.take_pattern_fragment ();
     425        69184 : }
     426              : 
     427              : void
     428         3996 : ExpandVisitor::expand_struct_fields (std::vector<AST::StructField> &fields)
     429              : {
     430         3996 :   expand_fields (fields);
     431         3996 : }
     432              : 
     433              : void
     434         3194 : ExpandVisitor::expand_tuple_fields (std::vector<AST::TupleField> &fields)
     435              : {
     436         3194 :   expand_fields (fields);
     437         3194 : }
     438              : 
     439              : // FIXME: This can definitely be refactored with the method above
     440              : void
     441        44967 : ExpandVisitor::expand_function_params (
     442              :   std::vector<std::unique_ptr<AST::Param>> &params)
     443              : {
     444        94461 :   for (auto &p : params)
     445        49494 :     visit (p);
     446        44967 : }
     447              : 
     448              : void
     449         9103 : ExpandVisitor::expand_generic_args (AST::GenericArgs &args)
     450              : {
     451        18614 :   for (auto &arg : args.get_generic_args ())
     452              :     {
     453         9511 :       switch (arg.get_kind ())
     454              :         {
     455         3842 :         case AST::GenericArg::Kind::Type:
     456         3842 :           maybe_expand_type (arg.get_type_ptr ());
     457         3842 :           break;
     458          138 :         case AST::GenericArg::Kind::Const:
     459          138 :           maybe_expand_expr (arg.get_expression_ptr ());
     460          138 :           break;
     461              :         default:
     462              :           break;
     463              :           // FIXME: Figure out what to do here if there is ambiguity. Since the
     464              :           // resolver comes after the expansion, we need to figure out a way to
     465              :           // strip ambiguous values here
     466              :           // TODO: ARTHUR: Probably add a `mark_as_strip` method to `GenericArg`
     467              :           // or something. This would clean up this whole thing
     468              :         }
     469              :     }
     470              : 
     471              :   // FIXME: Can we have macro invocations in generic type bindings?
     472              :   // expand binding args - strip sub-types only
     473              :   // FIXME: ARTHUR: This needs a test! Foo<Item = macro!()>
     474         9297 :   for (auto &binding : args.get_binding_args ())
     475          194 :     maybe_expand_type (binding.get_type_ptr ());
     476         9103 : }
     477              : 
     478              : void
     479          982 : ExpandVisitor::expand_qualified_path_type (AST::QualifiedPathType &path_type)
     480              : {
     481          982 :   maybe_expand_type (path_type.get_type_ptr ());
     482              : 
     483              :   // FIXME: ARTHUR: Can we do macro expansion in there? Needs a test!
     484          982 :   if (path_type.has_as_clause ())
     485          888 :     path_type.get_as_type_path ().accept_vis (*this);
     486          982 : }
     487              : 
     488              : void
     489          134 : ExpandVisitor::expand_closure_params (std::vector<AST::ClosureParam> &params)
     490              : {
     491          260 :   for (auto &param : params)
     492              :     {
     493          126 :       maybe_expand_pattern (param.get_pattern_ptr ());
     494              : 
     495          126 :       if (param.has_type_given ())
     496          116 :         maybe_expand_type (param.get_type_ptr ());
     497              :     }
     498          134 : }
     499              : 
     500              : void
     501          761 : ExpandVisitor::expand_where_clause (AST::WhereClause &where_clause)
     502              : {
     503         1542 :   for (auto &item : where_clause.get_items ())
     504          781 :     visit (item);
     505          761 : }
     506              : 
     507              : void
     508        10738 : ExpandVisitor::visit (AST::Crate &crate)
     509              : {
     510        10738 :   expand_inner_items (crate.items);
     511        10738 : }
     512              : 
     513              : void
     514         4503 : ExpandVisitor::visit (AST::DelimTokenTree &)
     515         4503 : {}
     516              : 
     517              : void
     518           63 : ExpandVisitor::visit (AST::AttrInputMetaItemContainer &)
     519           63 : {}
     520              : 
     521              : void
     522        55154 : ExpandVisitor::visit (AST::IdentifierExpr &ident_expr)
     523        55154 : {}
     524              : 
     525              : void
     526          542 : ExpandVisitor::visit (AST::LifetimeParam &)
     527          542 : {}
     528              : 
     529              : void
     530          200 : ExpandVisitor::visit (AST::ConstGenericParam &)
     531          200 : {}
     532              : 
     533              : void
     534         2802 : ExpandVisitor::visit (AST::MacroInvocation &macro_invoc)
     535              : {
     536         2802 :   if (macro_invoc_expect_id != macro_invoc.get_node_id ())
     537              :     {
     538            0 :       rust_internal_error_at (
     539              :         macro_invoc.get_locus (),
     540              :         "attempting to expand node with id %d into position with node id %d",
     541            0 :         (int) macro_invoc.get_node_id (), (int) macro_invoc_expect_id);
     542              :     }
     543              : 
     544              :   // TODO: Can we do the AST fragment replacing here? Probably not, right?
     545         4759 :   expander.expand_invoc (macro_invoc, macro_invoc.has_semicolon ()
     546              :                                         ? AST::InvocKind::Semicoloned
     547              :                                         : AST::InvocKind::Expr);
     548         2802 : }
     549              : 
     550              : void
     551        61978 : ExpandVisitor::visit (AST::PathInExpression &path)
     552              : {
     553        61978 :   if (!path.is_lang_item ())
     554       148571 :     for (auto &segment : path.get_segments ())
     555       173580 :       if (segment.has_generic_args ())
     556         2102 :         expand_generic_args (segment.get_generic_args ());
     557        61978 : }
     558              : 
     559              : void
     560         7003 : ExpandVisitor::visit (AST::TypePathSegmentGeneric &segment)
     561              : {
     562         7003 :   if (segment.has_generic_args ())
     563         7001 :     expand_generic_args (segment.get_generic_args ());
     564         7003 : }
     565              : 
     566              : void
     567           60 : ExpandVisitor::visit (AST::TypePathSegmentFunction &segment)
     568              : {
     569           60 :   auto &type_path_function = segment.get_type_path_function ();
     570              : 
     571          124 :   for (auto &type : type_path_function.get_params ())
     572           64 :     visit (type);
     573              : 
     574           60 :   if (type_path_function.has_return_type ())
     575           56 :     maybe_expand_type (type_path_function.get_return_type_ptr ());
     576           60 : }
     577              : 
     578              : void
     579          273 : ExpandVisitor::visit (AST::QualifiedPathInExpression &path)
     580              : {
     581          273 :   expand_qualified_path_type (path.get_qualified_path_type ());
     582              : 
     583          546 :   for (auto &segment : path.get_segments ())
     584          546 :     if (segment.has_generic_args ())
     585            0 :       expand_generic_args (segment.get_generic_args ());
     586          273 : }
     587              : 
     588              : void
     589          709 : ExpandVisitor::visit (AST::QualifiedPathInType &path)
     590              : {
     591          709 :   expand_qualified_path_type (path.get_qualified_path_type ());
     592              : 
     593              :   // this shouldn't strip any segments, but can strip inside them
     594          709 :   for (auto &segment : path.get_segments ())
     595            0 :     visit (segment);
     596          709 : }
     597              : 
     598              : void
     599       565972 : ExpandVisitor::visit (AST::LiteralExpr &expr)
     600       565972 : {}
     601              : 
     602              : void
     603         8155 : ExpandVisitor::visit (AST::AttrInputLiteral &)
     604         8155 : {}
     605              : 
     606              : void
     607            4 : ExpandVisitor::visit (AST::AttrInputExpr &attr_input)
     608              : {
     609            4 :   maybe_expand_expr (attr_input.get_expr_ptr ());
     610            4 : }
     611              : 
     612              : void
     613            0 : ExpandVisitor::visit (AST::MetaItemLitExpr &)
     614            0 : {}
     615              : 
     616              : void
     617            0 : ExpandVisitor::visit (AST::MetaItemPathExpr &)
     618            0 : {}
     619              : 
     620              : void
     621          166 : ExpandVisitor::visit (AST::StructExprStruct &expr)
     622          166 : {}
     623              : 
     624              : void
     625           74 : ExpandVisitor::visit (AST::ClosureExprInner &expr)
     626              : {
     627           74 :   expand_closure_params (expr.get_params ());
     628              : 
     629           74 :   maybe_expand_expr (expr.get_definition_expr_ptr ());
     630           74 : }
     631              : 
     632              : void
     633        54876 : ExpandVisitor::visit (AST::BlockExpr &expr)
     634              : {
     635        54876 :   expand_inner_stmts (expr);
     636              : 
     637        54876 :   expand_tail_expr (expr, expander);
     638        54876 :   if (expr.has_tail_expr ())
     639        40346 :     maybe_expand_expr (expr.get_tail_expr_ptr ());
     640        54876 : }
     641              : 
     642              : void
     643           60 : ExpandVisitor::visit (AST::ClosureExprInnerTyped &expr)
     644              : {
     645           60 :   expand_closure_params (expr.get_params ());
     646              : 
     647           60 :   maybe_expand_type (expr.get_return_type_ptr ());
     648              : 
     649           60 :   visit (expr.get_definition_expr ());
     650           60 : }
     651              : 
     652              : void
     653         2571 : ExpandVisitor::visit (AST::IfExpr &expr)
     654              : {
     655         2571 :   maybe_expand_expr (expr.get_condition_expr_ptr ());
     656              : 
     657         2571 :   visit (expr.get_if_block ());
     658         2571 : }
     659              : 
     660              : void
     661         3162 : ExpandVisitor::visit (AST::IfExprConseqElse &expr)
     662              : {
     663         3162 :   maybe_expand_expr (expr.get_condition_expr_ptr ());
     664              : 
     665         3162 :   visit (expr.get_if_block ());
     666         3162 :   visit (expr.get_else_block ());
     667         3162 : }
     668              : 
     669              : void
     670           36 : ExpandVisitor::visit (AST::IfLetExpr &expr)
     671              : {
     672           36 :   maybe_expand_expr (expr.get_value_expr_ptr ());
     673              : 
     674           36 :   visit (expr.get_if_block ());
     675           36 : }
     676              : 
     677              : void
     678           24 : ExpandVisitor::visit (AST::IfLetExprConseqElse &expr)
     679              : {
     680           24 :   maybe_expand_expr (expr.get_value_expr_ptr ());
     681              : 
     682           24 :   visit (expr.get_if_block ());
     683           24 :   visit (expr.get_else_block ());
     684           24 : }
     685              : 
     686              : void
     687        11129 : ExpandVisitor::visit (AST::TypeParam &param)
     688              : {
     689        13105 :   for (auto &bound : param.get_type_param_bounds ())
     690         1976 :     visit (bound);
     691              : 
     692        11129 :   if (param.has_type ())
     693          923 :     maybe_expand_type (param.get_type_ptr ());
     694        11129 : }
     695              : 
     696              : void
     697            4 : ExpandVisitor::visit (AST::LifetimeWhereClauseItem &)
     698            4 : {}
     699              : 
     700              : void
     701          777 : ExpandVisitor::visit (AST::TypeBoundWhereClauseItem &item)
     702              : {
     703          777 :   maybe_expand_type (item.get_type_ptr ());
     704              : 
     705         1554 :   for (auto &bound : item.get_type_param_bounds ())
     706          777 :     visit (bound);
     707          777 : }
     708              : 
     709              : void
     710         3189 : ExpandVisitor::visit (AST::Module &module)
     711              : {
     712         3189 :   expand_inner_items (module.get_items ());
     713         3189 : }
     714              : 
     715              : void
     716           48 : ExpandVisitor::visit (AST::ExternCrate &crate)
     717           48 : {}
     718              : 
     719              : void
     720            0 : ExpandVisitor::visit (AST::UseTreeGlob &)
     721            0 : {}
     722              : 
     723              : void
     724            0 : ExpandVisitor::visit (AST::UseTreeList &)
     725            0 : {}
     726              : 
     727              : void
     728            0 : ExpandVisitor::visit (AST::UseTreeRebind &)
     729            0 : {}
     730              : 
     731              : void
     732         1842 : ExpandVisitor::visit (AST::UseDeclaration &use_decl)
     733         1842 : {}
     734              : 
     735              : void
     736        44967 : ExpandVisitor::visit (AST::Function &function)
     737              : {
     738        44967 :   if (function.has_body ())
     739        34715 :     visit_inner_using_attrs (
     740        34715 :       function, function.get_definition ().value ()->get_inner_attrs ());
     741        49609 :   for (auto &param : function.get_generic_params ())
     742         4642 :     visit (param);
     743              : 
     744        44967 :   expand_function_params (function.get_function_params ());
     745              : 
     746        44967 :   if (function.has_return_type ())
     747        33074 :     maybe_expand_type (function.get_return_type_ptr ());
     748              : 
     749        44967 :   if (function.has_where_clause ())
     750          520 :     expand_where_clause (function.get_where_clause ());
     751              : 
     752        44967 :   if (function.has_body ())
     753        34715 :     visit (*function.get_definition ());
     754        44967 : }
     755              : 
     756              : void
     757         3563 : ExpandVisitor::visit (AST::StructStruct &struct_item)
     758              : {
     759         4752 :   for (auto &generic : struct_item.get_generic_params ())
     760         1189 :     visit (generic);
     761              : 
     762         3563 :   if (struct_item.has_where_clause ())
     763            4 :     expand_where_clause (struct_item.get_where_clause ());
     764              : 
     765         3563 :   expand_struct_fields (struct_item.get_fields ());
     766         3563 : }
     767              : 
     768              : void
     769         2080 : ExpandVisitor::visit (AST::TupleStruct &tuple_struct)
     770              : {
     771         2819 :   for (auto &generic : tuple_struct.get_generic_params ())
     772          739 :     visit (generic);
     773              : 
     774         2080 :   if (tuple_struct.has_where_clause ())
     775            0 :     expand_where_clause (tuple_struct.get_where_clause ());
     776              : 
     777         2080 :   expand_tuple_fields (tuple_struct.get_fields ());
     778         2080 : }
     779              : 
     780              : void
     781         1042 : ExpandVisitor::visit (AST::EnumItem &item)
     782         1042 : {}
     783              : 
     784              : void
     785         1114 : ExpandVisitor::visit (AST::EnumItemTuple &item)
     786              : {
     787         1114 :   expand_tuple_fields (item.get_tuple_fields ());
     788         1114 : }
     789              : 
     790              : void
     791          208 : ExpandVisitor::visit (AST::EnumItemStruct &item)
     792              : {
     793          208 :   expand_struct_fields (item.get_struct_fields ());
     794          208 : }
     795              : 
     796              : void
     797          685 : ExpandVisitor::visit (AST::EnumItemDiscriminant &item)
     798              : {
     799          685 :   maybe_expand_expr (item.get_expr_ptr ());
     800          685 : }
     801              : 
     802              : void
     803          225 : ExpandVisitor::visit (AST::Union &union_item)
     804              : {
     805          382 :   for (auto &generic : union_item.get_generic_params ())
     806          157 :     visit (generic);
     807              : 
     808          225 :   expand_struct_fields (union_item.get_variants ());
     809          225 : }
     810              : 
     811              : void
     812         8972 : ExpandVisitor::visit (AST::Trait &trait)
     813              : {
     814        10613 :   for (auto &generic : trait.get_generic_params ())
     815         1641 :     visit (generic);
     816              : 
     817        10648 :   for (auto &bound : trait.get_type_param_bounds ())
     818         1676 :     visit (bound);
     819              : 
     820         8972 :   if (trait.has_where_clause ())
     821           21 :     expand_where_clause (trait.get_where_clause ());
     822              : 
     823         8972 :   expander.push_context (MacroExpander::ContextType::TRAIT);
     824              : 
     825         8972 :   expand_macro_children (MacroExpander::ContextType::TRAIT,
     826              :                          trait.get_trait_items (),
     827              :                          &AST::SingleASTNode::take_assoc_item);
     828              : 
     829         8972 :   expander.pop_context ();
     830         8972 : }
     831              : 
     832              : void
     833         2193 : ExpandVisitor::visit (AST::InherentImpl &impl)
     834              : {
     835         4386 :   visit_inner_attrs (impl);
     836              :   // just expand sub-stuff - can't actually strip generic params themselves
     837         2967 :   for (auto &generic : impl.get_generic_params ())
     838          774 :     visit (generic);
     839              : 
     840              :   // FIXME: Is that correct? How do we test that?
     841         2193 :   expander.push_context (MacroExpander::ContextType::ITEM);
     842              : 
     843         2193 :   maybe_expand_type (impl.get_type_ptr ());
     844              : 
     845         2193 :   expander.pop_context ();
     846              : 
     847         2193 :   if (impl.has_where_clause ())
     848            2 :     expand_where_clause (impl.get_where_clause ());
     849              : 
     850         2193 :   expand_macro_children (MacroExpander::ContextType::IMPL,
     851              :                          impl.get_impl_items (),
     852              :                          &AST::SingleASTNode::take_assoc_item);
     853         2193 : }
     854              : 
     855              : void
     856        11580 : ExpandVisitor::visit (AST::TraitImpl &impl)
     857              : {
     858        23160 :   visit_inner_attrs (impl);
     859              :   // just expand sub-stuff - can't actually strip generic params themselves
     860        13478 :   for (auto &param : impl.get_generic_params ())
     861         1898 :     visit (param);
     862              : 
     863              :   // FIXME: Is that correct? How do we test that?
     864        11580 :   expander.push_context (MacroExpander::ContextType::ITEM);
     865              : 
     866        11580 :   maybe_expand_type (impl.get_type_ptr ());
     867              : 
     868        11580 :   expander.pop_context ();
     869              : 
     870        11580 :   visit (impl.get_trait_path ());
     871              : 
     872        11580 :   if (impl.has_where_clause ())
     873          214 :     expand_where_clause (impl.get_where_clause ());
     874              : 
     875        11580 :   expand_macro_children (MacroExpander::ContextType::TRAIT_IMPL,
     876              :                          impl.get_impl_items (),
     877              :                          &AST::SingleASTNode::take_assoc_item);
     878        11580 : }
     879              : 
     880              : void
     881            2 : ExpandVisitor::visit (AST::ExternalTypeItem &item)
     882            2 : {}
     883              : 
     884              : void
     885            2 : ExpandVisitor::visit (AST::ExternalStaticItem &static_item)
     886              : {
     887            2 :   maybe_expand_type (static_item.get_type_ptr ());
     888            2 : }
     889              : 
     890              : void
     891         3580 : ExpandVisitor::visit (AST::ExternBlock &block)
     892              : {
     893         7160 :   visit_inner_attrs (block);
     894              : 
     895         3580 :   expand_macro_children (MacroExpander::ContextType::EXTERN,
     896              :                          block.get_extern_items (),
     897              :                          &AST::SingleASTNode::take_external_item);
     898         3580 : }
     899              : 
     900              : void
     901            0 : ExpandVisitor::visit (AST::MacroMatchRepetition &)
     902            0 : {}
     903              : 
     904              : void
     905            0 : ExpandVisitor::visit (AST::MacroMatcher &)
     906            0 : {}
     907              : 
     908              : void
     909         3799 : ExpandVisitor::visit (AST::MacroRulesDefinition &rules_def)
     910         3799 : {}
     911              : 
     912              : void
     913            0 : ExpandVisitor::visit (AST::MetaItemPath &)
     914            0 : {}
     915              : 
     916              : void
     917            0 : ExpandVisitor::visit (AST::MetaItemSeq &)
     918            0 : {}
     919              : 
     920              : void
     921            0 : ExpandVisitor::visit (AST::MetaListPaths &)
     922            0 : {}
     923              : 
     924              : void
     925            0 : ExpandVisitor::visit (AST::MetaListNameValueStr &)
     926            0 : {}
     927              : 
     928              : void
     929          219 : ExpandVisitor::visit (AST::StructPatternFieldIdent &field)
     930          219 : {}
     931              : 
     932              : void
     933          131 : ExpandVisitor::visit (AST::BareFunctionType &type)
     934              : {
     935          229 :   for (auto &param : type.get_function_params ())
     936              :     {
     937           98 :       maybe_expand_type (param.get_type_ptr ());
     938              :     }
     939              : 
     940          131 :   if (type.has_return_type ())
     941           97 :     visit (type.get_return_type ());
     942          131 : }
     943              : 
     944              : void
     945        27671 : ExpandVisitor::visit (AST::FunctionParam &param)
     946              : {
     947        27671 :   maybe_expand_pattern (param.get_pattern_ptr ());
     948        27671 :   maybe_expand_type (param.get_type_ptr ());
     949        27671 : }
     950              : 
     951              : void
     952         1751 : ExpandVisitor::visit (AST::VariadicParam &param)
     953              : {
     954         1751 :   if (param.has_pattern ())
     955           22 :     maybe_expand_pattern (param.get_pattern_ptr ());
     956         1751 : }
     957              : 
     958              : void
     959        20072 : ExpandVisitor::visit (AST::SelfParam &param)
     960              : {
     961              :   /* TODO: maybe check for invariants being violated - e.g. both type and
     962              :    * lifetime? */
     963        20072 :   if (param.has_type ())
     964            2 :     maybe_expand_type (param.get_type_ptr ());
     965        20072 : }
     966              : 
     967              : template <typename T>
     968              : void
     969            0 : ExpandVisitor::expand_inner_attribute (T &item, AST::SimplePath &path)
     970              : {
     971              :   // FIXME: Retrieve path from segments + local use statements instead of string
     972            0 :   expander.expand_attribute_proc_macro (item, path);
     973            0 : }
     974              : 
     975              : template <typename T>
     976              : void
     977        52068 : ExpandVisitor::visit_inner_using_attrs (T &item,
     978              :                                         std::vector<AST::Attribute> &attrs)
     979              : {
     980        52068 :   for (auto it = attrs.begin (); it != attrs.end (); /* erase => No increment*/)
     981              :     {
     982            0 :       auto current = *it;
     983              : 
     984            0 :       if (!is_builtin (current) && !current.is_derive ())
     985              :         {
     986            0 :           it = attrs.erase (it);
     987            0 :           expand_inner_attribute (item, current.get_path ());
     988              :         }
     989              :       else
     990              :         {
     991            0 :           it++;
     992              :         }
     993              :     }
     994        52068 : }
     995              : 
     996              : template <typename T>
     997              : void
     998         3580 : ExpandVisitor::visit_inner_attrs (T &item)
     999              : {
    1000        17353 :   visit_inner_using_attrs (item, item.get_inner_attrs ());
    1001              : }
    1002              : 
    1003              : } // namespace Rust
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.