diff options
author | SimplyTheOther <simplytheother@gmail.com> | 2020-11-15 22:18:49 +0800 |
---|---|---|
committer | SimplyTheOther <simplytheother@gmail.com> | 2020-12-08 21:10:31 +0800 |
commit | 4ec3b8d62b1b6ae79d55b71b423dcb04129884c6 (patch) | |
tree | e3b1d7ff3ac504d718c66af7b881d6757c9f8314 /gcc | |
parent | 25de39b1f0e307b0ff6de485d9ac5648e9295f3d (diff) | |
download | gcc-4ec3b8d62b1b6ae79d55b71b423dcb04129884c6.zip gcc-4ec3b8d62b1b6ae79d55b71b423dcb04129884c6.tar.gz gcc-4ec3b8d62b1b6ae79d55b71b423dcb04129884c6.tar.bz2 |
Added more expr cfg stripping
Fixed compile errors
Fixed compile errors relating to block expr visibility changes
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/analysis/rust-type-resolution.cc | 4 | ||||
-rw-r--r-- | gcc/rust/ast/rust-expr.h | 79 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 8 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 374 |
4 files changed, 409 insertions, 56 deletions
diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc index c3a5587..5aa2905 100644 --- a/gcc/rust/analysis/rust-type-resolution.cc +++ b/gcc/rust/analysis/rust-type-resolution.cc @@ -615,7 +615,7 @@ void TypeResolution::visit (AST::BlockExpr &expr) { scope.Push (); - for (auto &stmt : expr.statements) + for (auto &stmt : expr.get_statements ()) { stmt->accept_vis (*this); } @@ -792,7 +792,7 @@ TypeResolution::visit (AST::Function &function) } // walk the expression body - for (auto &stmt : function.get_definition ()->statements) + for (auto &stmt : function.get_definition ()->get_statements ()) { stmt->accept_vis (*this); } diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 6f68542..66ffe16 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -2565,7 +2565,6 @@ protected: // A block AST node class BlockExpr : public ExprWithBlock { -public: std::vector<Attribute> inner_attrs; // bool has_statements; @@ -2575,13 +2574,14 @@ public: Location locus; +public: std::string as_string () const override; // Returns whether the block contains statements. bool has_statements () const { return !statements.empty (); } - // Returns whether the block contains an expression - bool has_expr () const { return expr != nullptr; } + // Returns whether the block contains a final expression. + bool has_tail_expr () const { return expr != nullptr; } BlockExpr (std::vector<std::unique_ptr<Stmt> > block_statements, std::unique_ptr<ExprWithoutBlock> block_expr, @@ -2651,6 +2651,22 @@ public: } bool is_marked_for_strip () const override { return expr == nullptr && statements.empty (); } + // TODO: this mutable getter seems really dodgy. Think up better way. + const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; } + std::vector<Attribute> &get_inner_attrs () { return inner_attrs; } + + const std::vector<std::unique_ptr<Stmt> > &get_statements () const { return statements; } + std::vector<std::unique_ptr<Stmt> > &get_statements () { return statements; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<ExprWithoutBlock> &get_tail_expr () { + rust_assert (expr != nullptr); + return expr; + } + + // Removes the tail expression from the block. + void strip_tail_expr () { expr = nullptr; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2729,10 +2745,17 @@ public: void accept_vis (ASTVisitor &vis) override; - /* Invalid if inner expr is null, so base stripping on that. Technically, type should also not be null. */ + /* Invalid if inner expr is null, so base stripping on that. Technically, + * type should also not be null. */ void mark_for_strip () override { expr = nullptr; } bool is_marked_for_strip () const override { return expr == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<BlockExpr> &get_definition_block () { + rust_assert (expr != nullptr); + return expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2858,6 +2881,12 @@ public: void mark_for_strip () override { marked_for_strip = true; } bool is_marked_for_strip () const override { return marked_for_strip; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_break_expr () { + rust_assert (break_expr != nullptr); + return break_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2938,6 +2967,18 @@ public: void mark_for_strip () override { from = nullptr; to = nullptr; } bool is_marked_for_strip () const override { return from == nullptr && to == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_from_expr () { + rust_assert (from != nullptr); + return from; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_to_expr () { + rust_assert (to != nullptr); + return to; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2993,6 +3034,12 @@ public: void mark_for_strip () override { from = nullptr; } bool is_marked_for_strip () const override { return from == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_from_expr () { + rust_assert (from != nullptr); + return from; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3049,6 +3096,12 @@ public: void mark_for_strip () override { to = nullptr; } bool is_marked_for_strip () const override { return to == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_to_expr () { + rust_assert (to != nullptr); + return to; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3142,6 +3195,18 @@ public: void mark_for_strip () override { from = nullptr; to = nullptr; } bool is_marked_for_strip () const override { return from == nullptr && to == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_from_expr () { + rust_assert (from != nullptr); + return from; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_to_expr () { + rust_assert (to != nullptr); + return to; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3198,6 +3263,12 @@ public: void mark_for_strip () override { to = nullptr; } bool is_marked_for_strip () const override { return to == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_to_expr () { + rust_assert (to != nullptr); + return to; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 12ce47f..17d9cde 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -701,7 +701,7 @@ Compilation::visit (AST::BlockExpr &expr) start_location, end_location); scope.PushBlock (code_block); - for (auto &stmt : expr.statements) + for (auto &stmt : expr.get_statements ()) { stmt->accept_vis (*this); } @@ -1039,10 +1039,10 @@ Compilation::visit (AST::Function &function) Bblock *enclosingScope = NULL; Location start_location = function.get_locus (); Location end_location; - if (function.get_definition ()->statements.size () > 0) + if (function.get_definition ()->get_statements ().size () > 0) { end_location - = function.get_definition ()->statements.back ()->get_locus_slow (); + = function.get_definition ()->get_statements ().back ()->get_locus_slow (); } auto code_block = backend->block (fndecl, enclosingScope, vars, @@ -1063,7 +1063,7 @@ Compilation::visit (AST::Function &function) scope.PushCurrentFunction (function.get_function_name (), fndecl, returnType, retDecl); - for (auto &stmt : function.get_definition ()->statements) + for (auto &stmt : function.get_definition ()->get_statements ()) stmt->accept_vis (*this); scope.PopBlock (); diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index ed5f365..417f51b 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -2,6 +2,7 @@ #include "rust-ast-full.h" // is full really required? #include "rust-ast-visitor.h" +#include "rust-diagnostics.h" namespace Rust { // Visitor used to expand attributes. @@ -139,7 +140,11 @@ namespace Rust { /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ - expr.get_borrowed_expr()->accept_vis(*this); + 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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::DereferenceExpr& expr) override { // initial strip test based on outer attrs @@ -152,7 +157,11 @@ namespace Rust { /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ - expr.get_dereferenced_expr()->accept_vis(*this); + 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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::ErrorPropagationExpr& expr) override { // initial strip test based on outer attrs @@ -165,7 +174,11 @@ namespace Rust { /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ - expr.get_propagating_expr()->accept_vis(*this); + 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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::NegationExpr& expr) override { // initial strip test based on outer attrs @@ -178,7 +191,11 @@ namespace Rust { /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ - expr.get_negated_expr()->accept_vis(*this); + 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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::ArithmeticOrLogicalExpr& expr) override { /* outer attributes never allowed before these. while cannot strip @@ -192,8 +209,12 @@ namespace Rust { expr.get_right_expr()->accept_vis(*this); // ensure that they are not marked for strip - rust_assert(!expr.get_left_expr()->is_marked_for_strip()); - rust_assert(!expr.get_right_expr()->is_marked_for_strip()); + if (expr.get_left_expr()->is_marked_for_strip()) + rust_error_at(expr.get_left_expr()->get_locus_slow(), + "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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::ComparisonExpr& expr) override { /* outer attributes never allowed before these. while cannot strip @@ -207,8 +228,12 @@ namespace Rust { expr.get_right_expr()->accept_vis(*this); // ensure that they are not marked for strip - rust_assert(!expr.get_left_expr()->is_marked_for_strip()); - rust_assert(!expr.get_right_expr()->is_marked_for_strip()); + if (expr.get_left_expr()->is_marked_for_strip()) + rust_error_at(expr.get_left_expr()->get_locus_slow(), + "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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::LazyBooleanExpr& expr) override { /* outer attributes never allowed before these. while cannot strip @@ -222,19 +247,25 @@ namespace Rust { expr.get_right_expr()->accept_vis(*this); // ensure that they are not marked for strip - rust_assert(!expr.get_left_expr()->is_marked_for_strip()); - rust_assert(!expr.get_right_expr()->is_marked_for_strip()); + if (expr.get_left_expr()->is_marked_for_strip()) + rust_error_at(expr.get_left_expr()->get_locus_slow(), + "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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::TypeCastExpr& expr) override { /* outer attributes never allowed before these. while cannot strip - * two direct descendant expressions, can strip ones below that */ + * direct descendant expression, can strip ones below that */ /* should have no possibility for outer attrs as would be parsed * with outer expr */ expr.get_casted_expr()->accept_vis(*this); // ensure that they are not marked for strip - rust_assert(!expr.get_casted_expr()->is_marked_for_strip()); + if (expr.get_casted_expr()->is_marked_for_strip()) + rust_error_at(expr.get_casted_expr()->get_locus_slow(), + "cannot strip expression in this position - outer attributes are never allowed before cast exprs"); } void visit(AST::AssignmentExpr& expr) override { /* outer attributes never allowed before these. while cannot strip @@ -248,8 +279,12 @@ namespace Rust { expr.get_right_expr()->accept_vis(*this); // ensure that they are not marked for strip - rust_assert(!expr.get_left_expr()->is_marked_for_strip()); - rust_assert(!expr.get_right_expr()->is_marked_for_strip()); + if (expr.get_left_expr()->is_marked_for_strip()) + rust_error_at(expr.get_left_expr()->get_locus_slow(), + "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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::CompoundAssignmentExpr& expr) override { /* outer attributes never allowed before these. while cannot strip @@ -263,8 +298,12 @@ namespace Rust { expr.get_right_expr()->accept_vis(*this); // ensure that they are not marked for strip - rust_assert(!expr.get_left_expr()->is_marked_for_strip()); - rust_assert(!expr.get_right_expr()->is_marked_for_strip()); + if (expr.get_left_expr()->is_marked_for_strip()) + rust_error_at(expr.get_left_expr()->get_locus_slow(), + "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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::GroupedExpr& expr) override { // initial strip test based on outer attrs @@ -285,7 +324,11 @@ namespace Rust { /* strip any internal sub-expressions - expression itself isn't * allowed to have external attributes in this position so can't be * stripped. */ - expr.get_expr_in_parens()->accept_vis(*this); + 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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::ArrayElemsValues& elems) override { /* apparently outer attributes are allowed in "elements of array @@ -310,8 +353,17 @@ namespace Rust { * such, not implementing. TODO clear up the ambiguity here */ // only intend stripping for internal sub-expressions - elems.get_elem_to_copy()->accept_vis(*this); - elems.get_num_copies()->accept_vis(*this); + 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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + + auto& copy_count = elems.get_num_copies(); + copy_count->accept_vis(*this); + if (copy_count->is_marked_for_strip()) + rust_error_at(copy_count->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::ArrayExpr& expr) override { // initial strip test based on outer attrs @@ -336,14 +388,29 @@ namespace Rust { } void visit(AST::ArrayIndexExpr& expr) override { /* it is unclear whether outer attributes are supposed to be - * allowed, but conceptually it wouldn't make much sense, so - * assuming no. TODO */ + * 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(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. */ - expr.get_array_expr()->accept_vis(*this); - expr.get_index_expr()->accept_vis(*this); + 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_slow(), + "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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::TupleExpr& expr) override { /* according to spec, outer attributes are allowed on "elements of @@ -390,7 +457,11 @@ namespace Rust { /* 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. */ - expr.get_tuple_expr()->accept_vis(*this); + 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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::StructExprStruct& expr) override { // initial strip test based on outer attrs @@ -414,12 +485,20 @@ namespace Rust { void visit(AST::StructExprFieldIdentifierValue& field) override { /* as no attrs possible (at moment, at least), only sub-expression * stripping is possible */ - field.get_value()->accept_vis(*this); + auto& value = field.get_value(); + value->accept_vis(*this); + if (value->is_marked_for_strip()) + rust_error_at(value->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::StructExprFieldIndexValue& field) override { /* as no attrs possible (at moment, at least), only sub-expression * stripping is possible */ - field.get_value()->accept_vis(*this); + auto& value = field.get_value(); + value->accept_vis(*this); + if (value->is_marked_for_strip()) + rust_error_at(value->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::StructExprStructFields& expr) override { // initial strip test based on outer attrs @@ -448,8 +527,13 @@ namespace Rust { /* 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()) - expr.get_struct_base().get_base_struct()->accept_vis(*this); + 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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + } } void visit(AST::StructExprStructBase& expr) override { // initial strip test based on outer attrs @@ -470,7 +554,11 @@ namespace Rust { /* 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()); - expr.get_struct_base().get_base_struct()->accept_vis(*this); + 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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::StructExprTuple& expr) override { // initial strip test based on outer attrs @@ -517,12 +605,20 @@ namespace Rust { void visit(AST::EnumExprFieldIdentifierValue& field) override { /* as no attrs possible (at moment, at least), only sub-expression * stripping is possible */ - field.get_value()->accept_vis(*this); + auto& value = field.get_value(); + value->accept_vis(*this); + if (value->is_marked_for_strip()) + rust_error_at(value->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::EnumExprFieldIndexValue& field) override { /* as no attrs possible (at moment, at least), only sub-expression * stripping is possible */ - field.get_value()->accept_vis(*this); + auto& value = field.get_value(); + value->accept_vis(*this); + if (value->is_marked_for_strip()) + rust_error_at(value->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::EnumExprStruct& expr) override { // initial strip test based on outer attrs @@ -582,7 +678,11 @@ namespace Rust { /* 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. */ - expr.get_function_expr()->accept_vis(*this); + auto& function = expr.get_function_expr(); + function->accept_vis(*this); + if (function->is_marked_for_strip()) + rust_error_at(function->get_locus_slow(), + "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 */ @@ -610,7 +710,11 @@ namespace Rust { /* 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. */ - expr.get_receiver_expr()->accept_vis(*this); + auto& receiver = expr.get_receiver_expr(); + receiver->accept_vis(*this); + if (receiver->is_marked_for_strip()) + rust_error_at(receiver->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); // no outer attrs on paths possible @@ -638,9 +742,13 @@ namespace Rust { } /* should not be outer attrs on "receiver" expression - outer attrs - * should be associated with call expr as a whole. only sub-expr + * should be associated with field expr as a whole. only sub-expr * expansion is possible. */ - expr.get_receiver_expr()->accept_vis(*this); + auto& receiver = expr.get_receiver_expr(); + receiver->accept_vis(*this); + if (receiver->is_marked_for_strip()) + rust_error_at(receiver->get_locus_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::ClosureExprInner& expr) override { // initial strip test based on outer attrs @@ -661,19 +769,193 @@ namespace Rust { else i++; } + + // 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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); } void visit(AST::BlockExpr& expr) override { - - } - void visit(AST::ClosureExprInnerTyped& expr) override {} - void visit(AST::ContinueExpr& expr) override {} - void visit(AST::BreakExpr& expr) override {} - void visit(AST::RangeFromToExpr& expr) override {} - void visit(AST::RangeFromExpr& expr) override {} - void visit(AST::RangeToExpr& expr) override {} - void visit(AST::RangeFullExpr& expr) override {} - void visit(AST::RangeFromToInclExpr& expr) override {} - void visit(AST::RangeToInclExpr& expr) override {} + // initial strip test based on outer attrs + expander.expand_cfg_attrs(expr.get_outer_attrs()); + if (expander.fails_cfg(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(expr.get_inner_attrs())) { + expr.mark_for_strip(); + return; + } + + // strip all statements + auto& stmts = expr.get_statements(); + for (int i = 0; i < stmts.size();) { + auto& stmt = stmts[i]; + + // mark for stripping if required + stmt->accept_vis(*this); + + if (stmt->is_marked_for_strip()) + stmts.erase(stmts.begin() + i); + else + i++; + } + + // 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); + + if (tail_expr->is_marked_for_strip()) + expr.strip_tail_expr(); + } + } + void visit(AST::ClosureExprInnerTyped& expr) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(expr.get_outer_attrs()); + if (expander.fails_cfg(expr.get_outer_attrs())) { + expr.mark_for_strip(); + return; + } + + /* strip closure parameters if required - this is specifically + * allowed by spec */ + auto& params = expr.get_params(); + for (int i = 0; i < params.size();) { + auto& param_attrs = params[i].get_outer_attrs(); + expander.expand_cfg_attrs(param_attrs); + if (expander.fails_cfg(param_attrs)) + params.erase(params.begin() + i); + else + i++; + } + + // 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_slow(), + "cannot strip block expression in this position - outer attributes not allowed"); + } + void visit(AST::ContinueExpr& expr) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(expr.get_outer_attrs()); + if (expander.fails_cfg(expr.get_outer_attrs())) { + expr.mark_for_strip(); + return; + } + } + void visit(AST::BreakExpr& expr) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(expr.get_outer_attrs()); + if (expander.fails_cfg(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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + } + } + void visit(AST::RangeFromToExpr& expr) override { + /* 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_slow(), + "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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + } + void visit(AST::RangeFromExpr& expr) override { + /* 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_slow(), + "cannot strip expression in this position - outer attributes are never allowed before range exprs"); + } + void visit(AST::RangeToExpr& expr) override { + /* 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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + } + void visit(AST::RangeFullExpr& expr) override { + // outer attributes never allowed before these, so no stripping + } + void visit(AST::RangeFromToInclExpr& expr) override { + /* 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_slow(), + "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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + } + void visit(AST::RangeToInclExpr& expr) override { + /* 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_slow(), + "cannot strip expression in this position - outer attributes not allowed"); + } void visit(AST::ReturnExpr& expr) override {} void visit(AST::UnsafeBlockExpr& expr) override {} void visit(AST::LoopExpr& expr) override {} |