LCOV - code coverage report
Current view: top level - gcc/rust/ast - rust-macro.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 74.7 % 324 242
Test Date: 2024-12-28 13:16:48 Functions: 64.6 % 79 51
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : // Copyright (C) 2020-2024 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                 :             : #include "rust-macro-builtins.h"
      29                 :             : 
      30                 :             : namespace Rust {
      31                 :             : namespace AST {
      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                 :         676 :   MacroFragSpec (Kind kind) : kind (kind) {}
      54                 :             : 
      55                 :         676 :   static MacroFragSpec get_frag_spec_from_str (const std::string &str)
      56                 :             :   {
      57                 :         676 :     if (str == "block")
      58                 :           2 :       return MacroFragSpec (BLOCK);
      59                 :         674 :     else if (str == "expr")
      60                 :         249 :       return MacroFragSpec (EXPR);
      61                 :         425 :     else if (str == "ident")
      62                 :          69 :       return MacroFragSpec (IDENT);
      63                 :         356 :     else if (str == "item")
      64                 :           3 :       return MacroFragSpec (ITEM);
      65                 :         353 :     else if (str == "lifetime")
      66                 :           0 :       return MacroFragSpec (LIFETIME);
      67                 :         353 :     else if (str == "literal")
      68                 :          88 :       return MacroFragSpec (LITERAL);
      69                 :         265 :     else if (str == "meta")
      70                 :           9 :       return MacroFragSpec (META);
      71                 :         256 :     else if (str == "pat" || str == "pat_param")
      72                 :           7 :       return MacroFragSpec (PAT);
      73                 :         249 :     else if (str == "path")
      74                 :           1 :       return MacroFragSpec (PATH);
      75                 :         248 :     else if (str == "stmt")
      76                 :          52 :       return MacroFragSpec (STMT);
      77                 :         196 :     else if (str == "tt")
      78                 :          34 :       return MacroFragSpec (TT);
      79                 :         162 :     else if (str == "ty")
      80                 :         159 :       return MacroFragSpec (TY);
      81                 :           3 :     else if (str == "vis")
      82                 :           3 :       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                 :        6688 :   Kind get_kind () const { return kind; }
      92                 :         676 :   bool is_error () const { return kind == Kind::INVALID; }
      93                 :             : 
      94                 :             :   // Converts a frag spec enum item to a string form.
      95                 :          13 :   std::string as_string () const
      96                 :             :   {
      97                 :          13 :     switch (kind)
      98                 :             :       {
      99                 :           0 :       case BLOCK:
     100                 :           0 :         return "block";
     101                 :          10 :       case EXPR:
     102                 :          10 :         return "expr";
     103                 :           1 :       case IDENT:
     104                 :           1 :         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                 :           1 :       case TY:
     122                 :           1 :         return "ty";
     123                 :           1 :       case VIS:
     124                 :           1 :         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                 :         175 :   bool has_follow_set_restrictions () const
     133                 :             :   {
     134                 :         175 :     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                 :           6 :   bool has_follow_set_fragment_restrictions () const
     149                 :             :   {
     150                 :           6 :     switch (kind)
     151                 :             :       {
     152                 :             :       case PATH:
     153                 :             :       case PAT:
     154                 :             :       case TY:
     155                 :             :       case VIS:
     156                 :             :         return true;
     157                 :           2 :       default:
     158                 :           2 :         return false;
     159                 :             :       }
     160                 :             :   }
     161                 :             : 
     162                 :             : private:
     163                 :             :   Kind kind;
     164                 :             : };
     165                 :             : 
     166                 :             : // A macro match that has an identifier and fragment spec
     167                 :             : class MacroMatchFragment : public MacroMatch
     168                 :             : {
     169                 :             :   Identifier ident;
     170                 :             :   MacroFragSpec frag_spec;
     171                 :             :   location_t locus;
     172                 :             : 
     173                 :             : public:
     174                 :         676 :   MacroMatchFragment (Identifier ident, MacroFragSpec frag_spec,
     175                 :             :                       location_t locus)
     176                 :         676 :     : 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                 :          12 :   location_t get_match_locus () const override { return locus; };
     195                 :             : 
     196                 :             :   void accept_vis (ASTVisitor &vis) override;
     197                 :             : 
     198                 :        8481 :   MacroMatchType get_macro_match_type () const override
     199                 :             :   {
     200                 :        8481 :     return MacroMatchType::Fragment;
     201                 :             :   }
     202                 :             : 
     203                 :        8196 :   Identifier get_ident () const { return ident; }
     204                 :          15 :   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                 :         666 :   MacroMatchFragment *clone_macro_match_impl () const override
     210                 :             :   {
     211                 :         666 :     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                 :        3277 :   bool has_sep () const { return sep != nullptr; }
     240                 :             : 
     241                 :         351 :   MacroMatchRepetition (std::vector<std::unique_ptr<MacroMatch>> matches,
     242                 :             :                         MacroRepOp op, std::unique_ptr<MacroRepSep> sep,
     243                 :             :                         location_t locus)
     244                 :         351 :     : matches (std::move (matches)), op (op), sep (std::move (sep)),
     245                 :         351 :       locus (locus)
     246                 :             :   {}
     247                 :             : 
     248                 :             :   // Copy constructor with clone
     249                 :         342 :   MacroMatchRepetition (MacroMatchRepetition const &other)
     250                 :         342 :     : op (other.op), locus (other.locus)
     251                 :             :   {
     252                 :             :     // guard to protect from null pointer dereference
     253                 :         342 :     if (other.sep != nullptr)
     254                 :         105 :       sep = other.sep->clone_token ();
     255                 :             : 
     256                 :         342 :     matches.reserve (other.matches.size ());
     257                 :         740 :     for (const auto &e : other.matches)
     258                 :         398 :       matches.push_back (e->clone_macro_match ());
     259                 :         342 :   }
     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                 :        1601 :   location_t get_match_locus () const override { return locus; };
     286                 :             : 
     287                 :             :   void accept_vis (ASTVisitor &vis) override;
     288                 :             : 
     289                 :        1645 :   MacroMatchType get_macro_match_type () const override
     290                 :             :   {
     291                 :        1645 :     return MacroMatchType::Repetition;
     292                 :             :   }
     293                 :             : 
     294                 :        1606 :   MacroRepOp get_op () const { return op; }
     295                 :         254 :   const std::unique_ptr<MacroRepSep> &get_sep () const { return sep; }
     296                 :        3420 :   std::vector<std::unique_ptr<MacroMatch>> &get_matches () { return matches; }
     297                 :             :   const std::vector<std::unique_ptr<MacroMatch>> &get_matches () const
     298                 :             :   {
     299                 :          37 :     return matches;
     300                 :             :   }
     301                 :             : 
     302                 :             : protected:
     303                 :             :   /* Use covariance to implement clone function as returning this object rather
     304                 :             :    * than base */
     305                 :         342 :   MacroMatchRepetition *clone_macro_match_impl () const override
     306                 :             :   {
     307                 :         342 :     return new MacroMatchRepetition (*this);
     308                 :             :   }
     309                 :             : };
     310                 :             : 
     311                 :             : // can't inline due to polymorphism
     312                 :        1712 : 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                 :         866 :   MacroMatcher (DelimType delim_type,
     323                 :             :                 std::vector<std::unique_ptr<MacroMatch>> matches,
     324                 :             :                 location_t locus)
     325                 :         866 :     : delim_type (delim_type), matches (std::move (matches)), locus (locus),
     326                 :         866 :       is_invalid (false)
     327                 :             :   {}
     328                 :             : 
     329                 :             :   // copy constructor with vector clone
     330                 :         953 :   MacroMatcher (MacroMatcher const &other)
     331                 :         953 :     : delim_type (other.delim_type), locus (other.locus)
     332                 :             :   {
     333                 :         953 :     matches.reserve (other.matches.size ());
     334                 :        1988 :     for (const auto &e : other.matches)
     335                 :        1035 :       matches.push_back (e->clone_macro_match ());
     336                 :         953 :   }
     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                 :         865 :   MacroMatcher (MacroMatcher &&other) = default;
     353                 :             :   MacroMatcher &operator= (MacroMatcher &&other) = default;
     354                 :             : 
     355                 :             :   // Creates an error state macro matcher.
     356                 :          27 :   static MacroMatcher create_error (location_t locus)
     357                 :             :   {
     358                 :          27 :     return MacroMatcher (true, locus);
     359                 :             :   }
     360                 :             : 
     361                 :             :   // Returns whether MacroMatcher is in an error state.
     362                 :         880 :   bool is_error () const { return is_invalid; }
     363                 :           3 :   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                 :         133 :   MacroMatchType get_macro_match_type () const override
     370                 :             :   {
     371                 :         133 :     return MacroMatchType::Matcher;
     372                 :             :   }
     373                 :             : 
     374                 :         108 :   DelimType get_delim_type () const { return delim_type; }
     375                 :        4283 :   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                 :          45 :   MacroMatcher *clone_macro_match_impl () const override
     385                 :             :   {
     386                 :          45 :     return new MacroMatcher (*this);
     387                 :             :   }
     388                 :             : 
     389                 :             :   // constructor only used to create error matcher
     390                 :          27 :   MacroMatcher (bool is_invalid, location_t locus)
     391                 :          14 :     : delim_type (PARENS), locus (locus), is_invalid (is_invalid)
     392                 :             :   {}
     393                 :             : };
     394                 :             : 
     395                 :             : // TODO: inline?
     396                 :        1657 : struct MacroTranscriber
     397                 :             : {
     398                 :             : private:
     399                 :             :   DelimTokenTree token_tree;
     400                 :             :   location_t locus;
     401                 :             : 
     402                 :             : public:
     403                 :         833 :   MacroTranscriber (DelimTokenTree token_tree, location_t locus)
     404                 :         820 :     : 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                 :        2822 :   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                 :         832 :   MacroRule (MacroMatcher matcher, MacroTranscriber transcriber,
     425                 :             :              location_t locus)
     426                 :         832 :     : matcher (std::move (matcher)), transcriber (std::move (transcriber)),
     427                 :         832 :       locus (locus)
     428                 :         832 :   {}
     429                 :             : 
     430                 :             :   // Returns whether macro rule is in error state.
     431                 :         814 :   bool is_error () const { return matcher.is_error (); }
     432                 :             : 
     433                 :             :   // Creates an error state macro rule.
     434                 :          13 :   static MacroRule create_error (location_t locus)
     435                 :             :   {
     436                 :          13 :     return MacroRule (MacroMatcher::create_error (locus),
     437                 :          26 :                       MacroTranscriber (DelimTokenTree::create_empty (),
     438                 :          13 :                                         UNDEF_LOCATION),
     439                 :          13 :                       locus);
     440                 :             :   }
     441                 :             : 
     442                 :           2 :   location_t get_locus () const { return locus; }
     443                 :             : 
     444                 :             :   std::string as_string () const;
     445                 :             : 
     446                 :        4145 :   MacroMatcher &get_matcher () { return matcher; }
     447                 :        2820 :   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 &)
     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                 :         687 :   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                 :         687 :     : VisItem (std::move (vis), outer_attrs),
     501                 :        1374 :       outer_attrs (std::move (outer_attrs)), rule_name (std::move (rule_name)),
     502                 :         687 :       delim_type (delim_type), rules (std::move (rules)), locus (locus),
     503                 :         687 :       associated_transcriber (dummy_builtin), is_builtin_rule (false),
     504                 :         687 :       kind (kind)
     505                 :         687 :   {}
     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                 :         645 :   mbe (Identifier rule_name, DelimType delim_type, std::vector<MacroRule> rules,
     522                 :             :        std::vector<Attribute> outer_attrs, location_t locus)
     523                 :             :   {
     524                 :         645 :     return Rust::make_unique<MacroRulesDefinition> (
     525                 :         645 :       MacroRulesDefinition (rule_name, delim_type, rules, outer_attrs, locus,
     526                 :             :                             AST::MacroRulesDefinition::MacroKind::MBE,
     527                 :        1290 :                             AST::Visibility::create_error ()));
     528                 :             :   }
     529                 :             : 
     530                 :             :   static std::unique_ptr<MacroRulesDefinition>
     531                 :          42 :   decl_macro (Identifier rule_name, std::vector<MacroRule> rules,
     532                 :             :               std::vector<Attribute> outer_attrs, location_t locus,
     533                 :             :               Visibility vis)
     534                 :             :   {
     535                 :          42 :     return Rust::make_unique<MacroRulesDefinition> (MacroRulesDefinition (
     536                 :             :       rule_name, AST::DelimType::CURLY, rules, outer_attrs, locus,
     537                 :          84 :       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                 :        5279 :   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                 :       12589 :   std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
     548                 :        2452 :   const std::vector<Attribute> &get_outer_attrs () const override
     549                 :             :   {
     550                 :        2452 :     return outer_attrs;
     551                 :             :   }
     552                 :             : 
     553                 :         642 :   std::vector<MacroRule> &get_macro_rules () { return rules; }
     554                 :             :   const std::vector<MacroRule> &get_macro_rules () const { return rules; }
     555                 :             : 
     556                 :        3451 :   location_t get_locus () const override final { return locus; }
     557                 :             : 
     558                 :        3055 :   Identifier get_rule_name () const { return rule_name; }
     559                 :             : 
     560                 :        2055 :   std::vector<MacroRule> &get_rules () { return rules; }
     561                 :             :   const std::vector<MacroRule> &get_rules () const { return rules; }
     562                 :             : 
     563                 :        2271 :   bool is_builtin () const { return is_builtin_rule; }
     564                 :         218 :   const MacroTranscriberFunc &get_builtin_transcriber () const
     565                 :             :   {
     566                 :         218 :     rust_assert (is_builtin ());
     567                 :         218 :     return associated_transcriber;
     568                 :             :   }
     569                 :         105 :   void set_builtin_transcriber (MacroTranscriberFunc transcriber)
     570                 :             :   {
     571                 :         105 :     associated_transcriber = transcriber;
     572                 :         105 :     is_builtin_rule = true;
     573                 :             :   }
     574                 :             : 
     575                 :        2630 :   AST::Kind get_ast_kind () const override
     576                 :             :   {
     577                 :        2630 :     return AST::Kind::MACRO_RULES_DEFINITION;
     578                 :             :   }
     579                 :             : 
     580                 :          23 :   MacroKind get_kind () const { return kind; }
     581                 :             : 
     582                 :             : protected:
     583                 :             :   /* Use covariance to implement clone function as returning this object rather
     584                 :             :    * than base */
     585                 :          53 :   MacroRulesDefinition *clone_item_impl () const override
     586                 :             :   {
     587                 :          53 :     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                 :           0 :   Pattern::Kind get_pattern_kind () override
     614                 :             :   {
     615                 :           0 :     return Pattern::Kind::MacroInvocation;
     616                 :             :   }
     617                 :             : 
     618                 :             :   /**
     619                 :             :    * The default constructor you should use. Whenever we parse a macro call, we
     620                 :             :    * cannot possibly know whether or not this call refers to a builtin macro or
     621                 :             :    * a regular macro. With name resolution and scopes and nested macro calls,
     622                 :             :    * this is literally impossible. Hence, always start by creating a `Regular`
     623                 :             :    * MacroInvocation which will then (maybe!) become a `Builtin` macro
     624                 :             :    * invocation in the expander.
     625                 :             :    */
     626                 :             :   static std::unique_ptr<MacroInvocation>
     627                 :        2395 :   Regular (MacroInvocData invoc_data, std::vector<Attribute> outer_attrs,
     628                 :             :            location_t locus, bool is_semi_coloned = false)
     629                 :             :   {
     630                 :        2395 :     return std::unique_ptr<MacroInvocation> (
     631                 :             :       new MacroInvocation (InvocKind::Regular, tl::nullopt, invoc_data,
     632                 :        2395 :                            outer_attrs, locus, is_semi_coloned, {}));
     633                 :             :   }
     634                 :             : 
     635                 :             :   /**
     636                 :             :    * Create a builtin macro invocation. This can only be done after macro
     637                 :             :    * name-resolution and within the macro expander, so unless you're modifying
     638                 :             :    * these visitors, you probably do not want to use this function.
     639                 :             :    */
     640                 :           7 :   static std::unique_ptr<MacroInvocation> Builtin (
     641                 :             :     BuiltinMacro kind, MacroInvocData invoc_data,
     642                 :             :     std::vector<Attribute> outer_attrs, location_t locus,
     643                 :             :     std::vector<std::unique_ptr<MacroInvocation>> &&pending_eager_invocations
     644                 :             :     = {},
     645                 :             :     bool is_semi_coloned = false)
     646                 :             :   {
     647                 :           7 :     return std::unique_ptr<MacroInvocation> (
     648                 :             :       new MacroInvocation (InvocKind::Builtin, kind, invoc_data, outer_attrs,
     649                 :             :                            locus, is_semi_coloned,
     650                 :           7 :                            std::move (pending_eager_invocations)));
     651                 :             :   }
     652                 :             : 
     653                 :        2757 :   location_t get_locus () const override final { return locus; }
     654                 :             : 
     655                 :             :   void accept_vis (ASTVisitor &vis) override;
     656                 :             : 
     657                 :             :   // Invalid if path is empty, so base stripping on that.
     658                 :           0 :   void mark_for_strip () override { invoc_data.mark_for_strip (); }
     659                 :        2753 :   bool is_marked_for_strip () const override
     660                 :             :   {
     661                 :        2753 :     return invoc_data.is_marked_for_strip ();
     662                 :             :   }
     663                 :             : 
     664                 :         475 :   const std::vector<Attribute> &get_outer_attrs () const override
     665                 :             :   {
     666                 :         475 :     return outer_attrs;
     667                 :             :   }
     668                 :        6837 :   std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; }
     669                 :             : 
     670                 :           0 :   void set_outer_attrs (std::vector<Attribute> new_attrs) override
     671                 :             :   {
     672                 :           0 :     outer_attrs = std::move (new_attrs);
     673                 :           0 :   }
     674                 :             : 
     675                 :        1704 :   NodeId get_node_id () const override final
     676                 :             :   {
     677                 :        1704 :     return ExprWithoutBlock::get_node_id ();
     678                 :             :   }
     679                 :             : 
     680                 :         230 :   AST::Kind get_ast_kind () const override
     681                 :             :   {
     682                 :         230 :     return AST::Kind::MACRO_INVOCATION;
     683                 :             :   }
     684                 :             : 
     685                 :        7402 :   NodeId get_macro_node_id () const { return node_id; }
     686                 :             : 
     687                 :        4609 :   MacroInvocData &get_invoc_data () { return invoc_data; }
     688                 :             : 
     689                 :        4540 :   bool has_semicolon () const { return is_semi_coloned; }
     690                 :             : 
     691                 :        4548 :   InvocKind get_kind () const { return kind; }
     692                 :             :   tl::optional<BuiltinMacro> get_builtin_kind () const { return builtin_kind; }
     693                 :             : 
     694                 :             :   /**
     695                 :             :    * Turn the current MacroInvocation into a builtin macro invocation
     696                 :             :    */
     697                 :         218 :   void map_to_builtin (BuiltinMacro macro)
     698                 :             :   {
     699                 :         218 :     kind = InvocKind::Builtin;
     700                 :         218 :     builtin_kind = macro;
     701                 :             :   }
     702                 :             : 
     703                 :             :   /**
     704                 :             :    * Get the list of pending macro invcations within the builtin macro
     705                 :             :    * invocation that should get expanded eagerly.
     706                 :             :    */
     707                 :             :   std::vector<std::unique_ptr<MacroInvocation>> &
     708                 :         236 :   get_pending_eager_invocations ()
     709                 :             :   {
     710                 :         236 :     rust_assert (kind == InvocKind::Builtin);
     711                 :             : 
     712                 :         236 :     return pending_eager_invocs;
     713                 :             :   }
     714                 :             : 
     715                 :             : private:
     716                 :             :   /* Full constructor */
     717                 :        2402 :   MacroInvocation (
     718                 :             :     InvocKind kind, tl::optional<BuiltinMacro> builtin_kind,
     719                 :             :     MacroInvocData invoc_data, std::vector<Attribute> outer_attrs,
     720                 :             :     location_t locus, bool is_semi_coloned,
     721                 :             :     std::vector<std::unique_ptr<MacroInvocation>> &&pending_eager_invocs)
     722                 :        4804 :     : TraitItem (locus), outer_attrs (std::move (outer_attrs)), locus (locus),
     723                 :        2402 :       node_id (Analysis::Mappings::get ()->get_next_node_id ()),
     724                 :        2402 :       invoc_data (std::move (invoc_data)), is_semi_coloned (is_semi_coloned),
     725                 :        2402 :       kind (kind), builtin_kind (builtin_kind),
     726                 :        2402 :       pending_eager_invocs (std::move (pending_eager_invocs))
     727                 :        2402 :   {}
     728                 :             : 
     729                 :        9315 :   MacroInvocation (const MacroInvocation &other)
     730                 :       27945 :     : TraitItem (other.locus), ExternalItem (other.node_id),
     731                 :       18630 :       outer_attrs (other.outer_attrs), locus (other.locus),
     732                 :        9315 :       node_id (other.node_id), invoc_data (other.invoc_data),
     733                 :        9315 :       is_semi_coloned (other.is_semi_coloned), kind (other.kind),
     734                 :       18630 :       builtin_kind (other.builtin_kind)
     735                 :             :   {
     736                 :        9315 :     if (other.kind == InvocKind::Builtin)
     737                 :         331 :       for (auto &pending : other.pending_eager_invocs)
     738                 :          69 :         pending_eager_invocs.emplace_back (
     739                 :          69 :           pending->clone_macro_invocation_impl ());
     740                 :        9315 :   }
     741                 :             : 
     742                 :             :   std::vector<Attribute> outer_attrs;
     743                 :             :   location_t locus;
     744                 :             :   NodeId node_id;
     745                 :             : 
     746                 :             :   /* The data given to the macro invocation */
     747                 :             :   MacroInvocData invoc_data;
     748                 :             : 
     749                 :             :   /* Important for when we actually expand the macro */
     750                 :             :   bool is_semi_coloned;
     751                 :             : 
     752                 :             :   /* Is this a builtin macro or a regular macro */
     753                 :             :   InvocKind kind;
     754                 :             : 
     755                 :             :   /* If it is a builtin macro, which one */
     756                 :             :   tl::optional<BuiltinMacro> builtin_kind = tl::nullopt;
     757                 :             : 
     758                 :             :   /**
     759                 :             :    * Pending invocations within a builtin macro invocation. This vector is empty
     760                 :             :    * and should not be accessed for a regular macro invocation. The macro
     761                 :             :    * invocations within should be name resolved and expanded before the builtin
     762                 :             :    * macro invocation get expanded again. It is then the role of the expander to
     763                 :             :    * insert these new tokens properly in the delimited token tree and try the
     764                 :             :    * builtin transcriber once again.
     765                 :             :    */
     766                 :             :   std::vector<std::unique_ptr<MacroInvocation>> pending_eager_invocs;
     767                 :             : 
     768                 :             : protected:
     769                 :             :   /* Use covariance to implement clone function as returning this object rather
     770                 :             :    * than base */
     771                 :           0 :   MacroInvocation *clone_pattern_impl () const final override
     772                 :             :   {
     773                 :           0 :     return clone_macro_invocation_impl ();
     774                 :             :   }
     775                 :             : 
     776                 :             :   /* Use covariance to implement clone function as returning this object rather
     777                 :             :    * than base */
     778                 :           0 :   MacroInvocation *clone_expr_without_block_impl () const final override
     779                 :             :   {
     780                 :           0 :     return clone_macro_invocation_impl ();
     781                 :             :   }
     782                 :             : 
     783                 :             :   /* Use covariance to implement clone function as returning this object rather
     784                 :             :    * than base */
     785                 :           0 :   MacroInvocation *clone_type_no_bounds_impl () const final override
     786                 :             :   {
     787                 :           0 :     return clone_macro_invocation_impl ();
     788                 :             :   }
     789                 :             : 
     790                 :           0 :   MacroInvocation *clone_external_item_impl () const final override
     791                 :             :   {
     792                 :           0 :     return clone_macro_invocation_impl ();
     793                 :             :   }
     794                 :             : 
     795                 :             : public:
     796                 :        9315 :   /*virtual*/ MacroInvocation *clone_macro_invocation_impl () const
     797                 :             :   {
     798                 :        9315 :     return new MacroInvocation (*this);
     799                 :             :   }
     800                 :             : 
     801                 :         397 :   void add_semicolon () override { is_semi_coloned = true; }
     802                 :             : 
     803                 :             : protected:
     804                 :         595 :   Item *clone_item_impl () const override
     805                 :             :   {
     806                 :         595 :     return clone_macro_invocation_impl ();
     807                 :             :   }
     808                 :             : 
     809                 :           0 :   bool is_item () const override { return !has_semicolon (); }
     810                 :             : 
     811                 :           0 :   MacroInvocation *clone_associated_item_impl () const override
     812                 :             :   {
     813                 :           0 :     return clone_macro_invocation_impl ();
     814                 :             :   };
     815                 :             : };
     816                 :             : 
     817                 :             : // more generic meta item path-only form
     818                 :          24 : class MetaItemPath : public MetaItem
     819                 :             : {
     820                 :             :   SimplePath path;
     821                 :             : 
     822                 :             : public:
     823                 :          24 :   MetaItemPath (SimplePath path) : path (std::move (path)) {}
     824                 :             : 
     825                 :           0 :   std::string as_string () const override { return path.as_string (); }
     826                 :             : 
     827                 :             :   void accept_vis (ASTVisitor &vis) override;
     828                 :             : 
     829                 :             :   // HACK: used to simplify parsing - returns non-empty only in this case
     830                 :           0 :   SimplePath to_path_item () const override
     831                 :             :   {
     832                 :             :     // this should copy construct - TODO ensure it does
     833                 :           0 :     return path;
     834                 :             :   }
     835                 :             : 
     836                 :          24 :   SimplePath &get_path () { return path; }
     837                 :             : 
     838                 :           0 :   location_t get_locus () const override { return path.get_locus (); }
     839                 :             : 
     840                 :             :   bool check_cfg_predicate (const Session &session) const override;
     841                 :             : 
     842                 :             :   Attribute to_attribute () const override;
     843                 :             : 
     844                 :           0 :   MetaItem::ItemKind get_item_kind () const override
     845                 :             :   {
     846                 :           0 :     return MetaItem::ItemKind::Path;
     847                 :             :   }
     848                 :             : 
     849                 :             : protected:
     850                 :             :   // Use covariance to implement clone function as returning this type
     851                 :           0 :   MetaItemPath *clone_meta_item_inner_impl () const override
     852                 :             :   {
     853                 :           0 :     return new MetaItemPath (*this);
     854                 :             :   }
     855                 :             : };
     856                 :             : 
     857                 :             : // more generic meta item sequence form
     858                 :             : class MetaItemSeq : public MetaItem
     859                 :             : {
     860                 :             :   SimplePath path;
     861                 :             :   std::vector<std::unique_ptr<MetaItemInner>> seq;
     862                 :             : 
     863                 :             : public:
     864                 :          54 :   MetaItemSeq (SimplePath path, std::vector<std::unique_ptr<MetaItemInner>> seq)
     865                 :          54 :     : path (std::move (path)), seq (std::move (seq))
     866                 :          54 :   {}
     867                 :             : 
     868                 :             :   // copy constructor with vector clone
     869                 :           9 :   MetaItemSeq (const MetaItemSeq &other) : path (other.path)
     870                 :             :   {
     871                 :           9 :     seq.reserve (other.seq.size ());
     872                 :          20 :     for (const auto &e : other.seq)
     873                 :          11 :       seq.push_back (e->clone_meta_item_inner ());
     874                 :           9 :   }
     875                 :             : 
     876                 :             :   // overloaded assignment operator with vector clone
     877                 :             :   MetaItemSeq &operator= (const MetaItemSeq &other)
     878                 :             :   {
     879                 :             :     MetaItem::operator= (other);
     880                 :             :     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                 :             :     return *this;
     887                 :             :   }
     888                 :             : 
     889                 :             :   // default move constructors
     890                 :             :   MetaItemSeq (MetaItemSeq &&other) = default;
     891                 :             :   MetaItemSeq &operator= (MetaItemSeq &&other) = default;
     892                 :             : 
     893                 :             :   std::string as_string () const override;
     894                 :             : 
     895                 :           0 :   SimplePath &get_path () { return path; }
     896                 :             : 
     897                 :           0 :   std::vector<std::unique_ptr<MetaItemInner>> &get_seq () { return seq; }
     898                 :             : 
     899                 :             :   void accept_vis (ASTVisitor &vis) override;
     900                 :             : 
     901                 :           0 :   location_t get_locus () const override { return path.get_locus (); }
     902                 :             : 
     903                 :             :   bool check_cfg_predicate (const Session &session) const override;
     904                 :             : 
     905                 :             :   Attribute to_attribute () const override;
     906                 :             : 
     907                 :           0 :   MetaItem::ItemKind get_item_kind () const override
     908                 :             :   {
     909                 :           0 :     return MetaItem::ItemKind::Seq;
     910                 :             :   }
     911                 :             : 
     912                 :             : protected:
     913                 :             :   // Use covariance to implement clone function as returning this type
     914                 :           9 :   MetaItemSeq *clone_meta_item_inner_impl () const override
     915                 :             :   {
     916                 :           9 :     return new MetaItemSeq (*this);
     917                 :             :   }
     918                 :             : };
     919                 :             : 
     920                 :             : // Preferred specialisation for single-identifier meta items.
     921                 :         158 : class MetaWord : public MetaItem
     922                 :             : {
     923                 :             :   Identifier ident;
     924                 :             :   location_t ident_locus;
     925                 :             : 
     926                 :             : public:
     927                 :         601 :   MetaWord (Identifier ident, location_t ident_locus)
     928                 :         601 :     : ident (std::move (ident)), ident_locus (ident_locus)
     929                 :             :   {}
     930                 :             : 
     931                 :         535 :   std::string as_string () const override { return ident.as_string (); }
     932                 :             : 
     933                 :             :   void accept_vis (ASTVisitor &vis) override;
     934                 :             : 
     935                 :             :   Identifier &get_ident () { return ident; }
     936                 :             : 
     937                 :           3 :   location_t 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                 :          24 :   MetaItem::ItemKind get_item_kind () const override
     944                 :             :   {
     945                 :          24 :     return MetaItem::ItemKind::Word;
     946                 :             :   }
     947                 :             : 
     948                 :             : protected:
     949                 :             :   // Use covariance to implement clone function as returning this type
     950                 :          79 :   MetaWord *clone_meta_item_inner_impl () const override
     951                 :             :   {
     952                 :          79 :     return new MetaWord (*this);
     953                 :             :   }
     954                 :             : };
     955                 :             : 
     956                 :             : // Preferred specialisation for "identifier '=' string literal" meta items.
     957                 :             : class MetaNameValueStr : public MetaItem
     958                 :             : {
     959                 :             :   Identifier ident;
     960                 :             :   location_t ident_locus;
     961                 :             : 
     962                 :             :   // NOTE: str stored without quotes
     963                 :             :   std::string str;
     964                 :             :   location_t str_locus;
     965                 :             : 
     966                 :             : public:
     967                 :         163 :   MetaNameValueStr (Identifier ident, location_t ident_locus, std::string str,
     968                 :             :                     location_t str_locus)
     969                 :         326 :     : ident (std::move (ident)), ident_locus (ident_locus),
     970                 :         163 :       str (std::move (str)), str_locus (str_locus)
     971                 :         163 :   {}
     972                 :             : 
     973                 :         407 :   std::string as_string () const override
     974                 :             :   {
     975                 :         814 :     return ident.as_string () + " = \"" + str + "\"";
     976                 :             :   }
     977                 :             : 
     978                 :             :   void accept_vis (ASTVisitor &vis) override;
     979                 :             : 
     980                 :             :   // HACK: used to simplify parsing - creates a copy of this
     981                 :           4 :   std::unique_ptr<MetaNameValueStr> to_meta_name_value_str () const override
     982                 :             :   {
     983                 :           4 :     return std::unique_ptr<MetaNameValueStr> (clone_meta_item_inner_impl ());
     984                 :             :   }
     985                 :             : 
     986                 :           3 :   location_t get_locus () const override { return ident_locus; }
     987                 :             : 
     988                 :             :   bool check_cfg_predicate (const Session &session) const override;
     989                 :             : 
     990                 :             :   Attribute to_attribute () const override;
     991                 :             : 
     992                 :          26 :   inline std::pair<Identifier, std::string> get_name_value_pair () const
     993                 :             :   {
     994                 :          26 :     return std::pair<Identifier, std::string> (ident, str);
     995                 :             :   }
     996                 :             : 
     997                 :          21 :   bool is_key_value_pair () const override { return true; }
     998                 :             : 
     999                 :           0 :   MetaItem::ItemKind get_item_kind () const override
    1000                 :             :   {
    1001                 :           0 :     return MetaItem::ItemKind::NameValueStr;
    1002                 :             :   }
    1003                 :             : 
    1004                 :             : protected:
    1005                 :             :   // Use covariance to implement clone function as returning this type
    1006                 :         559 :   MetaNameValueStr *clone_meta_item_inner_impl () const override
    1007                 :             :   {
    1008                 :         559 :     return new MetaNameValueStr (*this);
    1009                 :             :   }
    1010                 :             : };
    1011                 :             : 
    1012                 :             : // doubles up as MetaListIdents - determine via iterating through each path?
    1013                 :             : // Preferred specialisation for "identifier '(' SimplePath, SimplePath, ... ')'"
    1014                 :             : class MetaListPaths : public MetaItem
    1015                 :             : {
    1016                 :             :   Identifier ident;
    1017                 :             :   location_t ident_locus;
    1018                 :             :   std::vector<SimplePath> paths;
    1019                 :             : 
    1020                 :             : public:
    1021                 :           0 :   MetaListPaths (Identifier ident, location_t ident_locus,
    1022                 :             :                  std::vector<SimplePath> paths)
    1023                 :           0 :     : ident (std::move (ident)), ident_locus (ident_locus),
    1024                 :           0 :       paths (std::move (paths))
    1025                 :           0 :   {}
    1026                 :             : 
    1027                 :             :   std::string as_string () const override;
    1028                 :             : 
    1029                 :             :   void accept_vis (ASTVisitor &vis) override;
    1030                 :             : 
    1031                 :           0 :   Identifier get_ident () const { return ident; }
    1032                 :             : 
    1033                 :           0 :   std::vector<SimplePath> &get_paths () { return paths; };
    1034                 :             : 
    1035                 :           0 :   location_t get_locus () const override { return ident_locus; }
    1036                 :             : 
    1037                 :             :   bool check_cfg_predicate (const Session &session) const override;
    1038                 :             : 
    1039                 :             :   Attribute to_attribute () const override;
    1040                 :             : 
    1041                 :           0 :   MetaItem::ItemKind get_item_kind () const override
    1042                 :             :   {
    1043                 :           0 :     return MetaItem::ItemKind::ListPaths;
    1044                 :             :   }
    1045                 :             : 
    1046                 :             : private:
    1047                 :             :   bool check_path_exists_in_cfg (const Session &session,
    1048                 :             :                                  const SimplePath &path) const;
    1049                 :             : 
    1050                 :             : protected:
    1051                 :             :   // Use covariance to implement clone function as returning this type
    1052                 :           0 :   MetaListPaths *clone_meta_item_inner_impl () const override
    1053                 :             :   {
    1054                 :           0 :     return new MetaListPaths (*this);
    1055                 :             :   }
    1056                 :             : };
    1057                 :             : 
    1058                 :             : // Preferred specialisation for "identifier '(' MetaNameValueStr, ... ')'"
    1059                 :             : class MetaListNameValueStr : public MetaItem
    1060                 :             : {
    1061                 :             :   Identifier ident;
    1062                 :             :   location_t ident_locus;
    1063                 :             :   std::vector<MetaNameValueStr> strs;
    1064                 :             : 
    1065                 :             : public:
    1066                 :           0 :   MetaListNameValueStr (Identifier ident, location_t ident_locus,
    1067                 :             :                         std::vector<MetaNameValueStr> strs)
    1068                 :           0 :     : ident (std::move (ident)), ident_locus (ident_locus),
    1069                 :           0 :       strs (std::move (strs))
    1070                 :           0 :   {}
    1071                 :             : 
    1072                 :             :   std::string as_string () const override;
    1073                 :             : 
    1074                 :             :   void accept_vis (ASTVisitor &vis) override;
    1075                 :             : 
    1076                 :           0 :   Identifier get_ident () { return ident; }
    1077                 :             : 
    1078                 :           0 :   std::vector<MetaNameValueStr> &get_values () { return strs; }
    1079                 :             : 
    1080                 :           0 :   location_t get_locus () const override { return ident_locus; }
    1081                 :             : 
    1082                 :             :   bool check_cfg_predicate (const Session &session) const override;
    1083                 :             : 
    1084                 :             :   Attribute to_attribute () const override;
    1085                 :             : 
    1086                 :           0 :   MetaItem::ItemKind get_item_kind () const override
    1087                 :             :   {
    1088                 :           0 :     return MetaItem::ItemKind::ListNameValueStr;
    1089                 :             :   }
    1090                 :             : 
    1091                 :             : protected:
    1092                 :             :   // Use covariance to implement clone function as returning this type
    1093                 :           0 :   MetaListNameValueStr *clone_meta_item_inner_impl () const override
    1094                 :             :   {
    1095                 :           0 :     return new MetaListNameValueStr (*this);
    1096                 :             :   }
    1097                 :             : };
    1098                 :             : 
    1099                 :             : // Object that parses macros from a token stream.
    1100                 :             : /* TODO: would "AttributeParser" be a better name? MetaItems are only for
    1101                 :             :  * attributes, I believe */
    1102                 :             : struct AttributeParser
    1103                 :             : {
    1104                 :             : private:
    1105                 :             :   // TODO: might as well rewrite to use lexer tokens
    1106                 :             :   std::vector<std::unique_ptr<Token>> token_stream;
    1107                 :             :   int stream_pos;
    1108                 :             : 
    1109                 :             : public:
    1110                 :         750 :   AttributeParser (std::vector<std::unique_ptr<Token>> token_stream,
    1111                 :             :                    int stream_start_pos = 0)
    1112                 :         750 :     : token_stream (std::move (token_stream)), stream_pos (stream_start_pos)
    1113                 :             :   {}
    1114                 :             : 
    1115                 :         750 :   ~AttributeParser () = default;
    1116                 :             : 
    1117                 :             :   std::vector<std::unique_ptr<MetaItemInner>> parse_meta_item_seq ();
    1118                 :             : 
    1119                 :             : private:
    1120                 :             :   // Parses a MetaItemInner.
    1121                 :             :   std::unique_ptr<MetaItemInner> parse_meta_item_inner ();
    1122                 :             :   // Returns whether token can end a meta item.
    1123                 :             :   bool is_end_meta_item_tok (TokenId id) const;
    1124                 :             :   // Parses a simple path.
    1125                 :             :   SimplePath parse_simple_path ();
    1126                 :             :   // Parses a segment of a simple path (but not scope resolution operator).
    1127                 :             :   SimplePathSegment parse_simple_path_segment ();
    1128                 :             :   // Parses a MetaItemLitExpr.
    1129                 :             :   std::unique_ptr<MetaItemLitExpr> parse_meta_item_lit ();
    1130                 :             :   // Parses a literal.
    1131                 :             :   Literal parse_literal ();
    1132                 :             :   // Parses a meta item that begins with a simple path.
    1133                 :             :   std::unique_ptr<MetaItem> parse_path_meta_item ();
    1134                 :             : 
    1135                 :             :   // TODO: should this be const?
    1136                 :        6811 :   std::unique_ptr<Token> &peek_token (int i = 0)
    1137                 :             :   {
    1138                 :        4793 :     return token_stream[stream_pos + i];
    1139                 :             :   }
    1140                 :             : 
    1141                 :        2496 :   void skip_token (int i = 0) { stream_pos += 1 + i; }
    1142                 :             : };
    1143                 :             : } // namespace AST
    1144                 :             : } // namespace Rust
    1145                 :             : 
    1146                 :             : /* <https://stackoverflow.com/a/35304501> */
    1147                 :             : namespace std {
    1148                 :             : template <> struct hash<Rust::AST::MacroFragSpec::Kind>
    1149                 :             : {
    1150                 :        1327 :   size_t operator() (const Rust::AST::MacroFragSpec::Kind &t) const noexcept
    1151                 :             :   {
    1152                 :        1327 :     return size_t (t);
    1153                 :             :   }
    1154                 :             : };
    1155                 :             : } // namespace std
    1156                 :             : 
    1157                 :             : #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.