aboutsummaryrefslogtreecommitdiff
path: root/gcc/rust/ast/rust-item.h
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/rust/ast/rust-item.h')
-rw-r--r--gcc/rust/ast/rust-item.h1532
1 files changed, 1244 insertions, 288 deletions
diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h
index b5d9247..f18124d 100644
--- a/gcc/rust/ast/rust-item.h
+++ b/gcc/rust/ast/rust-item.h
@@ -57,7 +57,7 @@ class TypeParam : public GenericParam
// bool has_type_param_bounds;
// TypeParamBounds type_param_bounds;
- std::vector<std::unique_ptr<TypeParamBound>>
+ std::vector<std::unique_ptr<TypeParamBound> >
type_param_bounds; // inlined form
// bool has_type;
@@ -76,8 +76,8 @@ public:
bool has_outer_attribute () const { return !outer_attr.is_empty (); }
TypeParam (Identifier type_representation, Location locus = Location (),
- std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds
- = std::vector<std::unique_ptr<TypeParamBound>> (),
+ std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds
+ = std::vector<std::unique_ptr<TypeParamBound> > (),
std::unique_ptr<Type> type = nullptr,
Attribute outer_attr = Attribute::create_empty ())
: outer_attr (std::move (outer_attr)),
@@ -89,9 +89,12 @@ public:
// Copy constructor uses clone
TypeParam (TypeParam const &other)
: outer_attr (other.outer_attr),
- type_representation (other.type_representation),
- type (other.type->clone_type ()), locus (other.locus)
+ type_representation (other.type_representation), locus (other.locus)
{
+ // guard to prevent null pointer dereference
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+
type_param_bounds.reserve (other.type_param_bounds.size ());
for (const auto &e : other.type_param_bounds)
type_param_bounds.push_back (e->clone_type_param_bound ());
@@ -101,11 +104,15 @@ public:
TypeParam &operator= (TypeParam const &other)
{
type_representation = other.type_representation;
- // type_param_bounds = other.type_param_bounds;
- type = other.type->clone_type ();
outer_attr = other.outer_attr;
locus = other.locus;
+ // guard to prevent null pointer dereference
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ else
+ type = nullptr;
+
type_param_bounds.reserve (other.type_param_bounds.size ());
for (const auto &e : other.type_param_bounds)
type_param_bounds.push_back (e->clone_type_param_bound ());
@@ -123,6 +130,24 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (type != nullptr);
+ return type;
+ }
+
+ // TODO: mutable getter seems kinda dodgy
+ std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
+ {
+ return type_param_bounds;
+ }
+ const std::vector<std::unique_ptr<TypeParamBound> > &
+ get_type_param_bounds () const
+ {
+ return type_param_bounds;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
TypeParam *clone_generic_param_impl () const override
@@ -193,7 +218,7 @@ class TypeBoundWhereClauseItem : public WhereClauseItem
// bool has_type_param_bounds;
// TypeParamBounds type_param_bounds;
- std::vector<std::unique_ptr<TypeParamBound>>
+ std::vector<std::unique_ptr<TypeParamBound> >
type_param_bounds; // inlined form
// should this store location info?
@@ -207,7 +232,7 @@ public:
TypeBoundWhereClauseItem (
std::vector<LifetimeParam> for_lifetimes, std::unique_ptr<Type> bound_type,
- std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds)
+ std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds)
: for_lifetimes (std::move (for_lifetimes)),
bound_type (std::move (bound_type)),
type_param_bounds (std::move (type_param_bounds))
@@ -245,6 +270,24 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (bound_type != nullptr);
+ return bound_type;
+ }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
+ {
+ return type_param_bounds;
+ }
+ const std::vector<std::unique_ptr<TypeParamBound> > &
+ get_type_param_bounds () const
+ {
+ return type_param_bounds;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
TypeBoundWhereClauseItem *clone_where_clause_item_impl () const override
@@ -257,13 +300,13 @@ protected:
struct WhereClause
{
private:
- std::vector<std::unique_ptr<WhereClauseItem>> where_clause_items;
+ std::vector<std::unique_ptr<WhereClauseItem> > where_clause_items;
// should this store location info?
public:
WhereClause (
- std::vector<std::unique_ptr<WhereClauseItem>> where_clause_items)
+ std::vector<std::unique_ptr<WhereClauseItem> > where_clause_items)
: where_clause_items (std::move (where_clause_items))
{}
@@ -292,13 +335,23 @@ public:
// Creates a WhereClause with no items.
static WhereClause create_empty ()
{
- return WhereClause (std::vector<std::unique_ptr<WhereClauseItem>> ());
+ return WhereClause (std::vector<std::unique_ptr<WhereClauseItem> > ());
}
// Returns whether the WhereClause has no items.
bool is_empty () const { return where_clause_items.empty (); }
std::string as_string () const;
+
+ // TODO: this mutable getter seems kinda dodgy
+ std::vector<std::unique_ptr<WhereClauseItem> > &get_items ()
+ {
+ return where_clause_items;
+ }
+ const std::vector<std::unique_ptr<WhereClauseItem> > &get_items () const
+ {
+ return where_clause_items;
+ }
};
// A self parameter in a method
@@ -322,6 +375,8 @@ private:
{}
// this is ok as no outside classes can ever call this
+ // TODO: self param can have outer attributes
+
public:
// Returns whether the self-param has a type field.
bool has_type () const { return type != nullptr; }
@@ -332,21 +387,15 @@ public:
// Returns whether the self-param is in an error state.
bool is_error () const
{
- return has_type () && has_lifetime ();
+ return (has_type () && has_lifetime ()) || (has_lifetime () && !has_ref);
// not having either is not an error
}
// Creates an error state self-param.
static SelfParam create_error ()
{
- /* HACK: creates a dummy type. Since it's a unique pointer, it should
- * clean it up, but it still allocates memory, which is not ideal. */
- return SelfParam (Lifetime (Lifetime::STATIC), false, false,
- new QualifiedPathInType (
- QualifiedPathInType::create_error ()));
- /* FIXME: is there a reason why I didn't just create a null pointer? Is it
- * due to error being having both a type and a lifetime? If it is, wouldn't
- * something like "not has_ref and has lifetime" for error be better? */
+ // cannot have no ref but have a lifetime at the same time
+ return SelfParam (Lifetime (Lifetime::STATIC), false, false, nullptr);
}
// Type-based self parameter (not ref, no lifetime)
@@ -373,13 +422,16 @@ public:
// Overload assignment operator to use clone
SelfParam &operator= (SelfParam const &other)
{
- if (other.type != nullptr)
- type = other.type->clone_type ();
is_mut = other.is_mut;
has_ref = other.has_ref;
lifetime = other.lifetime;
locus = other.locus;
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ else
+ type = nullptr;
+
return *this;
}
@@ -390,6 +442,13 @@ public:
std::string as_string () const;
Location get_locus () const { return locus; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (has_type ());
+ return type;
+ }
};
// Qualifiers for function, i.e. const, unsafe, extern etc.
@@ -424,7 +483,7 @@ public:
if (!this->extern_abi.empty ())
{
// having extern is required; not having it is an implementation error
- gcc_assert (has_extern);
+ rust_assert (has_extern);
}
}
@@ -434,31 +493,45 @@ public:
// A function parameter
struct FunctionParam
{
-public:
+private:
+ std::vector<Attribute> outer_attrs;
+ Location locus;
std::unique_ptr<Pattern> param_name;
std::unique_ptr<Type> type;
- Location locus;
-
+public:
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 +545,30 @@ 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; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Pattern> &get_pattern ()
+ {
+ rust_assert (param_name != nullptr);
+ return param_name;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (type != nullptr);
+ return type;
+ }
};
// Visibility of item - if the item has it, then it is some form of public
@@ -581,7 +672,7 @@ class Method : public InherentImplItem, public TraitImplItem
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
SelfParam self_param;
@@ -596,7 +687,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,17 +695,18 @@ 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.
static Method create_error ()
{
return Method ("", FunctionQualifiers (FunctionQualifiers::NONE, true),
- std::vector<std::unique_ptr<GenericParam>> (),
+ 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.
@@ -634,11 +726,11 @@ public:
// Mega-constructor with all possible fields
Method (Identifier method_name, FunctionQualifiers qualifiers,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
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,8 +738,8 @@ 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)),
- locus (locus)
+ where_clause (std::move (where_clause)),
+ function_body (std::move (function_body)), locus (locus)
{}
// TODO: add constructor with less fields
@@ -657,10 +749,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 +773,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 +803,56 @@ 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;
+ }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ std::vector<FunctionParam> &get_function_params () { return function_params; }
+ const std::vector<FunctionParam> &get_function_params () const
+ {
+ return function_params;
+ }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_definition ()
+ {
+ rust_assert (function_body != nullptr);
+ return function_body;
+ }
+
+ SelfParam &get_self_param () { return self_param; }
+ const SelfParam &get_self_param () const { return self_param; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_return_type ()
+ {
+ rust_assert (has_return_type ());
+ return return_type;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -715,24 +873,25 @@ protected:
class VisItem : public Item
{
Visibility visibility;
+ std::vector<Attribute> outer_attrs;
protected:
// Visibility constructor
VisItem (Visibility visibility,
std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
- : Item (std::move (outer_attrs)), visibility (std::move (visibility))
+ : visibility (std::move (visibility)), outer_attrs (std::move (outer_attrs))
{}
// Visibility copy constructor
- VisItem (VisItem const &other) : Item (other), visibility (other.visibility)
+ VisItem (VisItem const &other)
+ : visibility (other.visibility), outer_attrs (other.outer_attrs)
{}
// Overload assignment operator to clone
VisItem &operator= (VisItem const &other)
{
- Item::operator= (other);
visibility = other.visibility;
- // outer_attrs = other.outer_attrs;
+ outer_attrs = other.outer_attrs;
return *this;
}
@@ -747,6 +906,13 @@ public:
bool has_visibility () const { return !visibility.is_error (); }
std::string as_string () const override;
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ Visibility &get_vis () { return visibility; }
+ const Visibility &get_vis () const { return visibility; }
+
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
};
// Rust module item - abstract base class
@@ -767,6 +933,10 @@ public:
std::string as_string () const override;
Location get_locus () const { return locus; }
+
+ // Invalid if name is empty, so base stripping on that.
+ void mark_for_strip () override { module_name = ""; }
+ bool is_marked_for_strip () const override { return module_name.empty (); }
};
// Module with a body, defined in file
@@ -775,7 +945,7 @@ class ModuleBodied : public Module
// bool has_inner_attrs;
std::vector<Attribute> inner_attrs;
// bool has_items;
- std::vector<std::unique_ptr<Item>> items;
+ std::vector<std::unique_ptr<Item> > items;
public:
std::string as_string () const override;
@@ -788,8 +958,8 @@ public:
// Full constructor
ModuleBodied (Identifier name, Location locus,
- std::vector<std::unique_ptr<Item>> items
- = std::vector<std::unique_ptr<Item>> (),
+ std::vector<std::unique_ptr<Item> > items
+ = std::vector<std::unique_ptr<Item> > (),
Visibility visibility = Visibility::create_error (),
std::vector<Attribute> inner_attrs = std::vector<Attribute> (),
std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
@@ -830,6 +1000,16 @@ public:
* the module. */
void add_crate_name (std::vector<std::string> &names) const override;
+ // TODO: think of better way to do this - mutable getter seems dodgy
+ const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
+ std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
+
+ const std::vector<std::unique_ptr<Item> > &get_items () const
+ {
+ return items;
+ }
+ std::vector<std::unique_ptr<Item> > &get_items () { return items; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -837,17 +1017,16 @@ protected:
{
return new ModuleBodied (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual ModuleBodied* clone_statement_impl() const override {
- return new ModuleBodied(*this);
- }*/
};
// Module without a body, loaded from external file
class ModuleNoBody : public Module
{
+ /* TODO: are modules loaded from file unique? As in, can you load the same
+ * file into two different other files? Because this may make the difference
+ * between simply replacing this with the module
+ * "definition" (as loaded from another file) vs this having to "reference" a
+ * module with body. */
public:
std::string as_string () const override;
@@ -867,12 +1046,6 @@ protected:
{
return new ModuleNoBody (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual ModuleNoBody* clone_statement_impl() const override {
- return new ModuleNoBody(*this);
- }*/
};
// Rust extern crate declaration AST node
@@ -920,6 +1093,13 @@ public:
names.push_back (referenced_crate);
}
+ // Invalid if crate name is empty, so base stripping on that.
+ void mark_for_strip () override { referenced_crate = ""; }
+ bool is_marked_for_strip () const override
+ {
+ return referenced_crate.empty ();
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -927,12 +1107,6 @@ protected:
{
return new ExternCrate (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual ExternCrate* clone_statement_impl() const override {
- return new ExternCrate(*this);
- }*/
};
// The path-ish thing referred to in a use declaration - abstract base class
@@ -985,7 +1159,7 @@ public:
{
// compiler implementation error if there is a path with a
// non-path-prefixed use tree glob
- gcc_assert (!has_path ());
+ rust_assert (!has_path ());
}
// TODO: do path-prefixed paths also have to have a path? If so, have an
// assert for that too.
@@ -1025,11 +1199,11 @@ private:
PathType path_type;
SimplePath path;
- std::vector<std::unique_ptr<UseTree>> trees;
+ std::vector<std::unique_ptr<UseTree> > trees;
public:
UseTreeList (PathType path_type, SimplePath path,
- std::vector<std::unique_ptr<UseTree>> trees, Location locus)
+ std::vector<std::unique_ptr<UseTree> > trees, Location locus)
: UseTree (locus), path_type (path_type), path (std::move (path)),
trees (std::move (trees))
{
@@ -1037,7 +1211,7 @@ public:
{
// compiler implementation error if there is a path with a
// non-path-prefixed use tree glob
- gcc_assert (!has_path ());
+ rust_assert (!has_path ());
}
// TODO: do path-prefixed paths also have to have a path? If so, have an
// assert for that too.
@@ -1153,19 +1327,27 @@ public:
// Copy constructor with clone
UseDeclaration (UseDeclaration const &other)
- : VisItem (other), use_tree (other.use_tree->clone_use_tree ()),
- locus (other.locus)
- {}
+ : VisItem (other), locus (other.locus)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.use_tree != nullptr)
+ use_tree = other.use_tree->clone_use_tree ();
+ }
// Overloaded assignment operator to clone
UseDeclaration &operator= (UseDeclaration const &other)
{
VisItem::operator= (other);
- use_tree = other.use_tree->clone_use_tree ();
// visibility = other.visibility->clone_visibility();
// outer_attrs = other.outer_attrs;
locus = other.locus;
+ // guard to prevent null dereference (only required if error state)
+ if (other.use_tree != nullptr)
+ use_tree = other.use_tree->clone_use_tree ();
+ else
+ use_tree = nullptr;
+
return *this;
}
@@ -1177,6 +1359,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if use tree is null, so base stripping on that.
+ void mark_for_strip () override { use_tree = nullptr; }
+ bool is_marked_for_strip () const override { return use_tree == nullptr; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1184,12 +1370,6 @@ protected:
{
return new UseDeclaration (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual UseDeclaration* clone_statement_impl() const override {
- return new UseDeclaration(*this);
- }*/
};
// Parameters used in a function - TODO inline?
@@ -1202,13 +1382,12 @@ class LetStmt;
// Rust function declaration AST node
class Function : public VisItem, public InherentImplItem, public TraitImplItem
{
-public:
FunctionQualifiers qualifiers;
Identifier function_name;
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
// bool has_function_params;
// FunctionParams function_params;
@@ -1224,6 +1403,7 @@ public:
Location locus;
+public:
std::vector<LetStmt *> locals;
std::string as_string () const override;
@@ -1235,14 +1415,14 @@ public:
bool has_function_params () const { return !function_params.empty (); }
// Returns whether function has return type - if not, it is void.
- bool has_function_return_type () const { return return_type != nullptr; }
+ bool has_return_type () const { return return_type != nullptr; }
// Returns whether function has a where clause.
bool has_where_clause () const { return !where_clause.is_empty (); }
// Mega-constructor with all possible fields
Function (Identifier function_name, FunctionQualifiers qualifiers,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
std::vector<FunctionParam> function_params,
std::unique_ptr<Type> return_type, WhereClause where_clause,
std::unique_ptr<BlockExpr> function_body, Visibility vis,
@@ -1264,11 +1444,16 @@ public:
: VisItem (other), qualifiers (other.qualifiers),
function_name (other.function_name),
function_params (other.function_params),
- return_type (other.return_type->clone_type ()),
- where_clause (other.where_clause),
- function_body (other.function_body->clone_block_expr ()),
- locus (other.locus)
+ where_clause (other.where_clause), locus (other.locus)
{
+ // guard to prevent null dereference (always required)
+ if (other.return_type != nullptr)
+ return_type = other.return_type->clone_type ();
+
+ // guard to prevent null dereference (only required if error state)
+ if (other.function_body != nullptr)
+ function_body = other.function_body->clone_block_expr ();
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -1280,15 +1465,24 @@ public:
VisItem::operator= (other);
function_name = other.function_name;
qualifiers = other.qualifiers;
- // generic_params = other.generic_params;
function_params = other.function_params;
- return_type = other.return_type->clone_type ();
where_clause = other.where_clause;
- function_body = other.function_body->clone_block_expr ();
// visibility = other.visibility->clone_visibility();
// outer_attrs = other.outer_attrs;
locus = other.locus;
+ // guard to prevent null dereference (always required)
+ if (other.return_type != nullptr)
+ return_type = other.return_type->clone_type ();
+ else
+ return_type = nullptr;
+
+ // guard to prevent null dereference (only required if error state)
+ if (other.function_body != nullptr)
+ function_body = other.function_body->clone_block_expr ();
+ else
+ function_body = nullptr;
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -1304,6 +1498,54 @@ 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;
+ }
+
+ // 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;
+ }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_definition ()
+ {
+ rust_assert (function_body != nullptr);
+ return function_body;
+ }
+
+ FunctionQualifiers get_qualifiers () const { return qualifiers; }
+
+ Identifier get_function_name () const { return function_name; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_return_type ()
+ {
+ rust_assert (has_return_type ());
+ return return_type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1322,12 +1564,6 @@ protected:
{
return new Function (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual Function* clone_statement_impl() const override {
- return new Function(*this);
- }*/
};
// Rust type alias (i.e. typedef) AST node
@@ -1337,7 +1573,7 @@ class TypeAlias : public VisItem, public TraitImplItem
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
// bool has_where_clause;
WhereClause where_clause;
@@ -1357,7 +1593,7 @@ public:
// Mega-constructor with all possible fields
TypeAlias (Identifier new_type_name,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
WhereClause where_clause, std::unique_ptr<Type> existing_type,
Visibility vis, std::vector<Attribute> outer_attrs, Location locus)
: VisItem (std::move (vis), std::move (outer_attrs)),
@@ -1370,9 +1606,12 @@ public:
// Copy constructor
TypeAlias (TypeAlias const &other)
: VisItem (other), new_type_name (other.new_type_name),
- where_clause (other.where_clause),
- existing_type (other.existing_type->clone_type ()), locus (other.locus)
+ where_clause (other.where_clause), locus (other.locus)
{
+ // guard to prevent null dereference (only required if error state)
+ if (other.existing_type != nullptr)
+ existing_type = other.existing_type->clone_type ();
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -1383,13 +1622,17 @@ public:
{
VisItem::operator= (other);
new_type_name = other.new_type_name;
- // generic_params = other.generic_params;
where_clause = other.where_clause;
- existing_type = other.existing_type->clone_type ();
// visibility = other.visibility->clone_visibility();
// outer_attrs = other.outer_attrs;
locus = other.locus;
+ // guard to prevent null dereference (only required if error state)
+ if (other.existing_type != nullptr)
+ existing_type = other.existing_type->clone_type ();
+ else
+ existing_type = nullptr;
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -1405,6 +1648,36 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if existing type is null, so base stripping on that.
+ void mark_for_strip () override { existing_type = nullptr; }
+ bool is_marked_for_strip () const override
+ {
+ return existing_type == nullptr;
+ }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type_aliased ()
+ {
+ rust_assert (existing_type != nullptr);
+ return existing_type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1416,30 +1689,26 @@ protected:
{
return new TypeAlias (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual TypeAlias* clone_statement_impl() const override {
- return new TypeAlias(*this);
- }*/
};
// Rust base struct declaration AST node - abstract base class
class Struct : public VisItem
{
-public:
+protected:
// protected to enable access by derived classes - allows better as_string
Identifier struct_name;
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
// bool has_where_clause;
WhereClause where_clause;
+private:
Location locus;
+public:
// Returns whether struct has generic parameters.
bool has_generics () const { return !generic_params.empty (); }
@@ -1448,9 +1717,31 @@ public:
Location get_locus () const { return locus; }
+ // Invalid if name is empty, so base stripping on that.
+ void mark_for_strip () override { struct_name = ""; }
+ bool is_marked_for_strip () const override { return struct_name.empty (); }
+
+ Identifier get_struct_name () const { return struct_name; }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
protected:
Struct (Identifier struct_name,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
WhereClause where_clause, Visibility vis, Location locus,
std::vector<Attribute> outer_attrs = std::vector<Attribute> ())
: VisItem (std::move (vis), std::move (outer_attrs)),
@@ -1492,7 +1783,7 @@ protected:
// A single field in a struct
struct StructField
{
-public:
+private:
// bool has_outer_attributes;
std::vector<Attribute> outer_attrs;
@@ -1504,6 +1795,7 @@ public:
// should this store location info?
+public:
// Returns whether struct field has any outer attributes.
bool has_outer_attributes () const { return !outer_attrs.empty (); }
@@ -1520,9 +1812,12 @@ public:
// Copy constructor
StructField (StructField const &other)
: outer_attrs (other.outer_attrs), visibility (other.visibility),
- field_name (other.field_name),
- field_type (other.field_type->clone_type ())
- {}
+ field_name (other.field_name)
+ {
+ // guard to prevent null dereference
+ if (other.field_type != nullptr)
+ field_type = other.field_type->clone_type ();
+ }
~StructField () = default;
@@ -1530,10 +1825,15 @@ public:
StructField &operator= (StructField const &other)
{
field_name = other.field_name;
- field_type = other.field_type->clone_type ();
visibility = other.visibility;
outer_attrs = other.outer_attrs;
+ // guard to prevent null dereference
+ if (other.field_type != nullptr)
+ field_type = other.field_type->clone_type ();
+ else
+ field_type = nullptr;
+
return *this;
}
@@ -1555,20 +1855,35 @@ public:
}
std::string as_string () const;
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ Identifier get_field_name () const { return field_name; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_field_type ()
+ {
+ rust_assert (field_type != nullptr);
+ return field_type;
+ }
+
+ Visibility get_visibility () const { return visibility; }
};
// Rust struct declaration with true struct type AST node
class StructStruct : public Struct
{
-public:
std::vector<StructField> fields;
bool is_unit;
+public:
std::string as_string () const override;
// Mega-constructor with all possible fields
StructStruct (std::vector<StructField> fields, Identifier struct_name,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
WhereClause where_clause, bool is_unit, Visibility vis,
std::vector<Attribute> outer_attrs, Location locus)
: Struct (std::move (struct_name), std::move (generic_params),
@@ -1579,7 +1894,7 @@ public:
// Unit struct constructor
StructStruct (Identifier struct_name,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
WhereClause where_clause, Visibility vis,
std::vector<Attribute> outer_attrs, Location locus)
: Struct (std::move (struct_name), std::move (generic_params),
@@ -1596,6 +1911,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<StructField> &get_fields () { return fields; }
+ const std::vector<StructField> &get_fields () const { return fields; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1603,12 +1922,6 @@ protected:
{
return new StructStruct (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual StructStruct* clone_statement_impl() const override {
- return new StructStruct(*this);
- }*/
};
// A single field in a tuple
@@ -1642,19 +1955,27 @@ public:
// Copy constructor with clone
TupleField (TupleField const &other)
- : outer_attrs (other.outer_attrs), visibility (other.visibility),
- field_type (other.field_type->clone_type ())
- {}
+ : outer_attrs (other.outer_attrs), visibility (other.visibility)
+ {
+ // guard to prevent null dereference (only required if error)
+ if (other.field_type != nullptr)
+ field_type = other.field_type->clone_type ();
+ }
~TupleField () = default;
// Overloaded assignment operator to clone
TupleField &operator= (TupleField const &other)
{
- field_type = other.field_type->clone_type ();
visibility = other.visibility;
outer_attrs = other.outer_attrs;
+ // guard to prevent null dereference (only required if error)
+ if (other.field_type != nullptr)
+ field_type = other.field_type->clone_type ();
+ else
+ field_type = nullptr;
+
return *this;
}
@@ -1672,6 +1993,17 @@ public:
}
std::string as_string () const;
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_field_type ()
+ {
+ rust_assert (field_type != nullptr);
+ return field_type;
+ }
};
// Rust tuple declared using struct keyword AST node
@@ -1684,7 +2016,7 @@ public:
// Mega-constructor with all possible fields
TupleStruct (std::vector<TupleField> fields, Identifier struct_name,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
WhereClause where_clause, Visibility vis,
std::vector<Attribute> outer_attrs, Location locus)
: Struct (std::move (struct_name), std::move (generic_params),
@@ -1695,6 +2027,10 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<TupleField> &get_fields () { return fields; }
+ const std::vector<TupleField> &get_fields () const { return fields; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -1702,12 +2038,6 @@ protected:
{
return new TupleStruct (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual TupleStruct* clone_statement_impl() const override {
- return new TupleStruct(*this);
- }*/
};
/* An item used in an "enum" tagged union - not abstract: base represents a
@@ -1744,6 +2074,14 @@ public:
// not pure virtual as not abstract
virtual void accept_vis (ASTVisitor &vis);
+ // Based on idea that name is never empty.
+ void mark_for_strip () { variant_name = ""; }
+ bool is_marked_for_strip () const { return variant_name.empty (); }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
protected:
// Clone function implementation as (not pure) virtual method
virtual EnumItem *clone_enum_item_impl () const
@@ -1772,6 +2110,13 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<TupleField> &get_tuple_fields () { return tuple_fields; }
+ const std::vector<TupleField> &get_tuple_fields () const
+ {
+ return tuple_fields;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
EnumItemTuple *clone_enum_item_impl () const override
@@ -1801,6 +2146,13 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<StructField> &get_struct_fields () { return struct_fields; }
+ const std::vector<StructField> &get_struct_fields () const
+ {
+ return struct_fields;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
EnumItemStruct *clone_enum_item_impl () const override
@@ -1845,6 +2197,13 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_expr ()
+ {
+ rust_assert (expression != nullptr);
+ return expression;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
EnumItemDiscriminant *clone_enum_item_impl () const override
@@ -1860,12 +2219,12 @@ class Enum : public VisItem
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
// bool has_where_clause;
WhereClause where_clause;
- std::vector<std::unique_ptr<EnumItem>> items;
+ std::vector<std::unique_ptr<EnumItem> > items;
Location locus;
@@ -1884,8 +2243,8 @@ public:
// Mega-constructor
Enum (Identifier enum_name, Visibility vis,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
- WhereClause where_clause, std::vector<std::unique_ptr<EnumItem>> items,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
+ WhereClause where_clause, std::vector<std::unique_ptr<EnumItem> > items,
std::vector<Attribute> outer_attrs, Location locus)
: VisItem (std::move (vis), std::move (outer_attrs)),
enum_name (std::move (enum_name)),
@@ -1937,16 +2296,37 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if name is empty, so base stripping on that.
+ void mark_for_strip () override { enum_name = ""; }
+ bool is_marked_for_strip () const override { return enum_name.empty (); }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<std::unique_ptr<EnumItem> > &get_variants () { return items; }
+ const std::vector<std::unique_ptr<EnumItem> > &get_variants () const
+ {
+ return items;
+ }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
Enum *clone_item_impl () const override { return new Enum (*this); }
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual Enum* clone_statement_impl() const override {
- return new Enum(*this);
- }*/
};
// Rust untagged union used for C compat AST node
@@ -1956,7 +2336,7 @@ class Union : public VisItem
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
// bool has_where_clause;
WhereClause where_clause;
@@ -1975,7 +2355,7 @@ public:
bool has_where_clause () const { return !where_clause.is_empty (); }
Union (Identifier union_name, Visibility vis,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
WhereClause where_clause, std::vector<StructField> variants,
std::vector<Attribute> outer_attrs, Location locus)
: VisItem (std::move (vis), std::move (outer_attrs)),
@@ -2020,16 +2400,34 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if name is empty, so base stripping on that.
+ void mark_for_strip () override { union_name = ""; }
+ bool is_marked_for_strip () const override { return union_name.empty (); }
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<StructField> &get_variants () { return variants; }
+ const std::vector<StructField> &get_variants () const { return variants; }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
Union *clone_item_impl () const override { return new Union (*this); }
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual Union* clone_statement_impl() const override {
- return new Union(*this);
- }*/
};
/* "Constant item" AST node - used for constant, compile-time expressions
@@ -2041,7 +2439,7 @@ class ConstantItem : public VisItem,
// either has an identifier or "_" - maybe handle in identifier?
// bool identifier_is_underscore;
// if no identifier declared, identifier will be "_"
- Identifier identifier;
+ std::string identifier;
std::unique_ptr<Type> type;
std::unique_ptr<Expr> const_expr;
@@ -2051,7 +2449,7 @@ class ConstantItem : public VisItem,
public:
std::string as_string () const override;
- ConstantItem (Identifier ident, Visibility vis, std::unique_ptr<Type> type,
+ ConstantItem (std::string ident, Visibility vis, std::unique_ptr<Type> type,
std::unique_ptr<Expr> const_expr,
std::vector<Attribute> outer_attrs, Location locus)
: VisItem (std::move (vis), std::move (outer_attrs)),
@@ -2060,20 +2458,32 @@ public:
{}
ConstantItem (ConstantItem const &other)
- : VisItem (other), identifier (other.identifier),
- type (other.type->clone_type ()),
- const_expr (other.const_expr->clone_expr ()), locus (other.locus)
- {}
+ : VisItem (other), identifier (other.identifier), locus (other.locus)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ if (other.const_expr != nullptr)
+ const_expr = other.const_expr->clone_expr ();
+ }
// Overload assignment operator to clone
ConstantItem &operator= (ConstantItem const &other)
{
VisItem::operator= (other);
identifier = other.identifier;
- type = other.type->clone_type ();
- const_expr = other.const_expr->clone_expr ();
locus = other.locus;
+ // guard to prevent null dereference (only required if error state)
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ else
+ type = nullptr;
+ if (other.const_expr != nullptr)
+ const_expr = other.const_expr->clone_expr ();
+ else
+ const_expr = nullptr;
+
return *this;
}
@@ -2083,12 +2493,37 @@ public:
/* Returns whether constant item is an "unnamed" (wildcard underscore used
* as identifier) constant. */
- bool is_unnamed () const { return identifier == std::string ("_"); }
+ bool is_unnamed () const { return identifier == "_"; }
Location get_locus () const { return locus; }
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if type or expression are null, so base stripping on that.
+ void mark_for_strip () override
+ {
+ type = nullptr;
+ const_expr = nullptr;
+ }
+ bool is_marked_for_strip () const override
+ {
+ return type == nullptr && const_expr == nullptr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_expr ()
+ {
+ rust_assert (const_expr != nullptr);
+ return const_expr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (type != nullptr);
+ return type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -2110,12 +2545,6 @@ protected:
{
return new ConstantItem (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual ConstantItem* clone_statement_impl() const override {
- return new ConstantItem(*this);
- }*/
};
/* Static item AST node - items within module scope with fixed storage
@@ -2142,9 +2571,14 @@ public:
// Copy constructor with clone
StaticItem (StaticItem const &other)
: VisItem (other), has_mut (other.has_mut), name (other.name),
- type (other.type->clone_type ()), expr (other.expr->clone_expr ()),
locus (other.locus)
- {}
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ if (other.expr != nullptr)
+ expr = other.expr->clone_expr ();
+ }
// Overloaded assignment operator to clone
StaticItem &operator= (StaticItem const &other)
@@ -2152,10 +2586,18 @@ public:
VisItem::operator= (other);
name = other.name;
has_mut = other.has_mut;
- type = other.type->clone_type ();
- expr = other.expr->clone_expr ();
locus = other.locus;
+ // guard to prevent null dereference (only required if error state)
+ if (other.type != nullptr)
+ type = other.type->clone_type ();
+ else
+ type = nullptr;
+ if (other.expr != nullptr)
+ expr = other.expr->clone_expr ();
+ else
+ expr = nullptr;
+
return *this;
}
@@ -2167,6 +2609,31 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if type or expression are null, so base stripping on that.
+ void mark_for_strip () override
+ {
+ type = nullptr;
+ expr = nullptr;
+ }
+ bool is_marked_for_strip () const override
+ {
+ return type == nullptr && expr == nullptr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_expr ()
+ {
+ rust_assert (expr != nullptr);
+ return expr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (type != nullptr);
+ return type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -2174,12 +2641,6 @@ protected:
{
return new StaticItem (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual StaticItem* clone_statement_impl() const override {
- return new StaticItem(*this);
- }*/
};
// Function declaration in traits
@@ -2192,7 +2653,7 @@ private:
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
// bool has_params;
// FunctionParams function_params;
@@ -2221,7 +2682,7 @@ public:
// Mega-constructor
TraitFunctionDecl (Identifier function_name, FunctionQualifiers qualifiers,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
std::vector<FunctionParam> function_params,
std::unique_ptr<Type> return_type,
WhereClause where_clause)
@@ -2236,10 +2697,12 @@ public:
// Copy constructor with clone
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)
+ function_params (other.function_params), 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 ());
@@ -2253,9 +2716,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 ());
@@ -2268,6 +2736,40 @@ 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;
+ }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_return_type ()
+ {
+ rust_assert (has_return_type ());
+ return return_type;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
};
// Actual trait item function declaration within traits
@@ -2292,6 +2794,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 ();
}
@@ -2303,8 +2806,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;
}
@@ -2319,6 +2826,31 @@ 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; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_definition ()
+ {
+ rust_assert (has_definition ());
+ return block_expr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ TraitFunctionDecl &get_trait_function_decl ()
+ {
+ // TODO: maybe only allow access if not marked for strip?
+ return decl;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
TraitItemFunc *clone_trait_item_impl () const override
@@ -2337,7 +2869,7 @@ private:
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
SelfParam self_param;
@@ -2368,7 +2900,7 @@ public:
// Mega-constructor
TraitMethodDecl (Identifier function_name, FunctionQualifiers qualifiers,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
SelfParam self_param,
std::vector<FunctionParam> function_params,
std::unique_ptr<Type> return_type, WhereClause where_clause)
@@ -2385,9 +2917,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 ());
@@ -2402,9 +2937,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 ());
@@ -2417,6 +2957,43 @@ 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;
+ }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_return_type ()
+ {
+ rust_assert (has_return_type ());
+ return return_type;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
+ SelfParam &get_self_param () { return self_param; }
+ const SelfParam &get_self_param () const { return self_param; }
};
// Actual trait item method declaration within traits
@@ -2439,9 +3016,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)
- {}
+ : 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 ();
+ }
// Overloaded assignment operator to clone
TraitItemMethod &operator= (TraitItemMethod const &other)
@@ -2449,9 +3029,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;
}
@@ -2465,6 +3050,31 @@ 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; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ TraitMethodDecl &get_trait_method_decl ()
+ {
+ // TODO: maybe only allow access if not marked for strip?
+ return decl;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_definition ()
+ {
+ rust_assert (has_definition ());
+ return block_expr;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
TraitItemMethod *clone_trait_item_impl () const override
@@ -2498,10 +3108,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)
@@ -2509,10 +3125,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;
}
@@ -2526,6 +3152,28 @@ 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; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_expr ()
+ {
+ rust_assert (expr != nullptr);
+ return expr;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (type != nullptr);
+ return type;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
TraitItemConst *clone_trait_item_impl () const override
@@ -2543,7 +3191,7 @@ class TraitItemType : public TraitItem
// bool has_type_param_bounds;
// TypeParamBounds type_param_bounds;
- std::vector<std::unique_ptr<TypeParamBound>>
+ std::vector<std::unique_ptr<TypeParamBound> >
type_param_bounds; // inlined form
Location locus;
@@ -2554,7 +3202,7 @@ public:
TraitItemType (
Identifier name,
- std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
+ std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds,
std::vector<Attribute> outer_attrs, Location locus)
: outer_attrs (std::move (outer_attrs)), name (std::move (name)),
type_param_bounds (std::move (type_param_bounds)), locus (locus)
@@ -2594,6 +3242,25 @@ 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; }
+
+ // TODO: mutable getter seems kinda dodgy
+ std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
+ {
+ return type_param_bounds;
+ }
+ const std::vector<std::unique_ptr<TypeParamBound> > &
+ get_type_param_bounds () const
+ {
+ return type_param_bounds;
+ }
+
protected:
// Clone function implementation as (not pure) virtual method
TraitItemType *clone_trait_item_impl () const override
@@ -2606,23 +3273,24 @@ protected:
class Trait : public VisItem
{
bool has_unsafe;
-
Identifier name;
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
// bool has_type_param_bounds;
// TypeParamBounds type_param_bounds;
- std::vector<std::unique_ptr<TypeParamBound>>
+ std::vector<std::unique_ptr<TypeParamBound> >
type_param_bounds; // inlined form
// bool has_where_clause;
WhereClause where_clause;
+ std::vector<Attribute> inner_attrs;
+
// bool has_trait_items;
- std::vector<std::unique_ptr<TraitItem>> trait_items;
+ std::vector<std::unique_ptr<TraitItem> > trait_items;
Location locus;
@@ -2641,25 +3309,31 @@ 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,
+ 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<std::unique_ptr<TraitItem> > trait_items, Visibility vis,
+ 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)),
+ 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)
@@ -2681,6 +3355,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 ());
@@ -2706,16 +3381,53 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Invalid if trait name is empty, so base stripping on that.
+ void mark_for_strip () override { name = ""; }
+ bool is_marked_for_strip () const override { return name.empty (); }
+
+ // 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;
+ }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ std::vector<std::unique_ptr<TypeParamBound> > &get_type_param_bounds ()
+ {
+ return type_param_bounds;
+ }
+ const std::vector<std::unique_ptr<TypeParamBound> > &
+ get_type_param_bounds () const
+ {
+ return type_param_bounds;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
Trait *clone_item_impl () const override { return new Trait (*this); }
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual Trait* clone_statement_impl() const override {
- return new Trait(*this);
- }*/
};
// Implementation item declaration AST node - abstract base class
@@ -2725,7 +3437,7 @@ class Impl : public VisItem
protected:
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
std::unique_ptr<Type> trait_type;
@@ -2751,9 +3463,40 @@ public:
Location get_locus () const { return locus; }
+ // Invalid if trait type is null, so base stripping on that.
+ void mark_for_strip () override { trait_type = nullptr; }
+ bool is_marked_for_strip () const override { return trait_type == nullptr; }
+
+ // 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; }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (trait_type != nullptr);
+ return trait_type;
+ }
+
protected:
// Mega-constructor
- Impl (std::vector<std::unique_ptr<GenericParam>> generic_params,
+ Impl (std::vector<std::unique_ptr<GenericParam> > generic_params,
std::unique_ptr<Type> trait_type, WhereClause where_clause,
Visibility vis, std::vector<Attribute> inner_attrs,
std::vector<Attribute> outer_attrs, Location locus)
@@ -2766,10 +3509,13 @@ protected:
// Copy constructor
Impl (Impl const &other)
- : VisItem (other), trait_type (other.trait_type->clone_type ()),
- where_clause (other.where_clause), inner_attrs (other.inner_attrs),
- locus (other.locus)
+ : VisItem (other), where_clause (other.where_clause),
+ inner_attrs (other.inner_attrs), locus (other.locus)
{
+ // guard to prevent null dereference (only required if error state)
+ if (other.trait_type != nullptr)
+ trait_type = other.trait_type->clone_type ();
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -2779,11 +3525,16 @@ protected:
Impl &operator= (Impl const &other)
{
VisItem::operator= (other);
- trait_type = other.trait_type->clone_type ();
where_clause = other.where_clause;
inner_attrs = other.inner_attrs;
locus = other.locus;
+ // guard to prevent null dereference (only required if error state)
+ if (other.trait_type != nullptr)
+ trait_type = other.trait_type->clone_type ();
+ else
+ trait_type = nullptr;
+
generic_params.reserve (other.generic_params.size ());
for (const auto &e : other.generic_params)
generic_params.push_back (e->clone_generic_param ());
@@ -2800,7 +3551,7 @@ protected:
class InherentImpl : public Impl
{
// bool has_impl_items;
- std::vector<std::unique_ptr<InherentImplItem>> impl_items;
+ std::vector<std::unique_ptr<InherentImplItem> > impl_items;
public:
std::string as_string () const override;
@@ -2809,8 +3560,8 @@ public:
bool has_impl_items () const { return !impl_items.empty (); }
// Mega-constructor
- InherentImpl (std::vector<std::unique_ptr<InherentImplItem>> impl_items,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ InherentImpl (std::vector<std::unique_ptr<InherentImplItem> > impl_items,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
std::unique_ptr<Type> trait_type, WhereClause where_clause,
Visibility vis, std::vector<Attribute> inner_attrs,
std::vector<Attribute> outer_attrs, Location locus)
@@ -2846,6 +3597,16 @@ 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 */
@@ -2853,12 +3614,6 @@ protected:
{
return new InherentImpl (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual InherentImpl* clone_statement_impl() const override {
- return new InherentImpl(*this);
- }*/
};
// The "impl footrait for foo" impl block declaration AST node
@@ -2869,7 +3624,7 @@ class TraitImpl : public Impl
TypePath trait_path;
// bool has_impl_items;
- std::vector<std::unique_ptr<TraitImplItem>> impl_items;
+ std::vector<std::unique_ptr<TraitImplItem> > impl_items;
public:
std::string as_string () const override;
@@ -2879,8 +3634,8 @@ public:
// Mega-constructor
TraitImpl (TypePath trait_path, bool is_unsafe, bool has_exclam,
- std::vector<std::unique_ptr<TraitImplItem>> impl_items,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<TraitImplItem> > impl_items,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
std::unique_ptr<Type> trait_type, WhereClause where_clause,
Visibility vis, std::vector<Attribute> inner_attrs,
std::vector<Attribute> outer_attrs, Location locus)
@@ -2924,18 +3679,30 @@ 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;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ TypePath &get_trait_path ()
+ {
+ // TODO: assert that trait path is not empty?
+ return trait_path;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
TraitImpl *clone_item_impl () const override { return new TraitImpl (*this); }
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual TraitImpl* clone_statement_impl() const override {
- return new TraitImpl(*this);
- }*/
};
+#if 0
// Abstract base class for an item used inside an extern block
class ExternalItem
{
@@ -2951,6 +3718,10 @@ class ExternalItem
public:
virtual ~ExternalItem () {}
+ /* TODO: spec syntax rules state that "MacroInvocationSemi" can be used as
+ * ExternalItem, but text body isn't so clear. Adding MacroInvocationSemi
+ * support would require a lot of refactoring. */
+
// Returns whether item has outer attributes.
bool has_outer_attrs () const { return !outer_attrs.empty (); }
@@ -2969,6 +3740,11 @@ public:
virtual void accept_vis (ASTVisitor &vis) = 0;
+ // TODO: make virtual? Would be more flexible.
+ // Based on idea that name should never be empty.
+ void mark_for_strip () { item_name = ""; };
+ bool is_marked_for_strip () const { return item_name.empty (); };
+
protected:
ExternalItem (Identifier item_name, Visibility vis,
std::vector<Attribute> outer_attrs, Location locus)
@@ -3003,10 +3779,20 @@ protected:
// possibly make this public if required
std::string get_item_name () const { return item_name; }
};
+#endif
// A static item used in an extern block
class ExternalStaticItem : public ExternalItem
{
+ // bool has_outer_attrs;
+ std::vector<Attribute> outer_attrs;
+
+ // bool has_visibility;
+ Visibility visibility;
+
+ Identifier item_name;
+ Location locus;
+
bool has_mut;
std::unique_ptr<Type> item_type;
@@ -3014,24 +3800,36 @@ public:
ExternalStaticItem (Identifier item_name, std::unique_ptr<Type> item_type,
bool is_mut, Visibility vis,
std::vector<Attribute> outer_attrs, Location locus)
- : ExternalItem (std::move (item_name), std::move (vis),
- std::move (outer_attrs), locus),
- has_mut (is_mut), item_type (std::move (item_type))
+ : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
+ item_name (std::move (item_name)), locus (locus), has_mut (is_mut),
+ item_type (std::move (item_type))
{}
// Copy constructor
ExternalStaticItem (ExternalStaticItem const &other)
- : ExternalItem (other), has_mut (other.has_mut),
- item_type (other.item_type->clone_type ())
- {}
+ : outer_attrs (other.outer_attrs), visibility (other.visibility),
+ item_name (other.item_name), locus (other.locus), has_mut (other.has_mut)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.item_type != nullptr)
+ item_type = other.item_type->clone_type ();
+ }
// Overloaded assignment operator to clone
ExternalStaticItem &operator= (ExternalStaticItem const &other)
{
- ExternalItem::operator= (other);
- item_type = other.item_type->clone_type ();
+ outer_attrs = other.outer_attrs;
+ visibility = other.visibility;
+ item_name = other.item_name;
+ locus = other.locus;
has_mut = other.has_mut;
+ // guard to prevent null dereference (only required if error state)
+ if (other.item_type != nullptr)
+ item_type = other.item_type->clone_type ();
+ else
+ item_type = nullptr;
+
return *this;
}
@@ -3043,6 +3841,29 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Returns whether item has outer attributes.
+ bool has_outer_attrs () const { return !outer_attrs.empty (); }
+
+ // Returns whether item has non-default visibility.
+ bool has_visibility () const { return !visibility.is_error (); }
+
+ Location get_locus () const { return locus; }
+
+ // Based on idea that type should never be null.
+ void mark_for_strip () override { item_type = nullptr; };
+ bool is_marked_for_strip () const override { return item_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; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (item_type != nullptr);
+ return item_type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -3057,17 +3878,22 @@ struct NamedFunctionParam
{
private:
// bool has_name; // otherwise is _
- Identifier name; // TODO: handle wildcard in identifier?
+ std::string name;
std::unique_ptr<Type> param_type;
// TODO: should this store location data?
+ // seemingly new since writing this node
+ std::vector<Attribute> outer_attrs;
+
public:
- // Returns whether the named function parameter has a name (i.e. name is not
- // '_').
+ /* Returns whether the named function parameter has a name (i.e. name is not
+ * '_'). */
bool has_name () const { return name != "_"; }
+ bool has_outer_attrs () const { return !outer_attrs.empty (); }
+
// Returns whether the named function parameter is in an error state.
bool is_error () const
{
@@ -3078,17 +3904,23 @@ public:
// Creates an error state named function parameter.
static NamedFunctionParam create_error ()
{
- return NamedFunctionParam ("", nullptr);
+ return NamedFunctionParam ("", nullptr, {});
}
- NamedFunctionParam (Identifier name, std::unique_ptr<Type> param_type)
- : name (std::move (name)), param_type (std::move (param_type))
+ NamedFunctionParam (std::string name, std::unique_ptr<Type> param_type,
+ std::vector<Attribute> outer_attrs)
+ : name (std::move (name)), param_type (std::move (param_type)),
+ outer_attrs (std::move (outer_attrs))
{}
// Copy constructor
NamedFunctionParam (NamedFunctionParam const &other)
- : name (other.name), param_type (other.param_type->clone_type ())
- {}
+ : name (other.name), outer_attrs (other.outer_attrs)
+ {
+ // guard to prevent null dereference (only required if error state)
+ if (other.param_type != nullptr)
+ param_type = other.param_type->clone_type ();
+ }
~NamedFunctionParam () = default;
@@ -3096,8 +3928,14 @@ public:
NamedFunctionParam &operator= (NamedFunctionParam const &other)
{
name = other.name;
- param_type = other.param_type->clone_type ();
// has_name = other.has_name;
+ outer_attrs = other.outer_attrs;
+
+ // guard to prevent null dereference (only required if error state)
+ if (other.param_type != nullptr)
+ param_type = other.param_type->clone_type ();
+ else
+ param_type = nullptr;
return *this;
}
@@ -3107,14 +3945,38 @@ public:
NamedFunctionParam &operator= (NamedFunctionParam &&other) = default;
std::string as_string () const;
+
+ // Based on idea that nane should never be empty.
+ void mark_for_strip () { param_type = nullptr; };
+ bool is_marked_for_strip () const { return is_error (); };
+
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ std::vector<Attribute> &get_outer_attrs () { return outer_attrs; }
+ const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_type ()
+ {
+ rust_assert (param_type != nullptr);
+ return param_type;
+ }
};
// A function item used in an extern block
class ExternalFunctionItem : public ExternalItem
{
+ // bool has_outer_attrs;
+ std::vector<Attribute> outer_attrs;
+
+ // bool has_visibility;
+ Visibility visibility;
+
+ Identifier item_name;
+ Location locus;
+
// bool has_generics;
// Generics generic_params;
- std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined
+ std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined
// bool has_return_type;
// FunctionReturnType return_type;
@@ -3125,6 +3987,7 @@ class ExternalFunctionItem : public ExternalItem
std::vector<NamedFunctionParam> function_params;
bool has_variadics;
+ std::vector<Attribute> variadic_outer_attrs;
public:
// Returns whether item has generic parameters.
@@ -3136,28 +3999,56 @@ public:
// Returns whether item has a where clause.
bool has_where_clause () const { return !where_clause.is_empty (); }
+ // Returns whether item has outer attributes.
+ bool has_outer_attrs () const { return !outer_attrs.empty (); }
+
+ // Returns whether item has non-default visibility.
+ bool has_visibility () const { return !visibility.is_error (); }
+
+ // Returns whether item has variadic parameters.
+ bool is_variadic () const { return has_variadics; }
+
+ // Returns whether item has outer attributes on its variadic parameters.
+ bool has_variadic_outer_attrs () const
+ {
+ return !variadic_outer_attrs.empty ();
+ }
+
+ Location get_locus () const { return locus; }
+
ExternalFunctionItem (
Identifier item_name,
- std::vector<std::unique_ptr<GenericParam>> generic_params,
+ std::vector<std::unique_ptr<GenericParam> > generic_params,
std::unique_ptr<Type> return_type, WhereClause where_clause,
std::vector<NamedFunctionParam> function_params, bool has_variadics,
- Visibility vis, std::vector<Attribute> outer_attrs, Location locus)
- : ExternalItem (std::move (item_name), std::move (vis),
- std::move (outer_attrs), locus),
+ std::vector<Attribute> variadic_outer_attrs, Visibility vis,
+ std::vector<Attribute> outer_attrs, Location locus)
+ : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)),
+ item_name (std::move (item_name)), locus (locus),
generic_params (std::move (generic_params)),
return_type (std::move (return_type)),
where_clause (std::move (where_clause)),
function_params (std::move (function_params)),
- has_variadics (has_variadics)
- {}
+ has_variadics (has_variadics),
+ variadic_outer_attrs (std::move (variadic_outer_attrs))
+ {
+ // TODO: assert that if has variadic outer attrs, then has_variadics is
+ // true?
+ }
// Copy constructor with clone
ExternalFunctionItem (ExternalFunctionItem const &other)
- : ExternalItem (other), return_type (other.return_type->clone_type ()),
+ : outer_attrs (other.outer_attrs), visibility (other.visibility),
+ item_name (other.item_name), locus (other.locus),
where_clause (other.where_clause),
function_params (other.function_params),
- has_variadics (other.has_variadics)
+ has_variadics (other.has_variadics),
+ variadic_outer_attrs (other.variadic_outer_attrs)
{
+ // guard to prevent null pointer 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 ());
@@ -3166,11 +4057,20 @@ public:
// Overloaded assignment operator with clone
ExternalFunctionItem &operator= (ExternalFunctionItem const &other)
{
- ExternalItem::operator= (other);
- return_type = other.return_type->clone_type ();
+ outer_attrs = other.outer_attrs;
+ visibility = other.visibility;
+ item_name = other.item_name;
+ locus = other.locus;
where_clause = other.where_clause;
function_params = other.function_params;
has_variadics = other.has_variadics;
+ variadic_outer_attrs = other.variadic_outer_attrs;
+
+ // guard to prevent null pointer 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)
@@ -3187,6 +4087,46 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Based on idea that nane should never be empty.
+ void mark_for_strip () override { item_name = ""; };
+ bool is_marked_for_strip () const override { return item_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; }
+
+ std::vector<NamedFunctionParam> &get_function_params ()
+ {
+ return function_params;
+ }
+ const std::vector<NamedFunctionParam> &get_function_params () const
+ {
+ return function_params;
+ }
+
+ std::vector<std::unique_ptr<GenericParam> > &get_generic_params ()
+ {
+ return generic_params;
+ }
+ const std::vector<std::unique_ptr<GenericParam> > &get_generic_params () const
+ {
+ return generic_params;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ WhereClause &get_where_clause ()
+ {
+ rust_assert (has_where_clause ());
+ return where_clause;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Type> &get_return_type ()
+ {
+ rust_assert (has_return_type ());
+ return return_type;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -3206,10 +4146,13 @@ class ExternBlock : public VisItem
std::vector<Attribute> inner_attrs;
// bool has_extern_items;
- std::vector<std::unique_ptr<ExternalItem>> extern_items;
+ std::vector<std::unique_ptr<ExternalItem> > extern_items;
Location locus;
+ // TODO: find another way to store this to save memory?
+ bool marked_for_strip = false;
+
public:
std::string as_string () const override;
@@ -3223,7 +4166,7 @@ public:
bool has_abi () const { return !abi.empty (); }
ExternBlock (std::string abi,
- std::vector<std::unique_ptr<ExternalItem>> extern_items,
+ std::vector<std::unique_ptr<ExternalItem> > extern_items,
Visibility vis, std::vector<Attribute> inner_attrs,
std::vector<Attribute> outer_attrs, Location locus)
: VisItem (std::move (vis), std::move (outer_attrs)), abi (std::move (abi)),
@@ -3234,7 +4177,7 @@ public:
// Copy constructor with vector clone
ExternBlock (ExternBlock const &other)
: VisItem (other), abi (other.abi), inner_attrs (other.inner_attrs),
- locus (other.locus)
+ locus (other.locus), marked_for_strip (other.marked_for_strip)
{
extern_items.reserve (other.extern_items.size ());
for (const auto &e : other.extern_items)
@@ -3248,6 +4191,7 @@ public:
abi = other.abi;
inner_attrs = other.inner_attrs;
locus = other.locus;
+ marked_for_strip = other.marked_for_strip;
extern_items.reserve (other.extern_items.size ());
for (const auto &e : other.extern_items)
@@ -3264,6 +4208,24 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // Can't think of any invalid invariants, so store boolean.
+ void mark_for_strip () override { marked_for_strip = true; }
+ bool is_marked_for_strip () const override { return marked_for_strip; }
+
+ // TODO: think of better way to do this
+ const std::vector<std::unique_ptr<ExternalItem> > &get_extern_items () const
+ {
+ return extern_items;
+ }
+ std::vector<std::unique_ptr<ExternalItem> > &get_extern_items ()
+ {
+ return extern_items;
+ }
+
+ // TODO: think of better way to do this
+ const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
+ std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
+
protected:
/* Use covariance to implement clone function as returning this object
* rather than base */
@@ -3271,12 +4233,6 @@ protected:
{
return new ExternBlock (*this);
}
-
- /* Use covariance to implement clone function as returning this object
- * rather than base */
- /*virtual ExternBlock* clone_statement_impl() const override {
- return new ExternBlock(*this);
- }*/
};
// Replaced with forward decls - defined in "rust-macro.h"