| // Copyright (C) 2020-2023 Free Software Foundation, Inc. |
| |
| // This file is part of GCC. |
| |
| // GCC is free software; you can redistribute it and/or modify it under |
| // the terms of the GNU General Public License as published by the Free |
| // Software Foundation; either version 3, or (at your option) any later |
| // version. |
| |
| // GCC is distributed in the hope that it will be useful, but WITHOUT ANY |
| // WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| // FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| // for more details. |
| |
| // You should have received a copy of the GNU General Public License |
| // along with GCC; see the file COPYING3. If not see |
| // <http://www.gnu.org/licenses/>. |
| |
| #include "rust-attribute-visitor.h" |
| #include "rust-session-manager.h" |
| |
| namespace Rust { |
| |
| // Visitor used to expand attributes. |
| void |
| AttrVisitor::expand_struct_fields (std::vector<AST::StructField> &fields) |
| { |
| for (auto it = fields.begin (); it != fields.end ();) |
| { |
| auto &field = *it; |
| |
| auto &field_attrs = field.get_outer_attrs (); |
| expander.expand_cfg_attrs (field_attrs); |
| if (expander.fails_cfg_with_expand (field_attrs)) |
| { |
| it = fields.erase (it); |
| continue; |
| } |
| |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| |
| // expand sub-types of type, but can't strip type itself |
| auto &type = field.get_field_type (); |
| type->accept_vis (*this); |
| |
| maybe_expand_type (type); |
| |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), |
| "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| |
| // if nothing else happens, increment |
| ++it; |
| } |
| } |
| |
| void |
| AttrVisitor::expand_tuple_fields (std::vector<AST::TupleField> &fields) |
| { |
| for (auto it = fields.begin (); it != fields.end ();) |
| { |
| auto &field = *it; |
| |
| auto &field_attrs = field.get_outer_attrs (); |
| expander.expand_cfg_attrs (field_attrs); |
| if (expander.fails_cfg_with_expand (field_attrs)) |
| { |
| it = fields.erase (it); |
| continue; |
| } |
| |
| // expand sub-types of type, but can't strip type itself |
| auto &type = field.get_field_type (); |
| type->accept_vis (*this); |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), |
| "cannot strip type in this position"); |
| |
| // if nothing else happens, increment |
| ++it; |
| } |
| } |
| |
| void |
| AttrVisitor::expand_function_params (std::vector<AST::FunctionParam> ¶ms) |
| { |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| |
| for (auto it = params.begin (); it != params.end ();) |
| { |
| auto ¶m = *it; |
| |
| auto ¶m_attrs = param.get_outer_attrs (); |
| expander.expand_cfg_attrs (param_attrs); |
| if (expander.fails_cfg_with_expand (param_attrs)) |
| { |
| it = params.erase (it); |
| continue; |
| } |
| |
| // TODO: should an unwanted strip lead to break out of loop? |
| auto &pattern = param.get_pattern (); |
| pattern->accept_vis (*this); |
| if (pattern->is_marked_for_strip ()) |
| rust_error_at (pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| |
| auto &type = param.get_type (); |
| type->accept_vis (*this); |
| |
| maybe_expand_type (type); |
| |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), |
| "cannot strip type in this position"); |
| |
| // increment |
| ++it; |
| } |
| |
| expander.pop_context (); |
| } |
| |
| void |
| AttrVisitor::expand_generic_args (AST::GenericArgs &args) |
| { |
| // lifetime args can't be expanded |
| // FIXME: Can we have macro invocations for lifetimes? |
| |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| |
| // expand type args - strip sub-types only |
| for (auto &arg : args.get_generic_args ()) |
| { |
| switch (arg.get_kind ()) |
| { |
| case AST::GenericArg::Kind::Type: { |
| auto &type = arg.get_type (); |
| type->accept_vis (*this); |
| maybe_expand_type (type); |
| |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), |
| "cannot strip type in this position"); |
| break; |
| } |
| case AST::GenericArg::Kind::Const: { |
| auto &expr = arg.get_expression (); |
| expr->accept_vis (*this); |
| maybe_expand_expr (expr); |
| |
| if (expr->is_marked_for_strip ()) |
| rust_error_at (expr->get_locus (), |
| "cannot strip expression in this position"); |
| break; |
| } |
| default: |
| break; |
| // FIXME: Figure out what to do here if there is ambiguity. Since the |
| // resolver comes after the expansion, we need to figure out a way to |
| // strip ambiguous values here |
| // TODO: Arthur: Probably add a `mark_as_strip` method to `GenericArg` |
| // or something. This would clean up this whole thing |
| } |
| } |
| |
| expander.pop_context (); |
| |
| // FIXME: Can we have macro invocations in generic type bindings? |
| // expand binding args - strip sub-types only |
| for (auto &binding : args.get_binding_args ()) |
| { |
| auto &type = binding.get_type (); |
| type->accept_vis (*this); |
| |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), |
| "cannot strip type in this position"); |
| } |
| } |
| |
| void |
| AttrVisitor::expand_qualified_path_type (AST::QualifiedPathType &path_type) |
| { |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| |
| auto &type = path_type.get_type (); |
| type->accept_vis (*this); |
| |
| maybe_expand_type (type); |
| |
| expander.pop_context (); |
| |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), "cannot strip type in this position"); |
| |
| if (path_type.has_as_clause ()) |
| { |
| auto &type_path = path_type.get_as_type_path (); |
| visit (type_path); |
| if (type_path.is_marked_for_strip ()) |
| rust_error_at (type_path.get_locus (), |
| "cannot strip type path in this position"); |
| } |
| } |
| |
| void |
| AttrVisitor::AttrVisitor::expand_closure_params ( |
| std::vector<AST::ClosureParam> ¶ms) |
| { |
| for (auto it = params.begin (); it != params.end ();) |
| { |
| auto ¶m = *it; |
| |
| auto ¶m_attrs = param.get_outer_attrs (); |
| expander.expand_cfg_attrs (param_attrs); |
| if (expander.fails_cfg_with_expand (param_attrs)) |
| { |
| it = params.erase (it); |
| continue; |
| } |
| |
| auto &pattern = param.get_pattern (); |
| pattern->accept_vis (*this); |
| if (pattern->is_marked_for_strip ()) |
| rust_error_at (pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| |
| if (param.has_type_given ()) |
| { |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| auto &type = param.get_type (); |
| type->accept_vis (*this); |
| |
| maybe_expand_type (type); |
| |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), |
| "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| } |
| |
| // increment if found nothing else so far |
| ++it; |
| } |
| } |
| |
| void |
| AttrVisitor::expand_self_param (AST::SelfParam &self_param) |
| { |
| if (self_param.has_type ()) |
| { |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| auto &type = self_param.get_type (); |
| type->accept_vis (*this); |
| |
| maybe_expand_type (type); |
| |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), |
| "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| } |
| /* TODO: maybe check for invariants being violated - e.g. both type and |
| * lifetime? */ |
| } |
| |
| void |
| AttrVisitor::expand_where_clause (AST::WhereClause &where_clause) |
| { |
| // items cannot be stripped conceptually, so just accept visitor |
| for (auto &item : where_clause.get_items ()) |
| item->accept_vis (*this); |
| } |
| |
| void |
| AttrVisitor::expand_trait_function_decl (AST::TraitFunctionDecl &decl) |
| { |
| // just expand sub-stuff - can't actually strip generic params themselves |
| for (auto ¶m : decl.get_generic_params ()) |
| param->accept_vis (*this); |
| |
| /* strip function parameters if required - this is specifically |
| * allowed by spec */ |
| expand_function_params (decl.get_function_params ()); |
| |
| if (decl.has_return_type ()) |
| { |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| |
| auto &return_type = decl.get_return_type (); |
| return_type->accept_vis (*this); |
| |
| maybe_expand_type (return_type); |
| |
| if (return_type->is_marked_for_strip ()) |
| rust_error_at (return_type->get_locus (), |
| "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| } |
| |
| if (decl.has_where_clause ()) |
| expand_where_clause (decl.get_where_clause ()); |
| } |
| |
| void |
| AttrVisitor::expand_trait_method_decl (AST::TraitMethodDecl &decl) |
| { |
| // just expand sub-stuff - can't actually strip generic params themselves |
| for (auto ¶m : decl.get_generic_params ()) |
| param->accept_vis (*this); |
| |
| /* assuming you can't strip self param - wouldn't be a method |
| * anymore. spec allows outer attrs on self param, but doesn't |
| * specify whether cfg is used. */ |
| expand_self_param (decl.get_self_param ()); |
| |
| /* strip function parameters if required - this is specifically |
| * allowed by spec */ |
| expand_function_params (decl.get_function_params ()); |
| |
| if (decl.has_return_type ()) |
| { |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| |
| auto &return_type = decl.get_return_type (); |
| return_type->accept_vis (*this); |
| |
| maybe_expand_type (return_type); |
| |
| if (return_type->is_marked_for_strip ()) |
| rust_error_at (return_type->get_locus (), |
| "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| } |
| |
| if (decl.has_where_clause ()) |
| expand_where_clause (decl.get_where_clause ()); |
| } |
| |
| void |
| AttrVisitor::visit (AST::Token &) |
| { |
| // shouldn't require? |
| } |
| void |
| AttrVisitor::visit (AST::DelimTokenTree &) |
| { |
| // shouldn't require? |
| } |
| void |
| AttrVisitor::visit (AST::AttrInputMetaItemContainer &) |
| { |
| // shouldn't require? |
| } |
| void |
| AttrVisitor::visit (AST::IdentifierExpr &ident_expr) |
| { |
| // strip test based on outer attrs |
| expander.expand_cfg_attrs (ident_expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (ident_expr.get_outer_attrs ())) |
| { |
| ident_expr.mark_for_strip (); |
| return; |
| } |
| } |
| void |
| AttrVisitor::visit (AST::Lifetime &) |
| { |
| // shouldn't require? |
| } |
| void |
| AttrVisitor::visit (AST::LifetimeParam &) |
| { |
| // supposedly does not require - cfg does nothing |
| } |
| void |
| AttrVisitor::visit (AST::ConstGenericParam &) |
| { |
| // likewise |
| } |
| |
| void |
| AttrVisitor::visit (AST::MacroInvocation ¯o_invoc) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (macro_invoc.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (macro_invoc.get_outer_attrs ())) |
| { |
| macro_invoc.mark_for_strip (); |
| return; |
| } |
| |
| // can't strip simple path |
| |
| // I don't think any macro token trees can be stripped in any way |
| |
| // TODO: maybe have cfg! macro stripping behaviour here? |
| expander.expand_invoc (macro_invoc, macro_invoc.has_semicolon ()); |
| } |
| |
| void |
| AttrVisitor::visit (AST::PathInExpression &path) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (path.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (path.get_outer_attrs ())) |
| { |
| path.mark_for_strip (); |
| return; |
| } |
| |
| for (auto &segment : path.get_segments ()) |
| { |
| if (segment.has_generic_args ()) |
| expand_generic_args (segment.get_generic_args ()); |
| } |
| } |
| void |
| AttrVisitor::visit (AST::TypePathSegment &) |
| { |
| // shouldn't require |
| } |
| void |
| AttrVisitor::visit (AST::TypePathSegmentGeneric &segment) |
| { |
| // TODO: strip inside generic args |
| |
| if (!segment.has_generic_args ()) |
| return; |
| |
| expand_generic_args (segment.get_generic_args ()); |
| } |
| void |
| AttrVisitor::visit (AST::TypePathSegmentFunction &segment) |
| { |
| auto &type_path_function = segment.get_type_path_function (); |
| |
| for (auto &type : type_path_function.get_params ()) |
| { |
| type->accept_vis (*this); |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), |
| "cannot strip type in this position"); |
| } |
| |
| if (type_path_function.has_return_type ()) |
| { |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| |
| auto &return_type = type_path_function.get_return_type (); |
| return_type->accept_vis (*this); |
| |
| maybe_expand_type (return_type); |
| |
| if (return_type->is_marked_for_strip ()) |
| rust_error_at (return_type->get_locus (), |
| "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| } |
| } |
| void |
| AttrVisitor::visit (AST::TypePath &path) |
| { |
| // this shouldn't strip any segments, but can strip inside them |
| for (auto &segment : path.get_segments ()) |
| segment->accept_vis (*this); |
| } |
| void |
| AttrVisitor::visit (AST::QualifiedPathInExpression &path) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (path.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (path.get_outer_attrs ())) |
| { |
| path.mark_for_strip (); |
| return; |
| } |
| |
| expand_qualified_path_type (path.get_qualified_path_type ()); |
| |
| for (auto &segment : path.get_segments ()) |
| { |
| if (segment.has_generic_args ()) |
| expand_generic_args (segment.get_generic_args ()); |
| } |
| } |
| void |
| AttrVisitor::visit (AST::QualifiedPathInType &path) |
| { |
| expand_qualified_path_type (path.get_qualified_path_type ()); |
| |
| // this shouldn't strip any segments, but can strip inside them |
| for (auto &segment : path.get_segments ()) |
| segment->accept_vis (*this); |
| } |
| |
| void |
| AttrVisitor::visit (AST::LiteralExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| } |
| void |
| AttrVisitor::visit (AST::AttrInputLiteral &) |
| { |
| // shouldn't require? |
| } |
| void |
| AttrVisitor::visit (AST::MetaItemLitExpr &) |
| { |
| // shouldn't require? |
| } |
| void |
| AttrVisitor::visit (AST::MetaItemPathLit &) |
| { |
| // shouldn't require? |
| } |
| void |
| AttrVisitor::visit (AST::BorrowExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* strip any internal sub-expressions - expression itself isn't |
| * allowed to have external attributes in this position so can't be |
| * stripped. */ |
| auto &borrowed_expr = expr.get_borrowed_expr (); |
| borrowed_expr->accept_vis (*this); |
| if (borrowed_expr->is_marked_for_strip ()) |
| rust_error_at (borrowed_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::DereferenceExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* strip any internal sub-expressions - expression itself isn't |
| * allowed to have external attributes in this position so can't be |
| * stripped. */ |
| auto &dereferenced_expr = expr.get_dereferenced_expr (); |
| dereferenced_expr->accept_vis (*this); |
| if (dereferenced_expr->is_marked_for_strip ()) |
| rust_error_at (dereferenced_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::ErrorPropagationExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* strip any internal sub-expressions - expression itself isn't |
| * allowed to have external attributes in this position so can't be |
| * stripped. */ |
| auto &propagating_expr = expr.get_propagating_expr (); |
| propagating_expr->accept_vis (*this); |
| if (propagating_expr->is_marked_for_strip ()) |
| rust_error_at (propagating_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::NegationExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* strip any internal sub-expressions - expression itself isn't |
| * allowed to have external attributes in this position so can't be |
| * stripped. */ |
| auto &negated_expr = expr.get_negated_expr (); |
| negated_expr->accept_vis (*this); |
| if (negated_expr->is_marked_for_strip ()) |
| rust_error_at (negated_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::ArithmeticOrLogicalExpr &expr) |
| { |
| /* outer attributes never allowed before these. while cannot strip |
| * two direct descendant expressions, can strip ones below that */ |
| |
| /* should have no possibility for outer attrs as would be parsed |
| * with outer expr */ |
| auto &l_expr = expr.get_left_expr (); |
| l_expr->accept_vis (*this); |
| maybe_expand_expr (l_expr); |
| |
| /* should syntactically not have outer attributes, though this may |
| * not have worked in practice */ |
| auto &r_expr = expr.get_right_expr (); |
| r_expr->accept_vis (*this); |
| maybe_expand_expr (r_expr); |
| |
| // ensure that they are not marked for strip |
| if (expr.get_left_expr ()->is_marked_for_strip ()) |
| rust_error_at (expr.get_left_expr ()->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes are never allowed " |
| "before binary op exprs"); |
| if (expr.get_right_expr ()->is_marked_for_strip ()) |
| rust_error_at (expr.get_right_expr ()->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::ComparisonExpr &expr) |
| { |
| /* outer attributes never allowed before these. while cannot strip |
| * two direct descendant expressions, can strip ones below that */ |
| |
| /* should have no possibility for outer attrs as would be parsed |
| * with outer expr */ |
| auto &l_expr = expr.get_left_expr (); |
| l_expr->accept_vis (*this); |
| maybe_expand_expr (l_expr); |
| |
| /* should syntactically not have outer attributes, though this may |
| * not have worked in practice */ |
| auto &r_expr = expr.get_right_expr (); |
| r_expr->accept_vis (*this); |
| maybe_expand_expr (r_expr); |
| |
| // ensure that they are not marked for strip |
| if (expr.get_left_expr ()->is_marked_for_strip ()) |
| rust_error_at (expr.get_left_expr ()->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes are never allowed " |
| "before binary op exprs"); |
| if (expr.get_right_expr ()->is_marked_for_strip ()) |
| rust_error_at (expr.get_right_expr ()->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::LazyBooleanExpr &expr) |
| { |
| /* outer attributes never allowed before these. while cannot strip |
| * two direct descendant expressions, can strip ones below that */ |
| |
| /* should have no possibility for outer attrs as would be parsed |
| * with outer expr */ |
| auto &l_expr = expr.get_left_expr (); |
| l_expr->accept_vis (*this); |
| maybe_expand_expr (l_expr); |
| |
| /* should syntactically not have outer attributes, though this may |
| * not have worked in practice */ |
| auto &r_expr = expr.get_right_expr (); |
| r_expr->accept_vis (*this); |
| maybe_expand_expr (r_expr); |
| |
| // ensure that they are not marked for strip |
| if (expr.get_left_expr ()->is_marked_for_strip ()) |
| rust_error_at (expr.get_left_expr ()->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes are never allowed " |
| "before binary op exprs"); |
| if (expr.get_right_expr ()->is_marked_for_strip ()) |
| rust_error_at (expr.get_right_expr ()->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::TypeCastExpr &expr) |
| { |
| /* outer attributes never allowed before these. while cannot strip |
| * direct descendant expression, can strip ones below that */ |
| |
| auto &casted_expr = expr.get_casted_expr (); |
| /* should have no possibility for outer attrs as would be parsed |
| * with outer expr */ |
| casted_expr->accept_vis (*this); |
| |
| // ensure that they are not marked for strip |
| if (casted_expr->is_marked_for_strip ()) |
| rust_error_at (casted_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes are never allowed before cast exprs"); |
| |
| // TODO: strip sub-types of type |
| auto &type = expr.get_type_to_cast_to (); |
| type->accept_vis (*this); |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), "cannot strip type in this position"); |
| } |
| void |
| AttrVisitor::visit (AST::AssignmentExpr &expr) |
| { |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* should have no possibility for outer attrs as would be parsed |
| * with outer expr */ |
| auto &l_expr = expr.get_left_expr (); |
| l_expr->accept_vis (*this); |
| maybe_expand_expr (l_expr); |
| |
| /* should syntactically not have outer attributes, though this may |
| * not have worked in practice */ |
| auto &r_expr = expr.get_right_expr (); |
| r_expr->accept_vis (*this); |
| maybe_expand_expr (r_expr); |
| |
| // ensure that they are not marked for strip |
| if (expr.get_left_expr ()->is_marked_for_strip ()) |
| rust_error_at (expr.get_left_expr ()->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes are never allowed " |
| "before binary op exprs"); |
| if (expr.get_right_expr ()->is_marked_for_strip ()) |
| rust_error_at (expr.get_right_expr ()->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::CompoundAssignmentExpr &expr) |
| { |
| /* outer attributes never allowed before these. while cannot strip |
| * two direct descendant expressions, can strip ones below that */ |
| |
| /* should have no possibility for outer attrs as would be parsed |
| * with outer expr */ |
| auto &l_expr = expr.get_left_expr (); |
| l_expr->accept_vis (*this); |
| maybe_expand_expr (l_expr); |
| |
| /* should syntactically not have outer attributes, though this may |
| * not have worked in practice */ |
| auto &r_expr = expr.get_right_expr (); |
| r_expr->accept_vis (*this); |
| maybe_expand_expr (r_expr); |
| |
| // ensure that they are not marked for strip |
| if (expr.get_left_expr ()->is_marked_for_strip ()) |
| rust_error_at (expr.get_left_expr ()->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes are never allowed " |
| "before binary op exprs"); |
| if (expr.get_right_expr ()->is_marked_for_strip ()) |
| rust_error_at (expr.get_right_expr ()->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::GroupedExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* strip test based on inner attrs - spec says these are inner |
| * attributes, not outer attributes of inner expr */ |
| expander.expand_cfg_attrs (expr.get_inner_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_inner_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* strip any internal sub-expressions - expression itself isn't |
| * allowed to have external attributes in this position so can't be |
| * stripped. */ |
| auto &inner_expr = expr.get_expr_in_parens (); |
| inner_expr->accept_vis (*this); |
| if (inner_expr->is_marked_for_strip ()) |
| rust_error_at (inner_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::ArrayElemsValues &elems) |
| { |
| /* apparently outer attributes are allowed in "elements of array |
| * expressions" according to spec */ |
| expand_pointer_allow_strip (elems.get_values ()); |
| } |
| void |
| AttrVisitor::visit (AST::ArrayElemsCopied &elems) |
| { |
| /* apparently outer attributes are allowed in "elements of array |
| * expressions" according to spec. on the other hand, it would not |
| * make conceptual sense to be able to remove either expression. As |
| * such, not implementing. TODO clear up the ambiguity here */ |
| |
| // only intend stripping for internal sub-expressions |
| auto &copied_expr = elems.get_elem_to_copy (); |
| copied_expr->accept_vis (*this); |
| if (copied_expr->is_marked_for_strip ()) |
| rust_error_at (copied_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| |
| auto ©_count = elems.get_num_copies (); |
| copy_count->accept_vis (*this); |
| if (copy_count->is_marked_for_strip ()) |
| rust_error_at (copy_count->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::ArrayExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* strip test based on inner attrs - spec says there are separate |
| * inner attributes, not just outer attributes of inner exprs */ |
| expander.expand_cfg_attrs (expr.get_inner_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_inner_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* assuming you can't strip away the ArrayElems type, but can strip |
| * internal expressions and whatever */ |
| expr.get_array_elems ()->accept_vis (*this); |
| } |
| void |
| AttrVisitor::visit (AST::ArrayIndexExpr &expr) |
| { |
| /* it is unclear whether outer attributes are supposed to be |
| * allowed, but conceptually it wouldn't make much sense, but |
| * having expansion code anyway. TODO */ |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* strip any internal sub-expressions - expression itself isn't |
| * allowed to have external attributes in this position so can't be |
| * stripped. */ |
| auto &array_expr = expr.get_array_expr (); |
| array_expr->accept_vis (*this); |
| if (array_expr->is_marked_for_strip ()) |
| rust_error_at (array_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| |
| auto &index_expr = expr.get_index_expr (); |
| index_expr->accept_vis (*this); |
| if (index_expr->is_marked_for_strip ()) |
| rust_error_at (index_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::TupleExpr &expr) |
| { |
| /* according to spec, outer attributes are allowed on "elements of |
| * tuple expressions" */ |
| |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* strip test based on inner attrs - spec says these are inner |
| * attributes, not outer attributes of inner expr */ |
| expander.expand_cfg_attrs (expr.get_inner_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_inner_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* apparently outer attributes are allowed in "elements of tuple |
| * expressions" according to spec */ |
| expand_pointer_allow_strip (expr.get_tuple_elems ()); |
| } |
| void |
| AttrVisitor::visit (AST::TupleIndexExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* wouldn't strip this directly (as outer attrs should be |
| * associated with this level), but any sub-expressions would be |
| * stripped. Thus, no need to erase when strip check called. */ |
| auto &tuple_expr = expr.get_tuple_expr (); |
| tuple_expr->accept_vis (*this); |
| if (tuple_expr->is_marked_for_strip ()) |
| rust_error_at (tuple_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::StructExprStruct &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* strip test based on inner attrs - spec says these are inner |
| * attributes, not outer attributes of inner expr */ |
| expander.expand_cfg_attrs (expr.get_inner_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_inner_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| // strip sub-exprs of path |
| auto &struct_name = expr.get_struct_name (); |
| visit (struct_name); |
| if (struct_name.is_marked_for_strip ()) |
| rust_error_at (struct_name.get_locus (), |
| "cannot strip path in this position"); |
| } |
| void |
| AttrVisitor::visit (AST::StructExprFieldIdentifier &) |
| { |
| // as no attrs (at moment, at least), no stripping possible |
| } |
| void |
| AttrVisitor::visit (AST::StructExprFieldIdentifierValue &field) |
| { |
| /* as no attrs possible (at moment, at least), only sub-expression |
| * stripping is possible */ |
| auto &value = field.get_value (); |
| value->accept_vis (*this); |
| if (value->is_marked_for_strip ()) |
| rust_error_at (value->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::StructExprFieldIndexValue &field) |
| { |
| /* as no attrs possible (at moment, at least), only sub-expression |
| * stripping is possible */ |
| auto &value = field.get_value (); |
| value->accept_vis (*this); |
| if (value->is_marked_for_strip ()) |
| rust_error_at (value->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::StructExprStructFields &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* strip test based on inner attrs - spec says these are inner |
| * attributes, not outer attributes of inner expr */ |
| expander.expand_cfg_attrs (expr.get_inner_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_inner_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| // strip sub-exprs of path |
| auto &struct_name = expr.get_struct_name (); |
| visit (struct_name); |
| if (struct_name.is_marked_for_strip ()) |
| rust_error_at (struct_name.get_locus (), |
| "cannot strip path in this position"); |
| |
| /* spec does not specify whether expressions are allowed to be |
| * stripped at top level of struct fields, but I wouldn't think |
| * that they would be, so operating under the assumption that only |
| * sub-expressions can be stripped. */ |
| for (auto &field : expr.get_fields ()) |
| { |
| field->accept_vis (*this); |
| // shouldn't strip in this |
| } |
| |
| /* struct base presumably can't be stripped, as the '..' is before |
| * the expression. as such, can only strip sub-expressions. */ |
| if (expr.has_struct_base ()) |
| { |
| auto &base_struct_expr = expr.get_struct_base ().get_base_struct (); |
| base_struct_expr->accept_vis (*this); |
| if (base_struct_expr->is_marked_for_strip ()) |
| rust_error_at (base_struct_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| } |
| void |
| AttrVisitor::visit (AST::StructExprStructBase &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* strip test based on inner attrs - spec says these are inner |
| * attributes, not outer attributes of inner expr */ |
| expander.expand_cfg_attrs (expr.get_inner_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_inner_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| // strip sub-exprs of path |
| auto &struct_name = expr.get_struct_name (); |
| visit (struct_name); |
| if (struct_name.is_marked_for_strip ()) |
| rust_error_at (struct_name.get_locus (), |
| "cannot strip path in this position"); |
| |
| /* struct base presumably can't be stripped, as the '..' is before |
| * the expression. as such, can only strip sub-expressions. */ |
| rust_assert (!expr.get_struct_base ().is_invalid ()); |
| auto &base_struct_expr = expr.get_struct_base ().get_base_struct (); |
| base_struct_expr->accept_vis (*this); |
| if (base_struct_expr->is_marked_for_strip ()) |
| rust_error_at (base_struct_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::CallExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* should not be outer attrs on "function" expression - outer attrs |
| * should be associated with call expr as a whole. only sub-expr |
| * expansion is possible. */ |
| auto &function = expr.get_function_expr (); |
| function->accept_vis (*this); |
| if (function->is_marked_for_strip ()) |
| rust_error_at (function->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| |
| /* spec says outer attributes are specifically allowed for elements |
| * of call expressions, so full stripping possible */ |
| // FIXME: Arthur: Figure out how to refactor this - This is similar to |
| // expanding items in the crate or stmts in blocks |
| expand_pointer_allow_strip (expr.get_params ()); |
| auto ¶ms = expr.get_params (); |
| for (auto it = params.begin (); it != params.end ();) |
| { |
| auto &stmt = *it; |
| |
| stmt->accept_vis (*this); |
| |
| auto final_fragment = expander.take_expanded_fragment (); |
| if (final_fragment.should_expand ()) |
| { |
| // Remove the current expanded invocation |
| it = params.erase (it); |
| for (auto &node : final_fragment.get_nodes ()) |
| { |
| it = params.insert (it, node.take_expr ()); |
| it++; |
| } |
| } |
| else if (stmt->is_marked_for_strip ()) |
| it = params.erase (it); |
| else |
| it++; |
| } |
| } |
| void |
| AttrVisitor::visit (AST::MethodCallExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* should not be outer attrs on "receiver" expression - outer attrs |
| * should be associated with call expr as a whole. only sub-expr |
| * expansion is possible. */ |
| auto &receiver = expr.get_receiver_expr (); |
| receiver->accept_vis (*this); |
| if (receiver->is_marked_for_strip ()) |
| rust_error_at (receiver->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| |
| auto &method_name = expr.get_method_name (); |
| if (method_name.has_generic_args ()) |
| expand_generic_args (method_name.get_generic_args ()); |
| |
| /* spec says outer attributes are specifically allowed for elements |
| * of method call expressions, so full stripping possible */ |
| expand_pointer_allow_strip (expr.get_params ()); |
| } |
| void |
| AttrVisitor::visit (AST::FieldAccessExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* should not be outer attrs on "receiver" expression - outer attrs |
| * should be associated with field expr as a whole. only sub-expr |
| * expansion is possible. */ |
| auto &receiver = expr.get_receiver_expr (); |
| receiver->accept_vis (*this); |
| if (receiver->is_marked_for_strip ()) |
| rust_error_at (receiver->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::ClosureExprInner &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* strip closure parameters if required - this is specifically |
| * allowed by spec */ |
| expand_closure_params (expr.get_params ()); |
| |
| // can't strip expression itself, but can strip sub-expressions |
| auto &definition_expr = expr.get_definition_expr (); |
| definition_expr->accept_vis (*this); |
| if (definition_expr->is_marked_for_strip ()) |
| rust_error_at (definition_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| |
| void |
| AttrVisitor::visit (AST::BlockExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* strip test based on inner attrs - spec says there are inner |
| * attributes, not just outer attributes of inner stmts */ |
| expander.expand_cfg_attrs (expr.get_inner_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_inner_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| std::function<std::unique_ptr<AST::Stmt> (AST::SingleASTNode)> extractor |
| = [] (AST::SingleASTNode node) { return node.take_stmt (); }; |
| |
| expand_macro_children (MacroExpander::BLOCK, expr.get_statements (), |
| extractor); |
| |
| expander.push_context (MacroExpander::BLOCK); |
| |
| // strip tail expression if exists - can actually fully remove it |
| if (expr.has_tail_expr ()) |
| { |
| auto &tail_expr = expr.get_tail_expr (); |
| |
| tail_expr->accept_vis (*this); |
| maybe_expand_expr (tail_expr); |
| |
| if (tail_expr->is_marked_for_strip ()) |
| expr.strip_tail_expr (); |
| } |
| expander.pop_context (); |
| } |
| |
| void |
| AttrVisitor::visit (AST::ClosureExprInnerTyped &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* strip closure parameters if required - this is specifically |
| * allowed by spec */ |
| expand_closure_params (expr.get_params ()); |
| |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| |
| // can't strip return type, but can strip sub-types |
| auto &type = expr.get_return_type (); |
| type->accept_vis (*this); |
| |
| maybe_expand_type (type); |
| |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| |
| // can't strip expression itself, but can strip sub-expressions |
| auto &definition_block = expr.get_definition_block (); |
| definition_block->accept_vis (*this); |
| if (definition_block->is_marked_for_strip ()) |
| rust_error_at (definition_block->get_locus (), |
| "cannot strip block expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::ContinueExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| } |
| void |
| AttrVisitor::visit (AST::BreakExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* spec does not say that you can have outer attributes on |
| * expression, so assuming you can't. stripping for sub-expressions |
| * is the only thing that can be done */ |
| if (expr.has_break_expr ()) |
| { |
| auto &break_expr = expr.get_break_expr (); |
| |
| break_expr->accept_vis (*this); |
| |
| if (break_expr->is_marked_for_strip ()) |
| rust_error_at (break_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| } |
| void |
| AttrVisitor::visit (AST::RangeFromToExpr &expr) |
| { |
| /* outer attributes never allowed before these. while cannot strip |
| * two direct descendant expressions, can strip ones below that */ |
| |
| /* should have no possibility for outer attrs as would be parsed |
| * with outer expr */ |
| expr.get_from_expr ()->accept_vis (*this); |
| /* should syntactically not have outer attributes, though this may |
| * not have worked in practice */ |
| expr.get_to_expr ()->accept_vis (*this); |
| |
| // ensure that they are not marked for strip |
| if (expr.get_from_expr ()->is_marked_for_strip ()) |
| rust_error_at (expr.get_from_expr ()->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes are never allowed " |
| "before range exprs"); |
| if (expr.get_to_expr ()->is_marked_for_strip ()) |
| rust_error_at (expr.get_to_expr ()->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::RangeFromExpr &expr) |
| { |
| /* outer attributes never allowed before these. while cannot strip |
| * direct descendant expression, can strip ones below that */ |
| |
| /* should have no possibility for outer attrs as would be parsed |
| * with outer expr */ |
| auto &from_expr = expr.get_from_expr (); |
| |
| from_expr->accept_vis (*this); |
| |
| if (from_expr->is_marked_for_strip ()) |
| rust_error_at (from_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes are never allowed before range exprs"); |
| } |
| void |
| AttrVisitor::visit (AST::RangeToExpr &expr) |
| { |
| /* outer attributes never allowed before these. while cannot strip |
| * direct descendant expression, can strip ones below that */ |
| |
| /* should syntactically not have outer attributes, though this may |
| * not have worked in practice */ |
| auto &to_expr = expr.get_to_expr (); |
| |
| to_expr->accept_vis (*this); |
| |
| if (to_expr->is_marked_for_strip ()) |
| rust_error_at (to_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::RangeFullExpr &) |
| { |
| // outer attributes never allowed before these, so no stripping |
| } |
| void |
| AttrVisitor::visit (AST::RangeFromToInclExpr &expr) |
| { |
| /* outer attributes never allowed before these. while cannot strip |
| * two direct descendant expressions, can strip ones below that */ |
| |
| /* should have no possibility for outer attrs as would be parsed |
| * with outer expr */ |
| expr.get_from_expr ()->accept_vis (*this); |
| /* should syntactically not have outer attributes, though this may |
| * not have worked in practice */ |
| expr.get_to_expr ()->accept_vis (*this); |
| |
| // ensure that they are not marked for strip |
| if (expr.get_from_expr ()->is_marked_for_strip ()) |
| rust_error_at (expr.get_from_expr ()->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes are never allowed " |
| "before range exprs"); |
| if (expr.get_to_expr ()->is_marked_for_strip ()) |
| rust_error_at (expr.get_to_expr ()->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::RangeToInclExpr &expr) |
| { |
| /* outer attributes never allowed before these. while cannot strip |
| * direct descendant expression, can strip ones below that */ |
| |
| /* should syntactically not have outer attributes, though this may |
| * not have worked in practice */ |
| auto &to_expr = expr.get_to_expr (); |
| |
| to_expr->accept_vis (*this); |
| |
| if (to_expr->is_marked_for_strip ()) |
| rust_error_at (to_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::ReturnExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* spec does not say that you can have outer attributes on |
| * expression, so assuming you can't. stripping for sub-expressions |
| * is the only thing that can be done */ |
| if (expr.has_returned_expr ()) |
| { |
| auto &returned_expr = expr.get_returned_expr (); |
| |
| returned_expr->accept_vis (*this); |
| |
| if (returned_expr->is_marked_for_strip ()) |
| rust_error_at (returned_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| /* TODO: conceptually, you would maybe be able to remove a returned |
| * expr - e.g. if you had conditional compilation returning void or |
| * returning a type. On the other hand, I think that function |
| * return type cannot be conditionally compiled, so I assumed you |
| * can't do this either. */ |
| } |
| void |
| AttrVisitor::visit (AST::UnsafeBlockExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| // can't strip block itself, but can strip sub-expressions |
| auto &block_expr = expr.get_block_expr (); |
| block_expr->accept_vis (*this); |
| if (block_expr->is_marked_for_strip ()) |
| rust_error_at (block_expr->get_locus (), |
| "cannot strip block expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::LoopExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| // can't strip block itself, but can strip sub-expressions |
| auto &loop_block = expr.get_loop_block (); |
| loop_block->accept_vis (*this); |
| if (loop_block->is_marked_for_strip ()) |
| rust_error_at (loop_block->get_locus (), |
| "cannot strip block expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::WhileLoopExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| // can't strip predicate expr itself, but can strip sub-expressions |
| auto &predicate_expr = expr.get_predicate_expr (); |
| predicate_expr->accept_vis (*this); |
| if (predicate_expr->is_marked_for_strip ()) |
| rust_error_at (predicate_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| |
| // can't strip block itself, but can strip sub-expressions |
| auto &loop_block = expr.get_loop_block (); |
| loop_block->accept_vis (*this); |
| if (loop_block->is_marked_for_strip ()) |
| rust_error_at (loop_block->get_locus (), |
| "cannot strip block expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::WhileLetLoopExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| for (auto &pattern : expr.get_patterns ()) |
| { |
| pattern->accept_vis (*this); |
| if (pattern->is_marked_for_strip ()) |
| rust_error_at (pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| } |
| |
| // can't strip scrutinee expr itself, but can strip sub-expressions |
| auto &scrutinee_expr = expr.get_scrutinee_expr (); |
| scrutinee_expr->accept_vis (*this); |
| if (scrutinee_expr->is_marked_for_strip ()) |
| rust_error_at (scrutinee_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| |
| // can't strip block itself, but can strip sub-expressions |
| auto &loop_block = expr.get_loop_block (); |
| loop_block->accept_vis (*this); |
| if (loop_block->is_marked_for_strip ()) |
| rust_error_at (loop_block->get_locus (), |
| "cannot strip block expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::ForLoopExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| // strip sub-patterns of pattern |
| auto &pattern = expr.get_pattern (); |
| pattern->accept_vis (*this); |
| if (pattern->is_marked_for_strip ()) |
| rust_error_at (pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| |
| // can't strip scrutinee expr itself, but can strip sub-expressions |
| auto &iterator_expr = expr.get_iterator_expr (); |
| iterator_expr->accept_vis (*this); |
| if (iterator_expr->is_marked_for_strip ()) |
| rust_error_at (iterator_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| |
| // can't strip block itself, but can strip sub-expressions |
| auto &loop_block = expr.get_loop_block (); |
| loop_block->accept_vis (*this); |
| if (loop_block->is_marked_for_strip ()) |
| rust_error_at (loop_block->get_locus (), |
| "cannot strip block expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::IfExpr &expr) |
| { |
| // rust playground test shows that IfExpr does support outer attrs, at least |
| // when used as statement |
| |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| // can't strip condition expr itself, but can strip sub-expressions |
| auto &condition_expr = expr.get_condition_expr (); |
| condition_expr->accept_vis (*this); |
| maybe_expand_expr (condition_expr); |
| if (condition_expr->is_marked_for_strip ()) |
| rust_error_at (condition_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| |
| // can't strip if block itself, but can strip sub-expressions |
| auto &if_block = expr.get_if_block (); |
| if_block->accept_vis (*this); |
| if (if_block->is_marked_for_strip ()) |
| rust_error_at (if_block->get_locus (), |
| "cannot strip block expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::IfExprConseqElse &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| // can't strip condition expr itself, but can strip sub-expressions |
| auto &condition_expr = expr.get_condition_expr (); |
| condition_expr->accept_vis (*this); |
| maybe_expand_expr (condition_expr); |
| if (condition_expr->is_marked_for_strip ()) |
| rust_error_at (condition_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| |
| // can't strip if block itself, but can strip sub-expressions |
| auto &if_block = expr.get_if_block (); |
| if_block->accept_vis (*this); |
| if (if_block->is_marked_for_strip ()) |
| rust_error_at (if_block->get_locus (), |
| "cannot strip block expression in this position - outer " |
| "attributes not allowed"); |
| |
| // can't strip else block itself, but can strip sub-expressions |
| auto &else_block = expr.get_else_block (); |
| else_block->accept_vis (*this); |
| if (else_block->is_marked_for_strip ()) |
| rust_error_at (else_block->get_locus (), |
| "cannot strip block expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::IfExprConseqIf &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| // can't strip condition expr itself, but can strip sub-expressions |
| auto &condition_expr = expr.get_condition_expr (); |
| condition_expr->accept_vis (*this); |
| maybe_expand_expr (condition_expr); |
| if (condition_expr->is_marked_for_strip ()) |
| rust_error_at (condition_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| |
| // can't strip if block itself, but can strip sub-expressions |
| auto &if_block = expr.get_if_block (); |
| if_block->accept_vis (*this); |
| if (if_block->is_marked_for_strip ()) |
| rust_error_at (if_block->get_locus (), |
| "cannot strip block expression in this position - outer " |
| "attributes not allowed"); |
| |
| // can't strip if expr itself, but can strip sub-expressions |
| auto &conseq_if_expr = expr.get_conseq_if_expr (); |
| conseq_if_expr->accept_vis (*this); |
| if (conseq_if_expr->is_marked_for_strip ()) |
| rust_error_at (conseq_if_expr->get_locus (), |
| "cannot strip consequent if expression in this " |
| "position - outer attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::IfExprConseqIfLet &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| // can't strip condition expr itself, but can strip sub-expressions |
| auto &condition_expr = expr.get_condition_expr (); |
| condition_expr->accept_vis (*this); |
| maybe_expand_expr (condition_expr); |
| if (condition_expr->is_marked_for_strip ()) |
| rust_error_at (condition_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| |
| // can't strip if block itself, but can strip sub-expressions |
| auto &if_block = expr.get_if_block (); |
| if_block->accept_vis (*this); |
| if (if_block->is_marked_for_strip ()) |
| rust_error_at (if_block->get_locus (), |
| "cannot strip block expression in this position - outer " |
| "attributes not allowed"); |
| |
| // can't strip if let expr itself, but can strip sub-expressions |
| auto &conseq_if_let_expr = expr.get_conseq_if_let_expr (); |
| conseq_if_let_expr->accept_vis (*this); |
| if (conseq_if_let_expr->is_marked_for_strip ()) |
| rust_error_at (conseq_if_let_expr->get_locus (), |
| "cannot strip consequent if let expression in this " |
| "position - outer attributes not " |
| "allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::IfLetExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| for (auto &pattern : expr.get_patterns ()) |
| { |
| pattern->accept_vis (*this); |
| if (pattern->is_marked_for_strip ()) |
| rust_error_at (pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| } |
| |
| // can't strip value expr itself, but can strip sub-expressions |
| auto &value_expr = expr.get_value_expr (); |
| value_expr->accept_vis (*this); |
| if (value_expr->is_marked_for_strip ()) |
| rust_error_at (value_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| |
| // can't strip if block itself, but can strip sub-expressions |
| auto &if_block = expr.get_if_block (); |
| if_block->accept_vis (*this); |
| if (if_block->is_marked_for_strip ()) |
| rust_error_at (if_block->get_locus (), |
| "cannot strip block expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::IfLetExprConseqElse &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| for (auto &pattern : expr.get_patterns ()) |
| { |
| pattern->accept_vis (*this); |
| if (pattern->is_marked_for_strip ()) |
| rust_error_at (pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| } |
| |
| // can't strip value expr itself, but can strip sub-expressions |
| auto &value_expr = expr.get_value_expr (); |
| value_expr->accept_vis (*this); |
| if (value_expr->is_marked_for_strip ()) |
| rust_error_at (value_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| |
| // can't strip if block itself, but can strip sub-expressions |
| auto &if_block = expr.get_if_block (); |
| if_block->accept_vis (*this); |
| if (if_block->is_marked_for_strip ()) |
| rust_error_at (if_block->get_locus (), |
| "cannot strip block expression in this position - outer " |
| "attributes not allowed"); |
| |
| // can't strip else block itself, but can strip sub-expressions |
| auto &else_block = expr.get_else_block (); |
| else_block->accept_vis (*this); |
| if (else_block->is_marked_for_strip ()) |
| rust_error_at (else_block->get_locus (), |
| "cannot strip block expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::IfLetExprConseqIf &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| for (auto &pattern : expr.get_patterns ()) |
| { |
| pattern->accept_vis (*this); |
| if (pattern->is_marked_for_strip ()) |
| rust_error_at (pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| } |
| |
| // can't strip value expr itself, but can strip sub-expressions |
| auto &value_expr = expr.get_value_expr (); |
| value_expr->accept_vis (*this); |
| if (value_expr->is_marked_for_strip ()) |
| rust_error_at (value_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| |
| // can't strip if block itself, but can strip sub-expressions |
| auto &if_block = expr.get_if_block (); |
| if_block->accept_vis (*this); |
| if (if_block->is_marked_for_strip ()) |
| rust_error_at (if_block->get_locus (), |
| "cannot strip block expression in this position - outer " |
| "attributes not allowed"); |
| |
| // can't strip if expr itself, but can strip sub-expressions |
| auto &conseq_if_expr = expr.get_conseq_if_expr (); |
| conseq_if_expr->accept_vis (*this); |
| if (conseq_if_expr->is_marked_for_strip ()) |
| rust_error_at (conseq_if_expr->get_locus (), |
| "cannot strip consequent if expression in this " |
| "position - outer attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::IfLetExprConseqIfLet &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| for (auto &pattern : expr.get_patterns ()) |
| { |
| pattern->accept_vis (*this); |
| if (pattern->is_marked_for_strip ()) |
| rust_error_at (pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| } |
| |
| // can't strip value expr itself, but can strip sub-expressions |
| auto &value_expr = expr.get_value_expr (); |
| value_expr->accept_vis (*this); |
| if (value_expr->is_marked_for_strip ()) |
| rust_error_at (value_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| |
| // can't strip if block itself, but can strip sub-expressions |
| auto &if_block = expr.get_if_block (); |
| if_block->accept_vis (*this); |
| if (if_block->is_marked_for_strip ()) |
| rust_error_at (if_block->get_locus (), |
| "cannot strip block expression in this position - outer " |
| "attributes not allowed"); |
| |
| // can't strip if let expr itself, but can strip sub-expressions |
| auto &conseq_if_let_expr = expr.get_conseq_if_let_expr (); |
| conseq_if_let_expr->accept_vis (*this); |
| if (conseq_if_let_expr->is_marked_for_strip ()) |
| rust_error_at (conseq_if_let_expr->get_locus (), |
| "cannot strip consequent if let expression in this " |
| "position - outer attributes not " |
| "allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::MatchExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| // inner attr strip test |
| expander.expand_cfg_attrs (expr.get_inner_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_inner_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| // can't strip scrutinee expr itself, but can strip sub-expressions |
| auto &scrutinee_expr = expr.get_scrutinee_expr (); |
| scrutinee_expr->accept_vis (*this); |
| if (scrutinee_expr->is_marked_for_strip ()) |
| rust_error_at (scrutinee_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| |
| // strip match cases |
| auto &match_cases = expr.get_match_cases (); |
| for (auto it = match_cases.begin (); it != match_cases.end ();) |
| { |
| auto &match_case = *it; |
| |
| // strip match case based on outer attributes in match arm |
| auto &match_arm = match_case.get_arm (); |
| expander.expand_cfg_attrs (match_arm.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (match_arm.get_outer_attrs ())) |
| { |
| // strip match case |
| it = match_cases.erase (it); |
| continue; |
| } |
| |
| for (auto &pattern : match_arm.get_patterns ()) |
| { |
| pattern->accept_vis (*this); |
| if (pattern->is_marked_for_strip ()) |
| rust_error_at (pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| } |
| |
| /* assuming that guard expression cannot be stripped as |
| * strictly speaking you would have to strip the whole guard to |
| * make syntactical sense, which you can't do. as such, only |
| * strip sub-expressions */ |
| if (match_arm.has_match_arm_guard ()) |
| { |
| auto &guard_expr = match_arm.get_guard_expr (); |
| guard_expr->accept_vis (*this); |
| if (guard_expr->is_marked_for_strip ()) |
| rust_error_at (guard_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| |
| // strip sub-expressions from match cases |
| auto &case_expr = match_case.get_expr (); |
| case_expr->accept_vis (*this); |
| if (case_expr->is_marked_for_strip ()) |
| rust_error_at (case_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| |
| // increment to next case if haven't continued |
| ++it; |
| } |
| } |
| void |
| AttrVisitor::visit (AST::AwaitExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| /* can't strip awaited expr itself, but can strip sub-expressions |
| * - this is because you can't have no expr to await */ |
| auto &awaited_expr = expr.get_awaited_expr (); |
| awaited_expr->accept_vis (*this); |
| if (awaited_expr->is_marked_for_strip ()) |
| rust_error_at (awaited_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::AsyncBlockExpr &expr) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (expr.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (expr.get_outer_attrs ())) |
| { |
| expr.mark_for_strip (); |
| return; |
| } |
| |
| // can't strip block itself, but can strip sub-expressions |
| auto &block_expr = expr.get_block_expr (); |
| block_expr->accept_vis (*this); |
| if (block_expr->is_marked_for_strip ()) |
| rust_error_at (block_expr->get_locus (), |
| "cannot strip block expression in this position - outer " |
| "attributes not allowed"); |
| } |
| |
| void |
| AttrVisitor::visit (AST::TypeParam ¶m) |
| { |
| // outer attributes don't actually do anything, so ignore them |
| |
| if (param.has_type_param_bounds ()) |
| { |
| // don't strip directly, only components of bounds |
| for (auto &bound : param.get_type_param_bounds ()) |
| bound->accept_vis (*this); |
| } |
| |
| if (param.has_type ()) |
| { |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| auto &type = param.get_type (); |
| type->accept_vis (*this); |
| |
| maybe_expand_type (type); |
| |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), |
| "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| } |
| } |
| void |
| AttrVisitor::visit (AST::LifetimeWhereClauseItem &) |
| { |
| // shouldn't require |
| } |
| void |
| AttrVisitor::visit (AST::TypeBoundWhereClauseItem &item) |
| { |
| // for lifetimes shouldn't require |
| |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| |
| auto &type = item.get_type (); |
| type->accept_vis (*this); |
| |
| maybe_expand_type (type); |
| |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| |
| // don't strip directly, only components of bounds |
| for (auto &bound : item.get_type_param_bounds ()) |
| bound->accept_vis (*this); |
| } |
| void |
| AttrVisitor::visit (AST::Method &method) |
| { |
| // initial test based on outer attrs |
| expander.expand_cfg_attrs (method.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (method.get_outer_attrs ())) |
| { |
| method.mark_for_strip (); |
| return; |
| } |
| |
| // just expand sub-stuff - can't actually strip generic params themselves |
| for (auto ¶m : method.get_generic_params ()) |
| param->accept_vis (*this); |
| |
| /* assuming you can't strip self param - wouldn't be a method |
| * anymore. spec allows outer attrs on self param, but doesn't |
| * specify whether cfg is used. */ |
| expand_self_param (method.get_self_param ()); |
| |
| /* strip method parameters if required - this is specifically |
| * allowed by spec */ |
| expand_function_params (method.get_function_params ()); |
| |
| if (method.has_return_type ()) |
| { |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| |
| auto &return_type = method.get_return_type (); |
| return_type->accept_vis (*this); |
| |
| maybe_expand_type (return_type); |
| |
| if (return_type->is_marked_for_strip ()) |
| rust_error_at (return_type->get_locus (), |
| "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| } |
| |
| if (method.has_where_clause ()) |
| expand_where_clause (method.get_where_clause ()); |
| |
| /* body should always exist - if error state, should have returned |
| * before now */ |
| // can't strip block itself, but can strip sub-expressions |
| auto &block_expr = method.get_definition (); |
| block_expr->accept_vis (*this); |
| if (block_expr->is_marked_for_strip ()) |
| rust_error_at (block_expr->get_locus (), |
| "cannot strip block expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::Module &module) |
| { |
| // strip test based on outer attrs |
| expander.expand_cfg_attrs (module.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (module.get_outer_attrs ())) |
| { |
| module.mark_for_strip (); |
| return; |
| } |
| |
| // A loaded module might have inner attributes |
| if (module.get_kind () == AST::Module::ModuleKind::LOADED) |
| { |
| // strip test based on inner attrs |
| expander.expand_cfg_attrs (module.get_inner_attrs ()); |
| if (expander.fails_cfg_with_expand (module.get_inner_attrs ())) |
| { |
| module.mark_for_strip (); |
| return; |
| } |
| } |
| |
| // Parse the module's items if they haven't been expanded and the file |
| // should be parsed (i.e isn't hidden behind an untrue or impossible cfg |
| // directive) |
| if (!module.is_marked_for_strip () |
| && module.get_kind () == AST::Module::ModuleKind::UNLOADED) |
| { |
| module.load_items (); |
| } |
| |
| // strip items if required |
| expand_pointer_allow_strip (module.get_items ()); |
| } |
| void |
| AttrVisitor::visit (AST::ExternCrate &extern_crate) |
| { |
| // strip test based on outer attrs |
| expander.expand_cfg_attrs (extern_crate.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (extern_crate.get_outer_attrs ())) |
| { |
| extern_crate.mark_for_strip (); |
| return; |
| } |
| |
| if (!extern_crate.references_self ()) |
| { |
| Session &session = Session::get_instance (); |
| session.load_extern_crate (extern_crate.get_referenced_crate (), |
| extern_crate.get_locus ()); |
| } |
| } |
| void |
| AttrVisitor::visit (AST::UseTreeGlob &) |
| { |
| // shouldn't require? |
| } |
| void |
| AttrVisitor::visit (AST::UseTreeList &) |
| { |
| // shouldn't require? |
| } |
| void |
| AttrVisitor::visit (AST::UseTreeRebind &) |
| { |
| // shouldn't require? |
| } |
| void |
| AttrVisitor::visit (AST::UseDeclaration &use_decl) |
| { |
| // strip test based on outer attrs |
| expander.expand_cfg_attrs (use_decl.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (use_decl.get_outer_attrs ())) |
| { |
| use_decl.mark_for_strip (); |
| return; |
| } |
| } |
| void |
| AttrVisitor::visit (AST::Function &function) |
| { |
| // initial test based on outer attrs |
| expander.expand_cfg_attrs (function.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (function.get_outer_attrs ())) |
| { |
| function.mark_for_strip (); |
| return; |
| } |
| |
| // just expand sub-stuff - can't actually strip generic params themselves |
| for (auto ¶m : function.get_generic_params ()) |
| param->accept_vis (*this); |
| |
| /* strip function parameters if required - this is specifically |
| * allowed by spec */ |
| expand_function_params (function.get_function_params ()); |
| |
| if (function.has_return_type ()) |
| { |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| |
| auto &return_type = function.get_return_type (); |
| return_type->accept_vis (*this); |
| |
| maybe_expand_type (return_type); |
| |
| if (return_type->is_marked_for_strip ()) |
| rust_error_at (return_type->get_locus (), |
| "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| } |
| |
| if (function.has_where_clause ()) |
| expand_where_clause (function.get_where_clause ()); |
| |
| /* body should always exist - if error state, should have returned |
| * before now */ |
| // can't strip block itself, but can strip sub-expressions |
| auto &block_expr = function.get_definition (); |
| block_expr->accept_vis (*this); |
| if (block_expr->is_marked_for_strip ()) |
| rust_error_at (block_expr->get_locus (), |
| "cannot strip block expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::TypeAlias &type_alias) |
| { |
| // initial test based on outer attrs |
| expander.expand_cfg_attrs (type_alias.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (type_alias.get_outer_attrs ())) |
| { |
| type_alias.mark_for_strip (); |
| return; |
| } |
| |
| // just expand sub-stuff - can't actually strip generic params themselves |
| for (auto ¶m : type_alias.get_generic_params ()) |
| param->accept_vis (*this); |
| |
| if (type_alias.has_where_clause ()) |
| expand_where_clause (type_alias.get_where_clause ()); |
| |
| auto &type = type_alias.get_type_aliased (); |
| type->accept_vis (*this); |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), "cannot strip type in this position"); |
| } |
| void |
| AttrVisitor::visit (AST::StructStruct &struct_item) |
| { |
| // initial test based on outer attrs |
| expander.expand_cfg_attrs (struct_item.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (struct_item.get_outer_attrs ())) |
| { |
| struct_item.mark_for_strip (); |
| return; |
| } |
| |
| // just expand sub-stuff - can't actually strip generic params themselves |
| for (auto ¶m : struct_item.get_generic_params ()) |
| param->accept_vis (*this); |
| |
| if (struct_item.has_where_clause ()) |
| expand_where_clause (struct_item.get_where_clause ()); |
| |
| /* strip struct fields if required - this is presumably |
| * allowed by spec */ |
| expand_struct_fields (struct_item.get_fields ()); |
| } |
| void |
| AttrVisitor::visit (AST::TupleStruct &tuple_struct) |
| { |
| // initial test based on outer attrs |
| expander.expand_cfg_attrs (tuple_struct.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (tuple_struct.get_outer_attrs ())) |
| { |
| tuple_struct.mark_for_strip (); |
| return; |
| } |
| |
| // just expand sub-stuff - can't actually strip generic params themselves |
| for (auto ¶m : tuple_struct.get_generic_params ()) |
| param->accept_vis (*this); |
| |
| /* strip struct fields if required - this is presumably |
| * allowed by spec */ |
| expand_tuple_fields (tuple_struct.get_fields ()); |
| |
| if (tuple_struct.has_where_clause ()) |
| expand_where_clause (tuple_struct.get_where_clause ()); |
| } |
| void |
| AttrVisitor::visit (AST::EnumItem &item) |
| { |
| // initial test based on outer attrs |
| expander.expand_cfg_attrs (item.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (item.get_outer_attrs ())) |
| { |
| item.mark_for_strip (); |
| return; |
| } |
| } |
| void |
| AttrVisitor::visit (AST::EnumItemTuple &item) |
| { |
| // initial test based on outer attrs |
| expander.expand_cfg_attrs (item.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (item.get_outer_attrs ())) |
| { |
| item.mark_for_strip (); |
| return; |
| } |
| |
| /* strip item fields if required - this is presumably |
| * allowed by spec */ |
| expand_tuple_fields (item.get_tuple_fields ()); |
| } |
| void |
| AttrVisitor::visit (AST::EnumItemStruct &item) |
| { |
| // initial test based on outer attrs |
| expander.expand_cfg_attrs (item.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (item.get_outer_attrs ())) |
| { |
| item.mark_for_strip (); |
| return; |
| } |
| |
| /* strip item fields if required - this is presumably |
| * allowed by spec */ |
| expand_struct_fields (item.get_struct_fields ()); |
| } |
| void |
| AttrVisitor::visit (AST::EnumItemDiscriminant &item) |
| { |
| // initial test based on outer attrs |
| expander.expand_cfg_attrs (item.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (item.get_outer_attrs ())) |
| { |
| item.mark_for_strip (); |
| return; |
| } |
| |
| /* strip any internal sub-expressions - expression itself isn't |
| * allowed to have external attributes in this position so can't be |
| * stripped. */ |
| auto &expr = item.get_expr (); |
| expr->accept_vis (*this); |
| if (expr->is_marked_for_strip ()) |
| rust_error_at (expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::Enum &enum_item) |
| { |
| // initial test based on outer attrs |
| expander.expand_cfg_attrs (enum_item.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (enum_item.get_outer_attrs ())) |
| { |
| enum_item.mark_for_strip (); |
| return; |
| } |
| |
| // just expand sub-stuff - can't actually strip generic params themselves |
| for (auto ¶m : enum_item.get_generic_params ()) |
| param->accept_vis (*this); |
| |
| if (enum_item.has_where_clause ()) |
| expand_where_clause (enum_item.get_where_clause ()); |
| |
| /* strip enum fields if required - this is presumably |
| * allowed by spec */ |
| expand_pointer_allow_strip (enum_item.get_variants ()); |
| } |
| void |
| AttrVisitor::visit (AST::Union &union_item) |
| { |
| // initial test based on outer attrs |
| expander.expand_cfg_attrs (union_item.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (union_item.get_outer_attrs ())) |
| { |
| union_item.mark_for_strip (); |
| return; |
| } |
| |
| // just expand sub-stuff - can't actually strip generic params themselves |
| for (auto ¶m : union_item.get_generic_params ()) |
| param->accept_vis (*this); |
| |
| if (union_item.has_where_clause ()) |
| expand_where_clause (union_item.get_where_clause ()); |
| |
| /* strip union fields if required - this is presumably |
| * allowed by spec */ |
| expand_struct_fields (union_item.get_variants ()); |
| } |
| void |
| AttrVisitor::visit (AST::ConstantItem &const_item) |
| { |
| // initial test based on outer attrs |
| expander.expand_cfg_attrs (const_item.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (const_item.get_outer_attrs ())) |
| { |
| const_item.mark_for_strip (); |
| return; |
| } |
| |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| |
| // strip any sub-types |
| auto &type = const_item.get_type (); |
| type->accept_vis (*this); |
| |
| maybe_expand_type (type); |
| |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| |
| /* strip any internal sub-expressions - expression itself isn't |
| * allowed to have external attributes in this position so can't be |
| * stripped. */ |
| auto &expr = const_item.get_expr (); |
| expr->accept_vis (*this); |
| if (expr->is_marked_for_strip ()) |
| rust_error_at (expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::StaticItem &static_item) |
| { |
| // initial test based on outer attrs |
| expander.expand_cfg_attrs (static_item.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (static_item.get_outer_attrs ())) |
| { |
| static_item.mark_for_strip (); |
| return; |
| } |
| |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| |
| // strip any sub-types |
| auto &type = static_item.get_type (); |
| type->accept_vis (*this); |
| |
| maybe_expand_type (type); |
| |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| |
| /* strip any internal sub-expressions - expression itself isn't |
| * allowed to have external attributes in this position so can't be |
| * stripped. */ |
| auto &expr = static_item.get_expr (); |
| expr->accept_vis (*this); |
| if (expr->is_marked_for_strip ()) |
| rust_error_at (expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| void |
| AttrVisitor::visit (AST::TraitItemFunc &item) |
| { |
| // initial test based on outer attrs |
| expander.expand_cfg_attrs (item.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (item.get_outer_attrs ())) |
| { |
| item.mark_for_strip (); |
| return; |
| } |
| |
| expand_trait_function_decl (item.get_trait_function_decl ()); |
| |
| if (item.has_definition ()) |
| { |
| /* strip any internal sub-expressions - expression itself isn't |
| * allowed to have external attributes in this position so can't be |
| * stripped. */ |
| auto &block = item.get_definition (); |
| block->accept_vis (*this); |
| if (block->is_marked_for_strip ()) |
| rust_error_at (block->get_locus (), |
| "cannot strip block expression in this " |
| "position - outer attributes not allowed"); |
| } |
| } |
| void |
| AttrVisitor::visit (AST::TraitItemMethod &item) |
| { |
| // initial test based on outer attrs |
| expander.expand_cfg_attrs (item.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (item.get_outer_attrs ())) |
| { |
| item.mark_for_strip (); |
| return; |
| } |
| |
| expand_trait_method_decl (item.get_trait_method_decl ()); |
| |
| if (item.has_definition ()) |
| { |
| /* strip any internal sub-expressions - expression itself isn't |
| * allowed to have external attributes in this position so can't be |
| * stripped. */ |
| auto &block = item.get_definition (); |
| block->accept_vis (*this); |
| if (block->is_marked_for_strip ()) |
| rust_error_at (block->get_locus (), |
| "cannot strip block expression in this " |
| "position - outer attributes not allowed"); |
| } |
| } |
| void |
| AttrVisitor::visit (AST::TraitItemConst &item) |
| { |
| // initial test based on outer attrs |
| expander.expand_cfg_attrs (item.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (item.get_outer_attrs ())) |
| { |
| item.mark_for_strip (); |
| return; |
| } |
| |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| |
| // strip any sub-types |
| auto &type = item.get_type (); |
| type->accept_vis (*this); |
| |
| maybe_expand_type (type); |
| |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| |
| /* strip any internal sub-expressions - expression itself isn't |
| * allowed to have external attributes in this position so can't be |
| * stripped */ |
| if (item.has_expression ()) |
| { |
| auto &expr = item.get_expr (); |
| expr->accept_vis (*this); |
| if (expr->is_marked_for_strip ()) |
| rust_error_at (expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| } |
| } |
| void |
| AttrVisitor::visit (AST::TraitItemType &item) |
| { |
| // initial test based on outer attrs |
| expander.expand_cfg_attrs (item.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (item.get_outer_attrs ())) |
| { |
| item.mark_for_strip (); |
| return; |
| } |
| |
| if (item.has_type_param_bounds ()) |
| { |
| // don't strip directly, only components of bounds |
| for (auto &bound : item.get_type_param_bounds ()) |
| bound->accept_vis (*this); |
| } |
| } |
| void |
| AttrVisitor::visit (AST::Trait &trait) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (trait.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (trait.get_outer_attrs ())) |
| { |
| trait.mark_for_strip (); |
| return; |
| } |
| |
| // strip test based on inner attrs |
| expander.expand_cfg_attrs (trait.get_inner_attrs ()); |
| if (expander.fails_cfg_with_expand (trait.get_inner_attrs ())) |
| { |
| trait.mark_for_strip (); |
| return; |
| } |
| |
| // just expand sub-stuff - can't actually strip generic params themselves |
| for (auto ¶m : trait.get_generic_params ()) |
| param->accept_vis (*this); |
| |
| if (trait.has_type_param_bounds ()) |
| { |
| // don't strip directly, only components of bounds |
| for (auto &bound : trait.get_type_param_bounds ()) |
| bound->accept_vis (*this); |
| } |
| |
| if (trait.has_where_clause ()) |
| expand_where_clause (trait.get_where_clause ()); |
| |
| std::function<std::unique_ptr<AST::TraitItem> (AST::SingleASTNode)> extractor |
| = [] (AST::SingleASTNode node) { return node.take_trait_item (); }; |
| |
| expand_macro_children (MacroExpander::TRAIT, trait.get_trait_items (), |
| extractor); |
| } |
| void |
| AttrVisitor::visit (AST::InherentImpl &impl) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (impl.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (impl.get_outer_attrs ())) |
| { |
| impl.mark_for_strip (); |
| return; |
| } |
| |
| // strip test based on inner attrs |
| expander.expand_cfg_attrs (impl.get_inner_attrs ()); |
| if (expander.fails_cfg_with_expand (impl.get_inner_attrs ())) |
| { |
| impl.mark_for_strip (); |
| return; |
| } |
| |
| // just expand sub-stuff - can't actually strip generic params themselves |
| for (auto ¶m : impl.get_generic_params ()) |
| param->accept_vis (*this); |
| |
| expander.push_context (MacroExpander::ContextType::ITEM); |
| |
| auto &type = impl.get_type (); |
| type->accept_vis (*this); |
| |
| maybe_expand_type (type); |
| |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| |
| if (impl.has_where_clause ()) |
| expand_where_clause (impl.get_where_clause ()); |
| |
| std::function<std::unique_ptr<AST::InherentImplItem> (AST::SingleASTNode)> |
| extractor = [] (AST::SingleASTNode node) { return node.take_impl_item (); }; |
| |
| expand_macro_children (MacroExpander::IMPL, impl.get_impl_items (), |
| extractor); |
| } |
| void |
| AttrVisitor::visit (AST::TraitImpl &impl) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (impl.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (impl.get_outer_attrs ())) |
| { |
| impl.mark_for_strip (); |
| return; |
| } |
| |
| // strip test based on inner attrs |
| expander.expand_cfg_attrs (impl.get_inner_attrs ()); |
| if (expander.fails_cfg_with_expand (impl.get_inner_attrs ())) |
| { |
| impl.mark_for_strip (); |
| return; |
| } |
| |
| // just expand sub-stuff - can't actually strip generic params themselves |
| for (auto ¶m : impl.get_generic_params ()) |
| param->accept_vis (*this); |
| |
| expander.push_context (MacroExpander::ContextType::ITEM); |
| |
| auto &type = impl.get_type (); |
| type->accept_vis (*this); |
| |
| maybe_expand_type (type); |
| |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| |
| auto &trait_path = impl.get_trait_path (); |
| visit (trait_path); |
| if (trait_path.is_marked_for_strip ()) |
| rust_error_at (trait_path.get_locus (), |
| "cannot strip typepath in this position"); |
| |
| if (impl.has_where_clause ()) |
| expand_where_clause (impl.get_where_clause ()); |
| |
| std::function<std::unique_ptr<AST::TraitImplItem> (AST::SingleASTNode)> |
| extractor |
| = [] (AST::SingleASTNode node) { return node.take_trait_impl_item (); }; |
| |
| expand_macro_children (MacroExpander::TRAIT_IMPL, impl.get_impl_items (), |
| extractor); |
| } |
| void |
| AttrVisitor::visit (AST::ExternalStaticItem &item) |
| { |
| // strip test based on outer attrs |
| expander.expand_cfg_attrs (item.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (item.get_outer_attrs ())) |
| { |
| item.mark_for_strip (); |
| return; |
| } |
| |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| |
| auto &type = item.get_type (); |
| type->accept_vis (*this); |
| |
| maybe_expand_type (type); |
| |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| } |
| void |
| AttrVisitor::visit (AST::ExternalFunctionItem &item) |
| { |
| // strip test based on outer attrs |
| expander.expand_cfg_attrs (item.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (item.get_outer_attrs ())) |
| { |
| item.mark_for_strip (); |
| return; |
| } |
| |
| // just expand sub-stuff - can't actually strip generic params themselves |
| for (auto ¶m : item.get_generic_params ()) |
| param->accept_vis (*this); |
| |
| /* strip function parameters if required - this is specifically |
| * allowed by spec */ |
| auto ¶ms = item.get_function_params (); |
| for (auto it = params.begin (); it != params.end ();) |
| { |
| auto ¶m = *it; |
| |
| auto ¶m_attrs = param.get_outer_attrs (); |
| expander.expand_cfg_attrs (param_attrs); |
| if (expander.fails_cfg_with_expand (param_attrs)) |
| { |
| it = params.erase (it); |
| continue; |
| } |
| |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| |
| auto &type = param.get_type (); |
| type->accept_vis (*this); |
| |
| maybe_expand_type (type); |
| |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), |
| "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| |
| // increment if nothing else happens |
| ++it; |
| } |
| /* NOTE: these are extern function params, which may have different |
| * rules and restrictions to "normal" function params. So expansion |
| * handled separately. */ |
| |
| /* TODO: assuming that variadic nature cannot be stripped. If this |
| * is not true, then have code here to do so. */ |
| |
| if (item.has_return_type ()) |
| { |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| |
| auto &return_type = item.get_return_type (); |
| return_type->accept_vis (*this); |
| |
| maybe_expand_type (return_type); |
| |
| if (return_type->is_marked_for_strip ()) |
| rust_error_at (return_type->get_locus (), |
| "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| } |
| |
| if (item.has_where_clause ()) |
| expand_where_clause (item.get_where_clause ()); |
| } |
| |
| void |
| AttrVisitor::visit (AST::ExternBlock &block) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (block.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (block.get_outer_attrs ())) |
| { |
| block.mark_for_strip (); |
| return; |
| } |
| |
| // strip test based on inner attrs |
| expander.expand_cfg_attrs (block.get_inner_attrs ()); |
| if (expander.fails_cfg_with_expand (block.get_inner_attrs ())) |
| { |
| block.mark_for_strip (); |
| return; |
| } |
| |
| std::function<std::unique_ptr<AST::ExternalItem> (AST::SingleASTNode)> |
| extractor |
| = [] (AST::SingleASTNode node) { return node.take_external_item (); }; |
| |
| expand_macro_children (MacroExpander::EXTERN, block.get_extern_items (), |
| extractor); |
| } |
| |
| // I don't think it would be possible to strip macros without expansion |
| void |
| AttrVisitor::visit (AST::MacroMatchFragment &) |
| {} |
| void |
| AttrVisitor::visit (AST::MacroMatchRepetition &) |
| {} |
| void |
| AttrVisitor::visit (AST::MacroMatcher &) |
| {} |
| void |
| AttrVisitor::visit (AST::MacroRulesDefinition &rules_def) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (rules_def.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (rules_def.get_outer_attrs ())) |
| { |
| rules_def.mark_for_strip (); |
| return; |
| } |
| } |
| |
| void |
| AttrVisitor::visit (AST::MetaItemPath &) |
| {} |
| void |
| AttrVisitor::visit (AST::MetaItemSeq &) |
| {} |
| void |
| AttrVisitor::visit (AST::MetaWord &) |
| {} |
| void |
| AttrVisitor::visit (AST::MetaNameValueStr &) |
| {} |
| void |
| AttrVisitor::visit (AST::MetaListPaths &) |
| {} |
| void |
| AttrVisitor::visit (AST::MetaListNameValueStr &) |
| {} |
| |
| void |
| AttrVisitor::visit (AST::LiteralPattern &) |
| { |
| // not possible |
| } |
| void |
| AttrVisitor::visit (AST::IdentifierPattern &pattern) |
| { |
| // can only strip sub-patterns of the inner pattern to bind |
| if (!pattern.has_pattern_to_bind ()) |
| return; |
| |
| auto &sub_pattern = pattern.get_pattern_to_bind (); |
| sub_pattern->accept_vis (*this); |
| if (sub_pattern->is_marked_for_strip ()) |
| rust_error_at (sub_pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| } |
| void |
| AttrVisitor::visit (AST::WildcardPattern &) |
| { |
| // not possible |
| } |
| void |
| AttrVisitor::visit (AST::RangePatternBoundLiteral &) |
| { |
| // not possible |
| } |
| void |
| AttrVisitor::visit (AST::RangePatternBoundPath &bound) |
| { |
| // can expand path, but not strip it directly |
| auto &path = bound.get_path (); |
| visit (path); |
| if (path.is_marked_for_strip ()) |
| rust_error_at (path.get_locus (), "cannot strip path in this position"); |
| } |
| void |
| AttrVisitor::visit (AST::RangePatternBoundQualPath &bound) |
| { |
| // can expand path, but not strip it directly |
| auto &path = bound.get_qualified_path (); |
| visit (path); |
| if (path.is_marked_for_strip ()) |
| rust_error_at (path.get_locus (), "cannot strip path in this position"); |
| } |
| void |
| AttrVisitor::visit (AST::RangePattern &pattern) |
| { |
| // should have no capability to strip lower or upper bounds, only expand |
| pattern.get_lower_bound ()->accept_vis (*this); |
| pattern.get_upper_bound ()->accept_vis (*this); |
| } |
| void |
| AttrVisitor::visit (AST::ReferencePattern &pattern) |
| { |
| auto &sub_pattern = pattern.get_referenced_pattern (); |
| sub_pattern->accept_vis (*this); |
| if (sub_pattern->is_marked_for_strip ()) |
| rust_error_at (sub_pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| } |
| void |
| AttrVisitor::visit (AST::StructPatternFieldTuplePat &field) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (field.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (field.get_outer_attrs ())) |
| { |
| field.mark_for_strip (); |
| return; |
| } |
| |
| // strip sub-patterns (can't strip top-level pattern) |
| auto &sub_pattern = field.get_index_pattern (); |
| sub_pattern->accept_vis (*this); |
| if (sub_pattern->is_marked_for_strip ()) |
| rust_error_at (sub_pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| } |
| void |
| AttrVisitor::visit (AST::StructPatternFieldIdentPat &field) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (field.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (field.get_outer_attrs ())) |
| { |
| field.mark_for_strip (); |
| return; |
| } |
| |
| // strip sub-patterns (can't strip top-level pattern) |
| auto &sub_pattern = field.get_ident_pattern (); |
| sub_pattern->accept_vis (*this); |
| if (sub_pattern->is_marked_for_strip ()) |
| rust_error_at (sub_pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| } |
| void |
| AttrVisitor::visit (AST::StructPatternFieldIdent &field) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (field.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (field.get_outer_attrs ())) |
| { |
| field.mark_for_strip (); |
| return; |
| } |
| } |
| void |
| AttrVisitor::visit (AST::StructPattern &pattern) |
| { |
| // expand (but don't strip) path |
| auto &path = pattern.get_path (); |
| visit (path); |
| if (path.is_marked_for_strip ()) |
| rust_error_at (path.get_locus (), "cannot strip path in this position"); |
| |
| /* TODO: apparently struct pattern fields can have outer attrs. so can they |
| * be stripped? */ |
| if (!pattern.has_struct_pattern_elems ()) |
| return; |
| |
| auto &elems = pattern.get_struct_pattern_elems (); |
| |
| // assuming you can strip struct pattern fields |
| expand_pointer_allow_strip (elems.get_struct_pattern_fields ()); |
| |
| // assuming you can strip the ".." part |
| if (elems.has_etc ()) |
| { |
| expander.expand_cfg_attrs (elems.get_etc_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (elems.get_etc_outer_attrs ())) |
| elems.strip_etc (); |
| } |
| } |
| void |
| AttrVisitor::visit (AST::TupleStructItemsNoRange &tuple_items) |
| { |
| // can't strip individual patterns, only sub-patterns |
| for (auto &pattern : tuple_items.get_patterns ()) |
| { |
| pattern->accept_vis (*this); |
| |
| if (pattern->is_marked_for_strip ()) |
| rust_error_at (pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| // TODO: quit stripping now? or keep going? |
| } |
| } |
| void |
| AttrVisitor::visit (AST::TupleStructItemsRange &tuple_items) |
| { |
| // can't strip individual patterns, only sub-patterns |
| for (auto &lower_pattern : tuple_items.get_lower_patterns ()) |
| { |
| lower_pattern->accept_vis (*this); |
| |
| if (lower_pattern->is_marked_for_strip ()) |
| rust_error_at (lower_pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| // TODO: quit stripping now? or keep going? |
| } |
| for (auto &upper_pattern : tuple_items.get_upper_patterns ()) |
| { |
| upper_pattern->accept_vis (*this); |
| |
| if (upper_pattern->is_marked_for_strip ()) |
| rust_error_at (upper_pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| // TODO: quit stripping now? or keep going? |
| } |
| } |
| void |
| AttrVisitor::visit (AST::TupleStructPattern &pattern) |
| { |
| // expand (but don't strip) path |
| auto &path = pattern.get_path (); |
| visit (path); |
| if (path.is_marked_for_strip ()) |
| rust_error_at (path.get_locus (), "cannot strip path in this position"); |
| |
| if (pattern.has_items ()) |
| pattern.get_items ()->accept_vis (*this); |
| } |
| void |
| AttrVisitor::visit (AST::TuplePatternItemsMultiple &tuple_items) |
| { |
| // can't strip individual patterns, only sub-patterns |
| for (auto &pattern : tuple_items.get_patterns ()) |
| { |
| pattern->accept_vis (*this); |
| |
| if (pattern->is_marked_for_strip ()) |
| rust_error_at (pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| // TODO: quit stripping now? or keep going? |
| } |
| } |
| void |
| AttrVisitor::visit (AST::TuplePatternItemsRanged &tuple_items) |
| { |
| // can't strip individual patterns, only sub-patterns |
| for (auto &lower_pattern : tuple_items.get_lower_patterns ()) |
| { |
| lower_pattern->accept_vis (*this); |
| |
| if (lower_pattern->is_marked_for_strip ()) |
| rust_error_at (lower_pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| // TODO: quit stripping now? or keep going? |
| } |
| for (auto &upper_pattern : tuple_items.get_upper_patterns ()) |
| { |
| upper_pattern->accept_vis (*this); |
| |
| if (upper_pattern->is_marked_for_strip ()) |
| rust_error_at (upper_pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| // TODO: quit stripping now? or keep going? |
| } |
| } |
| void |
| AttrVisitor::visit (AST::TuplePattern &pattern) |
| { |
| if (pattern.has_tuple_pattern_items ()) |
| pattern.get_items ()->accept_vis (*this); |
| } |
| void |
| AttrVisitor::visit (AST::GroupedPattern &pattern) |
| { |
| // can't strip inner pattern, only sub-patterns |
| auto &pattern_in_parens = pattern.get_pattern_in_parens (); |
| |
| pattern_in_parens->accept_vis (*this); |
| |
| if (pattern_in_parens->is_marked_for_strip ()) |
| rust_error_at (pattern_in_parens->get_locus (), |
| "cannot strip pattern in this position"); |
| } |
| void |
| AttrVisitor::visit (AST::SlicePattern &pattern) |
| { |
| // can't strip individual patterns, only sub-patterns |
| for (auto &item : pattern.get_items ()) |
| { |
| item->accept_vis (*this); |
| |
| if (item->is_marked_for_strip ()) |
| rust_error_at (item->get_locus (), |
| "cannot strip pattern in this position"); |
| // TODO: quit stripping now? or keep going? |
| } |
| } |
| void |
| AttrVisitor::visit (AST::AltPattern &pattern) |
| { |
| // can't strip individual patterns, only sub-patterns |
| for (auto &alt : pattern.get_alts ()) |
| { |
| alt->accept_vis (*this); |
| |
| if (alt->is_marked_for_strip ()) |
| rust_error_at (alt->get_locus (), |
| "cannot strip pattern in this position"); |
| // TODO: quit stripping now? or keep going? |
| } |
| } |
| |
| void |
| AttrVisitor::visit (AST::EmptyStmt &) |
| { |
| // assuming no outer attributes, so nothing can happen |
| } |
| void |
| AttrVisitor::visit (AST::LetStmt &stmt) |
| { |
| // initial strip test based on outer attrs |
| expander.expand_cfg_attrs (stmt.get_outer_attrs ()); |
| if (expander.fails_cfg_with_expand (stmt.get_outer_attrs ())) |
| { |
| stmt.mark_for_strip (); |
| return; |
| } |
| |
| // can't strip pattern, but call for sub-patterns |
| auto &pattern = stmt.get_pattern (); |
| pattern->accept_vis (*this); |
| if (pattern->is_marked_for_strip ()) |
| rust_error_at (pattern->get_locus (), |
| "cannot strip pattern in this position"); |
| |
| // similar for type |
| if (stmt.has_type ()) |
| { |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| |
| auto &type = stmt.get_type (); |
| type->accept_vis (*this); |
| |
| maybe_expand_type (type); |
| |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), |
| "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| } |
| |
| /* strip any internal sub-expressions - expression itself isn't |
| * allowed to have external attributes in this position so can't be |
| * stripped */ |
| if (stmt.has_init_expr ()) |
| { |
| auto &init_expr = stmt.get_init_expr (); |
| init_expr->accept_vis (*this); |
| |
| if (init_expr->is_marked_for_strip ()) |
| rust_error_at (init_expr->get_locus (), |
| "cannot strip expression in this position - outer " |
| "attributes not allowed"); |
| |
| maybe_expand_expr (init_expr); |
| } |
| } |
| void |
| AttrVisitor::visit (AST::ExprStmtWithoutBlock &stmt) |
| { |
| // outer attributes associated with expr, so rely on expr |
| |
| // guard - should prevent null pointer expr |
| if (stmt.is_marked_for_strip ()) |
| return; |
| |
| // strip if expr is to be stripped |
| auto &expr = stmt.get_expr (); |
| expr->accept_vis (*this); |
| if (expr->is_marked_for_strip ()) |
| { |
| stmt.mark_for_strip (); |
| return; |
| } |
| } |
| void |
| AttrVisitor::visit (AST::ExprStmtWithBlock &stmt) |
| { |
| // outer attributes associated with expr, so rely on expr |
| |
| // guard - should prevent null pointer expr |
| if (stmt.is_marked_for_strip ()) |
| return; |
| |
| // strip if expr is to be stripped |
| auto &expr = stmt.get_expr (); |
| expr->accept_vis (*this); |
| if (expr->is_marked_for_strip ()) |
| { |
| stmt.mark_for_strip (); |
| return; |
| } |
| } |
| |
| void |
| AttrVisitor::visit (AST::TraitBound &bound) |
| { |
| // nothing in for lifetimes to strip |
| |
| // expand but don't strip type path |
| auto &path = bound.get_type_path (); |
| visit (path); |
| if (path.is_marked_for_strip ()) |
| rust_error_at (path.get_locus (), |
| "cannot strip type path in this position"); |
| } |
| void |
| AttrVisitor::visit (AST::ImplTraitType &type) |
| { |
| // don't strip directly, only components of bounds |
| for (auto &bound : type.get_type_param_bounds ()) |
| bound->accept_vis (*this); |
| } |
| void |
| AttrVisitor::visit (AST::TraitObjectType &type) |
| { |
| // don't strip directly, only components of bounds |
| for (auto &bound : type.get_type_param_bounds ()) |
| bound->accept_vis (*this); |
| } |
| void |
| AttrVisitor::visit (AST::ParenthesisedType &type) |
| { |
| // expand but don't strip inner type |
| auto &inner_type = type.get_type_in_parens (); |
| inner_type->accept_vis (*this); |
| if (inner_type->is_marked_for_strip ()) |
| rust_error_at (inner_type->get_locus (), |
| "cannot strip type in this position"); |
| } |
| void |
| AttrVisitor::visit (AST::ImplTraitTypeOneBound &type) |
| { |
| // no stripping possible |
| visit (type.get_trait_bound ()); |
| } |
| void |
| AttrVisitor::visit (AST::TraitObjectTypeOneBound &type) |
| { |
| // no stripping possible |
| visit (type.get_trait_bound ()); |
| } |
| void |
| AttrVisitor::visit (AST::TupleType &type) |
| { |
| // TODO: assuming that types can't be stripped as types don't have outer |
| // attributes |
| for (auto &elem_type : type.get_elems ()) |
| { |
| elem_type->accept_vis (*this); |
| if (elem_type->is_marked_for_strip ()) |
| rust_error_at (elem_type->get_locus (), |
| "cannot strip type in this position"); |
| } |
| } |
| void |
| AttrVisitor::visit (AST::NeverType &) |
| { |
| // no stripping possible |
| } |
| void |
| AttrVisitor::visit (AST::RawPointerType &type) |
| { |
| // expand but don't strip type pointed to |
| auto &pointed_type = type.get_type_pointed_to (); |
| pointed_type->accept_vis (*this); |
| if (pointed_type->is_marked_for_strip ()) |
| rust_error_at (pointed_type->get_locus (), |
| "cannot strip type in this position"); |
| } |
| void |
| AttrVisitor::visit (AST::ReferenceType &type) |
| { |
| // expand but don't strip type referenced |
| auto &referenced_type = type.get_type_referenced (); |
| referenced_type->accept_vis (*this); |
| if (referenced_type->is_marked_for_strip ()) |
| rust_error_at (referenced_type->get_locus (), |
| "cannot strip type in this position"); |
| } |
| void |
| AttrVisitor::visit (AST::ArrayType &type) |
| { |
| // expand but don't strip type referenced |
| auto &base_type = type.get_elem_type (); |
| base_type->accept_vis (*this); |
| if (base_type->is_marked_for_strip ()) |
| rust_error_at (base_type->get_locus (), |
| "cannot strip type in this position"); |
| |
| // same for expression |
| auto &size_expr = type.get_size_expr (); |
| size_expr->accept_vis (*this); |
| if (size_expr->is_marked_for_strip ()) |
| rust_error_at (size_expr->get_locus (), |
| "cannot strip expression in this position"); |
| } |
| void |
| AttrVisitor::visit (AST::SliceType &type) |
| { |
| // expand but don't strip elem type |
| auto &elem_type = type.get_elem_type (); |
| elem_type->accept_vis (*this); |
| if (elem_type->is_marked_for_strip ()) |
| rust_error_at (elem_type->get_locus (), |
| "cannot strip type in this position"); |
| } |
| void |
| AttrVisitor::visit (AST::InferredType &) |
| { |
| // none possible |
| } |
| void |
| AttrVisitor::visit (AST::BareFunctionType &type) |
| { |
| // seem to be no generics |
| |
| // presumably function params can be stripped |
| auto ¶ms = type.get_function_params (); |
| for (auto it = params.begin (); it != params.end ();) |
| { |
| auto ¶m = *it; |
| |
| auto ¶m_attrs = param.get_outer_attrs (); |
| expander.expand_cfg_attrs (param_attrs); |
| if (expander.fails_cfg_with_expand (param_attrs)) |
| { |
| it = params.erase (it); |
| continue; |
| } |
| |
| expander.push_context (MacroExpander::ContextType::TYPE); |
| |
| auto &type = param.get_type (); |
| type->accept_vis (*this); |
| |
| maybe_expand_type (type); |
| |
| if (type->is_marked_for_strip ()) |
| rust_error_at (type->get_locus (), |
| "cannot strip type in this position"); |
| |
| expander.pop_context (); |
| |
| // increment if nothing else happens |
| ++it; |
| } |
| |
| /* TODO: assuming that variadic nature cannot be stripped. If this |
| * is not true, then have code here to do so. */ |
| |
| if (type.has_return_type ()) |
| { |
| // FIXME: Can we have type expansion in this position? |
| // In that case, we need to handle AST::TypeNoBounds on top of just |
| // AST::Types |
| auto &return_type = type.get_return_type (); |
| return_type->accept_vis (*this); |
| if (return_type->is_marked_for_strip ()) |
| rust_error_at (return_type->get_locus (), |
| "cannot strip type in this position"); |
| } |
| |
| // no where clause, apparently |
| } |
| |
| void |
| AttrVisitor::maybe_expand_expr (std::unique_ptr<AST::Expr> &expr) |
| { |
| auto final_fragment = expander.take_expanded_fragment (); |
| if (final_fragment.should_expand () |
| && final_fragment.is_expression_fragment ()) |
| expr = final_fragment.take_expression_fragment (); |
| } |
| |
| void |
| AttrVisitor::maybe_expand_type (std::unique_ptr<AST::Type> &type) |
| { |
| auto final_fragment = expander.take_expanded_fragment (); |
| if (final_fragment.should_expand () && final_fragment.is_type_fragment ()) |
| type = final_fragment.take_type_fragment (); |
| } |
| |
| } // namespace Rust |