diff options
author | SimplyTheOther <simplytheother@gmail.com> | 2020-11-10 12:22:20 +0800 |
---|---|---|
committer | SimplyTheOther <simplytheother@gmail.com> | 2020-12-08 21:10:26 +0800 |
commit | 37bbf2b8cbd4578f0fbe7cbbd573493481f62a45 (patch) | |
tree | 0adb716f3dc73607e30175d1b55267f01d4341f9 | |
parent | 164e38246f0f469fa83f5fa3f56fc53fa1b46450 (diff) | |
download | gcc-37bbf2b8cbd4578f0fbe7cbbd573493481f62a45.zip gcc-37bbf2b8cbd4578f0fbe7cbbd573493481f62a45.tar.gz gcc-37bbf2b8cbd4578f0fbe7cbbd573493481f62a45.tar.bz2 |
Added cfg stripping for some expressions
Attempt to fix compile error
-rw-r--r-- | gcc/rust/analysis/rust-type-resolution.cc | 18 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast.h | 11 | ||||
-rw-r--r-- | gcc/rust/ast/rust-expr.h | 153 | ||||
-rw-r--r-- | gcc/rust/ast/rust-item.h | 104 | ||||
-rw-r--r-- | gcc/rust/ast/rust-macro.h | 4 | ||||
-rw-r--r-- | gcc/rust/ast/rust-path.h | 1 | ||||
-rw-r--r-- | gcc/rust/ast/rust-stmt.h | 24 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 50 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 746 |
9 files changed, 951 insertions, 160 deletions
diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc index aef02ce..87cf828 100644 --- a/gcc/rust/analysis/rust-type-resolution.cc +++ b/gcc/rust/analysis/rust-type-resolution.cc @@ -158,7 +158,7 @@ void TypeResolution::visit (AST::IdentifierExpr &ident_expr) { AST::Type *type = NULL; - bool ok = scope.LookupType (ident_expr.ident, &type); + bool ok = scope.LookupType (ident_expr.get_ident (), &type); if (!ok) { rust_error_at (ident_expr.get_locus (), "unknown identifier"); @@ -235,7 +235,7 @@ void TypeResolution::visit (AST::LiteralExpr &expr) { std::string type; - switch (expr.literal.get_lit_type ()) + switch (expr.get_lit_type ()) { case AST::Literal::CHAR: type = "char"; @@ -273,7 +273,7 @@ TypeResolution::visit (AST::LiteralExpr &expr) if (type.empty ()) { rust_error_at (expr.get_locus (), "unknown literal: %s", - expr.literal.as_string ().c_str ()); + expr.get_literal ().as_string ().c_str ()); return; } @@ -338,7 +338,7 @@ TypeResolution::visit (AST::ArithmeticOrLogicalExpr &expr) // scope will require knowledge of the type // do the lhsType and the rhsType match - typesAreCompatible (lhsType, rhsType, expr.right_expr->get_locus_slow ()); + typesAreCompatible (lhsType, rhsType, expr.get_right_expr ()->get_locus_slow ()); } void @@ -382,7 +382,7 @@ TypeResolution::visit (AST::AssignmentExpr &expr) // do the lhsType and the rhsType match if (!typesAreCompatible (lhsType, rhsType, - expr.right_expr->get_locus_slow ())) + expr.get_right_expr ()->get_locus_slow ())) return; // is the lhs mutable? @@ -469,7 +469,7 @@ TypeResolution::visit (AST::StructExprStructFields &expr) if (identifierBuffer != NULL) { AST::StructField *declField = NULL; - for (auto &df : decl->fields) + for (auto &df : decl->get_fields ()) { if (identifierBuffer->compare (df.field_name) == 0) { @@ -493,9 +493,9 @@ TypeResolution::visit (AST::StructExprStructFields &expr) else if (tupleIndexBuffer != NULL) { AST::StructField *declField = NULL; - if (*tupleIndexBuffer < decl->fields.size ()) + if (*tupleIndexBuffer < decl->get_fields ().size ()) { - declField = &decl->fields[*tupleIndexBuffer]; + declField = &decl->get_fields ()[*tupleIndexBuffer]; } tupleIndexBuffer = NULL; @@ -811,7 +811,7 @@ TypeResolution::visit (AST::TypeAlias &type_alias) void TypeResolution::visit (AST::StructStruct &struct_item) { - for (auto &field : struct_item.fields) + for (auto &field : struct_item.get_fields ()) { if (!isTypeInScope (field.field_type.get (), Linemap::unknown_location ())) diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index e0f46ac..c186f22 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -810,7 +810,9 @@ class Expr std::vector<Attribute> outer_attrs; public: + // TODO: this mutable getter seems really dodgy. Think up better way. const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } + std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } // Unique pointer custom clone function std::unique_ptr<Expr> clone_expr () const @@ -905,11 +907,10 @@ public: */ class IdentifierExpr : public ExprWithoutBlock { -public: Identifier ident; - Location locus; +public: IdentifierExpr (Identifier ident, Location locus = Location (), std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) @@ -922,6 +923,8 @@ public: Location get_locus () const { return locus; } Location get_locus_slow () const override { return get_locus (); } + Identifier get_ident () const { return ident; } + void accept_vis (ASTVisitor &vis) override; // Clones this object. @@ -1385,6 +1388,10 @@ public: void mark_for_strip () override { path = SimplePath::create_empty (); } bool is_marked_for_strip () const override { return path.is_empty (); } + // TODO: this mutable getter seems really dodgy. Think up better way. + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } + std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } + protected: MacroInvocationSemi *clone_macro_invocation_semi_impl () const { diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 4647829..a92a8ad 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -41,10 +41,10 @@ public: // Literals? Or literal base? class LiteralExpr : public ExprWithoutBlock { -public: Literal literal; Location locus; +public: std::string as_string () const override { return literal.as_string (); } Literal::LitType get_lit_type () const { return literal.get_lit_type (); } @@ -71,6 +71,8 @@ public: Location get_locus () const { return locus; } Location get_locus_slow () const override { return get_locus (); } + Literal get_literal () const { return literal; } + void accept_vis (ASTVisitor &vis) override; // Invalid if literal is in error state, so base stripping on that. @@ -118,10 +120,7 @@ public: /* this can never be a cfg predicate - cfg and cfg_attr require a token-tree * cfg */ bool - check_cfg_predicate (const Session&) const override - { - return false; - } + check_cfg_predicate (const Session&) const override { return false; } protected: /* Use covariance to implement clone function as returning this object rather @@ -264,6 +263,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_borrowed_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -287,6 +292,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_dereferenced_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -311,6 +322,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_propagating_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -330,6 +347,7 @@ public: NOT }; +private: /* Note: overload negation via std::ops::Neg and not via std::ops::Not * Negation only works for signed integer and floating-point types, NOT only * works for boolean and integer types (via bitwise NOT) */ @@ -350,7 +368,11 @@ public: void accept_vis (ASTVisitor &vis) override; - Expr *get_expr () { return main_or_left_expr.get (); } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_negated_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } protected: /* Use covariance to implement clone function as returning this object rather @@ -379,6 +401,7 @@ public: RIGHT_SHIFT // std::ops::Shr }; +private: // Note: overloading trait specified in comments ExprType expr_type; @@ -422,7 +445,17 @@ public: void accept_vis (ASTVisitor &vis) override; - Expr *get_lhs () { return main_or_left_expr.get (); } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_left_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_right_expr () { + rust_assert (right_expr != nullptr); + return right_expr; + } void visit_lhs (ASTVisitor &vis) { main_or_left_expr->accept_vis (vis); } void visit_rhs (ASTVisitor &vis) { right_expr->accept_vis (vis); } @@ -450,6 +483,7 @@ public: LESS_OR_EQUAL // std::cmp::PartialEq::le }; +private: // Note: overloading trait specified in comments ExprType expr_type; @@ -493,7 +527,17 @@ public: void accept_vis (ASTVisitor &vis) override; - Expr *get_lhs () { return main_or_left_expr.get (); } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_left_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_right_expr () { + rust_assert (right_expr != nullptr); + return right_expr; + } /* TODO: implement via a function call to std::cmp::PartialEq::eq(&op1, &op2) * maybe? */ @@ -516,6 +560,7 @@ public: LOGICAL_AND }; +private: ExprType expr_type; std::unique_ptr<Expr> right_expr; @@ -558,7 +603,17 @@ public: void accept_vis (ASTVisitor &vis) override; - Expr *get_lhs () { return main_or_left_expr.get (); } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_left_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_right_expr () { + rust_assert (right_expr != nullptr); + return right_expr; + } protected: /* Use covariance to implement clone function as returning this object rather @@ -602,12 +657,18 @@ public: return *this; } - // move constructors as not supported in c++03 + // move constructors TypeCastExpr (TypeCastExpr &&other) = default; TypeCastExpr &operator= (TypeCastExpr &&other) = default; void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_casted_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -620,9 +681,9 @@ protected: // Binary assignment expression. class AssignmentExpr : public OperatorExpr { -public: std::unique_ptr<Expr> right_expr; +public: std::string as_string () const override; // Call OperatorExpr constructor to initialise left_expr @@ -659,7 +720,17 @@ public: void visit_lhs (ASTVisitor &vis) { main_or_left_expr->accept_vis (vis); } void visit_rhs (ASTVisitor &vis) { right_expr->accept_vis (vis); } - Expr *get_lhs () { return main_or_left_expr.get (); } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_left_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_right_expr () { + rust_assert (right_expr != nullptr); + return right_expr; + } protected: /* Use covariance to implement clone function as returning this object rather @@ -733,6 +804,18 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_left_expr () { + rust_assert (main_or_left_expr != nullptr); + return main_or_left_expr; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_right_expr () { + rust_assert (right_expr != nullptr); + return right_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -753,7 +836,8 @@ class GroupedExpr : public ExprWithoutBlock public: std::string as_string () const override; - std::vector<Attribute> get_inner_attrs () const { return inner_attrs; } + const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; } + std::vector<Attribute> &get_inner_attrs () { return inner_attrs; } GroupedExpr (std::unique_ptr<Expr> parenthesised_expr, std::vector<Attribute> inner_attribs, @@ -803,6 +887,12 @@ public: void mark_for_strip () override { expr_in_parens = nullptr; } bool is_marked_for_strip () const override { return expr_in_parens == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_expr_in_parens () { + rust_assert (expr_in_parens != nullptr); + return expr_in_parens; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -872,6 +962,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems really dodgy. Think up better way. + const std::vector<std::unique_ptr<Expr> > &get_values () const { return values; } + std::vector<std::unique_ptr<Expr> > &get_values () { return values; } + protected: ArrayElemsValues *clone_array_elems_impl () const override { @@ -918,6 +1012,18 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_elem_to_copy () { + rust_assert (elem_to_copy != nullptr); + return elem_to_copy; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_num_copies () { + rust_assert (num_copies != nullptr); + return num_copies; + } + protected: ArrayElemsCopied *clone_array_elems_impl () const override { @@ -939,7 +1045,8 @@ class ArrayExpr : public ExprWithoutBlock public: std::string as_string () const override; - std::vector<Attribute> get_inner_attrs () const { return inner_attrs; } + const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; } + std::vector<Attribute> &get_inner_attrs () { return inner_attrs; } // Returns whether array expr has array elems or if it is just empty. bool has_array_elems () const { return internal_elements != nullptr; } @@ -992,6 +1099,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<ArrayElems> &get_array_elems () { + rust_assert (internal_elements != nullptr); + return internal_elements; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1068,6 +1181,18 @@ public: void mark_for_strip () override { array_expr = nullptr; index_expr = nullptr; } bool is_marked_for_strip () const override { return array_expr == nullptr && index_expr == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_array_expr () { + rust_assert (array_expr != nullptr); + return array_expr; + } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_index_expr () { + rust_assert (index_expr != nullptr); + return index_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index a4ff3eb..8a85edad 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -733,6 +733,19 @@ public: void mark_for_strip () override { function_body = nullptr; } bool is_marked_for_strip () const override { return function_body == nullptr; } + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } + + std::vector<FunctionParam> &get_function_params () { return function_params; } + const std::vector<FunctionParam> &get_function_params () const { return function_params; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<BlockExpr> &get_definition () { + rust_assert (function_body != nullptr); + return function_body; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -879,6 +892,13 @@ public: * the module. */ void add_crate_name (std::vector<std::string> &names) const override; + // TODO: think of better way to do this - mutable getter seems dodgy + 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<Item>>& get_items () const { return items; } + std::vector<std::unique_ptr<Item>>& get_items () { return items; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1366,6 +1386,16 @@ public: void mark_for_strip () override { function_body = nullptr; } bool is_marked_for_strip () const override { return function_body == nullptr; } + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<FunctionParam> &get_function_params () { return function_params; } + const std::vector<FunctionParam> &get_function_params () const { return function_params; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<BlockExpr> &get_definition () { + rust_assert (function_body != nullptr); + return function_body; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1637,10 +1667,10 @@ public: // Rust struct declaration with true struct type AST node class StructStruct : public Struct { -public: std::vector<StructField> fields; bool is_unit; +public: std::string as_string () const override; // Mega-constructor with all possible fields @@ -1672,6 +1702,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<StructField> &get_fields () { return fields; } + const std::vector<StructField> &get_fields () const { return fields; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1712,19 +1746,27 @@ public: // Copy constructor with clone TupleField (TupleField const &other) - : outer_attrs (other.outer_attrs), visibility (other.visibility), - field_type (other.field_type->clone_type ()) - {} + : outer_attrs (other.outer_attrs), visibility (other.visibility) + { + // guard to prevent null dereference (only required if error) + if (other.field_type != nullptr) + field_type = other.field_type->clone_type (); + } ~TupleField () = default; // Overloaded assignment operator to clone TupleField &operator= (TupleField const &other) { - field_type = other.field_type->clone_type (); visibility = other.visibility; outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error) + if (other.field_type != nullptr) + field_type = other.field_type->clone_type (); + else + field_type = nullptr; + return *this; } @@ -1742,6 +1784,10 @@ public: } std::string as_string () const; + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } }; // Rust tuple declared using struct keyword AST node @@ -1765,6 +1811,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<TupleField> &get_fields () { return fields; } + const std::vector<TupleField> &get_fields () const { return fields; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1808,6 +1858,14 @@ public: // not pure virtual as not abstract virtual void accept_vis (ASTVisitor &vis); + // Based on idea that name is never empty. + void mark_for_strip () { variant_name = ""; } + bool is_marked_for_strip () const { return variant_name.empty (); } + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } + protected: // Clone function implementation as (not pure) virtual method virtual EnumItem *clone_enum_item_impl () const @@ -1836,6 +1894,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<TupleField> &get_tuple_fields () { return tuple_fields; } + const std::vector<TupleField> &get_tuple_fields () const { return tuple_fields; } + protected: // Clone function implementation as (not pure) virtual method EnumItemTuple *clone_enum_item_impl () const override @@ -1865,6 +1927,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<StructField> &get_struct_fields () { return struct_fields; } + const std::vector<StructField> &get_struct_fields () const { return struct_fields; } + protected: // Clone function implementation as (not pure) virtual method EnumItemStruct *clone_enum_item_impl () const override @@ -1909,6 +1975,12 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_expr () { + rust_assert (expression != nullptr); + return expression; + } + protected: // Clone function implementation as (not pure) virtual method EnumItemDiscriminant *clone_enum_item_impl () const override @@ -2005,6 +2077,10 @@ public: void mark_for_strip () override { enum_name = ""; } bool is_marked_for_strip () const override { return enum_name.empty (); } + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<std::unique_ptr<EnumItem>> &get_variants () { return items; } + const std::vector<std::unique_ptr<EnumItem>> &get_variants () const { return items; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2169,6 +2245,12 @@ public: void mark_for_strip () override { type = nullptr; const_expr = nullptr; } bool is_marked_for_strip () const override { return type == nullptr && const_expr == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_expr () { + rust_assert (const_expr != nullptr); + return const_expr; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2258,6 +2340,12 @@ public: void mark_for_strip () override { type = nullptr; expr = nullptr; } bool is_marked_for_strip () const override { return type == nullptr && expr == nullptr; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_expr () { + rust_assert (expr != nullptr); + return expr; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2715,6 +2803,12 @@ public: std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_expr () { + rust_assert (expr != nullptr); + return expr; + } + protected: // Clone function implementation as (not pure) virtual method TraitItemConst *clone_trait_item_impl () const override diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index 8d50b88..2a97854 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -315,6 +315,10 @@ public: void mark_for_strip () override { rule_name = ""; } bool is_marked_for_strip () const override { return rule_name.empty (); } + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 32147d3..c59e6bd 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -328,7 +328,6 @@ class TypePathSegment * GenericArgs are, so could disallow that in constructor, which won't give * that much size overhead. */ PathIdentSegment ident_segment; - Location locus; protected: diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index 127ea21..f7c47d7 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -38,10 +38,10 @@ protected: * introduces new name into scope */ class LetStmt : public Stmt { -public: // bool has_outer_attrs; std::vector<Attribute> outer_attrs; +public: std::unique_ptr<Pattern> variables_pattern; // bool has_type; @@ -125,6 +125,16 @@ public: void mark_for_strip () override { variables_pattern = nullptr; } bool is_marked_for_strip () const override { return variables_pattern == nullptr; } + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } + + // TODO: is this better? Or is a "vis_block" better? + std::unique_ptr<Expr> &get_init_expr () { + rust_assert (init_expr != nullptr); + return init_expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -204,6 +214,12 @@ public: 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<ExprWithoutBlock> &get_expr () { + rust_assert (expr != nullptr); + return expr; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -260,6 +276,12 @@ public: 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<ExprWithBlock> &get_expr () { + rust_assert (expr != nullptr); + return expr; + } + 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 af0f454..0589347 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -246,7 +246,7 @@ void Compilation::visit (AST::LiteralExpr &expr) { Bexpression *compiled; - switch (expr.literal.get_lit_type ()) + switch (expr.get_lit_type ()) { case AST::Literal::BOOL: compiled = compileBooleanLiteral (expr.as_string ()); @@ -293,16 +293,16 @@ void Compilation::visit (AST::NegationExpr &expr) { Bexpression *root = NULL; - VISIT_POP (expr.get_expr ()->get_locus_slow (), expr.get_expr (), root, + VISIT_POP (expr.get_negated_expr ()->get_locus_slow (), expr.get_negated_expr ().get (), root, exprs); if (root == NULL) { - rust_error_at (expr.get_expr ()->get_locus_slow (), "failed to compile"); + rust_error_at (expr.get_negated_expr ()->get_locus_slow (), "failed to compile"); return; } Operator op; - switch (expr.negation_type) + switch (expr.get_negation_type ()) { case AST::NegationExpr::NEGATE: op = OPERATOR_MINUS; @@ -323,23 +323,23 @@ void Compilation::visit (AST::ArithmeticOrLogicalExpr &expr) { Bexpression *lhs = NULL; - VISIT_POP (expr.get_lhs ()->get_locus_slow (), expr.get_lhs (), lhs, exprs); + VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs); if (lhs == NULL) { - rust_error_at (expr.get_lhs ()->get_locus_slow (), "failed to compile"); + rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile"); return; } Bexpression *rhs = NULL; - VISIT_POP (expr.right_expr->get_locus_slow (), expr.right_expr, rhs, exprs); + VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs); if (rhs == NULL) { - rust_error_at (expr.right_expr->get_locus_slow (), "failed to compile"); + rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile"); return; } Operator op; - switch (expr.expr_type) + switch (expr.get_expr_type ()) { case AST::ArithmeticOrLogicalExpr::ADD: op = OPERATOR_PLUS; @@ -385,23 +385,23 @@ void Compilation::visit (AST::ComparisonExpr &expr) { Bexpression *lhs = NULL; - VISIT_POP (expr.get_lhs ()->get_locus_slow (), expr.get_lhs (), lhs, exprs); + VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs); if (lhs == NULL) { - rust_error_at (expr.get_lhs ()->get_locus_slow (), "failed to compile"); + rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile"); return; } Bexpression *rhs = NULL; - VISIT_POP (expr.right_expr->get_locus_slow (), expr.right_expr, rhs, exprs); + VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs); if (rhs == NULL) { - rust_error_at (expr.right_expr->get_locus_slow (), "failed to compile"); + rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile"); return; } Operator op; - switch (expr.expr_type) + switch (expr.get_expr_type ()) { case AST::ComparisonExpr::EQUAL: op = OPERATOR_EQEQ; @@ -435,23 +435,23 @@ void Compilation::visit (AST::LazyBooleanExpr &expr) { Bexpression *lhs = NULL; - VISIT_POP (expr.get_lhs ()->get_locus_slow (), expr.get_lhs (), lhs, exprs); + VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs); if (lhs == NULL) { - rust_error_at (expr.get_lhs ()->get_locus_slow (), "failed to compile"); + rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile"); return; } Bexpression *rhs = NULL; - VISIT_POP (expr.right_expr->get_locus_slow (), expr.right_expr, rhs, exprs); + VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs); if (rhs == NULL) { - rust_error_at (expr.right_expr->get_locus_slow (), "failed to compile"); + rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile"); return; } Operator op; - switch (expr.expr_type) + switch (expr.get_expr_type ()) { case AST::LazyBooleanExpr::LOGICAL_OR: op = OPERATOR_OROR; @@ -477,18 +477,18 @@ void Compilation::visit (AST::AssignmentExpr &expr) { Bexpression *lhs = NULL; - VISIT_POP (expr.get_lhs ()->get_locus_slow (), expr.get_lhs (), lhs, exprs); + VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs); if (lhs == NULL) { - rust_error_at (expr.get_lhs ()->get_locus_slow (), "failed to compile"); + rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile"); return; } Bexpression *rhs = NULL; - VISIT_POP (expr.right_expr->get_locus_slow (), expr.right_expr, rhs, exprs); + VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs); if (rhs == NULL) { - rust_error_at (expr.right_expr->get_locus_slow (), "failed to compile"); + rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile"); return; } @@ -536,7 +536,7 @@ Compilation::visit (AST::StructExprFieldIdentifierValue &field) AST::StructStruct *decl = structBuffer.back (); size_t index = 0; bool found = false; - for (auto &df : decl->fields) + for (auto &df : decl->get_fields ()) { if (field.field_name.compare (df.field_name) == 0) { @@ -1089,7 +1089,7 @@ void Compilation::visit (AST::StructStruct &struct_item) { std::vector<Backend::Btyped_identifier> fields; - for (auto &field : struct_item.fields) + for (auto &field : struct_item.get_fields ()) { translatedType = NULL; field.field_type->accept_vis (*this); diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index ad97e2cd..164b5a5 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -13,62 +13,338 @@ namespace Rust { AttrVisitor(MacroExpander& expander) : expander(expander) {} void expand_struct_fields(std::vector<AST::StructField>& fields) { - for (int i = 0; i < fields.size(); ) { - auto& field_attrs = fields[i].get_outer_attrs (); + for (int i = 0; i < fields.size();) { + auto& field_attrs = fields[i].get_outer_attrs(); expander.expand_cfg_attrs(field_attrs); - if (expander.fails_cfg (field_attrs)) - fields.erase (fields.begin() + i); + if (expander.fails_cfg(field_attrs)) + fields.erase(fields.begin() + i); + else + i++; + } + } + + void expand_tuple_fields(std::vector<AST::TupleField>& fields) { + for (int i = 0; i < fields.size();) { + auto& field_attrs = fields[i].get_outer_attrs(); + expander.expand_cfg_attrs(field_attrs); + if (expander.fails_cfg(field_attrs)) + fields.erase(fields.begin() + i); else i++; } } void expand_function_params(std::vector<AST::FunctionParam>& params) { - for (int i = 0; i < params.size(); ) { - auto& param_attrs = params[i].get_outer_attrs (); + 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); + if (expander.fails_cfg(param_attrs)) + params.erase(params.begin() + i); + else + i++; + } + } + + void visit(AST::Token& tok) override { + // shouldn't require? + } + void visit(AST::DelimTokenTree& delim_tok_tree) override { + // shouldn't require? + } + void visit(AST::AttrInputMetaItemContainer& input) override { + // shouldn't require? + } + void visit(AST::IdentifierExpr& ident_expr) override { + // strip test based on outer attrs + expander.expand_cfg_attrs(ident_expr.get_outer_attrs()); + if (expander.fails_cfg(ident_expr.get_outer_attrs())) { + ident_expr.mark_for_strip(); + return; + } + } + void visit(AST::Lifetime& lifetime) override { + // shouldn't require? + } + void visit(AST::LifetimeParam& lifetime_param) override { + // supposedly does not require - cfg does nothing + } + void visit(AST::MacroInvocationSemi& macro_invoc) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(macro_invoc.get_outer_attrs()); + if (expander.fails_cfg(macro_invoc.get_outer_attrs())) { + macro_invoc.mark_for_strip(); + return; + } + + // I don't think any macro token trees can be stripped in any way + } + + void visit(AST::PathInExpression& path) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(path.get_outer_attrs()); + if (expander.fails_cfg(path.get_outer_attrs())) { + path.mark_for_strip(); + return; + } + } + void visit(AST::TypePathSegment& segment) override { + // shouldn't require? + } + void visit(AST::TypePathSegmentGeneric& segment) override { + // shouldn't require? + } + void visit(AST::TypePathSegmentFunction& segment) override { + // shouldn't require? + } + void visit(AST::TypePath& path) override { + // shouldn't require? + } + void visit(AST::QualifiedPathInExpression& path) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(path.get_outer_attrs()); + if (expander.fails_cfg(path.get_outer_attrs())) { + path.mark_for_strip(); + return; + } + } + void visit(AST::QualifiedPathInType& path) override { + // shouldn't require? + } + + void visit(AST::LiteralExpr& 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::AttrInputLiteral& attr_input) override { + // shouldn't require? + } + void visit(AST::MetaItemLitExpr& meta_item) override { + // shouldn't require? + } + void visit(AST::MetaItemPathLit& meta_item) override { + // shouldn't require? + } + void visit(AST::BorrowExpr& 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 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); + } + void visit(AST::DereferenceExpr& 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 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); + } + void visit(AST::ErrorPropagationExpr& 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 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); + } + void visit(AST::NegationExpr& 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 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); + } + void visit(AST::ArithmeticOrLogicalExpr& 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_left_expr()->accept_vis(*this); + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + 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()); + } + void visit(AST::ComparisonExpr& 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_left_expr()->accept_vis(*this); + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + 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()); + } + void visit(AST::LazyBooleanExpr& 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_left_expr()->accept_vis(*this); + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + 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()); + } + void visit(AST::TypeCastExpr& 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_casted_expr()->accept_vis(*this); + + // ensure that they are not marked for strip + rust_assert(!expr.get_casted_expr()->is_marked_for_strip()); + } + void visit(AST::AssignmentExpr& 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_left_expr()->accept_vis(*this); + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + 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()); + } + void visit(AST::CompoundAssignmentExpr& 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_left_expr()->accept_vis(*this); + /* should syntactically not have outer attributes, though this may + * not have worked in practice */ + 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()); + } + void visit(AST::GroupedExpr& 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 these are inner + * attributes, not outer attributes of inner expr */ + expander.expand_cfg_attrs(expr.get_inner_attrs()); + if (expander.fails_cfg(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. */ + expr.get_expr_in_parens()->accept_vis(*this); + } + void visit(AST::ArrayElemsValues& elems) override { + /* apparently outer attributes are allowed in "elements of array + * expressions" according to spec */ + auto& values = elems.get_values(); + for (int i = 0; i < values.size();) { + auto& value = values[i]; + + // mark for stripping if required + value->accept_vis(*this); + + if (value->is_marked_for_strip()) + values.erase(values.begin() + i); else i++; } } + void visit(AST::ArrayElemsCopied& elems) override { + /* 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 + elems.get_elem_to_copy()->accept_vis(*this); + elems.get_num_copies()->accept_vis(*this); + } + void visit(AST::ArrayExpr& 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 separate + * inner attributes, not just outer attributes of inner exprs */ + expander.expand_cfg_attrs(expr.get_inner_attrs()); + if (expander.fails_cfg(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 */ + if (expr.has_array_elems()) + expr.get_array_elems()->accept_vis(*this); + } + 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 */ - void visit(AST::Token& tok) override {} - void visit(AST::DelimTokenTree& delim_tok_tree) override {} - void visit(AST::AttrInputMetaItemContainer& input) override {} - void visit(AST::IdentifierExpr& ident_expr) override {} - void visit(AST::Lifetime& lifetime) override {} - void visit(AST::LifetimeParam& lifetime_param) override {} - void visit(AST::MacroInvocationSemi& macro) override {} - - void visit(AST::PathInExpression& path) override {} - void visit(AST::TypePathSegment& segment) override {} - void visit(AST::TypePathSegmentGeneric& segment) override {} - void visit(AST::TypePathSegmentFunction& segment) override {} - void visit(AST::TypePath& path) override {} - void visit(AST::QualifiedPathInExpression& path) override {} - void visit(AST::QualifiedPathInType& path) override {} - - void visit(AST::LiteralExpr& expr) override {} - void visit(AST::AttrInputLiteral& attr_input) override {} - void visit(AST::MetaItemLitExpr& meta_item) override {} - void visit(AST::MetaItemPathLit& meta_item) override {} - void visit(AST::BorrowExpr& expr) override {} - void visit(AST::DereferenceExpr& expr) override {} - void visit(AST::ErrorPropagationExpr& expr) override {} - void visit(AST::NegationExpr& expr) override {} - void visit(AST::ArithmeticOrLogicalExpr& expr) override {} - void visit(AST::ComparisonExpr& expr) override {} - void visit(AST::LazyBooleanExpr& expr) override {} - void visit(AST::TypeCastExpr& expr) override {} - void visit(AST::AssignmentExpr& expr) override {} - void visit(AST::CompoundAssignmentExpr& expr) override {} - void visit(AST::GroupedExpr& expr) override {} - void visit(AST::ArrayElemsValues& elems) override {} - void visit(AST::ArrayElemsCopied& elems) override {} - void visit(AST::ArrayExpr& expr) override {} - void visit(AST::ArrayIndexExpr& expr) override {} + /* 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); + } void visit(AST::TupleExpr& expr) override {} void visit(AST::TupleIndexExpr& expr) override {} void visit(AST::StructExprStruct& expr) override {} @@ -117,16 +393,90 @@ namespace Rust { void visit(AST::AwaitExpr& expr) override {} void visit(AST::AsyncBlockExpr& expr) override {} - void visit(AST::TypeParam& param) override {} - void visit(AST::LifetimeWhereClauseItem& item) override {} - void visit(AST::TypeBoundWhereClauseItem& item) override {} - void visit(AST::Method& method) override {} - void visit(AST::ModuleBodied& module) override {} - void visit(AST::ModuleNoBody& module) override {} - void visit(AST::ExternCrate& crate) override {} - void visit(AST::UseTreeGlob& use_tree) override {} - void visit(AST::UseTreeList& use_tree) override {} - void visit(AST::UseTreeRebind& use_tree) override {} + void visit(AST::TypeParam& param) override { + // shouldn't require? + } + void visit(AST::LifetimeWhereClauseItem& item) override { + // shouldn't require? + } + void visit(AST::TypeBoundWhereClauseItem& item) override { + // shouldn't require? + } + void visit(AST::Method& method) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(method.get_outer_attrs()); + if (expander.fails_cfg(method.get_outer_attrs())) { + method.mark_for_strip(); + return; + } + + /* 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. */ + + /* strip method parameters if required - this is specifically + * allowed by spec */ + expand_function_params(method.get_function_params()); + + /* body should always exist - if error state, should have returned + * before now */ + method.get_definition()->accept_vis(*this); + // TODO: can block as a whole be invalidated here? Assuming no + } + void visit(AST::ModuleBodied& module) override { + // strip test based on outer attrs + expander.expand_cfg_attrs(module.get_outer_attrs()); + if (expander.fails_cfg(module.get_outer_attrs())) { + module.mark_for_strip(); + return; + } + + // strip test based on inner attrs + expander.expand_cfg_attrs(module.get_inner_attrs()); + if (expander.fails_cfg(module.get_inner_attrs())) { + module.mark_for_strip(); + return; + } + + // strip items if required + auto& items = module.get_items(); + for (int i = 0; i < items.size();) { + auto& item = items[i]; + + // mark for stripping if required + item->accept_vis(*this); + + if (item->is_marked_for_strip()) + items.erase(items.begin() + i); + else + i++; + } + } + void visit(AST::ModuleNoBody& module) override { + // strip test based on outer attrs + expander.expand_cfg_attrs(module.get_outer_attrs()); + if (expander.fails_cfg(module.get_outer_attrs())) { + module.mark_for_strip(); + return; + } + } + void visit(AST::ExternCrate& crate) override { + // strip test based on outer attrs + expander.expand_cfg_attrs(crate.get_outer_attrs()); + if (expander.fails_cfg(crate.get_outer_attrs())) { + crate.mark_for_strip(); + return; + } + } + void visit(AST::UseTreeGlob& use_tree) override { + // shouldn't require? + } + void visit(AST::UseTreeList& use_tree) override { + // shouldn't require? + } + void visit(AST::UseTreeRebind& use_tree) override { + // shouldn't require? + } void visit(AST::UseDeclaration& use_decl) override { // strip test based on outer attrs expander.expand_cfg_attrs(use_decl.get_outer_attrs()); @@ -135,15 +485,123 @@ namespace Rust { return; } } - void visit(AST::Function& function) override {} - void visit(AST::TypeAlias& type_alias) override {} - void visit(AST::StructStruct& struct_item) override {} - void visit(AST::TupleStruct& tuple_struct) override {} - void visit(AST::EnumItem& item) override {} - void visit(AST::EnumItemTuple& item) override {} - void visit(AST::EnumItemStruct& item) override {} - void visit(AST::EnumItemDiscriminant& item) override {} - void visit(AST::Enum& enum_item) override {} + void visit(AST::Function& function) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(function.get_outer_attrs()); + if (expander.fails_cfg(function.get_outer_attrs())) { + function.mark_for_strip(); + return; + } + + /* strip function parameters if required - this is specifically + * allowed by spec */ + expand_function_params(function.get_function_params()); + + /* body should always exist - if error state, should have returned + * before now */ + function.get_definition()->accept_vis(*this); + // TODO: can block as a whole be invalidated here? Assuming no + } + void visit(AST::TypeAlias& type_alias) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(type_alias.get_outer_attrs()); + if (expander.fails_cfg(type_alias.get_outer_attrs())) { + type_alias.mark_for_strip(); + return; + } + } + void visit(AST::StructStruct& struct_item) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(struct_item.get_outer_attrs()); + if (expander.fails_cfg(struct_item.get_outer_attrs())) { + struct_item.mark_for_strip(); + return; + } + + /* strip struct fields if required - this is presumably + * allowed by spec */ + expand_struct_fields(struct_item.get_fields()); + } + void visit(AST::TupleStruct& tuple_struct) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(tuple_struct.get_outer_attrs()); + if (expander.fails_cfg(tuple_struct.get_outer_attrs())) { + tuple_struct.mark_for_strip(); + return; + } + + /* strip struct fields if required - this is presumably + * allowed by spec */ + expand_tuple_fields(tuple_struct.get_fields()); + } + void visit(AST::EnumItem& item) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(item.get_outer_attrs()); + if (expander.fails_cfg(item.get_outer_attrs())) { + item.mark_for_strip(); + return; + } + } + void visit(AST::EnumItemTuple& item) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(item.get_outer_attrs()); + if (expander.fails_cfg(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 visit(AST::EnumItemStruct& item) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(item.get_outer_attrs()); + if (expander.fails_cfg(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 visit(AST::EnumItemDiscriminant& item) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(item.get_outer_attrs()); + if (expander.fails_cfg(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. */ + item.get_expr()->accept_vis(*this); + } + void visit(AST::Enum& enum_item) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(enum_item.get_outer_attrs()); + if (expander.fails_cfg(enum_item.get_outer_attrs())) { + enum_item.mark_for_strip(); + return; + } + + /* strip enum fields if required - this is presumably + * allowed by spec */ + auto& variants = enum_item.get_variants(); + for (int i = 0; i < variants.size();) { + auto& variant = variants[i]; + + // mark for stripping if required + variant->accept_vis(*this); + + if (variant->is_marked_for_strip()) + variants.erase(variants.begin() + i); + else + i++; + } + } void visit(AST::Union& union_item) override { // initial test based on outer attrs expander.expand_cfg_attrs(union_item.get_outer_attrs()); @@ -151,7 +609,7 @@ namespace Rust { union_item.mark_for_strip(); return; } - + /* strip union fields if required - this is presumably * allowed by spec */ expand_struct_fields(union_item.get_variants()); @@ -163,8 +621,11 @@ namespace Rust { const_item.mark_for_strip(); return; } - /* TODO: is there any way to invalidate the expr? Are attributes - * even allowed on it? */ + + /* strip any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + const_item.get_expr()->accept_vis(*this); } void visit(AST::StaticItem& static_item) override { // initial test based on outer attrs @@ -173,8 +634,11 @@ namespace Rust { static_item.mark_for_strip(); return; } - /* TODO: is there any way to invalidate the expr? Are attributes - * even allowed on it? */ + + /* strip any internal sub-expressions - expression itself isn't + * allowed to have external attributes in this position so can't be + * stripped. */ + static_item.get_expr()->accept_vis(*this); } void visit(AST::TraitItemFunc& item) override { // initial test based on outer attrs @@ -184,7 +648,7 @@ namespace Rust { return; } - /* strip function parameters if required - this is specifically + /* strip function parameters if required - this is specifically * allowed by spec */ expand_function_params(item.get_function_params()); @@ -201,11 +665,11 @@ namespace Rust { return; } - /* assuming you can't strip self param - wouldn't be a method + /* 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. */ - /* strip function parameters if required - this is specifically + /* strip function parameters if required - this is specifically * allowed by spec */ expand_function_params(item.get_function_params()); @@ -221,8 +685,12 @@ namespace Rust { item.mark_for_strip(); return; } - /* TODO: is there any way to invalidate the expr? Are attributes - * even allowed on it? */ + + /* 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()) + item.get_expr()->accept_vis(*this); } void visit(AST::TraitItemType& item) override { // initial test based on outer attrs @@ -249,14 +717,14 @@ namespace Rust { // strip trait items if required auto& trait_items = trait.get_trait_items(); - for (int i = 0; i < trait_items.size(); ) { + for (int i = 0; i < trait_items.size();) { auto& item = trait_items[i]; // mark for stripping if required item->accept_vis(*this); - if (item->is_marked_for_strip ()) - trait_items.erase (trait_items.begin() + i); + if (item->is_marked_for_strip()) + trait_items.erase(trait_items.begin() + i); else i++; } @@ -276,16 +744,16 @@ namespace Rust { return; } - // strip external items if required + // strip inherent impl items if required auto& impl_items = impl.get_impl_items(); - for (int i = 0; i < impl_items.size(); ) { + for (int i = 0; i < impl_items.size();) { auto& item = impl_items[i]; // mark for stripping if required item->accept_vis(*this); - if (item->is_marked_for_strip ()) - impl_items.erase (impl_items.begin() + i); + if (item->is_marked_for_strip()) + impl_items.erase(impl_items.begin() + i); else i++; } @@ -305,16 +773,16 @@ namespace Rust { return; } - // strip external items if required + // strip trait impl items if required auto& impl_items = impl.get_impl_items(); - for (int i = 0; i < impl_items.size(); ) { + for (int i = 0; i < impl_items.size();) { auto& item = impl_items[i]; // mark for stripping if required item->accept_vis(*this); - if (item->is_marked_for_strip ()) - impl_items.erase (impl_items.begin() + i); + if (item->is_marked_for_strip()) + impl_items.erase(impl_items.begin() + i); else i++; } @@ -335,22 +803,22 @@ namespace Rust { return; } - /* strip function parameters if required - this is specifically + /* strip function parameters if required - this is specifically * allowed by spec */ auto& params = item.get_function_params(); - for (int i = 0; i < params.size(); ) { - auto& param_attrs = params[i].get_outer_attrs (); + 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); + if (expander.fails_cfg(param_attrs)) + params.erase(params.begin() + i); else i++; } - /* NOTE: these are extern function params, which may have different - * rules and restrictions to "normal" function params. So expansion + /* 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 + /* TODO: assuming that variadic nature cannot be stripped. If this * is not true, then have code here to do so. */ } void visit(AST::ExternBlock& block) override { @@ -370,14 +838,14 @@ namespace Rust { // strip external items if required auto& extern_items = block.get_extern_items(); - for (int i = 0; i < extern_items.size(); ) { + for (int i = 0; i < extern_items.size();) { auto& item = extern_items[i]; // mark for stripping if required item->accept_vis(*this); - if (item->is_marked_for_strip ()) - extern_items.erase (extern_items.begin() + i); + if (item->is_marked_for_strip()) + extern_items.erase(extern_items.begin() + i); else i++; } @@ -386,8 +854,26 @@ namespace Rust { void visit(AST::MacroMatchFragment& match) override {} void visit(AST::MacroMatchRepetition& match) override {} void visit(AST::MacroMatcher& matcher) override {} - void visit(AST::MacroRulesDefinition& rules_def) override {} - void visit(AST::MacroInvocation& macro_invoc) override {} + void visit(AST::MacroRulesDefinition& rules_def) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(rules_def.get_outer_attrs()); + if (expander.fails_cfg(rules_def.get_outer_attrs())) { + rules_def.mark_for_strip(); + return; + } + + // I don't think any macro rules can be stripped in any way + } + void visit(AST::MacroInvocation& macro_invoc) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(macro_invoc.get_outer_attrs()); + if (expander.fails_cfg(macro_invoc.get_outer_attrs())) { + macro_invoc.mark_for_strip(); + return; + } + + // I don't think any macro token trees can be stripped in any way + } void visit(AST::MetaItemPath& meta_item) override {} void visit(AST::MetaItemSeq& meta_item) override {} void visit(AST::MetaWord& meta_item) override {} @@ -395,6 +881,7 @@ namespace Rust { void visit(AST::MetaListPaths& meta_item) override {} void visit(AST::MetaListNameValueStr& meta_item) override {} + // stripping shouldn't be required or possible for patterns void visit(AST::LiteralPattern& pattern) override {} void visit(AST::IdentifierPattern& pattern) override {} void visit(AST::WildcardPattern& pattern) override {} @@ -416,11 +903,55 @@ namespace Rust { void visit(AST::GroupedPattern& pattern) override {} void visit(AST::SlicePattern& pattern) override {} - void visit(AST::EmptyStmt& stmt) override {} - void visit(AST::LetStmt& stmt) override {} - void visit(AST::ExprStmtWithoutBlock& stmt) override {} - void visit(AST::ExprStmtWithBlock& stmt) override {} + void visit(AST::EmptyStmt& stmt) override { + // assuming no outer attributes, so nothing can happen + } + void visit(AST::LetStmt& stmt) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(stmt.get_outer_attrs()); + if (expander.fails_cfg(stmt.get_outer_attrs())) { + stmt.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 */ + if (stmt.has_init_expr()) + stmt.get_init_expr()->accept_vis(*this); + } + void visit(AST::ExprStmtWithoutBlock& stmt) override { + // 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 visit(AST::ExprStmtWithBlock& stmt) override { + // 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; + } + } + + // stripping shouldn't be required or possible for types void visit(AST::TraitBound& bound) override {} void visit(AST::ImplTraitType& type) override {} void visit(AST::TraitObjectType& type) override {} @@ -515,10 +1046,19 @@ namespace Rust { } // expand module attributes? - // expand attributes recursively + // expand attributes recursively and strip items if required AttrVisitor attr_visitor(*this); - for (auto& i : crate.items) { - i->accept_vis(attr_visitor); + auto& items = crate.items; + for (int i = 0; i < items.size();) { + auto& item = items[i]; + + // mark for stripping if required + item->accept_vis(attr_visitor); + + if (item->is_marked_for_strip()) + items.erase(items.begin() + i); + else + i++; } // TODO: should recursive attribute and macro expansion be done in the same transversal? Or in // separate ones like currently? |