aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSimplyTheOther <simplytheother@gmail.com>2020-11-17 22:00:30 +0800
committerSimplyTheOther <simplytheother@gmail.com>2020-12-08 21:10:32 +0800
commit9b252167a77316750f34c455222e5f30724e51e4 (patch)
treee5a69430cc9104031ef958852605f15c6aa76494
parent4ec3b8d62b1b6ae79d55b71b423dcb04129884c6 (diff)
downloadgcc-9b252167a77316750f34c455222e5f30724e51e4.zip
gcc-9b252167a77316750f34c455222e5f30724e51e4.tar.gz
gcc-9b252167a77316750f34c455222e5f30724e51e4.tar.bz2
Added more expression cfg stripping
Fixed compile errors
-rw-r--r--gcc/rust/ast/rust-ast-full-test.cc12
-rw-r--r--gcc/rust/ast/rust-expr.h164
-rw-r--r--gcc/rust/backend/rust-compile.cc22
-rw-r--r--gcc/rust/expand/rust-macro-expand.cc532
4 files changed, 660 insertions, 70 deletions
diff --git a/gcc/rust/ast/rust-ast-full-test.cc b/gcc/rust/ast/rust-ast-full-test.cc
index f9dd99c..5601a1a 100644
--- a/gcc/rust/ast/rust-ast-full-test.cc
+++ b/gcc/rust/ast/rust-ast-full-test.cc
@@ -1700,10 +1700,8 @@ ReturnExpr::as_string () const
{
std::string str ("return ");
- if (has_return_expr ())
- {
+ if (has_returned_expr ())
str += return_expr->as_string ();
- }
return str;
}
@@ -2255,13 +2253,9 @@ WhileLetLoopExpr::as_string () const
str += "\n Label: ";
if (!has_loop_label ())
- {
str += "none";
- }
else
- {
str += loop_label.as_string ();
- }
str += "\n Match arm patterns: ";
if (match_arm_patterns.empty ())
@@ -2271,12 +2265,10 @@ WhileLetLoopExpr::as_string () const
else
{
for (const auto &pattern : match_arm_patterns)
- {
str += "\n " + pattern->as_string ();
- }
}
- str += "\n Scrutinee expr: " + condition->as_string ();
+ str += "\n Scrutinee expr: " + scrutinee->as_string ();
str += "\n Loop block: " + loop_block->as_string ();
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index 66ffe16..df77611 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -3281,7 +3281,6 @@ protected:
// Return expression AST node representation
class ReturnExpr : public ExprWithoutBlock
{
-public:
std::unique_ptr<Expr> return_expr;
Location locus;
@@ -3289,11 +3288,12 @@ public:
// TODO: find another way to store this to save memory?
bool marked_for_strip = false;
+public:
std::string as_string () const override;
/* Returns whether the object has an expression returned (i.e. not void return
* type). */
- bool has_return_expr () const { return return_expr != nullptr; }
+ bool has_returned_expr () const { return return_expr != nullptr; }
// Constructor for ReturnExpr.
ReturnExpr (Location locus, std::unique_ptr<Expr> returned_expr = nullptr,
@@ -3341,6 +3341,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<Expr> &get_returned_expr () {
+ rust_assert (return_expr != nullptr);
+ return return_expr;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3358,7 +3364,6 @@ class UnsafeBlockExpr : public ExprWithBlock
{
// Or just have it extend BlockExpr
std::unique_ptr<BlockExpr> expr;
-
Location locus;
public:
@@ -3408,6 +3413,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<BlockExpr> &get_block_expr () {
+ rust_assert (expr != nullptr);
+ return expr;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3422,7 +3433,6 @@ protected:
class LoopLabel /*: public Node*/
{
Lifetime label; // or type LIFETIME_OR_LABEL
-
Location locus;
public:
@@ -3504,6 +3514,12 @@ public:
// Invalid if loop block is null, so base stripping on that.
void mark_for_strip () override { loop_block = nullptr; }
bool is_marked_for_strip () const override { return loop_block == nullptr; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_loop_block () {
+ rust_assert (loop_block != nullptr);
+ return loop_block;
+ }
};
// 'Loop' expression (i.e. the infinite loop) AST node
@@ -3573,6 +3589,12 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_predicate_expr () {
+ rust_assert (condition != nullptr);
+ return condition;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3587,14 +3609,14 @@ class WhileLetLoopExpr : public BaseLoopExpr
{
// MatchArmPatterns patterns;
std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined
- std::unique_ptr<Expr> condition;
+ std::unique_ptr<Expr> scrutinee;
public:
std::string as_string () const override;
// Constructor with a loop label
WhileLetLoopExpr (std::vector<std::unique_ptr<Pattern> > match_arm_patterns,
- std::unique_ptr<Expr> condition,
+ std::unique_ptr<Expr> scrutinee,
std::unique_ptr<BlockExpr> loop_block, Location locus,
LoopLabel loop_label = LoopLabel::error (),
std::vector<Attribute> outer_attribs
@@ -3602,14 +3624,14 @@ public:
: BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label),
std::move (outer_attribs)),
match_arm_patterns (std::move (match_arm_patterns)),
- condition (std::move (condition))
+ scrutinee (std::move (scrutinee))
{}
// Copy constructor with clone
WhileLetLoopExpr (WhileLetLoopExpr const &other)
: BaseLoopExpr (other),
- /*match_arm_patterns(other.match_arm_patterns),*/ condition (
- other.condition->clone_expr ())
+ /*match_arm_patterns(other.match_arm_patterns),*/ scrutinee (
+ other.scrutinee->clone_expr ())
{
match_arm_patterns.reserve (other.match_arm_patterns.size ());
for (const auto &e : other.match_arm_patterns)
@@ -3621,7 +3643,7 @@ public:
{
BaseLoopExpr::operator= (other);
// match_arm_patterns = other.match_arm_patterns;
- condition = other.condition->clone_expr ();
+ scrutinee = other.scrutinee->clone_expr ();
// loop_block = other.loop_block->clone_block_expr();
// loop_label = other.loop_label;
// outer_attrs = other.outer_attrs;
@@ -3639,6 +3661,12 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_scrutinee_expr () {
+ rust_assert (scrutinee != nullptr);
+ return scrutinee;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3694,6 +3722,12 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_iterator_expr () {
+ rust_assert (iterator_expr != nullptr);
+ return iterator_expr;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3777,8 +3811,17 @@ public:
void vis_if_condition (ASTVisitor &vis) { condition->accept_vis (vis); }
void vis_if_block (ASTVisitor &vis) { if_block->accept_vis (vis); }
- Expr *get_if_condition () { return condition.get (); }
- BlockExpr *get_if_block () { return if_block.get (); }
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_condition_expr () {
+ rust_assert (condition != nullptr);
+ return condition;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_if_block () {
+ rust_assert (if_block != nullptr);
+ return if_block;
+ }
// Invalid if if block or condition is null, so base stripping on that.
void mark_for_strip () override { if_block = nullptr; condition = nullptr; }
@@ -3836,6 +3879,12 @@ public:
void vis_else_block (ASTVisitor &vis) { else_block->accept_vis (vis); }
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_else_block () {
+ rust_assert (else_block != nullptr);
+ return else_block;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3888,6 +3937,12 @@ public:
conseq_if_expr->accept_vis (vis);
}
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<IfExpr> &get_conseq_if_expr () {
+ rust_assert (conseq_if_expr != nullptr);
+ return conseq_if_expr;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -3976,6 +4031,18 @@ public:
void mark_for_strip () override { if_block = nullptr; value = nullptr; }
bool is_marked_for_strip () const override { return if_block == nullptr && value == nullptr; }
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_value_expr () {
+ rust_assert (value != nullptr);
+ return value;
+ }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_if_block () {
+ rust_assert (if_block != nullptr);
+ return if_block;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base (or rather this or any derived object) */
@@ -4030,6 +4097,12 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<IfLetExpr> &get_conseq_if_let_expr () {
+ rust_assert (if_let_expr != nullptr);
+ return if_let_expr;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -4082,6 +4155,12 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_else_block () {
+ rust_assert (else_block != nullptr);
+ return else_block;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -4133,6 +4212,12 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<IfExpr> &get_conseq_if_expr () {
+ rust_assert (if_expr != nullptr);
+ return if_expr;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -4184,6 +4269,12 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<IfLetExpr> &get_conseq_if_let_expr () {
+ rust_assert (if_let_expr != nullptr);
+ return if_let_expr;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -4265,6 +4356,16 @@ public:
}
std::string as_string () const;
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_guard_expr () {
+ rust_assert (has_match_arm_guard ());
+ return guard_expr;
+ }
+
+ // 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; }
};
/*
@@ -4330,6 +4431,18 @@ public:
~MatchCase () = default;
std::string as_string () const;
+
+ // 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?
+ MatchArm &get_arm () {
+ rust_assert (!arm.is_error ());
+ return arm;
+ }
};
#if 0
@@ -4502,6 +4615,19 @@ public:
void mark_for_strip () override { branch_value = nullptr; }
bool is_marked_for_strip () const override { return branch_value == nullptr; }
+ // TODO: this mutable getter seems really dodgy. Think up better way.
+ const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; }
+ std::vector<Attribute> &get_inner_attrs () { return inner_attrs; }
+
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_scrutinee_expr () {
+ rust_assert (branch_value != nullptr);
+ return branch_value;
+ }
+
+ const std::vector<MatchCase> &get_match_cases () const { return match_arms; }
+ std::vector<MatchCase> &get_match_cases () { return match_arms; }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -4515,7 +4641,6 @@ protected:
class AwaitExpr : public ExprWithoutBlock
{
std::unique_ptr<Expr> awaited_expr;
-
Location locus;
public:
@@ -4565,6 +4690,12 @@ public:
void mark_for_strip () override { awaited_expr = nullptr; }
bool is_marked_for_strip () const override { return awaited_expr == nullptr; }
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<Expr> &get_awaited_expr () {
+ rust_assert (awaited_expr != nullptr);
+ return awaited_expr;
+ }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -4580,7 +4711,6 @@ class AsyncBlockExpr : public ExprWithBlock
// TODO: should this extend BlockExpr rather than be a composite of it?
bool has_move;
std::unique_ptr<BlockExpr> block_expr;
-
Location locus;
public:
@@ -4630,6 +4760,12 @@ public:
void mark_for_strip () override { block_expr = nullptr; }
bool is_marked_for_strip () const override { return block_expr == nullptr; }
+ // TODO: is this better? Or is a "vis_block" better?
+ std::unique_ptr<BlockExpr> &get_block_expr () {
+ rust_assert (block_expr != nullptr);
+ return block_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 17d9cde..eb01b12 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -740,10 +740,10 @@ void
Compilation::visit (AST::ReturnExpr &expr)
{
Bexpression *ret = NULL;
- VISIT_POP (expr.return_expr->get_locus_slow (), expr.return_expr, ret, exprs);
+ VISIT_POP (expr.get_returned_expr ()->get_locus_slow (), expr.get_returned_expr ().get (), ret, exprs);
if (ret == NULL)
{
- rust_fatal_error (expr.return_expr->get_locus_slow (),
+ rust_fatal_error (expr.get_returned_expr ()->get_locus_slow (),
"failed to compile");
return;
}
@@ -778,11 +778,11 @@ void
Compilation::visit (AST::IfExpr &expr)
{
Bexpression *cond = NULL;
- VISIT_POP (expr.get_if_condition ()->get_locus_slow (),
- expr.get_if_condition (), cond, exprs);
+ VISIT_POP (expr.get_condition_expr ()->get_locus_slow (),
+ expr.get_condition_expr ().get (), cond, exprs);
if (cond == NULL)
{
- rust_error_at (expr.get_if_condition ()->get_locus_slow (),
+ rust_error_at (expr.get_condition_expr ()->get_locus_slow (),
"failed to compile");
return;
}
@@ -799,11 +799,11 @@ void
Compilation::visit (AST::IfExprConseqElse &expr)
{
Bexpression *cond = NULL;
- VISIT_POP (expr.get_if_condition ()->get_locus_slow (),
- expr.get_if_condition (), cond, exprs);
+ VISIT_POP (expr.get_condition_expr ()->get_locus_slow (),
+ expr.get_condition_expr ().get (), cond, exprs);
if (cond == NULL)
{
- rust_error_at (expr.get_if_condition ()->get_locus_slow (),
+ rust_error_at (expr.get_condition_expr ()->get_locus_slow (),
"failed to compile");
return;
}
@@ -824,11 +824,11 @@ void
Compilation::visit (AST::IfExprConseqIf &expr)
{
Bexpression *cond = NULL;
- VISIT_POP (expr.get_if_condition ()->get_locus_slow (),
- expr.get_if_condition (), cond, exprs);
+ VISIT_POP (expr.get_condition_expr ()->get_locus_slow (),
+ expr.get_condition_expr ().get (), cond, exprs);
if (cond == NULL)
{
- rust_error_at (expr.get_if_condition ()->get_locus_slow (),
+ rust_error_at (expr.get_condition_expr ()->get_locus_slow (),
"failed to compile");
return;
}
diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc
index 417f51b..7dd9750 100644
--- a/gcc/rust/expand/rust-macro-expand.cc
+++ b/gcc/rust/expand/rust-macro-expand.cc
@@ -956,23 +956,436 @@ namespace Rust {
rust_error_at(to_expr->get_locus_slow(),
"cannot strip expression in this position - outer attributes not allowed");
}
- void visit(AST::ReturnExpr& expr) override {}
- void visit(AST::UnsafeBlockExpr& expr) override {}
- void visit(AST::LoopExpr& expr) override {}
- void visit(AST::WhileLoopExpr& expr) override {}
- void visit(AST::WhileLetLoopExpr& expr) override {}
- void visit(AST::ForLoopExpr& expr) override {}
- void visit(AST::IfExpr& expr) override {}
- void visit(AST::IfExprConseqElse& expr) override {}
- void visit(AST::IfExprConseqIf& expr) override {}
- void visit(AST::IfExprConseqIfLet& expr) override {}
- void visit(AST::IfLetExpr& expr) override {}
- void visit(AST::IfLetExprConseqElse& expr) override {}
- void visit(AST::IfLetExprConseqIf& expr) override {}
- void visit(AST::IfLetExprConseqIfLet& expr) override {}
- void visit(AST::MatchExpr& expr) override {}
- void visit(AST::AwaitExpr& expr) override {}
- void visit(AST::AsyncBlockExpr& expr) override {}
+ void visit(AST::ReturnExpr& 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;
+ }
+
+ /* spec does not say that you can have outer attributes on
+ * expression, so assuming you can't. stripping for sub-expressions
+ * is the only thing that can be done */
+ if (expr.has_returned_expr()) {
+ auto& returned_expr = expr.get_returned_expr();
+
+ returned_expr->accept_vis(*this);
+
+ if (returned_expr->is_marked_for_strip())
+ rust_error_at(returned_expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
+ }
+ /* TODO: conceptually, you would maybe be able to remove a returned
+ * expr - e.g. if you had conditional compilation returning void or
+ * returning a type. On the other hand, I think that function
+ * return type cannot be conditionally compiled, so I assumed you
+ * can't do this either. */
+ }
+ void visit(AST::UnsafeBlockExpr& 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;
+ }
+
+ // can't strip block itself, but can strip sub-expressions
+ auto& block_expr = expr.get_block_expr();
+ block_expr->accept_vis(*this);
+ if (block_expr->is_marked_for_strip())
+ rust_error_at(block_expr->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
+ }
+ void visit(AST::LoopExpr& 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;
+ }
+
+ // can't strip block itself, but can strip sub-expressions
+ auto& loop_block = expr.get_loop_block();
+ loop_block->accept_vis(*this);
+ if (loop_block->is_marked_for_strip())
+ rust_error_at(loop_block->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
+ }
+ void visit(AST::WhileLoopExpr& 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;
+ }
+
+ // can't strip predicate expr itself, but can strip sub-expressions
+ auto& predicate_expr = expr.get_predicate_expr();
+ predicate_expr->accept_vis(*this);
+ if (predicate_expr->is_marked_for_strip())
+ rust_error_at(predicate_expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
+
+ // can't strip block itself, but can strip sub-expressions
+ auto& loop_block = expr.get_loop_block();
+ loop_block->accept_vis(*this);
+ if (loop_block->is_marked_for_strip())
+ rust_error_at(loop_block->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
+ }
+ void visit(AST::WhileLetLoopExpr& 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;
+ }
+
+ // can't strip scrutinee expr itself, but can strip sub-expressions
+ auto& scrutinee_expr = expr.get_scrutinee_expr();
+ scrutinee_expr->accept_vis(*this);
+ if (scrutinee_expr->is_marked_for_strip())
+ rust_error_at(scrutinee_expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
+
+ // can't strip block itself, but can strip sub-expressions
+ auto& loop_block = expr.get_loop_block();
+ loop_block->accept_vis(*this);
+ if (loop_block->is_marked_for_strip())
+ rust_error_at(loop_block->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
+ }
+ void visit(AST::ForLoopExpr& 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;
+ }
+
+ // can't strip scrutinee expr itself, but can strip sub-expressions
+ auto& iterator_expr = expr.get_iterator_expr();
+ iterator_expr->accept_vis(*this);
+ if (iterator_expr->is_marked_for_strip())
+ rust_error_at(iterator_expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
+
+ // can't strip block itself, but can strip sub-expressions
+ auto& loop_block = expr.get_loop_block();
+ loop_block->accept_vis(*this);
+ if (loop_block->is_marked_for_strip())
+ rust_error_at(loop_block->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
+ }
+ void visit(AST::IfExpr& 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;
+ }
+
+ // can't strip condition expr itself, but can strip sub-expressions
+ auto& condition_expr = expr.get_condition_expr();
+ condition_expr->accept_vis(*this);
+ if (condition_expr->is_marked_for_strip())
+ rust_error_at(condition_expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
+
+ // can't strip if block itself, but can strip sub-expressions
+ auto& if_block = expr.get_if_block();
+ if_block->accept_vis(*this);
+ if (if_block->is_marked_for_strip())
+ rust_error_at(if_block->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
+ }
+ void visit(AST::IfExprConseqElse& 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;
+ }
+
+ // can't strip condition expr itself, but can strip sub-expressions
+ auto& condition_expr = expr.get_condition_expr();
+ condition_expr->accept_vis(*this);
+ if (condition_expr->is_marked_for_strip())
+ rust_error_at(condition_expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
+
+ // can't strip if block itself, but can strip sub-expressions
+ auto& if_block = expr.get_if_block();
+ if_block->accept_vis(*this);
+ if (if_block->is_marked_for_strip())
+ rust_error_at(if_block->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
+
+ // can't strip else block itself, but can strip sub-expressions
+ auto& else_block = expr.get_else_block();
+ else_block->accept_vis(*this);
+ if (else_block->is_marked_for_strip())
+ rust_error_at(else_block->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
+ }
+ void visit(AST::IfExprConseqIf& 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;
+ }
+
+ // can't strip condition expr itself, but can strip sub-expressions
+ auto& condition_expr = expr.get_condition_expr();
+ condition_expr->accept_vis(*this);
+ if (condition_expr->is_marked_for_strip())
+ rust_error_at(condition_expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
+
+ // can't strip if block itself, but can strip sub-expressions
+ auto& if_block = expr.get_if_block();
+ if_block->accept_vis(*this);
+ if (if_block->is_marked_for_strip())
+ rust_error_at(if_block->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
+
+ // can't strip if expr itself, but can strip sub-expressions
+ auto& conseq_if_expr = expr.get_conseq_if_expr();
+ conseq_if_expr->accept_vis(*this);
+ if (conseq_if_expr->is_marked_for_strip())
+ rust_error_at(conseq_if_expr->get_locus_slow(),
+ "cannot strip consequent if expression in this position - outer attributes not allowed");
+ }
+ void visit(AST::IfExprConseqIfLet& 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;
+ }
+
+ // can't strip condition expr itself, but can strip sub-expressions
+ auto& condition_expr = expr.get_condition_expr();
+ condition_expr->accept_vis(*this);
+ if (condition_expr->is_marked_for_strip())
+ rust_error_at(condition_expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
+
+ // can't strip if block itself, but can strip sub-expressions
+ auto& if_block = expr.get_if_block();
+ if_block->accept_vis(*this);
+ if (if_block->is_marked_for_strip())
+ rust_error_at(if_block->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
+
+ // can't strip if let expr itself, but can strip sub-expressions
+ auto& conseq_if_let_expr = expr.get_conseq_if_let_expr();
+ conseq_if_let_expr->accept_vis(*this);
+ if (conseq_if_let_expr->is_marked_for_strip())
+ rust_error_at(conseq_if_let_expr->get_locus_slow(),
+ "cannot strip consequent if let expression in this position - outer attributes not allowed");
+ }
+ void visit(AST::IfLetExpr& 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;
+ }
+
+ // can't strip value expr itself, but can strip sub-expressions
+ auto& value_expr = expr.get_value_expr();
+ value_expr->accept_vis(*this);
+ if (value_expr->is_marked_for_strip())
+ rust_error_at(value_expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
+
+ // can't strip if block itself, but can strip sub-expressions
+ auto& if_block = expr.get_if_block();
+ if_block->accept_vis(*this);
+ if (if_block->is_marked_for_strip())
+ rust_error_at(if_block->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
+ }
+ void visit(AST::IfLetExprConseqElse& 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;
+ }
+
+ // can't strip value expr itself, but can strip sub-expressions
+ auto& value_expr = expr.get_value_expr();
+ value_expr->accept_vis(*this);
+ if (value_expr->is_marked_for_strip())
+ rust_error_at(value_expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
+
+ // can't strip if block itself, but can strip sub-expressions
+ auto& if_block = expr.get_if_block();
+ if_block->accept_vis(*this);
+ if (if_block->is_marked_for_strip())
+ rust_error_at(if_block->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
+
+ // can't strip else block itself, but can strip sub-expressions
+ auto& else_block = expr.get_else_block();
+ else_block->accept_vis(*this);
+ if (else_block->is_marked_for_strip())
+ rust_error_at(else_block->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
+ }
+ void visit(AST::IfLetExprConseqIf& 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;
+ }
+
+ // can't strip value expr itself, but can strip sub-expressions
+ auto& value_expr = expr.get_value_expr();
+ value_expr->accept_vis(*this);
+ if (value_expr->is_marked_for_strip())
+ rust_error_at(value_expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
+
+ // can't strip if block itself, but can strip sub-expressions
+ auto& if_block = expr.get_if_block();
+ if_block->accept_vis(*this);
+ if (if_block->is_marked_for_strip())
+ rust_error_at(if_block->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
+
+ // can't strip if expr itself, but can strip sub-expressions
+ auto& conseq_if_expr = expr.get_conseq_if_expr();
+ conseq_if_expr->accept_vis(*this);
+ if (conseq_if_expr->is_marked_for_strip())
+ rust_error_at(conseq_if_expr->get_locus_slow(),
+ "cannot strip consequent if expression in this position - outer attributes not allowed");
+ }
+ void visit(AST::IfLetExprConseqIfLet& 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;
+ }
+
+ // can't strip value expr itself, but can strip sub-expressions
+ auto& value_expr = expr.get_value_expr();
+ value_expr->accept_vis(*this);
+ if (value_expr->is_marked_for_strip())
+ rust_error_at(value_expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
+
+ // can't strip if block itself, but can strip sub-expressions
+ auto& if_block = expr.get_if_block();
+ if_block->accept_vis(*this);
+ if (if_block->is_marked_for_strip())
+ rust_error_at(if_block->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
+
+ // can't strip if let expr itself, but can strip sub-expressions
+ auto& conseq_if_let_expr = expr.get_conseq_if_let_expr();
+ conseq_if_let_expr->accept_vis(*this);
+ if (conseq_if_let_expr->is_marked_for_strip())
+ rust_error_at(conseq_if_let_expr->get_locus_slow(),
+ "cannot strip consequent if let expression in this position - outer attributes not allowed");
+ }
+ void visit(AST::MatchExpr& 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;
+ }
+
+ // inner attr strip test
+ expander.expand_cfg_attrs(expr.get_inner_attrs());
+ if (expander.fails_cfg(expr.get_inner_attrs())) {
+ expr.mark_for_strip();
+ return;
+ }
+
+ // can't strip scrutinee expr itself, but can strip sub-expressions
+ auto& scrutinee_expr = expr.get_scrutinee_expr();
+ scrutinee_expr->accept_vis(*this);
+ if (scrutinee_expr->is_marked_for_strip())
+ rust_error_at(scrutinee_expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
+
+ // strip match cases
+ auto& match_cases = expr.get_match_cases();
+ for (int i = 0; i < match_cases.size(); ) {
+ auto& match_case = match_cases[i];
+
+ // strip match case based on outer attributes in match arm
+ auto& match_arm = match_case.get_arm();
+ expander.expand_cfg_attrs(match_arm.get_outer_attrs());
+ if (expander.fails_cfg(match_arm.get_outer_attrs())) {
+ // strip match case
+ match_cases.erase(match_cases.begin() + i);
+ continue;
+ }
+
+ /* assuming that guard expression cannot be stripped as
+ * strictly speaking you would have to strip the whole guard to
+ * make syntactical sense, which you can't do. as such, only
+ * strip sub-expressions */
+ if (match_arm.has_match_arm_guard()) {
+ auto& guard_expr = match_arm.get_guard_expr();
+ guard_expr->accept_vis(*this);
+ if (guard_expr->is_marked_for_strip())
+ rust_error_at(guard_expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
+ }
+
+ // strip sub-expressions from match cases
+ auto& case_expr = match_case.get_expr();
+ case_expr->accept_vis(*this);
+ if (case_expr->is_marked_for_strip())
+ rust_error_at(case_expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
+
+ // increment to next case if haven't continued
+ i++;
+ }
+ }
+ void visit(AST::AwaitExpr& 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;
+ }
+
+ /* can't strip awaited expr itself, but can strip sub-expressions
+ * - this is because you can't have no expr to await */
+ auto& awaited_expr = expr.get_awaited_expr();
+ awaited_expr->accept_vis(*this);
+ if (awaited_expr->is_marked_for_strip())
+ rust_error_at(awaited_expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
+ }
+ void visit(AST::AsyncBlockExpr& 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;
+ }
+
+ // can't strip block itself, but can strip sub-expressions
+ auto& block_expr = expr.get_block_expr();
+ block_expr->accept_vis(*this);
+ if (block_expr->is_marked_for_strip())
+ rust_error_at(block_expr->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
+ }
void visit(AST::TypeParam& param) override {
// shouldn't require?
@@ -1001,8 +1414,12 @@ namespace Rust {
/* 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
+ // can't strip block itself, but can strip sub-expressions
+ auto& block_expr = method.get_definition();
+ block_expr->accept_vis(*this);
+ if (block_expr->is_marked_for_strip())
+ rust_error_at(block_expr->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
}
void visit(AST::ModuleBodied& module) override {
// strip test based on outer attrs
@@ -1080,8 +1497,12 @@ namespace Rust {
/* 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
+ // can't strip block itself, but can strip sub-expressions
+ auto& block_expr = function.get_definition();
+ block_expr->accept_vis(*this);
+ if (block_expr->is_marked_for_strip())
+ rust_error_at(block_expr->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
}
void visit(AST::TypeAlias& type_alias) override {
// initial test based on outer attrs
@@ -1158,7 +1579,11 @@ namespace Rust {
/* 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);
+ auto& expr = item.get_expr();
+ expr->accept_vis(*this);
+ if (expr->is_marked_for_strip())
+ rust_error_at(expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
}
void visit(AST::Enum& enum_item) override {
// initial test based on outer attrs
@@ -1206,7 +1631,11 @@ namespace Rust {
/* 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);
+ auto& expr = const_item.get_expr();
+ expr->accept_vis(*this);
+ if (expr->is_marked_for_strip())
+ rust_error_at(expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
}
void visit(AST::StaticItem& static_item) override {
// initial test based on outer attrs
@@ -1219,7 +1648,11 @@ namespace Rust {
/* 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);
+ auto& expr = static_item.get_expr();
+ expr->accept_vis(*this);
+ if (expr->is_marked_for_strip())
+ rust_error_at(expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
}
void visit(AST::TraitItemFunc& item) override {
// initial test based on outer attrs
@@ -1234,8 +1667,14 @@ namespace Rust {
expand_function_params(item.get_function_params());
if (item.has_definition()) {
- item.get_definition()->accept_vis(*this);
- // TODO: can block as a whole be invalidated here? Assuming no
+ /* strip any internal sub-expressions - expression itself isn't
+ * allowed to have external attributes in this position so can't be
+ * stripped. */
+ auto& block = item.get_definition();
+ block->accept_vis(*this);
+ if (block->is_marked_for_strip())
+ rust_error_at(block->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
}
}
void visit(AST::TraitItemMethod& item) override {
@@ -1255,8 +1694,14 @@ namespace Rust {
expand_function_params(item.get_function_params());
if (item.has_definition()) {
- item.get_definition()->accept_vis(*this);
- // TODO: can block as a whole be invalidated here? Assuming no
+ /* strip any internal sub-expressions - expression itself isn't
+ * allowed to have external attributes in this position so can't be
+ * stripped. */
+ auto& block = item.get_definition();
+ block->accept_vis(*this);
+ if (block->is_marked_for_strip())
+ rust_error_at(block->get_locus_slow(),
+ "cannot strip block expression in this position - outer attributes not allowed");
}
}
void visit(AST::TraitItemConst& item) override {
@@ -1270,8 +1715,13 @@ namespace Rust {
/* 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);
+ if (item.has_expression()) {
+ auto& expr = item.get_expr();
+ expr->accept_vis(*this);
+ if (expr->is_marked_for_strip())
+ rust_error_at(expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
+ }
}
void visit(AST::TraitItemType& item) override {
// initial test based on outer attrs
@@ -1474,7 +1924,9 @@ namespace Rust {
void visit(AST::StructPatternFieldTuplePat& field) override {}
void visit(AST::StructPatternFieldIdentPat& field) override {}
void visit(AST::StructPatternFieldIdent& field) override {}
- void visit(AST::StructPattern& pattern) override {}
+ void visit(AST::StructPattern& pattern) override {
+ // TODO: apparently struct pattern fields can have outer attrs. so can they be stripped?
+ }
void visit(AST::TupleStructItemsNoRange& tuple_items) override {}
void visit(AST::TupleStructItemsRange& tuple_items) override {}
void visit(AST::TupleStructPattern& pattern) override {}
@@ -1498,8 +1950,13 @@ namespace Rust {
/* 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);
+ if (stmt.has_init_expr()) {
+ auto& init_expr = stmt.get_init_expr();
+ init_expr->accept_vis(*this);
+ if (init_expr->is_marked_for_strip())
+ rust_error_at(init_expr->get_locus_slow(),
+ "cannot strip expression in this position - outer attributes not allowed");
+ }
}
void visit(AST::ExprStmtWithoutBlock& stmt) override {
// outer attributes associated with expr, so rely on expr
@@ -1543,10 +2000,15 @@ namespace Rust {
void visit(AST::NeverType& type) override {}
void visit(AST::RawPointerType& type) override {}
void visit(AST::ReferenceType& type) override {}
- void visit(AST::ArrayType& type) override {}
+ void visit(AST::ArrayType& type) override {
+ // TODO: array type contains a "constant expression" - could this have strippable sub-exprs?
+ }
void visit(AST::SliceType& type) override {}
void visit(AST::InferredType& type) override {}
- void visit(AST::BareFunctionType& type) override {}
+ void visit(AST::BareFunctionType& type) override {
+ // TODO: bare function type contains "maybe-named params" that have outer attributes - could this be strippable?
+ // apparently "attribute rules are same as on regular function params", so looks like a yes
+ }
};
void MacroExpander::expand_invoc(std::unique_ptr<AST::MacroInvocation>& invoc) {