LCOV - code coverage report
Current view: top level - gcc/rust/ast - rust-macro.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 77.8 % 329 256
Test Date: 2025-06-21 16:26:05 Functions: 68.8 % 80 55
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

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

Generated by: LCOV version 2.1-beta

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