diff options
author | SimplyTheOther <simplytheother@gmail.com> | 2020-10-25 17:04:55 +0800 |
---|---|---|
committer | SimplyTheOther <simplytheother@gmail.com> | 2020-12-08 21:10:16 +0800 |
commit | 98d429466bf783ff1a7ac59bf800061d3e67061a (patch) | |
tree | dfd9923f42bc77371b7e379a70978d0618a4e0ed /gcc | |
parent | eb644945a4f1bcac234a099f904812dcbbafcc93 (diff) | |
download | gcc-98d429466bf783ff1a7ac59bf800061d3e67061a.zip gcc-98d429466bf783ff1a7ac59bf800061d3e67061a.tar.gz gcc-98d429466bf783ff1a7ac59bf800061d3e67061a.tar.bz2 |
Added strip-marking to statements, items and expressions (to allow them to be stripped from their parents)
Fixed compile errors and added more stripping behaviour for extern blocks
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/ast/rust-ast-full-test.cc | 41 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast.h | 98 | ||||
-rw-r--r-- | gcc/rust/ast/rust-expr.h | 1000 | ||||
-rw-r--r-- | gcc/rust/ast/rust-item.h | 319 | ||||
-rw-r--r-- | gcc/rust/ast/rust-macro.h | 44 | ||||
-rw-r--r-- | gcc/rust/ast/rust-path.h | 77 | ||||
-rw-r--r-- | gcc/rust/ast/rust-pattern.h | 21 | ||||
-rw-r--r-- | gcc/rust/ast/rust-stmt.h | 85 | ||||
-rw-r--r-- | gcc/rust/ast/rust-type.h | 98 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 219 | ||||
-rw-r--r-- | gcc/rust/rust-session-manager.cc | 3 |
11 files changed, 1153 insertions, 852 deletions
diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc index e269645..cbeb7d4 100644 --- a/gcc/rust/ast/rust-ast-full-test.cc +++ b/gcc/rust/ast/rust-ast-full-test.cc @@ -192,6 +192,8 @@ Attribute &Attribute::operator= (Attribute const &other) // guard to protect from null pointer dereference if (other.attr_input != nullptr) attr_input = other.attr_input->clone_attr_input (); + else + attr_input = nullptr; return *this; } @@ -323,7 +325,13 @@ std::string VisItem::as_string () const { // FIXME: can't do formatting on string to make identation occur. - std::string str = Item::as_string (); + std::string str; + + if (!outer_attrs.empty ()) + { + for (const auto &attr : outer_attrs) + str += attr.as_string () + "\n"; + } if (has_visibility ()) { @@ -334,7 +342,7 @@ VisItem::as_string () const } // Creates a string that reflects the outer attributes stored. -std::string +/*std::string Item::as_string () const { std::string str; @@ -348,7 +356,7 @@ Item::as_string () const } return str; -} +}*/ std::string Module::as_string () const @@ -1400,8 +1408,14 @@ TypeAlias::as_string () const std::string MacroInvocationSemi::as_string () const { + std::string str; + // get outer attrs - std::string str = MacroItem::as_string (); + if (!outer_attrs.empty ()) + { + for (const auto &attr : outer_attrs) + str += attr.as_string () + "\n"; + } str += "\n" + path.as_string () + "!"; @@ -1498,7 +1512,16 @@ MacroRule::as_string () const std::string MacroRulesDefinition::as_string () const { - std::string str ("macro_rules!"); + std::string str; + + // get outer attrs + if (!outer_attrs.empty ()) + { + for (const auto &attr : outer_attrs) + str += attr.as_string () + "\n"; + } + + str += "macro_rules!"; str += rule_name; @@ -1510,9 +1533,7 @@ MacroRulesDefinition::as_string () const else { for (const auto &rule : rules) - { str += "\n " + rule.as_string (); - } } str += "\n Delim type: "; @@ -5403,9 +5424,9 @@ std::vector<Attribute> Attribute::separate_cfg_attrs () { if (!has_attr_input () || path.as_string () != "cfg_attr") return {}; - // TODO: maybe replace with storing a "has been parsed" variable? - parse_attr_to_meta_item (); - // can't be const because of this anyway + // TODO: maybe replace with storing a "has been parsed" variable? + parse_attr_to_meta_item (); + // can't be const because of this anyway return attr_input->separate_cfg_attrs (); } diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 90e3504..31c547a 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -591,7 +591,7 @@ public: void accept_vis (ASTVisitor &vis) override; bool - check_cfg_predicate (const Session &session ATTRIBUTE_UNUSED) const override + check_cfg_predicate (const Session&) const override { // this should never be called - should be converted first return false; @@ -764,6 +764,9 @@ public: * methods. */ virtual Location get_locus_slow () const { return Location (); } + virtual void mark_for_strip () = 0; + virtual bool is_marked_for_strip () const = 0; + protected: // Clone function implementation as pure virtual method virtual Stmt *clone_stmt_impl () const = 0; @@ -772,10 +775,6 @@ protected: // Rust "item" AST node (declaration of top-level/module-level allowed stuff) class Item : public Stmt { - std::vector<Attribute> outer_attrs; - - // TODO: should outer attrs be defined here or in each derived class? - public: // Unique pointer custom clone function std::unique_ptr<Item> clone_item () const @@ -783,29 +782,22 @@ public: return std::unique_ptr<Item> (clone_item_impl ()); } - std::string as_string () const; + std::string as_string () const = 0; /* Adds crate names to the vector passed by reference, if it can - * (polymorphism). */ + * (polymorphism). TODO: remove, unused. */ virtual void add_crate_name (std::vector<std::string> &names ATTRIBUTE_UNUSED) const {} - virtual void accept_vis (ASTVisitor &vis ATTRIBUTE_UNUSED) {} - protected: - // Constructor - Item (std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) - : outer_attrs (std::move (outer_attribs)) - {} - // Clone function implementation as pure virtual method virtual Item *clone_item_impl () const = 0; /* Save having to specify two clone methods in derived classes by making * statement clone return item clone. Hopefully won't affect performance too * much. */ - Item *clone_stmt_impl () const override { return clone_item_impl (); } + Item *clone_stmt_impl () const final override { return clone_item_impl (); } }; // forward decl of ExprWithoutBlock @@ -849,6 +841,9 @@ public: virtual void accept_vis (ASTVisitor &vis) = 0; + virtual void mark_for_strip () = 0; + virtual bool is_marked_for_strip () const = 0; + protected: // Constructor Expr (std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) @@ -882,7 +877,7 @@ protected: /* Save having to specify two clone methods in derived classes by making expr * clone return exprwithoutblock clone. Hopefully won't affect performance too * much. */ - ExprWithoutBlock *clone_expr_impl () const override + ExprWithoutBlock *clone_expr_impl () const final override { return clone_expr_without_block_impl (); } @@ -935,6 +930,10 @@ public: return std::unique_ptr<IdentifierExpr> (clone_identifier_expr_impl ()); } + // "Error state" if ident is empty, so base stripping on this. + void mark_for_strip () override { ident = {}; } + bool is_marked_for_strip () const override { return ident.empty (); } + protected: // Clone method implementation IdentifierExpr *clone_expr_without_block_impl () const override @@ -946,9 +945,6 @@ protected: { return new IdentifierExpr (*this); } - - IdentifierExpr (IdentifierExpr const &other) = default; - IdentifierExpr &operator= (IdentifierExpr const &other) = default; }; // Pattern base AST node @@ -994,7 +990,7 @@ public: /* HACK: convert to trait bound. Virtual method overriden by classes that * enable this. */ - virtual TraitBound *to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const + virtual TraitBound *to_trait_bound (bool) const { return nullptr; } @@ -1025,7 +1021,7 @@ protected: /* Save having to specify two clone methods in derived classes by making type * clone return typenobounds clone. Hopefully won't affect performance too * much. */ - TypeNoBounds *clone_type_impl () const override + TypeNoBounds *clone_type_impl () const final override { return clone_type_no_bounds_impl (); } @@ -1207,10 +1203,12 @@ class MacroItem : public Item { /*public: std::string as_string() const;*/ + //std::vector<Attribute> outer_attrs; + protected: - MacroItem (std::vector<Attribute> outer_attribs) - : Item (std::move (outer_attribs)) - {} + /*MacroItem (std::vector<Attribute> outer_attribs) + : outer_attrs (std::move (outer_attribs)) + {}*/ }; // Item used in trait declarations - abstract base class @@ -1298,6 +1296,7 @@ class MacroInvocationSemi : public MacroItem, public InherentImplItem, public TraitImplItem { + std::vector<Attribute> outer_attrs; SimplePath path; // all delim types except curly must have invocation end with a semicolon DelimType delim_type; @@ -1310,36 +1309,15 @@ public: MacroInvocationSemi (SimplePath macro_path, DelimType delim_type, std::vector<std::unique_ptr<TokenTree>> token_trees, std::vector<Attribute> outer_attribs, Location locus) - : MacroItem (std::move (outer_attribs)), path (std::move (macro_path)), + : outer_attrs (std::move (outer_attribs)), path (std::move (macro_path)), delim_type (delim_type), token_trees (std::move (token_trees)), locus (locus) {} - /* TODO: possible issue with Item and TraitItem hierarchies both having outer - * attributes - * - storage inefficiency at least. - * Best current idea is to make Item preferred and have TraitItem get virtual - * functions for attributes or something. Or just redo the "composition" - * approach, but then this prevents polymorphism and would entail redoing - * quite a bit of the parser. */ - - // Move constructors - MacroInvocationSemi (MacroInvocationSemi &&other) = default; - MacroInvocationSemi &operator= (MacroInvocationSemi &&other) = default; - - void accept_vis (ASTVisitor &vis) override; - - // Clones this macro invocation semi. - std::unique_ptr<MacroInvocationSemi> clone_macro_invocation_semi () const - { - return std::unique_ptr<MacroInvocationSemi> ( - clone_macro_invocation_semi_impl ()); - } -protected: // Copy constructor with vector clone MacroInvocationSemi (MacroInvocationSemi const &other) : MacroItem (other), TraitItem (other), InherentImplItem (other), - TraitImplItem (other), path (other.path), delim_type (other.delim_type), + TraitImplItem (other), outer_attrs(other.outer_attrs), path (other.path), delim_type (other.delim_type), locus (other.locus) { token_trees.reserve (other.token_trees.size ()); @@ -1354,6 +1332,7 @@ protected: TraitItem::operator= (other); InherentImplItem::operator= (other); TraitImplItem::operator= (other); + outer_attrs = other.outer_attrs; path = other.path; delim_type = other.delim_type; locus = other.locus; @@ -1365,6 +1344,24 @@ protected: return *this; } + // Move constructors + MacroInvocationSemi (MacroInvocationSemi &&other) = default; + MacroInvocationSemi &operator= (MacroInvocationSemi &&other) = default; + + void accept_vis (ASTVisitor &vis) override; + + // Clones this macro invocation semi. + std::unique_ptr<MacroInvocationSemi> clone_macro_invocation_semi () const + { + return std::unique_ptr<MacroInvocationSemi> ( + clone_macro_invocation_semi_impl ()); + } + + // Invalid if path is empty, so base stripping on that. + void mark_for_strip () override { path = SimplePath::create_empty (); } + bool is_marked_for_strip () const override { return path.is_empty (); } + +protected: MacroInvocationSemi *clone_macro_invocation_semi_impl () const { return new MacroInvocationSemi (*this); @@ -1391,13 +1388,6 @@ protected: return clone_macro_invocation_semi_impl (); } - // FIXME: remove if item impl virtual override works properly - // Use covariance to implement clone function as returning this object rather - // than base - /*MacroInvocationSemi* clone_statement_impl() const override { - return clone_macro_invocation_semi_impl (); - }*/ - /* Use covariance to implement clone function as returning this object rather * than base */ MacroInvocationSemi *clone_trait_item_impl () const override diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index fd6913f..4647829 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -23,7 +23,7 @@ protected: virtual ExprWithBlock *clone_expr_with_block_impl () const = 0; // prevent having to define multiple clone expressions - ExprWithBlock *clone_expr_impl () const override + ExprWithBlock *clone_expr_impl () const final override { return clone_expr_with_block_impl (); } @@ -73,19 +73,16 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - LiteralExpr *clone_expr_impl () const override - { - return new LiteralExpr (*this); - } + // Invalid if literal is in error state, so base stripping on that. + void mark_for_strip () override { literal = Literal::create_error (); } + bool is_marked_for_strip () const override { return literal.is_error (); } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ LiteralExpr *clone_expr_without_block_impl () const override { - return new LiteralExpr (*this); + return clone_literal_expr_impl (); } /* not virtual as currently no subclasses of LiteralExpr, but could be in @@ -121,7 +118,7 @@ public: /* this can never be a cfg predicate - cfg and cfg_attr require a token-tree * cfg */ bool - check_cfg_predicate (const Session &session ATTRIBUTE_UNUSED) const override + check_cfg_predicate (const Session&) const override { return false; } @@ -212,18 +209,26 @@ protected: // Copy constructor (only for initialisation of expr purposes) OperatorExpr (OperatorExpr const &other) - : ExprWithoutBlock (other), locus (other.locus), - main_or_left_expr (other.main_or_left_expr->clone_expr ()) - {} + : ExprWithoutBlock (other), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.main_or_left_expr != nullptr) + main_or_left_expr = other.main_or_left_expr->clone_expr (); + } // Overload assignment operator to deep copy expr OperatorExpr &operator= (OperatorExpr const &other) { ExprWithoutBlock::operator= (other); - main_or_left_expr = other.main_or_left_expr->clone_expr (); locus = other.locus; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.main_or_left_expr != nullptr) + main_or_left_expr = other.main_or_left_expr->clone_expr (); + else + main_or_left_expr = nullptr; + return *this; } @@ -234,6 +239,10 @@ protected: public: Location get_locus () const { return locus; } Location get_locus_slow () const override { return get_locus (); } + + // Invalid if expr is null, so base stripping on that. + void mark_for_strip () override { main_or_left_expr = nullptr; } + bool is_marked_for_strip () const override { return main_or_left_expr == nullptr; } }; /* Unary prefix & or &mut (or && and &&mut) borrow operator. Cannot be @@ -249,9 +258,8 @@ public: BorrowExpr (std::unique_ptr<Expr> borrow_lvalue, bool is_mut_borrow, bool is_double_borrow, std::vector<Attribute> outer_attribs, Location locus) - : OperatorExpr (std::move (borrow_lvalue), std::move (outer_attribs), - locus), - is_mut (is_mut_borrow), double_borrow (is_double_borrow) + : OperatorExpr (std::move (borrow_lvalue), std::move (outer_attribs), + locus), is_mut (is_mut_borrow), double_borrow (is_double_borrow) {} void accept_vis (ASTVisitor &vis) override; @@ -259,13 +267,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - BorrowExpr *clone_expr_impl () const override - { - return new BorrowExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ BorrowExpr *clone_expr_without_block_impl () const override { return new BorrowExpr (*this); @@ -289,13 +290,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - DereferenceExpr *clone_expr_impl () const override - { - return new DereferenceExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ DereferenceExpr *clone_expr_without_block_impl () const override { return new DereferenceExpr (*this); @@ -320,13 +314,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - ErrorPropagationExpr *clone_expr_impl () const override - { - return new ErrorPropagationExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ ErrorPropagationExpr *clone_expr_without_block_impl () const override { return new ErrorPropagationExpr (*this); @@ -368,13 +355,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - NegationExpr *clone_expr_impl () const override - { - return new NegationExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ NegationExpr *clone_expr_without_block_impl () const override { return new NegationExpr (*this); @@ -450,13 +430,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - ArithmeticOrLogicalExpr *clone_expr_impl () const override - { - return new ArithmeticOrLogicalExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ ArithmeticOrLogicalExpr *clone_expr_without_block_impl () const override { return new ArithmeticOrLogicalExpr (*this); @@ -527,13 +500,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - ComparisonExpr *clone_expr_impl () const override - { - return new ComparisonExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ ComparisonExpr *clone_expr_without_block_impl () const override { return new ComparisonExpr (*this); @@ -597,13 +563,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - LazyBooleanExpr *clone_expr_impl () const override - { - return new LazyBooleanExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ LazyBooleanExpr *clone_expr_without_block_impl () const override { return new LazyBooleanExpr (*this); @@ -652,13 +611,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TypeCastExpr *clone_expr_impl () const override - { - return new TypeCastExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ TypeCastExpr *clone_expr_without_block_impl () const override { return new TypeCastExpr (*this); @@ -712,13 +664,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - AssignmentExpr *clone_expr_impl () const override - { - return new AssignmentExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ AssignmentExpr *clone_expr_without_block_impl () const override { return new AssignmentExpr (*this); @@ -791,13 +736,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - CompoundAssignmentExpr *clone_expr_impl () const override - { - return new CompoundAssignmentExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ CompoundAssignmentExpr *clone_expr_without_block_impl () const override { return new CompoundAssignmentExpr (*this); @@ -828,18 +766,27 @@ public: // Copy constructor includes clone for expr_in_parens GroupedExpr (GroupedExpr const &other) : ExprWithoutBlock (other), inner_attrs (other.inner_attrs), - expr_in_parens (other.expr_in_parens->clone_expr ()), locus (other.locus) - {} + locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.expr_in_parens != nullptr) + expr_in_parens = other.expr_in_parens->clone_expr (); + } // Overloaded assignment operator to clone expr_in_parens GroupedExpr &operator= (GroupedExpr const &other) { ExprWithoutBlock::operator= (other); inner_attrs = other.inner_attrs; - expr_in_parens = other.expr_in_parens->clone_expr (); locus = other.locus; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.expr_in_parens != nullptr) + expr_in_parens = other.expr_in_parens->clone_expr (); + else + expr_in_parens = nullptr; + return *this; } @@ -852,14 +799,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - GroupedExpr *clone_expr_impl () const override - { - return new GroupedExpr (*this); - } + // Invalid if inner expr is null, so base stripping on that. + void mark_for_strip () override { expr_in_parens = nullptr; } + bool is_marked_for_strip () const override { return expr_in_parens == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ GroupedExpr *clone_expr_without_block_impl () const override @@ -988,6 +932,9 @@ class ArrayExpr : public ExprWithoutBlock std::unique_ptr<ArrayElems> internal_elements; Location locus; + + // TODO: find another way to store this to save memory? + bool marked_for_strip = false; public: std::string as_string () const override; @@ -1009,7 +956,7 @@ public: // Copy constructor requires cloning ArrayElems for polymorphism to hold ArrayExpr (ArrayExpr const &other) : ExprWithoutBlock (other), inner_attrs (other.inner_attrs), - locus (other.locus) + locus (other.locus), marked_for_strip (other.marked_for_strip) { if (other.has_array_elems ()) internal_elements = other.internal_elements->clone_array_elems (); @@ -1020,11 +967,15 @@ public: { ExprWithoutBlock::operator= (other); inner_attrs = other.inner_attrs; - if (other.has_array_elems ()) - internal_elements = other.internal_elements->clone_array_elems (); locus = other.locus; + marked_for_strip = other.marked_for_strip; // outer_attrs = other.outer_attrs; + if (other.has_array_elems ()) + internal_elements = other.internal_elements->clone_array_elems (); + else + internal_elements = nullptr; + return *this; } @@ -1037,11 +988,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - ArrayExpr *clone_expr_impl () const override { return new ArrayExpr (*this); } + // Can't think of any invalid invariants, so store boolean. + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ ArrayExpr *clone_expr_without_block_impl () const override @@ -1075,19 +1026,32 @@ public: // Copy constructor requires special cloning due to unique_ptr ArrayIndexExpr (ArrayIndexExpr const &other) - : ExprWithoutBlock (other), array_expr (other.array_expr->clone_expr ()), - index_expr (other.index_expr->clone_expr ()), locus (other.locus) - {} + : ExprWithoutBlock (other), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.array_expr != nullptr) + array_expr = other.array_expr->clone_expr (); + if (other.index_expr != nullptr) + index_expr = other.index_expr->clone_expr (); + } // Overload assignment operator to clone unique_ptrs ArrayIndexExpr &operator= (ArrayIndexExpr const &other) { ExprWithoutBlock::operator= (other); - array_expr = other.array_expr->clone_expr (); - index_expr = other.index_expr->clone_expr (); // outer_attrs = other.outer_attrs; locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.array_expr != nullptr) + array_expr = other.array_expr->clone_expr (); + else + array_expr = nullptr; + if (other.index_expr != nullptr) + index_expr = other.index_expr->clone_expr (); + else + index_expr = nullptr; + return *this; } @@ -1100,14 +1064,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - ArrayIndexExpr *clone_expr_impl () const override - { - return new ArrayIndexExpr (*this); - } + // Invalid if either expr is null, so base stripping on that. + 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; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ ArrayIndexExpr *clone_expr_without_block_impl () const override @@ -1126,6 +1087,9 @@ class TupleExpr : public ExprWithoutBlock Location locus; + // TODO: find another way to store this to save memory? + bool marked_for_strip = false; + public: std::string as_string () const override; @@ -1142,7 +1106,7 @@ public: // copy constructor with vector clone TupleExpr (TupleExpr const &other) : ExprWithoutBlock (other), inner_attrs (other.inner_attrs), - locus (other.locus) + locus (other.locus), marked_for_strip (other.marked_for_strip) { tuple_elems.reserve (other.tuple_elems.size ()); for (const auto &e : other.tuple_elems) @@ -1155,6 +1119,7 @@ public: ExprWithoutBlock::operator= (other); inner_attrs = other.inner_attrs; locus = other.locus; + marked_for_strip = other.marked_for_strip; tuple_elems.reserve (other.tuple_elems.size ()); for (const auto &e : other.tuple_elems) @@ -1175,11 +1140,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - TupleExpr *clone_expr_impl () const override { return new TupleExpr (*this); } + // Can't think of any invalid invariants, so store boolean. + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ TupleExpr *clone_expr_without_block_impl () const override @@ -1213,19 +1178,27 @@ public: // Copy constructor requires a clone for tuple_expr TupleIndexExpr (TupleIndexExpr const &other) - : ExprWithoutBlock (other), tuple_expr (other.tuple_expr->clone_expr ()), - tuple_index (other.tuple_index), locus (other.locus) - {} + : ExprWithoutBlock (other), tuple_index (other.tuple_index), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.tuple_expr != nullptr) + tuple_expr = other.tuple_expr->clone_expr (); + } // Overload assignment operator in order to clone TupleIndexExpr &operator= (TupleIndexExpr const &other) { ExprWithoutBlock::operator= (other); - tuple_expr = other.tuple_expr->clone_expr (); tuple_index = other.tuple_index; locus = other.locus; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.tuple_expr != nullptr) + tuple_expr = other.tuple_expr->clone_expr (); + else + tuple_expr = nullptr; + return *this; } @@ -1238,14 +1211,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - TupleIndexExpr *clone_expr_impl () const override - { - return new TupleIndexExpr (*this); - } + // Invalid if tuple expr is null, so base stripping on that. + void mark_for_strip () override { tuple_expr = nullptr; } + bool is_marked_for_strip () const override { return tuple_expr == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ TupleIndexExpr *clone_expr_without_block_impl () const override @@ -1271,6 +1241,10 @@ public: const PathInExpression &get_struct_name () const { return struct_name; } std::string as_string () const override; + + // Invalid if path is empty, so base stripping on that. + void mark_for_strip () override { struct_name = PathInExpression::create_error (); } + bool is_marked_for_strip () const override { return struct_name.is_error (); } }; // Actual AST node of the struct creator (with no fields). Not abstract! @@ -1301,13 +1275,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - StructExprStruct *clone_expr_impl () const override - { - return new StructExprStruct (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ StructExprStruct *clone_expr_without_block_impl () const override { return new StructExprStruct (*this); @@ -1332,7 +1299,7 @@ public: /* HACK: gets around base_struct pointer being null (e.g. if no struct base * exists) */ if (other.base_struct != nullptr) - other.base_struct->clone_expr (); + base_struct = other.base_struct->clone_expr (); } // Destructor @@ -1341,7 +1308,11 @@ public: // Overload assignment operator to clone base_struct StructBase &operator= (StructBase const &other) { - base_struct = other.base_struct->clone_expr (); + // prevent null pointer dereference + if (other.base_struct != nullptr) + base_struct = other.base_struct->clone_expr (); + else + base_struct = nullptr; return *this; } @@ -1557,13 +1528,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - StructExprStructFields *clone_expr_impl () const override - { - return new StructExprStructFields (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ StructExprStructFields *clone_expr_without_block_impl () const override { return new StructExprStructFields (*this); @@ -1595,13 +1559,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - StructExprStructBase *clone_expr_impl () const override - { - return new StructExprStructBase (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ StructExprStructBase *clone_expr_without_block_impl () const override { return new StructExprStructBase (*this); @@ -1669,13 +1626,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - StructExprTuple *clone_expr_impl () const override - { - return new StructExprTuple (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ StructExprTuple *clone_expr_without_block_impl () const override { return new StructExprTuple (*this); @@ -1708,13 +1658,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - StructExprUnit *clone_expr_impl () const override - { - return new StructExprUnit (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ StructExprUnit *clone_expr_without_block_impl () const override { return new StructExprUnit (*this); @@ -1738,6 +1681,10 @@ protected: public: // TODO: maybe remove and have string version gotten here directly PathInExpression get_enum_variant_path () const { return enum_variant_path; } + + // Invalid if path is in error state, so base stripping on that. + void mark_for_strip () override { enum_variant_path = PathInExpression::create_error (); } + bool is_marked_for_strip () const override { return enum_variant_path.is_error (); } }; /* Base AST node for a single enum expression field (in enum instance creation) @@ -1828,9 +1775,6 @@ public: field_name (std::move (field_name)) {} - // copy constructor, destructor, and assignment operator should not need - // defining - void accept_vis (ASTVisitor &vis) override; protected: @@ -1924,13 +1868,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - EnumExprStruct *clone_expr_impl () const override - { - return new EnumExprStruct (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ EnumExprStruct *clone_expr_without_block_impl () const override { return new EnumExprStruct (*this); @@ -1993,13 +1930,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - EnumExprTuple *clone_expr_impl () const override - { - return new EnumExprTuple (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ EnumExprTuple *clone_expr_without_block_impl () const override { return new EnumExprTuple (*this); @@ -2033,13 +1963,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - EnumExprFieldless *clone_expr_impl () const override - { - return new EnumExprFieldless (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ EnumExprFieldless *clone_expr_without_block_impl () const override { return new EnumExprFieldless (*this); @@ -2077,9 +2000,11 @@ public: // copy constructor requires clone CallExpr (CallExpr const &other) - : ExprWithoutBlock (other), function (other.function->clone_expr ()), - locus (other.locus) - /*, params(other.params),*/ { + : ExprWithoutBlock (other), locus (other.locus) { + // guard to prevent null dereference (only required if error state) + if (other.function != nullptr) + function = other.function->clone_expr (); + params.reserve (other.params.size ()); for (const auto &e : other.params) params.push_back (e->clone_expr ()); @@ -2089,11 +2014,15 @@ public: CallExpr &operator= (CallExpr const &other) { ExprWithoutBlock::operator= (other); - function = other.function->clone_expr (); locus = other.locus; - // params = other.params; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.function != nullptr) + function = other.function->clone_expr (); + else + function = nullptr; + params.reserve (other.params.size ()); for (const auto &e : other.params) params.push_back (e->clone_expr ()); @@ -2113,11 +2042,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - CallExpr *clone_expr_impl () const override { return new CallExpr (*this); } + // Invalid if function expr is null, so base stripping on that. + void mark_for_strip () override { function = nullptr; } + bool is_marked_for_strip () const override { return function == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ CallExpr *clone_expr_without_block_impl () const override @@ -2155,9 +2084,11 @@ public: // copy constructor required due to cloning MethodCallExpr (MethodCallExpr const &other) - : ExprWithoutBlock (other), receiver (other.receiver->clone_expr ()), - method_name (other.method_name), locus (other.locus) - /*, params(other.params),*/ { + : ExprWithoutBlock (other), method_name (other.method_name), locus (other.locus) { + // guard to prevent null dereference (only required if error state) + if (other.receiver != nullptr) + receiver = other.receiver->clone_expr (); + params.reserve (other.params.size ()); for (const auto &e : other.params) params.push_back (e->clone_expr ()); @@ -2167,12 +2098,16 @@ public: MethodCallExpr &operator= (MethodCallExpr const &other) { ExprWithoutBlock::operator= (other); - receiver = other.receiver->clone_expr (); method_name = other.method_name; locus = other.locus; - // params = other.params; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.receiver != nullptr) + receiver = other.receiver->clone_expr (); + else + receiver = nullptr; + params.reserve (other.params.size ()); for (const auto &e : other.params) params.push_back (e->clone_expr ()); @@ -2189,14 +2124,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - MethodCallExpr *clone_expr_impl () const override - { - return new MethodCallExpr (*this); - } + // Invalid if receiver expr is null, so base stripping on that. + void mark_for_strip () override { receiver = nullptr; } + bool is_marked_for_strip () const override { return receiver == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ MethodCallExpr *clone_expr_without_block_impl () const override @@ -2227,19 +2159,27 @@ public: // Copy constructor required due to unique_ptr cloning FieldAccessExpr (FieldAccessExpr const &other) - : ExprWithoutBlock (other), receiver (other.receiver->clone_expr ()), - field (other.field), locus (other.locus) - {} + : ExprWithoutBlock (other), field (other.field), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.receiver != nullptr) + receiver = other.receiver->clone_expr (); + } // Overload assignment operator to clone unique_ptr FieldAccessExpr &operator= (FieldAccessExpr const &other) { ExprWithoutBlock::operator= (other); - receiver = other.receiver->clone_expr (); field = other.field; locus = other.locus; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.receiver != nullptr) + receiver = other.receiver->clone_expr (); + else + receiver = nullptr; + return *this; } @@ -2252,14 +2192,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - FieldAccessExpr *clone_expr_impl () const override - { - return new FieldAccessExpr (*this); - } + // Invalid if receiver expr is null, so base stripping on that. + void mark_for_strip () override { receiver = nullptr; } + bool is_marked_for_strip () const override { return receiver == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ FieldAccessExpr *clone_expr_without_block_impl () const override @@ -2294,6 +2231,8 @@ public: : pattern (other.pattern->clone_pattern ()) { // guard to protect from null pointer dereference + if (other.pattern != nullptr) + pattern = other.pattern->clone_pattern (); if (other.type != nullptr) type = other.type->clone_type (); } @@ -2303,8 +2242,15 @@ public: // Assignment operator must be overloaded to clone as well ClosureParam &operator= (ClosureParam const &other) { - pattern = other.pattern->clone_pattern (); - type = other.type->clone_type (); + // guard to protect from null pointer dereference + if (other.pattern != nullptr) + pattern = other.pattern->clone_pattern (); + else + pattern = nullptr; + if (other.type != nullptr) + type = other.type->clone_type (); + else + type = nullptr; return *this; } @@ -2367,18 +2313,27 @@ public: // Copy constructor must be defined to allow copying via cloning of unique_ptr ClosureExprInner (ClosureExprInner const &other) - : ClosureExpr (other), closure_inner (other.closure_inner->clone_expr ()) - {} + : ClosureExpr (other) + { + // guard to prevent null dereference (only required if error state) + if (other.closure_inner != nullptr) + closure_inner = other.closure_inner->clone_expr (); + } // Overload assignment operator to clone closure_inner ClosureExprInner &operator= (ClosureExprInner const &other) { ClosureExpr::operator= (other); - closure_inner = other.closure_inner->clone_expr (); // params = other.params; // has_move = other.has_move; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.closure_inner != nullptr) + closure_inner = other.closure_inner->clone_expr (); + else + closure_inner = nullptr; + return *this; } @@ -2388,14 +2343,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - ClosureExprInner *clone_expr_impl () const override - { - return new ClosureExprInner (*this); - } + // Invalid if inner expr is null, so base stripping on that. + void mark_for_strip () override { closure_inner = nullptr; } + bool is_marked_for_strip () const override { return closure_inner == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ ClosureExprInner *clone_expr_without_block_impl () const override @@ -2437,8 +2389,7 @@ public: // Copy constructor with clone BlockExpr (BlockExpr const &other) - : ExprWithBlock (other), /*statements(other.statements),*/ - inner_attrs (other.inner_attrs), locus (other.locus) + : ExprWithBlock (other), inner_attrs (other.inner_attrs), locus (other.locus) { // guard to protect from null pointer dereference if (other.expr != nullptr) @@ -2453,12 +2404,16 @@ public: BlockExpr &operator= (BlockExpr const &other) { ExprWithBlock::operator= (other); - // statements = other.statements; - expr = other.expr->clone_expr_without_block (); inner_attrs = other.inner_attrs; locus = other.locus; // outer_attrs = other.outer_attrs; + // guard to protect from null pointer dereference + if (other.expr != nullptr) + expr = other.expr->clone_expr_without_block (); + else + expr = nullptr; + statements.reserve (other.statements.size ()); for (const auto &e : other.statements) statements.push_back (e->clone_stmt ()); @@ -2481,14 +2436,16 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - BlockExpr *clone_expr_impl () const override - { - return clone_block_expr_impl (); + // Invalid if has no statements or final expr, so base stripping on that. + void mark_for_strip () override + { + expr = nullptr; + statements.clear (); + statements.shrink_to_fit (); } + bool is_marked_for_strip () const override { return expr == nullptr && statements.empty (); } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ BlockExpr *clone_expr_with_block_impl () const override @@ -2507,6 +2464,7 @@ protected: // Represents a type-specified closure expression AST node class ClosureExprInnerTyped : public ClosureExpr { + // TODO: spec says typenobounds std::unique_ptr<Type> return_type; std::unique_ptr<BlockExpr> expr; // only used because may be polymorphic in future @@ -2529,20 +2487,33 @@ public: // Copy constructor requires cloning ClosureExprInnerTyped (ClosureExprInnerTyped const &other) - : ClosureExpr (other), return_type (other.return_type->clone_type ()), - expr (other.expr->clone_block_expr ()) - {} + : ClosureExpr (other) + { + // guard to prevent null dereference (only required if error state) + if (other.expr != nullptr) + expr = other.expr->clone_block_expr (); + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + } // Overload assignment operator to clone unique_ptrs ClosureExprInnerTyped &operator= (ClosureExprInnerTyped const &other) { ClosureExpr::operator= (other); - return_type = other.return_type->clone_type (); - expr = other.expr->clone_block_expr (); // params = other.params; // has_move = other.has_move; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.expr != nullptr) + expr = other.expr->clone_block_expr (); + else + expr = nullptr; + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + else + return_type = nullptr; + return *this; } @@ -2552,14 +2523,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - ClosureExprInnerTyped *clone_expr_impl () const override - { - return new ClosureExprInnerTyped (*this); - } + /* 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; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ ClosureExprInnerTyped *clone_expr_without_block_impl () const override @@ -2575,6 +2543,9 @@ class ContinueExpr : public ExprWithoutBlock Lifetime label; Location locus; + // TODO: find another way to store this to save memory? + bool marked_for_strip = false; + public: std::string as_string () const override; @@ -2594,14 +2565,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - ContinueExpr *clone_expr_impl () const override - { - return new ContinueExpr (*this); - } + // Can't think of any invalid invariants, so store boolean. + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ ContinueExpr *clone_expr_without_block_impl () const override @@ -2622,6 +2590,9 @@ class BreakExpr : public ExprWithoutBlock Location locus; + // TODO: find another way to store this to save memory? + bool marked_for_strip = false; + public: std::string as_string () const override; @@ -2643,7 +2614,7 @@ public: // Copy constructor defined to use clone for unique pointer BreakExpr (BreakExpr const &other) - : ExprWithoutBlock (other), label (other.label), locus (other.locus) + : ExprWithoutBlock (other), label (other.label), locus (other.locus), marked_for_strip (other.marked_for_strip) { // guard to protect from null pointer dereference if (other.break_expr != nullptr) @@ -2655,10 +2626,16 @@ public: { ExprWithoutBlock::operator= (other); label = other.label; - break_expr = other.break_expr->clone_expr (); locus = other.locus; + marked_for_strip = other.marked_for_strip; // outer_attrs = other.outer_attrs; + // guard to protect from null pointer dereference + if (other.break_expr != nullptr) + break_expr = other.break_expr->clone_expr (); + else + break_expr = nullptr; + return *this; } @@ -2671,11 +2648,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - BreakExpr *clone_expr_impl () const override { return new BreakExpr (*this); } + // Can't think of any invalid invariants, so store boolean. + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ BreakExpr *clone_expr_without_block_impl () const override @@ -2718,16 +2695,29 @@ public: // Copy constructor with cloning RangeFromToExpr (RangeFromToExpr const &other) - : RangeExpr (other), from (other.from->clone_expr ()), - to (other.to->clone_expr ()) - {} + : RangeExpr (other) + { + // guard to prevent null dereference (only required if error state) + if (other.from != nullptr) + from = other.from->clone_expr (); + if (other.to != nullptr) + to = other.to->clone_expr (); + } // Overload assignment operator to clone unique pointers RangeFromToExpr &operator= (RangeFromToExpr const &other) { RangeExpr::operator= (other); - from = other.from->clone_expr (); - to = other.to->clone_expr (); + + // guard to prevent null dereference (only required if error state) + if (other.from != nullptr) + from = other.from->clone_expr (); + else + from = nullptr; + if (other.to != nullptr) + to = other.to->clone_expr (); + else + to = nullptr; return *this; } @@ -2738,14 +2728,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - RangeFromToExpr *clone_expr_impl () const override - { - return new RangeFromToExpr (*this); - } + // Invalid if either expr is null, so base stripping on that. + void mark_for_strip () override { from = nullptr; to = nullptr; } + bool is_marked_for_strip () const override { return from == nullptr && to == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ RangeFromToExpr *clone_expr_without_block_impl () const override @@ -2769,14 +2756,23 @@ public: // Copy constructor with clone RangeFromExpr (RangeFromExpr const &other) - : RangeExpr (other), from (other.from->clone_expr ()) - {} + : RangeExpr (other) + { + // guard to prevent null dereference (only required if error state) + if (other.from != nullptr) + from = other.from->clone_expr (); + } // Overload assignment operator to clone unique_ptr RangeFromExpr &operator= (RangeFromExpr const &other) { RangeExpr::operator= (other); - from = other.from->clone_expr (); + + // guard to prevent null dereference (only required if error state) + if (other.from != nullptr) + from = other.from->clone_expr (); + else + from = nullptr; return *this; } @@ -2787,14 +2783,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - RangeFromExpr *clone_expr_impl () const override - { - return new RangeFromExpr (*this); - } + // Invalid if expr is null, so base stripping on that. + void mark_for_strip () override { from = nullptr; } + bool is_marked_for_strip () const override { return from == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ RangeFromExpr *clone_expr_without_block_impl () const override @@ -2819,14 +2812,23 @@ public: // Copy constructor with clone RangeToExpr (RangeToExpr const &other) - : RangeExpr (other), to (other.to->clone_expr ()) - {} + : RangeExpr (other) + { + // guard to prevent null dereference (only required if error state) + if (other.to != nullptr) + to = other.to->clone_expr (); + } // Overload assignment operator to clone unique_ptr RangeToExpr &operator= (RangeToExpr const &other) { RangeExpr::operator= (other); - to = other.to->clone_expr (); + + // guard to prevent null dereference (only required if error state) + if (other.to != nullptr) + to = other.to->clone_expr (); + else + to = nullptr; return *this; } @@ -2837,14 +2839,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - RangeToExpr *clone_expr_impl () const override - { - return new RangeToExpr (*this); - } + // Invalid if expr is null, so base stripping on that. + void mark_for_strip () override { to = nullptr; } + bool is_marked_for_strip () const override { return to == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ RangeToExpr *clone_expr_without_block_impl () const override @@ -2857,6 +2856,9 @@ protected: // constructs a std::ops::RangeFull object class RangeFullExpr : public RangeExpr { + // TODO: find another way to store this to save memory? + bool marked_for_strip = false; + public: std::string as_string () const override; @@ -2865,14 +2867,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - RangeFullExpr *clone_expr_impl () const override - { - return new RangeFullExpr (*this); - } + // Can't think of any invalid invariants, so store boolean. + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ RangeFullExpr *clone_expr_without_block_impl () const override @@ -2900,16 +2899,29 @@ public: // Copy constructor with clone RangeFromToInclExpr (RangeFromToInclExpr const &other) - : RangeExpr (other), from (other.from->clone_expr ()), - to (other.to->clone_expr ()) - {} + : RangeExpr (other) + { + // guard to prevent null dereference (only required if error state) + if (other.from != nullptr) + from = other.from->clone_expr (); + if (other.to != nullptr) + to = other.to->clone_expr (); + } // Overload assignment operator to use clone RangeFromToInclExpr &operator= (RangeFromToInclExpr const &other) { RangeExpr::operator= (other); - from = other.from->clone_expr (); - to = other.to->clone_expr (); + + // guard to prevent null dereference (only required if error state) + if (other.from != nullptr) + from = other.from->clone_expr (); + else + from = nullptr; + if (other.to != nullptr) + to = other.to->clone_expr (); + else + to = nullptr; return *this; } @@ -2920,14 +2932,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - RangeFromToInclExpr *clone_expr_impl () const override - { - return new RangeFromToInclExpr (*this); - } + // Invalid if either expr is null, so base stripping on that. + void mark_for_strip () override { from = nullptr; to = nullptr; } + bool is_marked_for_strip () const override { return from == nullptr && to == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ RangeFromToInclExpr *clone_expr_without_block_impl () const override @@ -2952,14 +2961,23 @@ public: // Copy constructor with clone RangeToInclExpr (RangeToInclExpr const &other) - : RangeExpr (other), to (other.to->clone_expr ()) - {} + : RangeExpr (other) + { + // guard to prevent null dereference (only required if error state) + if (other.to != nullptr) + to = other.to->clone_expr (); + } // Overload assignment operator to clone pointer RangeToInclExpr &operator= (RangeToInclExpr const &other) { RangeExpr::operator= (other); - to = other.to->clone_expr (); + + // guard to prevent null dereference (only required if error state) + if (other.to != nullptr) + to = other.to->clone_expr (); + else + to = nullptr; return *this; } @@ -2970,14 +2988,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - RangeToInclExpr *clone_expr_impl () const override - { - return new RangeToInclExpr (*this); - } + // Invalid if expr is null, so base stripping on that. + void mark_for_strip () override { to = nullptr; } + bool is_marked_for_strip () const override { return to == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ RangeToInclExpr *clone_expr_without_block_impl () const override @@ -2994,6 +3009,9 @@ public: Location locus; + // TODO: find another way to store this to save memory? + bool marked_for_strip = false; + std::string as_string () const override; /* Returns whether the object has an expression returned (i.e. not void return @@ -3009,7 +3027,7 @@ public: // Copy constructor with clone ReturnExpr (ReturnExpr const &other) - : ExprWithoutBlock (other), locus (other.locus) + : ExprWithoutBlock (other), locus (other.locus), marked_for_strip (other.marked_for_strip) { // guard to protect from null pointer dereference if (other.return_expr != nullptr) @@ -3020,10 +3038,16 @@ public: ReturnExpr &operator= (ReturnExpr const &other) { ExprWithoutBlock::operator= (other); - return_expr = other.return_expr->clone_expr (); locus = other.locus; + marked_for_strip = other.marked_for_strip; // outer_attrs = other.outer_attrs; + // guard to protect from null pointer dereference + if (other.return_expr != nullptr) + return_expr = other.return_expr->clone_expr (); + else + return_expr = nullptr; + return *this; } @@ -3036,14 +3060,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - ReturnExpr *clone_expr_impl () const override - { - return new ReturnExpr (*this); - } + // Can't think of any invalid invariants, so store boolean. + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ ReturnExpr *clone_expr_without_block_impl () const override @@ -3074,18 +3095,26 @@ public: // Copy constructor with clone UnsafeBlockExpr (UnsafeBlockExpr const &other) - : ExprWithBlock (other), expr (other.expr->clone_block_expr ()), - locus (other.locus) - {} + : ExprWithBlock (other), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.expr != nullptr) + expr = other.expr->clone_block_expr (); + } // Overloaded assignment operator to clone UnsafeBlockExpr &operator= (UnsafeBlockExpr const &other) { ExprWithBlock::operator= (other); - expr = other.expr->clone_block_expr (); locus = other.locus; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.expr != nullptr) + expr = other.expr->clone_block_expr (); + else + expr = nullptr; + return *this; } @@ -3098,14 +3127,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - UnsafeBlockExpr *clone_expr_impl () const override - { - return new UnsafeBlockExpr (*this); - } + // Invalid if block is null, so base stripping on that. + void mark_for_strip () override { expr = nullptr; } + bool is_marked_for_strip () const override { return expr == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ UnsafeBlockExpr *clone_expr_with_block_impl () const override @@ -3164,19 +3190,27 @@ protected: // Copy constructor for BaseLoopExpr with clone BaseLoopExpr (BaseLoopExpr const &other) - : ExprWithBlock (other), loop_label (other.loop_label), - loop_block (other.loop_block->clone_block_expr ()), locus (other.locus) - {} + : ExprWithBlock (other), loop_label (other.loop_label), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.loop_block != nullptr) + loop_block = other.loop_block->clone_block_expr (); + } // Overloaded assignment operator to clone BaseLoopExpr &operator= (BaseLoopExpr const &other) { ExprWithBlock::operator= (other); - loop_block = other.loop_block->clone_block_expr (); loop_label = other.loop_label; locus = other.locus; // outer_attrs = other.outer_attrs; + // guard to prevent null dereference (only required if error state) + if (other.loop_block != nullptr) + loop_block = other.loop_block->clone_block_expr (); + else + loop_block = nullptr; + return *this; } @@ -3189,6 +3223,10 @@ public: Location get_locus () const { return locus; } Location get_locus_slow () const override { return get_locus (); } + + // Invalid if loop block is null, so base stripping on that. + void mark_for_strip () override { loop_block = nullptr; } + bool is_marked_for_strip () const override { return loop_block == nullptr; } }; // 'Loop' expression (i.e. the infinite loop) AST node @@ -3210,10 +3248,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - LoopExpr *clone_expr_impl () const override { return new LoopExpr (*this); } - - /* Use covariance to implement clone function as returning this object rather - * than base */ LoopExpr *clone_expr_with_block_impl () const override { return new LoopExpr (*this); @@ -3265,13 +3299,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - WhileLoopExpr *clone_expr_impl () const override - { - return new WhileLoopExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ WhileLoopExpr *clone_expr_with_block_impl () const override { return new WhileLoopExpr (*this); @@ -3338,13 +3365,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - WhileLetLoopExpr *clone_expr_impl () const override - { - return new WhileLetLoopExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ WhileLetLoopExpr *clone_expr_with_block_impl () const override { return new WhileLetLoopExpr (*this); @@ -3400,13 +3420,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - ForLoopExpr *clone_expr_impl () const override - { - return new ForLoopExpr (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ ForLoopExpr *clone_expr_with_block_impl () const override { return new ForLoopExpr (*this); @@ -3437,18 +3450,31 @@ public: // Copy constructor with clone IfExpr (IfExpr const &other) - : ExprWithBlock (other), condition (other.condition->clone_expr ()), - if_block (other.if_block->clone_block_expr ()), locus (other.locus) - {} + : ExprWithBlock (other), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.condition != nullptr) + condition = other.condition->clone_expr (); + if (other.if_block != nullptr) + if_block = other.if_block->clone_block_expr (); + } // Overloaded assignment operator to clone expressions IfExpr &operator= (IfExpr const &other) { ExprWithBlock::operator= (other); - condition = other.condition->clone_expr (); - if_block = other.if_block->clone_block_expr (); locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.condition != nullptr) + condition = other.condition->clone_expr (); + else + condition = nullptr; + if (other.if_block != nullptr) + if_block = other.if_block->clone_block_expr (); + else + if_block = nullptr; + return *this; } @@ -3477,19 +3503,19 @@ public: Expr *get_if_condition () { return condition.get (); } BlockExpr *get_if_block () { return if_block.get (); } -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - IfExpr *clone_expr_impl () const override { return new IfExpr (*this); } + // Invalid if if block or condition is null, so base stripping on that. + void mark_for_strip () override { if_block = nullptr; condition = nullptr; } + bool is_marked_for_strip () const override { return if_block == nullptr && condition == nullptr; } +protected: // Base clone function but still concrete as concrete base class virtual IfExpr *clone_if_expr_impl () const { return new IfExpr (*this); } /* Use covariance to implement clone function as returning this object rather * than base */ - IfExpr *clone_expr_with_block_impl () const override + IfExpr *clone_expr_with_block_impl () const final override { - return new IfExpr (*this); + return clone_if_expr_impl (); } }; @@ -3536,20 +3562,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - IfExprConseqElse *clone_expr_impl () const override - { - return new IfExprConseqElse (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ - IfExprConseqElse *clone_expr_with_block_impl () const override - { - return new IfExprConseqElse (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ IfExprConseqElse *clone_if_expr_impl () const override { return new IfExprConseqElse (*this); @@ -3602,20 +3614,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - IfExprConseqIf *clone_expr_impl () const override - { - return new IfExprConseqIf (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ - IfExprConseqIf *clone_expr_with_block_impl () const override - { - return new IfExprConseqIf (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ IfExprConseqIf *clone_if_expr_impl () const override { return new IfExprConseqIf (*this); @@ -3646,11 +3644,14 @@ public: // copy constructor with clone IfLetExpr (IfLetExpr const &other) - : ExprWithBlock (other), - /*match_arm_patterns(other.match_arm_patterns),*/ value ( - other.value->clone_expr ()), - if_block (other.if_block->clone_block_expr ()), locus (other.locus) + : ExprWithBlock (other), locus (other.locus) { + // guard to prevent null dereference (only required if error state) + if (other.value != nullptr) + value = other.value->clone_expr (); + if (other.if_block != nullptr) + if_block = other.if_block->clone_block_expr (); + match_arm_patterns.reserve (other.match_arm_patterns.size ()); for (const auto &e : other.match_arm_patterns) match_arm_patterns.push_back (e->clone_pattern ()); @@ -3660,11 +3661,18 @@ public: IfLetExpr &operator= (IfLetExpr const &other) { ExprWithBlock::operator= (other); - // match_arm_patterns = other.match_arm_patterns; - value = other.value->clone_expr (); - if_block = other.if_block->clone_block_expr (); locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.value != nullptr) + value = other.value->clone_expr (); + else + value = nullptr; + if (other.if_block != nullptr) + if_block = other.if_block->clone_block_expr (); + else + if_block = nullptr; + match_arm_patterns.reserve (other.match_arm_patterns.size ()); for (const auto &e : other.match_arm_patterns) match_arm_patterns.push_back (e->clone_pattern ()); @@ -3687,16 +3695,16 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - IfLetExpr *clone_expr_impl () const override { return new IfLetExpr (*this); } + // Invalid if block or value is null, so base stripping on that. + void mark_for_strip () override { if_block = nullptr; value = nullptr; } + bool is_marked_for_strip () const override { return if_block == nullptr && value == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather - * than base */ - IfLetExpr *clone_expr_with_block_impl () const override + * than base (or rather this or any derived object) */ + IfLetExpr *clone_expr_with_block_impl () const final override { - return new IfLetExpr (*this); + return clone_if_let_expr_impl (); } // Base clone function but still concrete as concrete base class @@ -3748,20 +3756,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - IfExprConseqIfLet *clone_expr_impl () const override - { - return new IfExprConseqIfLet (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ - IfExprConseqIfLet *clone_expr_with_block_impl () const override - { - return new IfExprConseqIfLet (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ IfExprConseqIfLet *clone_if_expr_impl () const override { return new IfExprConseqIfLet (*this); @@ -3814,20 +3808,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - IfLetExprConseqElse *clone_expr_impl () const override - { - return new IfLetExprConseqElse (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ - IfLetExprConseqElse *clone_expr_with_block_impl () const override - { - return new IfLetExprConseqElse (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ IfLetExprConseqElse *clone_if_let_expr_impl () const override { return new IfLetExprConseqElse (*this); @@ -3879,20 +3859,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - IfLetExprConseqIf *clone_expr_impl () const override - { - return new IfLetExprConseqIf (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ - IfLetExprConseqIf *clone_expr_with_block_impl () const override - { - return new IfLetExprConseqIf (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ IfLetExprConseqIf *clone_if_let_expr_impl () const override { return new IfLetExprConseqIf (*this); @@ -3944,20 +3910,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - IfLetExprConseqIfLet *clone_expr_impl () const override - { - return new IfLetExprConseqIfLet (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ - IfLetExprConseqIfLet *clone_expr_with_block_impl () const override - { - return new IfLetExprConseqIfLet (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ IfLetExprConseqIfLet *clone_if_let_expr_impl () const override { return new IfLetExprConseqIfLet (*this); @@ -4012,6 +3964,8 @@ public: if (other.guard_expr != nullptr) guard_expr = other.guard_expr->clone_expr (); + else + guard_expr = nullptr; match_arm_patterns.reserve (other.match_arm_patterns.size ()); for (const auto &e : other.match_arm_patterns) @@ -4224,10 +4178,13 @@ public: // Copy constructor requires clone due to unique_ptr MatchExpr (MatchExpr const &other) - : ExprWithBlock (other), branch_value (other.branch_value->clone_expr ()), - inner_attrs (other.inner_attrs), match_arms (other.match_arms), - locus (other.locus) + : ExprWithBlock (other), inner_attrs (other.inner_attrs), + match_arms (other.match_arms), locus (other.locus) { + // guard to prevent null dereference (only required if error state) + if (other.branch_value != nullptr) + branch_value = other.branch_value->clone_expr (); + /*match_arms.reserve (other.match_arms.size ()); for (const auto &e : other.match_arms) match_arms.push_back (e->clone_match_case ());*/ @@ -4237,12 +4194,17 @@ public: MatchExpr &operator= (MatchExpr const &other) { ExprWithBlock::operator= (other); - branch_value = other.branch_value->clone_expr (); inner_attrs = other.inner_attrs; match_arms = other.match_arms; // outer_attrs = other.outer_attrs; locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.branch_value != nullptr) + branch_value = other.branch_value->clone_expr (); + else + branch_value = nullptr; + /*match_arms.reserve (other.match_arms.size ()); for (const auto &e : other.match_arms) match_arms.push_back (e->clone_match_case ());*/ @@ -4259,11 +4221,11 @@ public: void accept_vis (ASTVisitor &vis) override; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - MatchExpr *clone_expr_impl () const override { return new MatchExpr (*this); } + // Invalid if branch value is null, so base stripping on that. + void mark_for_strip () override { branch_value = nullptr; } + bool is_marked_for_strip () const override { return branch_value == nullptr; } +protected: /* Use covariance to implement clone function as returning this object rather * than base */ MatchExpr *clone_expr_with_block_impl () const override @@ -4289,17 +4251,25 @@ public: // copy constructor with clone AwaitExpr (AwaitExpr const &other) - : ExprWithoutBlock (other), - awaited_expr (other.awaited_expr->clone_expr ()), locus (other.locus) - {} + : ExprWithoutBlock (other), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.awaited_expr != nullptr) + awaited_expr = other.awaited_expr->clone_expr (); + } // overloaded assignment operator with clone AwaitExpr &operator= (AwaitExpr const &other) { ExprWithoutBlock::operator= (other); - awaited_expr = other.awaited_expr->clone_expr (); locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.awaited_expr != nullptr) + awaited_expr = other.awaited_expr->clone_expr (); + else + awaited_expr = nullptr; + return *this; } @@ -4314,6 +4284,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if awaited expr is null, so base stripping on that. + void mark_for_strip () override { awaited_expr = nullptr; } + bool is_marked_for_strip () const override { return awaited_expr == nullptr; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -4341,18 +4315,26 @@ public: // copy constructor with clone AsyncBlockExpr (AsyncBlockExpr const &other) - : ExprWithBlock (other), has_move (other.has_move), - block_expr (other.block_expr->clone_block_expr ()), locus (other.locus) - {} + : ExprWithBlock (other), has_move (other.has_move), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.block_expr != nullptr) + block_expr = other.block_expr->clone_block_expr (); + } // overloaded assignment operator to clone AsyncBlockExpr &operator= (AsyncBlockExpr const &other) { ExprWithBlock::operator= (other); has_move = other.has_move; - block_expr = other.block_expr->clone_block_expr (); locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.block_expr != nullptr) + block_expr = other.block_expr->clone_block_expr (); + else + block_expr = nullptr; + return *this; } @@ -4367,6 +4349,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if block is null, so base stripping on that. + void mark_for_strip () override { block_expr = nullptr; } + bool is_marked_for_strip () const override { return block_expr == nullptr; } + 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 b5d9247..c35e65f 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -715,24 +715,24 @@ protected: class VisItem : public Item { Visibility visibility; + std::vector<Attribute> outer_attrs; protected: // Visibility constructor VisItem (Visibility visibility, std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) - : Item (std::move (outer_attrs)), visibility (std::move (visibility)) + : visibility (std::move (visibility)), outer_attrs(std::move (outer_attrs)) {} // Visibility copy constructor - VisItem (VisItem const &other) : Item (other), visibility (other.visibility) + VisItem (VisItem const &other) : visibility (other.visibility), outer_attrs(other.outer_attrs) {} // Overload assignment operator to clone VisItem &operator= (VisItem const &other) { - Item::operator= (other); visibility = other.visibility; - // outer_attrs = other.outer_attrs; + outer_attrs = other.outer_attrs; return *this; } @@ -747,6 +747,13 @@ public: bool has_visibility () const { return !visibility.is_error (); } std::string as_string () const override; + + // TODO: this mutable getter seems really dodgy. Think up better way. + Visibility &get_vis () { return visibility; } + const Visibility &get_vis () const { return visibility; } + + std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } }; // Rust module item - abstract base class @@ -767,6 +774,10 @@ public: std::string as_string () const override; Location get_locus () const { return locus; } + + // Invalid if name is empty, so base stripping on that. + void mark_for_strip () override { module_name = ""; } + bool is_marked_for_strip () const override { return module_name.empty (); } }; // Module with a body, defined in file @@ -837,17 +848,14 @@ protected: { return new ModuleBodied (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual ModuleBodied* clone_statement_impl() const override { - return new ModuleBodied(*this); - }*/ }; // Module without a body, loaded from external file class ModuleNoBody : public Module { + /* TODO: are modules loaded from file unique? As in, can you load the same file into two different + * other files? Because this may make the difference between simply replacing this with the module + * "definition" (as loaded from another file) vs this having to "reference" a module with body. */ public: std::string as_string () const override; @@ -867,12 +875,6 @@ protected: { return new ModuleNoBody (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual ModuleNoBody* clone_statement_impl() const override { - return new ModuleNoBody(*this); - }*/ }; // Rust extern crate declaration AST node @@ -920,6 +922,10 @@ public: names.push_back (referenced_crate); } + // Invalid if crate name is empty, so base stripping on that. + void mark_for_strip () override { referenced_crate = ""; } + bool is_marked_for_strip () const override { return referenced_crate.empty (); } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -927,12 +933,6 @@ protected: { return new ExternCrate (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual ExternCrate* clone_statement_impl() const override { - return new ExternCrate(*this); - }*/ }; // The path-ish thing referred to in a use declaration - abstract base class @@ -1153,19 +1153,27 @@ public: // Copy constructor with clone UseDeclaration (UseDeclaration const &other) - : VisItem (other), use_tree (other.use_tree->clone_use_tree ()), - locus (other.locus) - {} + : VisItem (other), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.use_tree != nullptr) + use_tree = other.use_tree->clone_use_tree (); + } // Overloaded assignment operator to clone UseDeclaration &operator= (UseDeclaration const &other) { VisItem::operator= (other); - use_tree = other.use_tree->clone_use_tree (); // visibility = other.visibility->clone_visibility(); // outer_attrs = other.outer_attrs; locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.use_tree != nullptr) + use_tree = other.use_tree->clone_use_tree (); + else + use_tree = nullptr; + return *this; } @@ -1177,6 +1185,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if use tree is null, so base stripping on that. + void mark_for_strip () override { use_tree = nullptr; } + bool is_marked_for_strip () const override { return use_tree == nullptr; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1184,12 +1196,6 @@ protected: { return new UseDeclaration (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual UseDeclaration* clone_statement_impl() const override { - return new UseDeclaration(*this); - }*/ }; // Parameters used in a function - TODO inline? @@ -1264,11 +1270,16 @@ public: : VisItem (other), qualifiers (other.qualifiers), function_name (other.function_name), function_params (other.function_params), - return_type (other.return_type->clone_type ()), - where_clause (other.where_clause), - function_body (other.function_body->clone_block_expr ()), - locus (other.locus) + where_clause (other.where_clause), locus (other.locus) { + // guard to prevent null dereference (always required) + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + + // guard to prevent null dereference (only required if error state) + if (other.function_body != nullptr) + function_body = other.function_body->clone_block_expr (); + generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); @@ -1280,15 +1291,24 @@ public: VisItem::operator= (other); function_name = other.function_name; qualifiers = other.qualifiers; - // generic_params = other.generic_params; function_params = other.function_params; - return_type = other.return_type->clone_type (); where_clause = other.where_clause; - function_body = other.function_body->clone_block_expr (); // visibility = other.visibility->clone_visibility(); // outer_attrs = other.outer_attrs; locus = other.locus; + // guard to prevent null dereference (always required) + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + else + return_type = nullptr; + + // guard to prevent null dereference (only required if error state) + if (other.function_body != nullptr) + function_body = other.function_body->clone_block_expr (); + else + function_body = nullptr; + generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); @@ -1304,6 +1324,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if block is null, so base stripping on that. + void mark_for_strip () override { function_body = nullptr; } + bool is_marked_for_strip () const override { return function_body == nullptr; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1322,12 +1346,6 @@ protected: { return new Function (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual Function* clone_statement_impl() const override { - return new Function(*this); - }*/ }; // Rust type alias (i.e. typedef) AST node @@ -1370,9 +1388,12 @@ public: // Copy constructor TypeAlias (TypeAlias const &other) : VisItem (other), new_type_name (other.new_type_name), - where_clause (other.where_clause), - existing_type (other.existing_type->clone_type ()), locus (other.locus) + where_clause (other.where_clause), locus (other.locus) { + // guard to prevent null dereference (only required if error state) + if (other.existing_type != nullptr) + existing_type = other.existing_type->clone_type (); + generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); @@ -1383,13 +1404,17 @@ public: { VisItem::operator= (other); new_type_name = other.new_type_name; - // generic_params = other.generic_params; where_clause = other.where_clause; - existing_type = other.existing_type->clone_type (); // visibility = other.visibility->clone_visibility(); // outer_attrs = other.outer_attrs; locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.existing_type != nullptr) + existing_type = other.existing_type->clone_type (); + else + existing_type = nullptr; + generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); @@ -1405,6 +1430,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if existing type is null, so base stripping on that. + void mark_for_strip () override { existing_type = nullptr; } + bool is_marked_for_strip () const override { return existing_type == nullptr; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1416,12 +1445,6 @@ protected: { return new TypeAlias (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual TypeAlias* clone_statement_impl() const override { - return new TypeAlias(*this); - }*/ }; // Rust base struct declaration AST node - abstract base class @@ -1448,6 +1471,10 @@ public: Location get_locus () const { return locus; } + // Invalid if name is empty, so base stripping on that. + void mark_for_strip () override { struct_name = ""; } + bool is_marked_for_strip () const override { return struct_name.empty (); } + protected: Struct (Identifier struct_name, std::vector<std::unique_ptr<GenericParam>> generic_params, @@ -1584,8 +1611,7 @@ public: std::vector<Attribute> outer_attrs, Location locus) : Struct (std::move (struct_name), std::move (generic_params), std::move (where_clause), std::move (vis), locus, - std::move (outer_attrs)), - is_unit (true) + std::move (outer_attrs)), is_unit (true) {} // TODO: can a unit struct have generic fields? assuming yes for now. @@ -1603,12 +1629,6 @@ protected: { return new StructStruct (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual StructStruct* clone_statement_impl() const override { - return new StructStruct(*this); - }*/ }; // A single field in a tuple @@ -1702,12 +1722,6 @@ protected: { return new TupleStruct (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual TupleStruct* clone_statement_impl() const override { - return new TupleStruct(*this); - }*/ }; /* An item used in an "enum" tagged union - not abstract: base represents a @@ -1937,16 +1951,14 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if name is empty, so base stripping on that. + void mark_for_strip () override { enum_name = ""; } + bool is_marked_for_strip () const override { return enum_name.empty (); } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ Enum *clone_item_impl () const override { return new Enum (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual Enum* clone_statement_impl() const override { - return new Enum(*this); - }*/ }; // Rust untagged union used for C compat AST node @@ -2020,16 +2032,14 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if name is empty, so base stripping on that. + void mark_for_strip () override { union_name = ""; } + bool is_marked_for_strip () const override { return union_name.empty (); } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ Union *clone_item_impl () const override { return new Union (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual Union* clone_statement_impl() const override { - return new Union(*this); - }*/ }; /* "Constant item" AST node - used for constant, compile-time expressions @@ -2041,7 +2051,7 @@ class ConstantItem : public VisItem, // either has an identifier or "_" - maybe handle in identifier? // bool identifier_is_underscore; // if no identifier declared, identifier will be "_" - Identifier identifier; + std::string identifier; std::unique_ptr<Type> type; std::unique_ptr<Expr> const_expr; @@ -2051,7 +2061,7 @@ class ConstantItem : public VisItem, public: std::string as_string () const override; - ConstantItem (Identifier ident, Visibility vis, std::unique_ptr<Type> type, + ConstantItem (std::string ident, Visibility vis, std::unique_ptr<Type> type, std::unique_ptr<Expr> const_expr, std::vector<Attribute> outer_attrs, Location locus) : VisItem (std::move (vis), std::move (outer_attrs)), @@ -2060,20 +2070,32 @@ public: {} ConstantItem (ConstantItem const &other) - : VisItem (other), identifier (other.identifier), - type (other.type->clone_type ()), - const_expr (other.const_expr->clone_expr ()), locus (other.locus) - {} + : VisItem (other), identifier (other.identifier), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.type != nullptr) + type = other.type->clone_type (); + if (other.const_expr != nullptr) + const_expr = other.const_expr->clone_expr (); + } // Overload assignment operator to clone ConstantItem &operator= (ConstantItem const &other) { VisItem::operator= (other); identifier = other.identifier; - type = other.type->clone_type (); - const_expr = other.const_expr->clone_expr (); locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.type != nullptr) + type = other.type->clone_type (); + else + type = nullptr; + if (other.const_expr != nullptr) + const_expr = other.const_expr->clone_expr (); + else + const_expr = nullptr; + return *this; } @@ -2083,12 +2105,16 @@ public: /* Returns whether constant item is an "unnamed" (wildcard underscore used * as identifier) constant. */ - bool is_unnamed () const { return identifier == std::string ("_"); } + bool is_unnamed () const { return identifier == "_"; } Location get_locus () const { return locus; } void accept_vis (ASTVisitor &vis) override; + // Invalid if type or expression are null, so base stripping on that. + void mark_for_strip () override { type = nullptr; const_expr = nullptr; } + bool is_marked_for_strip () const override { return type == nullptr && const_expr == nullptr; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2110,12 +2136,6 @@ protected: { return new ConstantItem (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual ConstantItem* clone_statement_impl() const override { - return new ConstantItem(*this); - }*/ }; /* Static item AST node - items within module scope with fixed storage @@ -2142,9 +2162,14 @@ public: // Copy constructor with clone StaticItem (StaticItem const &other) : VisItem (other), has_mut (other.has_mut), name (other.name), - type (other.type->clone_type ()), expr (other.expr->clone_expr ()), locus (other.locus) - {} + { + // guard to prevent null dereference (only required if error state) + if (other.type != nullptr) + type = other.type->clone_type (); + if (other.expr != nullptr) + expr = other.expr->clone_expr (); + } // Overloaded assignment operator to clone StaticItem &operator= (StaticItem const &other) @@ -2152,10 +2177,18 @@ public: VisItem::operator= (other); name = other.name; has_mut = other.has_mut; - type = other.type->clone_type (); - expr = other.expr->clone_expr (); locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.type != nullptr) + type = other.type->clone_type (); + else + type = nullptr; + if (other.expr != nullptr) + expr = other.expr->clone_expr (); + else + expr = nullptr; + return *this; } @@ -2167,6 +2200,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if type or expression are null, so base stripping on that. + void mark_for_strip () override { type = nullptr; expr = nullptr; } + bool is_marked_for_strip () const override { return type == nullptr && expr == nullptr; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2174,12 +2211,6 @@ protected: { return new StaticItem (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual StaticItem* clone_statement_impl() const override { - return new StaticItem(*this); - }*/ }; // Function declaration in traits @@ -2606,7 +2637,6 @@ protected: class Trait : public VisItem { bool has_unsafe; - Identifier name; // bool has_generics; @@ -2706,16 +2736,14 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if trait name is empty, so base stripping on that. + void mark_for_strip () override { name = ""; } + bool is_marked_for_strip () const override { return name.empty (); } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ Trait *clone_item_impl () const override { return new Trait (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual Trait* clone_statement_impl() const override { - return new Trait(*this); - }*/ }; // Implementation item declaration AST node - abstract base class @@ -2751,6 +2779,10 @@ public: Location get_locus () const { return locus; } + // Invalid if trait type is null, so base stripping on that. + void mark_for_strip () override { trait_type = nullptr; } + bool is_marked_for_strip () const override { return trait_type == nullptr; } + protected: // Mega-constructor Impl (std::vector<std::unique_ptr<GenericParam>> generic_params, @@ -2766,10 +2798,13 @@ protected: // Copy constructor Impl (Impl const &other) - : VisItem (other), trait_type (other.trait_type->clone_type ()), - where_clause (other.where_clause), inner_attrs (other.inner_attrs), - locus (other.locus) + : VisItem (other), where_clause (other.where_clause), + inner_attrs (other.inner_attrs), locus (other.locus) { + // guard to prevent null dereference (only required if error state) + if (other.trait_type != nullptr) + trait_type = other.trait_type->clone_type (); + generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); @@ -2779,11 +2814,16 @@ protected: Impl &operator= (Impl const &other) { VisItem::operator= (other); - trait_type = other.trait_type->clone_type (); where_clause = other.where_clause; inner_attrs = other.inner_attrs; locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.trait_type != nullptr) + trait_type = other.trait_type->clone_type (); + else + trait_type = nullptr; + generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); @@ -2853,12 +2893,6 @@ protected: { return new InherentImpl (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual InherentImpl* clone_statement_impl() const override { - return new InherentImpl(*this); - }*/ }; // The "impl footrait for foo" impl block declaration AST node @@ -2928,12 +2962,6 @@ protected: /* Use covariance to implement clone function as returning this object * rather than base */ TraitImpl *clone_item_impl () const override { return new TraitImpl (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual TraitImpl* clone_statement_impl() const override { - return new TraitImpl(*this); - }*/ }; // Abstract base class for an item used inside an extern block @@ -2951,6 +2979,10 @@ class ExternalItem public: virtual ~ExternalItem () {} + /* TODO: spec syntax rules state that "MacroInvocationSemi" can be used as + * ExternalItem, but text body isn't so clear. Adding MacroInvocationSemi + * support would require a lot of refactoring. */ + // Returns whether item has outer attributes. bool has_outer_attrs () const { return !outer_attrs.empty (); } @@ -2969,6 +3001,11 @@ public: virtual void accept_vis (ASTVisitor &vis) = 0; + // TODO: make virtual? Would be more flexible. + // Based on idea that name should never be empty. + void mark_for_strip () { item_name = ""; }; + bool is_marked_for_strip () const { return item_name.empty (); }; + protected: ExternalItem (Identifier item_name, Visibility vis, std::vector<Attribute> outer_attrs, Location locus) @@ -3209,6 +3246,9 @@ class ExternBlock : public VisItem std::vector<std::unique_ptr<ExternalItem>> extern_items; Location locus; + + // TODO: find another way to store this to save memory? + bool marked_for_strip = false; public: std::string as_string () const override; @@ -3234,7 +3274,7 @@ public: // Copy constructor with vector clone ExternBlock (ExternBlock const &other) : VisItem (other), abi (other.abi), inner_attrs (other.inner_attrs), - locus (other.locus) + locus (other.locus), marked_for_strip (other.marked_for_strip) { extern_items.reserve (other.extern_items.size ()); for (const auto &e : other.extern_items) @@ -3248,6 +3288,7 @@ public: abi = other.abi; inner_attrs = other.inner_attrs; locus = other.locus; + marked_for_strip = other.marked_for_strip; extern_items.reserve (other.extern_items.size ()); for (const auto &e : other.extern_items) @@ -3264,6 +3305,18 @@ public: void accept_vis (ASTVisitor &vis) override; + // Can't think of any invalid invariants, so store boolean. + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } + + // TODO: think of better way to do this + const std::vector<std::unique_ptr<ExternalItem>>& get_extern_items () const { return extern_items; } + std::vector<std::unique_ptr<ExternalItem>>& get_extern_items () { return extern_items; } + + // TODO: think of better way to do this + const std::vector<Attribute>& get_inner_attrs () const { return inner_attrs; } + std::vector<Attribute>& get_inner_attrs () { return inner_attrs; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -3271,12 +3324,6 @@ protected: { return new ExternBlock (*this); } - - /* Use covariance to implement clone function as returning this object - * rather than base */ - /*virtual ExternBlock* clone_statement_impl() const override { - return new ExternBlock(*this); - }*/ }; // Replaced with forward decls - defined in "rust-macro.h" diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index 9ecbb51..8d50b88 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -124,7 +124,7 @@ private: public: // Returns whether macro match repetition has separator token. - bool has_sep () const { return sep != NULL; } + bool has_sep () const { return sep != nullptr; } MacroMatchRepetition (std::vector<std::unique_ptr<MacroMatch> > matches, MacroRepOp op, std::unique_ptr<MacroRepSep> sep) @@ -133,8 +133,12 @@ public: // Copy constructor with clone MacroMatchRepetition (MacroMatchRepetition const &other) - : op (other.op), sep (other.sep->clone_token ()) + : op (other.op) { + // guard to protect from null pointer dereference + if (other.sep != nullptr) + sep = other.sep->clone_token (); + matches.reserve (other.matches.size ()); for (const auto &e : other.matches) matches.push_back (e->clone_macro_match ()); @@ -144,7 +148,12 @@ public: MacroMatchRepetition &operator= (MacroMatchRepetition const &other) { op = other.op; - sep = other.sep->clone_token (); + + // guard to protect from null pointer dereference + if (other.sep != nullptr) + sep = other.sep->clone_token (); + else + sep = nullptr; matches.reserve (other.matches.size ()); for (const auto &e : other.matches) @@ -280,8 +289,9 @@ public: // A macro rules definition item AST node class MacroRulesDefinition : public MacroItem { + std::vector<Attribute> outer_attrs; Identifier rule_name; - // MacroRulesDef rules_def; // TODO: inline + // MacroRulesDef rules_def; // only curly without required semicolon at end DelimType delim_type; // MacroRules rules; @@ -295,12 +305,16 @@ public: MacroRulesDefinition (Identifier rule_name, DelimType delim_type, std::vector<MacroRule> rules, std::vector<Attribute> outer_attrs, Location locus) - : MacroItem (std::move (outer_attrs)), rule_name (std::move (rule_name)), + : outer_attrs (std::move (outer_attrs)), rule_name (std::move (rule_name)), delim_type (delim_type), rules (std::move (rules)), locus (locus) {} void accept_vis (ASTVisitor &vis) override; + // Invalid if rule name is empty, so base stripping on that. + void mark_for_strip () override { rule_name = ""; } + bool is_marked_for_strip () const override { return rule_name.empty (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -334,6 +348,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if path is empty, so base stripping on that. + void mark_for_strip () override { path = SimplePath::create_empty (); } + bool is_marked_for_strip () const override { return path.is_empty (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -341,14 +359,7 @@ protected: { return new MacroInvocation (*this); } - - /* Use covariance to implement clone function as returning this object rather - * than base */ - MacroInvocation *clone_expr_impl () const override - { - return new MacroInvocation (*this); - } - + /* Use covariance to implement clone function as returning this object rather * than base */ MacroInvocation *clone_expr_without_block_impl () const override @@ -358,13 +369,6 @@ protected: /* Use covariance to implement clone function as returning this object rather * than base */ - MacroInvocation *clone_type_impl () const override - { - return new MacroInvocation (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ MacroInvocation *clone_type_no_bounds_impl () const override { return new MacroInvocation (*this); diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 3006780..32147d3 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -70,9 +70,12 @@ public: // Copy constructor has to deep copy the type as it is a unique pointer GenericArgsBinding (GenericArgsBinding const &other) - : identifier (other.identifier), type (other.type->clone_type ()), - locus (other.locus) - {} + : identifier (other.identifier), locus (other.locus) + { + // guard to protect from null pointer dereference + if (other.type != nullptr) + type = other.type->clone_type (); + } // default destructor ~GenericArgsBinding () = default; @@ -81,8 +84,14 @@ public: GenericArgsBinding &operator= (GenericArgsBinding const &other) { identifier = other.identifier; - type = other.type->clone_type (); locus = other.locus; + + // guard to protect from null pointer dereference + if (other.type != nullptr) + type = other.type->clone_type (); + else + type = nullptr; + return *this; } @@ -231,6 +240,9 @@ protected: * and creates a SimplePath from them. */ SimplePath convert_to_simple_path (bool with_opening_scope_resolution) const; + // Removes all segments of the path. + void remove_all_segments () { segments.clear (); segments.shrink_to_fit (); } + public: /* Returns whether the path is a single segment (excluding qualified path * initial as segment). */ @@ -286,6 +298,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if path is empty (error state), so base stripping on that. + void mark_for_strip () override { remove_all_segments (); } + bool is_marked_for_strip () const override { return is_error (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -446,13 +462,6 @@ public: // Constructor TypePathFunction (std::vector<std::unique_ptr<Type>> inputs, - Type *type = nullptr) - : inputs (std::move (inputs)), return_type (type), is_invalid (false) - {} - // FIXME: deprecated - - // Constructor - TypePathFunction (std::vector<std::unique_ptr<Type>> inputs, std::unique_ptr<Type> type = nullptr) : inputs (std::move (inputs)), return_type (std::move (type)), is_invalid (false) @@ -460,9 +469,12 @@ public: // Copy constructor with clone TypePathFunction (TypePathFunction const &other) - : return_type (other.return_type->clone_type ()), - is_invalid (other.is_invalid) + : is_invalid (other.is_invalid) { + // guard to protect from null pointer dereference + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + inputs.reserve (other.inputs.size ()); for (const auto &e : other.inputs) inputs.push_back (e->clone_type ()); @@ -473,9 +485,14 @@ public: // Overloaded assignment operator to clone type TypePathFunction &operator= (TypePathFunction const &other) { - return_type = other.return_type->clone_type (); is_invalid = other.is_invalid; + // guard to protect from null pointer dereference + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + else + return_type = nullptr; + inputs.reserve (other.inputs.size ()); for (const auto &e : other.inputs) inputs.push_back (e->clone_type ()); @@ -539,10 +556,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TypePath *clone_type_impl () const override { return new TypePath (*this); } - - /* Use covariance to implement clone function as returning this object rather - * than base */ TypePath *clone_type_no_bounds_impl () const override { return new TypePath (*this); @@ -635,9 +648,12 @@ public: // Copy constructor uses custom deep copy for Type to preserve polymorphism QualifiedPathType (QualifiedPathType const &other) - : type_to_invoke_on (other.type_to_invoke_on->clone_type ()), - trait_path (other.trait_path), locus (other.locus) - {} + : trait_path (other.trait_path), locus (other.locus) + { + // guard to prevent null dereference + if (other.type_to_invoke_on != nullptr) + type_to_invoke_on = other.type_to_invoke_on->clone_type (); + } // default destructor ~QualifiedPathType () = default; @@ -645,9 +661,15 @@ public: // overload assignment operator to use custom clone method QualifiedPathType &operator= (QualifiedPathType const &other) { - type_to_invoke_on = other.type_to_invoke_on->clone_type (); trait_path = other.trait_path; locus = other.locus; + + // guard to prevent null dereference + if (other.type_to_invoke_on != nullptr) + type_to_invoke_on = other.type_to_invoke_on->clone_type (); + else + type_to_invoke_on = nullptr; + return *this; } @@ -710,6 +732,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if path_type is error, so base stripping on that. + void mark_for_strip () override { path_type = QualifiedPathType::create_error (); } + bool is_marked_for_strip () const override { return is_error (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -737,13 +763,6 @@ class QualifiedPathInType : public TypeNoBounds protected: /* Use covariance to implement clone function as returning this object rather * than base */ - QualifiedPathInType *clone_type_impl () const override - { - return new QualifiedPathInType (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ QualifiedPathInType *clone_type_no_bounds_impl () const override { return new QualifiedPathInType (*this); diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 4e639a5..63abe7a 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -77,7 +77,7 @@ public: : variable_ident (other.variable_ident), is_ref (other.is_ref), is_mut (other.is_mut), locus (other.locus) { - // fix to get prevent null pointer dereference + // fix to prevent null pointer dereference if (other.to_bind != nullptr) to_bind = other.to_bind->clone_pattern (); } @@ -90,9 +90,11 @@ public: is_mut = other.is_mut; locus = other.locus; - // fix to get prevent null pointer dereference + // fix to prevent null pointer dereference if (other.to_bind != nullptr) to_bind = other.to_bind->clone_pattern (); + else + to_bind = nullptr; return *this; } @@ -1006,15 +1008,24 @@ public: // Copy constructor requires clone TuplePattern (TuplePattern const &other) - : items (other.items->clone_tuple_pattern_items ()), locus (other.locus) - {} + : locus (other.locus) + { + // guard to prevent null dereference + if (other.items != nullptr) + items = other.items->clone_tuple_pattern_items (); + } // Overload assignment operator to clone TuplePattern &operator= (TuplePattern const &other) { - items = other.items->clone_tuple_pattern_items (); locus = other.locus; + // guard to prevent null dereference + if (other.items != nullptr) + items = other.items->clone_tuple_pattern_items (); + else + items = nullptr; + return *this; } diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index ce7a37a..127ea21 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -12,6 +12,9 @@ class EmptyStmt : public Stmt { Location locus; + // TODO: find another way to store this to save memory? + bool marked_for_strip = false; + public: std::string as_string () const override { return std::string (1, ';'); } @@ -21,6 +24,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Can't think of any invalid invariants, so store boolean. + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -68,21 +75,41 @@ public: // Copy constructor with clone LetStmt (LetStmt const &other) - : outer_attrs (other.outer_attrs), - variables_pattern (other.variables_pattern->clone_pattern ()), - type (other.type->clone_type ()), - init_expr (other.init_expr->clone_expr ()), locus (other.locus) - {} + : outer_attrs (other.outer_attrs), locus (other.locus) + { + // guard to prevent null dereference (only required if error state) + if (other.variables_pattern != nullptr) + variables_pattern = other.variables_pattern->clone_pattern (); + + // guard to prevent null dereference (always required) + if (other.init_expr != nullptr) + init_expr = other.init_expr->clone_expr (); + if (other.type != nullptr) + type = other.type->clone_type (); + } // Overloaded assignment operator to clone LetStmt &operator= (LetStmt const &other) { - variables_pattern = other.variables_pattern->clone_pattern (); - init_expr = other.init_expr->clone_expr (); - type = other.type->clone_type (); outer_attrs = other.outer_attrs; locus = other.locus; + // guard to prevent null dereference (only required if error state) + if (other.variables_pattern != nullptr) + variables_pattern = other.variables_pattern->clone_pattern (); + else + variables_pattern = nullptr; + + // guard to prevent null dereference (always required) + if (other.init_expr != nullptr) + init_expr = other.init_expr->clone_expr (); + else + init_expr = nullptr; + if (other.type != nullptr) + type = other.type->clone_type (); + else + type = nullptr; + return *this; } @@ -94,6 +121,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if pattern is null, so base stripping on that. + void mark_for_strip () override { variables_pattern = nullptr; } + bool is_marked_for_strip () const override { return variables_pattern == nullptr; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -138,8 +169,12 @@ public: // Copy constructor with clone ExprStmtWithoutBlock (ExprStmtWithoutBlock const &other) - : ExprStmt (other), expr (other.expr->clone_expr_without_block ()) - {} + : ExprStmt (other) + { + // guard to prevent null dereference (only required if error state) + if (other.expr != nullptr) + expr = other.expr->clone_expr_without_block (); + } /*ExprStmtWithoutBlock (ExprStmtWithoutBlock const &other) : ExprStmt (other), expr (other.expr->clone_expr ()) {}*/ @@ -148,9 +183,14 @@ public: ExprStmtWithoutBlock &operator= (ExprStmtWithoutBlock const &other) { ExprStmt::operator= (other); - expr = other.expr->clone_expr_without_block (); //expr = other.expr->clone_expr (); + // guard to prevent null dereference (only required if error state) + if (other.expr != nullptr) + expr = other.expr->clone_expr_without_block (); + else + expr = nullptr; + return *this; } @@ -160,6 +200,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if expr is null, so base stripping on that. + void mark_for_strip () override { expr = nullptr; } + bool is_marked_for_strip () const override { return expr == nullptr; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -185,14 +229,23 @@ public: // Copy constructor with clone ExprStmtWithBlock (ExprStmtWithBlock const &other) - : ExprStmt (other), expr (other.expr->clone_expr_with_block ()) - {} + : ExprStmt (other) + { + // guard to prevent null dereference (only required if error state) + if (other.expr != nullptr) + expr = other.expr->clone_expr_with_block (); + } // Overloaded assignment operator to clone ExprStmtWithBlock &operator= (ExprStmtWithBlock const &other) { ExprStmt::operator= (other); - expr = other.expr->clone_expr_with_block (); + + // guard to prevent null dereference (only required if error state) + if (other.expr != nullptr) + expr = other.expr->clone_expr_with_block (); + else + expr = nullptr; return *this; } @@ -203,6 +256,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if expr is null, so base stripping on that. + void mark_for_strip () override { expr = nullptr; } + bool is_marked_for_strip () const override { return expr == nullptr; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index b396a44..78b57eb 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -177,13 +177,6 @@ class ParenthesisedType : public TypeNoBounds protected: /* Use covariance to implement clone function as returning this object rather * than base */ - ParenthesisedType *clone_type_impl () const override - { - return new ParenthesisedType (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ ParenthesisedType *clone_type_no_bounds_impl () const override { return new ParenthesisedType (*this); @@ -242,13 +235,6 @@ class ImplTraitTypeOneBound : public TypeNoBounds protected: /* Use covariance to implement clone function as returning this object rather * than base */ - ImplTraitTypeOneBound *clone_type_impl () const override - { - return new ImplTraitTypeOneBound (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ ImplTraitTypeOneBound *clone_type_no_bounds_impl () const override { return new ImplTraitTypeOneBound (*this); @@ -278,13 +264,6 @@ class TraitObjectTypeOneBound : public TypeNoBounds protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TraitObjectTypeOneBound *clone_type_impl () const override - { - return new TraitObjectTypeOneBound (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ TraitObjectTypeOneBound *clone_type_no_bounds_impl () const override { return new TraitObjectTypeOneBound (*this); @@ -362,10 +341,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - TupleType *clone_type_impl () const override { return new TupleType (*this); } - - /* Use covariance to implement clone function as returning this object rather - * than base */ TupleType *clone_type_no_bounds_impl () const override { return new TupleType (*this); @@ -382,10 +357,6 @@ class NeverType : public TypeNoBounds protected: /* Use covariance to implement clone function as returning this object rather * than base */ - NeverType *clone_type_impl () const override { return new NeverType (*this); } - - /* Use covariance to implement clone function as returning this object rather - * than base */ NeverType *clone_type_no_bounds_impl () const override { return new NeverType (*this); @@ -455,13 +426,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - RawPointerType *clone_type_impl () const override - { - return new RawPointerType (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ RawPointerType *clone_type_no_bounds_impl () const override { return new RawPointerType (*this); @@ -522,13 +486,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - ReferenceType *clone_type_impl () const override - { - return new ReferenceType (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ ReferenceType *clone_type_no_bounds_impl () const override { return new ReferenceType (*this); @@ -577,10 +534,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - ArrayType *clone_type_impl () const override { return new ArrayType (*this); } - - /* Use covariance to implement clone function as returning this object rather - * than base */ ArrayType *clone_type_no_bounds_impl () const override { return new ArrayType (*this); @@ -627,10 +580,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - SliceType *clone_type_impl () const override { return new SliceType (*this); } - - /* Use covariance to implement clone function as returning this object rather - * than base */ SliceType *clone_type_no_bounds_impl () const override { return new SliceType (*this); @@ -647,13 +596,6 @@ class InferredType : public TypeNoBounds protected: /* Use covariance to implement clone function as returning this object rather * than base */ - InferredType *clone_type_impl () const override - { - return new InferredType (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ InferredType *clone_type_no_bounds_impl () const override { return new InferredType (*this); @@ -699,9 +641,12 @@ public: // Copy constructor with clone MaybeNamedParam (MaybeNamedParam const &other) - : param_type (other.param_type->clone_type ()), - param_kind (other.param_kind), name (other.name), locus (other.locus) - {} + : param_kind (other.param_kind), name (other.name), locus (other.locus) + { + // guard to prevent null dereference + if (other.param_type != nullptr) + param_type = other.param_type->clone_type (); + } ~MaybeNamedParam () = default; @@ -710,9 +655,14 @@ public: { name = other.name; param_kind = other.param_kind; - param_type = other.param_type->clone_type (); locus = other.locus; + // guard to prevent null dereference + if (other.param_type != nullptr) + param_type = other.param_type->clone_type (); + else + param_type = nullptr; + return *this; } @@ -773,10 +723,12 @@ public: BareFunctionType (BareFunctionType const &other) : for_lifetimes (other.for_lifetimes), function_qualifiers (other.function_qualifiers), params (other.params), - is_variadic (other.is_variadic), - return_type (other.return_type->clone_type_no_bounds ()), - locus (other.locus) - {} + is_variadic (other.is_variadic), locus (other.locus) + { + // guard to prevent null dereference + if (other.return_type != nullptr) + return_type = other.return_type->clone_type_no_bounds (); + } // Overload assignment operator to deep copy BareFunctionType &operator= (BareFunctionType const &other) @@ -785,9 +737,14 @@ public: function_qualifiers = other.function_qualifiers; params = other.params; is_variadic = other.is_variadic; - return_type = other.return_type->clone_type_no_bounds (); locus = other.locus; + // guard to prevent null dereference + if (other.return_type != nullptr) + return_type = other.return_type->clone_type_no_bounds (); + else + return_type = nullptr; + return *this; } @@ -804,13 +761,6 @@ public: protected: /* Use covariance to implement clone function as returning this object rather * than base */ - BareFunctionType *clone_type_impl () const override - { - return new BareFunctionType (*this); - } - - /* Use covariance to implement clone function as returning this object rather - * than base */ BareFunctionType *clone_type_no_bounds_impl () const override { return new BareFunctionType (*this); diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 4a39be3..a7d2a1a 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -1,8 +1,217 @@ #include "rust-macro-expand.h" #include "rust-ast-full.h" // is full really required? +#include "rust-ast-visitor.h" namespace Rust { + // Visitor used to expand attributes. + class AttrVisitor : public AST::ASTVisitor { + private: + MacroExpander& expander; + + public: + AttrVisitor(MacroExpander& expander) : expander(expander) {} + + 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 {} + void visit(AST::TupleExpr& expr) override {} + void visit(AST::TupleIndexExpr& expr) override {} + void visit(AST::StructExprStruct& expr) override {} + void visit(AST::StructExprFieldIdentifier& field) override {} + void visit(AST::StructExprFieldIdentifierValue& field) override {} + void visit(AST::StructExprFieldIndexValue& field) override {} + void visit(AST::StructExprStructFields& expr) override {} + void visit(AST::StructExprStructBase& expr) override {} + void visit(AST::StructExprTuple& expr) override {} + void visit(AST::StructExprUnit& expr) override {} + void visit(AST::EnumExprFieldIdentifier& field) override {} + void visit(AST::EnumExprFieldIdentifierValue& field) override {} + void visit(AST::EnumExprFieldIndexValue& field) override {} + void visit(AST::EnumExprStruct& expr) override {} + void visit(AST::EnumExprTuple& expr) override {} + void visit(AST::EnumExprFieldless& expr) override {} + void visit(AST::CallExpr& expr) override {} + void visit(AST::MethodCallExpr& expr) override {} + void visit(AST::FieldAccessExpr& expr) override {} + void visit(AST::ClosureExprInner& expr) override {} + 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 {} + void visit(AST::ReturnExpr& expr) override {} + void visit(AST::UnsafeBlockExpr& expr) override {} + void visit(AST::LoopExpr& expr) override {} + void visit(AST::WhileLoopExpr& expr) override {} + void visit(AST::WhileLetLoopExpr& expr) override {} + void visit(AST::ForLoopExpr& expr) override {} + void visit(AST::IfExpr& expr) override {} + void visit(AST::IfExprConseqElse& expr) override {} + void visit(AST::IfExprConseqIf& expr) override {} + void visit(AST::IfExprConseqIfLet& expr) override {} + void visit(AST::IfLetExpr& expr) override {} + void visit(AST::IfLetExprConseqElse& expr) override {} + void visit(AST::IfLetExprConseqIf& expr) override {} + void visit(AST::IfLetExprConseqIfLet& expr) override {} + void visit(AST::MatchExpr& expr) override {} + 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::UseDeclaration& use_decl) override {} + 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::Union& union_item) override {} + void visit(AST::ConstantItem& const_item) override {} + void visit(AST::StaticItem& static_item) override {} + void visit(AST::TraitItemFunc& item) override {} + void visit(AST::TraitItemMethod& item) override {} + void visit(AST::TraitItemConst& item) override {} + void visit(AST::TraitItemType& item) override {} + void visit(AST::Trait& trait) override {} + void visit(AST::InherentImpl& impl) override {} + void visit(AST::TraitImpl& impl) override {} + void visit(AST::ExternalStaticItem& item) override {} + void visit(AST::ExternalFunctionItem& item) override {} + void visit(AST::ExternBlock& block) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(block.get_outer_attrs()); + if (expander.fails_cfg(block.get_outer_attrs())) { + block.mark_for_strip(); + return; + } + + // strip test based on inner attrs + expander.expand_cfg_attrs(block.get_inner_attrs()); + if (expander.fails_cfg(block.get_inner_attrs())) { + block.mark_for_strip(); + return; + } + + // strip external items if required + auto& extern_items = block.get_extern_items(); + for (auto 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); + else + i++; + + } + } + + 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::MetaItemPath& meta_item) override {} + void visit(AST::MetaItemSeq& meta_item) override {} + void visit(AST::MetaWord& meta_item) override {} + void visit(AST::MetaNameValueStr& meta_item) override {} + void visit(AST::MetaListPaths& meta_item) override {} + void visit(AST::MetaListNameValueStr& meta_item) override {} + + void visit(AST::LiteralPattern& pattern) override {} + void visit(AST::IdentifierPattern& pattern) override {} + void visit(AST::WildcardPattern& pattern) override {} + void visit(AST::RangePatternBoundLiteral& bound) override {} + void visit(AST::RangePatternBoundPath& bound) override {} + void visit(AST::RangePatternBoundQualPath& bound) override {} + void visit(AST::RangePattern& pattern) override {} + void visit(AST::ReferencePattern& pattern) override {} + void visit(AST::StructPatternFieldTuplePat& field) override {} + void visit(AST::StructPatternFieldIdentPat& field) override {} + void visit(AST::StructPatternFieldIdent& field) override {} + void visit(AST::StructPattern& pattern) override {} + void visit(AST::TupleStructItemsNoRange& tuple_items) override {} + void visit(AST::TupleStructItemsRange& tuple_items) override {} + void visit(AST::TupleStructPattern& pattern) override {} + void visit(AST::TuplePatternItemsMultiple& tuple_items) override {} + void visit(AST::TuplePatternItemsRanged& tuple_items) override {} + void visit(AST::TuplePattern& pattern) override {} + 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::TraitBound& bound) override {} + void visit(AST::ImplTraitType& type) override {} + void visit(AST::TraitObjectType& type) override {} + void visit(AST::ParenthesisedType& type) override {} + void visit(AST::ImplTraitTypeOneBound& type) override {} + void visit(AST::TraitObjectTypeOneBound& type) override {} + void visit(AST::TupleType& type) override {} + void visit(AST::NeverType& type) override {} + void visit(AST::RawPointerType& type) override {} + void visit(AST::ReferenceType& type) override {} + void visit(AST::ArrayType& type) override {} + void visit(AST::SliceType& type) override {} + void visit(AST::InferredType& type) override {} + void visit(AST::BareFunctionType& type) override {} + }; + void MacroExpander::expand_invoc(std::unique_ptr<AST::MacroInvocation>& invoc) { /* if current expansion depth > recursion limit, create an error (maybe fatal * error) and return */ @@ -24,7 +233,7 @@ namespace Rust { - derive container macro - unreachable*/ } - /* Determines whether any cfg predicate is false and hence item with attributes should + /* Determines whether any cfg predicate is false and hence item with attributes should * be stripped. */ bool MacroExpander::fails_cfg(std::vector<AST::Attribute>& attrs) { for (auto& attr : attrs) { @@ -81,6 +290,14 @@ namespace Rust { } // expand module attributes? + // expand attributes recursively + AttrVisitor attr_visitor(*this); + for (auto& i : crate.items) { + i->accept_vis(attr_visitor); + } + // TODO: should recursive attribute and macro expansion be done in the same transversal? Or in + // separate ones like currently? + // expand module tree recursively // post-process diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 7940df7..fd50bf1 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -626,8 +626,7 @@ Session::injection (AST::Crate &crate) * rustc also has a "quote" macro that is defined differently and is * supposedly not stable so eh. */ /* TODO: actually implement injection of these macros. In particular, derive - * macros, cfg, and - * test should be prioritised since they seem to be used the most. */ + * macros, cfg, and test should be prioritised since they seem to be used the most. */ // crate injection std::vector<std::string> names; |