LCOV - code coverage report
Current view: top level - gcc/rust/ast - rust-ast.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 89.6 % 469 420
Test Date: 2026-02-28 14:20:25 Functions: 79.2 % 130 103
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_AST_BASE_H
      20              : #define RUST_AST_BASE_H
      21              : // Base for AST used in gccrs, basically required by all specific ast things
      22              : 
      23              : #include "rust-system.h"
      24              : #include "rust-hir-map.h"
      25              : #include "rust-token.h"
      26              : #include "rust-location.h"
      27              : #include "rust-diagnostics.h"
      28              : #include "rust-keyword-values.h"
      29              : 
      30              : namespace Rust {
      31              : // TODO: remove typedefs and make actual types for these
      32              : typedef int TupleIndex;
      33              : struct Session;
      34              : struct MacroExpander;
      35              : 
      36      3754354 : class Identifier
      37              : {
      38              : public:
      39              :   // Create dummy identifier
      40         1016 :   Identifier () : ident (""), loc (UNDEF_LOCATION) {}
      41              :   // Create identifier with dummy location
      42       309973 :   Identifier (std::string ident, location_t loc = UNDEF_LOCATION)
      43       618856 :     : ident (ident), loc (loc)
      44              :   {}
      45              :   // Create identifier from token
      46        42475 :   Identifier (const_TokenPtr token)
      47        42475 :     : ident (token->get_str ()), loc (token->get_locus ())
      48        42475 :   {}
      49              : 
      50      4125420 :   Identifier (const Identifier &) = default;
      51      1098758 :   Identifier (Identifier &&) = default;
      52            0 :   Identifier &operator= (const Identifier &) = default;
      53         3325 :   Identifier &operator= (Identifier &&) = default;
      54              : 
      55         5083 :   location_t get_locus () const { return loc; }
      56      1853514 :   const std::string &as_string () const { return ident; }
      57              : 
      58       198164 :   bool empty () const { return ident.empty (); }
      59              : 
      60              :   bool operator== (const Identifier &other) const
      61              :   {
      62              :     return ident == other.ident;
      63              :   }
      64              : 
      65            1 :   operator const std::string & () const { return ident; }
      66              : 
      67              : private:
      68              :   std::string ident;
      69              :   location_t loc;
      70              : };
      71              : 
      72              : std::ostream &operator<< (std::ostream &os, Identifier const &i);
      73              : 
      74              : namespace AST {
      75              : // foward decl: ast visitor
      76              : class ASTVisitor;
      77              : using AttrVec = std::vector<Attribute>;
      78              : 
      79       382992 : class Visitable
      80              : {
      81              : public:
      82       174931 :   virtual ~Visitable () = default;
      83              :   virtual void accept_vis (ASTVisitor &vis) = 0;
      84              : };
      85              : 
      86              : /**
      87              :  * Base function for reconstructing and asserting that the new NodeId is
      88              :  * different from the old NodeId. It then wraps the given pointer into a unique
      89              :  * pointer and returns it.
      90              :  */
      91              : template <typename T>
      92              : std::unique_ptr<T>
      93           95 : reconstruct_base (const T *instance)
      94              : {
      95           95 :   auto *reconstructed = instance->reconstruct_impl ();
      96              : 
      97           95 :   rust_assert (reconstructed->get_node_id () != instance->get_node_id ());
      98              : 
      99           95 :   return std::unique_ptr<T> (reconstructed);
     100              : }
     101              : 
     102              : /**
     103              :  * Reconstruct multiple items in a vector
     104              :  */
     105              : template <typename T>
     106              : std::vector<std::unique_ptr<T>>
     107           93 : reconstruct_vec (const std::vector<std::unique_ptr<T>> &to_reconstruct)
     108              : {
     109           93 :   std::vector<std::unique_ptr<T>> reconstructed;
     110           93 :   reconstructed.reserve (to_reconstruct.size ());
     111              : 
     112          186 :   for (const auto &elt : to_reconstruct)
     113           93 :     reconstructed.emplace_back (std::unique_ptr<T> (elt->reconstruct_impl ()));
     114              : 
     115           93 :   return reconstructed;
     116              : }
     117              : 
     118              : // Delimiter types - used in macros and whatever.
     119              : enum DelimType
     120              : {
     121              :   PARENS,
     122              :   SQUARE,
     123              :   CURLY
     124              : };
     125              : 
     126              : // forward decl for use in token tree method
     127              : class Token;
     128              : 
     129              : // A tree of tokens (or a single token) - abstract base class
     130       378661 : class TokenTree : public Visitable
     131              : {
     132              : public:
     133        48951 :   virtual ~TokenTree () {}
     134              : 
     135              :   // Unique pointer custom clone function
     136       498546 :   std::unique_ptr<TokenTree> clone_token_tree () const
     137              :   {
     138       498546 :     return std::unique_ptr<TokenTree> (clone_token_tree_impl ());
     139              :   }
     140              : 
     141              :   virtual std::string as_string () const = 0;
     142              : 
     143              :   /* Converts token tree to a flat token stream. Tokens must be pointer to
     144              :    * avoid mutual dependency with Token. */
     145              :   virtual std::vector<std::unique_ptr<Token>> to_token_stream () const = 0;
     146              : 
     147              : protected:
     148              :   // pure virtual clone implementation
     149              :   virtual TokenTree *clone_token_tree_impl () const = 0;
     150              : };
     151              : 
     152              : // Abstract base class for a macro match
     153       138327 : class MacroMatch : public Visitable
     154              : {
     155              : public:
     156              :   enum MacroMatchType
     157              :   {
     158              :     Fragment,
     159              :     Repetition,
     160              :     Matcher,
     161              :     Tok
     162              :   };
     163              : 
     164         1211 :   virtual ~MacroMatch () {}
     165              : 
     166              :   virtual std::string as_string () const = 0;
     167              :   virtual location_t get_match_locus () const = 0;
     168              : 
     169              :   // Unique pointer custom clone function
     170         4195 :   std::unique_ptr<MacroMatch> clone_macro_match () const
     171              :   {
     172         4195 :     return std::unique_ptr<MacroMatch> (clone_macro_match_impl ());
     173              :   }
     174              : 
     175              :   virtual MacroMatchType get_macro_match_type () const = 0;
     176              : 
     177              : protected:
     178              :   // pure virtual clone implementation
     179              :   virtual MacroMatch *clone_macro_match_impl () const = 0;
     180              : };
     181              : 
     182              : // A token is a kind of token tree (except delimiter tokens)
     183              : class Token : public TokenTree, public MacroMatch
     184              : {
     185              :   // A token is a kind of token tree (except delimiter tokens)
     186              :   // A token is a kind of MacroMatch (except $ and delimiter tokens)
     187              : 
     188              :   const_TokenPtr tok_ref;
     189              : 
     190              :   /* new idea: wrapper around const_TokenPtr used for heterogeneuous storage
     191              :    * in token trees. rather than convert back and forth when parsing macros,
     192              :    * just wrap it. */
     193              : 
     194              : public:
     195              :   // Unique pointer custom clone function
     196       909681 :   std::unique_ptr<Token> clone_token () const
     197              :   {
     198       909681 :     return std::unique_ptr<Token> (clone_token_impl ());
     199              :   }
     200              : 
     201              :   // Constructor from lexer const_TokenPtr
     202       235136 :   Token (const_TokenPtr lexer_tok_ptr) : tok_ref (std::move (lexer_tok_ptr)) {}
     203              : 
     204        42423 :   bool is_string_lit () const
     205              :   {
     206        42423 :     switch (get_id ())
     207              :       {
     208              :       case STRING_LITERAL:
     209              :       case BYTE_STRING_LITERAL:
     210              :       case RAW_STRING_LITERAL:
     211              :         return true;
     212        41608 :       default:
     213        41608 :         return false;
     214              :       }
     215              :   }
     216              : 
     217              :   std::string as_string () const override;
     218          203 :   location_t get_match_locus () const override
     219              :   {
     220          203 :     return tok_ref->get_locus ();
     221              :   };
     222              : 
     223              :   void accept_vis (ASTVisitor &vis) override;
     224              : 
     225              :   // Return copy of itself but in token stream form.
     226              :   std::vector<std::unique_ptr<Token>> to_token_stream () const override;
     227              : 
     228       274606 :   TokenId get_id () const { return tok_ref->get_id (); }
     229           17 :   bool should_have_str () const { return tok_ref->should_have_str (); }
     230        25170 :   const std::string &get_str () const { return tok_ref->get_str (); }
     231              : 
     232          873 :   location_t get_locus () const { return tok_ref->get_locus (); }
     233              : 
     234            1 :   PrimitiveCoreType get_type_hint () const { return tok_ref->get_type_hint (); }
     235              : 
     236              :   // Get a new token pointer copy.
     237       467088 :   const_TokenPtr get_tok_ptr () const { return tok_ref; }
     238              : 
     239         4273 :   MacroMatchType get_macro_match_type () const override
     240              :   {
     241         4273 :     return MacroMatchType::Tok;
     242              :   }
     243              : 
     244              : protected:
     245              :   // No virtual for now as not polymorphic but can be in future
     246      1563840 :   /*virtual*/ Token *clone_token_impl () const { return new Token (*this); }
     247              : 
     248              :   /* Use covariance to implement clone function as returning this object
     249              :    * rather than base */
     250       471025 :   Token *clone_token_tree_impl () const final override
     251              :   {
     252       471025 :     return clone_token_impl ();
     253              :   }
     254              : 
     255              :   /* Use covariance to implement clone function as returning this object
     256              :    * rather than base */
     257            0 :   Token *clone_macro_match_impl () const final override
     258              :   {
     259            0 :     return clone_token_impl ();
     260              :   }
     261              : };
     262              : 
     263              : // A literal - value with a type. Used in LiteralExpr and LiteralPattern.
     264        22367 : struct Literal
     265              : {
     266              : public:
     267              :   enum LitType
     268              :   {
     269              :     CHAR,
     270              :     STRING,
     271              :     BYTE,
     272              :     BYTE_STRING,
     273              :     RAW_STRING,
     274              :     INT,
     275              :     FLOAT,
     276              :     BOOL,
     277              :     ERROR
     278              :   };
     279              : 
     280              : private:
     281              :   /* TODO: maybe make subclasses of each type of literal with their typed
     282              :    * values (or generics) */
     283              :   std::string value_as_string;
     284              :   LitType type;
     285              :   PrimitiveCoreType type_hint;
     286              : 
     287              : public:
     288        33267 :   std::string as_string () const { return value_as_string; }
     289              : 
     290        29374 :   LitType get_lit_type () const { return type; }
     291              : 
     292        20500 :   PrimitiveCoreType get_type_hint () const { return type_hint; }
     293              : 
     294        38126 :   Literal (std::string value_as_string, LitType type,
     295              :            PrimitiveCoreType type_hint)
     296        38126 :     : value_as_string (std::move (value_as_string)), type (type),
     297        38126 :       type_hint (type_hint)
     298              :   {}
     299              : 
     300            0 :   static Literal create_error ()
     301              :   {
     302            0 :     return Literal ("", ERROR, PrimitiveCoreType::CORETYPE_UNKNOWN);
     303              :   }
     304              : 
     305              :   // Returns whether literal is in an invalid state.
     306       611604 :   bool is_error () const { return type == ERROR; }
     307              : };
     308              : 
     309              : /* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr
     310              :  * to be defined */
     311              : class AttrInputLiteral;
     312              : 
     313              : /* TODO: move applicable stuff into here or just don't include it because
     314              :  * nothing uses it A segment of a path (maybe) */
     315        95415 : class PathSegment
     316              : {
     317              : public:
     318        24074 :   virtual ~PathSegment () {}
     319              : 
     320              :   virtual std::string as_string () const = 0;
     321              : 
     322              :   // TODO: add visitor here?
     323              : };
     324              : 
     325              : // A segment of a simple path without generic or type arguments
     326        92575 : class SimplePathSegment : public PathSegment
     327              : {
     328              :   std::string segment_name;
     329              :   location_t locus;
     330              :   NodeId node_id;
     331              : 
     332              :   // only allow identifiers, "super", "self", "crate", or "$crate"
     333              : public:
     334              :   // TODO: put checks in constructor to enforce this rule?
     335        34700 :   SimplePathSegment (std::string segment_name, location_t locus)
     336        69400 :     : segment_name (std::move (segment_name)), locus (locus),
     337        34700 :       node_id (Analysis::Mappings::get ().get_next_node_id ())
     338        34700 :   {}
     339              : 
     340              :   /* Returns whether simple path segment is in an invalid state (currently, if
     341              :    * empty). */
     342       264843 :   bool is_error () const { return segment_name.empty (); }
     343              : 
     344              :   // Creates an error SimplePathSegment
     345              :   static SimplePathSegment create_error ()
     346              :   {
     347              :     return SimplePathSegment (std::string (""), UNDEF_LOCATION);
     348              :   }
     349              : 
     350              :   std::string as_string () const override;
     351              : 
     352        29964 :   location_t get_locus () const { return locus; }
     353        19803 :   NodeId get_node_id () const { return node_id; }
     354        77349 :   const std::string &get_segment_name () const { return segment_name; }
     355        26331 :   bool is_super_path_seg () const
     356              :   {
     357        26331 :     return as_string ().compare (Values::Keywords::SUPER) == 0;
     358              :   }
     359        37060 :   bool is_crate_path_seg () const
     360              :   {
     361        37060 :     return as_string ().compare (Values::Keywords::CRATE) == 0;
     362              :   }
     363        50189 :   bool is_lower_self_seg () const
     364              :   {
     365        50189 :     return as_string ().compare (Values::Keywords::SELF) == 0;
     366              :   }
     367         2084 :   bool is_big_self () const
     368              :   {
     369         2084 :     return as_string ().compare (Values::Keywords::SELF_ALIAS) == 0;
     370              :   }
     371              : };
     372              : 
     373              : // A simple path without generic or type arguments
     374       406362 : class SimplePath
     375              : {
     376              :   bool opening_scope_resolution;
     377              :   std::vector<SimplePathSegment> segments;
     378              :   location_t locus;
     379              :   NodeId node_id;
     380              : 
     381              : public:
     382              :   // Constructor
     383        99449 :   explicit SimplePath (std::vector<SimplePathSegment> path_segments,
     384              :                        bool has_opening_scope_resolution = false,
     385              :                        location_t locus = UNDEF_LOCATION)
     386        99449 :     : opening_scope_resolution (has_opening_scope_resolution),
     387        99449 :       segments (std::move (path_segments)), locus (locus),
     388        99449 :       node_id (Analysis::Mappings::get ().get_next_node_id ())
     389        99449 :   {}
     390              : 
     391          391 :   explicit SimplePath (Identifier ident)
     392          391 :     : opening_scope_resolution (false),
     393         1173 :       segments ({SimplePathSegment (ident.as_string (), ident.get_locus ())}),
     394          391 :       locus (ident.get_locus ()),
     395          391 :       node_id (Analysis::Mappings::get ().get_next_node_id ())
     396          391 :   {}
     397              : 
     398              :   // Creates an empty SimplePath.
     399        66177 :   static SimplePath create_empty ()
     400              :   {
     401        66177 :     return SimplePath (std::vector<SimplePathSegment> ());
     402              :   }
     403              : 
     404              :   // Returns whether the SimplePath is empty, i.e. has path segments.
     405        13322 :   bool is_empty () const { return segments.empty (); }
     406              : 
     407              :   const std::string as_string () const;
     408              : 
     409        11678 :   bool has_opening_scope_resolution () const
     410              :   {
     411        11678 :     return opening_scope_resolution;
     412              :   }
     413              : 
     414         2809 :   location_t get_locus () const { return locus; }
     415          124 :   NodeId get_node_id () const { return node_id; }
     416              : 
     417              :   // does this need visitor if not polymorphic? probably not
     418              : 
     419              :   // path-to-string comparison operator
     420       375632 :   bool operator== (const std::string &rhs) const
     421              :   {
     422       375632 :     return !opening_scope_resolution && segments.size () == 1
     423       751264 :            && segments[0].as_string () == rhs;
     424              :   }
     425              : 
     426              :   /* Creates a single-segment SimplePath from a string. This will not check to
     427              :    * ensure that this is a valid identifier in path, so be careful. Also, this
     428              :    * will have no location data.
     429              :    * TODO have checks? */
     430           54 :   static SimplePath from_str (std::string str, location_t locus)
     431              :   {
     432           54 :     std::vector<AST::SimplePathSegment> single_segments
     433          108 :       = {AST::SimplePathSegment (std::move (str), locus)};
     434           54 :     return SimplePath (std::move (single_segments), false, locus);
     435           54 :   }
     436              : 
     437        37336 :   const std::vector<SimplePathSegment> &get_segments () const
     438              :   {
     439        40428 :     return segments;
     440              :   }
     441              : 
     442        55501 :   std::vector<SimplePathSegment> &get_segments () { return segments; }
     443              : 
     444        13095 :   const SimplePathSegment &get_final_segment () const
     445              :   {
     446        13095 :     return segments.back ();
     447              :   }
     448              : };
     449              : 
     450              : // path-to-string inverse comparison operator
     451              : inline bool
     452        11608 : operator!= (const SimplePath &lhs, const std::string &rhs)
     453              : {
     454        11608 :   return !(lhs == rhs);
     455              : }
     456              : 
     457              : // forward decl for Attribute
     458              : class AttrInput;
     459              : 
     460              : // Visibility of item - if the item has it, then it is some form of public
     461       264940 : struct Visibility
     462              : {
     463              : public:
     464              :   enum VisType
     465              :   {
     466              :     PRIV,
     467              :     PUB,
     468              :     PUB_CRATE,
     469              :     PUB_SELF,
     470              :     PUB_SUPER,
     471              :     PUB_IN_PATH
     472              :   };
     473              : 
     474              : private:
     475              :   VisType vis_type;
     476              :   // Only assigned if vis_type is IN_PATH
     477              :   SimplePath in_path;
     478              :   location_t locus;
     479              : 
     480        60104 :   Visibility (VisType vis_type, SimplePath in_path, location_t locus)
     481        13144 :     : vis_type (vis_type), in_path (std::move (in_path)), locus (locus)
     482              :   {}
     483              : 
     484              : public:
     485        40145 :   VisType get_vis_type () const { return vis_type; }
     486              : 
     487              :   // Returns whether a visibility has a path
     488       594601 :   bool has_path () const { return vis_type >= PUB_CRATE; }
     489              : 
     490              :   // Returns whether visibility is public or not.
     491         1234 :   bool is_public () const { return vis_type != PRIV; }
     492              : 
     493         2684 :   location_t get_locus () const { return locus; }
     494              : 
     495              :   // Unique pointer custom clone function
     496              :   /*std::unique_ptr<Visibility> clone_visibility() const {
     497              :       return std::unique_ptr<Visibility>(clone_visibility_impl());
     498              :   }*/
     499              : 
     500              :   /* TODO: think of a way to only allow valid Visibility states - polymorphism
     501              :    * is one idea but may be too resource-intensive. */
     502              : 
     503              :   // Creates a public visibility with no further features/arguments.
     504              :   // empty?
     505         8249 :   static Visibility create_public (location_t pub_vis_location)
     506              :   {
     507         8249 :     return Visibility (PUB, SimplePath::create_empty (), pub_vis_location);
     508              :   }
     509              : 
     510              :   // Creates a public visibility with crate-relative paths
     511           53 :   static Visibility create_crate (location_t crate_tok_location,
     512              :                                   location_t crate_vis_location)
     513              :   {
     514           53 :     return Visibility (PUB_CRATE,
     515           53 :                        SimplePath::from_str (Values::Keywords::CRATE,
     516              :                                              crate_tok_location),
     517           53 :                        crate_vis_location);
     518              :   }
     519              : 
     520              :   // Creates a public visibility with self-relative paths
     521            0 :   static Visibility create_self (location_t self_tok_location,
     522              :                                  location_t self_vis_location)
     523              :   {
     524            0 :     return Visibility (PUB_SELF,
     525            0 :                        SimplePath::from_str (Values::Keywords::SELF,
     526              :                                              self_tok_location),
     527            0 :                        self_vis_location);
     528              :   }
     529              : 
     530              :   // Creates a public visibility with parent module-relative paths
     531            1 :   static Visibility create_super (location_t super_tok_location,
     532              :                                   location_t super_vis_location)
     533              :   {
     534            1 :     return Visibility (PUB_SUPER,
     535            1 :                        SimplePath::from_str (Values::Keywords::SUPER,
     536              :                                              super_tok_location),
     537            1 :                        super_vis_location);
     538              :   }
     539              : 
     540              :   // Creates a private visibility
     541        51789 :   static Visibility create_private ()
     542              :   {
     543        51789 :     return Visibility (PRIV, SimplePath::create_empty (), UNDEF_LOCATION);
     544              :   }
     545              : 
     546              :   // Creates a public visibility with a given path or whatever.
     547           12 :   static Visibility create_in_path (SimplePath in_path,
     548              :                                     location_t in_path_vis_location)
     549              :   {
     550           12 :     return Visibility (PUB_IN_PATH, std::move (in_path), in_path_vis_location);
     551              :   }
     552              : 
     553              :   std::string as_string () const;
     554           61 :   const SimplePath &get_path () const { return in_path; }
     555          992 :   SimplePath &get_path () { return in_path; }
     556              : 
     557              : protected:
     558              :   // Clone function implementation - not currently virtual but may be if
     559              :   // polymorphism used
     560              :   /*virtual*/ Visibility *clone_visibility_impl () const
     561              :   {
     562              :     return new Visibility (*this);
     563              :   }
     564              : };
     565              : 
     566              : // aka Attr
     567              : // Attribute AST representation
     568              : struct Attribute
     569              : {
     570              : private:
     571              :   SimplePath path;
     572              : 
     573              :   // bool has_attr_input;
     574              :   std::unique_ptr<AttrInput> attr_input;
     575              : 
     576              :   location_t locus;
     577              : 
     578              :   bool inner_attribute;
     579              : 
     580              :   // TODO: maybe a variable storing whether attr input is parsed or not
     581              : 
     582              : public:
     583              :   // Returns whether Attribute has AttrInput
     584        77532 :   bool has_attr_input () const { return attr_input != nullptr; }
     585              : 
     586              :   // Constructor has pointer AttrInput for polymorphism reasons
     587        34142 :   Attribute (SimplePath path, std::unique_ptr<AttrInput> input,
     588              :              location_t locus = UNDEF_LOCATION, bool inner_attribute = false)
     589        34142 :     : path (std::move (path)), attr_input (std::move (input)), locus (locus),
     590        34142 :       inner_attribute (inner_attribute)
     591              :   {}
     592              : 
     593              :   bool is_derive () const;
     594              : 
     595              :   std::vector<std::reference_wrapper<AST::SimplePath>> get_traits_to_derive ();
     596              : 
     597              :   // default destructor
     598       146155 :   ~Attribute () = default;
     599              : 
     600              :   // no point in being defined inline as requires virtual call anyway
     601              :   Attribute (const Attribute &other);
     602              : 
     603              :   // no point in being defined inline as requires virtual call anyway
     604              :   Attribute &operator= (const Attribute &other);
     605              : 
     606              :   // default move semantics
     607        93712 :   Attribute (Attribute &&other) = default;
     608            7 :   Attribute &operator= (Attribute &&other) = default;
     609              : 
     610              :   // Unique pointer custom clone function
     611              :   std::unique_ptr<Attribute> clone_attribute () const
     612              :   {
     613              :     return std::unique_ptr<Attribute> (clone_attribute_impl ());
     614              :   }
     615              : 
     616              :   // Creates an empty attribute (which is invalid)
     617         5532 :   static Attribute create_empty ()
     618              :   {
     619         5532 :     return Attribute (SimplePath::create_empty (), nullptr);
     620              :   }
     621              : 
     622              :   // Returns whether the attribute is considered an "empty" attribute.
     623         2623 :   bool is_empty () const { return attr_input == nullptr && path.is_empty (); }
     624              : 
     625              :   // Returns whether the attribute has no input
     626        23086 :   bool empty_input () const { return !attr_input; }
     627              : 
     628         6546 :   location_t get_locus () const { return locus; }
     629              : 
     630        61067 :   AttrInput &get_attr_input () const { return *attr_input; }
     631              : 
     632              :   /* e.g.:
     633              :       #![crate_type = "lib"]
     634              :       #[test]
     635              :       #[cfg(target_os = "linux")]
     636              :       #[allow(non_camel_case_types)]
     637              :       #![allow(unused_variables)]
     638              :   */
     639              : 
     640              :   // Full built-in attribute list:
     641              :   /*   cfg
     642              :    *   cfg_attr
     643              :    *   test
     644              :    *   ignore
     645              :    *   should_panic
     646              :    *   derive
     647              :    *   macro_export
     648              :    *   macro_use
     649              :    *   proc_macro
     650              :    *   proc_macro_derive
     651              :    *   proc_macro_attribute
     652              :    *   allow
     653              :    *   warn
     654              :    *   deny
     655              :    *   forbid
     656              :    *   deprecated
     657              :    *   must_use
     658              :    *   link
     659              :    *   link_name
     660              :    *   no_link
     661              :    *   repr
     662              :    *   crate_type
     663              :    *   no_main
     664              :    *   export_name
     665              :    *   link_section
     666              :    *   no_mangle
     667              :    *   used
     668              :    *   crate_name
     669              :    *   inline
     670              :    *   cold
     671              :    *   no_builtins
     672              :    *   target_feature
     673              :    *   doc
     674              :    *   no_std
     675              :    *   no_implicit_prelude
     676              :    *   path
     677              :    *   recursion_limit
     678              :    *   type_length_limit
     679              :    *   panic_handler
     680              :    *   global_allocator
     681              :    *   windows_subsystem
     682              :    *   feature     */
     683              : 
     684              :   std::string as_string () const;
     685              : 
     686         2084 :   bool is_inner_attribute () const { return inner_attribute; }
     687              : 
     688              :   // no visitor pattern as not currently polymorphic
     689              : 
     690       175969 :   const SimplePath &get_path () const { return path; }
     691       219716 :   SimplePath &get_path () { return path; }
     692              : 
     693              :   // Call to parse attribute body to meta item syntax.
     694              :   void parse_attr_to_meta_item ();
     695              : 
     696              :   /* Determines whether cfg predicate is true and item with attribute should
     697              :    * not be stripped. Attribute body must already be parsed to meta item. */
     698              :   bool check_cfg_predicate (const Session &session) const;
     699              : 
     700              :   // Returns whether body has been parsed to meta item form or not.
     701              :   bool is_parsed_to_meta_item () const;
     702              : 
     703              :   /* Returns any attributes generated from cfg_attr attributes. Attribute body
     704              :    * must already be parsed to meta item. */
     705              :   std::vector<Attribute> separate_cfg_attrs () const;
     706              : 
     707              : protected:
     708              :   // not virtual as currently no subclasses of Attribute, but could be in
     709              :   // future
     710              :   /*virtual*/ Attribute *clone_attribute_impl () const
     711              :   {
     712              :     return new Attribute (*this);
     713              :   }
     714              : };
     715              : 
     716              : // Attribute body - abstract base class
     717        57188 : class AttrInput : public Visitable
     718              : {
     719              : public:
     720              :   enum AttrInputType
     721              :   {
     722              :     LITERAL,
     723              :     MACRO,
     724              :     META_ITEM,
     725              :     TOKEN_TREE,
     726              :   };
     727              : 
     728        48951 :   virtual ~AttrInput () {}
     729              : 
     730              :   // Unique pointer custom clone function
     731        71417 :   std::unique_ptr<AttrInput> clone_attr_input () const
     732              :   {
     733        71417 :     return std::unique_ptr<AttrInput> (clone_attr_input_impl ());
     734              :   }
     735              : 
     736              :   virtual std::string as_string () const = 0;
     737              : 
     738              :   virtual bool check_cfg_predicate (const Session &session) const = 0;
     739              : 
     740              :   // Parse attribute input to meta item, if possible
     741            0 :   virtual AttrInput *parse_to_meta_item () const { return nullptr; }
     742              : 
     743            0 :   virtual std::vector<Attribute> separate_cfg_attrs () const { return {}; }
     744              : 
     745              :   // Returns whether attr input has been parsed to meta item syntax.
     746              :   virtual bool is_meta_item () const = 0;
     747              : 
     748              :   virtual AttrInputType get_attr_input_type () const = 0;
     749              : 
     750              : protected:
     751              :   // pure virtual clone implementation
     752              :   virtual AttrInput *clone_attr_input_impl () const = 0;
     753              : };
     754              : 
     755              : // Forward decl - defined in rust-macro.h
     756              : class MetaNameValueStr;
     757              : 
     758              : // abstract base meta item inner class
     759           54 : class MetaItemInner : public Visitable
     760              : {
     761              : protected:
     762              :   // pure virtual as MetaItemInner
     763              :   virtual MetaItemInner *clone_meta_item_inner_impl () const = 0;
     764              : 
     765              : public:
     766              :   enum class Kind
     767              :   {
     768              :     LitExpr,
     769              :     MetaItem,
     770              :   };
     771              : 
     772              :   // Unique pointer custom clone function
     773         2461 :   std::unique_ptr<MetaItemInner> clone_meta_item_inner () const
     774              :   {
     775         2461 :     return std::unique_ptr<MetaItemInner> (clone_meta_item_inner_impl ());
     776              :   }
     777              : 
     778              :   virtual Kind get_kind () = 0;
     779              : 
     780              :   virtual ~MetaItemInner ();
     781              : 
     782              :   virtual location_t get_locus () const = 0;
     783              : 
     784              :   virtual std::string as_string () const = 0;
     785              : 
     786              :   /* HACK: used to simplify parsing - creates a copy of that type, or returns
     787              :    * null */
     788              :   virtual std::unique_ptr<MetaNameValueStr> to_meta_name_value_str () const;
     789              : 
     790              :   // HACK: used to simplify parsing - same thing
     791            0 :   virtual SimplePath to_path_item () const
     792              :   {
     793            0 :     return SimplePath::create_empty ();
     794              :   }
     795              : 
     796            0 :   virtual Attribute to_attribute () const { return Attribute::create_empty (); }
     797              : 
     798              :   virtual bool check_cfg_predicate (const Session &session) const = 0;
     799              : 
     800           42 :   virtual bool is_key_value_pair () const { return false; }
     801              : };
     802              : 
     803              : // Container used to store MetaItems as AttrInput (bridge-ish kinda thing)
     804              : class AttrInputMetaItemContainer : public AttrInput
     805              : {
     806              :   std::vector<std::unique_ptr<MetaItemInner>> items;
     807              : 
     808              : public:
     809        17777 :   AttrInputMetaItemContainer (std::vector<std::unique_ptr<MetaItemInner>> items)
     810        17777 :     : items (std::move (items))
     811              :   {}
     812              : 
     813              :   // copy constructor with vector clone
     814         2306 :   AttrInputMetaItemContainer (const AttrInputMetaItemContainer &other)
     815         2306 :   {
     816         2306 :     items.reserve (other.items.size ());
     817         4734 :     for (const auto &e : other.items)
     818         2428 :       items.push_back (e->clone_meta_item_inner ());
     819         2306 :   }
     820              : 
     821              :   // copy assignment operator with vector clone
     822              :   AttrInputMetaItemContainer &
     823              :   operator= (const AttrInputMetaItemContainer &other)
     824              :   {
     825              :     AttrInput::operator= (other);
     826              : 
     827              :     items.reserve (other.items.size ());
     828              :     for (const auto &e : other.items)
     829              :       items.push_back (e->clone_meta_item_inner ());
     830              : 
     831              :     return *this;
     832              :   }
     833              : 
     834              :   // default move constructors
     835              :   AttrInputMetaItemContainer (AttrInputMetaItemContainer &&other) = default;
     836              :   AttrInputMetaItemContainer &operator= (AttrInputMetaItemContainer &&other)
     837              :     = default;
     838              : 
     839              :   std::string as_string () const override;
     840              : 
     841              :   void accept_vis (ASTVisitor &vis) override;
     842              : 
     843              :   bool check_cfg_predicate (const Session &session) const override;
     844              : 
     845          262 :   AttrInputType get_attr_input_type () const final override
     846              :   {
     847          262 :     return AttrInput::AttrInputType::META_ITEM;
     848              :   }
     849              : 
     850              :   // Clones this object.
     851              :   std::unique_ptr<AttrInputMetaItemContainer>
     852              :   clone_attr_input_meta_item_container () const
     853              :   {
     854              :     return std::unique_ptr<AttrInputMetaItemContainer> (
     855              :       clone_attr_input_meta_item_container_impl ());
     856              :   }
     857              : 
     858              :   std::vector<Attribute> separate_cfg_attrs () const override;
     859              : 
     860         6164 :   bool is_meta_item () const override { return true; }
     861              : 
     862              :   // TODO: this mutable getter seems dodgy
     863        20884 :   std::vector<std::unique_ptr<MetaItemInner>> &get_items () { return items; }
     864              :   const std::vector<std::unique_ptr<MetaItemInner>> &get_items () const
     865              :   {
     866            1 :     return items;
     867              :   }
     868              : 
     869              : protected:
     870              :   // Use covariance to implement clone function as returning this type
     871         2306 :   AttrInputMetaItemContainer *clone_attr_input_impl () const final override
     872              :   {
     873         2306 :     return clone_attr_input_meta_item_container_impl ();
     874              :   }
     875              : 
     876         2306 :   AttrInputMetaItemContainer *clone_attr_input_meta_item_container_impl () const
     877              :   {
     878         2306 :     return new AttrInputMetaItemContainer (*this);
     879              :   }
     880              : };
     881              : 
     882              : // A token tree with delimiters
     883        47803 : class DelimTokenTree : public TokenTree, public AttrInput
     884              : {
     885              :   DelimType delim_type;
     886              :   std::vector<std::unique_ptr<TokenTree>> token_trees;
     887              :   location_t locus;
     888              : 
     889              : protected:
     890        53826 :   DelimTokenTree *clone_delim_tok_tree_impl () const
     891              :   {
     892        53826 :     return new DelimTokenTree (*this);
     893              :   }
     894              : 
     895              :   /* Use covariance to implement clone function as returning a DelimTokenTree
     896              :    * object */
     897            0 :   DelimTokenTree *clone_attr_input_impl () const final override
     898              :   {
     899            0 :     return clone_delim_tok_tree_impl ();
     900              :   }
     901              : 
     902              :   /* Use covariance to implement clone function as returning a DelimTokenTree
     903              :    * object */
     904        27521 :   DelimTokenTree *clone_token_tree_impl () const final override
     905              :   {
     906        27521 :     return clone_delim_tok_tree_impl ();
     907              :   }
     908              : 
     909              : public:
     910        22615 :   DelimTokenTree (DelimType delim_type,
     911              :                   std::vector<std::unique_ptr<TokenTree>> token_trees
     912              :                   = std::vector<std::unique_ptr<TokenTree>> (),
     913              :                   location_t locus = UNDEF_LOCATION)
     914        22615 :     : delim_type (delim_type), token_trees (std::move (token_trees)),
     915        22615 :       locus (locus)
     916              :   {}
     917              : 
     918              :   // Copy constructor with vector clone
     919        88430 :   DelimTokenTree (DelimTokenTree const &other)
     920        88430 :     : delim_type (other.delim_type), locus (other.locus)
     921              :   {
     922        88430 :     token_trees.clear ();
     923        88430 :     token_trees.reserve (other.token_trees.size ());
     924       586808 :     for (const auto &e : other.token_trees)
     925       498378 :       token_trees.push_back (e->clone_token_tree ());
     926        88430 :   }
     927              : 
     928              :   // overloaded assignment operator with vector clone
     929           43 :   DelimTokenTree &operator= (DelimTokenTree const &other)
     930              :   {
     931           43 :     delim_type = other.delim_type;
     932           43 :     locus = other.locus;
     933              : 
     934           43 :     token_trees.clear ();
     935           43 :     token_trees.reserve (other.token_trees.size ());
     936          211 :     for (const auto &e : other.token_trees)
     937          168 :       token_trees.push_back (e->clone_token_tree ());
     938              : 
     939           43 :     return *this;
     940              :   }
     941              : 
     942              :   // move constructors
     943        23873 :   DelimTokenTree (DelimTokenTree &&other) = default;
     944              :   DelimTokenTree &operator= (DelimTokenTree &&other) = default;
     945              : 
     946           13 :   static DelimTokenTree create_empty () { return DelimTokenTree (PARENS); }
     947              : 
     948              :   std::string as_string () const override;
     949              : 
     950              :   void accept_vis (ASTVisitor &vis) override;
     951              : 
     952            0 :   bool check_cfg_predicate (const Session &) const override
     953              :   {
     954              :     // this should never be called - should be converted first
     955            0 :     rust_assert (false);
     956              :     return false;
     957              :   }
     958              : 
     959              :   AttrInputMetaItemContainer *parse_to_meta_item () const override;
     960              : 
     961              :   std::vector<std::unique_ptr<Token>> to_token_stream () const override;
     962              : 
     963              :   std::unique_ptr<DelimTokenTree> clone_delim_token_tree () const
     964              :   {
     965              :     return std::unique_ptr<DelimTokenTree> (clone_delim_tok_tree_impl ());
     966              :   }
     967              : 
     968         1148 :   bool is_meta_item () const override { return false; }
     969              : 
     970        17929 :   AttrInputType get_attr_input_type () const final override
     971              :   {
     972        17929 :     return AttrInput::AttrInputType::TOKEN_TREE;
     973              :   }
     974              : 
     975              :   std::vector<std::unique_ptr<TokenTree>> &get_token_trees ()
     976              :   {
     977        61616 :     return token_trees;
     978              :   }
     979              : 
     980              :   const std::vector<std::unique_ptr<TokenTree>> &get_token_trees () const
     981              :   {
     982            0 :     return token_trees;
     983              :   }
     984              : 
     985         7833 :   DelimType get_delim_type () const { return delim_type; }
     986         4880 :   location_t get_locus () const { return locus; }
     987              : };
     988              : 
     989              : /* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr
     990              :  * to be defined */
     991              : class AttrInputLiteral;
     992              : 
     993              : // abstract base meta item class
     994        20192 : class MetaItem : public MetaItemInner
     995              : {
     996              : public:
     997              :   enum class ItemKind
     998              :   {
     999              :     Path,
    1000              :     Word,
    1001              :     NameValueStr,
    1002              :     PathExpr,
    1003              :     Seq,
    1004              :     ListPaths,
    1005              :     ListNameValueStr,
    1006              :   };
    1007              : 
    1008          499 :   MetaItemInner::Kind get_kind () override
    1009              :   {
    1010          499 :     return MetaItemInner::Kind::MetaItem;
    1011              :   }
    1012              : 
    1013              :   virtual ItemKind get_item_kind () const = 0;
    1014              : };
    1015              : 
    1016              : // Forward decl - defined in rust-expr.h
    1017              : class MetaItemLitExpr;
    1018              : 
    1019              : // Forward decl - defined in rust-expr.h
    1020              : class MetaItemPathExpr;
    1021              : 
    1022              : // Forward decl - defined in rust-macro.h
    1023              : class MetaItemPath;
    1024              : 
    1025              : // Forward decl - defined in rust-macro.h
    1026              : class MetaItemSeq;
    1027              : 
    1028              : // Forward decl - defined in rust-macro.h
    1029              : class MetaWord;
    1030              : 
    1031              : // Forward decl - defined in rust-macro.h
    1032              : class MetaListPaths;
    1033              : 
    1034              : // Forward decl - defined in rust-macro.h
    1035              : class MetaListNameValueStr;
    1036              : 
    1037              : /* Base statement abstract class. Note that most "statements" are not allowed
    1038              :  * in top-level module scope - only a subclass of statements called "items"
    1039              :  * are. */
    1040         1100 : class Stmt : public Visitable
    1041              : {
    1042              : public:
    1043              :   enum class Kind
    1044              :   {
    1045              :     Empty,
    1046              :     Item,
    1047              :     Let,
    1048              :     Expr,
    1049              :     MacroInvocation,
    1050              :   };
    1051              : 
    1052              :   // Unique pointer custom clone function
    1053        31017 :   std::unique_ptr<Stmt> clone_stmt () const
    1054              :   {
    1055        31017 :     return std::unique_ptr<Stmt> (clone_stmt_impl ());
    1056              :   }
    1057              : 
    1058              :   virtual ~Stmt () {}
    1059              : 
    1060              :   virtual std::string as_string () const = 0;
    1061              : 
    1062              :   virtual location_t get_locus () const = 0;
    1063              : 
    1064              :   virtual void mark_for_strip () = 0;
    1065              :   virtual bool is_marked_for_strip () const = 0;
    1066              : 
    1067              :   // TODO: put this in a virtual base class?
    1068       200629 :   virtual NodeId get_node_id () const { return node_id; }
    1069              : 
    1070              :   virtual Kind get_stmt_kind () = 0;
    1071              : 
    1072              :   // TODO: Can we remove these two?
    1073              :   virtual bool is_item () const = 0;
    1074         4073 :   virtual bool is_expr () const { return false; }
    1075              : 
    1076           38 :   virtual void add_semicolon () {}
    1077              : 
    1078              : protected:
    1079       164747 :   Stmt () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
    1080              : 
    1081              :   // Clone function implementation as pure virtual method
    1082              :   virtual Stmt *clone_stmt_impl () const = 0;
    1083              : 
    1084              :   NodeId node_id;
    1085              : };
    1086              : 
    1087              : // Rust "item" AST node (declaration of top-level/module-level allowed stuff)
    1088        15533 : class Item : public Stmt
    1089              : {
    1090              : public:
    1091              :   enum class Kind
    1092              :   {
    1093              :     MacroRulesDefinition,
    1094              :     MacroInvocation,
    1095              :     Module,
    1096              :     ExternCrate,
    1097              :     UseDeclaration,
    1098              :     Function,
    1099              :     TypeAlias,
    1100              :     Struct,
    1101              :     EnumItem,
    1102              :     Enum,
    1103              :     Union,
    1104              :     ConstantItem,
    1105              :     StaticItem,
    1106              :     Trait,
    1107              :     Impl,
    1108              :     ExternBlock,
    1109              :   };
    1110              : 
    1111              :   virtual Kind get_item_kind () const = 0;
    1112              : 
    1113              :   // Unique pointer custom clone function
    1114        31979 :   std::unique_ptr<Item> clone_item () const
    1115              :   {
    1116        31979 :     return std::unique_ptr<Item> (clone_item_impl ());
    1117              :   }
    1118              : 
    1119              :   /* Adds crate names to the vector passed by reference, if it can
    1120              :    * (polymorphism). TODO: remove, unused. */
    1121              :   virtual void
    1122            0 :   add_crate_name (std::vector<std::string> &names ATTRIBUTE_UNUSED) const
    1123            0 :   {}
    1124              : 
    1125         2756 :   Stmt::Kind get_stmt_kind () final { return Stmt::Kind::Item; }
    1126              : 
    1127              :   // FIXME: ARTHUR: Is it okay to have removed that final? Is it *required*
    1128              :   // behavior that we have items that can also be expressions?
    1129            0 :   bool is_item () const override { return true; }
    1130              : 
    1131              :   virtual std::vector<Attribute> &get_outer_attrs () = 0;
    1132              :   virtual const std::vector<Attribute> &get_outer_attrs () const = 0;
    1133              : 
    1134        58535 :   virtual bool has_outer_attrs () const { return !get_outer_attrs ().empty (); }
    1135              : 
    1136              : protected:
    1137              :   // Clone function implementation as pure virtual method
    1138              :   virtual Item *clone_item_impl () const = 0;
    1139              : 
    1140              :   /* Save having to specify two clone methods in derived classes by making
    1141              :    * statement clone return item clone. Hopefully won't affect performance too
    1142              :    * much. */
    1143         1203 :   Item *clone_stmt_impl () const final override { return clone_item_impl (); }
    1144              : };
    1145              : 
    1146         3828 : class GlobContainer
    1147              : {
    1148              : public:
    1149              :   enum class Kind
    1150              :   {
    1151              :     Crate,
    1152              :     Module,
    1153              :     Enum,
    1154              :   };
    1155              : 
    1156              :   virtual Kind get_glob_container_kind () const = 0;
    1157              : };
    1158              : 
    1159              : // Item that supports visibility - abstract base class
    1160              : class VisItem : public Item
    1161              : {
    1162              :   Visibility visibility;
    1163              :   std::vector<Attribute> outer_attrs;
    1164              : 
    1165              : protected:
    1166              :   // Visibility constructor
    1167        39637 :   VisItem (Visibility visibility,
    1168              :            std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
    1169        39637 :     : visibility (std::move (visibility)), outer_attrs (std::move (outer_attrs))
    1170        39637 :   {}
    1171              : 
    1172              :   // Visibility copy constructor
    1173        57906 :   VisItem (VisItem const &other)
    1174        57906 :     : visibility (other.visibility), outer_attrs (other.outer_attrs)
    1175        57906 :   {}
    1176              : 
    1177              :   // Overload assignment operator to clone
    1178            0 :   VisItem &operator= (VisItem const &other)
    1179              :   {
    1180            0 :     visibility = other.visibility;
    1181            0 :     outer_attrs = other.outer_attrs;
    1182              : 
    1183            0 :     return *this;
    1184              :   }
    1185              : 
    1186              :   // move constructors
    1187          970 :   VisItem (VisItem &&other) = default;
    1188              :   VisItem &operator= (VisItem &&other) = default;
    1189              : 
    1190              : public:
    1191              :   /* Does the item have some kind of public visibility (non-default
    1192              :    * visibility)? */
    1193         1234 :   bool has_visibility () const { return visibility.is_public (); }
    1194              : 
    1195              :   std::string as_string () const override;
    1196              : 
    1197              :   // TODO: this mutable getter seems really dodgy. Think up better way.
    1198       570693 :   Visibility &get_visibility () { return visibility; }
    1199              :   const Visibility &get_visibility () const { return visibility; }
    1200              : 
    1201       971124 :   std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
    1202        78829 :   const std::vector<Attribute> &get_outer_attrs () const override
    1203              :   {
    1204        78829 :     return outer_attrs;
    1205              :   }
    1206              : 
    1207              :   virtual Item::Kind get_item_kind () const override = 0;
    1208              : };
    1209              : 
    1210              : // forward decl of ExprWithoutBlock
    1211              : class ExprWithoutBlock;
    1212              : 
    1213              : // Base expression AST node - abstract
    1214        47911 : class Expr : public Visitable
    1215              : {
    1216              : public:
    1217              :   enum class Kind
    1218              :   {
    1219              :     PathInExpression,
    1220              :     QualifiedPathInExpression,
    1221              :     Literal,
    1222              :     Operator,
    1223              :     Grouped,
    1224              :     Array,
    1225              :     ArrayIndex,
    1226              :     Tuple,
    1227              :     TupleIndex,
    1228              :     Struct,
    1229              :     Call,
    1230              :     MethodCall,
    1231              :     FieldAccess,
    1232              :     Closure,
    1233              :     Block,
    1234              :     ConstExpr,
    1235              :     ConstBlock,
    1236              :     Continue,
    1237              :     Break,
    1238              :     Range,
    1239              :     Box,
    1240              :     Return,
    1241              :     UnsafeBlock,
    1242              :     Loop,
    1243              :     If,
    1244              :     IfLet,
    1245              :     Match,
    1246              :     Await,
    1247              :     AsyncBlock,
    1248              :     InlineAsm,
    1249              :     LlvmInlineAsm,
    1250              :     Identifier,
    1251              :     FormatArgs,
    1252              :     OffsetOf,
    1253              :     MacroInvocation,
    1254              :     Borrow,
    1255              :     Dereference,
    1256              :     ErrorPropagation,
    1257              :     Negation,
    1258              :     ArithmeticOrLogical,
    1259              :     Comparison,
    1260              :     LazyBoolean,
    1261              :     TypeCast,
    1262              :     Assignment,
    1263              :     CompoundAssignment,
    1264              :     Try,
    1265              :   };
    1266              : 
    1267              :   virtual Kind get_expr_kind () const = 0;
    1268              : 
    1269              :   // Unique pointer custom clone function
    1270          122 :   std::unique_ptr<Expr> clone_expr () const
    1271              :   {
    1272       238080 :     return std::unique_ptr<Expr> (clone_expr_impl ());
    1273              :   }
    1274              : 
    1275              :   /* TODO: public methods that could be useful:
    1276              :    *  - get_type() - returns type of expression. set_type() may also be useful
    1277              :    * for some?
    1278              :    *  - evaluate() - evaluates expression if constant? can_evaluate()? */
    1279              : 
    1280              :   virtual std::string as_string () const = 0;
    1281              : 
    1282         2016 :   virtual ~Expr () {}
    1283              : 
    1284              :   virtual location_t get_locus () const = 0;
    1285              : 
    1286           42 :   virtual bool is_literal () const { return false; }
    1287              : 
    1288              :   // HACK: strictly not needed, but faster than full downcast clone
    1289              :   virtual bool is_expr_without_block () const = 0;
    1290              : 
    1291              :   virtual void mark_for_strip () = 0;
    1292              :   virtual bool is_marked_for_strip () const = 0;
    1293              : 
    1294      1547097 :   virtual NodeId get_node_id () const { return node_id; }
    1295              : 
    1296            0 :   virtual void set_node_id (NodeId id) { node_id = id; }
    1297              : 
    1298              :   virtual std::vector<Attribute> &get_outer_attrs () = 0;
    1299              : 
    1300              :   // TODO: think of less hacky way to implement this kind of thing
    1301              :   // Sets outer attributes.
    1302              :   virtual void set_outer_attrs (std::vector<Attribute>) = 0;
    1303              : 
    1304              : protected:
    1305              :   // Constructor
    1306       274089 :   Expr () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
    1307              : 
    1308              :   // Clone function implementation as pure virtual method
    1309              :   virtual Expr *clone_expr_impl () const = 0;
    1310              : 
    1311              :   NodeId node_id;
    1312              : };
    1313              : 
    1314              : // AST node for an expression without an accompanying block - abstract
    1315       250119 : class ExprWithoutBlock : public Expr
    1316              : {
    1317              : protected:
    1318              :   // pure virtual clone implementation
    1319              :   virtual ExprWithoutBlock *clone_expr_without_block_impl () const = 0;
    1320              : 
    1321              :   /* Save having to specify two clone methods in derived classes by making
    1322              :    * expr clone return exprwithoutblock clone. Hopefully won't affect
    1323              :    * performance too much. */
    1324       224638 :   ExprWithoutBlock *clone_expr_impl () const final override
    1325              :   {
    1326       224638 :     return clone_expr_without_block_impl ();
    1327              :   }
    1328              : 
    1329        45184 :   bool is_expr_without_block () const final override { return true; };
    1330              : 
    1331              : public:
    1332              :   // Unique pointer custom clone function
    1333           31 :   std::unique_ptr<ExprWithoutBlock> clone_expr_without_block () const
    1334              :   {
    1335           31 :     return std::unique_ptr<ExprWithoutBlock> (clone_expr_without_block_impl ());
    1336              :   }
    1337              : };
    1338              : 
    1339              : /* HACK: IdentifierExpr, delete when figure out identifier vs expr problem in
    1340              :  * Pratt parser */
    1341              : /* Alternatively, identifiers could just be represented as single-segment
    1342              :  * paths
    1343              :  */
    1344              : class IdentifierExpr : public ExprWithoutBlock
    1345              : {
    1346              :   std::vector<Attribute> outer_attrs;
    1347              :   Identifier ident;
    1348              :   location_t locus;
    1349              : 
    1350              : public:
    1351        25243 :   IdentifierExpr (Identifier ident, std::vector<Attribute> outer_attrs,
    1352              :                   location_t locus)
    1353        75729 :     : outer_attrs (std::move (outer_attrs)), ident (std::move (ident)),
    1354        25243 :       locus (locus)
    1355        25243 :   {}
    1356              : 
    1357           12 :   std::string as_string () const override { return ident.as_string (); }
    1358              : 
    1359        87678 :   location_t get_locus () const override final { return locus; }
    1360              : 
    1361        50533 :   Identifier get_ident () const { return ident; }
    1362              : 
    1363              :   void accept_vis (ASTVisitor &vis) override;
    1364              : 
    1365              :   // Clones this object.
    1366              :   std::unique_ptr<IdentifierExpr> clone_identifier_expr () const
    1367              :   {
    1368              :     return std::unique_ptr<IdentifierExpr> (clone_identifier_expr_impl ());
    1369              :   }
    1370              : 
    1371              :   // "Error state" if ident is empty, so base stripping on this.
    1372            0 :   void mark_for_strip () override { ident = {""}; }
    1373       168066 :   bool is_marked_for_strip () const override { return ident.empty (); }
    1374              : 
    1375              :   const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
    1376       878603 :   std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
    1377              : 
    1378            0 :   void set_outer_attrs (std::vector<Attribute> new_attrs) override
    1379              :   {
    1380            0 :     outer_attrs = std::move (new_attrs);
    1381            0 :   }
    1382              : 
    1383        24337 :   Expr::Kind get_expr_kind () const override { return Expr::Kind::Identifier; }
    1384              : 
    1385              : protected:
    1386              :   // Clone method implementation
    1387        44861 :   IdentifierExpr *clone_expr_without_block_impl () const final override
    1388              :   {
    1389        44861 :     return clone_identifier_expr_impl ();
    1390              :   }
    1391              : 
    1392        44861 :   IdentifierExpr *clone_identifier_expr_impl () const
    1393              :   {
    1394        44861 :     return new IdentifierExpr (*this);
    1395              :   }
    1396              : };
    1397              : 
    1398              : // Pattern base AST node
    1399       158894 : class Pattern : public Visitable
    1400              : {
    1401              : public:
    1402              :   enum class Kind
    1403              :   {
    1404              :     Literal,
    1405              :     Identifier,
    1406              :     Wildcard,
    1407              :     Rest,
    1408              :     Range,
    1409              :     Reference,
    1410              :     Struct,
    1411              :     TupleStruct,
    1412              :     Tuple,
    1413              :     Grouped,
    1414              :     Slice,
    1415              :     Alt,
    1416              :     Path,
    1417              :     MacroInvocation,
    1418              :   };
    1419              : 
    1420              :   // Unique pointer custom clone function
    1421        44130 :   std::unique_ptr<Pattern> clone_pattern () const
    1422              :   {
    1423        44130 :     return std::unique_ptr<Pattern> (clone_pattern_impl ());
    1424              :   }
    1425              : 
    1426              :   virtual Kind get_pattern_kind () = 0;
    1427              : 
    1428              :   // possible virtual methods: is_refutable()
    1429              : 
    1430              :   virtual ~Pattern () {}
    1431              : 
    1432              :   virtual std::string as_string () const = 0;
    1433              : 
    1434              :   // as only one kind of pattern can be stripped, have default of nothing
    1435            0 :   virtual void mark_for_strip () {}
    1436       140509 :   virtual bool is_marked_for_strip () const { return false; }
    1437              : 
    1438              :   virtual location_t get_locus () const = 0;
    1439              :   virtual NodeId get_node_id () const = 0;
    1440              : 
    1441              : protected:
    1442              :   // Clone pattern implementation as pure virtual method
    1443              :   virtual Pattern *clone_pattern_impl () const = 0;
    1444              : };
    1445              : 
    1446              : // forward decl for Type
    1447              : class TraitBound;
    1448              : 
    1449              : // Base class for types as represented in AST - abstract
    1450       163975 : class Type : public Visitable
    1451              : {
    1452              : public:
    1453              :   enum Kind
    1454              :   {
    1455              :     MacroInvocation,
    1456              :     TypePath,
    1457              :     QualifiedPathInType,
    1458              :     ImplTrait,
    1459              :     TraitObject,
    1460              :     Parenthesised,
    1461              :     ImplTraitTypeOneBound,
    1462              :     TraitObjectTypeOneBound,
    1463              :     Tuple,
    1464              :     Never,
    1465              :     RawPointer,
    1466              :     Reference,
    1467              :     Array,
    1468              :     Slice,
    1469              :     Inferred,
    1470              :     BareFunction,
    1471              :   };
    1472              : 
    1473              :   virtual Kind get_type_kind () const = 0;
    1474              : 
    1475              :   // Unique pointer custom clone function
    1476        80912 :   std::unique_ptr<Type> clone_type () const
    1477              :   {
    1478        80912 :     return std::unique_ptr<Type> (clone_type_impl ());
    1479              :   }
    1480              : 
    1481              :   // Similar to `clone_type`, but generates a new instance of the node with a
    1482              :   // different NodeId
    1483           95 :   std::unique_ptr<Type> reconstruct () const { return reconstruct_base (this); }
    1484              : 
    1485              :   // virtual destructor
    1486        66330 :   virtual ~Type () {}
    1487              : 
    1488              :   virtual std::string as_string () const = 0;
    1489              : 
    1490              :   /* HACK: convert to trait bound. Virtual method overriden by classes that
    1491              :    * enable this. */
    1492            4 :   virtual TraitBound *to_trait_bound (bool) const { return nullptr; }
    1493              :   /* as pointer, shouldn't require definition beforehand, only forward
    1494              :    * declaration. */
    1495              : 
    1496              :   // as only two kinds of types can be stripped, have default of nothing
    1497            0 :   virtual void mark_for_strip () {}
    1498        76505 :   virtual bool is_marked_for_strip () const { return false; }
    1499              : 
    1500              :   virtual location_t get_locus () const = 0;
    1501              : 
    1502              :   // TODO: put this in a virtual base class?
    1503        47474 :   virtual NodeId get_node_id () const { return node_id; }
    1504              :   virtual Type *reconstruct_impl () const = 0;
    1505              : 
    1506              : protected:
    1507       106616 :   Type () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
    1508           13 :   Type (NodeId node_id) : node_id (node_id) {}
    1509              : 
    1510              :   // Clone and reconstruct function implementations as pure virtual methods
    1511              :   virtual Type *clone_type_impl () const = 0;
    1512              : 
    1513              :   NodeId node_id;
    1514              : };
    1515              : 
    1516              : // A type without parentheses? - abstract
    1517       224588 : class TypeNoBounds : public Type
    1518              : {
    1519              : public:
    1520              :   // Unique pointer custom clone function
    1521        22930 :   std::unique_ptr<TypeNoBounds> clone_type_no_bounds () const
    1522              :   {
    1523        22930 :     return std::unique_ptr<TypeNoBounds> (clone_type_no_bounds_impl ());
    1524              :   }
    1525              : 
    1526            0 :   std::unique_ptr<TypeNoBounds> reconstruct () const
    1527              :   {
    1528            0 :     return reconstruct_base (this);
    1529              :   }
    1530              : 
    1531              :   virtual TypeNoBounds *reconstruct_impl () const override = 0;
    1532              : 
    1533              : protected:
    1534              :   // Clone function implementation as pure virtual method
    1535              :   virtual TypeNoBounds *clone_type_no_bounds_impl () const = 0;
    1536              : 
    1537              :   /* Save having to specify two clone methods in derived classes by making
    1538              :    * type clone return typenobounds clone. Hopefully won't affect performance
    1539              :    * too much. */
    1540        80899 :   TypeNoBounds *clone_type_impl () const final override
    1541              :   {
    1542        80899 :     return clone_type_no_bounds_impl ();
    1543              :   }
    1544              : 
    1545       106602 :   TypeNoBounds () : Type () {}
    1546              : };
    1547              : 
    1548              : /* Abstract base class representing a type param bound - Lifetime and
    1549              :  * TraitBound extends it */
    1550              : class TypeParamBound : public Visitable
    1551              : {
    1552              : public:
    1553              :   enum TypeParamBoundType
    1554              :   {
    1555              :     TRAIT,
    1556              :     LIFETIME
    1557              :   };
    1558              : 
    1559        10810 :   virtual ~TypeParamBound () {}
    1560              : 
    1561              :   // Unique pointer custom clone function
    1562         1819 :   std::unique_ptr<TypeParamBound> clone_type_param_bound () const
    1563              :   {
    1564         1819 :     return std::unique_ptr<TypeParamBound> (clone_type_param_bound_impl ());
    1565              :   }
    1566              : 
    1567            0 :   std::unique_ptr<TypeParamBound> reconstruct () const
    1568              :   {
    1569            0 :     return reconstruct_base (this);
    1570              :   }
    1571              : 
    1572              :   virtual std::string as_string () const = 0;
    1573              : 
    1574        11435 :   NodeId get_node_id () const { return node_id; }
    1575              : 
    1576              :   virtual location_t get_locus () const = 0;
    1577              : 
    1578              :   virtual TypeParamBoundType get_bound_type () const = 0;
    1579              : 
    1580              :   virtual TypeParamBound *reconstruct_impl () const = 0;
    1581              : 
    1582              : protected:
    1583              :   // Clone function implementation as pure virtual method
    1584              :   virtual TypeParamBound *clone_type_param_bound_impl () const = 0;
    1585              : 
    1586              :   TypeParamBound () : node_id (Analysis::Mappings::get ().get_next_node_id ())
    1587              :   {}
    1588          645 :   TypeParamBound (NodeId node_id) : node_id (node_id) {}
    1589              : 
    1590              :   NodeId node_id;
    1591              : };
    1592              : 
    1593              : // Represents a lifetime (and is also a kind of type param bound)
    1594        34450 : class Lifetime : public TypeParamBound
    1595              : {
    1596              : public:
    1597              :   enum LifetimeType
    1598              :   {
    1599              :     NAMED,   // corresponds to LIFETIME_OR_LABEL
    1600              :     STATIC,  // corresponds to 'static
    1601              :     WILDCARD // corresponds to '_
    1602              :   };
    1603              : 
    1604              : private:
    1605              :   LifetimeType lifetime_type;
    1606              :   std::string lifetime_name;
    1607              :   location_t locus;
    1608              :   NodeId node_id;
    1609              : 
    1610              : public:
    1611              :   // Constructor
    1612        23521 :   Lifetime (LifetimeType type, std::string name = std::string (),
    1613              :             location_t locus = UNDEF_LOCATION)
    1614        23521 :     : TypeParamBound (Analysis::Mappings::get ().get_next_node_id ()),
    1615        23521 :       lifetime_type (type), lifetime_name (std::move (name)), locus (locus)
    1616        23521 :   {}
    1617              : 
    1618           12 :   Lifetime (NodeId id, LifetimeType type, std::string name = std::string (),
    1619              :             location_t locus = UNDEF_LOCATION)
    1620           12 :     : TypeParamBound (id), lifetime_type (type),
    1621           24 :       lifetime_name (std::move (name)), locus (locus)
    1622              :   {}
    1623              : 
    1624        22646 :   static Lifetime elided () { return Lifetime (WILDCARD, ""); }
    1625              : 
    1626              :   // Returns true if the lifetime is in an error state.
    1627              :   std::string as_string () const override;
    1628              : 
    1629              :   void accept_vis (ASTVisitor &vis) override;
    1630              : 
    1631        10399 :   LifetimeType get_lifetime_type () const { return lifetime_type; }
    1632              : 
    1633        10477 :   location_t get_locus () const override final { return locus; }
    1634              : 
    1635        30372 :   std::string get_lifetime_name () const { return lifetime_name; }
    1636              : 
    1637            0 :   TypeParamBoundType get_bound_type () const override
    1638              :   {
    1639            0 :     return TypeParamBound::TypeParamBoundType::LIFETIME;
    1640              :   }
    1641              : 
    1642              : protected:
    1643              :   /* Use covariance to implement clone function as returning this object
    1644              :    * rather than base */
    1645           12 :   Lifetime *clone_type_param_bound_impl () const override
    1646              :   {
    1647           24 :     return new Lifetime (node_id, lifetime_type, lifetime_name, locus);
    1648              :   }
    1649            0 :   Lifetime *reconstruct_impl () const override
    1650              :   {
    1651            0 :     return new Lifetime (lifetime_type, lifetime_name, locus);
    1652              :   }
    1653              : };
    1654              : 
    1655              : /* Base generic parameter in AST. Abstract - can be represented by a Lifetime
    1656              :  * or Type param */
    1657              : class GenericParam : public Visitable
    1658              : {
    1659              : public:
    1660              :   enum class Kind
    1661              :   {
    1662              :     Lifetime,
    1663              :     Type,
    1664              :     Const,
    1665              :   };
    1666              : 
    1667              :   virtual ~GenericParam () {}
    1668              : 
    1669              :   // Unique pointer custom clone function
    1670         5064 :   std::unique_ptr<GenericParam> clone_generic_param () const
    1671              :   {
    1672         5064 :     return std::unique_ptr<GenericParam> (clone_generic_param_impl ());
    1673              :   }
    1674              : 
    1675              :   virtual std::string as_string () const = 0;
    1676              : 
    1677              :   virtual location_t get_locus () const = 0;
    1678              : 
    1679              :   virtual Kind get_kind () const = 0;
    1680              : 
    1681        95450 :   NodeId get_node_id () const { return node_id; }
    1682              : 
    1683              : protected:
    1684          479 :   GenericParam () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
    1685        16342 :   GenericParam (NodeId node_id) : node_id (node_id) {}
    1686              : 
    1687              :   // Clone function implementation as pure virtual method
    1688              :   virtual GenericParam *clone_generic_param_impl () const = 0;
    1689              : 
    1690              :   NodeId node_id;
    1691              : };
    1692              : 
    1693              : // A lifetime generic parameter (as opposed to a type generic parameter)
    1694              : class LifetimeParam : public GenericParam
    1695              : {
    1696              :   Lifetime lifetime;
    1697              :   std::vector<Lifetime> lifetime_bounds;
    1698              :   AST::AttrVec outer_attrs;
    1699              :   location_t locus;
    1700              : 
    1701              : public:
    1702            0 :   Lifetime get_lifetime () const { return lifetime; }
    1703              : 
    1704         3471 :   Lifetime &get_lifetime () { return lifetime; }
    1705              : 
    1706         4022 :   AST::AttrVec &get_outer_attrs () { return outer_attrs; }
    1707              : 
    1708              :   // Returns whether the lifetime param has any lifetime bounds.
    1709           21 :   bool has_lifetime_bounds () const { return !lifetime_bounds.empty (); }
    1710              : 
    1711         3243 :   std::vector<Lifetime> &get_lifetime_bounds () { return lifetime_bounds; }
    1712              : 
    1713              :   const std::vector<Lifetime> &get_lifetime_bounds () const
    1714              :   {
    1715            0 :     return lifetime_bounds;
    1716              :   }
    1717              : 
    1718              :   // Returns whether the lifetime param has an outer attribute.
    1719            0 :   bool has_outer_attribute () const { return !outer_attrs.empty (); }
    1720              : 
    1721              :   // Constructor
    1722          281 :   LifetimeParam (Lifetime lifetime, std::vector<Lifetime> lifetime_bounds,
    1723              :                  AST::AttrVec outer_attrs, location_t locus)
    1724          562 :     : lifetime (std::move (lifetime)),
    1725          281 :       lifetime_bounds (std::move (lifetime_bounds)),
    1726          281 :       outer_attrs (std::move (outer_attrs)), locus (locus)
    1727          281 :   {}
    1728              : 
    1729              :   std::string as_string () const override;
    1730              : 
    1731              :   void accept_vis (ASTVisitor &vis) override;
    1732              : 
    1733          414 :   location_t get_locus () const override final { return locus; }
    1734              : 
    1735          757 :   Kind get_kind () const override final { return Kind::Lifetime; }
    1736              : 
    1737              : protected:
    1738              :   /* Use covariance to implement clone function as returning this object
    1739              :    * rather than base */
    1740          581 :   LifetimeParam *clone_generic_param_impl () const override
    1741              :   {
    1742          581 :     return new LifetimeParam (*this);
    1743              :   }
    1744              : };
    1745              : 
    1746        33608 : class AssociatedItem : public Visitable
    1747              : {
    1748              : protected:
    1749              :   // Clone function implementation as pure virtual method
    1750              :   virtual AssociatedItem *clone_associated_item_impl () const = 0;
    1751              : 
    1752              : public:
    1753              :   virtual ~AssociatedItem () {}
    1754              : 
    1755        23210 :   std::unique_ptr<AssociatedItem> clone_associated_item () const
    1756              :   {
    1757        23210 :     return std::unique_ptr<AssociatedItem> (clone_associated_item_impl ());
    1758              :   }
    1759              : 
    1760              :   virtual std::string as_string () const = 0;
    1761              : 
    1762              :   virtual void mark_for_strip () = 0;
    1763              :   virtual bool is_marked_for_strip () const = 0;
    1764              : 
    1765              :   virtual location_t get_locus () const = 0;
    1766              : 
    1767              :   virtual NodeId get_node_id () const = 0;
    1768              : };
    1769              : 
    1770              : // Item used in trait declarations - abstract base class
    1771              : class TraitItem : public AssociatedItem
    1772              : {
    1773              : protected:
    1774        15659 :   TraitItem (location_t locus)
    1775        15659 :     : node_id (Analysis::Mappings::get ().get_next_node_id ()),
    1776        31318 :       vis (Visibility::create_private ()), locus (locus)
    1777        15659 :   {}
    1778              : 
    1779          748 :   TraitItem (Visibility vis, location_t locus)
    1780          748 :     : node_id (Analysis::Mappings::get ().get_next_node_id ()), vis (vis),
    1781          748 :       locus (locus)
    1782          748 :   {}
    1783              : 
    1784              :   // Clone function implementation as pure virtual method
    1785              :   virtual TraitItem *clone_associated_item_impl () const override = 0;
    1786              : 
    1787              :   NodeId node_id;
    1788              :   Visibility vis;
    1789              :   location_t locus;
    1790              : 
    1791              : public:
    1792              :   // Unique pointer custom clone function
    1793              :   std::unique_ptr<TraitItem> clone_trait_item () const
    1794              :   {
    1795              :     return std::unique_ptr<TraitItem> (clone_associated_item_impl ());
    1796              :   }
    1797              : 
    1798         5307 :   NodeId get_node_id () const override { return node_id; }
    1799         3776 :   location_t get_locus () const override { return locus; }
    1800              : };
    1801              : 
    1802              : // Abstract base class for an item used inside an extern block
    1803              : class ExternalItem : public Visitable
    1804              : {
    1805              : public:
    1806         3008 :   ExternalItem () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {}
    1807              : 
    1808        58334 :   ExternalItem (NodeId node_id) : node_id (node_id) {}
    1809              : 
    1810              :   virtual ~ExternalItem () {}
    1811              : 
    1812              :   // Unique pointer custom clone function
    1813         2276 :   std::unique_ptr<ExternalItem> clone_external_item () const
    1814              :   {
    1815         2276 :     return std::unique_ptr<ExternalItem> (clone_external_item_impl ());
    1816              :   }
    1817              : 
    1818              :   virtual std::string as_string () const = 0;
    1819              : 
    1820              :   virtual void mark_for_strip () = 0;
    1821              :   virtual bool is_marked_for_strip () const = 0;
    1822              : 
    1823           10 :   virtual NodeId get_node_id () const { return node_id; }
    1824              : 
    1825              : protected:
    1826              :   // Clone function implementation as pure virtual method
    1827              :   virtual ExternalItem *clone_external_item_impl () const = 0;
    1828              : 
    1829              :   NodeId node_id;
    1830              : };
    1831              : 
    1832              : /* Data structure to store the data used in macro invocations and macro
    1833              :  * invocations with semicolons. */
    1834              : struct MacroInvocData
    1835              : {
    1836              : private:
    1837              :   SimplePath path;
    1838              :   DelimTokenTree token_tree;
    1839              : 
    1840              :   // One way of parsing the macro. Probably not applicable for all macros.
    1841              :   std::vector<std::unique_ptr<MetaItemInner>> parsed_items;
    1842              :   bool parsed_to_meta_item = false;
    1843              :   MacroExpander *expander = nullptr;
    1844              : 
    1845              : public:
    1846              :   std::string as_string () const;
    1847              : 
    1848         3004 :   MacroInvocData (SimplePath path, DelimTokenTree token_tree)
    1849         3004 :     : path (std::move (path)), token_tree (std::move (token_tree))
    1850         3004 :   {}
    1851              : 
    1852              :   // Copy constructor with vector clone
    1853        14907 :   MacroInvocData (const MacroInvocData &other)
    1854        14907 :     : path (other.path), token_tree (other.token_tree),
    1855        14907 :       parsed_to_meta_item (other.parsed_to_meta_item)
    1856              :   {
    1857        14907 :     parsed_items.reserve (other.parsed_items.size ());
    1858        14907 :     for (const auto &e : other.parsed_items)
    1859            0 :       parsed_items.push_back (e->clone_meta_item_inner ());
    1860        14907 :   }
    1861              : 
    1862              :   // Copy assignment operator with vector clone
    1863              :   MacroInvocData &operator= (const MacroInvocData &other)
    1864              :   {
    1865              :     path = other.path;
    1866              :     token_tree = other.token_tree;
    1867              :     parsed_to_meta_item = other.parsed_to_meta_item;
    1868              :     expander = other.expander;
    1869              : 
    1870              :     parsed_items.reserve (other.parsed_items.size ());
    1871              :     for (const auto &e : other.parsed_items)
    1872              :       parsed_items.push_back (e->clone_meta_item_inner ());
    1873              : 
    1874              :     return *this;
    1875              :   }
    1876              : 
    1877              :   // Move constructors
    1878         3387 :   MacroInvocData (MacroInvocData &&other) = default;
    1879              :   MacroInvocData &operator= (MacroInvocData &&other) = default;
    1880              : 
    1881              :   // Invalid if path is empty, so base stripping on that.
    1882            0 :   void mark_for_strip () { path = SimplePath::create_empty (); }
    1883         6361 :   bool is_marked_for_strip () const { return path.is_empty (); }
    1884              : 
    1885              :   // Returns whether the macro has been parsed already.
    1886           47 :   bool is_parsed () const { return parsed_to_meta_item; }
    1887              :   // TODO: update on other ways of parsing it
    1888              : 
    1889              :   // TODO: this mutable getter seems kinda dodgy
    1890         5761 :   DelimTokenTree &get_delim_tok_tree () { return token_tree; }
    1891              :   const DelimTokenTree &get_delim_tok_tree () const { return token_tree; }
    1892              : 
    1893              :   // Set the delim token tree of a macro invocation
    1894           43 :   void set_delim_tok_tree (DelimTokenTree tree) { token_tree = tree; }
    1895              : 
    1896              :   // TODO: this mutable getter seems kinda dodgy
    1897         5797 :   SimplePath &get_path () { return path; }
    1898              :   const SimplePath &get_path () const { return path; }
    1899              : 
    1900         2839 :   void set_expander (MacroExpander *new_expander) { expander = new_expander; }
    1901          219 :   MacroExpander *get_expander ()
    1902              :   {
    1903          219 :     rust_assert (expander);
    1904          219 :     return expander;
    1905              :   }
    1906              : 
    1907              :   void
    1908           47 :   set_meta_item_output (std::vector<std::unique_ptr<MetaItemInner>> new_items)
    1909              :   {
    1910           47 :     parsed_items = std::move (new_items);
    1911              :   }
    1912              :   std::vector<std::unique_ptr<MetaItemInner>> &get_meta_items ()
    1913              :   {
    1914              :     return parsed_items;
    1915              :   }
    1916              :   const std::vector<std::unique_ptr<MetaItemInner>> &get_meta_items () const
    1917              :   {
    1918              :     return parsed_items;
    1919              :   }
    1920              : };
    1921              : 
    1922              : class SingleASTNode : public Visitable
    1923              : {
    1924              : public:
    1925              :   enum class Kind
    1926              :   {
    1927              :     Expr,
    1928              :     Item,
    1929              :     Stmt,
    1930              :     Extern,
    1931              :     Assoc,
    1932              :     Type,
    1933              :     Pattern,
    1934              :   };
    1935              : 
    1936              : private:
    1937              :   Kind kind;
    1938              : 
    1939              :   // FIXME make this a union
    1940              :   std::unique_ptr<Expr> expr;
    1941              :   std::unique_ptr<Item> item;
    1942              :   std::unique_ptr<Stmt> stmt;
    1943              :   std::unique_ptr<ExternalItem> external_item;
    1944              :   std::unique_ptr<AssociatedItem> assoc_item;
    1945              :   std::unique_ptr<Type> type;
    1946              :   std::unique_ptr<Pattern> pattern;
    1947              : 
    1948              : public:
    1949         1959 :   SingleASTNode (std::unique_ptr<Expr> expr)
    1950         1959 :     : kind (Kind::Expr), expr (std::move (expr))
    1951              :   {}
    1952              : 
    1953         2592 :   SingleASTNode (std::unique_ptr<Item> item)
    1954         2592 :     : kind (Kind::Item), item (std::move (item))
    1955              :   {}
    1956              : 
    1957          469 :   SingleASTNode (std::unique_ptr<Stmt> stmt)
    1958          469 :     : kind (Kind::Stmt), stmt (std::move (stmt))
    1959              :   {}
    1960              : 
    1961            3 :   SingleASTNode (std::unique_ptr<ExternalItem> item)
    1962            3 :     : kind (Kind::Extern), external_item (std::move (item))
    1963              :   {}
    1964              : 
    1965          107 :   SingleASTNode (std::unique_ptr<AssociatedItem> item)
    1966          107 :     : kind (Kind::Assoc), assoc_item (std::move (item))
    1967              :   {}
    1968              : 
    1969           29 :   SingleASTNode (std::unique_ptr<Type> type)
    1970           29 :     : kind (Kind::Type), type (std::move (type))
    1971              :   {}
    1972              : 
    1973            1 :   SingleASTNode (std::unique_ptr<Pattern> pattern)
    1974            1 :     : kind (Kind::Pattern), pattern (std::move (pattern))
    1975              :   {}
    1976              : 
    1977              :   SingleASTNode (SingleASTNode const &other);
    1978              : 
    1979              :   SingleASTNode operator= (SingleASTNode const &other);
    1980              : 
    1981         6101 :   SingleASTNode (SingleASTNode &&other) = default;
    1982              :   SingleASTNode &operator= (SingleASTNode &&other) = default;
    1983              : 
    1984         3844 :   Kind get_kind () const { return kind; }
    1985              : 
    1986              :   std::unique_ptr<Expr> &get_expr ()
    1987              :   {
    1988              :     rust_assert (kind == Kind::Expr);
    1989              :     return expr;
    1990              :   }
    1991              : 
    1992            0 :   std::unique_ptr<Item> &get_item ()
    1993              :   {
    1994            0 :     rust_assert (kind == Kind::Item);
    1995            0 :     return item;
    1996              :   }
    1997              : 
    1998              :   std::unique_ptr<Stmt> &get_stmt ()
    1999              :   {
    2000              :     rust_assert (kind == Kind::Stmt);
    2001              :     return stmt;
    2002              :   }
    2003              : 
    2004              :   /**
    2005              :    * Access the inner nodes and take ownership of them.
    2006              :    * You can only call these functions once per node
    2007              :    */
    2008              : 
    2009          482 :   std::unique_ptr<Stmt> take_stmt ()
    2010              :   {
    2011          482 :     rust_assert (!is_error ());
    2012          482 :     return std::move (stmt);
    2013              :   }
    2014              : 
    2015         1892 :   std::unique_ptr<Expr> take_expr ()
    2016              :   {
    2017         1892 :     rust_assert (!is_error ());
    2018         1892 :     return std::move (expr);
    2019              :   }
    2020              : 
    2021         2591 :   std::unique_ptr<Item> take_item ()
    2022              :   {
    2023         2591 :     rust_assert (!is_error ());
    2024         2591 :     return std::move (item);
    2025              :   }
    2026              : 
    2027            3 :   std::unique_ptr<ExternalItem> take_external_item ()
    2028              :   {
    2029            3 :     rust_assert (!is_error ());
    2030            3 :     return std::move (external_item);
    2031              :   }
    2032              : 
    2033          107 :   std::unique_ptr<AssociatedItem> take_assoc_item ()
    2034              :   {
    2035          107 :     rust_assert (!is_error ());
    2036          107 :     return std::move (assoc_item);
    2037              :   }
    2038              : 
    2039           29 :   std::unique_ptr<Type> take_type ()
    2040              :   {
    2041           29 :     rust_assert (!is_error ());
    2042           29 :     return std::move (type);
    2043              :   }
    2044              : 
    2045            1 :   std::unique_ptr<Pattern> take_pattern ()
    2046              :   {
    2047            1 :     rust_assert (!is_error ());
    2048            1 :     return std::move (pattern);
    2049              :   }
    2050              : 
    2051              :   void accept_vis (ASTVisitor &vis) override;
    2052              : 
    2053              :   bool is_error ();
    2054              : 
    2055              :   std::string as_string () const;
    2056              : };
    2057              : 
    2058              : // A crate AST object - holds all the data for a single compilation unit
    2059              : struct Crate final : public GlobContainer
    2060              : {
    2061              :   std::vector<Attribute> inner_attrs;
    2062              :   // dodgy spacing required here
    2063              :   /* TODO: is it better to have a vector of items here or a module (implicit
    2064              :    * top-level one)? */
    2065              :   std::vector<std::unique_ptr<Item>> items;
    2066              : 
    2067              :   NodeId node_id;
    2068              : 
    2069              : public:
    2070              :   // Constructor
    2071         4658 :   Crate (std::vector<std::unique_ptr<Item>> items,
    2072              :          std::vector<Attribute> inner_attrs)
    2073         4658 :     : inner_attrs (std::move (inner_attrs)), items (std::move (items)),
    2074         4658 :       node_id (Analysis::Mappings::get ().get_next_node_id ())
    2075         4658 :   {}
    2076              : 
    2077              :   // Copy constructor with vector clone
    2078         4526 :   Crate (Crate const &other)
    2079         4526 :     : inner_attrs (other.inner_attrs), node_id (other.node_id)
    2080              :   {
    2081         4526 :     items.reserve (other.items.size ());
    2082        23199 :     for (const auto &e : other.items)
    2083        18673 :       items.push_back (e->clone_item ());
    2084         4526 :   }
    2085              : 
    2086         4624 :   ~Crate () = default;
    2087              : 
    2088              :   // Overloaded assignment operator with vector clone
    2089              :   Crate &operator= (Crate const &other)
    2090              :   {
    2091              :     inner_attrs = other.inner_attrs;
    2092              :     node_id = other.node_id;
    2093              : 
    2094              :     items.reserve (other.items.size ());
    2095              :     for (const auto &e : other.items)
    2096              :       items.push_back (e->clone_item ());
    2097              : 
    2098              :     return *this;
    2099              :   }
    2100              : 
    2101              :   // Move constructors
    2102              :   Crate (Crate &&other) = default;
    2103              :   Crate &operator= (Crate &&other) = default;
    2104              : 
    2105              :   // Get crate representation as string (e.g. for debugging).
    2106              :   std::string as_string () const;
    2107              : 
    2108              :   // Delete all crate information, e.g. if fails cfg.
    2109            1 :   void strip_crate ()
    2110              :   {
    2111            1 :     inner_attrs.clear ();
    2112            1 :     inner_attrs.shrink_to_fit ();
    2113              : 
    2114            1 :     items.clear ();
    2115            1 :     items.shrink_to_fit ();
    2116              :     // TODO: is this the best way to do this?
    2117            1 :   }
    2118              : 
    2119              :   void inject_extern_crate (std::string name);
    2120              : 
    2121       106352 :   NodeId get_node_id () const { return node_id; }
    2122              :   const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
    2123        75966 :   std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
    2124              : 
    2125              :   std::vector<std::unique_ptr<AST::Item>> take_items ()
    2126              :   {
    2127              :     return std::move (items);
    2128              :   }
    2129              : 
    2130              :   void set_items (std::vector<std::unique_ptr<AST::Item>> &&new_items)
    2131              :   {
    2132              :     items = std::move (new_items);
    2133              :   }
    2134              : 
    2135         4510 :   GlobContainer::Kind get_glob_container_kind () const override
    2136              :   {
    2137         4510 :     return GlobContainer::Kind::Crate;
    2138              :   }
    2139              : };
    2140              : 
    2141              : } // namespace AST
    2142              : } // namespace Rust
    2143              : 
    2144              : namespace std {
    2145              : template <> struct less<Rust::Identifier>
    2146              : {
    2147              :   bool operator() (const Rust::Identifier &lhs,
    2148              :                    const Rust::Identifier &rhs) const
    2149              :   {
    2150              :     return lhs.as_string () < rhs.as_string ();
    2151              :   }
    2152              : };
    2153              : 
    2154              : template <> struct hash<Rust::Identifier>
    2155              : {
    2156              :   std::size_t operator() (const Rust::Identifier &k) const
    2157              :   {
    2158              :     using std::hash;
    2159              :     using std::size_t;
    2160              :     using std::string;
    2161              : 
    2162              :     return hash<string> () (k.as_string ()) ^ (hash<int> () (k.get_locus ()));
    2163              :   }
    2164              : };
    2165              : 
    2166              : } // namespace std
    2167              : 
    2168              : #endif
        

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.