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