(root)/
gcc-13.2.0/
gcc/
rust/
ast/
rust-macro.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_MACRO_H
      20  #define RUST_AST_MACRO_H
      21  
      22  #include "rust-system.h"
      23  #include "rust-ast.h"
      24  #include "rust-ast-fragment.h"
      25  #include "rust-location.h"
      26  #include "rust-item.h"
      27  #include "rust-make-unique.h"
      28  
      29  namespace Rust {
      30  namespace AST {
      31  class MacroFragSpec
      32  {
      33  public:
      34    enum Kind
      35    {
      36      BLOCK,
      37      EXPR,
      38      IDENT,
      39      ITEM,
      40      LIFETIME,
      41      LITERAL,
      42      META,
      43      PAT,
      44      PATH,
      45      STMT,
      46      TT,
      47      TY,
      48      VIS,
      49      INVALID // not really a specifier, but used to mark invalid one passed in
      50    };
      51  
      52    MacroFragSpec (Kind kind) : kind (kind) {}
      53  
      54    static MacroFragSpec get_frag_spec_from_str (const std::string &str)
      55    {
      56      if (str == "block")
      57        return MacroFragSpec (BLOCK);
      58      else if (str == "expr")
      59        return MacroFragSpec (EXPR);
      60      else if (str == "ident")
      61        return MacroFragSpec (IDENT);
      62      else if (str == "item")
      63        return MacroFragSpec (ITEM);
      64      else if (str == "lifetime")
      65        return MacroFragSpec (LIFETIME);
      66      else if (str == "literal")
      67        return MacroFragSpec (LITERAL);
      68      else if (str == "meta")
      69        return MacroFragSpec (META);
      70      else if (str == "pat" || str == "pat_param")
      71        return MacroFragSpec (PAT);
      72      else if (str == "path")
      73        return MacroFragSpec (PATH);
      74      else if (str == "stmt")
      75        return MacroFragSpec (STMT);
      76      else if (str == "tt")
      77        return MacroFragSpec (TT);
      78      else if (str == "ty")
      79        return MacroFragSpec (TY);
      80      else if (str == "vis")
      81        return MacroFragSpec (VIS);
      82      else
      83        {
      84  	// error_at("invalid string '%s' used as fragment specifier",
      85  	// str->c_str()));
      86  	return MacroFragSpec (INVALID);
      87        }
      88    }
      89  
      90    Kind get_kind () const { return kind; }
      91    bool is_error () const { return kind == Kind::INVALID; }
      92  
      93    // Converts a frag spec enum item to a string form.
      94    std::string as_string () const
      95    {
      96      switch (kind)
      97        {
      98        case BLOCK:
      99  	return "block";
     100        case EXPR:
     101  	return "expr";
     102        case IDENT:
     103  	return "ident";
     104        case ITEM:
     105  	return "item";
     106        case LIFETIME:
     107  	return "lifetime";
     108        case LITERAL:
     109  	return "literal";
     110        case META:
     111  	return "meta";
     112        case PAT:
     113  	return "pat";
     114        case PATH:
     115  	return "path";
     116        case STMT:
     117  	return "stmt";
     118        case TT:
     119  	return "tt";
     120        case TY:
     121  	return "ty";
     122        case VIS:
     123  	return "vis";
     124        case INVALID:
     125  	return "INVALID_FRAG_SPEC";
     126        default:
     127  	return "ERROR_MARK_STRING - unknown frag spec";
     128        }
     129    }
     130  
     131    bool has_follow_set_restrictions () const
     132    {
     133      switch (kind)
     134        {
     135        case EXPR:
     136        case STMT:
     137        case PAT:
     138        case PATH:
     139        case TY:
     140        case VIS:
     141  	return true;
     142        default:
     143  	return false;
     144        }
     145    }
     146  
     147    bool has_follow_set_fragment_restrictions () const
     148    {
     149      switch (kind)
     150        {
     151        case PAT:
     152        case TY:
     153        case VIS:
     154  	return true;
     155        default:
     156  	return false;
     157        }
     158    }
     159  
     160  private:
     161    Kind kind;
     162  };
     163  
     164  // A macro match that has an identifier and fragment spec
     165  class MacroMatchFragment : public MacroMatch
     166  {
     167    Identifier ident;
     168    MacroFragSpec frag_spec;
     169    Location locus;
     170  
     171  public:
     172    MacroMatchFragment (Identifier ident, MacroFragSpec frag_spec, Location locus)
     173      : ident (std::move (ident)), frag_spec (frag_spec), locus (locus)
     174    {}
     175  
     176    // Returns whether macro match fragment is in an error state.
     177    bool is_error () const
     178    {
     179      return frag_spec.get_kind () == MacroFragSpec::INVALID;
     180    }
     181  
     182    // Creates an error state macro match fragment.
     183    static MacroMatchFragment create_error (Location locus)
     184    {
     185      return MacroMatchFragment (std::string (""),
     186  			       MacroFragSpec (MacroFragSpec::Kind::INVALID),
     187  			       locus);
     188    }
     189  
     190    std::string as_string () const override;
     191    Location get_match_locus () const override { return locus; };
     192  
     193    void accept_vis (ASTVisitor &vis) override;
     194  
     195    MacroMatchType get_macro_match_type () const override
     196    {
     197      return MacroMatchType::Fragment;
     198    }
     199  
     200    Identifier get_ident () const { return ident; }
     201    const MacroFragSpec &get_frag_spec () const { return frag_spec; }
     202  
     203  protected:
     204    /* Use covariance to implement clone function as returning this object rather
     205     * than base */
     206    MacroMatchFragment *clone_macro_match_impl () const override
     207    {
     208      return new MacroMatchFragment (*this);
     209    }
     210  };
     211  
     212  // A repetition macro match
     213  class MacroMatchRepetition : public MacroMatch
     214  {
     215  public:
     216    enum MacroRepOp
     217    {
     218      NONE,
     219      ANY,
     220      ONE_OR_MORE,
     221      ZERO_OR_ONE,
     222    };
     223  
     224  private:
     225    std::vector<std::unique_ptr<MacroMatch>> matches;
     226    MacroRepOp op;
     227  
     228    // bool has_sep;
     229    typedef Token MacroRepSep;
     230    // any token except delimiters and repetition operators
     231    std::unique_ptr<MacroRepSep> sep;
     232    Location locus;
     233  
     234  public:
     235    // Returns whether macro match repetition has separator token.
     236    bool has_sep () const { return sep != nullptr; }
     237  
     238    MacroMatchRepetition (std::vector<std::unique_ptr<MacroMatch>> matches,
     239  			MacroRepOp op, std::unique_ptr<MacroRepSep> sep,
     240  			Location locus)
     241      : matches (std::move (matches)), op (op), sep (std::move (sep)),
     242        locus (locus)
     243    {}
     244  
     245    // Copy constructor with clone
     246    MacroMatchRepetition (MacroMatchRepetition const &other)
     247      : op (other.op), locus (other.locus)
     248    {
     249      // guard to protect from null pointer dereference
     250      if (other.sep != nullptr)
     251        sep = other.sep->clone_token ();
     252  
     253      matches.reserve (other.matches.size ());
     254      for (const auto &e : other.matches)
     255        matches.push_back (e->clone_macro_match ());
     256    }
     257  
     258    // Overloaded assignment operator to clone
     259    MacroMatchRepetition &operator= (MacroMatchRepetition const &other)
     260    {
     261      op = other.op;
     262      locus = other.locus;
     263  
     264      // guard to protect from null pointer dereference
     265      if (other.sep != nullptr)
     266        sep = other.sep->clone_token ();
     267      else
     268        sep = nullptr;
     269  
     270      matches.reserve (other.matches.size ());
     271      for (const auto &e : other.matches)
     272        matches.push_back (e->clone_macro_match ());
     273  
     274      return *this;
     275    }
     276  
     277    // move constructors
     278    MacroMatchRepetition (MacroMatchRepetition &&other) = default;
     279    MacroMatchRepetition &operator= (MacroMatchRepetition &&other) = default;
     280  
     281    std::string as_string () const override;
     282    Location get_match_locus () const override { return locus; };
     283  
     284    void accept_vis (ASTVisitor &vis) override;
     285  
     286    MacroMatchType get_macro_match_type () const override
     287    {
     288      return MacroMatchType::Repetition;
     289    }
     290  
     291    MacroRepOp get_op () const { return op; }
     292    const std::unique_ptr<MacroRepSep> &get_sep () const { return sep; }
     293    std::vector<std::unique_ptr<MacroMatch>> &get_matches () { return matches; }
     294    const std::vector<std::unique_ptr<MacroMatch>> &get_matches () const
     295    {
     296      return matches;
     297    }
     298  
     299  protected:
     300    /* Use covariance to implement clone function as returning this object rather
     301     * than base */
     302    MacroMatchRepetition *clone_macro_match_impl () const override
     303    {
     304      return new MacroMatchRepetition (*this);
     305    }
     306  };
     307  
     308  // can't inline due to polymorphism
     309  class MacroMatcher : public MacroMatch
     310  {
     311    DelimType delim_type;
     312    std::vector<std::unique_ptr<MacroMatch>> matches;
     313    Location locus;
     314  
     315    // TODO: think of way to mark invalid that doesn't take up more space
     316    bool is_invalid;
     317  
     318  public:
     319    MacroMatcher (DelimType delim_type,
     320  		std::vector<std::unique_ptr<MacroMatch>> matches,
     321  		Location locus)
     322      : delim_type (delim_type), matches (std::move (matches)), locus (locus),
     323        is_invalid (false)
     324    {}
     325  
     326    // copy constructor with vector clone
     327    MacroMatcher (MacroMatcher const &other)
     328      : delim_type (other.delim_type), locus (other.locus)
     329    {
     330      matches.reserve (other.matches.size ());
     331      for (const auto &e : other.matches)
     332        matches.push_back (e->clone_macro_match ());
     333    }
     334  
     335    // overloaded assignment operator with vector clone
     336    MacroMatcher &operator= (MacroMatcher const &other)
     337    {
     338      delim_type = other.delim_type;
     339      locus = other.locus;
     340  
     341      matches.reserve (other.matches.size ());
     342      for (const auto &e : other.matches)
     343        matches.push_back (e->clone_macro_match ());
     344  
     345      return *this;
     346    }
     347  
     348    // move constructors
     349    MacroMatcher (MacroMatcher &&other) = default;
     350    MacroMatcher &operator= (MacroMatcher &&other) = default;
     351  
     352    // Creates an error state macro matcher.
     353    static MacroMatcher create_error (Location locus)
     354    {
     355      return MacroMatcher (true, locus);
     356    }
     357  
     358    // Returns whether MacroMatcher is in an error state.
     359    bool is_error () const { return is_invalid; }
     360    Location get_match_locus () const override { return locus; }
     361  
     362    std::string as_string () const override;
     363  
     364    void accept_vis (ASTVisitor &vis) override;
     365  
     366    MacroMatchType get_macro_match_type () const override
     367    {
     368      return MacroMatchType::Matcher;
     369    }
     370  
     371    DelimType get_delim_type () const { return delim_type; }
     372    std::vector<std::unique_ptr<MacroMatch>> &get_matches () { return matches; }
     373    const std::vector<std::unique_ptr<MacroMatch>> &get_matches () const
     374    {
     375      return matches;
     376    }
     377  
     378  protected:
     379    /* Use covariance to implement clone function as returning this object rather
     380     * than base */
     381    MacroMatcher *clone_macro_match_impl () const override
     382    {
     383      return new MacroMatcher (*this);
     384    }
     385  
     386    // constructor only used to create error matcher
     387    MacroMatcher (bool is_invalid, Location locus)
     388      : delim_type (PARENS), locus (locus), is_invalid (is_invalid)
     389    {}
     390  };
     391  
     392  // TODO: inline?
     393  struct MacroTranscriber
     394  {
     395  private:
     396    DelimTokenTree token_tree;
     397    Location locus;
     398  
     399  public:
     400    MacroTranscriber (DelimTokenTree token_tree, Location locus)
     401      : token_tree (std::move (token_tree)), locus (locus)
     402    {}
     403  
     404    std::string as_string () const { return token_tree.as_string (); }
     405  
     406    Location get_locus () const { return locus; }
     407  
     408    DelimTokenTree &get_token_tree () { return token_tree; }
     409    const DelimTokenTree &get_token_tree () const { return token_tree; }
     410  };
     411  
     412  // A macro rule? Matcher and transcriber pair?
     413  struct MacroRule
     414  {
     415  private:
     416    MacroMatcher matcher;
     417    MacroTranscriber transcriber;
     418    Location locus;
     419  
     420  public:
     421    MacroRule (MacroMatcher matcher, MacroTranscriber transcriber, Location locus)
     422      : matcher (std::move (matcher)), transcriber (std::move (transcriber)),
     423        locus (locus)
     424    {}
     425  
     426    // Returns whether macro rule is in error state.
     427    bool is_error () const { return matcher.is_error (); }
     428  
     429    // Creates an error state macro rule.
     430    static MacroRule create_error (Location locus)
     431    {
     432      return MacroRule (MacroMatcher::create_error (locus),
     433  		      MacroTranscriber (DelimTokenTree::create_empty (),
     434  					Location ()),
     435  		      locus);
     436    }
     437  
     438    Location get_locus () const { return locus; }
     439  
     440    std::string as_string () const;
     441  
     442    MacroMatcher &get_matcher () { return matcher; }
     443    MacroTranscriber &get_transcriber () { return transcriber; }
     444  };
     445  
     446  // A macro rules definition item AST node
     447  class MacroRulesDefinition : public VisItem
     448  {
     449  public:
     450    enum MacroKind
     451    {
     452      // Macro by Example (legacy macro rules)
     453      MBE,
     454      // Declarative macros 2.0
     455      DeclMacro,
     456    };
     457  
     458  private:
     459    std::vector<Attribute> outer_attrs;
     460    Identifier rule_name;
     461    // MacroRulesDef rules_def;
     462    // only curly without required semicolon at end
     463    DelimType delim_type;
     464    // MacroRules rules;
     465    std::vector<MacroRule> rules; // inlined form
     466    Location locus;
     467  
     468    std::function<Fragment (Location, MacroInvocData &)> associated_transcriber;
     469    // Since we can't compare std::functions, we need to use an extra boolean
     470    bool is_builtin_rule;
     471    MacroKind kind;
     472  
     473    /**
     474     * Default function to use as an associated transcriber. This function should
     475     * never be called, hence the gcc_unreachable().
     476     * If this function is used, then the macro is not builtin and the compiler
     477     * should make use of the actual rules. If the macro is builtin, then another
     478     * associated transcriber should be used
     479     */
     480    static Fragment dummy_builtin (Location, MacroInvocData &)
     481    {
     482      gcc_unreachable ();
     483      return Fragment::create_error ();
     484    }
     485  
     486    /* NOTE: in rustc, macro definitions are considered (and parsed as) a type
     487     * of macro, whereas here they are considered part of the language itself.
     488     * I am not aware of the implications of this decision. The rustc spec does
     489     * mention that using the same parser for macro definitions and invocations
     490     * is "extremely self-referential and non-intuitive". */
     491    MacroRulesDefinition (Identifier rule_name, DelimType delim_type,
     492  			std::vector<MacroRule> rules,
     493  			std::vector<Attribute> outer_attrs, Location locus,
     494  			MacroKind kind, Visibility vis)
     495      : VisItem (std::move (vis), outer_attrs),
     496        outer_attrs (std::move (outer_attrs)), rule_name (std::move (rule_name)),
     497        delim_type (delim_type), rules (std::move (rules)), locus (locus),
     498        associated_transcriber (dummy_builtin), is_builtin_rule (false),
     499        kind (kind)
     500    {}
     501  
     502    MacroRulesDefinition (
     503      Identifier builtin_name, DelimType delim_type,
     504      std::function<Fragment (Location, MacroInvocData &)> associated_transcriber,
     505      MacroKind kind, Visibility vis)
     506      : VisItem (std::move (vis), std::vector<Attribute> ()),
     507        outer_attrs (std::vector<Attribute> ()), rule_name (builtin_name),
     508        delim_type (delim_type), rules (std::vector<MacroRule> ()),
     509        locus (Location ()), associated_transcriber (associated_transcriber),
     510        is_builtin_rule (true), kind (kind)
     511    {}
     512  
     513  public:
     514    std::string as_string () const override;
     515  
     516    static std::unique_ptr<MacroRulesDefinition>
     517    mbe (Identifier rule_name, DelimType delim_type, std::vector<MacroRule> rules,
     518         std::vector<Attribute> outer_attrs, Location locus)
     519    {
     520      return Rust::make_unique<MacroRulesDefinition> (
     521        MacroRulesDefinition (rule_name, delim_type, rules, outer_attrs, locus,
     522  			    AST::MacroRulesDefinition::MacroKind::MBE,
     523  			    AST::Visibility::create_error ()));
     524    }
     525  
     526    static std::unique_ptr<MacroRulesDefinition>
     527    decl_macro (Identifier rule_name, std::vector<MacroRule> rules,
     528  	      std::vector<Attribute> outer_attrs, Location locus,
     529  	      Visibility vis)
     530    {
     531      return Rust::make_unique<MacroRulesDefinition> (MacroRulesDefinition (
     532        rule_name, AST::DelimType::CURLY, rules, outer_attrs, locus,
     533        AST::MacroRulesDefinition::MacroKind::DeclMacro, vis));
     534    }
     535  
     536    void accept_vis (ASTVisitor &vis) override;
     537  
     538    // Invalid if rule name is empty, so base stripping on that.
     539    void mark_for_strip () override { rule_name = ""; }
     540    bool is_marked_for_strip () const override { return rule_name.empty (); }
     541  
     542    // TODO: this mutable getter seems really dodgy. Think up better way.
     543    std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
     544    const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
     545  
     546    std::vector<MacroRule> &get_macro_rules () { return rules; }
     547    const std::vector<MacroRule> &get_macro_rules () const { return rules; }
     548  
     549    Location get_locus () const override final { return locus; }
     550  
     551    Identifier get_rule_name () const { return rule_name; }
     552  
     553    std::vector<MacroRule> &get_rules () { return rules; }
     554    const std::vector<MacroRule> &get_rules () const { return rules; }
     555  
     556    bool is_builtin () const { return is_builtin_rule; }
     557    const std::function<Fragment (Location, MacroInvocData &)> &
     558    get_builtin_transcriber () const
     559    {
     560      rust_assert (is_builtin ());
     561      return associated_transcriber;
     562    }
     563    void set_builtin_transcriber (
     564      std::function<Fragment (Location, MacroInvocData &)> transcriber)
     565    {
     566      associated_transcriber = transcriber;
     567      is_builtin_rule = true;
     568    }
     569  
     570    Kind get_ast_kind () const override { return Kind::MACRO_RULES_DEFINITION; }
     571  
     572  protected:
     573    /* Use covariance to implement clone function as returning this object rather
     574     * than base */
     575    MacroRulesDefinition *clone_item_impl () const override
     576    {
     577      return new MacroRulesDefinition (*this);
     578    }
     579  };
     580  
     581  /**
     582   * All builtin macros possible
     583   */
     584  enum class BuiltinMacro
     585  {
     586    Assert,
     587    File,
     588    Line,
     589    Column,
     590    IncludeBytes,
     591    IncludeStr,
     592    CompileError,
     593    Concat,
     594    Env,
     595    Cfg,
     596    Include
     597  };
     598  
     599  BuiltinMacro
     600  builtin_macro_from_string (const std::string &identifier);
     601  
     602  /* AST node of a macro invocation, which is replaced by the macro result at
     603   * compile time. This is technically a sum-type/tagged-union, which represents
     604   * both classic macro invocations and builtin macro invocations. Regular macro
     605   * invocations are expanded lazily, but builtin macro invocations need to be
     606   * expanded eagerly, hence the differentiation.
     607   */
     608  class MacroInvocation : public TypeNoBounds,
     609  			public Pattern,
     610  			public Item,
     611  			public TraitItem,
     612  			public TraitImplItem,
     613  			public InherentImplItem,
     614  			public ExternalItem,
     615  			public ExprWithoutBlock
     616  {
     617  public:
     618    enum class InvocKind
     619    {
     620      Regular,
     621      Builtin,
     622    };
     623  
     624    std::string as_string () const override;
     625  
     626    /**
     627     * The default constructor you should use. Whenever we parse a macro call, we
     628     * cannot possibly know whether or not this call refers to a builtin macro or
     629     * a regular macro. With name resolution and scopes and nested macro calls,
     630     * this is literally impossible. Hence, always start by creating a `Regular`
     631     * MacroInvocation which will then (maybe!) become a `Builtin` macro
     632     * invocation in the expander.
     633     */
     634    static std::unique_ptr<MacroInvocation>
     635    Regular (MacroInvocData invoc_data, std::vector<Attribute> outer_attrs,
     636  	   Location locus, bool is_semi_coloned = false)
     637    {
     638      return std::unique_ptr<MacroInvocation> (
     639        new MacroInvocation (InvocKind::Regular, Optional<BuiltinMacro>::none (),
     640  			   invoc_data, outer_attrs, locus, is_semi_coloned,
     641  			   {}));
     642    }
     643  
     644    /**
     645     * Create a builtin macro invocation. This can only be done after macro
     646     * name-resolution and within the macro expander, so unless you're modifying
     647     * these visitors, you probably do not want to use this function.
     648     */
     649    static std::unique_ptr<MacroInvocation> Builtin (
     650      BuiltinMacro kind, MacroInvocData invoc_data,
     651      std::vector<Attribute> outer_attrs, Location locus,
     652      std::vector<std::unique_ptr<MacroInvocation>> &&pending_eager_invocations
     653      = {},
     654      bool is_semi_coloned = false)
     655    {
     656      return std::unique_ptr<MacroInvocation> (
     657        new MacroInvocation (InvocKind::Builtin,
     658  			   Optional<BuiltinMacro>::some (kind), invoc_data,
     659  			   outer_attrs, locus, is_semi_coloned,
     660  			   std::move (pending_eager_invocations)));
     661    }
     662  
     663    Location get_locus () const override final { return locus; }
     664  
     665    void accept_vis (ASTVisitor &vis) override;
     666  
     667    // Invalid if path is empty, so base stripping on that.
     668    void mark_for_strip () override { invoc_data.mark_for_strip (); }
     669    bool is_marked_for_strip () const override
     670    {
     671      return invoc_data.is_marked_for_strip ();
     672    }
     673  
     674    const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
     675    std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
     676  
     677    void set_outer_attrs (std::vector<Attribute> new_attrs) override
     678    {
     679      outer_attrs = std::move (new_attrs);
     680    }
     681  
     682    NodeId get_pattern_node_id () const override final
     683    {
     684      return ExprWithoutBlock::get_node_id ();
     685    }
     686  
     687    Kind get_ast_kind () const override { return Kind::MACRO_INVOCATION; }
     688  
     689    NodeId get_macro_node_id () const { return node_id; }
     690  
     691    MacroInvocData &get_invoc_data () { return invoc_data; }
     692  
     693    bool has_semicolon () const { return is_semi_coloned; }
     694  
     695    InvocKind get_kind () const { return kind; }
     696    Optional<BuiltinMacro> get_builtin_kind () const { return builtin_kind; }
     697  
     698    /**
     699     * Turn the current MacroInvocation into a builtin macro invocation
     700     */
     701    void map_to_builtin (BuiltinMacro macro)
     702    {
     703      kind = InvocKind::Builtin;
     704      builtin_kind = Optional<BuiltinMacro>::some (macro);
     705    }
     706  
     707    /**
     708     * Get the list of pending macro invcations within the builtin macro
     709     * invocation that should get expanded eagerly.
     710     */
     711    std::vector<std::unique_ptr<MacroInvocation>> &
     712    get_pending_eager_invocations ()
     713    {
     714      rust_assert (kind == InvocKind::Builtin);
     715  
     716      return pending_eager_invocs;
     717    }
     718  
     719  private:
     720    /* Full constructor */
     721    MacroInvocation (
     722      InvocKind kind, Optional<BuiltinMacro> builtin_kind,
     723      MacroInvocData invoc_data, std::vector<Attribute> outer_attrs,
     724      Location locus, bool is_semi_coloned,
     725      std::vector<std::unique_ptr<MacroInvocation>> &&pending_eager_invocs)
     726      : TraitItem (locus), outer_attrs (std::move (outer_attrs)), locus (locus),
     727        node_id (Analysis::Mappings::get ()->get_next_node_id ()),
     728        invoc_data (std::move (invoc_data)), is_semi_coloned (is_semi_coloned),
     729        kind (kind), builtin_kind (builtin_kind),
     730        pending_eager_invocs (std::move (pending_eager_invocs))
     731    {}
     732  
     733    MacroInvocation (const MacroInvocation &other)
     734      : TraitItem (other.locus), outer_attrs (other.outer_attrs),
     735        locus (other.locus), node_id (other.node_id),
     736        invoc_data (other.invoc_data), is_semi_coloned (other.is_semi_coloned),
     737        kind (other.kind), builtin_kind (other.builtin_kind)
     738    {
     739      if (other.kind == InvocKind::Builtin)
     740        for (auto &pending : other.pending_eager_invocs)
     741  	pending_eager_invocs.emplace_back (
     742  	  pending->clone_macro_invocation_impl ());
     743    }
     744  
     745    std::vector<Attribute> outer_attrs;
     746    Location locus;
     747    NodeId node_id;
     748  
     749    /* The data given to the macro invocation */
     750    MacroInvocData invoc_data;
     751  
     752    /* Important for when we actually expand the macro */
     753    bool is_semi_coloned;
     754  
     755    /* Is this a builtin macro or a regular macro */
     756    InvocKind kind;
     757  
     758    /* If it is a builtin macro, which one */
     759    Optional<BuiltinMacro> builtin_kind = Optional<BuiltinMacro>::none ();
     760  
     761    /**
     762     * Pending invocations within a builtin macro invocation. This vector is empty
     763     * and should not be accessed for a regular macro invocation. The macro
     764     * invocations within should be name resolved and expanded before the builtin
     765     * macro invocation get expanded again. It is then the role of the expander to
     766     * insert these new tokens properly in the delimited token tree and try the
     767     * builtin transcriber once again.
     768     */
     769    std::vector<std::unique_ptr<MacroInvocation>> pending_eager_invocs;
     770  
     771  protected:
     772    /* Use covariance to implement clone function as returning this object rather
     773     * than base */
     774    MacroInvocation *clone_pattern_impl () const final override
     775    {
     776      return clone_macro_invocation_impl ();
     777    }
     778  
     779    /* Use covariance to implement clone function as returning this object rather
     780     * than base */
     781    MacroInvocation *clone_expr_without_block_impl () const final override
     782    {
     783      return clone_macro_invocation_impl ();
     784    }
     785  
     786    /* Use covariance to implement clone function as returning this object rather
     787     * than base */
     788    MacroInvocation *clone_type_no_bounds_impl () const final override
     789    {
     790      return clone_macro_invocation_impl ();
     791    }
     792  
     793    MacroInvocation *clone_external_item_impl () const final override
     794    {
     795      return clone_macro_invocation_impl ();
     796    }
     797  
     798    /*virtual*/ MacroInvocation *clone_macro_invocation_impl () const
     799    {
     800      return new MacroInvocation (*this);
     801    }
     802  
     803    Item *clone_item_impl () const override
     804    {
     805      return clone_macro_invocation_impl ();
     806    }
     807  
     808    bool is_item () const override { return !has_semicolon (); }
     809  
     810    TraitItem *clone_trait_item_impl () const override
     811    {
     812      return clone_macro_invocation_impl ();
     813    };
     814  
     815    TraitImplItem *clone_trait_impl_item_impl () const override
     816    {
     817      return clone_macro_invocation_impl ();
     818    };
     819  
     820    InherentImplItem *clone_inherent_impl_item_impl () const override
     821    {
     822      return clone_macro_invocation_impl ();
     823    }
     824  
     825    ExprWithoutBlock *to_stmt () const override
     826  
     827    {
     828      auto new_impl = clone_macro_invocation_impl ();
     829      new_impl->is_semi_coloned = true;
     830  
     831      return new_impl;
     832    }
     833  };
     834  
     835  // more generic meta item path-only form
     836  class MetaItemPath : public MetaItem
     837  {
     838    SimplePath path;
     839  
     840  public:
     841    MetaItemPath (SimplePath path) : path (std::move (path)) {}
     842  
     843    std::string as_string () const override { return path.as_string (); }
     844  
     845    void accept_vis (ASTVisitor &vis) override;
     846  
     847    // HACK: used to simplify parsing - returns non-empty only in this case
     848    SimplePath to_path_item () const override
     849    {
     850      // this should copy construct - TODO ensure it does
     851      return path;
     852    }
     853  
     854    Location get_locus () const override { return path.get_locus (); }
     855  
     856    bool check_cfg_predicate (const Session &session) const override;
     857  
     858    Attribute to_attribute () const override;
     859  
     860  protected:
     861    // Use covariance to implement clone function as returning this type
     862    MetaItemPath *clone_meta_item_inner_impl () const override
     863    {
     864      return new MetaItemPath (*this);
     865    }
     866  };
     867  
     868  // more generic meta item sequence form
     869  class MetaItemSeq : public MetaItem
     870  {
     871    SimplePath path;
     872    std::vector<std::unique_ptr<MetaItemInner>> seq;
     873  
     874  public:
     875    MetaItemSeq (SimplePath path, std::vector<std::unique_ptr<MetaItemInner>> seq)
     876      : path (std::move (path)), seq (std::move (seq))
     877    {}
     878  
     879    // copy constructor with vector clone
     880    MetaItemSeq (const MetaItemSeq &other) : path (other.path)
     881    {
     882      seq.reserve (other.seq.size ());
     883      for (const auto &e : other.seq)
     884        seq.push_back (e->clone_meta_item_inner ());
     885    }
     886  
     887    // overloaded assignment operator with vector clone
     888    MetaItemSeq &operator= (const MetaItemSeq &other)
     889    {
     890      MetaItem::operator= (other);
     891      path = other.path;
     892  
     893      seq.reserve (other.seq.size ());
     894      for (const auto &e : other.seq)
     895        seq.push_back (e->clone_meta_item_inner ());
     896  
     897      return *this;
     898    }
     899  
     900    // default move constructors
     901    MetaItemSeq (MetaItemSeq &&other) = default;
     902    MetaItemSeq &operator= (MetaItemSeq &&other) = default;
     903  
     904    std::string as_string () const override;
     905  
     906    void accept_vis (ASTVisitor &vis) override;
     907  
     908    Location get_locus () const override { return path.get_locus (); }
     909  
     910    bool check_cfg_predicate (const Session &session) const override;
     911  
     912    Attribute to_attribute () const override;
     913  
     914  protected:
     915    // Use covariance to implement clone function as returning this type
     916    MetaItemSeq *clone_meta_item_inner_impl () const override
     917    {
     918      return new MetaItemSeq (*this);
     919    }
     920  };
     921  
     922  // Preferred specialisation for single-identifier meta items.
     923  class MetaWord : public MetaItem
     924  {
     925    Identifier ident;
     926    Location ident_locus;
     927  
     928  public:
     929    MetaWord (Identifier ident, Location ident_locus)
     930      : ident (std::move (ident)), ident_locus (ident_locus)
     931    {}
     932  
     933    std::string as_string () const override { return ident; }
     934  
     935    void accept_vis (ASTVisitor &vis) override;
     936  
     937    Location get_locus () const override { return ident_locus; }
     938  
     939    bool check_cfg_predicate (const Session &session) const override;
     940  
     941    Attribute to_attribute () const override;
     942  
     943  protected:
     944    // Use covariance to implement clone function as returning this type
     945    MetaWord *clone_meta_item_inner_impl () const override
     946    {
     947      return new MetaWord (*this);
     948    }
     949  };
     950  
     951  // Preferred specialisation for "identifier '=' string literal" meta items.
     952  class MetaNameValueStr : public MetaItem
     953  {
     954    Identifier ident;
     955    Location ident_locus;
     956  
     957    // NOTE: str stored without quotes
     958    std::string str;
     959    Location str_locus;
     960  
     961  public:
     962    MetaNameValueStr (Identifier ident, Location ident_locus, std::string str,
     963  		    Location str_locus)
     964      : ident (std::move (ident)), ident_locus (ident_locus),
     965        str (std::move (str)), str_locus (str_locus)
     966    {}
     967  
     968    std::string as_string () const override
     969    {
     970      return ident + " = \"" + str + "\"";
     971    }
     972  
     973    void accept_vis (ASTVisitor &vis) override;
     974  
     975    // HACK: used to simplify parsing - creates a copy of this
     976    std::unique_ptr<MetaNameValueStr> to_meta_name_value_str () const override
     977    {
     978      return std::unique_ptr<MetaNameValueStr> (clone_meta_item_inner_impl ());
     979    }
     980  
     981    Location get_locus () const override { return ident_locus; }
     982  
     983    bool check_cfg_predicate (const Session &session) const override;
     984  
     985    Attribute to_attribute () const override;
     986  
     987    inline std::pair<Identifier, std::string> get_name_value_pair () const
     988    {
     989      return std::pair<Identifier, std::string> (ident, str);
     990    }
     991  
     992    bool is_key_value_pair () const override { return true; }
     993  
     994  protected:
     995    // Use covariance to implement clone function as returning this type
     996    MetaNameValueStr *clone_meta_item_inner_impl () const override
     997    {
     998      return new MetaNameValueStr (*this);
     999    }
    1000  };
    1001  
    1002  // doubles up as MetaListIdents - determine via iterating through each path?
    1003  // Preferred specialisation for "identifier '(' SimplePath, SimplePath, ... ')'"
    1004  class MetaListPaths : public MetaItem
    1005  {
    1006    Identifier ident;
    1007    Location ident_locus;
    1008    std::vector<SimplePath> paths;
    1009  
    1010  public:
    1011    MetaListPaths (Identifier ident, Location ident_locus,
    1012  		 std::vector<SimplePath> paths)
    1013      : ident (std::move (ident)), ident_locus (ident_locus),
    1014        paths (std::move (paths))
    1015    {}
    1016  
    1017    std::string as_string () const override;
    1018  
    1019    void accept_vis (ASTVisitor &vis) override;
    1020  
    1021    Location get_locus () const override { return ident_locus; }
    1022  
    1023    bool check_cfg_predicate (const Session &session) const override;
    1024  
    1025    Attribute to_attribute () const override;
    1026  
    1027  private:
    1028    bool check_path_exists_in_cfg (const Session &session,
    1029  				 const SimplePath &path) const;
    1030  
    1031  protected:
    1032    // Use covariance to implement clone function as returning this type
    1033    MetaListPaths *clone_meta_item_inner_impl () const override
    1034    {
    1035      return new MetaListPaths (*this);
    1036    }
    1037  };
    1038  
    1039  // Preferred specialisation for "identifier '(' MetaNameValueStr, ... ')'"
    1040  class MetaListNameValueStr : public MetaItem
    1041  {
    1042    Identifier ident;
    1043    Location ident_locus;
    1044    std::vector<MetaNameValueStr> strs;
    1045  
    1046  public:
    1047    MetaListNameValueStr (Identifier ident, Location ident_locus,
    1048  			std::vector<MetaNameValueStr> strs)
    1049      : ident (std::move (ident)), ident_locus (ident_locus),
    1050        strs (std::move (strs))
    1051    {}
    1052  
    1053    std::string as_string () const override;
    1054  
    1055    void accept_vis (ASTVisitor &vis) override;
    1056  
    1057    Location get_locus () const override { return ident_locus; }
    1058  
    1059    bool check_cfg_predicate (const Session &session) const override;
    1060  
    1061    Attribute to_attribute () const override;
    1062  
    1063  protected:
    1064    // Use covariance to implement clone function as returning this type
    1065    MetaListNameValueStr *clone_meta_item_inner_impl () const override
    1066    {
    1067      return new MetaListNameValueStr (*this);
    1068    }
    1069  };
    1070  
    1071  // Object that parses macros from a token stream.
    1072  /* TODO: would "AttributeParser" be a better name? MetaItems are only for
    1073   * attributes, I believe */
    1074  struct AttributeParser
    1075  {
    1076  private:
    1077    // TODO: might as well rewrite to use lexer tokens
    1078    std::vector<std::unique_ptr<Token>> token_stream;
    1079    int stream_pos;
    1080  
    1081  public:
    1082    AttributeParser (std::vector<std::unique_ptr<Token>> token_stream,
    1083  		   int stream_start_pos = 0)
    1084      : token_stream (std::move (token_stream)), stream_pos (stream_start_pos)
    1085    {}
    1086  
    1087    ~AttributeParser () = default;
    1088  
    1089    std::vector<std::unique_ptr<MetaItemInner>> parse_meta_item_seq ();
    1090  
    1091  private:
    1092    // Parses a MetaItemInner.
    1093    std::unique_ptr<MetaItemInner> parse_meta_item_inner ();
    1094    // Returns whether token can end a meta item.
    1095    bool is_end_meta_item_tok (TokenId id) const;
    1096    // Parses a simple path.
    1097    SimplePath parse_simple_path ();
    1098    // Parses a segment of a simple path (but not scope resolution operator).
    1099    SimplePathSegment parse_simple_path_segment ();
    1100    // Parses a MetaItemLitExpr.
    1101    std::unique_ptr<MetaItemLitExpr> parse_meta_item_lit ();
    1102    // Parses a literal.
    1103    Literal parse_literal ();
    1104    // Parses a meta item that begins with a simple path.
    1105    std::unique_ptr<MetaItem> parse_path_meta_item ();
    1106  
    1107    // TODO: should this be const?
    1108    std::unique_ptr<Token> &peek_token (int i = 0)
    1109    {
    1110      return token_stream[stream_pos + i];
    1111    }
    1112  
    1113    void skip_token (int i = 0) { stream_pos += 1 + i; }
    1114  };
    1115  } // namespace AST
    1116  } // namespace Rust
    1117  
    1118  /* <https://stackoverflow.com/a/35304501> */
    1119  namespace std {
    1120  template <> struct hash<Rust::AST::MacroFragSpec::Kind>
    1121  {
    1122    size_t operator() (const Rust::AST::MacroFragSpec::Kind &t) const noexcept
    1123    {
    1124      return size_t (t);
    1125    }
    1126  };
    1127  } // namespace std
    1128  
    1129  #endif