aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/rust/analysis/rust-type-resolution.cc24
-rw-r--r--gcc/rust/ast/rust-ast-full-test.cc12
-rw-r--r--gcc/rust/ast/rust-ast.h20
-rw-r--r--gcc/rust/ast/rust-item.h239
-rw-r--r--gcc/rust/backend/rust-compile.cc86
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc177
-rw-r--r--gcc/rust/parse/rust-parse-impl.h105
-rw-r--r--gcc/rust/parse/rust-parse.h3
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 &param : 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 &param : 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 ();