LCOV - code coverage report
Current view: top level - gcc/rust/expand - rust-cfg-strip.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 71.4 % 1162 830
Test Date: 2026-02-28 14:20:25 Functions: 94.3 % 123 116
Legend: Lines:     hit not hit

            Line data    Source code
       1              : // Copyright (C) 2020-2026 Free Software Foundation, Inc.
       2              : 
       3              : // This file is part of GCC.
       4              : 
       5              : // GCC is free software; you can redistribute it and/or modify it under
       6              : // the terms of the GNU General Public License as published by the Free
       7              : // Software Foundation; either version 3, or (at your option) any later
       8              : // version.
       9              : 
      10              : // GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11              : // WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12              : // FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13              : // for more details.
      14              : 
      15              : // You should have received a copy of the GNU General Public License
      16              : // along with GCC; see the file COPYING3.  If not see
      17              : // <http://www.gnu.org/licenses/>.
      18              : 
      19              : #include "rust-cfg-strip.h"
      20              : #include "rust-ast-full.h"
      21              : #include "rust-ast-visitor.h"
      22              : #include "rust-path.h"
      23              : #include "rust-session-manager.h"
      24              : #include "rust-attribute-values.h"
      25              : #include "rust-macro-expand.h"
      26              : 
      27              : namespace Rust {
      28              : 
      29              : /**
      30              :  * Determines whether any cfg predicate is false and hence item with attributes
      31              :  * should be stripped. Note that attributes must be expanded before calling.
      32              :  */
      33              : bool
      34            0 : CfgStrip::fails_cfg (const AST::AttrVec &attrs) const
      35              : {
      36            0 :   auto &session = Session::get_instance ();
      37              : 
      38            0 :   for (const auto &attr : attrs)
      39              :     {
      40            0 :       if (attr.get_path () == Values::Attributes::CFG
      41            0 :           && !attr.check_cfg_predicate (session))
      42              :         return true;
      43            0 :       else if (!expansion_cfg.should_test
      44            0 :                && attr.get_path () == Values::Attributes::TEST)
      45              :         return true;
      46              :     }
      47              :   return false;
      48              : }
      49              : 
      50              : /**
      51              :  * Determines whether any cfg predicate is false and hence item with attributes
      52              :  * should be stripped. Will expand attributes as well.
      53              :  */
      54              : bool
      55      1771029 : CfgStrip::fails_cfg_with_expand (AST::AttrVec &attrs) const
      56              : {
      57      1771029 :   auto &session = Session::get_instance ();
      58              : 
      59              :   // TODO: maybe have something that strips cfg attributes that evaluate true?
      60      1871185 :   for (auto &attr : attrs)
      61              :     {
      62       100269 :       if (attr.get_path () == Values::Attributes::CFG)
      63              :         {
      64         2116 :           if (!attr.is_parsed_to_meta_item ())
      65          479 :             attr.parse_attr_to_meta_item ();
      66              : 
      67              :           // DEBUG
      68         2116 :           if (!attr.is_parsed_to_meta_item ())
      69            1 :             rust_debug ("failed to parse attr to meta item, right before "
      70              :                         "cfg predicate check");
      71              :           else
      72         2115 :             rust_debug ("attr has been successfully parsed to meta item, "
      73              :                         "right before cfg predicate check");
      74              : 
      75         2116 :           if (!attr.check_cfg_predicate (session))
      76              :             {
      77              :               // DEBUG
      78          112 :               rust_debug (
      79              :                 "cfg predicate failed for attribute: \033[0;31m'%s'\033[0m",
      80              :                 attr.as_string ().c_str ());
      81              : 
      82          112 :               return true;
      83              :             }
      84              :           else
      85              :             {
      86              :               // DEBUG
      87         2004 :               rust_debug ("cfg predicate succeeded for attribute: "
      88              :                           "\033[0;31m'%s'\033[0m",
      89              :                           attr.as_string ().c_str ());
      90              :             }
      91              :         }
      92        98153 :       else if (!expansion_cfg.should_test
      93       196306 :                && attr.get_path () == Values::Attributes::TEST)
      94              :         return true;
      95              :     }
      96              :   return false;
      97              : }
      98              : 
      99              : /**
     100              :  * Expands cfg_attr attributes.
     101              :  */
     102              : void
     103      1771029 : expand_cfg_attrs (AST::AttrVec &attrs)
     104              : {
     105      1771029 :   auto &session = Session::get_instance ();
     106              : 
     107      1871306 :   for (std::size_t i = 0; i < attrs.size (); i++)
     108              :     {
     109       100277 :       auto &attr = attrs[i];
     110       100277 :       if (attr.get_path () == Values::Attributes::CFG_ATTR)
     111              :         {
     112           23 :           if (!attr.is_parsed_to_meta_item ())
     113           16 :             attr.parse_attr_to_meta_item ();
     114              : 
     115           23 :           if (attr.check_cfg_predicate (session))
     116              :             {
     117              :               // split off cfg_attr
     118            8 :               AST::AttrVec new_attrs = attr.separate_cfg_attrs ();
     119              : 
     120              :               // remove attr from vector
     121            8 :               attrs.erase (attrs.begin () + i);
     122              : 
     123              :               // add new attrs to vector
     124            8 :               attrs.insert (attrs.begin () + i,
     125              :                             std::make_move_iterator (new_attrs.begin ()),
     126              :                             std::make_move_iterator (new_attrs.end ()));
     127              : 
     128              :               /* Decrement i so that the for loop's i++ will bring us back to
     129              :                * position i, allowing us to reprocess the newly inserted
     130              :                * attribute (in case it's also a cfg_attr that needs expansion)
     131              :                */
     132            8 :               i--;
     133            8 :             }
     134              : 
     135              :           /* do something - if feature (first token in tree) is in fact enabled,
     136              :            * make tokens listed afterwards into attributes. i.e.: for
     137              :            * [cfg_attr(feature = "wow", wow1, wow2)], if "wow" is true, then add
     138              :            * attributes [wow1] and [wow2] to attribute list. This can also be
     139              :            * recursive, so check for expanded attributes being recursive and
     140              :            * possibly recursively call the expand_attrs? */
     141              :         }
     142              :     }
     143      1771029 :   attrs.shrink_to_fit ();
     144      1771029 : }
     145              : 
     146              : void
     147        10411 : CfgStrip::go (AST::Crate &crate)
     148              : {
     149        10411 :   visit (crate);
     150        10411 : }
     151              : 
     152              : void
     153        10411 : CfgStrip::visit (AST::Crate &crate)
     154              : {
     155              :   // expand crate cfg_attr attributes
     156        10411 :   expand_cfg_attrs (crate.inner_attrs);
     157              : 
     158        10411 :   if (fails_cfg_with_expand (crate.inner_attrs))
     159              :     {
     160              :       // basically, delete whole crate
     161            1 :       crate.strip_crate ();
     162              :       // TODO: maybe create warning here? probably not desired behaviour
     163              :     }
     164              : 
     165        10411 :   auto &items = crate.items;
     166              : 
     167        10411 :   AST::DefaultASTVisitor::visit (crate);
     168        55566 :   for (auto it = items.begin (); it != items.end ();)
     169              :     {
     170        45155 :       auto &item = *it;
     171        45155 :       if (item->is_marked_for_strip ())
     172           19 :         it = items.erase (it);
     173              :       else
     174        45136 :         it++;
     175              :     }
     176              :   // expand module attributes?
     177        10411 : }
     178              : 
     179              : // Visitor used to expand attributes.
     180              : void
     181         4734 : CfgStrip::maybe_strip_struct_fields (std::vector<AST::StructField> &fields)
     182              : {
     183        10520 :   for (auto it = fields.begin (); it != fields.end ();)
     184              :     {
     185         5786 :       auto &field = *it;
     186              : 
     187         5786 :       auto &field_attrs = field.get_outer_attrs ();
     188         5786 :       expand_cfg_attrs (field_attrs);
     189         5786 :       if (fails_cfg_with_expand (field_attrs))
     190              :         {
     191            1 :           it = fields.erase (it);
     192            1 :           continue;
     193              :         }
     194              : 
     195              :       // expand sub-types of type, but can't strip type itself
     196         5785 :       auto &type = field.get_field_type ();
     197         5785 :       type.accept_vis (*this);
     198              : 
     199         5785 :       if (type.is_marked_for_strip ())
     200            0 :         rust_error_at (type.get_locus (), "cannot strip type in this position");
     201              : 
     202              :       // if nothing else happens, increment
     203         5785 :       ++it;
     204              :     }
     205         4734 : }
     206              : 
     207              : void
     208         5732 : CfgStrip::maybe_strip_struct_expr_fields (
     209              :   std::vector<std::unique_ptr<AST::StructExprField>> &fields)
     210              : {
     211        15993 :   for (auto it = fields.begin (); it != fields.end ();)
     212              :     {
     213        10261 :       auto &field = *it;
     214              : 
     215        10261 :       auto &field_attrs = field->get_outer_attrs ();
     216        10261 :       expand_cfg_attrs (field_attrs);
     217        10261 :       if (fails_cfg_with_expand (field_attrs))
     218              :         {
     219            1 :           it = fields.erase (it);
     220            1 :           continue;
     221              :         }
     222              : 
     223        10260 :       ++it;
     224              :     }
     225         5732 : }
     226              : 
     227              : void
     228         4704 : CfgStrip::maybe_strip_tuple_fields (std::vector<AST::TupleField> &fields)
     229              : {
     230        12197 :   for (auto it = fields.begin (); it != fields.end ();)
     231              :     {
     232         7493 :       auto &field = *it;
     233              : 
     234         7493 :       auto &field_attrs = field.get_outer_attrs ();
     235         7493 :       expand_cfg_attrs (field_attrs);
     236         7493 :       if (fails_cfg_with_expand (field_attrs))
     237              :         {
     238            0 :           it = fields.erase (it);
     239            0 :           continue;
     240              :         }
     241              : 
     242              :       // expand sub-types of type, but can't strip type itself
     243         7493 :       auto &type = field.get_field_type ();
     244         7493 :       type.accept_vis (*this);
     245         7493 :       if (type.is_marked_for_strip ())
     246            0 :         rust_error_at (type.get_locus (), "cannot strip type in this position");
     247              : 
     248              :       // if nothing else happens, increment
     249         7493 :       ++it;
     250              :     }
     251         4704 : }
     252              : 
     253              : void
     254        67551 : CfgStrip::maybe_strip_function_params (
     255              :   std::vector<std::unique_ptr<AST::Param>> &params)
     256              : {
     257       151978 :   for (auto it = params.begin (); it != params.end ();)
     258              :     {
     259        84427 :       if (!(*it)->is_self () && !(*it)->is_variadic ())
     260              :         {
     261        43016 :           auto param = static_cast<AST::FunctionParam *> (it->get ());
     262              : 
     263        43016 :           auto &param_attrs = param->get_outer_attrs ();
     264        43016 :           expand_cfg_attrs (param_attrs);
     265        43016 :           if (fails_cfg_with_expand (param_attrs))
     266              :             {
     267            0 :               it = params.erase (it);
     268            0 :               continue;
     269              :             }
     270              : 
     271              :           // TODO: should an unwanted strip lead to break out of loop?
     272        43016 :           auto &pattern = param->get_pattern ();
     273        43016 :           pattern.accept_vis (*this);
     274        43016 :           if (pattern.is_marked_for_strip ())
     275            0 :             rust_error_at (pattern.get_locus (),
     276              :                            "cannot strip pattern in this position");
     277              : 
     278        43016 :           auto &type = param->get_type ();
     279        43016 :           type.accept_vis (*this);
     280              : 
     281        43016 :           if (type.is_marked_for_strip ())
     282            0 :             rust_error_at (type.get_locus (),
     283              :                            "cannot strip type in this position");
     284              :         }
     285              :       // increment
     286        84427 :       ++it;
     287              :     }
     288        67551 : }
     289              : 
     290              : void
     291        20635 : CfgStrip::maybe_strip_generic_args (AST::GenericArgs &args)
     292              : {
     293              :   // lifetime args can't be expanded
     294              :   // FIXME: Can we have macro invocations for lifetimes?
     295              : 
     296              :   // expand type args - strip sub-types only
     297        42008 :   for (auto &arg : args.get_generic_args ())
     298              :     {
     299        21373 :       switch (arg.get_kind ())
     300              :         {
     301         9435 :         case AST::GenericArg::Kind::Type:
     302         9435 :           {
     303         9435 :             auto &type = arg.get_type ();
     304         9435 :             type.accept_vis (*this);
     305              : 
     306         9435 :             if (type.is_marked_for_strip ())
     307            0 :               rust_error_at (type.get_locus (),
     308              :                              "cannot strip type in this position");
     309              :             break;
     310              :           }
     311          392 :         case AST::GenericArg::Kind::Const:
     312          392 :           {
     313          392 :             auto &expr = arg.get_expression ();
     314          392 :             expr.accept_vis (*this);
     315              : 
     316          392 :             if (expr.is_marked_for_strip ())
     317            0 :               rust_error_at (expr.get_locus (),
     318              :                              "cannot strip expression in this position");
     319              :             break;
     320              :           }
     321              :         default:
     322              :           break;
     323              :           // FIXME: Figure out what to do here if there is ambiguity. Since the
     324              :           // resolver comes after the expansion, we need to figure out a way to
     325              :           // strip ambiguous values here
     326              :           // TODO: Arthur: Probably add a `mark_as_strip` method to `GenericArg`
     327              :           // or something. This would clean up this whole thing
     328              :         }
     329              :     }
     330              : 
     331              :   // FIXME: Can we have macro invocations in generic type bindings?
     332              :   // expand binding args - strip sub-types only
     333        20967 :   for (auto &binding : args.get_binding_args ())
     334              :     {
     335          332 :       auto &type = binding.get_type ();
     336          332 :       type.accept_vis (*this);
     337              : 
     338          332 :       if (type.is_marked_for_strip ())
     339            0 :         rust_error_at (type.get_locus (), "cannot strip type in this position");
     340              :     }
     341        20635 : }
     342              : 
     343              : void
     344         1779 : CfgStrip::maybe_strip_qualified_path_type (AST::QualifiedPathType &path_type)
     345              : {
     346         1779 :   auto &type = path_type.get_type ();
     347         1779 :   type.accept_vis (*this);
     348              : 
     349         1779 :   if (type.is_marked_for_strip ())
     350            0 :     rust_error_at (type.get_locus (), "cannot strip type in this position");
     351              : 
     352         1779 :   if (path_type.has_as_clause ())
     353              :     {
     354         1589 :       auto &type_path = path_type.get_as_type_path ();
     355         1589 :       visit (type_path);
     356         1589 :       if (type_path.is_marked_for_strip ())
     357            0 :         rust_error_at (type_path.get_locus (),
     358              :                        "cannot strip type path in this position");
     359              :     }
     360         1779 : }
     361              : 
     362              : void
     363          250 : CfgStrip::CfgStrip::maybe_strip_closure_params (
     364              :   std::vector<AST::ClosureParam> &params)
     365              : {
     366          500 :   for (auto it = params.begin (); it != params.end ();)
     367              :     {
     368          250 :       auto &param = *it;
     369              : 
     370          250 :       auto &param_attrs = param.get_outer_attrs ();
     371          250 :       expand_cfg_attrs (param_attrs);
     372          250 :       if (fails_cfg_with_expand (param_attrs))
     373              :         {
     374            0 :           it = params.erase (it);
     375            0 :           continue;
     376              :         }
     377              : 
     378          250 :       auto &pattern = param.get_pattern ();
     379          250 :       pattern.accept_vis (*this);
     380          250 :       if (pattern.is_marked_for_strip ())
     381            0 :         rust_error_at (pattern.get_locus (),
     382              :                        "cannot strip pattern in this position");
     383              : 
     384          250 :       if (param.has_type_given ())
     385              :         {
     386          232 :           auto &type = param.get_type ();
     387          232 :           type.accept_vis (*this);
     388              : 
     389          232 :           if (type.is_marked_for_strip ())
     390            0 :             rust_error_at (type.get_locus (),
     391              :                            "cannot strip type in this position");
     392              :         }
     393              : 
     394              :       // increment if found nothing else so far
     395          250 :       ++it;
     396              :     }
     397          250 : }
     398              : 
     399              : void
     400            0 : CfgStrip::maybe_strip_where_clause (AST::WhereClause &where_clause)
     401              : {
     402              :   // items cannot be stripped conceptually, so just accept visitor
     403            0 :   for (auto &item : where_clause.get_items ())
     404            0 :     item->accept_vis (*this);
     405            0 : }
     406              : 
     407              : void
     408       207976 : CfgStrip::visit (AST::IdentifierExpr &ident_expr)
     409              : {
     410              :   // strip test based on outer attrs
     411       207976 :   AST::DefaultASTVisitor::visit (ident_expr);
     412       207976 :   expand_cfg_attrs (ident_expr.get_outer_attrs ());
     413       207976 :   if (fails_cfg_with_expand (ident_expr.get_outer_attrs ()))
     414              :     {
     415            0 :       ident_expr.mark_for_strip ();
     416            0 :       return;
     417              :     }
     418              : }
     419              : 
     420              : void
     421         4583 : CfgStrip::visit (AST::MacroInvocation &macro_invoc)
     422              : {
     423              :   // initial strip test based on outer attrs
     424         4583 :   expand_cfg_attrs (macro_invoc.get_outer_attrs ());
     425         4583 :   if (fails_cfg_with_expand (macro_invoc.get_outer_attrs ()))
     426              :     {
     427            0 :       macro_invoc.mark_for_strip ();
     428            0 :       return;
     429              :     }
     430              : 
     431              :   // can't strip simple path
     432              : 
     433              :   // I don't think any macro token trees can be stripped in any way
     434              : 
     435              :   // TODO: maybe have cfg! macro stripping behaviour here?
     436              : }
     437              : 
     438              : void
     439       160455 : CfgStrip::visit (AST::PathInExpression &path)
     440              : {
     441              :   // initial strip test based on outer attrs
     442       160455 :   expand_cfg_attrs (path.get_outer_attrs ());
     443       160455 :   if (fails_cfg_with_expand (path.get_outer_attrs ()))
     444              :     {
     445            0 :       path.mark_for_strip ();
     446            0 :       return;
     447              :     }
     448              : 
     449       160455 :   if (!path.is_lang_item ())
     450              :     {
     451       382616 :       for (auto &segment : path.get_segments ())
     452              :         {
     453       445318 :           if (segment.has_generic_args ())
     454         7105 :             maybe_strip_generic_args (segment.get_generic_args ());
     455              :         }
     456              :     }
     457              : }
     458              : 
     459              : void
     460        13446 : CfgStrip::visit (AST::TypePathSegmentGeneric &segment)
     461              : {
     462              :   // TODO: strip inside generic args
     463              : 
     464        13446 :   if (!segment.has_generic_args ())
     465              :     return;
     466              : 
     467        13442 :   maybe_strip_generic_args (segment.get_generic_args ());
     468              : }
     469              : void
     470           78 : CfgStrip::visit (AST::TypePathSegmentFunction &segment)
     471              : {
     472           78 :   AST::DefaultASTVisitor::visit (segment);
     473           78 :   auto &type_path_function = segment.get_type_path_function ();
     474              : 
     475          160 :   for (auto &type : type_path_function.get_params ())
     476              :     {
     477           82 :       if (type->is_marked_for_strip ())
     478            0 :         rust_error_at (type->get_locus (),
     479              :                        "cannot strip type in this position");
     480              :     }
     481              : 
     482           78 :   if (type_path_function.has_return_type ())
     483              :     {
     484           74 :       auto &return_type = type_path_function.get_return_type ();
     485              : 
     486           74 :       if (return_type.is_marked_for_strip ())
     487            0 :         rust_error_at (return_type.get_locus (),
     488              :                        "cannot strip type in this position");
     489              :     }
     490           78 : }
     491              : 
     492              : void
     493          526 : CfgStrip::visit (AST::QualifiedPathInExpression &path)
     494              : {
     495              :   // initial strip test based on outer attrs
     496          526 :   AST::DefaultASTVisitor::visit (path);
     497              : 
     498          526 :   expand_cfg_attrs (path.get_outer_attrs ());
     499          526 :   if (fails_cfg_with_expand (path.get_outer_attrs ()))
     500              :     {
     501            0 :       path.mark_for_strip ();
     502            0 :       return;
     503              :     }
     504              : 
     505          526 :   maybe_strip_qualified_path_type (path.get_qualified_path_type ());
     506              : 
     507         1052 :   for (auto &segment : path.get_segments ())
     508              :     {
     509         1052 :       if (segment.has_generic_args ())
     510            0 :         maybe_strip_generic_args (segment.get_generic_args ());
     511              :     }
     512              : }
     513              : 
     514              : void
     515         1253 : CfgStrip::visit (AST::QualifiedPathInType &path)
     516              : {
     517         1253 :   maybe_strip_qualified_path_type (path.get_qualified_path_type ());
     518              : 
     519              :   // this shouldn't strip any segments, but can strip inside them
     520         1253 :   AST::DefaultASTVisitor::visit (path);
     521         1253 : }
     522              : 
     523              : void
     524       637076 : CfgStrip::visit (AST::LiteralExpr &expr)
     525              : {
     526              :   // initial strip test based on outer attrs
     527       637076 :   expand_cfg_attrs (expr.get_outer_attrs ());
     528       637076 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
     529              :     {
     530            0 :       expr.mark_for_strip ();
     531            0 :       return;
     532              :     }
     533              : }
     534              : 
     535              : void
     536        17510 : CfgStrip::visit (AST::BorrowExpr &expr)
     537              : {
     538        17510 :   AST::DefaultASTVisitor::visit (expr);
     539              :   // initial strip test based on outer attrs
     540        17510 :   expand_cfg_attrs (expr.get_outer_attrs ());
     541        17510 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
     542              :     {
     543            0 :       expr.mark_for_strip ();
     544            0 :       return;
     545              :     }
     546              : 
     547              :   /* strip any internal sub-expressions - expression itself isn't
     548              :    * allowed to have external attributes in this position so can't be
     549              :    * stripped. */
     550        17510 :   auto &borrowed_expr = expr.get_borrowed_expr ();
     551        17510 :   if (borrowed_expr.is_marked_for_strip ())
     552            0 :     rust_error_at (borrowed_expr.get_locus (),
     553              :                    "cannot strip expression in this position - outer "
     554              :                    "attributes not allowed");
     555              : }
     556              : void
     557        21384 : CfgStrip::visit (AST::DereferenceExpr &expr)
     558              : {
     559              :   // initial strip test based on outer attrs
     560        21384 :   expand_cfg_attrs (expr.get_outer_attrs ());
     561        21384 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
     562              :     {
     563            0 :       expr.mark_for_strip ();
     564            0 :       return;
     565              :     }
     566              : 
     567              :   /* strip any internal sub-expressions - expression itself isn't
     568              :    * allowed to have external attributes in this position so can't be
     569              :    * stripped. */
     570        21384 :   auto &dereferenced_expr = expr.get_dereferenced_expr ();
     571        21384 :   dereferenced_expr.accept_vis (*this);
     572        21384 :   if (dereferenced_expr.is_marked_for_strip ())
     573            0 :     rust_error_at (dereferenced_expr.get_locus (),
     574              :                    "cannot strip expression in this position - outer "
     575              :                    "attributes not allowed");
     576              : }
     577              : void
     578            4 : CfgStrip::visit (AST::ErrorPropagationExpr &expr)
     579              : {
     580            4 :   AST::DefaultASTVisitor::visit (expr);
     581              : 
     582              :   // initial strip test based on outer attrs
     583            4 :   expand_cfg_attrs (expr.get_outer_attrs ());
     584            4 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
     585              :     {
     586            0 :       expr.mark_for_strip ();
     587            0 :       return;
     588              :     }
     589              : 
     590              :   /* strip any internal sub-expressions - expression itself isn't
     591              :    * allowed to have external attributes in this position so can't be
     592              :    * stripped. */
     593            4 :   auto &propagating_expr = expr.get_propagating_expr ();
     594            4 :   if (propagating_expr.is_marked_for_strip ())
     595            0 :     rust_error_at (propagating_expr.get_locus (),
     596              :                    "cannot strip expression in this position - outer "
     597              :                    "attributes not allowed");
     598              : }
     599              : void
     600         2418 : CfgStrip::visit (AST::NegationExpr &expr)
     601              : {
     602         2418 :   AST::DefaultASTVisitor::visit (expr);
     603              :   // initial strip test based on outer attrs
     604         2418 :   expand_cfg_attrs (expr.get_outer_attrs ());
     605         2418 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
     606              :     {
     607            0 :       expr.mark_for_strip ();
     608            0 :       return;
     609              :     }
     610              : 
     611              :   /* strip any internal sub-expressions - expression itself isn't
     612              :    * allowed to have external attributes in this position so can't be
     613              :    * stripped. */
     614         2418 :   auto &negated_expr = expr.get_negated_expr ();
     615         2418 :   if (negated_expr.is_marked_for_strip ())
     616            0 :     rust_error_at (negated_expr.get_locus (),
     617              :                    "cannot strip expression in this position - outer "
     618              :                    "attributes not allowed");
     619              : }
     620              : void
     621       540417 : CfgStrip::visit (AST::ArithmeticOrLogicalExpr &expr)
     622              : {
     623       540417 :   AST::DefaultASTVisitor::visit (expr);
     624              :   /* outer attributes never allowed before these. while cannot strip
     625              :    * two direct descendant expressions, can strip ones below that */
     626              : 
     627              :   // ensure that they are not marked for strip
     628       540417 :   if (expr.get_left_expr ().is_marked_for_strip ())
     629            0 :     rust_error_at (expr.get_left_expr ().get_locus (),
     630              :                    "cannot strip expression in this position - outer "
     631              :                    "attributes are never allowed "
     632              :                    "before binary op exprs");
     633       540417 :   if (expr.get_right_expr ().is_marked_for_strip ())
     634            0 :     rust_error_at (expr.get_right_expr ().get_locus (),
     635              :                    "cannot strip expression in this position - outer "
     636              :                    "attributes not allowed");
     637       540417 : }
     638              : 
     639              : void
     640        13191 : CfgStrip::visit (AST::ComparisonExpr &expr)
     641              : {
     642              :   /* outer attributes never allowed before these. while cannot strip
     643              :    * two direct descendant expressions, can strip ones below that */
     644        13191 :   AST::DefaultASTVisitor::visit (expr);
     645              : 
     646              :   // ensure that they are not marked for strip
     647        13191 :   if (expr.get_left_expr ().is_marked_for_strip ())
     648            0 :     rust_error_at (expr.get_left_expr ().get_locus (),
     649              :                    "cannot strip expression in this position - outer "
     650              :                    "attributes are never allowed "
     651              :                    "before binary op exprs");
     652        13191 :   if (expr.get_right_expr ().is_marked_for_strip ())
     653            0 :     rust_error_at (expr.get_right_expr ().get_locus (),
     654              :                    "cannot strip expression in this position - outer "
     655              :                    "attributes not allowed");
     656        13191 : }
     657              : 
     658              : void
     659         1580 : CfgStrip::visit (AST::LazyBooleanExpr &expr)
     660              : {
     661              :   /* outer attributes never allowed before these. while cannot strip
     662              :    * two direct descendant expressions, can strip ones below that */
     663         1580 :   AST::DefaultASTVisitor::visit (expr);
     664              : 
     665              :   // ensure that they are not marked for strip
     666         1580 :   if (expr.get_left_expr ().is_marked_for_strip ())
     667            0 :     rust_error_at (expr.get_left_expr ().get_locus (),
     668              :                    "cannot strip expression in this position - outer "
     669              :                    "attributes are never allowed "
     670              :                    "before binary op exprs");
     671         1580 :   if (expr.get_right_expr ().is_marked_for_strip ())
     672            0 :     rust_error_at (expr.get_right_expr ().get_locus (),
     673              :                    "cannot strip expression in this position - outer "
     674              :                    "attributes not allowed");
     675         1580 : }
     676              : 
     677              : void
     678        52274 : CfgStrip::visit (AST::TypeCastExpr &expr)
     679              : {
     680              :   /* outer attributes never allowed before these. while cannot strip
     681              :    * direct descendant expression, can strip ones below that */
     682        52274 :   AST::DefaultASTVisitor::visit (expr);
     683              : 
     684        52274 :   auto &casted_expr = expr.get_casted_expr ();
     685              :   // ensure that they are not marked for strip
     686        52274 :   if (casted_expr.is_marked_for_strip ())
     687            0 :     rust_error_at (casted_expr.get_locus (),
     688              :                    "cannot strip expression in this position - outer "
     689              :                    "attributes are never allowed before cast exprs");
     690              : 
     691              :   // TODO: strip sub-types of type
     692        52274 :   auto &type = expr.get_type_to_cast_to ();
     693        52274 :   if (type.is_marked_for_strip ())
     694            0 :     rust_error_at (type.get_locus (), "cannot strip type in this position");
     695        52274 : }
     696              : void
     697        15840 : CfgStrip::visit (AST::AssignmentExpr &expr)
     698              : {
     699        15840 :   expand_cfg_attrs (expr.get_outer_attrs ());
     700        15840 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
     701              :     {
     702           14 :       expr.mark_for_strip ();
     703           14 :       return;
     704              :     }
     705        15826 :   AST::DefaultASTVisitor::visit (expr);
     706              : 
     707              :   // ensure that they are not marked for strip
     708        15826 :   if (expr.get_left_expr ().is_marked_for_strip ())
     709            0 :     rust_error_at (expr.get_left_expr ().get_locus (),
     710              :                    "cannot strip expression in this position - outer "
     711              :                    "attributes are never allowed "
     712              :                    "before binary op exprs");
     713        15826 :   if (expr.get_right_expr ().is_marked_for_strip ())
     714            0 :     rust_error_at (expr.get_right_expr ().get_locus (),
     715              :                    "cannot strip expression in this position - outer "
     716              :                    "attributes not allowed");
     717              : }
     718              : void
     719         6294 : CfgStrip::visit (AST::CompoundAssignmentExpr &expr)
     720              : {
     721              :   /* outer attributes never allowed before these. while cannot strip
     722              :    * two direct descendant expressions, can strip ones below that */
     723         6294 :   AST::DefaultASTVisitor::visit (expr);
     724              : 
     725              :   // ensure that they are not marked for strip
     726         6294 :   if (expr.get_left_expr ().is_marked_for_strip ())
     727            0 :     rust_error_at (expr.get_left_expr ().get_locus (),
     728              :                    "cannot strip expression in this position - outer "
     729              :                    "attributes are never allowed "
     730              :                    "before binary op exprs");
     731         6294 :   if (expr.get_right_expr ().is_marked_for_strip ())
     732            0 :     rust_error_at (expr.get_right_expr ().get_locus (),
     733              :                    "cannot strip expression in this position - outer "
     734              :                    "attributes not allowed");
     735         6294 : }
     736              : void
     737         2135 : CfgStrip::visit (AST::GroupedExpr &expr)
     738              : {
     739              :   // initial strip test based on outer attrs
     740         2135 :   expand_cfg_attrs (expr.get_outer_attrs ());
     741         2135 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
     742              :     {
     743            0 :       expr.mark_for_strip ();
     744            0 :       return;
     745              :     }
     746              : 
     747              :   /* strip test based on inner attrs - spec says these are inner
     748              :    * attributes, not outer attributes of inner expr */
     749         2135 :   expand_cfg_attrs (expr.get_inner_attrs ());
     750         2135 :   if (fails_cfg_with_expand (expr.get_inner_attrs ()))
     751              :     {
     752            0 :       expr.mark_for_strip ();
     753            0 :       return;
     754              :     }
     755              : 
     756              :   /* strip any internal sub-expressions - expression itself isn't
     757              :    * allowed to have external attributes in this position so can't be
     758              :    * stripped. */
     759         2135 :   AST::DefaultASTVisitor::visit (expr);
     760              : 
     761         2135 :   auto &inner_expr = expr.get_expr_in_parens ();
     762         2135 :   if (inner_expr.is_marked_for_strip ())
     763            0 :     rust_error_at (inner_expr.get_locus (),
     764              :                    "cannot strip expression in this position - outer "
     765              :                    "attributes not allowed");
     766              : }
     767              : void
     768         1148 : CfgStrip::visit (AST::ArrayElemsValues &elems)
     769              : {
     770              :   /* apparently outer attributes are allowed in "elements of array
     771              :    * expressions" according to spec */
     772         1148 :   maybe_strip_pointer_allow_strip (elems.get_values ());
     773         1148 : }
     774              : void
     775          466 : CfgStrip::visit (AST::ArrayElemsCopied &elems)
     776              : {
     777              :   /* apparently outer attributes are allowed in "elements of array
     778              :    * expressions" according to spec. on the other hand, it would not
     779              :    * make conceptual sense to be able to remove either expression. As
     780              :    * such, not implementing. TODO clear up the ambiguity here */
     781          466 :   AST::DefaultASTVisitor::visit (elems);
     782              : 
     783              :   // only intend stripping for internal sub-expressions
     784          466 :   auto &copied_expr = elems.get_elem_to_copy ();
     785          466 :   if (copied_expr.is_marked_for_strip ())
     786            0 :     rust_error_at (copied_expr.get_locus (),
     787              :                    "cannot strip expression in this position - outer "
     788              :                    "attributes not allowed");
     789              : 
     790          466 :   auto &copy_count = elems.get_num_copies ();
     791          466 :   copy_count.accept_vis (*this);
     792          466 :   if (copy_count.is_marked_for_strip ())
     793            0 :     rust_error_at (copy_count.get_locus (),
     794              :                    "cannot strip expression in this position - outer "
     795              :                    "attributes not allowed");
     796          466 : }
     797              : void
     798         1614 : CfgStrip::visit (AST::ArrayExpr &expr)
     799              : {
     800              :   // initial strip test based on outer attrs
     801         1614 :   expand_cfg_attrs (expr.get_outer_attrs ());
     802         1614 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
     803              :     {
     804            0 :       expr.mark_for_strip ();
     805            0 :       return;
     806              :     }
     807              : 
     808              :   /* strip test based on inner attrs - spec says there are separate
     809              :    * inner attributes, not just outer attributes of inner exprs */
     810         1614 :   expand_cfg_attrs (expr.get_inner_attrs ());
     811         1614 :   if (fails_cfg_with_expand (expr.get_inner_attrs ()))
     812              :     {
     813            0 :       expr.mark_for_strip ();
     814            0 :       return;
     815              :     }
     816              : 
     817              :   /* assuming you can't strip away the ArrayElems type, but can strip
     818              :    * internal expressions and whatever */
     819         1614 :   AST::DefaultASTVisitor::visit (expr);
     820              : }
     821              : 
     822              : void
     823         1220 : CfgStrip::visit (AST::ArrayIndexExpr &expr)
     824              : {
     825              :   /* it is unclear whether outer attributes are supposed to be
     826              :    * allowed, but conceptually it wouldn't make much sense, but
     827              :    * having expansion code anyway. TODO */
     828              :   // initial strip test based on outer attrs
     829         1220 :   expand_cfg_attrs (expr.get_outer_attrs ());
     830         1220 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
     831              :     {
     832            0 :       expr.mark_for_strip ();
     833            0 :       return;
     834              :     }
     835              : 
     836              :   /* strip any internal sub-expressions - expression itself isn't
     837              :    * allowed to have external attributes in this position so can't be
     838              :    * stripped. */
     839         1220 :   AST::DefaultASTVisitor::visit (expr);
     840              : 
     841         1220 :   const auto &array_expr = expr.get_array_expr ();
     842         1220 :   if (array_expr.is_marked_for_strip ())
     843            0 :     rust_error_at (array_expr.get_locus (),
     844              :                    "cannot strip expression in this position - outer "
     845              :                    "attributes not allowed");
     846              : 
     847         1220 :   const auto &index_expr = expr.get_index_expr ();
     848         1220 :   if (index_expr.is_marked_for_strip ())
     849            0 :     rust_error_at (index_expr.get_locus (),
     850              :                    "cannot strip expression in this position - outer "
     851              :                    "attributes not allowed");
     852              : }
     853              : void
     854         2617 : CfgStrip::visit (AST::TupleExpr &expr)
     855              : {
     856              :   /* according to spec, outer attributes are allowed on "elements of
     857              :    * tuple expressions" */
     858              : 
     859              :   // initial strip test based on outer attrs
     860         2617 :   expand_cfg_attrs (expr.get_outer_attrs ());
     861         2617 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
     862              :     {
     863            0 :       expr.mark_for_strip ();
     864            0 :       return;
     865              :     }
     866              : 
     867              :   /* strip test based on inner attrs - spec says these are inner
     868              :    * attributes, not outer attributes of inner expr */
     869         2617 :   expand_cfg_attrs (expr.get_inner_attrs ());
     870         2617 :   if (fails_cfg_with_expand (expr.get_inner_attrs ()))
     871              :     {
     872            0 :       expr.mark_for_strip ();
     873            0 :       return;
     874              :     }
     875              : 
     876              :   /* apparently outer attributes are allowed in "elements of tuple
     877              :    * expressions" according to spec */
     878         2617 :   maybe_strip_pointer_allow_strip (expr.get_tuple_elems ());
     879              : }
     880              : void
     881         5616 : CfgStrip::visit (AST::TupleIndexExpr &expr)
     882              : {
     883              :   // initial strip test based on outer attrs
     884         5616 :   expand_cfg_attrs (expr.get_outer_attrs ());
     885         5616 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
     886              :     {
     887            0 :       expr.mark_for_strip ();
     888            0 :       return;
     889              :     }
     890              : 
     891         5616 :   AST::DefaultASTVisitor::visit (expr);
     892              :   /* wouldn't strip this directly (as outer attrs should be
     893              :    * associated with this level), but any sub-expressions would be
     894              :    * stripped. Thus, no need to erase when strip check called. */
     895         5616 :   auto &tuple_expr = expr.get_tuple_expr ();
     896         5616 :   if (tuple_expr.is_marked_for_strip ())
     897            0 :     rust_error_at (tuple_expr.get_locus (),
     898              :                    "cannot strip expression in this position - outer "
     899              :                    "attributes not allowed");
     900              : }
     901              : 
     902              : void
     903          328 : CfgStrip::visit (AST::StructExprStruct &expr)
     904              : {
     905              :   // initial strip test based on outer attrs
     906          328 :   expand_cfg_attrs (expr.get_outer_attrs ());
     907          328 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
     908              :     {
     909            0 :       expr.mark_for_strip ();
     910            0 :       return;
     911              :     }
     912              : 
     913              :   /* strip test based on inner attrs - spec says these are inner
     914              :    * attributes, not outer attributes of inner expr */
     915          328 :   expand_cfg_attrs (expr.get_inner_attrs ());
     916          328 :   if (fails_cfg_with_expand (expr.get_inner_attrs ()))
     917              :     {
     918            0 :       expr.mark_for_strip ();
     919            0 :       return;
     920              :     }
     921              : 
     922              :   // strip sub-exprs of path
     923          328 :   auto &struct_name = expr.get_struct_name ();
     924          328 :   visit (struct_name);
     925          328 :   if (struct_name.is_marked_for_strip ())
     926            0 :     rust_error_at (struct_name.get_locus (),
     927              :                    "cannot strip path in this position");
     928              : }
     929              : 
     930              : void
     931         9419 : CfgStrip::visit (AST::StructExprFieldIdentifierValue &field)
     932              : {
     933              :   /* as no attrs possible (at moment, at least), only sub-expression
     934              :    * stripping is possible */
     935         9419 :   AST::DefaultASTVisitor::visit (field);
     936              : 
     937         9419 :   auto &value = field.get_value ();
     938         9419 :   if (value.is_marked_for_strip ())
     939            0 :     rust_error_at (value.get_locus (),
     940              :                    "cannot strip expression in this position - outer "
     941              :                    "attributes not allowed");
     942         9419 : }
     943              : void
     944          176 : CfgStrip::visit (AST::StructExprFieldIndexValue &field)
     945              : {
     946              :   /* as no attrs possible (at moment, at least), only sub-expression
     947              :    * stripping is possible */
     948          176 :   AST::DefaultASTVisitor::visit (field);
     949              : 
     950          176 :   auto &value = field.get_value ();
     951          176 :   if (value.is_marked_for_strip ())
     952            0 :     rust_error_at (value.get_locus (),
     953              :                    "cannot strip expression in this position - outer "
     954              :                    "attributes not allowed");
     955          176 : }
     956              : void
     957         5732 : CfgStrip::visit (AST::StructExprStructFields &expr)
     958              : {
     959              :   // initial strip test based on outer attrs
     960         5732 :   expand_cfg_attrs (expr.get_outer_attrs ());
     961         5732 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
     962              :     {
     963            0 :       expr.mark_for_strip ();
     964            0 :       return;
     965              :     }
     966              : 
     967              :   /* strip test based on inner attrs - spec says these are inner
     968              :    * attributes, not outer attributes of inner expr */
     969         5732 :   expand_cfg_attrs (expr.get_inner_attrs ());
     970         5732 :   if (fails_cfg_with_expand (expr.get_inner_attrs ()))
     971              :     {
     972            0 :       expr.mark_for_strip ();
     973            0 :       return;
     974              :     }
     975              : 
     976              :   // strip sub-exprs of path
     977         5732 :   auto &struct_name = expr.get_struct_name ();
     978         5732 :   visit (struct_name);
     979         5732 :   if (struct_name.is_marked_for_strip ())
     980            0 :     rust_error_at (struct_name.get_locus (),
     981              :                    "cannot strip path in this position");
     982              : 
     983              :   /* spec does not specify whether expressions are allowed to be
     984              :    * stripped at top level of struct fields, but I wouldn't think
     985              :    * that they would be, so operating under the assumption that only
     986              :    * sub-expressions can be stripped. */
     987         5732 :   AST::DefaultASTVisitor::visit (expr);
     988              : 
     989              :   /* struct base presumably can't be stripped, as the '..' is before
     990              :    * the expression. as such, can only strip sub-expressions. */
     991         5732 :   if (expr.has_struct_base ())
     992              :     {
     993          252 :       auto &base_struct_expr = expr.get_struct_base ().get_base_struct ();
     994          252 :       base_struct_expr.accept_vis (*this);
     995          252 :       if (base_struct_expr.is_marked_for_strip ())
     996            0 :         rust_error_at (base_struct_expr.get_locus (),
     997              :                        "cannot strip expression in this position - outer "
     998              :                        "attributes not allowed");
     999              :     }
    1000              : 
    1001         5732 :   maybe_strip_struct_expr_fields (expr.get_fields ());
    1002              : }
    1003              : 
    1004              : void
    1005            0 : CfgStrip::visit (AST::StructExprStructBase &expr)
    1006              : {
    1007              :   // initial strip test based on outer attrs
    1008            0 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1009            0 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1010              :     {
    1011            0 :       expr.mark_for_strip ();
    1012            0 :       return;
    1013              :     }
    1014              : 
    1015              :   /* strip test based on inner attrs - spec says these are inner
    1016              :    * attributes, not outer attributes of inner expr */
    1017            0 :   expand_cfg_attrs (expr.get_inner_attrs ());
    1018            0 :   if (fails_cfg_with_expand (expr.get_inner_attrs ()))
    1019              :     {
    1020            0 :       expr.mark_for_strip ();
    1021            0 :       return;
    1022              :     }
    1023              : 
    1024              :   // strip sub-exprs of path
    1025            0 :   auto &struct_name = expr.get_struct_name ();
    1026            0 :   visit (struct_name);
    1027            0 :   if (struct_name.is_marked_for_strip ())
    1028            0 :     rust_error_at (struct_name.get_locus (),
    1029              :                    "cannot strip path in this position");
    1030              : 
    1031              :   /* struct base presumably can't be stripped, as the '..' is before
    1032              :    * the expression. as such, can only strip sub-expressions. */
    1033            0 :   rust_assert (!expr.get_struct_base ().is_invalid ());
    1034            0 :   auto &base_struct_expr = expr.get_struct_base ().get_base_struct ();
    1035            0 :   base_struct_expr.accept_vis (*this);
    1036            0 :   if (base_struct_expr.is_marked_for_strip ())
    1037            0 :     rust_error_at (base_struct_expr.get_locus (),
    1038              :                    "cannot strip expression in this position - outer "
    1039              :                    "attributes not allowed");
    1040              : }
    1041              : void
    1042        68083 : CfgStrip::visit (AST::CallExpr &expr)
    1043              : {
    1044              :   // initial strip test based on outer attrs
    1045        68083 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1046        68083 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1047              :     {
    1048            0 :       expr.mark_for_strip ();
    1049            0 :       return;
    1050              :     }
    1051              : 
    1052              :   /* should not be outer attrs on "function" expression - outer attrs
    1053              :    * should be associated with call expr as a whole. only sub-expr
    1054              :    * expansion is possible. */
    1055        68083 :   AST::DefaultASTVisitor::visit (expr);
    1056              : 
    1057        68083 :   auto &function = expr.get_function_expr ();
    1058        68083 :   if (function.is_marked_for_strip ())
    1059            0 :     rust_error_at (function.get_locus (),
    1060              :                    "cannot strip expression in this position - outer "
    1061              :                    "attributes not allowed");
    1062              : 
    1063              :   /* spec says outer attributes are specifically allowed for elements
    1064              :    * of call expressions, so full stripping possible */
    1065              :   // FIXME: Arthur: Figure out how to refactor this - This is similar to
    1066              :   // expanding items in the crate or stmts in blocks
    1067        68083 :   maybe_strip_pointer_allow_strip (expr.get_params ());
    1068              : }
    1069              : void
    1070        20153 : CfgStrip::visit (AST::MethodCallExpr &expr)
    1071              : {
    1072              :   // initial strip test based on outer attrs
    1073        20153 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1074        20153 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1075              :     {
    1076            0 :       expr.mark_for_strip ();
    1077            0 :       return;
    1078              :     }
    1079              : 
    1080              :   /* should not be outer attrs on "receiver" expression - outer attrs
    1081              :    * should be associated with call expr as a whole. only sub-expr
    1082              :    * expansion is possible. */
    1083        20153 :   AST::DefaultASTVisitor::visit (expr);
    1084              : 
    1085        20153 :   auto &receiver = expr.get_receiver_expr ();
    1086        20153 :   if (receiver.is_marked_for_strip ())
    1087            0 :     rust_error_at (receiver.get_locus (),
    1088              :                    "cannot strip expression in this position - outer "
    1089              :                    "attributes not allowed");
    1090              : 
    1091        20153 :   auto &method_name = expr.get_method_name ();
    1092        20153 :   if (method_name.has_generic_args ())
    1093           88 :     maybe_strip_generic_args (method_name.get_generic_args ());
    1094              : 
    1095              :   /* spec says outer attributes are specifically allowed for elements
    1096              :    * of method call expressions, so full stripping possible */
    1097        20153 :   maybe_strip_pointer_allow_strip (expr.get_params ());
    1098              : }
    1099              : void
    1100        39745 : CfgStrip::visit (AST::FieldAccessExpr &expr)
    1101              : {
    1102              :   // initial strip test based on outer attrs
    1103        39745 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1104        39745 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1105              :     {
    1106            0 :       expr.mark_for_strip ();
    1107            0 :       return;
    1108              :     }
    1109              : 
    1110              :   /* should not be outer attrs on "receiver" expression - outer attrs
    1111              :    * should be associated with field expr as a whole. only sub-expr
    1112              :    * expansion is possible. */
    1113        39745 :   AST::DefaultASTVisitor::visit (expr);
    1114              : 
    1115        39745 :   auto &receiver = expr.get_receiver_expr ();
    1116        39745 :   if (receiver.is_marked_for_strip ())
    1117            0 :     rust_error_at (receiver.get_locus (),
    1118              :                    "cannot strip expression in this position - outer "
    1119              :                    "attributes not allowed");
    1120              : }
    1121              : void
    1122          130 : CfgStrip::visit (AST::ClosureExprInner &expr)
    1123              : {
    1124              :   // initial strip test based on outer attrs
    1125          130 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1126          130 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1127              :     {
    1128            0 :       expr.mark_for_strip ();
    1129            0 :       return;
    1130              :     }
    1131              : 
    1132              :   /* strip closure parameters if required - this is specifically
    1133              :    * allowed by spec */
    1134          130 :   maybe_strip_closure_params (expr.get_params ());
    1135              : 
    1136          130 :   AST::DefaultASTVisitor::visit (expr);
    1137              : 
    1138              :   // can't strip expression itself, but can strip sub-expressions
    1139          130 :   auto &definition_expr = expr.get_definition_expr ();
    1140          130 :   if (definition_expr.is_marked_for_strip ())
    1141            0 :     rust_error_at (definition_expr.get_locus (),
    1142              :                    "cannot strip expression in this position - outer "
    1143              :                    "attributes not allowed");
    1144              : }
    1145              : 
    1146              : void
    1147        90169 : CfgStrip::visit (AST::BlockExpr &expr)
    1148              : {
    1149              :   // initial strip test based on outer attrs
    1150        90169 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1151        90169 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1152              :     {
    1153           54 :       expr.mark_for_strip ();
    1154           54 :       return;
    1155              :     }
    1156              : 
    1157              :   /* strip test based on inner attrs - spec says there are inner
    1158              :    * attributes, not just outer attributes of inner stmts */
    1159        90115 :   expand_cfg_attrs (expr.get_inner_attrs ());
    1160        90115 :   if (fails_cfg_with_expand (expr.get_inner_attrs ()))
    1161              :     {
    1162            0 :       expr.mark_for_strip ();
    1163            0 :       return;
    1164              :     }
    1165              : 
    1166        90115 :   maybe_strip_pointer_allow_strip (expr.get_statements ());
    1167              : 
    1168        90115 :   AST::DefaultASTVisitor::visit (expr);
    1169              : 
    1170              :   // strip tail expression if exists - can actually fully remove it
    1171        90115 :   if (expr.has_tail_expr ())
    1172              :     {
    1173        70786 :       auto &tail_expr = expr.get_tail_expr ();
    1174              : 
    1175        70786 :       if (tail_expr.is_marked_for_strip ())
    1176           57 :         expr.strip_tail_expr ();
    1177              :     }
    1178              : }
    1179              : 
    1180              : void
    1181          120 : CfgStrip::visit (AST::ClosureExprInnerTyped &expr)
    1182              : {
    1183              :   // initial strip test based on outer attrs
    1184          120 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1185          120 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1186              :     {
    1187            0 :       expr.mark_for_strip ();
    1188            0 :       return;
    1189              :     }
    1190              : 
    1191              :   /* strip closure parameters if required - this is specifically
    1192              :    * allowed by spec */
    1193          120 :   maybe_strip_closure_params (expr.get_params ());
    1194              : 
    1195          120 :   AST::DefaultASTVisitor::visit (expr);
    1196              : 
    1197              :   // can't strip return type, but can strip sub-types
    1198          120 :   auto &type = expr.get_return_type ();
    1199              : 
    1200          120 :   if (type.is_marked_for_strip ())
    1201            0 :     rust_error_at (type.get_locus (), "cannot strip type in this position");
    1202              : 
    1203              :   // can't strip expression itself, but can strip sub-expressions
    1204          120 :   auto &definition_block = expr.get_definition_expr ();
    1205          120 :   definition_block.accept_vis (*this);
    1206          120 :   if (definition_block.is_marked_for_strip ())
    1207            0 :     rust_error_at (definition_block.get_locus (),
    1208              :                    "cannot strip block expression in this position - outer "
    1209              :                    "attributes not allowed");
    1210              : }
    1211              : void
    1212          154 : CfgStrip::visit (AST::ContinueExpr &expr)
    1213              : {
    1214              :   // initial strip test based on outer attrs
    1215          154 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1216          154 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1217              :     {
    1218            0 :       expr.mark_for_strip ();
    1219            0 :       return;
    1220              :     }
    1221              : }
    1222              : void
    1223          628 : CfgStrip::visit (AST::BreakExpr &expr)
    1224              : {
    1225              :   // initial strip test based on outer attrs
    1226          628 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1227          628 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1228              :     {
    1229            0 :       expr.mark_for_strip ();
    1230            0 :       return;
    1231              :     }
    1232          628 :   AST::DefaultASTVisitor::visit (expr);
    1233              : 
    1234              :   /* spec does not say that you can have outer attributes on
    1235              :    * expression, so assuming you can't. stripping for sub-expressions
    1236              :    * is the only thing that can be done */
    1237          628 :   if (expr.has_break_expr ())
    1238              :     {
    1239          248 :       auto &break_expr = expr.get_break_expr_unchecked ();
    1240              : 
    1241          248 :       if (break_expr.is_marked_for_strip ())
    1242            0 :         rust_error_at (break_expr.get_locus (),
    1243              :                        "cannot strip expression in this position - outer "
    1244              :                        "attributes not allowed");
    1245              :     }
    1246              : }
    1247              : void
    1248          356 : CfgStrip::visit (AST::RangeFromToExpr &expr)
    1249              : {
    1250              :   /* outer attributes never allowed before these. while cannot strip
    1251              :    * two direct descendant expressions, can strip ones below that */
    1252          356 :   AST::DefaultASTVisitor::visit (expr);
    1253              : 
    1254              :   // ensure that they are not marked for strip
    1255          356 :   if (expr.get_from_expr ().is_marked_for_strip ())
    1256            0 :     rust_error_at (expr.get_from_expr ().get_locus (),
    1257              :                    "cannot strip expression in this position - outer "
    1258              :                    "attributes are never allowed "
    1259              :                    "before range exprs");
    1260          356 :   if (expr.get_to_expr ().is_marked_for_strip ())
    1261            0 :     rust_error_at (expr.get_to_expr ().get_locus (),
    1262              :                    "cannot strip expression in this position - outer "
    1263              :                    "attributes not allowed");
    1264          356 : }
    1265              : void
    1266           28 : CfgStrip::visit (AST::RangeFromExpr &expr)
    1267              : {
    1268              :   /* outer attributes never allowed before these. while cannot strip
    1269              :    * direct descendant expression, can strip ones below that */
    1270              : 
    1271           28 :   AST::DefaultASTVisitor::visit (expr);
    1272              :   /* should have no possibility for outer attrs as would be parsed
    1273              :    * with outer expr */
    1274           28 :   auto &from_expr = expr.get_from_expr ();
    1275           28 :   if (from_expr.is_marked_for_strip ())
    1276            0 :     rust_error_at (from_expr.get_locus (),
    1277              :                    "cannot strip expression in this position - outer "
    1278              :                    "attributes are never allowed before range exprs");
    1279           28 : }
    1280              : void
    1281           28 : CfgStrip::visit (AST::RangeToExpr &expr)
    1282              : {
    1283              :   /* outer attributes never allowed before these. while cannot strip
    1284              :    * direct descendant expression, can strip ones below that */
    1285              : 
    1286           28 :   AST::DefaultASTVisitor::visit (expr);
    1287              :   /* should syntactically not have outer attributes, though this may
    1288              :    * not have worked in practice */
    1289           28 :   auto &to_expr = expr.get_to_expr ();
    1290           28 :   if (to_expr.is_marked_for_strip ())
    1291            0 :     rust_error_at (to_expr.get_locus (),
    1292              :                    "cannot strip expression in this position - outer "
    1293              :                    "attributes not allowed");
    1294           28 : }
    1295              : 
    1296              : void
    1297           28 : CfgStrip::visit (AST::RangeFromToInclExpr &expr)
    1298              : {
    1299              :   /* outer attributes never allowed before these. while cannot strip
    1300              :    * two direct descendant expressions, can strip ones below that */
    1301              : 
    1302           28 :   AST::DefaultASTVisitor::visit (expr);
    1303              : 
    1304              :   // ensure that they are not marked for strip
    1305           28 :   if (expr.get_from_expr ().is_marked_for_strip ())
    1306            0 :     rust_error_at (expr.get_from_expr ().get_locus (),
    1307              :                    "cannot strip expression in this position - outer "
    1308              :                    "attributes are never allowed "
    1309              :                    "before range exprs");
    1310           28 :   if (expr.get_to_expr ().is_marked_for_strip ())
    1311            0 :     rust_error_at (expr.get_to_expr ().get_locus (),
    1312              :                    "cannot strip expression in this position - outer "
    1313              :                    "attributes not allowed");
    1314           28 : }
    1315              : void
    1316            0 : CfgStrip::visit (AST::RangeToInclExpr &expr)
    1317              : {
    1318              :   /* outer attributes never allowed before these. while cannot strip
    1319              :    * direct descendant expression, can strip ones below that */
    1320              : 
    1321            0 :   AST::DefaultASTVisitor::visit (expr);
    1322              :   /* should syntactically not have outer attributes, though this may
    1323              :    * not have worked in practice */
    1324            0 :   auto &to_expr = expr.get_to_expr ();
    1325            0 :   if (to_expr.is_marked_for_strip ())
    1326            0 :     rust_error_at (to_expr.get_locus (),
    1327              :                    "cannot strip expression in this position - outer "
    1328              :                    "attributes not allowed");
    1329            0 : }
    1330              : void
    1331         3108 : CfgStrip::visit (AST::ReturnExpr &expr)
    1332              : {
    1333              :   // initial strip test based on outer attrs
    1334         3108 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1335         3108 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1336              :     {
    1337            0 :       expr.mark_for_strip ();
    1338            0 :       return;
    1339              :     }
    1340              : 
    1341         3108 :   AST::DefaultASTVisitor::visit (expr);
    1342              : 
    1343              :   /* spec does not say that you can have outer attributes on
    1344              :    * expression, so assuming you can't. stripping for sub-expressions
    1345              :    * is the only thing that can be done */
    1346         3108 :   if (expr.has_returned_expr ())
    1347              :     {
    1348         2750 :       auto &returned_expr = expr.get_returned_expr ();
    1349         2750 :       if (returned_expr.is_marked_for_strip ())
    1350            0 :         rust_error_at (returned_expr.get_locus (),
    1351              :                        "cannot strip expression in this position - outer "
    1352              :                        "attributes not allowed");
    1353              :     }
    1354              :   /* TODO: conceptually, you would maybe be able to remove a returned
    1355              :    * expr - e.g. if you had conditional compilation returning void or
    1356              :    * returning a type. On the other hand, I think that function
    1357              :    * return type cannot be conditionally compiled, so I assumed you
    1358              :    * can't do this either. */
    1359              : }
    1360              : void
    1361        16484 : CfgStrip::visit (AST::UnsafeBlockExpr &expr)
    1362              : {
    1363              :   // initial strip test based on outer attrs
    1364        16484 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1365        16484 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1366              :     {
    1367            7 :       expr.mark_for_strip ();
    1368            7 :       return;
    1369              :     }
    1370              : 
    1371        16477 :   AST::DefaultASTVisitor::visit (expr);
    1372              : 
    1373              :   // can't strip block itself, but can strip sub-expressions
    1374        16477 :   auto &block_expr = expr.get_block_expr ();
    1375        16477 :   if (block_expr.is_marked_for_strip ())
    1376            0 :     rust_error_at (block_expr.get_locus (),
    1377              :                    "cannot strip block expression in this position - outer "
    1378              :                    "attributes not allowed");
    1379              : }
    1380              : void
    1381          330 : CfgStrip::visit (AST::LoopExpr &expr)
    1382              : {
    1383              :   // initial strip test based on outer attrs
    1384          330 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1385          330 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1386              :     {
    1387            0 :       expr.mark_for_strip ();
    1388            0 :       return;
    1389              :     }
    1390              : 
    1391          330 :   AST::DefaultASTVisitor::visit (expr);
    1392              : 
    1393              :   // can't strip block itself, but can strip sub-expressions
    1394          330 :   auto &loop_block = expr.get_loop_block ();
    1395          330 :   if (loop_block.is_marked_for_strip ())
    1396            0 :     rust_error_at (loop_block.get_locus (),
    1397              :                    "cannot strip block expression in this position - outer "
    1398              :                    "attributes not allowed");
    1399              : }
    1400              : void
    1401          470 : CfgStrip::visit (AST::WhileLoopExpr &expr)
    1402              : {
    1403              :   // initial strip test based on outer attrs
    1404          470 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1405          470 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1406              :     {
    1407            0 :       expr.mark_for_strip ();
    1408            0 :       return;
    1409              :     }
    1410              : 
    1411          470 :   AST::DefaultASTVisitor::visit (expr);
    1412              :   // can't strip predicate expr itself, but can strip sub-expressions
    1413          470 :   auto &predicate_expr = expr.get_predicate_expr ();
    1414          470 :   if (predicate_expr.is_marked_for_strip ())
    1415            0 :     rust_error_at (predicate_expr.get_locus (),
    1416              :                    "cannot strip expression in this position - outer "
    1417              :                    "attributes not allowed");
    1418              : 
    1419              :   // can't strip block itself, but can strip sub-expressions
    1420          470 :   auto &loop_block = expr.get_loop_block ();
    1421          470 :   if (loop_block.is_marked_for_strip ())
    1422            0 :     rust_error_at (loop_block.get_locus (),
    1423              :                    "cannot strip block expression in this position - outer "
    1424              :                    "attributes not allowed");
    1425              : }
    1426              : void
    1427            4 : CfgStrip::visit (AST::WhileLetLoopExpr &expr)
    1428              : {
    1429              :   // initial strip test based on outer attrs
    1430            4 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1431            4 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1432              :     {
    1433            0 :       expr.mark_for_strip ();
    1434            0 :       return;
    1435              :     }
    1436              : 
    1437            4 :   AST::DefaultASTVisitor::visit (expr);
    1438              : 
    1439            4 :   if (expr.get_pattern ()->is_marked_for_strip ())
    1440            0 :     rust_error_at (expr.get_pattern ()->get_locus (),
    1441              :                    "cannot strip pattern in this position");
    1442              : 
    1443              :   // can't strip scrutinee expr itself, but can strip sub-expressions
    1444            4 :   auto &scrutinee_expr = expr.get_scrutinee_expr ();
    1445            4 :   if (scrutinee_expr.is_marked_for_strip ())
    1446            0 :     rust_error_at (scrutinee_expr.get_locus (),
    1447              :                    "cannot strip expression in this position - outer "
    1448              :                    "attributes not allowed");
    1449              : 
    1450              :   // can't strip block itself, but can strip sub-expressions
    1451            4 :   auto &loop_block = expr.get_loop_block ();
    1452            4 :   if (loop_block.is_marked_for_strip ())
    1453            0 :     rust_error_at (loop_block.get_locus (),
    1454              :                    "cannot strip block expression in this position - outer "
    1455              :                    "attributes not allowed");
    1456              : }
    1457              : void
    1458          120 : CfgStrip::visit (AST::ForLoopExpr &expr)
    1459              : {
    1460              :   // initial strip test based on outer attrs
    1461          120 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1462          120 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1463              :     {
    1464            0 :       expr.mark_for_strip ();
    1465            0 :       return;
    1466              :     }
    1467              : 
    1468          120 :   AST::DefaultASTVisitor::visit (expr);
    1469              :   // strip sub-patterns of pattern
    1470          120 :   auto &pattern = expr.get_pattern ();
    1471          120 :   if (pattern.is_marked_for_strip ())
    1472            0 :     rust_error_at (pattern.get_locus (),
    1473              :                    "cannot strip pattern in this position");
    1474              : 
    1475              :   // can't strip scrutinee expr itself, but can strip sub-expressions
    1476          120 :   auto &iterator_expr = expr.get_iterator_expr ();
    1477          120 :   if (iterator_expr.is_marked_for_strip ())
    1478            0 :     rust_error_at (iterator_expr.get_locus (),
    1479              :                    "cannot strip expression in this position - outer "
    1480              :                    "attributes not allowed");
    1481              : 
    1482              :   // can't strip block itself, but can strip sub-expressions
    1483          120 :   auto &loop_block = expr.get_loop_block ();
    1484          120 :   if (loop_block.is_marked_for_strip ())
    1485            0 :     rust_error_at (loop_block.get_locus (),
    1486              :                    "cannot strip block expression in this position - outer "
    1487              :                    "attributes not allowed");
    1488              : }
    1489              : void
    1490         8103 : CfgStrip::visit (AST::IfExpr &expr)
    1491              : {
    1492              :   // rust playground test shows that IfExpr does support outer attrs, at least
    1493              :   // when used as statement
    1494              : 
    1495              :   // initial strip test based on outer attrs
    1496         8103 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1497         8103 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1498              :     {
    1499            0 :       expr.mark_for_strip ();
    1500            0 :       return;
    1501              :     }
    1502              : 
    1503         8103 :   AST::DefaultASTVisitor::visit (expr);
    1504              : 
    1505              :   // can't strip condition expr itself, but can strip sub-expressions
    1506         8103 :   auto &condition_expr = expr.get_condition_expr ();
    1507         8103 :   if (condition_expr.is_marked_for_strip ())
    1508            0 :     rust_error_at (condition_expr.get_locus (),
    1509              :                    "cannot strip expression in this position - outer "
    1510              :                    "attributes not allowed");
    1511              : 
    1512              :   // can't strip if block itself, but can strip sub-expressions
    1513         8103 :   auto &if_block = expr.get_if_block ();
    1514         8103 :   if (if_block.is_marked_for_strip ())
    1515            0 :     rust_error_at (if_block.get_locus (),
    1516              :                    "cannot strip block expression in this position - outer "
    1517              :                    "attributes not allowed");
    1518              : }
    1519              : 
    1520              : void
    1521         5924 : CfgStrip::visit (AST::IfExprConseqElse &expr)
    1522              : {
    1523              :   // initial strip test based on outer attrs
    1524         5924 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1525         5924 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1526              :     {
    1527            0 :       expr.mark_for_strip ();
    1528            0 :       return;
    1529              :     }
    1530              : 
    1531         5924 :   AST::DefaultASTVisitor::visit (expr);
    1532              : 
    1533              :   // can't strip condition expr itself, but can strip sub-expressions
    1534         5924 :   auto &condition_expr = expr.get_condition_expr ();
    1535         5924 :   if (condition_expr.is_marked_for_strip ())
    1536            0 :     rust_error_at (condition_expr.get_locus (),
    1537              :                    "cannot strip expression in this position - outer "
    1538              :                    "attributes not allowed");
    1539              : 
    1540              :   // can't strip if block itself, but can strip sub-expressions
    1541         5924 :   auto &if_block = expr.get_if_block ();
    1542         5924 :   if (if_block.is_marked_for_strip ())
    1543            0 :     rust_error_at (if_block.get_locus (),
    1544              :                    "cannot strip block expression in this position - outer "
    1545              :                    "attributes not allowed");
    1546              : 
    1547              :   // can't strip else block itself, but can strip sub-expressions
    1548         5924 :   auto &else_block = expr.get_else_block ();
    1549         5924 :   if (else_block.is_marked_for_strip ())
    1550            0 :     rust_error_at (else_block.get_locus (),
    1551              :                    "cannot strip block expression in this position - outer "
    1552              :                    "attributes not allowed");
    1553              : }
    1554              : 
    1555              : void
    1556          102 : CfgStrip::visit (AST::IfLetExpr &expr)
    1557              : {
    1558              :   // initial strip test based on outer attrs
    1559          102 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1560          102 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1561              :     {
    1562            0 :       expr.mark_for_strip ();
    1563            0 :       return;
    1564              :     }
    1565              : 
    1566          102 :   AST::DefaultASTVisitor::visit (expr);
    1567              : 
    1568          102 :   if (expr.get_pattern ()->is_marked_for_strip ())
    1569            0 :     rust_error_at (expr.get_pattern ()->get_locus (),
    1570              :                    "cannot strip pattern in this position");
    1571              : 
    1572              :   // can't strip value expr itself, but can strip sub-expressions
    1573          102 :   auto &value_expr = expr.get_value_expr ();
    1574          102 :   if (value_expr.is_marked_for_strip ())
    1575            0 :     rust_error_at (value_expr.get_locus (),
    1576              :                    "cannot strip expression in this position - outer "
    1577              :                    "attributes not allowed");
    1578              : 
    1579              :   // can't strip if block itself, but can strip sub-expressions
    1580          102 :   auto &if_block = expr.get_if_block ();
    1581          102 :   if (if_block.is_marked_for_strip ())
    1582            0 :     rust_error_at (if_block.get_locus (),
    1583              :                    "cannot strip block expression in this position - outer "
    1584              :                    "attributes not allowed");
    1585              : }
    1586              : void
    1587           30 : CfgStrip::visit (AST::IfLetExprConseqElse &expr)
    1588              : {
    1589              :   // initial strip test based on outer attrs
    1590           30 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1591           30 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1592              :     {
    1593            0 :       expr.mark_for_strip ();
    1594            0 :       return;
    1595              :     }
    1596              : 
    1597           30 :   AST::DefaultASTVisitor::visit (expr);
    1598              : 
    1599           30 :   if (expr.get_pattern ()->is_marked_for_strip ())
    1600            0 :     rust_error_at (expr.get_pattern ()->get_locus (),
    1601              :                    "cannot strip pattern in this position");
    1602              : 
    1603              :   // can't strip value expr itself, but can strip sub-expressions
    1604           30 :   auto &value_expr = expr.get_value_expr ();
    1605           30 :   if (value_expr.is_marked_for_strip ())
    1606            0 :     rust_error_at (value_expr.get_locus (),
    1607              :                    "cannot strip expression in this position - outer "
    1608              :                    "attributes not allowed");
    1609              : 
    1610              :   // can't strip if block itself, but can strip sub-expressions
    1611           30 :   auto &if_block = expr.get_if_block ();
    1612           30 :   if (if_block.is_marked_for_strip ())
    1613            0 :     rust_error_at (if_block.get_locus (),
    1614              :                    "cannot strip block expression in this position - outer "
    1615              :                    "attributes not allowed");
    1616              : 
    1617              :   // can't strip else block itself, but can strip sub-expressions
    1618           30 :   auto &else_block = expr.get_else_block ();
    1619           30 :   if (else_block.is_marked_for_strip ())
    1620            0 :     rust_error_at (else_block.get_locus (),
    1621              :                    "cannot strip block expression in this position - outer "
    1622              :                    "attributes not allowed");
    1623              : }
    1624              : void
    1625         4419 : CfgStrip::visit (AST::MatchExpr &expr)
    1626              : {
    1627              :   // initial strip test based on outer attrs
    1628         4419 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1629         4419 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1630              :     {
    1631            0 :       expr.mark_for_strip ();
    1632            0 :       return;
    1633              :     }
    1634              : 
    1635              :   // inner attr strip test
    1636         4419 :   expand_cfg_attrs (expr.get_inner_attrs ());
    1637         4419 :   if (fails_cfg_with_expand (expr.get_inner_attrs ()))
    1638              :     {
    1639            0 :       expr.mark_for_strip ();
    1640            0 :       return;
    1641              :     }
    1642              : 
    1643         4419 :   AST::DefaultASTVisitor::visit (expr);
    1644              : 
    1645              :   // can't strip scrutinee expr itself, but can strip sub-expressions
    1646         4419 :   auto &scrutinee_expr = expr.get_scrutinee_expr ();
    1647         4419 :   if (scrutinee_expr.is_marked_for_strip ())
    1648            0 :     rust_error_at (scrutinee_expr.get_locus (),
    1649              :                    "cannot strip expression in this position - outer "
    1650              :                    "attributes not allowed");
    1651              : 
    1652              :   // strip match cases
    1653         4419 :   auto &match_cases = expr.get_match_cases ();
    1654        14601 :   for (auto it = match_cases.begin (); it != match_cases.end ();)
    1655              :     {
    1656        10182 :       auto &match_case = *it;
    1657              : 
    1658              :       // strip match case based on outer attributes in match arm
    1659        10182 :       auto &match_arm = match_case.get_arm ();
    1660        10182 :       expand_cfg_attrs (match_arm.get_outer_attrs ());
    1661        10182 :       if (fails_cfg_with_expand (match_arm.get_outer_attrs ()))
    1662              :         {
    1663              :           // strip match case
    1664            0 :           it = match_cases.erase (it);
    1665            0 :           continue;
    1666              :         }
    1667              : 
    1668        10182 :       if (match_arm.get_pattern ()->is_marked_for_strip ())
    1669            0 :         rust_error_at (match_arm.get_pattern ()->get_locus (),
    1670              :                        "cannot strip pattern in this position");
    1671              : 
    1672              :       /* assuming that guard expression cannot be stripped as
    1673              :        * strictly speaking you would have to strip the whole guard to
    1674              :        * make syntactical sense, which you can't do. as such, only
    1675              :        * strip sub-expressions */
    1676        10182 :       if (match_arm.has_match_arm_guard ())
    1677              :         {
    1678            2 :           auto &guard_expr = match_arm.get_guard_expr ();
    1679            2 :           if (guard_expr.is_marked_for_strip ())
    1680            0 :             rust_error_at (guard_expr.get_locus (),
    1681              :                            "cannot strip expression in this position - outer "
    1682              :                            "attributes not allowed");
    1683              :         }
    1684              : 
    1685              :       // strip sub-expressions from match cases
    1686        10182 :       auto &case_expr = match_case.get_expr ();
    1687        10182 :       if (case_expr.is_marked_for_strip ())
    1688            0 :         rust_error_at (case_expr.get_locus (),
    1689              :                        "cannot strip expression in this position - outer "
    1690              :                        "attributes not allowed");
    1691              : 
    1692              :       // increment to next case if haven't continued
    1693        10182 :       ++it;
    1694              :     }
    1695              : }
    1696              : 
    1697              : void
    1698            0 : CfgStrip::visit (AST::AwaitExpr &expr)
    1699              : {
    1700              :   // initial strip test based on outer attrs
    1701            0 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1702            0 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1703              :     {
    1704            0 :       expr.mark_for_strip ();
    1705            0 :       return;
    1706              :     }
    1707              : 
    1708              :   /* can't strip awaited expr itself, but can strip sub-expressions
    1709              :    * - this is because you can't have no expr to await */
    1710            0 :   auto &awaited_expr = expr.get_awaited_expr ();
    1711            0 :   awaited_expr->accept_vis (*this);
    1712            0 :   if (awaited_expr->is_marked_for_strip ())
    1713            0 :     rust_error_at (awaited_expr->get_locus (),
    1714              :                    "cannot strip expression in this position - outer "
    1715              :                    "attributes not allowed");
    1716              : }
    1717              : 
    1718              : void
    1719            0 : CfgStrip::visit (AST::AsyncBlockExpr &expr)
    1720              : {
    1721              :   // initial strip test based on outer attrs
    1722            0 :   expand_cfg_attrs (expr.get_outer_attrs ());
    1723            0 :   if (fails_cfg_with_expand (expr.get_outer_attrs ()))
    1724              :     {
    1725            0 :       expr.mark_for_strip ();
    1726            0 :       return;
    1727              :     }
    1728              : 
    1729            0 :   AST::DefaultASTVisitor::visit (expr);
    1730              : 
    1731              :   // can't strip block itself, but can strip sub-expressions
    1732            0 :   auto &block_expr = expr.get_block_expr ();
    1733            0 :   if (block_expr->is_marked_for_strip ())
    1734            0 :     rust_error_at (block_expr->get_locus (),
    1735              :                    "cannot strip block expression in this position - outer "
    1736              :                    "attributes not allowed");
    1737              : }
    1738              : 
    1739              : void
    1740        20007 : CfgStrip::visit (AST::TypeParam &param)
    1741              : {
    1742              :   // outer attributes don't actually do anything, so ignore them
    1743              : 
    1744        20007 :   AST::DefaultASTVisitor::visit (param);
    1745              : 
    1746        20007 :   if (param.has_type () && param.get_type ().is_marked_for_strip ())
    1747            0 :     rust_error_at (param.get_type ().get_locus (),
    1748              :                    "cannot strip type in this position");
    1749        20007 : }
    1750              : 
    1751              : void
    1752         1259 : CfgStrip::visit (AST::TypeBoundWhereClauseItem &item)
    1753              : {
    1754              :   // for lifetimes shouldn't require
    1755         1259 :   AST::DefaultASTVisitor::visit (item);
    1756              : 
    1757         1259 :   auto &type = item.get_type ();
    1758         1259 :   if (type.is_marked_for_strip ())
    1759            0 :     rust_error_at (type.get_locus (), "cannot strip type in this position");
    1760         1259 : }
    1761              : 
    1762              : void
    1763         3261 : CfgStrip::visit (AST::Module &module)
    1764              : {
    1765              :   // strip test based on outer attrs
    1766         3261 :   expand_cfg_attrs (module.get_outer_attrs ());
    1767         3261 :   if (fails_cfg_with_expand (module.get_outer_attrs ()))
    1768              :     {
    1769            0 :       module.mark_for_strip ();
    1770            0 :       return;
    1771              :     }
    1772              : 
    1773         3261 :   if (module.get_kind () == AST::Module::UNLOADED)
    1774              :     {
    1775           82 :       module.load_items ();
    1776              :     }
    1777              : 
    1778              :   // strip test based on inner attrs
    1779         3261 :   expand_cfg_attrs (module.get_inner_attrs ());
    1780         3261 :   if (fails_cfg_with_expand (module.get_inner_attrs ()))
    1781              :     {
    1782            0 :       module.mark_for_strip ();
    1783            0 :       return;
    1784              :     }
    1785              : 
    1786              :   // strip items if required
    1787         3261 :   maybe_strip_pointer_allow_strip (module.get_items ());
    1788              : }
    1789              : 
    1790              : void
    1791           51 : CfgStrip::visit (AST::ExternCrate &extern_crate)
    1792              : {
    1793              :   // strip test based on outer attrs
    1794           51 :   expand_cfg_attrs (extern_crate.get_outer_attrs ());
    1795           51 :   if (fails_cfg_with_expand (extern_crate.get_outer_attrs ()))
    1796              :     {
    1797            0 :       extern_crate.mark_for_strip ();
    1798            0 :       return;
    1799              :     }
    1800              : 
    1801           51 :   if (!extern_crate.references_self ())
    1802              :     {
    1803           51 :       Session &session = Session::get_instance ();
    1804           51 :       session.load_extern_crate (extern_crate.get_referenced_crate (),
    1805              :                                  extern_crate.get_locus ());
    1806              :     }
    1807              : }
    1808              : 
    1809              : void
    1810         1848 : CfgStrip::visit (AST::UseDeclaration &use_decl)
    1811              : {
    1812              :   // strip test based on outer attrs
    1813         1848 :   expand_cfg_attrs (use_decl.get_outer_attrs ());
    1814         1848 :   if (fails_cfg_with_expand (use_decl.get_outer_attrs ()))
    1815              :     {
    1816            0 :       use_decl.mark_for_strip ();
    1817            0 :       return;
    1818              :     }
    1819              : }
    1820              : 
    1821              : void
    1822        67582 : CfgStrip::visit (AST::Function &function)
    1823              : {
    1824              :   // initial test based on outer attrs
    1825        67582 :   expand_cfg_attrs (function.get_outer_attrs ());
    1826        67582 :   if (fails_cfg_with_expand (function.get_outer_attrs ()))
    1827              :     {
    1828           31 :       function.mark_for_strip ();
    1829           31 :       return;
    1830              :     }
    1831              : 
    1832        67551 :   AST::DefaultASTVisitor::visit (function);
    1833              : 
    1834              :   /* strip function parameters if required - this is specifically
    1835              :    * allowed by spec */
    1836        67551 :   maybe_strip_function_params (function.get_function_params ());
    1837              : 
    1838        67551 :   if (function.has_return_type ())
    1839              :     {
    1840        53601 :       auto &return_type = function.get_return_type ();
    1841        53601 :       if (return_type.is_marked_for_strip ())
    1842            0 :         rust_error_at (return_type.get_locus (),
    1843              :                        "cannot strip type in this position");
    1844              :     }
    1845              : 
    1846              :   /* body should always exist - if error state, should have returned
    1847              :    * before now */
    1848              :   // can't strip block itself, but can strip sub-expressions
    1849        67551 :   if (function.has_body ())
    1850              :     {
    1851        53476 :       auto &block_expr = function.get_definition ();
    1852        53476 :       if (block_expr.value ()->is_marked_for_strip ())
    1853            0 :         rust_error_at (block_expr.value ()->get_locus (),
    1854              :                        "cannot strip block expression in this position - outer "
    1855              :                        "attributes not allowed");
    1856              :     }
    1857              : }
    1858              : 
    1859              : void
    1860         6244 : CfgStrip::visit (AST::TypeAlias &type_alias)
    1861              : {
    1862              :   // initial test based on outer attrs
    1863         6244 :   expand_cfg_attrs (type_alias.get_outer_attrs ());
    1864         6244 :   if (fails_cfg_with_expand (type_alias.get_outer_attrs ()))
    1865              :     {
    1866            0 :       type_alias.mark_for_strip ();
    1867            0 :       return;
    1868              :     }
    1869              : 
    1870         6244 :   AST::DefaultASTVisitor::visit (type_alias);
    1871              : 
    1872         6244 :   auto &type = type_alias.get_type_aliased ();
    1873         6244 :   if (type.is_marked_for_strip ())
    1874            0 :     rust_error_at (type.get_locus (), "cannot strip type in this position");
    1875              : }
    1876              : 
    1877              : void
    1878         4074 : CfgStrip::visit (AST::StructStruct &struct_item)
    1879              : {
    1880              :   // initial test based on outer attrs
    1881         4074 :   expand_cfg_attrs (struct_item.get_outer_attrs ());
    1882         4074 :   if (fails_cfg_with_expand (struct_item.get_outer_attrs ()))
    1883              :     {
    1884            2 :       struct_item.mark_for_strip ();
    1885            2 :       return;
    1886              :     }
    1887              : 
    1888         4072 :   AST::DefaultASTVisitor::visit (struct_item);
    1889              : 
    1890              :   /* strip struct fields if required - this is presumably
    1891              :    * allowed by spec */
    1892         4072 :   maybe_strip_struct_fields (struct_item.get_fields ());
    1893              : }
    1894              : void
    1895         2454 : CfgStrip::visit (AST::TupleStruct &tuple_struct)
    1896              : {
    1897              :   // initial test based on outer attrs
    1898         2454 :   expand_cfg_attrs (tuple_struct.get_outer_attrs ());
    1899         2454 :   if (fails_cfg_with_expand (tuple_struct.get_outer_attrs ()))
    1900              :     {
    1901            0 :       tuple_struct.mark_for_strip ();
    1902            0 :       return;
    1903              :     }
    1904              : 
    1905         2454 :   AST::DefaultASTVisitor::visit (tuple_struct);
    1906              : 
    1907              :   /* strip struct fields if required - this is presumably
    1908              :    * allowed by spec */
    1909         2454 :   maybe_strip_tuple_fields (tuple_struct.get_fields ());
    1910              : }
    1911              : void
    1912         2112 : CfgStrip::visit (AST::EnumItem &item)
    1913              : {
    1914              :   // initial test based on outer attrs
    1915         2112 :   expand_cfg_attrs (item.get_outer_attrs ());
    1916         2112 :   if (fails_cfg_with_expand (item.get_outer_attrs ()))
    1917              :     {
    1918            0 :       item.mark_for_strip ();
    1919            0 :       return;
    1920              :     }
    1921              : }
    1922              : 
    1923              : void
    1924         2250 : CfgStrip::visit (AST::EnumItemTuple &item)
    1925              : {
    1926              :   // initial test based on outer attrs
    1927         2250 :   expand_cfg_attrs (item.get_outer_attrs ());
    1928         2250 :   if (fails_cfg_with_expand (item.get_outer_attrs ()))
    1929              :     {
    1930            0 :       item.mark_for_strip ();
    1931            0 :       return;
    1932              :     }
    1933              : 
    1934              :   /* strip item fields if required - this is presumably
    1935              :    * allowed by spec */
    1936         2250 :   maybe_strip_tuple_fields (item.get_tuple_fields ());
    1937              : }
    1938              : 
    1939              : void
    1940          440 : CfgStrip::visit (AST::EnumItemStruct &item)
    1941              : {
    1942              :   // initial test based on outer attrs
    1943          440 :   expand_cfg_attrs (item.get_outer_attrs ());
    1944          440 :   if (fails_cfg_with_expand (item.get_outer_attrs ()))
    1945              :     {
    1946            0 :       item.mark_for_strip ();
    1947            0 :       return;
    1948              :     }
    1949              : 
    1950              :   /* strip item fields if required - this is presumably
    1951              :    * allowed by spec */
    1952          440 :   maybe_strip_struct_fields (item.get_struct_fields ());
    1953              : }
    1954              : 
    1955              : void
    1956         1378 : CfgStrip::visit (AST::EnumItemDiscriminant &item)
    1957              : {
    1958              :   // initial test based on outer attrs
    1959         1378 :   expand_cfg_attrs (item.get_outer_attrs ());
    1960         1378 :   if (fails_cfg_with_expand (item.get_outer_attrs ()))
    1961              :     {
    1962            0 :       item.mark_for_strip ();
    1963            0 :       return;
    1964              :     }
    1965              : 
    1966         1378 :   AST::DefaultASTVisitor::visit (item);
    1967              :   /* strip any internal sub-expressions - expression itself isn't
    1968              :    * allowed to have external attributes in this position so can't be
    1969              :    * stripped. */
    1970         1378 :   auto &expr = item.get_expr ();
    1971         1378 :   if (expr.is_marked_for_strip ())
    1972            0 :     rust_error_at (expr.get_locus (),
    1973              :                    "cannot strip expression in this position - outer "
    1974              :                    "attributes not allowed");
    1975              : }
    1976              : void
    1977         1328 : CfgStrip::visit (AST::Enum &enum_item)
    1978              : {
    1979              :   // initial test based on outer attrs
    1980         1328 :   expand_cfg_attrs (enum_item.get_outer_attrs ());
    1981         1328 :   if (fails_cfg_with_expand (enum_item.get_outer_attrs ()))
    1982              :     {
    1983            0 :       enum_item.mark_for_strip ();
    1984            0 :       return;
    1985              :     }
    1986              : 
    1987         1328 :   AST::DefaultASTVisitor::visit (enum_item);
    1988              : 
    1989              :   /* strip enum fields if required - this is presumably
    1990              :    * allowed by spec */
    1991         1328 :   maybe_strip_pointer_allow_strip (enum_item.get_variants ());
    1992              : }
    1993              : void
    1994          222 : CfgStrip::visit (AST::Union &union_item)
    1995              : {
    1996              :   // initial test based on outer attrs
    1997          222 :   expand_cfg_attrs (union_item.get_outer_attrs ());
    1998          222 :   if (fails_cfg_with_expand (union_item.get_outer_attrs ()))
    1999              :     {
    2000            0 :       union_item.mark_for_strip ();
    2001            0 :       return;
    2002              :     }
    2003              : 
    2004          222 :   AST::DefaultASTVisitor::visit (union_item);
    2005              : 
    2006              :   /* strip union fields if required - this is presumably
    2007              :    * allowed by spec */
    2008          222 :   maybe_strip_struct_fields (union_item.get_variants ());
    2009              : }
    2010              : void
    2011         1503 : CfgStrip::visit (AST::ConstantItem &const_item)
    2012              : {
    2013              :   // initial test based on outer attrs
    2014         1503 :   expand_cfg_attrs (const_item.get_outer_attrs ());
    2015         1503 :   if (fails_cfg_with_expand (const_item.get_outer_attrs ()))
    2016              :     {
    2017            0 :       const_item.mark_for_strip ();
    2018            0 :       return;
    2019              :     }
    2020              : 
    2021         1503 :   AST::DefaultASTVisitor::visit (const_item);
    2022              : 
    2023              :   // strip any sub-types
    2024         1503 :   auto &type = const_item.get_type ();
    2025         1503 :   if (type.is_marked_for_strip ())
    2026            0 :     rust_error_at (type.get_locus (), "cannot strip type in this position");
    2027              : 
    2028              :   /* strip any internal sub-expressions - expression itself isn't
    2029              :    * allowed to have external attributes in this position so can't be
    2030              :    * stripped. */
    2031         1503 :   if (const_item.has_expr ())
    2032              :     {
    2033         1361 :       auto &expr = const_item.get_expr ();
    2034         1361 :       if (expr.is_marked_for_strip ())
    2035            0 :         rust_error_at (expr.get_locus (),
    2036              :                        "cannot strip expression in this position - outer "
    2037              :                        "attributes not allowed");
    2038              :     }
    2039              : }
    2040              : void
    2041          121 : CfgStrip::visit (AST::StaticItem &static_item)
    2042              : {
    2043              :   // initial test based on outer attrs
    2044          121 :   expand_cfg_attrs (static_item.get_outer_attrs ());
    2045          121 :   if (fails_cfg_with_expand (static_item.get_outer_attrs ()))
    2046              :     {
    2047            0 :       static_item.mark_for_strip ();
    2048            0 :       return;
    2049              :     }
    2050              : 
    2051          121 :   AST::DefaultASTVisitor::visit (static_item);
    2052              : 
    2053              :   // strip any sub-types
    2054          121 :   auto &type = static_item.get_type ();
    2055              : 
    2056          121 :   if (type.is_marked_for_strip ())
    2057            0 :     rust_error_at (type.get_locus (), "cannot strip type in this position");
    2058              : 
    2059              :   /* strip any internal sub-expressions - expression itself isn't
    2060              :    * allowed to have external attributes in this position so can't be
    2061              :    * stripped. */
    2062          121 :   auto &expr = static_item.get_expr ();
    2063          121 :   if (expr.is_marked_for_strip ())
    2064            0 :     rust_error_at (expr.get_locus (),
    2065              :                    "cannot strip expression in this position - outer "
    2066              :                    "attributes not allowed");
    2067              : }
    2068              : 
    2069              : void
    2070         3686 : CfgStrip::visit (AST::TraitItemType &item)
    2071              : {
    2072              :   // initial test based on outer attrs
    2073         3686 :   expand_cfg_attrs (item.get_outer_attrs ());
    2074         3686 :   if (fails_cfg_with_expand (item.get_outer_attrs ()))
    2075              :     {
    2076            0 :       item.mark_for_strip ();
    2077            0 :       return;
    2078              :     }
    2079              : 
    2080         3686 :   AST::DefaultASTVisitor::visit (item);
    2081              : }
    2082              : 
    2083              : void
    2084         8674 : CfgStrip::visit (AST::Trait &trait)
    2085              : {
    2086              :   // initial strip test based on outer attrs
    2087         8674 :   expand_cfg_attrs (trait.get_outer_attrs ());
    2088         8674 :   if (fails_cfg_with_expand (trait.get_outer_attrs ()))
    2089              :     {
    2090            1 :       trait.mark_for_strip ();
    2091            1 :       return;
    2092              :     }
    2093              : 
    2094              :   // strip test based on inner attrs
    2095         8673 :   expand_cfg_attrs (trait.get_inner_attrs ());
    2096         8673 :   if (fails_cfg_with_expand (trait.get_inner_attrs ()))
    2097              :     {
    2098            0 :       trait.mark_for_strip ();
    2099            0 :       return;
    2100              :     }
    2101              : 
    2102         8673 :   AST::DefaultASTVisitor::visit (trait);
    2103              : 
    2104         8673 :   maybe_strip_pointer_allow_strip (trait.get_trait_items ());
    2105              : }
    2106              : 
    2107              : void
    2108         2201 : CfgStrip::visit (AST::InherentImpl &impl)
    2109              : {
    2110              :   // initial strip test based on outer attrs
    2111         2201 :   expand_cfg_attrs (impl.get_outer_attrs ());
    2112         2201 :   if (fails_cfg_with_expand (impl.get_outer_attrs ()))
    2113              :     {
    2114            1 :       impl.mark_for_strip ();
    2115            1 :       return;
    2116              :     }
    2117              : 
    2118              :   // strip test based on inner attrs
    2119         2200 :   expand_cfg_attrs (impl.get_inner_attrs ());
    2120         2200 :   if (fails_cfg_with_expand (impl.get_inner_attrs ()))
    2121              :     {
    2122            0 :       impl.mark_for_strip ();
    2123            0 :       return;
    2124              :     }
    2125              : 
    2126         2200 :   AST::DefaultASTVisitor::visit (impl);
    2127              : 
    2128         2200 :   auto &type = impl.get_type ();
    2129              : 
    2130         2200 :   if (type.is_marked_for_strip ())
    2131            0 :     rust_error_at (type.get_locus (), "cannot strip type in this position");
    2132              : 
    2133         2200 :   maybe_strip_pointer_allow_strip (impl.get_impl_items ());
    2134              : }
    2135              : 
    2136              : void
    2137        11160 : CfgStrip::visit (AST::TraitImpl &impl)
    2138              : {
    2139              :   // initial strip test based on outer attrs
    2140        11160 :   expand_cfg_attrs (impl.get_outer_attrs ());
    2141        11160 :   if (fails_cfg_with_expand (impl.get_outer_attrs ()))
    2142              :     {
    2143            0 :       impl.mark_for_strip ();
    2144            0 :       return;
    2145              :     }
    2146              : 
    2147              :   // strip test based on inner attrs
    2148        11160 :   expand_cfg_attrs (impl.get_inner_attrs ());
    2149        11160 :   if (fails_cfg_with_expand (impl.get_inner_attrs ()))
    2150              :     {
    2151            0 :       impl.mark_for_strip ();
    2152            0 :       return;
    2153              :     }
    2154              : 
    2155        11160 :   AST::DefaultASTVisitor::visit (impl);
    2156              : 
    2157        11160 :   auto &type = impl.get_type ();
    2158        11160 :   if (type.is_marked_for_strip ())
    2159            0 :     rust_error_at (type.get_locus (), "cannot strip type in this position");
    2160              : 
    2161        11160 :   auto &trait_path = impl.get_trait_path ();
    2162        11160 :   visit (trait_path);
    2163        11160 :   if (trait_path.is_marked_for_strip ())
    2164            0 :     rust_error_at (trait_path.get_locus (),
    2165              :                    "cannot strip typepath in this position");
    2166              : 
    2167        11160 :   maybe_strip_pointer_allow_strip (impl.get_impl_items ());
    2168              : }
    2169              : 
    2170              : void
    2171            2 : CfgStrip::visit (AST::ExternalTypeItem &item)
    2172              : {
    2173            2 :   expand_cfg_attrs (item.get_outer_attrs ());
    2174              : 
    2175            2 :   if (fails_cfg_with_expand (item.get_outer_attrs ()))
    2176            0 :     item.mark_for_strip ();
    2177              : 
    2178              :   // TODO: Can we do anything like expand a macro here?
    2179              :   // extern "C" { type ffi_ty!(); }
    2180              :   // ?
    2181            2 : }
    2182              : 
    2183              : void
    2184            2 : CfgStrip::visit (AST::ExternalStaticItem &item)
    2185              : {
    2186              :   // strip test based on outer attrs
    2187            2 :   expand_cfg_attrs (item.get_outer_attrs ());
    2188            2 :   if (fails_cfg_with_expand (item.get_outer_attrs ()))
    2189              :     {
    2190            0 :       item.mark_for_strip ();
    2191            0 :       return;
    2192              :     }
    2193              : 
    2194            2 :   AST::DefaultASTVisitor::visit (item);
    2195              : 
    2196            2 :   auto &type = item.get_type ();
    2197            2 :   if (type.is_marked_for_strip ())
    2198            0 :     rust_error_at (type.get_locus (), "cannot strip type in this position");
    2199              : }
    2200              : 
    2201              : void
    2202         3351 : CfgStrip::visit (AST::ExternBlock &block)
    2203              : {
    2204              :   // initial strip test based on outer attrs
    2205         3351 :   expand_cfg_attrs (block.get_outer_attrs ());
    2206         3351 :   if (fails_cfg_with_expand (block.get_outer_attrs ()))
    2207              :     {
    2208            0 :       block.mark_for_strip ();
    2209            0 :       return;
    2210              :     }
    2211              : 
    2212              :   // strip test based on inner attrs
    2213         3351 :   expand_cfg_attrs (block.get_inner_attrs ());
    2214         3351 :   if (fails_cfg_with_expand (block.get_inner_attrs ()))
    2215              :     {
    2216            0 :       block.mark_for_strip ();
    2217            0 :       return;
    2218              :     }
    2219              : 
    2220         3351 :   maybe_strip_pointer_allow_strip (block.get_extern_items ());
    2221              : }
    2222              : 
    2223              : void
    2224         3815 : CfgStrip::visit (AST::MacroRulesDefinition &rules_def)
    2225              : {
    2226              :   // initial strip test based on outer attrs
    2227         3815 :   expand_cfg_attrs (rules_def.get_outer_attrs ());
    2228         3815 :   if (fails_cfg_with_expand (rules_def.get_outer_attrs ()))
    2229              :     {
    2230            0 :       rules_def.mark_for_strip ();
    2231            0 :       return;
    2232              :     }
    2233              : }
    2234              : 
    2235              : void
    2236       164034 : CfgStrip::visit (AST::IdentifierPattern &pattern)
    2237              : {
    2238              :   // can only strip sub-patterns of the inner pattern to bind
    2239       164034 :   if (!pattern.has_subpattern ())
    2240              :     return;
    2241              : 
    2242           70 :   AST::DefaultASTVisitor::visit (pattern);
    2243              : 
    2244           70 :   auto &sub_pattern = pattern.get_subpattern ();
    2245           70 :   if (sub_pattern.is_marked_for_strip ())
    2246            0 :     rust_error_at (sub_pattern.get_locus (),
    2247              :                    "cannot strip pattern in this position");
    2248              : }
    2249              : 
    2250              : void
    2251           42 : CfgStrip::visit (AST::RangePatternBoundPath &bound)
    2252              : {
    2253              :   // can expand path, but not strip it directly
    2254           42 :   auto &path = bound.get_path ();
    2255           42 :   visit (path);
    2256           42 :   if (path.is_marked_for_strip ())
    2257            0 :     rust_error_at (path.get_locus (), "cannot strip path in this position");
    2258           42 : }
    2259              : 
    2260              : void
    2261            0 : CfgStrip::visit (AST::RangePatternBoundQualPath &bound)
    2262              : {
    2263              :   // can expand path, but not strip it directly
    2264            0 :   auto &path = bound.get_qualified_path ();
    2265            0 :   visit (path);
    2266            0 :   if (path.is_marked_for_strip ())
    2267            0 :     rust_error_at (path.get_locus (), "cannot strip path in this position");
    2268            0 : }
    2269              : 
    2270              : void
    2271          820 : CfgStrip::visit (AST::ReferencePattern &pattern)
    2272              : {
    2273          820 :   AST::DefaultASTVisitor::visit (pattern);
    2274              : 
    2275          820 :   auto &sub_pattern = pattern.get_referenced_pattern ();
    2276          820 :   if (sub_pattern.is_marked_for_strip ())
    2277            0 :     rust_error_at (sub_pattern.get_locus (),
    2278              :                    "cannot strip pattern in this position");
    2279          820 : }
    2280              : void
    2281           78 : CfgStrip::visit (AST::StructPatternFieldTuplePat &field)
    2282              : {
    2283              :   // initial strip test based on outer attrs
    2284           78 :   expand_cfg_attrs (field.get_outer_attrs ());
    2285           78 :   if (fails_cfg_with_expand (field.get_outer_attrs ()))
    2286              :     {
    2287            0 :       field.mark_for_strip ();
    2288            0 :       return;
    2289              :     }
    2290              : 
    2291           78 :   AST::DefaultASTVisitor::visit (field);
    2292              : 
    2293              :   // strip sub-patterns (can't strip top-level pattern)
    2294           78 :   auto &sub_pattern = field.get_index_pattern ();
    2295           78 :   if (sub_pattern.is_marked_for_strip ())
    2296            0 :     rust_error_at (sub_pattern.get_locus (),
    2297              :                    "cannot strip pattern in this position");
    2298              : }
    2299              : 
    2300              : void
    2301          516 : CfgStrip::visit (AST::StructPatternFieldIdentPat &field)
    2302              : {
    2303              :   // initial strip test based on outer attrs
    2304          516 :   expand_cfg_attrs (field.get_outer_attrs ());
    2305          516 :   if (fails_cfg_with_expand (field.get_outer_attrs ()))
    2306              :     {
    2307            0 :       field.mark_for_strip ();
    2308            0 :       return;
    2309              :     }
    2310              : 
    2311          516 :   AST::DefaultASTVisitor::visit (field);
    2312              :   // strip sub-patterns (can't strip top-level pattern)
    2313          516 :   auto &sub_pattern = field.get_ident_pattern ();
    2314          516 :   if (sub_pattern.is_marked_for_strip ())
    2315            0 :     rust_error_at (sub_pattern.get_locus (),
    2316              :                    "cannot strip pattern in this position");
    2317              : }
    2318              : void
    2319          252 : CfgStrip::visit (AST::StructPatternFieldIdent &field)
    2320              : {
    2321              :   // initial strip test based on outer attrs
    2322          252 :   expand_cfg_attrs (field.get_outer_attrs ());
    2323          252 :   if (fails_cfg_with_expand (field.get_outer_attrs ()))
    2324              :     {
    2325            0 :       field.mark_for_strip ();
    2326            0 :       return;
    2327              :     }
    2328              : }
    2329              : 
    2330              : void
    2331          502 : CfgStrip::visit (AST::StructPattern &pattern)
    2332              : {
    2333              :   // expand (but don't strip) path
    2334          502 :   auto &path = pattern.get_path ();
    2335          502 :   visit (path);
    2336          502 :   if (path.is_marked_for_strip ())
    2337            0 :     rust_error_at (path.get_locus (), "cannot strip path in this position");
    2338              : 
    2339              :   /* TODO: apparently struct pattern fields can have outer attrs. so can they
    2340              :    * be stripped? */
    2341          502 :   if (!pattern.has_struct_pattern_elems ())
    2342              :     return;
    2343              : 
    2344          500 :   auto &elems = pattern.get_struct_pattern_elems ();
    2345              : 
    2346              :   // assuming you can strip struct pattern fields
    2347          500 :   maybe_strip_pointer_allow_strip (elems.get_struct_pattern_fields ());
    2348              : 
    2349              :   // assuming you can strip the ".." part
    2350          500 :   if (elems.has_rest ())
    2351              :     {
    2352           10 :       expand_cfg_attrs (elems.get_etc_outer_attrs ());
    2353           10 :       if (fails_cfg_with_expand (elems.get_etc_outer_attrs ()))
    2354            0 :         elems.strip_etc ();
    2355              :     }
    2356              : }
    2357              : 
    2358              : void
    2359         4788 : CfgStrip::visit (AST::TupleStructItemsNoRest &tuple_items)
    2360              : {
    2361         4788 :   AST::DefaultASTVisitor::visit (tuple_items);
    2362              :   // can't strip individual patterns, only sub-patterns
    2363        10114 :   for (auto &pattern : tuple_items.get_patterns ())
    2364              :     {
    2365         5326 :       if (pattern->is_marked_for_strip ())
    2366            0 :         rust_error_at (pattern->get_locus (),
    2367              :                        "cannot strip pattern in this position");
    2368              :       // TODO: quit stripping now? or keep going?
    2369              :     }
    2370         4788 : }
    2371              : void
    2372          148 : CfgStrip::visit (AST::TupleStructItemsHasRest &tuple_items)
    2373              : {
    2374          148 :   AST::DefaultASTVisitor::visit (tuple_items);
    2375              :   // can't strip individual patterns, only sub-patterns
    2376          266 :   for (auto &lower_pattern : tuple_items.get_lower_patterns ())
    2377              :     {
    2378          118 :       if (lower_pattern->is_marked_for_strip ())
    2379            0 :         rust_error_at (lower_pattern->get_locus (),
    2380              :                        "cannot strip pattern in this position");
    2381              :       // TODO: quit stripping now? or keep going?
    2382              :     }
    2383          214 :   for (auto &upper_pattern : tuple_items.get_upper_patterns ())
    2384              :     {
    2385           66 :       if (upper_pattern->is_marked_for_strip ())
    2386            0 :         rust_error_at (upper_pattern->get_locus (),
    2387              :                        "cannot strip pattern in this position");
    2388              :       // TODO: quit stripping now? or keep going?
    2389              :     }
    2390          148 : }
    2391              : 
    2392              : void
    2393         4936 : CfgStrip::visit (AST::TupleStructPattern &pattern)
    2394              : {
    2395              :   // expand (but don't strip) path
    2396         4936 :   auto &path = pattern.get_path ();
    2397         4936 :   visit (path);
    2398         4936 :   if (path.is_marked_for_strip ())
    2399            0 :     rust_error_at (path.get_locus (), "cannot strip path in this position");
    2400              : 
    2401         4936 :   AST::DefaultASTVisitor::visit (pattern);
    2402         4936 : }
    2403              : 
    2404              : void
    2405         3934 : CfgStrip::visit (AST::TuplePatternItemsNoRest &tuple_items)
    2406              : {
    2407         3934 :   AST::DefaultASTVisitor::visit (tuple_items);
    2408              : 
    2409              :   // can't strip individual patterns, only sub-patterns
    2410        11814 :   for (auto &pattern : tuple_items.get_patterns ())
    2411              :     {
    2412         7880 :       if (pattern->is_marked_for_strip ())
    2413            0 :         rust_error_at (pattern->get_locus (),
    2414              :                        "cannot strip pattern in this position");
    2415              :       // TODO: quit stripping now? or keep going?
    2416              :     }
    2417         3934 : }
    2418              : 
    2419              : void
    2420          102 : CfgStrip::visit (AST::TuplePatternItemsHasRest &tuple_items)
    2421              : {
    2422          102 :   AST::DefaultASTVisitor::visit (tuple_items);
    2423              : 
    2424              :   // can't strip individual patterns, only sub-patterns
    2425          206 :   for (auto &lower_pattern : tuple_items.get_lower_patterns ())
    2426              :     {
    2427          104 :       if (lower_pattern->is_marked_for_strip ())
    2428            0 :         rust_error_at (lower_pattern->get_locus (),
    2429              :                        "cannot strip pattern in this position");
    2430              :       // TODO: quit stripping now? or keep going?
    2431              :     }
    2432          214 :   for (auto &upper_pattern : tuple_items.get_upper_patterns ())
    2433              :     {
    2434          112 :       if (upper_pattern->is_marked_for_strip ())
    2435            0 :         rust_error_at (upper_pattern->get_locus (),
    2436              :                        "cannot strip pattern in this position");
    2437              :       // TODO: quit stripping now? or keep going?
    2438              :     }
    2439          102 : }
    2440              : 
    2441              : void
    2442          176 : CfgStrip::visit (AST::GroupedPattern &pattern)
    2443              : {
    2444          176 :   AST::DefaultASTVisitor::visit (pattern);
    2445              :   // can't strip inner pattern, only sub-patterns
    2446          176 :   auto &pattern_in_parens = pattern.get_pattern_in_parens ();
    2447              : 
    2448          176 :   if (pattern_in_parens.is_marked_for_strip ())
    2449            0 :     rust_error_at (pattern_in_parens.get_locus (),
    2450              :                    "cannot strip pattern in this position");
    2451          176 : }
    2452              : 
    2453              : void
    2454          120 : CfgStrip::visit (AST::SlicePatternItemsNoRest &items)
    2455              : {
    2456          120 :   AST::DefaultASTVisitor::visit (items);
    2457              :   // can't strip individual patterns, only sub-patterns
    2458          360 :   for (auto &pattern : items.get_patterns ())
    2459              :     {
    2460          240 :       if (pattern->is_marked_for_strip ())
    2461            0 :         rust_error_at (pattern->get_locus (),
    2462              :                        "cannot strip pattern in this position");
    2463              :     }
    2464          120 : }
    2465              : 
    2466              : void
    2467          172 : CfgStrip::visit (AST::SlicePatternItemsHasRest &items)
    2468              : {
    2469          172 :   AST::DefaultASTVisitor::visit (items);
    2470              :   // can't strip individual patterns, only sub-patterns
    2471          342 :   for (auto &pattern : items.get_lower_patterns ())
    2472              :     {
    2473          170 :       if (pattern->is_marked_for_strip ())
    2474            0 :         rust_error_at (pattern->get_locus (),
    2475              :                        "cannot strip pattern in this position");
    2476              :     }
    2477          342 :   for (auto &pattern : items.get_upper_patterns ())
    2478              :     {
    2479          170 :       if (pattern->is_marked_for_strip ())
    2480            0 :         rust_error_at (pattern->get_locus (),
    2481              :                        "cannot strip pattern in this position");
    2482              :     }
    2483          172 : }
    2484              : 
    2485              : void
    2486          292 : CfgStrip::visit (AST::SlicePattern &pattern)
    2487              : {
    2488          292 :   AST::DefaultASTVisitor::visit (pattern);
    2489          292 : }
    2490              : 
    2491              : void
    2492          970 : CfgStrip::visit (AST::AltPattern &pattern)
    2493              : {
    2494          970 :   AST::DefaultASTVisitor::visit (pattern);
    2495              :   // can't strip individual patterns, only sub-patterns
    2496         3040 :   for (auto &alt : pattern.get_alts ())
    2497              :     {
    2498         2070 :       if (alt->is_marked_for_strip ())
    2499            0 :         rust_error_at (alt->get_locus (),
    2500              :                        "cannot strip pattern in this position");
    2501              :       // TODO: quit stripping now? or keep going?
    2502              :     }
    2503          970 : }
    2504              : 
    2505              : void
    2506        73880 : CfgStrip::visit (AST::LetStmt &stmt)
    2507              : {
    2508              :   // initial strip test based on outer attrs
    2509        73880 :   expand_cfg_attrs (stmt.get_outer_attrs ());
    2510        73880 :   if (fails_cfg_with_expand (stmt.get_outer_attrs ()))
    2511              :     {
    2512            0 :       stmt.mark_for_strip ();
    2513            0 :       return;
    2514              :     }
    2515              : 
    2516        73880 :   AST::DefaultASTVisitor::visit (stmt);
    2517              :   // can't strip pattern, but call for sub-patterns
    2518        73880 :   auto &pattern = stmt.get_pattern ();
    2519        73880 :   if (pattern.is_marked_for_strip ())
    2520            0 :     rust_error_at (pattern.get_locus (),
    2521              :                    "cannot strip pattern in this position");
    2522              : 
    2523              :   // similar for type
    2524        73880 :   if (stmt.has_type ())
    2525              :     {
    2526        10010 :       auto &type = stmt.get_type ();
    2527              : 
    2528        10010 :       if (type.is_marked_for_strip ())
    2529            0 :         rust_error_at (type.get_locus (), "cannot strip type in this position");
    2530              :     }
    2531              : 
    2532              :   /* strip any internal sub-expressions - expression itself isn't
    2533              :    * allowed to have external attributes in this position so can't be
    2534              :    * stripped */
    2535        73880 :   if (stmt.has_init_expr ())
    2536              :     {
    2537        68756 :       auto &init_expr = stmt.get_init_expr ();
    2538              : 
    2539        68756 :       if (init_expr.is_marked_for_strip ())
    2540            0 :         rust_error_at (init_expr.get_locus (),
    2541              :                        "cannot strip expression in this position - outer "
    2542              :                        "attributes not allowed");
    2543              :     }
    2544              : }
    2545              : 
    2546              : void
    2547        61852 : CfgStrip::visit (AST::ExprStmt &stmt)
    2548              : {
    2549              :   // outer attributes associated with expr, so rely on expr
    2550              : 
    2551              :   // guard - should prevent null pointer expr
    2552        61852 :   if (stmt.is_marked_for_strip ())
    2553              :     return;
    2554              : 
    2555        61852 :   AST::DefaultASTVisitor::visit (stmt);
    2556              :   // strip if expr is to be stripped
    2557        61852 :   auto &expr = stmt.get_expr ();
    2558        61852 :   if (expr.is_marked_for_strip ())
    2559              :     {
    2560           18 :       stmt.mark_for_strip ();
    2561           18 :       return;
    2562              :     }
    2563              : }
    2564              : 
    2565              : void
    2566         6873 : CfgStrip::visit (AST::TraitBound &bound)
    2567              : {
    2568              :   // nothing in for lifetimes to strip
    2569              : 
    2570              :   // expand but don't strip type path
    2571         6873 :   auto &path = bound.get_type_path ();
    2572         6873 :   visit (path);
    2573         6873 :   if (path.is_marked_for_strip ())
    2574            0 :     rust_error_at (path.get_locus (),
    2575              :                    "cannot strip type path in this position");
    2576         6873 : }
    2577              : 
    2578              : void
    2579           22 : CfgStrip::visit (AST::ParenthesisedType &type)
    2580              : {
    2581           22 :   AST::DefaultASTVisitor::visit (type);
    2582              :   // expand but don't strip inner type
    2583           22 :   auto &inner_type = type.get_type_in_parens ();
    2584           22 :   if (inner_type->is_marked_for_strip ())
    2585            0 :     rust_error_at (inner_type->get_locus (),
    2586              :                    "cannot strip type in this position");
    2587           22 : }
    2588              : 
    2589              : void
    2590         1799 : CfgStrip::visit (AST::TupleType &type)
    2591              : {
    2592         1799 :   AST::DefaultASTVisitor::visit (type);
    2593              :   // TODO: assuming that types can't be stripped as types don't have outer
    2594              :   // attributes
    2595         4681 :   for (auto &elem_type : type.get_elems ())
    2596              :     {
    2597         2882 :       if (elem_type->is_marked_for_strip ())
    2598            0 :         rust_error_at (elem_type->get_locus (),
    2599              :                        "cannot strip type in this position");
    2600              :     }
    2601         1799 : }
    2602              : 
    2603              : void
    2604        48521 : CfgStrip::visit (AST::RawPointerType &type)
    2605              : {
    2606        48521 :   AST::DefaultASTVisitor::visit (type);
    2607              :   // expand but don't strip type pointed to
    2608        48521 :   auto &pointed_type = type.get_type_pointed_to ();
    2609        48521 :   if (pointed_type.is_marked_for_strip ())
    2610            0 :     rust_error_at (pointed_type.get_locus (),
    2611              :                    "cannot strip type in this position");
    2612        48521 : }
    2613              : 
    2614              : void
    2615        32958 : CfgStrip::visit (AST::ReferenceType &type)
    2616              : {
    2617        32958 :   AST::DefaultASTVisitor::visit (type);
    2618              :   // expand but don't strip type referenced
    2619        32958 :   auto &referenced_type = type.get_type_referenced ();
    2620        32958 :   if (referenced_type.is_marked_for_strip ())
    2621            0 :     rust_error_at (referenced_type.get_locus (),
    2622              :                    "cannot strip type in this position");
    2623        32958 : }
    2624              : 
    2625              : void
    2626         4876 : CfgStrip::visit (AST::ArrayType &type)
    2627              : {
    2628         4876 :   AST::DefaultASTVisitor::visit (type);
    2629              :   // expand but don't strip type referenced
    2630         4876 :   auto &base_type = type.get_elem_type ();
    2631         4876 :   if (base_type.is_marked_for_strip ())
    2632            0 :     rust_error_at (base_type.get_locus (),
    2633              :                    "cannot strip type in this position");
    2634              : 
    2635              :   // same for expression
    2636         4876 :   auto &size_expr = type.get_size_expr ();
    2637         4876 :   if (size_expr.is_marked_for_strip ())
    2638            0 :     rust_error_at (size_expr.get_locus (),
    2639              :                    "cannot strip expression in this position");
    2640         4876 : }
    2641              : void
    2642         4023 : CfgStrip::visit (AST::SliceType &type)
    2643              : {
    2644         4023 :   AST::DefaultASTVisitor::visit (type);
    2645              :   // expand but don't strip elem type
    2646         4023 :   auto &elem_type = type.get_elem_type ();
    2647         4023 :   if (elem_type.is_marked_for_strip ())
    2648            0 :     rust_error_at (elem_type.get_locus (),
    2649              :                    "cannot strip type in this position");
    2650         4023 : }
    2651              : 
    2652              : void
    2653          254 : CfgStrip::visit (AST::BareFunctionType &type)
    2654              : {
    2655              :   // seem to be no generics
    2656          254 :   AST::DefaultASTVisitor::visit (type);
    2657              : 
    2658              :   // presumably function params can be stripped
    2659          254 :   auto &params = type.get_function_params ();
    2660          474 :   for (auto it = params.begin (); it != params.end ();)
    2661              :     {
    2662          220 :       auto &param = *it;
    2663              : 
    2664          220 :       auto &param_attrs = param.get_outer_attrs ();
    2665          220 :       expand_cfg_attrs (param_attrs);
    2666          220 :       if (fails_cfg_with_expand (param_attrs))
    2667              :         {
    2668            0 :           it = params.erase (it);
    2669            0 :           continue;
    2670              :         }
    2671              : 
    2672          220 :       auto &type = param.get_type ();
    2673          220 :       if (type.is_marked_for_strip ())
    2674            0 :         rust_error_at (type.get_locus (), "cannot strip type in this position");
    2675              : 
    2676              :       // increment if nothing else happens
    2677          220 :       ++it;
    2678              :     }
    2679              : 
    2680              :   /* TODO: assuming that variadic nature cannot be stripped. If this
    2681              :    * is not true, then have code here to do so. */
    2682              : 
    2683          254 :   if (type.has_return_type ())
    2684              :     {
    2685              :       // FIXME: Can we have type expansion in this position?
    2686              :       // In that case, we need to handle AST::TypeNoBounds on top of just
    2687              :       // AST::Types
    2688          182 :       auto &return_type = type.get_return_type ();
    2689          182 :       if (return_type.is_marked_for_strip ())
    2690            0 :         rust_error_at (return_type.get_locus (),
    2691              :                        "cannot strip type in this position");
    2692              :     }
    2693              : 
    2694              :   // no where clause, apparently
    2695          254 : }
    2696              : 
    2697              : void
    2698        39642 : CfgStrip::visit (AST::SelfParam &param)
    2699              : {
    2700        39642 :   AST::DefaultASTVisitor::visit (param);
    2701              : 
    2702        39642 :   if (param.has_type ())
    2703              :     {
    2704            4 :       auto &type = param.get_type ();
    2705            4 :       if (type.is_marked_for_strip ())
    2706            0 :         rust_error_at (type.get_locus (), "cannot strip type in this position");
    2707              :     }
    2708              :   /* TODO: maybe check for invariants being violated - e.g. both type and
    2709              :    * lifetime? */
    2710        39642 : }
    2711              : 
    2712              : } // namespace Rust
        

Generated by: LCOV version 2.4-beta

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