diff options
-rw-r--r-- | gcc/rust/analysis/rust-type-resolution.cc | 24 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast-full-test.cc | 12 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast.h | 20 | ||||
-rw-r--r-- | gcc/rust/ast/rust-item.h | 239 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 86 | ||||
-rw-r--r-- | gcc/rust/expand/rust-macro-expand.cc | 177 | ||||
-rw-r--r-- | gcc/rust/parse/rust-parse-impl.h | 105 | ||||
-rw-r--r-- | gcc/rust/parse/rust-parse.h | 3 |
8 files changed, 498 insertions, 168 deletions
diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc index 3503a83..aef02ce 100644 --- a/gcc/rust/analysis/rust-type-resolution.cc +++ b/gcc/rust/analysis/rust-type-resolution.cc @@ -161,7 +161,7 @@ TypeResolution::visit (AST::IdentifierExpr &ident_expr) bool ok = scope.LookupType (ident_expr.ident, &type); if (!ok) { - rust_error_at (ident_expr.locus, "unknown identifier"); + rust_error_at (ident_expr.get_locus (), "unknown identifier"); return; } @@ -272,7 +272,7 @@ TypeResolution::visit (AST::LiteralExpr &expr) if (type.empty ()) { - rust_error_at (expr.locus, "unknown literal: %s", + rust_error_at (expr.get_locus (), "unknown literal: %s", expr.literal.as_string ().c_str ()); return; } @@ -282,7 +282,7 @@ TypeResolution::visit (AST::LiteralExpr &expr) if (ok) typeBuffer.push_back (val); else - rust_error_at (expr.locus, "unknown literal type: %s", type.c_str ()); + rust_error_at (expr.get_locus (), "unknown literal type: %s", type.c_str ()); } void @@ -318,7 +318,7 @@ TypeResolution::visit (AST::ArithmeticOrLogicalExpr &expr) expr.visit_lhs (*this); if (typeBuffer.size () <= before) { - rust_error_at (expr.locus, "unable to determine lhs type"); + rust_error_at (expr.get_locus (), "unable to determine lhs type"); return; } @@ -329,7 +329,7 @@ TypeResolution::visit (AST::ArithmeticOrLogicalExpr &expr) expr.visit_rhs (*this); if (typeBuffer.size () <= before) { - rust_error_at (expr.locus, "unable to determine rhs type"); + rust_error_at (expr.get_locus (), "unable to determine rhs type"); return; } @@ -361,7 +361,7 @@ TypeResolution::visit (AST::AssignmentExpr &expr) expr.visit_lhs (*this); if (typeBuffer.size () <= before) { - rust_error_at (expr.locus, "unable to determine lhs type"); + rust_error_at (expr.get_locus (), "unable to determine lhs type"); return; } @@ -372,7 +372,7 @@ TypeResolution::visit (AST::AssignmentExpr &expr) expr.visit_rhs (*this); if (typeBuffer.size () <= before) { - rust_error_at (expr.locus, "unable to determine rhs type"); + rust_error_at (expr.get_locus (), "unable to determine rhs type"); return; } @@ -583,7 +583,7 @@ TypeResolution::visit (AST::CallExpr &expr) auto numInferedParams = typeBuffer.size () - before; if (numInferedParams != expr.params.size ()) { - rust_error_at (expr.locus, "Failed to infer all parameters"); + rust_error_at (expr.get_locus (), "Failed to infer all parameters"); return; } @@ -768,14 +768,14 @@ TypeResolution::visit (AST::Function &function) for (auto ¶m : function.function_params) { - if (!isTypeInScope (param.type.get (), param.locus)) + if (!isTypeInScope (param.type.get (), param.get_locus ())) return; auto before = letPatternBuffer.size (); param.param_name->accept_vis (*this); if (letPatternBuffer.size () <= before) { - rust_error_at (param.locus, "failed to analyse parameter name"); + rust_error_at (param.get_locus (), "failed to analyse parameter name"); return; } @@ -787,7 +787,7 @@ TypeResolution::visit (AST::Function &function) // ensure the return type is resolved if (function.has_function_return_type ()) { - if (!isTypeInScope (function.return_type.get (), function.locus)) + if (!isTypeInScope (function.return_type.get (), function.get_locus ())) return; } @@ -1006,7 +1006,7 @@ TypeResolution::visit (AST::LetStmt &stmt) scope.InsertLocal (stmt.as_string (), &stmt); if (!stmt.has_init_expr () && !stmt.has_type ()) { - rust_error_at (stmt.locus, + rust_error_at (stmt.get_locus (), "E0282: type annotations or init expression needed"); return; } diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc index 1e95e47..8071226 100644 --- a/gcc/rust/ast/rust-ast-full-test.cc +++ b/gcc/rust/ast/rust-ast-full-test.cc @@ -678,33 +678,23 @@ Method::as_string () const else { for (const auto ¶m : function_params) - { str += "\n " + param.as_string (); - } } str += "\n Return type: "; if (has_return_type ()) - { str += return_type->as_string (); - } else - { str += "none (void)"; - } str += "\n Where clause: "; if (has_where_clause ()) - { str += where_clause.as_string (); - } else - { str += "none"; - } str += "\n Block expr (body): \n "; - str += expr->as_string (); + str += function_body->as_string (); return str; } diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 4c4b043..e0f46ac 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1221,21 +1221,12 @@ class TraitItem // NOTE: all children should have outer attributes protected: - // Constructor - /*TraitItem(std::vector<Attribute> outer_attrs = std::vector<Attribute>()) - : outer_attrs(std::move(outer_attrs)) {}*/ - // Clone function implementation as pure virtual method virtual TraitItem *clone_trait_item_impl () const = 0; public: virtual ~TraitItem () {} - // Returns whether TraitItem has outer attributes. - /*bool has_outer_attrs() const { - return !outer_attrs.empty(); - }*/ - // Unique pointer custom clone function std::unique_ptr<TraitItem> clone_trait_item () const { @@ -1245,6 +1236,9 @@ public: virtual std::string as_string () const = 0; virtual void accept_vis (ASTVisitor &vis) = 0; + + virtual void mark_for_strip () = 0; + virtual bool is_marked_for_strip () const = 0; }; /* Abstract base class for items used within an inherent impl block (the impl @@ -1267,6 +1261,9 @@ public: virtual std::string as_string () const = 0; virtual void accept_vis (ASTVisitor &vis) = 0; + + virtual void mark_for_strip () = 0; + virtual bool is_marked_for_strip () const = 0; }; // Abstract base class for items used in a trait impl @@ -1276,7 +1273,7 @@ protected: virtual TraitImplItem *clone_trait_impl_item_impl () const = 0; public: - virtual ~TraitImplItem (){}; + virtual ~TraitImplItem () {}; // Unique pointer custom clone function std::unique_ptr<TraitImplItem> clone_trait_impl_item () const @@ -1287,6 +1284,9 @@ public: virtual std::string as_string () const = 0; virtual void accept_vis (ASTVisitor &vis) = 0; + + virtual void mark_for_strip () = 0; + virtual bool is_marked_for_strip () const = 0; }; // Abstract base class for an item used inside an extern block diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 8542638..a56d1b5 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -434,31 +434,45 @@ public: // A function parameter struct FunctionParam { +private: + std::vector<Attribute> outer_attrs; + Location locus; + public: std::unique_ptr<Pattern> param_name; std::unique_ptr<Type> type; - Location locus; - FunctionParam (std::unique_ptr<Pattern> param_name, - std::unique_ptr<Type> param_type, Location locus) - : param_name (std::move (param_name)), type (std::move (param_type)), - locus (locus) + std::unique_ptr<Type> param_type, std::vector<Attribute> outer_attrs, Location locus) + : outer_attrs (std::move (outer_attrs)), locus (locus), + param_name (std::move (param_name)), type (std::move (param_type)) {} // Copy constructor uses clone - FunctionParam (FunctionParam const &other) - : param_name (other.param_name->clone_pattern ()), - type (other.type->clone_type ()), locus (other.locus) - {} + FunctionParam (FunctionParam const &other) : locus (other.locus) + { + // guard to prevent nullptr dereference + if (other.param_name != nullptr) + param_name = other.param_name->clone_pattern (); + if (other.type != nullptr) + type = other.type->clone_type (); + } // Overload assignment operator to use clone FunctionParam &operator= (FunctionParam const &other) { - param_name = other.param_name->clone_pattern (); - type = other.type->clone_type (); locus = other.locus; + // guard to prevent nullptr dereference + if (other.param_name != nullptr) + param_name = other.param_name->clone_pattern (); + else + param_name = nullptr; + if (other.type != nullptr) + type = other.type->clone_type (); + else + type = nullptr; + return *this; } @@ -472,12 +486,16 @@ public: // Creates an error FunctionParam. static FunctionParam create_error () { - return FunctionParam (nullptr, nullptr, Location ()); + return FunctionParam (nullptr, nullptr, {}, Location ()); } std::string as_string () const; Location get_locus () const { return locus; } + + // TODO: seems kinda dodgy. Think of better way. + std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } }; // Visibility of item - if the item has it, then it is some form of public @@ -596,7 +614,7 @@ class Method : public InherentImplItem, public TraitImplItem // bool has_where_clause; WhereClause where_clause; - std::unique_ptr<BlockExpr> expr; + std::unique_ptr<BlockExpr> function_body; Location locus; @@ -604,7 +622,7 @@ public: // Returns whether the method is in an error state. bool is_error () const { - return expr == nullptr || method_name.empty () || self_param.is_error (); + return function_body == nullptr || method_name.empty () || self_param.is_error (); } // Creates an error state method. @@ -614,7 +632,7 @@ public: std::vector<std::unique_ptr<GenericParam>> (), SelfParam::create_error (), std::vector<FunctionParam> (), nullptr, WhereClause::create_empty (), nullptr, - Visibility::create_error (), std::vector<Attribute> ()); + Visibility::create_error (), std::vector<Attribute> (), {}); } // Returns whether the method has generic parameters. @@ -638,7 +656,7 @@ public: SelfParam self_param, std::vector<FunctionParam> function_params, std::unique_ptr<Type> return_type, WhereClause where_clause, std::unique_ptr<BlockExpr> function_body, Visibility vis, - std::vector<Attribute> outer_attrs, Location locus = Location ()) + std::vector<Attribute> outer_attrs, Location locus) : outer_attrs (std::move (outer_attrs)), vis (std::move (vis)), qualifiers (std::move (qualifiers)), method_name (std::move (method_name)), @@ -646,7 +664,7 @@ public: self_param (std::move (self_param)), function_params (std::move (function_params)), return_type (std::move (return_type)), - where_clause (std::move (where_clause)), expr (std::move (function_body)), + where_clause (std::move (where_clause)), function_body (std::move (function_body)), locus (locus) {} @@ -657,10 +675,16 @@ public: : outer_attrs (other.outer_attrs), vis (other.vis), qualifiers (other.qualifiers), method_name (other.method_name), self_param (other.self_param), function_params (other.function_params), - return_type (other.return_type->clone_type ()), - where_clause (other.where_clause), expr (other.expr->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 ()); @@ -675,11 +699,21 @@ public: qualifiers = other.qualifiers; self_param = other.self_param; function_params = other.function_params; - return_type = other.return_type->clone_type (); where_clause = other.where_clause; - expr = other.expr->clone_block_expr (); 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 ()); @@ -695,6 +729,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 */ @@ -2268,9 +2306,12 @@ public: TraitFunctionDecl (TraitFunctionDecl const &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) { + // guard to prevent nullptr dereference + if (other.return_type != nullptr) + return_type = other.return_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 ()); @@ -2284,9 +2325,14 @@ public: function_name = other.function_name; qualifiers = other.qualifiers; function_params = other.function_params; - return_type = other.return_type->clone_type (); where_clause = other.where_clause; + // guard to prevent nullptr dereference + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + else + return_type = nullptr; + generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); @@ -2299,6 +2345,14 @@ public: TraitFunctionDecl &operator= (TraitFunctionDecl &&other) = default; std::string as_string () const; + + // Invalid if function name is empty, so base stripping on that. + void mark_for_strip () { function_name = ""; } + bool is_marked_for_strip () const { return function_name.empty (); } + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<FunctionParam> &get_function_params () { return function_params; } + const std::vector<FunctionParam> &get_function_params () const { return function_params; } }; // Actual trait item function declaration within traits @@ -2323,6 +2377,7 @@ public: TraitItemFunc (TraitItemFunc const &other) : outer_attrs (other.outer_attrs), decl (other.decl), locus (other.locus) { + // guard to prevent null dereference if (other.block_expr != nullptr) block_expr = other.block_expr->clone_block_expr (); } @@ -2334,8 +2389,12 @@ public: outer_attrs = other.outer_attrs; decl = other.decl; locus = other.locus; + + // guard to prevent null dereference if (other.block_expr != nullptr) block_expr = other.block_expr->clone_block_expr (); + else + block_expr = nullptr; return *this; } @@ -2350,6 +2409,17 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if trait decl is empty, so base stripping on that. + void mark_for_strip () override { decl.mark_for_strip (); } + bool is_marked_for_strip () const override { return decl.is_marked_for_strip (); } + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } + + std::vector<FunctionParam> &get_function_params () { return decl.get_function_params (); } + const std::vector<FunctionParam> &get_function_params () const { return decl.get_function_params (); } + protected: // Clone function implementation as (not pure) virtual method TraitItemFunc *clone_trait_item_impl () const override @@ -2416,9 +2486,12 @@ public: TraitMethodDecl (TraitMethodDecl const &other) : qualifiers (other.qualifiers), function_name (other.function_name), self_param (other.self_param), function_params (other.function_params), - return_type (other.return_type->clone_type ()), where_clause (other.where_clause) { + // guard to prevent nullptr dereference + if (other.return_type != nullptr) + return_type = other.return_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 ()); @@ -2433,9 +2506,14 @@ public: qualifiers = other.qualifiers; self_param = other.self_param; function_params = other.function_params; - return_type = other.return_type->clone_type (); where_clause = other.where_clause; + // guard to prevent nullptr dereference + if (other.return_type != nullptr) + return_type = other.return_type->clone_type (); + else + return_type = nullptr; + generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) generic_params.push_back (e->clone_generic_param ()); @@ -2448,6 +2526,14 @@ public: TraitMethodDecl &operator= (TraitMethodDecl &&other) = default; std::string as_string () const; + + // Invalid if method name is empty, so base stripping on that. + void mark_for_strip () { function_name = ""; } + bool is_marked_for_strip () const { return function_name.empty (); } + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<FunctionParam> &get_function_params () { return function_params; } + const std::vector<FunctionParam> &get_function_params () const { return function_params; } }; // Actual trait item method declaration within traits @@ -2471,8 +2557,12 @@ public: // Copy constructor with clone TraitItemMethod (TraitItemMethod const &other) : outer_attrs (other.outer_attrs), decl (other.decl), - block_expr (other.block_expr->clone_block_expr ()), locus (other.locus) - {} + locus (other.locus) + { + // guard to prevent null dereference + if (other.block_expr != nullptr) + block_expr = other.block_expr->clone_block_expr (); + } // Overloaded assignment operator to clone TraitItemMethod &operator= (TraitItemMethod const &other) @@ -2480,9 +2570,14 @@ public: TraitItem::operator= (other); outer_attrs = other.outer_attrs; decl = other.decl; - block_expr = other.block_expr->clone_block_expr (); locus = other.locus; + // guard to prevent null dereference + if (other.block_expr != nullptr) + block_expr = other.block_expr->clone_block_expr (); + else + block_expr = nullptr; + return *this; } @@ -2496,6 +2591,17 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if trait decl is empty, so base stripping on that. + void mark_for_strip () override { decl.mark_for_strip (); } + bool is_marked_for_strip () const override { return decl.is_marked_for_strip (); } + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } + + std::vector<FunctionParam> &get_function_params () { return decl.get_function_params (); } + const std::vector<FunctionParam> &get_function_params () const { return decl.get_function_params (); } + protected: // Clone function implementation as (not pure) virtual method TraitItemMethod *clone_trait_item_impl () const override @@ -2529,10 +2635,16 @@ public: // Copy constructor with clones TraitItemConst (TraitItemConst const &other) - : outer_attrs (other.outer_attrs), name (other.name), - type (other.type->clone_type ()), expr (other.expr->clone_expr ()), - locus (other.locus) - {} + : outer_attrs (other.outer_attrs), name (other.name), locus (other.locus) + { + // guard to prevent null dereference + if (other.expr != nullptr) + expr = other.expr->clone_expr (); + + // guard to prevent null dereference (only for error state) + if (other.type != nullptr) + type = other.type->clone_type (); + } // Overloaded assignment operator to clone TraitItemConst &operator= (TraitItemConst const &other) @@ -2540,10 +2652,20 @@ public: TraitItem::operator= (other); outer_attrs = other.outer_attrs; name = other.name; - type = other.type->clone_type (); - expr = other.expr->clone_expr (); locus = other.locus; + // guard to prevent null dereference + if (other.expr != nullptr) + expr = other.expr->clone_expr (); + else + expr = nullptr; + + // guard to prevent null dereference (only for error state) + if (other.type != nullptr) + type = other.type->clone_type (); + else + type = nullptr; + return *this; } @@ -2557,6 +2679,14 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if type is null, so base stripping on that. + void mark_for_strip () override { type = nullptr; } + bool is_marked_for_strip () const override { return type == nullptr; } + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } + protected: // Clone function implementation as (not pure) virtual method TraitItemConst *clone_trait_item_impl () const override @@ -2625,6 +2755,14 @@ public: void accept_vis (ASTVisitor &vis) override; + // Invalid if name is empty, so base stripping on that. + void mark_for_strip () override { name = ""; } + bool is_marked_for_strip () const override { return name.empty (); } + + // TODO: this mutable getter seems really dodgy. Think up better way. + std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } + protected: // Clone function implementation as (not pure) virtual method TraitItemType *clone_trait_item_impl () const override @@ -2651,6 +2789,8 @@ class Trait : public VisItem // bool has_where_clause; WhereClause where_clause; + std::vector<Attribute> inner_attrs; + // bool has_trait_items; std::vector<std::unique_ptr<TraitItem>> trait_items; @@ -2671,25 +2811,28 @@ public: // Returns whether trait has trait items. bool has_trait_items () const { return !trait_items.empty (); } + // Returns whether trait has inner attributes. + bool has_inner_attrs () const { return !inner_attrs.empty (); } + // Mega-constructor Trait (Identifier name, bool is_unsafe, std::vector<std::unique_ptr<GenericParam>> generic_params, std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds, WhereClause where_clause, std::vector<std::unique_ptr<TraitItem>> trait_items, Visibility vis, - std::vector<Attribute> outer_attrs, Location locus) + std::vector<Attribute> outer_attrs, std::vector<Attribute> inner_attrs, Location locus) : VisItem (std::move (vis), std::move (outer_attrs)), has_unsafe (is_unsafe), name (std::move (name)), generic_params (std::move (generic_params)), type_param_bounds (std::move (type_param_bounds)), - where_clause (std::move (where_clause)), + where_clause (std::move (where_clause)), inner_attrs (std::move (inner_attrs)), trait_items (std::move (trait_items)), locus (locus) {} // Copy constructor with vector clone Trait (Trait const &other) : VisItem (other), has_unsafe (other.has_unsafe), name (other.name), - where_clause (other.where_clause), locus (other.locus) + where_clause (other.where_clause), inner_attrs (other.inner_attrs), locus (other.locus) { generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) @@ -2711,6 +2854,7 @@ public: name = other.name; has_unsafe = other.has_unsafe; where_clause = other.where_clause; + inner_attrs = other.inner_attrs; locus = other.locus; generic_params.reserve (other.generic_params.size ()); @@ -2740,6 +2884,13 @@ public: void mark_for_strip () override { name = ""; } bool is_marked_for_strip () const override { return name.empty (); } + // 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; } + + const std::vector<std::unique_ptr<TraitItem>>& get_trait_items () const { return trait_items; } + std::vector<std::unique_ptr<TraitItem>>& get_trait_items () { return trait_items; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2783,6 +2934,10 @@ public: void mark_for_strip () override { trait_type = nullptr; } bool is_marked_for_strip () const override { return trait_type == nullptr; } + // 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: // Mega-constructor Impl (std::vector<std::unique_ptr<GenericParam>> generic_params, @@ -2886,6 +3041,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: think of better way to do this + const std::vector<std::unique_ptr<InherentImplItem>>& get_impl_items () const { return impl_items; } + std::vector<std::unique_ptr<InherentImplItem>>& get_impl_items () { return impl_items; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2958,6 +3117,10 @@ public: void accept_vis (ASTVisitor &vis) override; + // TODO: think of better way to do this + const std::vector<std::unique_ptr<TraitImplItem>>& get_impl_items () const { return impl_items; } + std::vector<std::unique_ptr<TraitImplItem>>& get_impl_items () { return impl_items; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 6374a45..af0f454 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -173,10 +173,10 @@ Compilation::visit (AST::IdentifierExpr &ident_expr) Bvariable *var = NULL; if (!scope.LookupVar (ident_expr.as_string (), &var)) { - rust_fatal_error (ident_expr.locus, "unknown var"); + rust_fatal_error (ident_expr.get_locus (), "unknown var"); return; } - exprs.push_back (backend->var_expression (var, ident_expr.locus)); + exprs.push_back (backend->var_expression (var, ident_expr.get_locus ())); } void @@ -199,7 +199,7 @@ Compilation::visit (AST::PathInExpression &path) if (scope.LookupFunction (path.as_string (), &fn)) { auto expr - = backend->function_code_expression (fn, path.get_locus_slow ()); + = backend->function_code_expression (fn, path.get_locus ()); exprs.push_back (expr); translatedType = scope.GetFnRetType (fn); return; @@ -221,14 +221,14 @@ Compilation::visit (AST::TypePath &path) { if (path.segments.size () > 1) { - rust_error_at (path.locus, "unable to compile multi segment types yet"); + rust_error_at (path.get_locus (), "unable to compile multi segment types yet"); return; } Btype *type = NULL; if (!scope.LookupType (path.as_string (), &type)) { - rust_error_at (path.locus, "unknown type"); + rust_error_at (path.get_locus (), "unknown type"); return; } translatedType = type; @@ -254,16 +254,16 @@ Compilation::visit (AST::LiteralExpr &expr) case AST::Literal::FLOAT: compiled - = compileFloatLiteral (expr.as_string (), expr.get_locus_slow ()); + = compileFloatLiteral (expr.as_string (), expr.get_locus ()); break; case AST::Literal::INT: compiled - = compileIntegerLiteral (expr.as_string (), expr.get_locus_slow ()); + = compileIntegerLiteral (expr.as_string (), expr.get_locus ()); break; default: - rust_fatal_error (expr.get_locus_slow (), "unknown literal"); + rust_fatal_error (expr.get_locus (), "unknown literal"); return; } @@ -311,11 +311,11 @@ Compilation::visit (AST::NegationExpr &expr) op = OPERATOR_NOT; break; default: - rust_fatal_error (expr.get_locus_slow (), "failed to compile operator"); + rust_fatal_error (expr.get_locus (), "failed to compile operator"); return; } - auto unary = backend->unary_expression (op, root, expr.get_locus_slow ()); + auto unary = backend->unary_expression (op, root, expr.get_locus ()); exprs.push_back (unary); } @@ -372,12 +372,12 @@ Compilation::visit (AST::ArithmeticOrLogicalExpr &expr) op = OPERATOR_RSHIFT; break; default: - rust_fatal_error (expr.get_locus_slow (), "failed to compile operator"); + rust_fatal_error (expr.get_locus (), "failed to compile operator"); return; } auto binExpr - = backend->binary_expression (op, lhs, rhs, expr.get_locus_slow ()); + = backend->binary_expression (op, lhs, rhs, expr.get_locus ()); exprs.push_back (binExpr); } @@ -422,12 +422,12 @@ Compilation::visit (AST::ComparisonExpr &expr) op = OPERATOR_LE; break; default: - rust_fatal_error (expr.get_locus_slow (), "failed to compile operator"); + rust_fatal_error (expr.get_locus (), "failed to compile operator"); return; } auto compExpr - = backend->binary_expression (op, lhs, rhs, expr.get_locus_slow ()); + = backend->binary_expression (op, lhs, rhs, expr.get_locus ()); exprs.push_back (compExpr); } @@ -460,12 +460,12 @@ Compilation::visit (AST::LazyBooleanExpr &expr) op = OPERATOR_ANDAND; break; default: - rust_fatal_error (expr.get_locus_slow (), "failed to compile operator"); + rust_fatal_error (expr.get_locus (), "failed to compile operator"); return; } auto compExpr - = backend->binary_expression (op, lhs, rhs, expr.get_locus_slow ()); + = backend->binary_expression (op, lhs, rhs, expr.get_locus ()); exprs.push_back (compExpr); } @@ -493,7 +493,7 @@ Compilation::visit (AST::AssignmentExpr &expr) } auto s = backend->assignment_statement (scope.GetCurrentFndecl (), lhs, rhs, - expr.get_locus_slow ()); + expr.get_locus ()); scope.AddStatement (s); } @@ -582,14 +582,14 @@ Compilation::visit (AST::StructExprStructFields &expr) AST::StructStruct *decl = NULL; if (!scope.LookupStructDecl (expr.get_struct_name ().as_string (), &decl)) { - rust_error_at (expr.get_locus_slow (), "unknown type"); + rust_error_at (expr.get_locus (), "unknown type"); return; } Btype *structType = NULL; if (!scope.LookupType (expr.get_struct_name ().as_string (), &structType)) { - rust_fatal_error (expr.get_locus_slow (), "unknown type"); + rust_fatal_error (expr.get_locus (), "unknown type"); return; } @@ -601,10 +601,10 @@ Compilation::visit (AST::StructExprStructFields &expr) for (auto &field : expr.fields) { Bexpression *value = NULL; - VISIT_POP (expr.get_locus_slow (), field, value, exprs); + VISIT_POP (expr.get_locus (), field, value, exprs); if (value == NULL) { - rust_fatal_error (expr.get_locus_slow (), + rust_fatal_error (expr.get_locus (), "failed to compile value to struct"); return; } @@ -614,7 +614,7 @@ Compilation::visit (AST::StructExprStructFields &expr) structBuffer.pop_back (); auto cons = backend->constructor_expression (structType, constructor, - expr.get_locus_slow ()); + expr.get_locus ()); exprs.push_back (cons); } @@ -674,7 +674,7 @@ Compilation::visit (AST::CallExpr &expr) } auto call = backend->call_expression (scope.GetCurrentFndecl (), fn, args, - NULL, expr.locus); + NULL, expr.get_locus ()); exprs.push_back (call); } @@ -751,7 +751,7 @@ Compilation::visit (AST::ReturnExpr &expr) std::vector<Bexpression *> retstmts; retstmts.push_back (ret); auto s = backend->return_statement (scope.GetCurrentFndecl (), retstmts, - expr.locus); + expr.get_locus ()); scope.AddStatement (s); } @@ -791,7 +791,7 @@ Compilation::visit (AST::IfExpr &expr) Bblock *then_block = scope.PopBlock (); auto stmt = backend->if_statement (scope.GetCurrentFndecl (), cond, - then_block, NULL, expr.get_locus_slow ()); + then_block, NULL, expr.get_locus ()); stmts.push_back (stmt); } @@ -816,7 +816,7 @@ Compilation::visit (AST::IfExprConseqElse &expr) auto stmt = backend->if_statement (scope.GetCurrentFndecl (), cond, then_block, - else_block, expr.get_locus_slow ()); + else_block, expr.get_locus ()); stmts.push_back (stmt); } @@ -856,7 +856,7 @@ Compilation::visit (AST::IfExprConseqIf &expr) auto stmt = backend->if_statement (scope.GetCurrentFndecl (), cond, then_block, - else_block, expr.get_locus_slow ()); + else_block, expr.get_locus ()); stmts.push_back (stmt); } @@ -956,7 +956,7 @@ Compilation::visit (AST::Function &function) param.type->accept_vis (*this); if (translatedType == NULL) { - rust_error_at (param.locus, "failed to generate type for parameter"); + rust_error_at (param.get_locus (), "failed to generate type for parameter"); return; } @@ -964,7 +964,7 @@ Compilation::visit (AST::Function &function) param.param_name->accept_vis (*this); if (patternBuffer.size () <= before) { - rust_error_at (param.locus, "failed to analyse parameter name"); + rust_error_at (param.get_locus (), "failed to analyse parameter name"); return; } @@ -975,7 +975,7 @@ Compilation::visit (AST::Function &function) patternBuffer.pop_back (); parameters.push_back ( Backend::Btyped_identifier (paramName.variable_ident, - translatedType, param.locus)); + translatedType, param.get_locus ())); } } @@ -986,7 +986,7 @@ Compilation::visit (AST::Function &function) function.return_type->accept_vis (*this); if (translatedType == NULL) { - rust_fatal_error (function.locus, + rust_fatal_error (function.get_locus (), "failed to generate type for function"); return; } @@ -998,10 +998,10 @@ Compilation::visit (AST::Function &function) } Btype *fntype = backend->function_type (receiver, parameters, results, NULL, - function.locus); + function.get_locus ()); Bfunction *fndecl = backend->function (fntype, function.function_name, "" /* asm_name */, - 0 /* flags */, function.locus); + 0 /* flags */, function.get_locus ()); scope.InsertFunction (function.function_name, fndecl, returnType); scope.Push (); @@ -1020,7 +1020,7 @@ Compilation::visit (AST::Function &function) if (!backend->function_set_parameters (fndecl, param_vars)) { - rust_error_at (function.locus, "failed to setup parameter variables"); + rust_error_at (function.get_locus (), "failed to setup parameter variables"); return; } @@ -1029,7 +1029,7 @@ Compilation::visit (AST::Function &function) { if (!compileVarDecl (fndecl, decl, vars)) { - rust_error_at (decl->locus, "failed to compile var decl"); + rust_error_at (decl->get_locus (), "failed to compile var decl"); return; } } @@ -1037,7 +1037,7 @@ Compilation::visit (AST::Function &function) // is null for top level functions - nested functions will have an enclosing // scope Bblock *enclosingScope = NULL; - Location start_location = function.locus; + Location start_location = function.get_locus (); Location end_location; if (function.function_body->statements.size () > 0) { @@ -1057,7 +1057,7 @@ Compilation::visit (AST::Function &function) Bstatement *ret_var_stmt = NULL; retDecl = backend->temporary_variable (fndecl, code_block, returnType, NULL, address_is_taken, - function.locus, &ret_var_stmt); + function.get_locus (), &ret_var_stmt); scope.AddStatement (ret_var_stmt); } scope.PushCurrentFunction (function.function_name, fndecl, returnType, @@ -1071,7 +1071,7 @@ Compilation::visit (AST::Function &function) auto body = backend->block_statement (code_block); if (!backend->function_set_body (fndecl, body)) { - rust_error_at (function.locus, "failed to set body to function"); + rust_error_at (function.get_locus (), "failed to set body to function"); return; } @@ -1096,23 +1096,23 @@ Compilation::visit (AST::StructStruct &struct_item) if (translatedType == NULL) { rust_fatal_error ( - struct_item.locus /* StructField is mi sing locus */, + struct_item.get_locus () /* StructField is mi sing locus */, "failed to compile struct field"); return; } fields.push_back (Backend::Btyped_identifier ( field.field_name, translatedType, - struct_item.locus /* StructField is mi sing locus */)); + struct_item.get_locus () /* StructField is mi sing locus */)); } auto compiledStruct = backend->placeholder_struct_type (struct_item.struct_name, - struct_item.locus); + struct_item.get_locus ()); bool ok = backend->set_placeholder_struct_type (compiledStruct, fields); if (!ok) { - rust_fatal_error (struct_item.locus, "failed to compile struct"); + rust_fatal_error (struct_item.get_locus (), "failed to compile struct"); return; } @@ -1304,7 +1304,7 @@ Compilation::visit (AST::LetStmt &stmt) Bvariable *var = NULL; if (!scope.LookupVar (pattern.variable_ident, &var)) { - rust_error_at (stmt.locus, "failed to find var decl for %s", + rust_error_at (stmt.get_locus (), "failed to find var decl for %s", pattern.variable_ident.c_str ()); return; } diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 80ad5d0..c7524dc 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -105,7 +105,14 @@ namespace Rust { 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::UseDeclaration& use_decl) override { + // strip test based on outer attrs + expander.expand_cfg_attrs(use_decl.get_outer_attrs()); + if (expander.fails_cfg(use_decl.get_outer_attrs())) { + use_decl.mark_for_strip(); + return; + } + } void visit(AST::Function& function) override {} void visit(AST::TypeAlias& type_alias) override {} void visit(AST::StructStruct& struct_item) override {} @@ -117,14 +124,158 @@ namespace Rust { 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::StaticItem& static_item) override { + + } + void visit(AST::TraitItemFunc& item) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(item.get_outer_attrs()); + if (expander.fails_cfg(item.get_outer_attrs())) { + item.mark_for_strip(); + return; + } + + /* strip function parameters if required - this is specifically + * allowed by spec */ + auto& params = item.get_function_params(); + for (int i = 0; i < params.size(); ) { + auto& param_attrs = params[i].get_outer_attrs (); + expander.expand_cfg_attrs(param_attrs); + if (expander.fails_cfg (param_attrs)) + params.erase (params.begin() + i); + else + i++; + } + } + void visit(AST::TraitItemMethod& item) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(item.get_outer_attrs()); + if (expander.fails_cfg(item.get_outer_attrs())) { + item.mark_for_strip(); + return; + } + + /* assuming you can't strip self param - wouldn't be a method + * anymore. spec allows outer attrs on self param, but doesn't + * specify whether cfg is used. */ + + /* strip function parameters if required - this is specifically + * allowed by spec */ + auto& params = item.get_function_params(); + for (int i = 0; i < params.size(); ) { + auto& param_attrs = params[i].get_outer_attrs (); + expander.expand_cfg_attrs(param_attrs); + if (expander.fails_cfg (param_attrs)) + params.erase (params.begin() + i); + else + i++; + } + } + void visit(AST::TraitItemConst& item) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(item.get_outer_attrs()); + if (expander.fails_cfg(item.get_outer_attrs())) { + item.mark_for_strip(); + return; + } + /* TODO: is there any way to invalidate the expr? Are attributes + * even allowed on it? */ + } + void visit(AST::TraitItemType& item) override { + // initial test based on outer attrs + expander.expand_cfg_attrs(item.get_outer_attrs()); + if (expander.fails_cfg(item.get_outer_attrs())) { + item.mark_for_strip(); + return; + } + } + void visit(AST::Trait& trait) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(trait.get_outer_attrs()); + if (expander.fails_cfg(trait.get_outer_attrs())) { + trait.mark_for_strip(); + return; + } + + // strip test based on inner attrs + expander.expand_cfg_attrs(trait.get_inner_attrs()); + if (expander.fails_cfg(trait.get_inner_attrs())) { + trait.mark_for_strip(); + return; + } + + // strip trait items if required + auto& trait_items = trait.get_trait_items(); + for (int i = 0; i < trait_items.size(); ) { + auto& item = trait_items[i]; + + // mark for stripping if required + item->accept_vis(*this); + + if (item->is_marked_for_strip ()) + trait_items.erase (trait_items.begin() + i); + else + i++; + } + } + void visit(AST::InherentImpl& impl) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(impl.get_outer_attrs()); + if (expander.fails_cfg(impl.get_outer_attrs())) { + impl.mark_for_strip(); + return; + } + + // strip test based on inner attrs + expander.expand_cfg_attrs(impl.get_inner_attrs()); + if (expander.fails_cfg(impl.get_inner_attrs())) { + impl.mark_for_strip(); + return; + } + + // strip external items if required + auto& impl_items = impl.get_impl_items(); + for (int i = 0; i < impl_items.size(); ) { + auto& item = impl_items[i]; + + // mark for stripping if required + item->accept_vis(*this); + + if (item->is_marked_for_strip ()) + impl_items.erase (impl_items.begin() + i); + else + i++; + } + } + void visit(AST::TraitImpl& impl) override { + // initial strip test based on outer attrs + expander.expand_cfg_attrs(impl.get_outer_attrs()); + if (expander.fails_cfg(impl.get_outer_attrs())) { + impl.mark_for_strip(); + return; + } + + // strip test based on inner attrs + expander.expand_cfg_attrs(impl.get_inner_attrs()); + if (expander.fails_cfg(impl.get_inner_attrs())) { + impl.mark_for_strip(); + return; + } + + // strip external items if required + auto& impl_items = impl.get_impl_items(); + for (int i = 0; i < impl_items.size(); ) { + auto& item = impl_items[i]; + + // mark for stripping if required + item->accept_vis(*this); + + if (item->is_marked_for_strip ()) + impl_items.erase (impl_items.begin() + i); + else + i++; + } + } void visit(AST::ExternalStaticItem& item) override { // strip test based on outer attrs expander.expand_cfg_attrs(item.get_outer_attrs()); @@ -144,8 +295,10 @@ namespace Rust { /* strip function parameters if required - this is specifically * allowed by spec */ auto& params = item.get_function_params(); - for (auto i = 0; i < params.size(); ) { - if (expander.fails_cfg (params[i].get_outer_attrs ())) + for (int i = 0; i < params.size(); ) { + auto& param_attrs = params[i].get_outer_attrs (); + expander.expand_cfg_attrs(param_attrs); + if (expander.fails_cfg (param_attrs)) params.erase (params.begin() + i); else i++; @@ -171,7 +324,7 @@ namespace Rust { // strip external items if required auto& extern_items = block.get_extern_items(); - for (auto i = 0; i < extern_items.size(); ) { + for (int i = 0; i < extern_items.size(); ) { auto& item = extern_items[i]; // mark for stripping if required diff --git a/gcc/rust/parse/rust-parse-impl.h b/gcc/rust/parse/rust-parse-impl.h index 9c293dc..1ad997f 100644 --- a/gcc/rust/parse/rust-parse-impl.h +++ b/gcc/rust/parse/rust-parse-impl.h @@ -464,6 +464,7 @@ Parser<ManagedTokenSource>::parse_inner_attributes () } } + inner_attributes.shrink_to_fit (); return inner_attributes; } @@ -962,6 +963,7 @@ Parser<ManagedTokenSource>::parse_items () } } + items.shrink_to_fit (); return items; } @@ -1073,6 +1075,7 @@ Parser<ManagedTokenSource>::parse_outer_attributes () } } + outer_attributes.shrink_to_fit (); return outer_attributes; /* TODO: this shares basically all code with parse_inner_attributes except @@ -2442,9 +2445,7 @@ Parser<ManagedTokenSource>::parse_function ( // parse function parameters (only if next token isn't right paren) std::vector<AST::FunctionParam> function_params; if (lexer.peek_token ()->get_id () != RIGHT_PAREN) - { - function_params = parse_function_params (); - } + function_params = parse_function_params ([](TokenId id) { return id == RIGHT_PAREN; }); if (!skip_token (RIGHT_PAREN)) { @@ -2745,6 +2746,7 @@ Parser<ManagedTokenSource>::parse_generic_params () std::make_move_iterator(type_params.end())); }*/ + generic_params.shrink_to_fit (); return generic_params; } @@ -2902,6 +2904,7 @@ Parser<ManagedTokenSource>::parse_generic_params (EndTokenPred is_end_token) std::make_move_iterator(type_params.end())); }*/ + generic_params.shrink_to_fit (); return generic_params; } @@ -3149,6 +3152,7 @@ Parser<ManagedTokenSource>::parse_type_params () lexer.skip_token (); } + type_params.shrink_to_fit (); return type_params; } @@ -3180,6 +3184,7 @@ Parser<ManagedTokenSource>::parse_type_params (EndTokenPred is_end_token) lexer.skip_token (); } + type_params.shrink_to_fit (); return type_params; /* TODO: this shares most code with parse_lifetime_params - good place to use * template (i.e. parse_non_ptr_sequence if doable) */ @@ -3236,24 +3241,24 @@ Parser<ManagedTokenSource>::parse_type_param () std::move (outer_attr))); } -// Parses regular (i.e. non-generic) parameters in functions or methods. +/* Parses regular (i.e. non-generic) parameters in functions or methods. Also + * has end token handling. */ template <typename ManagedTokenSource> +template <typename EndTokenPred> std::vector<AST::FunctionParam> -Parser<ManagedTokenSource>::parse_function_params () +Parser<ManagedTokenSource>::parse_function_params (EndTokenPred is_end_token) { std::vector<AST::FunctionParam> params; - // HACK: return early if RIGHT_PAREN is found - if (lexer.peek_token ()->get_id () == RIGHT_PAREN) - { + if (is_end_token (lexer.peek_token ()->get_id ())) return params; - } AST::FunctionParam initial_param = parse_function_param (); // Return empty parameter list if no parameter there - if (initial_param.is_error ()) + if (initial_param.is_error ()) { + // TODO: is this an error? return params; } @@ -3268,13 +3273,9 @@ Parser<ManagedTokenSource>::parse_function_params () // skip comma if applies lexer.skip_token (); - /* HACK: break if next token is a right (closing) paren - this is not - * strictly true via grammar rule but seems to be true in practice (i.e. - * with trailing comma). */ - if (lexer.peek_token ()->get_id () == RIGHT_PAREN) - { + // TODO: strictly speaking, shouldn't there be no trailing comma? + if (is_end_token (lexer.peek_token ()->get_id ())) break; - } // now, as right paren would break, function param is required AST::FunctionParam param = parse_function_param (); @@ -3291,6 +3292,7 @@ Parser<ManagedTokenSource>::parse_function_params () t = lexer.peek_token (); } + params.shrink_to_fit (); return params; } @@ -3300,6 +3302,10 @@ template <typename ManagedTokenSource> AST::FunctionParam Parser<ManagedTokenSource>::parse_function_param () { + // parse outer attributes if they exist + std::vector<AST::Attribute> outer_attrs = parse_outer_attributes (); + + // TODO: should saved location be at start of outer attributes or pattern? Location locus = lexer.peek_token ()->get_locus (); std::unique_ptr<AST::Pattern> param_pattern = parse_pattern (); @@ -3324,7 +3330,7 @@ Parser<ManagedTokenSource>::parse_function_param () } return AST::FunctionParam (std::move (param_pattern), std::move (param_type), - locus); + std::move (outer_attrs), locus); } /* Parses a function or method return type syntactical construction. Also @@ -3334,9 +3340,8 @@ std::unique_ptr<AST::Type> Parser<ManagedTokenSource>::parse_function_return_type () { if (lexer.peek_token ()->get_id () != RETURN_TYPE) - { return nullptr; - } + // skip return type, as it now obviously exists lexer.skip_token (); @@ -3391,6 +3396,7 @@ Parser<ManagedTokenSource>::parse_where_clause () t = lexer.peek_token (); } + where_clause_items.shrink_to_fit (); return AST::WhereClause (std::move (where_clause_items)); } @@ -3542,8 +3548,8 @@ Parser<ManagedTokenSource>::parse_type_param_bounds () return type_param_bounds; } -// Parses type parameter bounds in where clause or generic arguments, with end -// token handling. +/* Parses type parameter bounds in where clause or generic arguments, with end + * token handling. */ template <typename ManagedTokenSource> template <typename EndTokenPred> std::vector<std::unique_ptr<AST::TypeParamBound> > @@ -4092,6 +4098,7 @@ Parser<ManagedTokenSource>::parse_tuple_fields () t = lexer.peek_token (); } + fields.shrink_to_fit (); return fields; // TODO: this shares basically all code with function params and struct fields @@ -4196,6 +4203,7 @@ Parser<ManagedTokenSource>::parse_enum_items () items.push_back (std::move (item)); } + items.shrink_to_fit (); return items; /* TODO: use template if doable (parse_non_ptr_sequence) */ @@ -4237,6 +4245,7 @@ Parser<ManagedTokenSource>::parse_enum_items (EndTokenPred is_end_tok) items.push_back (std::move (item)); } + items.shrink_to_fit (); return items; /* TODO: use template if doable (parse_non_ptr_sequence) */ @@ -4530,6 +4539,9 @@ Parser<ManagedTokenSource>::parse_trait ( return nullptr; } + // parse inner attrs (if they exist) + std::vector<AST::Attribute> inner_attrs = parse_inner_attributes (); + // parse trait items std::vector<std::unique_ptr<AST::TraitItem> > trait_items; @@ -4555,11 +4567,12 @@ Parser<ManagedTokenSource>::parse_trait ( return nullptr; } + trait_items.shrink_to_fit (); return std::unique_ptr<AST::Trait> ( new AST::Trait (std::move (ident), is_unsafe, std::move (generic_params), std::move (type_param_bounds), std::move (where_clause), std::move (trait_items), std::move (vis), - std::move (outer_attrs), locus)); + std::move (outer_attrs), std::move (inner_attrs), locus)); } // Parses a trait item used inside traits (not trait, the Item). @@ -4613,27 +4626,25 @@ Parser<ManagedTokenSource>::parse_trait_item () return nullptr; } - // now for function vs method disambiguation - method has opening "self" - // param + /* now for function vs method disambiguation - method has opening "self" + * param */ AST::SelfParam self_param = parse_self_param (); - // FIXME: ensure that self param doesn't accidently consume tokens for a - // function + /* FIXME: ensure that self param doesn't accidently consume tokens for a + * function */ bool is_method = false; if (!self_param.is_error ()) { is_method = true; - // skip comma so function and method regular params can be parsed in - // same way + /* skip comma so function and method regular params can be parsed in + * same way */ if (lexer.peek_token ()->get_id () == COMMA) - { lexer.skip_token (); - } } // parse trait function params std::vector<AST::FunctionParam> function_params - = parse_function_params (); + = parse_function_params ([](TokenId id) { return id == RIGHT_PAREN; }); if (!skip_token (RIGHT_PAREN)) { @@ -4914,6 +4925,8 @@ Parser<ManagedTokenSource>::parse_impl (AST::Visibility vis, // DEBUG fprintf (stderr, "successfully parsed inherent impl\n"); + impl_items.shrink_to_fit (); + return std::unique_ptr<AST::InherentImpl> (new AST::InherentImpl ( std::move (impl_items), std::move (generic_params), std::move (type), std::move (where_clause), std::move (vis), std::move (inner_attrs), @@ -4987,6 +5000,8 @@ Parser<ManagedTokenSource>::parse_impl (AST::Visibility vis, // DEBUG fprintf (stderr, "successfully parsed trait impl\n"); + impl_items.shrink_to_fit (); + return std::unique_ptr<AST::TraitImpl> ( new AST::TraitImpl (std::move (type_path), is_unsafe, has_exclam, std::move (impl_items), std::move (generic_params), @@ -5138,24 +5153,22 @@ Parser<ManagedTokenSource>::parse_inherent_impl_function_or_method ( // now for function vs method disambiguation - method has opening "self" param AST::SelfParam self_param = parse_self_param (); - // FIXME: ensure that self param doesn't accidently consume tokens for a - // function one idea is to lookahead up to 4 tokens to see whether self is one - // of them + /* FIXME: ensure that self param doesn't accidently consume tokens for a + * function one idea is to lookahead up to 4 tokens to see whether self is one + * of them */ bool is_method = false; if (!self_param.is_error ()) { is_method = true; - // skip comma so function and method regular params can be parsed in same - // way + /* skip comma so function and method regular params can be parsed in same + * way */ if (lexer.peek_token ()->get_id () == COMMA) - { lexer.skip_token (); - } } // parse trait function params - std::vector<AST::FunctionParam> function_params = parse_function_params (); + std::vector<AST::FunctionParam> function_params = parse_function_params ([](TokenId id) { return id == RIGHT_PAREN; }); if (!skip_token (RIGHT_PAREN)) { @@ -5400,7 +5413,7 @@ Parser<ManagedTokenSource>::parse_trait_impl_function_or_method ( std::vector<AST::FunctionParam> function_params; if (lexer.peek_token ()->get_id () != RIGHT_PAREN) { - function_params = parse_function_params (); + function_params = parse_function_params ([](TokenId id) { return id == RIGHT_PAREN; }); if (function_params.empty ()) { @@ -5534,6 +5547,8 @@ Parser<ManagedTokenSource>::parse_extern_block ( // skip somewhere return nullptr; } + + extern_items.shrink_to_fit (); return std::unique_ptr<AST::ExternBlock> ( new AST::ExternBlock (std::move (abi), std::move (extern_items), @@ -5689,6 +5704,8 @@ Parser<ManagedTokenSource>::parse_external_item () // skip somewhere? return nullptr; } + + function_params.shrink_to_fit (); return std::unique_ptr<AST::ExternalFunctionItem> ( new AST::ExternalFunctionItem ( @@ -6220,6 +6237,7 @@ Parser<ManagedTokenSource>::parse_type_path_function () // parse optional return type std::unique_ptr<AST::Type> return_type = parse_function_return_type (); + inputs.shrink_to_fit (); return AST::TypePathFunction (std::move (inputs), std::move (return_type)); } @@ -6392,6 +6410,8 @@ Parser<ManagedTokenSource>::parse_qualified_path_in_expression ( t = lexer.peek_token (); } + segments.shrink_to_fit (); + // FIXME: outer attr parsing return AST::QualifiedPathInExpression (std::move (qual_path_type), std::move (segments), locus, @@ -6667,7 +6687,7 @@ Parser<ManagedTokenSource>::parse_method () lexer.skip_token (); // parse function parameters - std::vector<AST::FunctionParam> function_params = parse_function_params (); + std::vector<AST::FunctionParam> function_params = parse_function_params ([](TokenId id) { return id == RIGHT_PAREN; }); if (!skip_token (RIGHT_PAREN)) { @@ -7066,6 +7086,8 @@ Parser<ManagedTokenSource>::parse_block_expr ( // grammar allows for empty block expressions + stmts.shrink_to_fit (); + return std::unique_ptr<AST::BlockExpr> ( new AST::BlockExpr (std::move (stmts), std::move (expr), std::move (inner_attrs), std::move (outer_attrs), @@ -7154,6 +7176,7 @@ Parser<ManagedTokenSource>::parse_closure_expr ( t = lexer.peek_token (); } + params.shrink_to_fit (); break; default: rust_error_at (t->get_locus (), diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index 82d8d6f..5202abf 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -164,7 +164,8 @@ private: template <typename EndTokenPred> std::vector<std::unique_ptr<AST::TypeParam> > parse_type_params (EndTokenPred is_end_token); std::unique_ptr<AST::TypeParam> parse_type_param (); - std::vector<AST::FunctionParam> parse_function_params (); + template <typename EndTokenPred> + std::vector<AST::FunctionParam> parse_function_params (EndTokenPred is_end_token); AST::FunctionParam parse_function_param (); std::unique_ptr<AST::Type> parse_function_return_type (); AST::WhereClause parse_where_clause (); |