(root)/
gcc-13.2.0/
gcc/
rust/
ast/
rust-ast.h
       1  // Copyright (C) 2020-2023 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  
      29  namespace Rust {
      30  // TODO: remove typedefs and make actual types for these
      31  typedef std::string Identifier;
      32  typedef int TupleIndex;
      33  struct Session;
      34  struct MacroExpander;
      35  
      36  namespace AST {
      37  // foward decl: ast visitor
      38  class ASTVisitor;
      39  using AttrVec = std::vector<Attribute>;
      40  
      41  // The available kinds of AST Nodes
      42  enum Kind
      43  {
      44    UNKNOWN,
      45    MACRO_RULES_DEFINITION,
      46    MACRO_INVOCATION,
      47  };
      48  
      49  // Abstract base class for all AST elements
      50  class Node
      51  {
      52  public:
      53    /**
      54     * Get the kind of Node this is. This is used to differentiate various AST
      55     * elements with very little overhead when extracting the derived type through
      56     * static casting is not necessary.
      57     */
      58    // FIXME: Mark this as `= 0` in the future to make sure every node implements
      59    // it
      60    virtual Kind get_ast_kind () const { return Kind::UNKNOWN; }
      61  };
      62  
      63  // Delimiter types - used in macros and whatever.
      64  enum DelimType
      65  {
      66    PARENS,
      67    SQUARE,
      68    CURLY
      69  };
      70  
      71  // forward decl for use in token tree method
      72  class Token;
      73  
      74  // A tree of tokens (or a single token) - abstract base class
      75  class TokenTree
      76  {
      77  public:
      78    virtual ~TokenTree () {}
      79  
      80    // Unique pointer custom clone function
      81    std::unique_ptr<TokenTree> clone_token_tree () const
      82    {
      83      return std::unique_ptr<TokenTree> (clone_token_tree_impl ());
      84    }
      85  
      86    virtual std::string as_string () const = 0;
      87  
      88    virtual void accept_vis (ASTVisitor &vis) = 0;
      89  
      90    /* Converts token tree to a flat token stream. Tokens must be pointer to avoid
      91     * mutual dependency with Token. */
      92    virtual std::vector<std::unique_ptr<Token> > to_token_stream () const = 0;
      93  
      94  protected:
      95    // pure virtual clone implementation
      96    virtual TokenTree *clone_token_tree_impl () const = 0;
      97  };
      98  
      99  // Abstract base class for a macro match
     100  class MacroMatch
     101  {
     102  public:
     103    enum MacroMatchType
     104    {
     105      Fragment,
     106      Repetition,
     107      Matcher,
     108      Tok
     109    };
     110  
     111    virtual ~MacroMatch () {}
     112  
     113    virtual std::string as_string () const = 0;
     114    virtual Location get_match_locus () const = 0;
     115  
     116    // Unique pointer custom clone function
     117    std::unique_ptr<MacroMatch> clone_macro_match () const
     118    {
     119      return std::unique_ptr<MacroMatch> (clone_macro_match_impl ());
     120    }
     121  
     122    virtual void accept_vis (ASTVisitor &vis) = 0;
     123  
     124    virtual MacroMatchType get_macro_match_type () const = 0;
     125  
     126  protected:
     127    // pure virtual clone implementation
     128    virtual MacroMatch *clone_macro_match_impl () const = 0;
     129  };
     130  
     131  // A token is a kind of token tree (except delimiter tokens)
     132  class Token : public TokenTree, public MacroMatch
     133  {
     134    // A token is a kind of token tree (except delimiter tokens)
     135    // A token is a kind of MacroMatch (except $ and delimiter tokens)
     136  #if 0
     137    // TODO: improve member variables - current ones are the same as lexer token
     138    // Token kind.
     139    TokenId token_id;
     140    // Token location.
     141    Location locus;
     142    // Associated text (if any) of token.
     143    std::string str;
     144    // Token type hint (if any).
     145    PrimitiveCoreType type_hint;
     146  #endif
     147  
     148    const_TokenPtr tok_ref;
     149  
     150    /* new idea: wrapper around const_TokenPtr used for heterogeneuous storage in
     151     * token trees. rather than convert back and forth when parsing macros, just
     152     * wrap it. */
     153  
     154  public:
     155    // Unique pointer custom clone function
     156    std::unique_ptr<Token> clone_token () const
     157    {
     158      return std::unique_ptr<Token> (clone_token_impl ());
     159    }
     160  
     161  #if 0
     162    /* constructor from general text - avoid using if lexer const_TokenPtr is
     163     * available */
     164    Token (TokenId token_id, Location locus, std::string str,
     165  	 PrimitiveCoreType type_hint)
     166      : token_id (token_id), locus (locus), str (std::move (str)),
     167        type_hint (type_hint)
     168    {}
     169  #endif
     170    // not doable with new implementation - will have to make a const_TokenPtr
     171  
     172    // Constructor from lexer const_TokenPtr
     173  #if 0
     174    /* TODO: find workaround for std::string being nullptr - probably have to
     175     * introduce new method in lexer Token, or maybe make conversion method
     176     * there */
     177    Token (const_TokenPtr lexer_token_ptr)
     178      : token_id (lexer_token_ptr->get_id ()),
     179        locus (lexer_token_ptr->get_locus ()), str (""),
     180        type_hint (lexer_token_ptr->get_type_hint ())
     181    {
     182      // FIXME: change to "should have str" later?
     183      if (lexer_token_ptr->has_str ())
     184        {
     185  	str = lexer_token_ptr->get_str ();
     186  
     187  	// DEBUG
     188  	rust_debug ("ast token created with str '%s'", str.c_str ());
     189        }
     190      else
     191        {
     192  	// FIXME: is this returning correct thing?
     193  	str = lexer_token_ptr->get_token_description ();
     194  
     195  	// DEBUG
     196  	rust_debug ("ast token created with string '%s'", str.c_str ());
     197        }
     198  
     199      // DEBUG
     200      if (lexer_token_ptr->should_have_str () && !lexer_token_ptr->has_str ())
     201        {
     202  	rust_debug (
     203  		 "BAD: for token '%s', should have string but does not!",
     204  		 lexer_token_ptr->get_token_description ());
     205        }
     206    }
     207  #endif
     208    Token (const_TokenPtr lexer_tok_ptr) : tok_ref (std::move (lexer_tok_ptr)) {}
     209  
     210    bool is_string_lit () const
     211    {
     212      switch (get_id ())
     213        {
     214        case STRING_LITERAL:
     215        case BYTE_STRING_LITERAL:
     216  	return true;
     217        default:
     218  	return false;
     219        }
     220    }
     221  
     222    std::string as_string () const override;
     223    Location get_match_locus () const override { return tok_ref->get_locus (); };
     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    TokenId get_id () const { return tok_ref->get_id (); }
     231    const std::string &get_str () const { return tok_ref->get_str (); }
     232  
     233    Location get_locus () const { return tok_ref->get_locus (); }
     234  
     235    PrimitiveCoreType get_type_hint () const { return tok_ref->get_type_hint (); }
     236  
     237    // Get a new token pointer copy.
     238    const_TokenPtr get_tok_ptr () const { return tok_ref; }
     239  
     240    MacroMatchType get_macro_match_type () const override
     241    {
     242      return MacroMatchType::Tok;
     243    }
     244  
     245  protected:
     246    // No virtual for now as not polymorphic but can be in future
     247    /*virtual*/ Token *clone_token_impl () const { return new Token (*this); }
     248  
     249    /* Use covariance to implement clone function as returning this object rather
     250     * than base */
     251    Token *clone_token_tree_impl () const final override
     252    {
     253      return clone_token_impl ();
     254    }
     255  
     256    /* Use covariance to implement clone function as returning this object rather
     257     * than base */
     258    Token *clone_macro_match_impl () const final override
     259    {
     260      return clone_token_impl ();
     261    }
     262  };
     263  
     264  // A literal - value with a type. Used in LiteralExpr and LiteralPattern.
     265  struct Literal
     266  {
     267  public:
     268    enum LitType
     269    {
     270      CHAR,
     271      STRING,
     272      BYTE,
     273      BYTE_STRING,
     274      INT,
     275      FLOAT,
     276      BOOL,
     277      ERROR
     278    };
     279  
     280  private:
     281    /* TODO: maybe make subclasses of each type of literal with their typed values
     282     * (or generics) */
     283    std::string value_as_string;
     284    LitType type;
     285    PrimitiveCoreType type_hint;
     286  
     287  public:
     288    std::string as_string () const { return value_as_string; }
     289  
     290    LitType get_lit_type () const { return type; }
     291  
     292    PrimitiveCoreType get_type_hint () const { return type_hint; }
     293  
     294    Literal (std::string value_as_string, LitType type,
     295  	   PrimitiveCoreType type_hint)
     296      : value_as_string (std::move (value_as_string)), type (type),
     297        type_hint (type_hint)
     298    {}
     299  
     300    static Literal create_error ()
     301    {
     302      return Literal ("", ERROR, PrimitiveCoreType::CORETYPE_UNKNOWN);
     303    }
     304  
     305    // Returns whether literal is in an invalid state.
     306    bool is_error () const { return type == ERROR; }
     307  };
     308  
     309  /* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr to
     310   * be defined */
     311  class AttrInputLiteral;
     312  
     313  /* TODO: move applicable stuff into here or just don't include it because
     314   * nothing uses it A segment of a path (maybe) */
     315  class PathSegment
     316  {
     317  public:
     318    virtual ~PathSegment () {}
     319  
     320    virtual std::string as_string () const = 0;
     321  
     322    // TODO: add visitor here?
     323  };
     324  
     325  // A segment of a simple path without generic or type arguments
     326  class SimplePathSegment : public PathSegment
     327  {
     328    std::string segment_name;
     329    Location locus;
     330    NodeId node_id;
     331  
     332    // only allow identifiers, "super", "self", "crate", or "$crate"
     333  public:
     334    // TODO: put checks in constructor to enforce this rule?
     335    SimplePathSegment (std::string segment_name, Location locus)
     336      : segment_name (std::move (segment_name)), locus (locus),
     337        node_id (Analysis::Mappings::get ()->get_next_node_id ())
     338    {}
     339  
     340    /* Returns whether simple path segment is in an invalid state (currently, if
     341     * empty). */
     342    bool is_error () const { return segment_name.empty (); }
     343  
     344    // Creates an error SimplePathSegment
     345    static SimplePathSegment create_error ()
     346    {
     347      return SimplePathSegment (std::string (""), Location ());
     348    }
     349  
     350    std::string as_string () const override;
     351  
     352    Location get_locus () const { return locus; }
     353    NodeId get_node_id () const { return node_id; }
     354    const std::string &get_segment_name () const { return segment_name; }
     355    bool is_super_path_seg () const
     356    {
     357      return as_string ().compare ("super") == 0;
     358    }
     359    bool is_crate_path_seg () const
     360    {
     361      return as_string ().compare ("crate") == 0;
     362    }
     363    bool is_lower_self () const { return as_string ().compare ("self") == 0; }
     364    bool is_big_self () const { return as_string ().compare ("Self") == 0; }
     365  };
     366  
     367  // A simple path without generic or type arguments
     368  class SimplePath
     369  {
     370    bool has_opening_scope_resolution;
     371    std::vector<SimplePathSegment> segments;
     372    Location locus;
     373    NodeId node_id;
     374  
     375  public:
     376    // Constructor
     377    SimplePath (std::vector<SimplePathSegment> path_segments,
     378  	      bool has_opening_scope_resolution = false,
     379  	      Location locus = Location ())
     380      : has_opening_scope_resolution (has_opening_scope_resolution),
     381        segments (std::move (path_segments)), locus (locus),
     382        node_id (Analysis::Mappings::get ()->get_next_node_id ())
     383    {}
     384  
     385    // Creates an empty SimplePath.
     386    static SimplePath create_empty ()
     387    {
     388      return SimplePath (std::vector<SimplePathSegment> ());
     389    }
     390  
     391    // Returns whether the SimplePath is empty, i.e. has path segments.
     392    bool is_empty () const { return segments.empty (); }
     393  
     394    std::string as_string () const;
     395  
     396    Location get_locus () const { return locus; }
     397    NodeId get_node_id () const { return node_id; }
     398  
     399    // does this need visitor if not polymorphic? probably not
     400  
     401    // path-to-string comparison operator
     402    bool operator== (const std::string &rhs) const
     403    {
     404      return !has_opening_scope_resolution && segments.size () == 1
     405  	   && segments[0].as_string () == rhs;
     406    }
     407  
     408    /* Creates a single-segment SimplePath from a string. This will not check to
     409     * ensure that this is a valid identifier in path, so be careful. Also, this
     410     * will have no location data.
     411     * TODO have checks? */
     412    static SimplePath from_str (std::string str, Location locus)
     413    {
     414      std::vector<AST::SimplePathSegment> single_segments
     415        = {AST::SimplePathSegment (std::move (str), locus)};
     416      return SimplePath (std::move (single_segments));
     417    }
     418  
     419    const std::vector<SimplePathSegment> &get_segments () const
     420    {
     421      return segments;
     422    }
     423  
     424    std::vector<SimplePathSegment> &get_segments () { return segments; }
     425  };
     426  
     427  // path-to-string inverse comparison operator
     428  inline bool
     429  operator!= (const SimplePath &lhs, const std::string &rhs)
     430  {
     431    return !(lhs == rhs);
     432  }
     433  
     434  // forward decl for Attribute
     435  class AttrInput;
     436  
     437  // aka Attr
     438  // Attribute AST representation
     439  struct Attribute
     440  {
     441  private:
     442    SimplePath path;
     443  
     444    // bool has_attr_input;
     445    std::unique_ptr<AttrInput> attr_input;
     446  
     447    Location locus;
     448  
     449    // TODO: maybe a variable storing whether attr input is parsed or not
     450  
     451  public:
     452    // Returns whether Attribute has AttrInput
     453    bool has_attr_input () const { return attr_input != nullptr; }
     454  
     455    // Constructor has pointer AttrInput for polymorphism reasons
     456    Attribute (SimplePath path, std::unique_ptr<AttrInput> input,
     457  	     Location locus = Location ())
     458      : path (std::move (path)), attr_input (std::move (input)), locus (locus)
     459    {}
     460  
     461    // default destructor
     462    ~Attribute () = default;
     463  
     464    // no point in being defined inline as requires virtual call anyway
     465    Attribute (const Attribute &other);
     466  
     467    // no point in being defined inline as requires virtual call anyway
     468    Attribute &operator= (const Attribute &other);
     469  
     470    // default move semantics
     471    Attribute (Attribute &&other) = default;
     472    Attribute &operator= (Attribute &&other) = default;
     473  
     474    // Unique pointer custom clone function
     475    std::unique_ptr<Attribute> clone_attribute () const
     476    {
     477      return std::unique_ptr<Attribute> (clone_attribute_impl ());
     478    }
     479  
     480    // Creates an empty attribute (which is invalid)
     481    static Attribute create_empty ()
     482    {
     483      return Attribute (SimplePath::create_empty (), nullptr);
     484    }
     485  
     486    // Returns whether the attribute is considered an "empty" attribute.
     487    bool is_empty () const { return attr_input == nullptr && path.is_empty (); }
     488  
     489    Location get_locus () const { return locus; }
     490  
     491    AttrInput &get_attr_input () const { return *attr_input; }
     492  
     493    /* e.g.:
     494        #![crate_type = "lib"]
     495        #[test]
     496        #[cfg(target_os = "linux")]
     497        #[allow(non_camel_case_types)]
     498        #![allow(unused_variables)]
     499    */
     500  
     501    // Full built-in attribute list:
     502    /*   cfg
     503     *   cfg_attr
     504     *   test
     505     *   ignore
     506     *   should_panic
     507     *   derive
     508     *   macro_export
     509     *   macro_use
     510     *   proc_macro
     511     *   proc_macro_derive
     512     *   proc_macro_attribute
     513     *   allow
     514     *   warn
     515     *   deny
     516     *   forbid
     517     *   deprecated
     518     *   must_use
     519     *   link
     520     *   link_name
     521     *   no_link
     522     *   repr
     523     *   crate_type
     524     *   no_main
     525     *   export_name
     526     *   link_section
     527     *   no_mangle
     528     *   used
     529     *   crate_name
     530     *   inline
     531     *   cold
     532     *   no_builtins
     533     *   target_feature
     534     *   doc
     535     *   no_std
     536     *   no_implicit_prelude
     537     *   path
     538     *   recursion_limit
     539     *   type_length_limit
     540     *   panic_handler
     541     *   global_allocator
     542     *   windows_subsystem
     543     *   feature     */
     544  
     545    std::string as_string () const;
     546  
     547    // no visitor pattern as not currently polymorphic
     548  
     549    const SimplePath &get_path () const { return path; }
     550    SimplePath &get_path () { return path; }
     551  
     552    // Call to parse attribute body to meta item syntax.
     553    void parse_attr_to_meta_item ();
     554  
     555    /* Determines whether cfg predicate is true and item with attribute should not
     556     * be stripped. Attribute body must already be parsed to meta item. */
     557    bool check_cfg_predicate (const Session &session) const;
     558  
     559    // Returns whether body has been parsed to meta item form or not.
     560    bool is_parsed_to_meta_item () const;
     561  
     562    /* Returns any attributes generated from cfg_attr attributes. Attribute body
     563     * must already be parsed to meta item. */
     564    std::vector<Attribute> separate_cfg_attrs () const;
     565  
     566  protected:
     567    // not virtual as currently no subclasses of Attribute, but could be in future
     568    /*virtual*/ Attribute *clone_attribute_impl () const
     569    {
     570      return new Attribute (*this);
     571    }
     572  };
     573  
     574  // Attribute body - abstract base class
     575  class AttrInput
     576  {
     577  public:
     578    enum AttrInputType
     579    {
     580      LITERAL,
     581      META_ITEM,
     582      TOKEN_TREE,
     583    };
     584  
     585    virtual ~AttrInput () {}
     586  
     587    // Unique pointer custom clone function
     588    std::unique_ptr<AttrInput> clone_attr_input () const
     589    {
     590      return std::unique_ptr<AttrInput> (clone_attr_input_impl ());
     591    }
     592  
     593    virtual std::string as_string () const = 0;
     594  
     595    virtual void accept_vis (ASTVisitor &vis) = 0;
     596  
     597    virtual bool check_cfg_predicate (const Session &session) const = 0;
     598  
     599    // Parse attribute input to meta item, if possible
     600    virtual AttrInput *parse_to_meta_item () const { return nullptr; }
     601  
     602    virtual std::vector<Attribute> separate_cfg_attrs () const { return {}; }
     603  
     604    // Returns whether attr input has been parsed to meta item syntax.
     605    virtual bool is_meta_item () const = 0;
     606  
     607    virtual AttrInputType get_attr_input_type () const = 0;
     608  
     609  protected:
     610    // pure virtual clone implementation
     611    virtual AttrInput *clone_attr_input_impl () const = 0;
     612  };
     613  
     614  // Forward decl - defined in rust-macro.h
     615  class MetaNameValueStr;
     616  
     617  // abstract base meta item inner class
     618  class MetaItemInner
     619  {
     620  protected:
     621    // pure virtual as MetaItemInner
     622    virtual MetaItemInner *clone_meta_item_inner_impl () const = 0;
     623  
     624  public:
     625    // Unique pointer custom clone function
     626    std::unique_ptr<MetaItemInner> clone_meta_item_inner () const
     627    {
     628      return std::unique_ptr<MetaItemInner> (clone_meta_item_inner_impl ());
     629    }
     630  
     631    virtual ~MetaItemInner ();
     632  
     633    virtual Location get_locus () const = 0;
     634  
     635    virtual std::string as_string () const = 0;
     636  
     637    virtual void accept_vis (ASTVisitor &vis) = 0;
     638  
     639    /* HACK: used to simplify parsing - creates a copy of that type, or returns
     640     * null */
     641    virtual std::unique_ptr<MetaNameValueStr> to_meta_name_value_str () const;
     642  
     643    // HACK: used to simplify parsing - same thing
     644    virtual SimplePath to_path_item () const
     645    {
     646      return SimplePath::create_empty ();
     647    }
     648  
     649    virtual Attribute to_attribute () const { return Attribute::create_empty (); }
     650  
     651    virtual bool check_cfg_predicate (const Session &session) const = 0;
     652  
     653    virtual bool is_key_value_pair () const { return false; }
     654  };
     655  
     656  // Container used to store MetaItems as AttrInput (bridge-ish kinda thing)
     657  class AttrInputMetaItemContainer : public AttrInput
     658  {
     659    std::vector<std::unique_ptr<MetaItemInner> > items;
     660  
     661  public:
     662    AttrInputMetaItemContainer (
     663      std::vector<std::unique_ptr<MetaItemInner> > items)
     664      : items (std::move (items))
     665    {}
     666  
     667    // copy constructor with vector clone
     668    AttrInputMetaItemContainer (const AttrInputMetaItemContainer &other)
     669    {
     670      items.reserve (other.items.size ());
     671      for (const auto &e : other.items)
     672        items.push_back (e->clone_meta_item_inner ());
     673    }
     674  
     675    // copy assignment operator with vector clone
     676    AttrInputMetaItemContainer &
     677    operator= (const AttrInputMetaItemContainer &other)
     678    {
     679      AttrInput::operator= (other);
     680  
     681      items.reserve (other.items.size ());
     682      for (const auto &e : other.items)
     683        items.push_back (e->clone_meta_item_inner ());
     684  
     685      return *this;
     686    }
     687  
     688    // default move constructors
     689    AttrInputMetaItemContainer (AttrInputMetaItemContainer &&other) = default;
     690    AttrInputMetaItemContainer &operator= (AttrInputMetaItemContainer &&other)
     691      = default;
     692  
     693    std::string as_string () const override;
     694  
     695    void accept_vis (ASTVisitor &vis) override;
     696  
     697    bool check_cfg_predicate (const Session &session) const override;
     698  
     699    AttrInputType get_attr_input_type () const final override
     700    {
     701      return AttrInput::AttrInputType::META_ITEM;
     702    }
     703  
     704    // Clones this object.
     705    std::unique_ptr<AttrInputMetaItemContainer>
     706    clone_attr_input_meta_item_container () const
     707    {
     708      return std::unique_ptr<AttrInputMetaItemContainer> (
     709        clone_attr_input_meta_item_container_impl ());
     710    }
     711  
     712    std::vector<Attribute> separate_cfg_attrs () const override;
     713  
     714    bool is_meta_item () const override { return true; }
     715  
     716    // TODO: this mutable getter seems dodgy
     717    std::vector<std::unique_ptr<MetaItemInner> > &get_items () { return items; }
     718    const std::vector<std::unique_ptr<MetaItemInner> > &get_items () const
     719    {
     720      return items;
     721    }
     722  
     723  protected:
     724    // Use covariance to implement clone function as returning this type
     725    AttrInputMetaItemContainer *clone_attr_input_impl () const final override
     726    {
     727      return clone_attr_input_meta_item_container_impl ();
     728    }
     729  
     730    AttrInputMetaItemContainer *clone_attr_input_meta_item_container_impl () const
     731    {
     732      return new AttrInputMetaItemContainer (*this);
     733    }
     734  };
     735  
     736  // A token tree with delimiters
     737  class DelimTokenTree : public TokenTree, public AttrInput
     738  {
     739    DelimType delim_type;
     740    std::vector<std::unique_ptr<TokenTree> > token_trees;
     741    Location locus;
     742  
     743  protected:
     744    DelimTokenTree *clone_delim_tok_tree_impl () const
     745    {
     746      return new DelimTokenTree (*this);
     747    }
     748  
     749    /* Use covariance to implement clone function as returning a DelimTokenTree
     750     * object */
     751    DelimTokenTree *clone_attr_input_impl () const final override
     752    {
     753      return clone_delim_tok_tree_impl ();
     754    }
     755  
     756    /* Use covariance to implement clone function as returning a DelimTokenTree
     757     * object */
     758    DelimTokenTree *clone_token_tree_impl () const final override
     759    {
     760      return clone_delim_tok_tree_impl ();
     761    }
     762  
     763  public:
     764    DelimTokenTree (DelimType delim_type,
     765  		  std::vector<std::unique_ptr<TokenTree> > token_trees
     766  		  = std::vector<std::unique_ptr<TokenTree> > (),
     767  		  Location locus = Location ())
     768      : delim_type (delim_type), token_trees (std::move (token_trees)),
     769        locus (locus)
     770    {}
     771  
     772    // Copy constructor with vector clone
     773    DelimTokenTree (DelimTokenTree const &other)
     774      : delim_type (other.delim_type), locus (other.locus)
     775    {
     776      token_trees.clear ();
     777      token_trees.reserve (other.token_trees.size ());
     778      for (const auto &e : other.token_trees)
     779        token_trees.push_back (e->clone_token_tree ());
     780    }
     781  
     782    // overloaded assignment operator with vector clone
     783    DelimTokenTree &operator= (DelimTokenTree const &other)
     784    {
     785      delim_type = other.delim_type;
     786      locus = other.locus;
     787  
     788      token_trees.clear ();
     789      token_trees.reserve (other.token_trees.size ());
     790      for (const auto &e : other.token_trees)
     791        token_trees.push_back (e->clone_token_tree ());
     792  
     793      return *this;
     794    }
     795  
     796    // move constructors
     797    DelimTokenTree (DelimTokenTree &&other) = default;
     798    DelimTokenTree &operator= (DelimTokenTree &&other) = default;
     799  
     800    static DelimTokenTree create_empty () { return DelimTokenTree (PARENS); }
     801  
     802    std::string as_string () const override;
     803  
     804    void accept_vis (ASTVisitor &vis) override;
     805  
     806    bool check_cfg_predicate (const Session &) const override
     807    {
     808      // this should never be called - should be converted first
     809      rust_assert (false);
     810      return false;
     811    }
     812  
     813    AttrInputMetaItemContainer *parse_to_meta_item () const override;
     814  
     815    std::vector<std::unique_ptr<Token> > to_token_stream () const override;
     816  
     817    std::unique_ptr<DelimTokenTree> clone_delim_token_tree () const
     818    {
     819      return std::unique_ptr<DelimTokenTree> (clone_delim_tok_tree_impl ());
     820    }
     821  
     822    bool is_meta_item () const override { return false; }
     823  
     824    AttrInputType get_attr_input_type () const final override
     825    {
     826      return AttrInput::AttrInputType::TOKEN_TREE;
     827    }
     828  
     829    std::vector<std::unique_ptr<TokenTree> > &get_token_trees ()
     830    {
     831      return token_trees;
     832    }
     833  
     834    DelimType get_delim_type () const { return delim_type; }
     835  };
     836  
     837  /* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr to
     838   * be defined */
     839  class AttrInputLiteral;
     840  
     841  // abstract base meta item class
     842  class MetaItem : public MetaItemInner
     843  {
     844  };
     845  
     846  // Forward decl - defined in rust-expr.h
     847  class MetaItemLitExpr;
     848  
     849  // Forward decl - defined in rust-expr.h
     850  class MetaItemPathLit;
     851  
     852  // Forward decl - defined in rust-macro.h
     853  class MetaItemPath;
     854  
     855  // Forward decl - defined in rust-macro.h
     856  class MetaItemSeq;
     857  
     858  // Forward decl - defined in rust-macro.h
     859  class MetaWord;
     860  
     861  // Forward decl - defined in rust-macro.h
     862  class MetaListPaths;
     863  
     864  // Forward decl - defined in rust-macro.h
     865  class MetaListNameValueStr;
     866  
     867  /* Base statement abstract class. Note that most "statements" are not allowed in
     868   * top-level module scope - only a subclass of statements called "items" are. */
     869  class Stmt : public Node
     870  {
     871  public:
     872    // Unique pointer custom clone function
     873    std::unique_ptr<Stmt> clone_stmt () const
     874    {
     875      return std::unique_ptr<Stmt> (clone_stmt_impl ());
     876    }
     877  
     878    virtual ~Stmt () {}
     879  
     880    virtual std::string as_string () const = 0;
     881  
     882    virtual void accept_vis (ASTVisitor &vis) = 0;
     883  
     884    virtual Location get_locus () const = 0;
     885  
     886    virtual void mark_for_strip () = 0;
     887    virtual bool is_marked_for_strip () const = 0;
     888    NodeId get_node_id () const { return node_id; }
     889  
     890    virtual bool is_item () const = 0;
     891  
     892  protected:
     893    Stmt () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}
     894  
     895    // Clone function implementation as pure virtual method
     896    virtual Stmt *clone_stmt_impl () const = 0;
     897  
     898    NodeId node_id;
     899  };
     900  
     901  // Rust "item" AST node (declaration of top-level/module-level allowed stuff)
     902  class Item : public Stmt
     903  {
     904  public:
     905    // Unique pointer custom clone function
     906    std::unique_ptr<Item> clone_item () const
     907    {
     908      return std::unique_ptr<Item> (clone_item_impl ());
     909    }
     910  
     911    /* Adds crate names to the vector passed by reference, if it can
     912     * (polymorphism). TODO: remove, unused. */
     913    virtual void
     914    add_crate_name (std::vector<std::string> &names ATTRIBUTE_UNUSED) const
     915    {}
     916  
     917    // FIXME: ARTHUR: Is it okay to have removed that final? Is it *required*
     918    // behavior that we have items that can also be expressions?
     919    bool is_item () const override { return true; }
     920  
     921  protected:
     922    // Clone function implementation as pure virtual method
     923    virtual Item *clone_item_impl () const = 0;
     924  
     925    /* Save having to specify two clone methods in derived classes by making
     926     * statement clone return item clone. Hopefully won't affect performance too
     927     * much. */
     928    Item *clone_stmt_impl () const final override { return clone_item_impl (); }
     929  };
     930  
     931  // forward decl of ExprWithoutBlock
     932  class ExprWithoutBlock;
     933  
     934  // Base expression AST node - abstract
     935  class Expr : public Node
     936  {
     937  public:
     938    // Unique pointer custom clone function
     939    std::unique_ptr<Expr> clone_expr () const
     940    {
     941      return std::unique_ptr<Expr> (clone_expr_impl ());
     942    }
     943  
     944    /* TODO: public methods that could be useful:
     945     *  - get_type() - returns type of expression. set_type() may also be useful
     946     * for some?
     947     *  - evaluate() - evaluates expression if constant? can_evaluate()? */
     948  
     949    /* HACK: downcasting without dynamic_cast (if possible) via polymorphism -
     950     * overrided in subclasses of ExprWithoutBlock */
     951    virtual ExprWithoutBlock *as_expr_without_block () const { return nullptr; }
     952  
     953    virtual std::string as_string () const = 0;
     954  
     955    virtual ~Expr () {}
     956  
     957    virtual Location get_locus () const = 0;
     958  
     959    virtual bool is_literal () const { return false; }
     960  
     961    // HACK: strictly not needed, but faster than full downcast clone
     962    virtual bool is_expr_without_block () const = 0;
     963  
     964    virtual void accept_vis (ASTVisitor &vis) = 0;
     965  
     966    virtual void mark_for_strip () = 0;
     967    virtual bool is_marked_for_strip () const = 0;
     968  
     969    virtual NodeId get_node_id () const { return node_id; }
     970  
     971    virtual void set_node_id (NodeId id) { node_id = id; }
     972  
     973  protected:
     974    // Constructor
     975    Expr () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}
     976  
     977    // Clone function implementation as pure virtual method
     978    virtual Expr *clone_expr_impl () const = 0;
     979  
     980    // TODO: think of less hacky way to implement this kind of thing
     981    // Sets outer attributes.
     982    virtual void set_outer_attrs (std::vector<Attribute>) = 0;
     983  
     984    NodeId node_id;
     985  };
     986  
     987  // AST node for an expression without an accompanying block - abstract
     988  class ExprWithoutBlock : public Expr
     989  {
     990  protected:
     991    // pure virtual clone implementation
     992    virtual ExprWithoutBlock *clone_expr_without_block_impl () const = 0;
     993  
     994    /* Save having to specify two clone methods in derived classes by making expr
     995     * clone return exprwithoutblock clone. Hopefully won't affect performance too
     996     * much. */
     997    ExprWithoutBlock *clone_expr_impl () const final override
     998    {
     999      return clone_expr_without_block_impl ();
    1000    }
    1001  
    1002    bool is_expr_without_block () const final override { return true; };
    1003  
    1004  public:
    1005    // Unique pointer custom clone function
    1006    std::unique_ptr<ExprWithoutBlock> clone_expr_without_block () const
    1007    {
    1008      return std::unique_ptr<ExprWithoutBlock> (clone_expr_without_block_impl ());
    1009    }
    1010  
    1011    /* downcasting hack from expr to use pratt parsing with
    1012     * parse_expr_without_block */
    1013    ExprWithoutBlock *as_expr_without_block () const final override
    1014    {
    1015      return clone_expr_without_block_impl ();
    1016    }
    1017  
    1018    virtual ExprWithoutBlock *to_stmt () const { return clone_expr_impl (); }
    1019  };
    1020  
    1021  /* HACK: IdentifierExpr, delete when figure out identifier vs expr problem in
    1022   * Pratt parser */
    1023  /* Alternatively, identifiers could just be represented as single-segment paths
    1024   */
    1025  class IdentifierExpr : public ExprWithoutBlock
    1026  {
    1027    std::vector<Attribute> outer_attrs;
    1028    Identifier ident;
    1029    Location locus;
    1030  
    1031  public:
    1032    IdentifierExpr (Identifier ident, std::vector<Attribute> outer_attrs,
    1033  		  Location locus)
    1034      : outer_attrs (std::move (outer_attrs)), ident (std::move (ident)),
    1035        locus (locus)
    1036    {}
    1037  
    1038    std::string as_string () const override { return ident; }
    1039  
    1040    Location get_locus () const override final { return locus; }
    1041  
    1042    Identifier get_ident () const { return ident; }
    1043  
    1044    void accept_vis (ASTVisitor &vis) override;
    1045  
    1046    // Clones this object.
    1047    std::unique_ptr<IdentifierExpr> clone_identifier_expr () const
    1048    {
    1049      return std::unique_ptr<IdentifierExpr> (clone_identifier_expr_impl ());
    1050    }
    1051  
    1052    // "Error state" if ident is empty, so base stripping on this.
    1053    void mark_for_strip () override { ident = {}; }
    1054    bool is_marked_for_strip () const override { return ident.empty (); }
    1055  
    1056    const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
    1057    std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
    1058  
    1059    void set_outer_attrs (std::vector<Attribute> new_attrs) override
    1060    {
    1061      outer_attrs = std::move (new_attrs);
    1062    }
    1063  
    1064  protected:
    1065    // Clone method implementation
    1066    IdentifierExpr *clone_expr_without_block_impl () const final override
    1067    {
    1068      return clone_identifier_expr_impl ();
    1069    }
    1070  
    1071    IdentifierExpr *clone_identifier_expr_impl () const
    1072    {
    1073      return new IdentifierExpr (*this);
    1074    }
    1075  };
    1076  
    1077  // Pattern base AST node
    1078  class Pattern
    1079  {
    1080  public:
    1081    // Unique pointer custom clone function
    1082    std::unique_ptr<Pattern> clone_pattern () const
    1083    {
    1084      return std::unique_ptr<Pattern> (clone_pattern_impl ());
    1085    }
    1086  
    1087    // possible virtual methods: is_refutable()
    1088  
    1089    virtual ~Pattern () {}
    1090  
    1091    virtual std::string as_string () const = 0;
    1092    virtual void accept_vis (ASTVisitor &vis) = 0;
    1093  
    1094    // as only one kind of pattern can be stripped, have default of nothing
    1095    virtual void mark_for_strip () {}
    1096    virtual bool is_marked_for_strip () const { return false; }
    1097  
    1098    virtual Location get_locus () const = 0;
    1099    virtual NodeId get_pattern_node_id () const = 0;
    1100  
    1101  protected:
    1102    // Clone pattern implementation as pure virtual method
    1103    virtual Pattern *clone_pattern_impl () const = 0;
    1104  };
    1105  
    1106  // forward decl for Type
    1107  class TraitBound;
    1108  
    1109  // Base class for types as represented in AST - abstract
    1110  class Type : public Node
    1111  {
    1112  public:
    1113    // Unique pointer custom clone function
    1114    std::unique_ptr<Type> clone_type () const
    1115    {
    1116      return std::unique_ptr<Type> (clone_type_impl ());
    1117    }
    1118  
    1119    // virtual destructor
    1120    virtual ~Type () {}
    1121  
    1122    virtual std::string as_string () const = 0;
    1123  
    1124    /* HACK: convert to trait bound. Virtual method overriden by classes that
    1125     * enable this. */
    1126    virtual TraitBound *to_trait_bound (bool) const { return nullptr; }
    1127    /* as pointer, shouldn't require definition beforehand, only forward
    1128     * declaration. */
    1129  
    1130    virtual void accept_vis (ASTVisitor &vis) = 0;
    1131  
    1132    // as only two kinds of types can be stripped, have default of nothing
    1133    virtual void mark_for_strip () {}
    1134    virtual bool is_marked_for_strip () const { return false; }
    1135  
    1136    virtual Location get_locus () const = 0;
    1137  
    1138    NodeId get_node_id () const { return node_id; }
    1139  
    1140  protected:
    1141    Type () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}
    1142  
    1143    // Clone function implementation as pure virtual method
    1144    virtual Type *clone_type_impl () const = 0;
    1145  
    1146    NodeId node_id;
    1147  };
    1148  
    1149  // A type without parentheses? - abstract
    1150  class TypeNoBounds : public Type
    1151  {
    1152  public:
    1153    // Unique pointer custom clone function
    1154    std::unique_ptr<TypeNoBounds> clone_type_no_bounds () const
    1155    {
    1156      return std::unique_ptr<TypeNoBounds> (clone_type_no_bounds_impl ());
    1157    }
    1158  
    1159  protected:
    1160    // Clone function implementation as pure virtual method
    1161    virtual TypeNoBounds *clone_type_no_bounds_impl () const = 0;
    1162  
    1163    /* Save having to specify two clone methods in derived classes by making type
    1164     * clone return typenobounds clone. Hopefully won't affect performance too
    1165     * much. */
    1166    TypeNoBounds *clone_type_impl () const final override
    1167    {
    1168      return clone_type_no_bounds_impl ();
    1169    }
    1170  
    1171    TypeNoBounds () : Type () {}
    1172  };
    1173  
    1174  /* Abstract base class representing a type param bound - Lifetime and TraitBound
    1175   * extends it */
    1176  class TypeParamBound
    1177  {
    1178  public:
    1179    virtual ~TypeParamBound () {}
    1180  
    1181    // Unique pointer custom clone function
    1182    std::unique_ptr<TypeParamBound> clone_type_param_bound () const
    1183    {
    1184      return std::unique_ptr<TypeParamBound> (clone_type_param_bound_impl ());
    1185    }
    1186  
    1187    virtual std::string as_string () const = 0;
    1188  
    1189    virtual void accept_vis (ASTVisitor &vis) = 0;
    1190  
    1191    NodeId get_node_id () const { return node_id; }
    1192  
    1193    virtual Location get_locus () const = 0;
    1194  
    1195  protected:
    1196    // Clone function implementation as pure virtual method
    1197    virtual TypeParamBound *clone_type_param_bound_impl () const = 0;
    1198  
    1199    TypeParamBound (NodeId node_id) : node_id (node_id) {}
    1200  
    1201    NodeId node_id;
    1202  };
    1203  
    1204  // Represents a lifetime (and is also a kind of type param bound)
    1205  class Lifetime : public TypeParamBound
    1206  {
    1207  public:
    1208    enum LifetimeType
    1209    {
    1210      NAMED,   // corresponds to LIFETIME_OR_LABEL
    1211      STATIC,  // corresponds to 'static
    1212      WILDCARD // corresponds to '_
    1213    };
    1214  
    1215  private:
    1216    LifetimeType lifetime_type;
    1217    std::string lifetime_name;
    1218    Location locus;
    1219    NodeId node_id;
    1220  
    1221  public:
    1222    // Constructor
    1223    Lifetime (LifetimeType type, std::string name = std::string (),
    1224  	    Location locus = Location ())
    1225      : TypeParamBound (Analysis::Mappings::get ()->get_next_node_id ()),
    1226        lifetime_type (type), lifetime_name (std::move (name)), locus (locus)
    1227    {}
    1228  
    1229    Lifetime (NodeId id, LifetimeType type, std::string name = std::string (),
    1230  	    Location locus = Location ())
    1231      : TypeParamBound (id), lifetime_type (type),
    1232        lifetime_name (std::move (name)), locus (locus)
    1233    {}
    1234  
    1235    // Creates an "error" lifetime.
    1236    static Lifetime error () { return Lifetime (NAMED, ""); }
    1237  
    1238    // Returns true if the lifetime is in an error state.
    1239    bool is_error () const
    1240    {
    1241      return lifetime_type == NAMED && lifetime_name.empty ();
    1242    }
    1243  
    1244    std::string as_string () const override;
    1245  
    1246    void accept_vis (ASTVisitor &vis) override;
    1247  
    1248    LifetimeType get_lifetime_type () { return lifetime_type; }
    1249  
    1250    Location get_locus () const override final { return locus; }
    1251  
    1252    std::string get_lifetime_name () const { return lifetime_name; }
    1253  
    1254  protected:
    1255    /* Use covariance to implement clone function as returning this object rather
    1256     * than base */
    1257    Lifetime *clone_type_param_bound_impl () const override
    1258    {
    1259      return new Lifetime (node_id, lifetime_type, lifetime_name, locus);
    1260    }
    1261  };
    1262  
    1263  /* Base generic parameter in AST. Abstract - can be represented by a Lifetime or
    1264   * Type param */
    1265  class GenericParam
    1266  {
    1267  public:
    1268    enum class Kind
    1269    {
    1270      Lifetime,
    1271      Type,
    1272      Const,
    1273    };
    1274  
    1275    virtual ~GenericParam () {}
    1276  
    1277    // Unique pointer custom clone function
    1278    std::unique_ptr<GenericParam> clone_generic_param () const
    1279    {
    1280      return std::unique_ptr<GenericParam> (clone_generic_param_impl ());
    1281    }
    1282  
    1283    virtual std::string as_string () const = 0;
    1284  
    1285    virtual void accept_vis (ASTVisitor &vis) = 0;
    1286  
    1287    virtual Location get_locus () const = 0;
    1288  
    1289    virtual Kind get_kind () const = 0;
    1290  
    1291    NodeId get_node_id () { return node_id; }
    1292  
    1293  protected:
    1294    GenericParam () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}
    1295    GenericParam (NodeId node_id) : node_id (node_id) {}
    1296  
    1297    // Clone function implementation as pure virtual method
    1298    virtual GenericParam *clone_generic_param_impl () const = 0;
    1299  
    1300    NodeId node_id;
    1301  };
    1302  
    1303  // A lifetime generic parameter (as opposed to a type generic parameter)
    1304  class LifetimeParam : public GenericParam
    1305  {
    1306    Lifetime lifetime;
    1307    std::vector<Lifetime> lifetime_bounds;
    1308    Attribute outer_attr;
    1309    Location locus;
    1310  
    1311  public:
    1312    Lifetime get_lifetime () const { return lifetime; }
    1313  
    1314    // Returns whether the lifetime param has any lifetime bounds.
    1315    bool has_lifetime_bounds () const { return !lifetime_bounds.empty (); }
    1316  
    1317    std::vector<Lifetime> &get_lifetime_bounds () { return lifetime_bounds; }
    1318  
    1319    // Returns whether the lifetime param has an outer attribute.
    1320    bool has_outer_attribute () const { return !outer_attr.is_empty (); }
    1321  
    1322    // Creates an error state lifetime param.
    1323    static LifetimeParam create_error ()
    1324    {
    1325      return LifetimeParam (Lifetime::error (), {}, Attribute::create_empty (),
    1326  			  Location ());
    1327    }
    1328  
    1329    // Returns whether the lifetime param is in an error state.
    1330    bool is_error () const { return lifetime.is_error (); }
    1331  
    1332    // Constructor
    1333    LifetimeParam (Lifetime lifetime, std::vector<Lifetime> lifetime_bounds,
    1334  		 Attribute outer_attr, Location locus)
    1335      : lifetime (std::move (lifetime)),
    1336        lifetime_bounds (std::move (lifetime_bounds)),
    1337        outer_attr (std::move (outer_attr)), locus (locus)
    1338    {}
    1339  
    1340    std::string as_string () const override;
    1341  
    1342    void accept_vis (ASTVisitor &vis) override;
    1343  
    1344    Location get_locus () const override final { return locus; }
    1345  
    1346    Kind get_kind () const override final { return Kind::Lifetime; }
    1347  
    1348  protected:
    1349    /* Use covariance to implement clone function as returning this object rather
    1350     * than base */
    1351    LifetimeParam *clone_generic_param_impl () const override
    1352    {
    1353      return new LifetimeParam (*this);
    1354    }
    1355  };
    1356  
    1357  // Item used in trait declarations - abstract base class
    1358  class TraitItem
    1359  {
    1360  protected:
    1361    TraitItem (Location locus)
    1362      : node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus)
    1363    {}
    1364  
    1365    // Clone function implementation as pure virtual method
    1366    virtual TraitItem *clone_trait_item_impl () const = 0;
    1367  
    1368    NodeId node_id;
    1369    Location locus;
    1370  
    1371  public:
    1372    virtual ~TraitItem () {}
    1373  
    1374    // Unique pointer custom clone function
    1375    std::unique_ptr<TraitItem> clone_trait_item () const
    1376    {
    1377      return std::unique_ptr<TraitItem> (clone_trait_item_impl ());
    1378    }
    1379  
    1380    virtual std::string as_string () const = 0;
    1381  
    1382    virtual void accept_vis (ASTVisitor &vis) = 0;
    1383  
    1384    virtual void mark_for_strip () = 0;
    1385    virtual bool is_marked_for_strip () const = 0;
    1386  
    1387    NodeId get_node_id () const { return node_id; }
    1388    Location get_locus () const { return locus; }
    1389  };
    1390  
    1391  /* Abstract base class for items used within an inherent impl block (the impl
    1392   * name {} one) */
    1393  class InherentImplItem
    1394  {
    1395  protected:
    1396    // Clone function implementation as pure virtual method
    1397    virtual InherentImplItem *clone_inherent_impl_item_impl () const = 0;
    1398  
    1399  public:
    1400    virtual ~InherentImplItem () {}
    1401  
    1402    // Unique pointer custom clone function
    1403    std::unique_ptr<InherentImplItem> clone_inherent_impl_item () const
    1404    {
    1405      return std::unique_ptr<InherentImplItem> (clone_inherent_impl_item_impl ());
    1406    }
    1407  
    1408    virtual std::string as_string () const = 0;
    1409  
    1410    virtual void accept_vis (ASTVisitor &vis) = 0;
    1411  
    1412    virtual void mark_for_strip () = 0;
    1413    virtual bool is_marked_for_strip () const = 0;
    1414  
    1415    virtual Location get_locus () const = 0;
    1416  };
    1417  
    1418  // Abstract base class for items used in a trait impl
    1419  class TraitImplItem
    1420  {
    1421  protected:
    1422    virtual TraitImplItem *clone_trait_impl_item_impl () const = 0;
    1423  
    1424  public:
    1425    virtual ~TraitImplItem (){};
    1426  
    1427    // Unique pointer custom clone function
    1428    std::unique_ptr<TraitImplItem> clone_trait_impl_item () const
    1429    {
    1430      return std::unique_ptr<TraitImplItem> (clone_trait_impl_item_impl ());
    1431    }
    1432  
    1433    virtual std::string as_string () const = 0;
    1434  
    1435    virtual void accept_vis (ASTVisitor &vis) = 0;
    1436  
    1437    virtual void mark_for_strip () = 0;
    1438    virtual bool is_marked_for_strip () const = 0;
    1439  };
    1440  
    1441  // Abstract base class for an item used inside an extern block
    1442  class ExternalItem
    1443  {
    1444  public:
    1445    ExternalItem () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {}
    1446  
    1447    virtual ~ExternalItem () {}
    1448  
    1449    // Unique pointer custom clone function
    1450    std::unique_ptr<ExternalItem> clone_external_item () const
    1451    {
    1452      return std::unique_ptr<ExternalItem> (clone_external_item_impl ());
    1453    }
    1454  
    1455    virtual std::string as_string () const = 0;
    1456  
    1457    virtual void accept_vis (ASTVisitor &vis) = 0;
    1458  
    1459    virtual void mark_for_strip () = 0;
    1460    virtual bool is_marked_for_strip () const = 0;
    1461  
    1462    NodeId get_node_id () const { return node_id; }
    1463  
    1464  protected:
    1465    // Clone function implementation as pure virtual method
    1466    virtual ExternalItem *clone_external_item_impl () const = 0;
    1467  
    1468    NodeId node_id;
    1469  };
    1470  
    1471  /* Data structure to store the data used in macro invocations and macro
    1472   * invocations with semicolons. */
    1473  struct MacroInvocData
    1474  {
    1475  private:
    1476    SimplePath path;
    1477    DelimTokenTree token_tree;
    1478  
    1479    // One way of parsing the macro. Probably not applicable for all macros.
    1480    std::vector<std::unique_ptr<MetaItemInner> > parsed_items;
    1481    bool parsed_to_meta_item = false;
    1482    MacroExpander *expander = nullptr;
    1483  
    1484  public:
    1485    std::string as_string () const;
    1486  
    1487    MacroInvocData (SimplePath path, DelimTokenTree token_tree)
    1488      : path (std::move (path)), token_tree (std::move (token_tree))
    1489    {}
    1490  
    1491    // Copy constructor with vector clone
    1492    MacroInvocData (const MacroInvocData &other)
    1493      : path (other.path), token_tree (other.token_tree),
    1494        parsed_to_meta_item (other.parsed_to_meta_item)
    1495    {
    1496      parsed_items.reserve (other.parsed_items.size ());
    1497      for (const auto &e : other.parsed_items)
    1498        parsed_items.push_back (e->clone_meta_item_inner ());
    1499    }
    1500  
    1501    // Copy assignment operator with vector clone
    1502    MacroInvocData &operator= (const MacroInvocData &other)
    1503    {
    1504      path = other.path;
    1505      token_tree = other.token_tree;
    1506      parsed_to_meta_item = other.parsed_to_meta_item;
    1507      expander = other.expander;
    1508  
    1509      parsed_items.reserve (other.parsed_items.size ());
    1510      for (const auto &e : other.parsed_items)
    1511        parsed_items.push_back (e->clone_meta_item_inner ());
    1512  
    1513      return *this;
    1514    }
    1515  
    1516    // Move constructors
    1517    MacroInvocData (MacroInvocData &&other) = default;
    1518    MacroInvocData &operator= (MacroInvocData &&other) = default;
    1519  
    1520    // Invalid if path is empty, so base stripping on that.
    1521    void mark_for_strip () { path = SimplePath::create_empty (); }
    1522    bool is_marked_for_strip () const { return path.is_empty (); }
    1523  
    1524    // Returns whether the macro has been parsed already.
    1525    bool is_parsed () const { return parsed_to_meta_item; }
    1526    // TODO: update on other ways of parsing it
    1527  
    1528    // TODO: this mutable getter seems kinda dodgy
    1529    DelimTokenTree &get_delim_tok_tree () { return token_tree; }
    1530    const DelimTokenTree &get_delim_tok_tree () const { return token_tree; }
    1531  
    1532    // Set the delim token tree of a macro invocation
    1533    void set_delim_tok_tree (DelimTokenTree tree) { token_tree = tree; }
    1534  
    1535    // TODO: this mutable getter seems kinda dodgy
    1536    SimplePath &get_path () { return path; }
    1537    const SimplePath &get_path () const { return path; }
    1538  
    1539    void set_expander (MacroExpander *new_expander) { expander = new_expander; }
    1540    MacroExpander *get_expander ()
    1541    {
    1542      rust_assert (expander);
    1543      return expander;
    1544    }
    1545  
    1546    void
    1547    set_meta_item_output (std::vector<std::unique_ptr<MetaItemInner> > new_items)
    1548    {
    1549      parsed_items = std::move (new_items);
    1550    }
    1551    // TODO: mutable getter seems kinda dodgy
    1552    std::vector<std::unique_ptr<MetaItemInner> > &get_meta_items ()
    1553    {
    1554      return parsed_items;
    1555    }
    1556    const std::vector<std::unique_ptr<MetaItemInner> > &get_meta_items () const
    1557    {
    1558      return parsed_items;
    1559    }
    1560  };
    1561  
    1562  class SingleASTNode
    1563  {
    1564  public:
    1565    enum NodeType
    1566    {
    1567      EXPRESSION,
    1568      ITEM,
    1569      STMT,
    1570      EXTERN,
    1571      TRAIT,
    1572      IMPL,
    1573      TRAIT_IMPL,
    1574      TYPE,
    1575    };
    1576  
    1577  private:
    1578    NodeType kind;
    1579  
    1580    // FIXME make this a union
    1581    std::unique_ptr<Expr> expr;
    1582    std::unique_ptr<Item> item;
    1583    std::unique_ptr<Stmt> stmt;
    1584    std::unique_ptr<ExternalItem> external_item;
    1585    std::unique_ptr<TraitItem> trait_item;
    1586    std::unique_ptr<InherentImplItem> impl_item;
    1587    std::unique_ptr<TraitImplItem> trait_impl_item;
    1588    std::unique_ptr<Type> type;
    1589  
    1590  public:
    1591    SingleASTNode (std::unique_ptr<Expr> expr)
    1592      : kind (EXPRESSION), expr (std::move (expr))
    1593    {}
    1594  
    1595    SingleASTNode (std::unique_ptr<Item> item)
    1596      : kind (ITEM), item (std::move (item))
    1597    {}
    1598  
    1599    SingleASTNode (std::unique_ptr<Stmt> stmt)
    1600      : kind (STMT), stmt (std::move (stmt))
    1601    {}
    1602  
    1603    SingleASTNode (std::unique_ptr<ExternalItem> item)
    1604      : kind (EXTERN), external_item (std::move (item))
    1605    {}
    1606  
    1607    SingleASTNode (std::unique_ptr<TraitItem> item)
    1608      : kind (TRAIT), trait_item (std::move (item))
    1609    {}
    1610  
    1611    SingleASTNode (std::unique_ptr<InherentImplItem> item)
    1612      : kind (IMPL), impl_item (std::move (item))
    1613    {}
    1614  
    1615    SingleASTNode (std::unique_ptr<TraitImplItem> trait_impl_item)
    1616      : kind (TRAIT_IMPL), trait_impl_item (std::move (trait_impl_item))
    1617    {}
    1618  
    1619    SingleASTNode (std::unique_ptr<Type> type)
    1620      : kind (TYPE), type (std::move (type))
    1621    {}
    1622  
    1623    SingleASTNode (SingleASTNode const &other)
    1624    {
    1625      kind = other.kind;
    1626      switch (kind)
    1627        {
    1628        case EXPRESSION:
    1629  	expr = other.expr->clone_expr ();
    1630  	break;
    1631  
    1632        case ITEM:
    1633  	item = other.item->clone_item ();
    1634  	break;
    1635  
    1636        case STMT:
    1637  	stmt = other.stmt->clone_stmt ();
    1638  	break;
    1639  
    1640        case EXTERN:
    1641  	external_item = other.external_item->clone_external_item ();
    1642  	break;
    1643  
    1644        case TRAIT:
    1645  	trait_item = other.trait_item->clone_trait_item ();
    1646  	break;
    1647  
    1648        case IMPL:
    1649  	impl_item = other.impl_item->clone_inherent_impl_item ();
    1650  	break;
    1651  
    1652        case TRAIT_IMPL:
    1653  	trait_impl_item = other.trait_impl_item->clone_trait_impl_item ();
    1654  	break;
    1655  
    1656        case TYPE:
    1657  	type = other.type->clone_type ();
    1658  	break;
    1659        }
    1660    }
    1661  
    1662    SingleASTNode operator= (SingleASTNode const &other)
    1663    {
    1664      kind = other.kind;
    1665      switch (kind)
    1666        {
    1667        case EXPRESSION:
    1668  	expr = other.expr->clone_expr ();
    1669  	break;
    1670  
    1671        case ITEM:
    1672  	item = other.item->clone_item ();
    1673  	break;
    1674  
    1675        case STMT:
    1676  	stmt = other.stmt->clone_stmt ();
    1677  	break;
    1678  
    1679        case EXTERN:
    1680  	external_item = other.external_item->clone_external_item ();
    1681  	break;
    1682  
    1683        case TRAIT:
    1684  	trait_item = other.trait_item->clone_trait_item ();
    1685  	break;
    1686  
    1687        case IMPL:
    1688  	impl_item = other.impl_item->clone_inherent_impl_item ();
    1689  	break;
    1690  
    1691        case TRAIT_IMPL:
    1692  	trait_impl_item = other.trait_impl_item->clone_trait_impl_item ();
    1693  	break;
    1694  
    1695        case TYPE:
    1696  	type = other.type->clone_type ();
    1697  	break;
    1698        }
    1699      return *this;
    1700    }
    1701  
    1702    SingleASTNode (SingleASTNode &&other) = default;
    1703    SingleASTNode &operator= (SingleASTNode &&other) = default;
    1704  
    1705    NodeType get_kind () const { return kind; }
    1706  
    1707    std::unique_ptr<Expr> &get_expr ()
    1708    {
    1709      rust_assert (kind == EXPRESSION);
    1710      return expr;
    1711    }
    1712  
    1713    std::unique_ptr<Item> &get_item ()
    1714    {
    1715      rust_assert (kind == ITEM);
    1716      return item;
    1717    }
    1718  
    1719    std::unique_ptr<Stmt> &get_stmt ()
    1720    {
    1721      rust_assert (kind == STMT);
    1722      return stmt;
    1723    }
    1724  
    1725    /**
    1726     * Access the inner nodes and take ownership of them.
    1727     * You can only call these functions once per node
    1728     */
    1729  
    1730    std::unique_ptr<Stmt> take_stmt ()
    1731    {
    1732      rust_assert (!is_error ());
    1733      return std::move (stmt);
    1734    }
    1735  
    1736    std::unique_ptr<Expr> take_expr ()
    1737    {
    1738      rust_assert (!is_error ());
    1739      return std::move (expr);
    1740    }
    1741  
    1742    std::unique_ptr<Item> take_item ()
    1743    {
    1744      rust_assert (!is_error ());
    1745      return std::move (item);
    1746    }
    1747  
    1748    std::unique_ptr<TraitItem> take_trait_item ()
    1749    {
    1750      rust_assert (!is_error ());
    1751      return std::move (trait_item);
    1752    }
    1753  
    1754    std::unique_ptr<ExternalItem> take_external_item ()
    1755    {
    1756      rust_assert (!is_error ());
    1757      return std::move (external_item);
    1758    }
    1759  
    1760    std::unique_ptr<InherentImplItem> take_impl_item ()
    1761    {
    1762      rust_assert (!is_error ());
    1763      return std::move (impl_item);
    1764    }
    1765  
    1766    std::unique_ptr<TraitImplItem> take_trait_impl_item ()
    1767    {
    1768      rust_assert (!is_error ());
    1769      return std::move (trait_impl_item);
    1770    }
    1771  
    1772    std::unique_ptr<Type> take_type ()
    1773    {
    1774      rust_assert (!is_error ());
    1775      return std::move (type);
    1776    }
    1777  
    1778    void accept_vis (ASTVisitor &vis)
    1779    {
    1780      switch (kind)
    1781        {
    1782        case EXPRESSION:
    1783  	expr->accept_vis (vis);
    1784  	break;
    1785  
    1786        case ITEM:
    1787  	item->accept_vis (vis);
    1788  	break;
    1789  
    1790        case STMT:
    1791  	stmt->accept_vis (vis);
    1792  	break;
    1793  
    1794        case EXTERN:
    1795  	external_item->accept_vis (vis);
    1796  	break;
    1797  
    1798        case TRAIT:
    1799  	trait_item->accept_vis (vis);
    1800  	break;
    1801  
    1802        case IMPL:
    1803  	impl_item->accept_vis (vis);
    1804  	break;
    1805  
    1806        case TRAIT_IMPL:
    1807  	trait_impl_item->accept_vis (vis);
    1808  	break;
    1809  
    1810        case TYPE:
    1811  	type->accept_vis (vis);
    1812  	break;
    1813        }
    1814    }
    1815  
    1816    bool is_error ()
    1817    {
    1818      switch (kind)
    1819        {
    1820        case EXPRESSION:
    1821  	return expr == nullptr;
    1822        case ITEM:
    1823  	return item == nullptr;
    1824        case STMT:
    1825  	return stmt == nullptr;
    1826        case EXTERN:
    1827  	return external_item == nullptr;
    1828        case TRAIT:
    1829  	return trait_item == nullptr;
    1830        case IMPL:
    1831  	return impl_item == nullptr;
    1832        case TRAIT_IMPL:
    1833  	return trait_impl_item == nullptr;
    1834        case TYPE:
    1835  	return type == nullptr;
    1836        }
    1837  
    1838      gcc_unreachable ();
    1839      return true;
    1840    }
    1841  
    1842    std::string as_string () const
    1843    {
    1844      switch (kind)
    1845        {
    1846        case EXPRESSION:
    1847  	return "Expr: " + expr->as_string ();
    1848        case ITEM:
    1849  	return "Item: " + item->as_string ();
    1850        case STMT:
    1851  	return "Stmt: " + stmt->as_string ();
    1852        case EXTERN:
    1853  	return "External Item: " + external_item->as_string ();
    1854        case TRAIT:
    1855  	return "Trait Item: " + trait_item->as_string ();
    1856        case IMPL:
    1857  	return "Impl Item: " + impl_item->as_string ();
    1858        case TRAIT_IMPL:
    1859  	return "Trait Impl Item: " + trait_impl_item->as_string ();
    1860        case TYPE:
    1861  	return "Type: " + type->as_string ();
    1862        }
    1863  
    1864      gcc_unreachable ();
    1865      return "";
    1866    }
    1867  };
    1868  
    1869  // A crate AST object - holds all the data for a single compilation unit
    1870  struct Crate
    1871  {
    1872    std::vector<Attribute> inner_attrs;
    1873    // dodgy spacing required here
    1874    /* TODO: is it better to have a vector of items here or a module (implicit
    1875     * top-level one)? */
    1876    std::vector<std::unique_ptr<Item> > items;
    1877  
    1878    NodeId node_id;
    1879  
    1880  public:
    1881    // Constructor
    1882    Crate (std::vector<std::unique_ptr<Item> > items,
    1883  	 std::vector<Attribute> inner_attrs)
    1884      : inner_attrs (std::move (inner_attrs)), items (std::move (items)),
    1885        node_id (Analysis::Mappings::get ()->get_next_node_id ())
    1886    {}
    1887  
    1888    // Copy constructor with vector clone
    1889    Crate (Crate const &other)
    1890      : inner_attrs (other.inner_attrs), node_id (other.node_id)
    1891    {
    1892      items.reserve (other.items.size ());
    1893      for (const auto &e : other.items)
    1894        items.push_back (e->clone_item ());
    1895    }
    1896  
    1897    ~Crate () = default;
    1898  
    1899    // Overloaded assignment operator with vector clone
    1900    Crate &operator= (Crate const &other)
    1901    {
    1902      inner_attrs = other.inner_attrs;
    1903      node_id = other.node_id;
    1904  
    1905      items.reserve (other.items.size ());
    1906      for (const auto &e : other.items)
    1907        items.push_back (e->clone_item ());
    1908  
    1909      return *this;
    1910    }
    1911  
    1912    // Move constructors
    1913    Crate (Crate &&other) = default;
    1914    Crate &operator= (Crate &&other) = default;
    1915  
    1916    // Get crate representation as string (e.g. for debugging).
    1917    std::string as_string () const;
    1918  
    1919    // Delete all crate information, e.g. if fails cfg.
    1920    void strip_crate ()
    1921    {
    1922      inner_attrs.clear ();
    1923      inner_attrs.shrink_to_fit ();
    1924  
    1925      items.clear ();
    1926      items.shrink_to_fit ();
    1927      // TODO: is this the best way to do this?
    1928    }
    1929  
    1930    NodeId get_node_id () const { return node_id; }
    1931    const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
    1932  };
    1933  
    1934  // Base path expression AST node - abstract
    1935  class PathExpr : public ExprWithoutBlock
    1936  {
    1937  };
    1938  } // namespace AST
    1939  } // namespace Rust
    1940  
    1941  #endif