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

Generated by: LCOV version 2.4-beta

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