LCOV - code coverage report
Current view: top level - gcc/rust/expand - rust-expand-visitor.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 100.0 % 43 43
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 12 12
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              : #ifndef RUST_EXPAND_VISITOR_H
      20              : #define RUST_EXPAND_VISITOR_H
      21              : 
      22              : #include "rust-ast-pointer-visitor.h"
      23              : #include "rust-ast-visitor.h"
      24              : #include "rust-item.h"
      25              : #include "rust-macro-expand.h"
      26              : #include "rust-proc-macro.h"
      27              : 
      28              : namespace Rust {
      29              : 
      30              : /**
      31              :  * Whether or not an attribute is builtin
      32              :  */
      33              : bool is_builtin (AST::Attribute &attr);
      34              : 
      35              : class ExpandVisitor : public AST::PointerVisitor
      36              : {
      37              : public:
      38        10347 :   ExpandVisitor (MacroExpander &expander)
      39        10347 :     : expander (expander), macro_invoc_expect_id (UNKNOWN_NODEID)
      40              :   {}
      41              : 
      42              :   /* Expand all of the macro invocations currently contained in a crate */
      43              :   void go (AST::Crate &crate);
      44              : 
      45              :   using AST::PointerVisitor::reseat;
      46              :   using AST::PointerVisitor::visit;
      47              : 
      48        57502 :   void reseat (std::unique_ptr<AST::Expr> &ptr) override
      49              :   {
      50        57502 :     maybe_expand_expr (ptr);
      51        57502 :   }
      52              : 
      53         8137 :   void reseat (std::unique_ptr<AST::Type> &ptr) override
      54              :   {
      55         8137 :     maybe_expand_type (ptr);
      56         8137 :   }
      57              : 
      58        25541 :   void reseat (std::unique_ptr<AST::TypeNoBounds> &ptr) override
      59              :   {
      60        25541 :     maybe_expand_type (ptr);
      61        25541 :   }
      62              : 
      63         6985 :   void reseat (std::unique_ptr<AST::Pattern> &ptr) override
      64              :   {
      65         6985 :     maybe_expand_pattern (ptr);
      66         6985 :   }
      67              : 
      68              :   /**
      69              :    * Maybe expand a macro invocation in lieu of an expression, type or pattern.
      70              :    *
      71              :    * @ptr Core guidelines R33, this function reseats the pointer.
      72              :    */
      73              :   void maybe_expand_expr (std::unique_ptr<AST::Expr> &ptr);
      74              :   void maybe_expand_type (std::unique_ptr<AST::Type> &ptr);
      75              :   void maybe_expand_type (std::unique_ptr<AST::TypeNoBounds> &type);
      76              :   void maybe_expand_pattern (std::unique_ptr<AST::Pattern> &ptr);
      77              : 
      78              :   /**
      79              :    * Expand all macro invocations in lieu of types within a vector of struct
      80              :    * fields
      81              :    */
      82              :   void expand_struct_fields (std::vector<AST::StructField> &fields);
      83              : 
      84              :   /**
      85              :    * Expand all macro invocations in lieu of types within a vector of tuple
      86              :    * fields
      87              :    */
      88              :   void expand_tuple_fields (std::vector<AST::TupleField> &fields);
      89              : 
      90              :   /**
      91              :    * Expand all macro invocations in lieu of types within a list of function
      92              :    * parameters
      93              :    */
      94              :   void
      95              :   expand_function_params (std::vector<std::unique_ptr<AST::Param>> &params);
      96              : 
      97              :   /**
      98              :    * Expand all macro invocations in lieu of types within a list of generic
      99              :    * arguments
     100              :    */
     101              :   void expand_generic_args (AST::GenericArgs &args);
     102              : 
     103              :   /**
     104              :    * Expand a macro invocation in lieu of a qualified path type
     105              :    */
     106              :   void expand_qualified_path_type (AST::QualifiedPathType &path_type);
     107              : 
     108              :   /**
     109              :    * Expand all macro invocations in lieu of types within a list of closure
     110              :    * parameters
     111              :    */
     112              :   void expand_closure_params (std::vector<AST::ClosureParam> &params);
     113              :   void expand_where_clause (AST::WhereClause &where_clause);
     114              : 
     115              :   /**
     116              :    * Expand a set of values, erasing them if they are marked for strip, and
     117              :    * replacing them with expanded macro nodes if necessary.
     118              :    * This function is slightly different from `expand_pointer_allow_strip` as
     119              :    * it can only be called in certain expansion contexts - where macro
     120              :    * invocations are allowed.
     121              :    *
     122              :    * @param ctx Context to use for macro expansion
     123              :    * @param values Iterable reference over values to replace or erase
     124              :    * @param extractor Function to call when replacing values with the content
     125              :    *            of an expanded AST node
     126              :    */
     127              :   template <typename T, typename U>
     128        25707 :   void expand_macro_children (MacroExpander::ContextType ctx, T &values,
     129              :                               U (AST::SingleASTNode::*extractor) (void))
     130              :   {
     131        25707 :     expander.push_context (ctx);
     132              : 
     133        25707 :     expand_macro_children (values, extractor);
     134              : 
     135        25707 :     expander.pop_context ();
     136        25707 :   }
     137              : 
     138              :   /**
     139              :    * Same as `expand_macro_children`, but does not push a context. This is
     140              :    * useful if you're already pushing the context manually anyway for proc macro
     141              :    * expansion, like in `expand_inner_{items, stmts}`
     142              :    */
     143              :   template <typename T, typename U>
     144        92056 :   void expand_macro_children (T &values,
     145              :                               U (AST::SingleASTNode::*extractor) (void))
     146              :   {
     147       231665 :     for (auto it = values.begin (); it != values.end ();)
     148              :       {
     149       139609 :         auto &value = *it;
     150              : 
     151              :         // Perform expansion
     152       139609 :         NodeId old_expect = value->get_node_id ();
     153       139609 :         std::swap (macro_invoc_expect_id, old_expect);
     154       139609 :         value->accept_vis (*this);
     155       139609 :         std::swap (macro_invoc_expect_id, old_expect);
     156              : 
     157       139609 :         auto final_fragment = expander.take_expanded_fragment ();
     158              : 
     159              :         // FIXME: Is that correct? It seems *extremely* dodgy
     160       139609 :         if (final_fragment.should_expand ())
     161              :           {
     162          833 :             it = values.erase (it);
     163         4016 :             for (auto &node : final_fragment.get_nodes ())
     164              :               {
     165         3183 :                 U new_node = (node.*extractor) ();
     166         3183 :                 if (new_node != nullptr)
     167              :                   {
     168         3166 :                     it = values.insert (it, std::move (new_node));
     169         3166 :                     it++;
     170              :                   }
     171              :               }
     172              :           }
     173              :         else
     174              :           {
     175       138776 :             ++it;
     176              :           }
     177              :       }
     178        92056 :   }
     179              : 
     180              :   /**
     181              :    * Perform in-place expansion of procedural macros and macro invocations for
     182              :    * an item container or statement container, such as `AST::Crate`,
     183              :    * `AST::Module` or `AST::BlockExpr`. This function will insert the expanded
     184              :    * nodes in place, and replace macro invocations with their expanded nodes.
     185              :    *
     186              :    * @param values Vector of values to mutate in-place and append into
     187              :    */
     188              :   void expand_inner_items (std::vector<std::unique_ptr<AST::Item>> &values);
     189              :   void expand_inner_stmts (AST::BlockExpr &expr);
     190              : 
     191              :   // TODO: See if possible to make more specialization for Impl items, Block
     192              :   // stmts etc? This could allow us to remove expand_macro_children or at least
     193              :   // its extractor parameter
     194              :   /**
     195              :    * These functions allow to easily visit `std::unique_ptr`s as well as
     196              :    * _replace_ them when necessary, e.g when expanding macro invocations in a
     197              :    * list of expressions or types. The most generic version of the function will
     198              :    * simply call the visitor again on the pointer, but there are two
     199              :    * specializations for `std::unique_ptr<Expr>` and `std::unique_ptr<Type>` to
     200              :    * enable replacing as well.
     201              :    */
     202        99539 :   template <typename T> void visit (std::unique_ptr<T> &value)
     203              :   {
     204        99539 :     value->accept_vis (*this);
     205        34337 :   }
     206              : 
     207              :   template <typename T> void visit (std::unique_ptr<AST::Expr> &expr)
     208              :   {
     209              :     maybe_expand_expr (expr);
     210              :   }
     211              : 
     212              :   template <typename T> void visit (std::unique_ptr<AST::Type> &type)
     213              :   {
     214              :     maybe_expand_type (type);
     215              :   }
     216              : 
     217              :   void visit (AST::Crate &crate) override;
     218              :   void visit (AST::DelimTokenTree &) override;
     219              :   void visit (AST::AttrInputMetaItemContainer &) override;
     220              :   void visit (AST::IdentifierExpr &ident_expr) override;
     221              :   void visit (AST::LifetimeParam &) override;
     222              :   void visit (AST::ConstGenericParam &) override;
     223              : 
     224              :   void visit (AST::MacroInvocation &macro_invoc) override;
     225              : 
     226              :   void visit (AST::PathInExpression &path) override;
     227              :   void visit (AST::TypePathSegmentGeneric &segment) override;
     228              :   void visit (AST::TypePathSegmentFunction &segment) override;
     229              :   void visit (AST::QualifiedPathInExpression &path) override;
     230              :   void visit (AST::QualifiedPathInType &path) override;
     231              : 
     232              :   void visit (AST::LiteralExpr &expr) override;
     233              :   void visit (AST::AttrInputLiteral &) override;
     234              :   void visit (AST::AttrInputMacro &) override;
     235              :   void visit (AST::MetaItemLitExpr &) override;
     236              :   void visit (AST::MetaItemPathExpr &) override;
     237              :   void visit (AST::ArithmeticOrLogicalExpr &expr) override;
     238              :   void visit (AST::ComparisonExpr &expr) override;
     239              :   void visit (AST::LazyBooleanExpr &expr) override;
     240              :   void visit (AST::TypeCastExpr &expr) override;
     241              :   void visit (AST::AssignmentExpr &expr) override;
     242              :   void visit (AST::CompoundAssignmentExpr &expr) override;
     243              :   void visit (AST::GroupedExpr &expr) override;
     244              :   void visit (AST::StructExprStruct &expr) override;
     245              : 
     246              :   void visit (AST::CallExpr &expr) override;
     247              :   void visit (AST::ClosureExprInner &expr) override;
     248              : 
     249              :   void visit (AST::BlockExpr &expr) override;
     250              : 
     251              :   void visit (AST::ClosureExprInnerTyped &expr) override;
     252              :   void visit (AST::ContinueExpr &expr) override;
     253              :   void visit (AST::IfExpr &expr) override;
     254              :   void visit (AST::IfExprConseqElse &expr) override;
     255              :   void visit (AST::IfLetExpr &expr) override;
     256              :   void visit (AST::IfLetExprConseqElse &expr) override;
     257              :   void visit (AST::TupleExpr &expr) override;
     258              :   void visit (AST::TypeParam &param) override;
     259              :   void visit (AST::LifetimeWhereClauseItem &) override;
     260              :   void visit (AST::TypeBoundWhereClauseItem &item) override;
     261              :   void visit (AST::Module &module) override;
     262              :   void visit (AST::ExternCrate &crate) override;
     263              :   void visit (AST::UseTreeGlob &) override;
     264              :   void visit (AST::UseTreeList &) override;
     265              :   void visit (AST::UseTreeRebind &) override;
     266              :   void visit (AST::UseDeclaration &use_decl) override;
     267              :   void visit (AST::Function &function) override;
     268              :   void visit (AST::StructStruct &struct_item) override;
     269              :   void visit (AST::TupleStruct &tuple_struct) override;
     270              :   void visit (AST::EnumItem &item) override;
     271              :   void visit (AST::EnumItemTuple &item) override;
     272              :   void visit (AST::EnumItemStruct &item) override;
     273              :   void visit (AST::EnumItemDiscriminant &item) override;
     274              :   void visit (AST::Union &union_item) override;
     275              :   void visit (AST::ConstantItem &const_item) override;
     276              :   void visit (AST::StaticItem &static_item) override;
     277              :   void visit (AST::Trait &trait) override;
     278              :   void visit (AST::InherentImpl &impl) override;
     279              :   void visit (AST::TraitImpl &impl) override;
     280              :   void visit (AST::ExternalTypeItem &item) override;
     281              :   void visit (AST::ExternalStaticItem &item) override;
     282              :   void visit (AST::ExternBlock &block) override;
     283              : 
     284              :   // I don't think it would be possible to strip macros without expansion
     285              :   void visit (AST::MacroMatchRepetition &) override;
     286              :   void visit (AST::MacroMatcher &) override;
     287              :   void visit (AST::MacroRulesDefinition &rules_def) override;
     288              :   void visit (AST::MetaItemPath &) override;
     289              :   void visit (AST::MetaItemSeq &) override;
     290              :   void visit (AST::MetaListPaths &) override;
     291              :   void visit (AST::MetaListNameValueStr &) override;
     292              :   void visit (AST::StructPatternFieldIdent &field) override;
     293              :   void visit (AST::GroupedPattern &pattern) override;
     294              :   void visit (AST::SlicePatternItemsNoRest &items) override;
     295              :   void visit (AST::SlicePatternItemsHasRest &items) override;
     296              :   void visit (AST::AltPattern &pattern) override;
     297              :   void visit (AST::TupleStructItemsNoRest &tuple_items) override;
     298              :   void visit (AST::TupleStructItemsHasRest &tuple_items) override;
     299              :   void visit (AST::TuplePatternItemsNoRest &tuple_items) override;
     300              :   void visit (AST::TuplePatternItemsHasRest &tuple_items) override;
     301              : 
     302              :   void visit (AST::LetStmt &stmt) override;
     303              :   void visit (AST::ExprStmt &stmt) override;
     304              : 
     305              :   void visit (AST::BareFunctionType &type) override;
     306              :   void visit (AST::FunctionParam &param) override;
     307              :   void visit (AST::VariadicParam &param) override;
     308              :   void visit (AST::SelfParam &type) override;
     309              : 
     310              :   template <typename T>
     311              :   void expand_inner_attribute (T &item, AST::SimplePath &Path);
     312              : 
     313              :   template <typename T>
     314              :   void visit_inner_using_attrs (T &item, std::vector<AST::Attribute> &attrs);
     315              : 
     316              :   template <typename T> void visit_inner_attrs (T &item);
     317              : 
     318              : private:
     319              :   MacroExpander &expander;
     320              :   NodeId macro_invoc_expect_id;
     321              : 
     322              :   /**
     323              :    * Helper to expand all macro invocations in lieu of types within a vector of
     324              :    * fields (StructField or TupleField).
     325              :    */
     326         7108 :   template <typename T> void expand_fields (std::vector<T> &fields)
     327              :   {
     328        17053 :     for (auto &field : fields)
     329         9945 :       maybe_expand_type (field.get_field_type_ptr ());
     330         7108 :   }
     331              : };
     332              : 
     333              : } // namespace Rust
     334              : 
     335              : #endif // RUST_EXPAND_VISITOR_H
        

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.