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

Generated by: LCOV version 2.5.0-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.