diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-02-11 13:42:07 +0000 |
---|---|---|
committer | Philip Herron <herron.philip@googlemail.com> | 2021-02-13 09:54:32 +0000 |
commit | ebb5de23436436d4206766552e76cd4b802e0c74 (patch) | |
tree | fa7cf962d5c796e4a1c5e2dc72b6cf6345414671 | |
parent | 7366f6decf5ff3c652844913977582c9dec68d53 (diff) | |
download | gcc-ebb5de23436436d4206766552e76cd4b802e0c74.zip gcc-ebb5de23436436d4206766552e76cd4b802e0c74.tar.gz gcc-ebb5de23436436d4206766552e76cd4b802e0c74.tar.bz2 |
Add in ContinueExpr support
We made an implicit loop begin label that can be referenced in a goto to
restart the loop.
Fixes #188
-rw-r--r-- | gcc/rust/ast/rust-expr.h | 254 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-context.h | 15 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-expr.h | 55 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile-stmt.h | 19 | ||||
-rw-r--r-- | gcc/rust/hir/rust-ast-lower-expr.h | 15 | ||||
-rw-r--r-- | gcc/rust/hir/tree/rust-hir-expr.h | 2 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-expr.h | 24 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 12 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check.cc | 2 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/compilable/loop7.rs | 13 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/fail_compilation/continue1.rs | 9 |
11 files changed, 335 insertions, 85 deletions
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 5366fac..a7e7f1d 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -46,14 +46,14 @@ public: Literal::LitType get_lit_type () const { return literal.get_lit_type (); } LiteralExpr (std::string value_as_string, Literal::LitType type, - PrimitiveCoreType type_hint, - std::vector<Attribute> outer_attrs, Location locus) + PrimitiveCoreType type_hint, std::vector<Attribute> outer_attrs, + Location locus) : outer_attrs (std::move (outer_attrs)), literal (std::move (value_as_string), type, type_hint), locus (locus) {} - LiteralExpr (Literal literal, - std::vector<Attribute> outer_attrs, Location locus) + LiteralExpr (Literal literal, std::vector<Attribute> outer_attrs, + Location locus) : outer_attrs (std::move (outer_attrs)), literal (std::move (literal)), locus (locus) {} @@ -78,7 +78,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } protected: /* Use covariance to implement clone function as returning this object rather @@ -252,7 +255,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } }; /* Unary prefix & or &mut (or && and &&mut) borrow operator. Cannot be @@ -880,7 +886,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } GroupedExpr (std::unique_ptr<Expr> parenthesised_expr, std::vector<Attribute> inner_attribs, @@ -892,8 +901,8 @@ public: // Copy constructor includes clone for expr_in_parens GroupedExpr (GroupedExpr const &other) - : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), inner_attrs (other.inner_attrs), - locus (other.locus) + : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), + inner_attrs (other.inner_attrs), locus (other.locus) { // guard to prevent null dereference (only required if error state) if (other.expr_in_parens != nullptr) @@ -1120,7 +1129,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } // Returns whether array expr has array elems or if it is just empty. bool has_array_elems () const { return internal_elements != nullptr; } @@ -1136,8 +1148,9 @@ public: // Copy constructor requires cloning ArrayElems for polymorphism to hold ArrayExpr (ArrayExpr const &other) - : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), inner_attrs (other.inner_attrs), - locus (other.locus), marked_for_strip (other.marked_for_strip) + : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), + inner_attrs (other.inner_attrs), locus (other.locus), + marked_for_strip (other.marked_for_strip) { if (other.has_array_elems ()) internal_elements = other.internal_elements->clone_array_elems (); @@ -1214,7 +1227,8 @@ public: // Copy constructor requires special cloning due to unique_ptr ArrayIndexExpr (ArrayIndexExpr const &other) - : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), locus (other.locus) + : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), + locus (other.locus) { // guard to prevent null dereference (only required if error state) if (other.array_expr != nullptr) @@ -1280,7 +1294,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } protected: /* Use covariance to implement clone function as returning this object rather @@ -1311,7 +1328,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } TupleExpr (std::vector<std::unique_ptr<Expr> > tuple_elements, std::vector<Attribute> inner_attribs, @@ -1323,8 +1343,9 @@ public: // copy constructor with vector clone TupleExpr (TupleExpr const &other) - : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), inner_attrs (other.inner_attrs), - locus (other.locus), marked_for_strip (other.marked_for_strip) + : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), + inner_attrs (other.inner_attrs), locus (other.locus), + marked_for_strip (other.marked_for_strip) { tuple_elems.reserve (other.tuple_elems.size ()); for (const auto &e : other.tuple_elems) @@ -1410,8 +1431,8 @@ public: // Copy constructor requires a clone for tuple_expr TupleIndexExpr (TupleIndexExpr const &other) - : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), tuple_index (other.tuple_index), - locus (other.locus) + : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), + tuple_index (other.tuple_index), locus (other.locus) { // guard to prevent null dereference (only required if error state) if (other.tuple_expr != nullptr) @@ -1458,7 +1479,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } protected: /* Use covariance to implement clone function as returning this object rather @@ -1499,7 +1523,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } }; // Actual AST node of the struct creator (with no fields). Not abstract! @@ -2010,7 +2037,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } }; /* Base AST node for a single enum expression field (in enum instance creation) @@ -2350,7 +2380,8 @@ public: // copy constructor requires clone CallExpr (CallExpr const &other) - : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), locus (other.locus) + : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), + locus (other.locus) { // guard to prevent null dereference (only required if error state) if (other.function != nullptr) @@ -2423,7 +2454,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } protected: /* Use covariance to implement clone function as returning this object rather @@ -2458,8 +2492,8 @@ public: // copy constructor required due to cloning MethodCallExpr (MethodCallExpr const &other) - : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), method_name (other.method_name), - locus (other.locus) + : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), + method_name (other.method_name), locus (other.locus) { // guard to prevent null dereference (only required if error state) if (other.receiver != nullptr) @@ -2533,7 +2567,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } protected: /* Use covariance to implement clone function as returning this object rather @@ -2566,7 +2603,8 @@ public: // Copy constructor required due to unique_ptr cloning FieldAccessExpr (FieldAccessExpr const &other) - : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), field (other.field), locus (other.locus) + : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), + field (other.field), locus (other.locus) { // guard to prevent null dereference (only required if error state) if (other.receiver != nullptr) @@ -2615,7 +2653,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } protected: /* Use covariance to implement clone function as returning this object rather @@ -2740,7 +2781,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } }; // Represents a non-type-specified closure expression AST node @@ -2822,7 +2866,7 @@ class BlockExpr : public ExprWithBlock std::vector<Attribute> outer_attrs; std::vector<Attribute> inner_attrs; std::vector<std::unique_ptr<Stmt> > statements; - std::unique_ptr<ExprWithoutBlock> expr; + std::unique_ptr<ExprWithoutBlock> expr; Location locus; bool marked_for_strip = false; @@ -2847,8 +2891,9 @@ public: // Copy constructor with clone BlockExpr (BlockExpr const &other) - : ExprWithBlock (other), outer_attrs (other.outer_attrs), inner_attrs (other.inner_attrs), - locus (other.locus), marked_for_strip (other.marked_for_strip) + : ExprWithBlock (other), outer_attrs (other.outer_attrs), + inner_attrs (other.inner_attrs), locus (other.locus), + marked_for_strip (other.marked_for_strip) { // guard to protect from null pointer dereference if (other.expr != nullptr) @@ -2934,7 +2979,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } protected: /* Use covariance to implement clone function as returning this object rather @@ -3059,8 +3107,8 @@ public: bool has_label () const { return !label.is_error (); } // Constructor for a ContinueExpr with a label. - ContinueExpr (Lifetime label, - std::vector<Attribute> outer_attribs, Location locus) + ContinueExpr (Lifetime label, std::vector<Attribute> outer_attribs, + Location locus) : outer_attrs (std::move (outer_attribs)), label (std::move (label)), locus (locus) {} @@ -3077,7 +3125,12 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } + + Lifetime &get_label () { return label; } protected: /* Use covariance to implement clone function as returning this object rather @@ -3111,17 +3164,16 @@ public: bool has_break_expr () const { return break_expr != nullptr; } // Constructor for a break expression - BreakExpr (Lifetime break_label, - std::unique_ptr<Expr> expr_in_break, + BreakExpr (Lifetime break_label, std::unique_ptr<Expr> expr_in_break, std::vector<Attribute> outer_attribs, Location locus) - : outer_attrs (std::move (outer_attribs)), - label (std::move (break_label)), break_expr (std::move (expr_in_break)), - locus (locus) + : outer_attrs (std::move (outer_attribs)), label (std::move (break_label)), + break_expr (std::move (expr_in_break)), locus (locus) {} // Copy constructor defined to use clone for unique pointer BreakExpr (BreakExpr const &other) - : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), label (other.label), locus (other.locus), + : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), + label (other.label), locus (other.locus), marked_for_strip (other.marked_for_strip) { // guard to protect from null pointer dereference @@ -3170,8 +3222,11 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } - + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } + Lifetime &get_label () { return label; } protected: @@ -3197,7 +3252,10 @@ public: Location get_locus_slow () const final override { return get_locus (); } // should never be called - error if called - void set_outer_attrs (std::vector<Attribute> new_attrs) override { rust_assert (false); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + rust_assert (false); + } }; // Range from (inclusive) and to (exclusive) expression AST node object @@ -3608,8 +3666,8 @@ public: // Copy constructor with clone ReturnExpr (ReturnExpr const &other) - : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), locus (other.locus), - marked_for_strip (other.marked_for_strip) + : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), + locus (other.locus), marked_for_strip (other.marked_for_strip) { // guard to protect from null pointer dereference if (other.return_expr != nullptr) @@ -3656,7 +3714,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } protected: /* Use covariance to implement clone function as returning this object rather @@ -3689,7 +3750,8 @@ public: // Copy constructor with clone UnsafeBlockExpr (UnsafeBlockExpr const &other) - : ExprWithBlock (other), outer_attrs (other.outer_attrs), locus (other.locus) + : ExprWithBlock (other), outer_attrs (other.outer_attrs), + locus (other.locus) { // guard to prevent null dereference (only required if error state) if (other.expr != nullptr) @@ -3735,7 +3797,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } protected: /* Use covariance to implement clone function as returning this object rather @@ -3801,7 +3866,8 @@ protected: // Copy constructor for BaseLoopExpr with clone BaseLoopExpr (BaseLoopExpr const &other) - : ExprWithBlock (other), outer_attrs (other.outer_attrs), loop_label (other.loop_label), locus (other.locus) + : ExprWithBlock (other), outer_attrs (other.outer_attrs), + loop_label (other.loop_label), locus (other.locus) { // guard to prevent null dereference (only required if error state) if (other.loop_block != nullptr) @@ -3851,7 +3917,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } }; // 'Loop' expression (i.e. the infinite loop) AST node @@ -4105,13 +4174,15 @@ public: IfExpr (std::unique_ptr<Expr> condition, std::unique_ptr<BlockExpr> if_block, std::vector<Attribute> outer_attrs, Location locus) - : outer_attrs (std::move (outer_attrs)), condition (std::move (condition)), if_block (std::move (if_block)), - locus (locus) + : outer_attrs (std::move (outer_attrs)), condition (std::move (condition)), + if_block (std::move (if_block)), locus (locus) {} // outer attributes are never allowed on IfExprs // Copy constructor with clone - IfExpr (IfExpr const &other) : ExprWithBlock (other), outer_attrs (other.outer_attrs), locus (other.locus) + IfExpr (IfExpr const &other) + : ExprWithBlock (other), outer_attrs (other.outer_attrs), + locus (other.locus) { // guard to prevent null dereference (only required if error state) if (other.condition != nullptr) @@ -4187,7 +4258,10 @@ public: return if_block == nullptr && condition == nullptr; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } // TODO: this mutable getter seems really dodgy. Think up better way. const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } @@ -4215,8 +4289,10 @@ public: IfExprConseqElse (std::unique_ptr<Expr> condition, std::unique_ptr<BlockExpr> if_block, - std::unique_ptr<BlockExpr> else_block, std::vector<Attribute> outer_attrs, Location locus) - : IfExpr (std::move (condition), std::move (if_block), std::move (outer_attrs), locus), + std::unique_ptr<BlockExpr> else_block, + std::vector<Attribute> outer_attrs, Location locus) + : IfExpr (std::move (condition), std::move (if_block), + std::move (outer_attrs), locus), else_block (std::move (else_block)) {} // again, outer attributes not allowed @@ -4271,8 +4347,10 @@ public: IfExprConseqIf (std::unique_ptr<Expr> condition, std::unique_ptr<BlockExpr> if_block, - std::unique_ptr<IfExpr> conseq_if_expr, std::vector<Attribute> outer_attrs, Location locus) - : IfExpr (std::move (condition), std::move (if_block), std::move (outer_attrs), locus), + std::unique_ptr<IfExpr> conseq_if_expr, + std::vector<Attribute> outer_attrs, Location locus) + : IfExpr (std::move (condition), std::move (if_block), + std::move (outer_attrs), locus), conseq_if_expr (std::move (conseq_if_expr)) {} // outer attributes not allowed @@ -4333,8 +4411,8 @@ public: std::string as_string () const override; IfLetExpr (std::vector<std::unique_ptr<Pattern> > match_arm_patterns, - std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block, std::vector<Attribute> outer_attrs, - Location locus) + std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block, + std::vector<Attribute> outer_attrs, Location locus) : match_arm_patterns (std::move (match_arm_patterns)), value (std::move (value)), if_block (std::move (if_block)), locus (locus) {} @@ -4342,7 +4420,8 @@ public: // copy constructor with clone IfLetExpr (IfLetExpr const &other) - : ExprWithBlock (other), outer_attrs (other.outer_attrs), locus (other.locus) + : ExprWithBlock (other), outer_attrs (other.outer_attrs), + locus (other.locus) { // guard to prevent null dereference (only required if error state) if (other.value != nullptr) @@ -4429,7 +4508,10 @@ public: return match_arm_patterns; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } // TODO: this mutable getter seems really dodgy. Think up better way. const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } @@ -4460,9 +4542,10 @@ public: IfExprConseqIfLet (std::unique_ptr<Expr> condition, std::unique_ptr<BlockExpr> if_block, - std::unique_ptr<IfLetExpr> conseq_if_let_expr, std::vector<Attribute> outer_attrs, - Location locus) - : IfExpr (std::move (condition), std::move (if_block), std::move (outer_attrs), locus), + std::unique_ptr<IfLetExpr> conseq_if_let_expr, + std::vector<Attribute> outer_attrs, Location locus) + : IfExpr (std::move (condition), std::move (if_block), + std::move (outer_attrs), locus), if_let_expr (std::move (conseq_if_let_expr)) {} // outer attributes not allowed @@ -4517,7 +4600,8 @@ public: IfLetExprConseqElse ( std::vector<std::unique_ptr<Pattern> > match_arm_patterns, std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block, - std::unique_ptr<BlockExpr> else_block, std::vector<Attribute> outer_attrs, Location locus) + std::unique_ptr<BlockExpr> else_block, std::vector<Attribute> outer_attrs, + Location locus) : IfLetExpr (std::move (match_arm_patterns), std::move (value), std::move (if_block), std::move (outer_attrs), locus), else_block (std::move (else_block)) @@ -4576,7 +4660,8 @@ public: IfLetExprConseqIf (std::vector<std::unique_ptr<Pattern> > match_arm_patterns, std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block, - std::unique_ptr<IfExpr> if_expr, std::vector<Attribute> outer_attrs, Location locus) + std::unique_ptr<IfExpr> if_expr, + std::vector<Attribute> outer_attrs, Location locus) : IfLetExpr (std::move (match_arm_patterns), std::move (value), std::move (if_block), std::move (outer_attrs), locus), if_expr (std::move (if_expr)) @@ -4634,7 +4719,8 @@ public: IfLetExprConseqIfLet ( std::vector<std::unique_ptr<Pattern> > match_arm_patterns, std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block, - std::unique_ptr<IfLetExpr> if_let_expr, std::vector<Attribute> outer_attrs, Location locus) + std::unique_ptr<IfLetExpr> if_let_expr, std::vector<Attribute> outer_attrs, + Location locus) : IfLetExpr (std::move (match_arm_patterns), std::move (value), std::move (if_block), std::move (outer_attrs), locus), if_let_expr (std::move (if_let_expr)) @@ -4970,8 +5056,9 @@ public: // Copy constructor requires clone due to unique_ptr MatchExpr (MatchExpr const &other) - : ExprWithBlock (other), outer_attrs (other.outer_attrs), inner_attrs (other.inner_attrs), - match_arms (other.match_arms), locus (other.locus) + : ExprWithBlock (other), outer_attrs (other.outer_attrs), + inner_attrs (other.inner_attrs), match_arms (other.match_arms), + locus (other.locus) { // guard to prevent null dereference (only required if error state) if (other.branch_value != nullptr) @@ -5016,7 +5103,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } // TODO: is this better? Or is a "vis_block" better? std::unique_ptr<Expr> &get_scrutinee_expr () @@ -5054,7 +5144,8 @@ public: // copy constructor with clone AwaitExpr (AwaitExpr const &other) - : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), locus (other.locus) + : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), + locus (other.locus) { // guard to prevent null dereference (only required if error state) if (other.awaited_expr != nullptr) @@ -5102,7 +5193,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } protected: /* Use covariance to implement clone function as returning this object rather @@ -5131,7 +5225,8 @@ public: // copy constructor with clone AsyncBlockExpr (AsyncBlockExpr const &other) - : ExprWithBlock (other), outer_attrs (other.outer_attrs), has_move (other.has_move), locus (other.locus) + : ExprWithBlock (other), outer_attrs (other.outer_attrs), + has_move (other.has_move), locus (other.locus) { // guard to prevent null dereference (only required if error state) if (other.block_expr != nullptr) @@ -5180,7 +5275,10 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - void set_outer_attrs (std::vector<Attribute> new_attrs) override { outer_attrs = std::move (new_attrs); } + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } protected: /* Use covariance to implement clone function as returning this object rather diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h index 288b917..76255b0 100644 --- a/gcc/rust/backend/rust-compile-context.h +++ b/gcc/rust/backend/rust-compile-context.h @@ -219,6 +219,20 @@ public: return back; } + void push_loop_begin_label (Blabel *label) + { + loop_begin_labels.push_back (label); + } + + Blabel *peek_loop_begin_label () { return loop_begin_labels.back (); } + + Blabel *pop_loop_begin_label () + { + Blabel *pop = loop_begin_labels.back (); + loop_begin_labels.pop_back (); + return pop; + } + private: ::Backend *backend; Resolver::Resolver *resolver; @@ -235,6 +249,7 @@ private: std::vector< ::std::vector<Bstatement *> > statements; std::vector< ::Bblock *> scope_stack; std::vector< ::Bvariable *> loop_value_stack; + std::vector< ::Blabel *> loop_begin_labels; // To GCC middle-end std::vector< ::Btype *> type_decls; diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h index 1ca7631..1e4aef6 100644 --- a/gcc/rust/backend/rust-compile-expr.h +++ b/gcc/rust/backend/rust-compile-expr.h @@ -625,6 +625,13 @@ public: loop_label.get_lifetime ().get_mappings ().get_hirid (), label); } + Blabel *loop_begin_label + = ctx->get_backend ()->label (fnctx.fndecl, "", expr.get_locus ()); + Bstatement *loop_begin_label_decl + = ctx->get_backend ()->label_definition_statement (loop_begin_label); + ctx->add_statement (loop_begin_label_decl); + ctx->push_loop_begin_label (loop_begin_label); + Bblock *code_block = CompileBlock::compile (expr.get_loop_block ().get (), ctx, nullptr); Bexpression *loop_expr @@ -639,6 +646,7 @@ public: translated = ctx->get_backend ()->var_expression (tmp, expr.get_locus ()); } + ctx->pop_loop_begin_label (); } void visit (HIR::WhileLoopExpr &expr) @@ -668,6 +676,13 @@ public: start_location, end_location); ctx->push_block (loop_block); + Blabel *loop_begin_label + = ctx->get_backend ()->label (fnctx.fndecl, "", expr.get_locus ()); + Bstatement *loop_begin_label_decl + = ctx->get_backend ()->label_definition_statement (loop_begin_label); + ctx->add_statement (loop_begin_label_decl); + ctx->push_loop_begin_label (loop_begin_label); + Bexpression *condition = CompileExpr::Compile (expr.get_predicate_expr ().get (), ctx); Bexpression *exit_expr @@ -682,6 +697,7 @@ public: = ctx->get_backend ()->block_statement (code_block); ctx->add_statement (code_block_stmt); + ctx->pop_loop_begin_label (); ctx->pop_block (); Bexpression *loop_expr @@ -754,6 +770,45 @@ public: } } + void visit (HIR::ContinueExpr &expr) + { + Blabel *label = ctx->peek_loop_begin_label (); + if (expr.has_label ()) + { + NodeId resolved_node_id = UNKNOWN_NODEID; + if (!ctx->get_resolver ()->lookup_resolved_label ( + expr.get_label ().get_mappings ().get_nodeid (), + &resolved_node_id)) + { + rust_error_at ( + expr.get_label ().get_locus (), + "failed to resolve compiled label for label %s", + expr.get_label ().get_mappings ().as_string ().c_str ()); + return; + } + + HirId ref = UNKNOWN_HIRID; + if (!ctx->get_mappings ()->lookup_node_to_hir ( + expr.get_mappings ().get_crate_num (), resolved_node_id, &ref)) + { + rust_fatal_error (expr.get_locus (), + "reverse lookup label failure"); + return; + } + + if (!ctx->lookup_label_decl (ref, &label)) + { + rust_error_at (expr.get_label ().get_locus (), + "failed to lookup compiled label"); + return; + } + } + + Bstatement *goto_label + = ctx->get_backend ()->goto_statement (label, expr.get_locus ()); + ctx->add_statement (goto_label); + } + private: CompileExpr (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {} diff --git a/gcc/rust/backend/rust-compile-stmt.h b/gcc/rust/backend/rust-compile-stmt.h index d021240e4..add969a 100644 --- a/gcc/rust/backend/rust-compile-stmt.h +++ b/gcc/rust/backend/rust-compile-stmt.h @@ -66,10 +66,6 @@ public: return; } - // there is an ICE in GCC for void_node - if (ty->get_kind () == TyTy::TypeKind::UNIT) - return; - Bvariable *var = nullptr; if (!ctx->lookup_var_decl (stmt.get_mappings ().get_hirid (), &var)) { @@ -79,10 +75,21 @@ public: } Bexpression *init = CompileExpr::Compile (stmt.get_init_expr (), ctx); + if (init == nullptr) + return; auto fnctx = ctx->peek_fn (); - auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var, init); - ctx->add_statement (s); + if (ty->get_kind () == TyTy::TypeKind::UNIT) + { + Bstatement *expr_stmt + = ctx->get_backend ()->expression_statement (fnctx.fndecl, init); + ctx->add_statement (expr_stmt); + } + else + { + auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var, init); + ctx->add_statement (s); + } } private: diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index 8e80c7a..6921e6d 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -725,6 +725,21 @@ public: std::move (outer_attribs)); } + void visit (AST::ContinueExpr &expr) + { + std::vector<HIR::Attribute> outer_attribs; + HIR::Lifetime break_label = lower_lifetime (expr.get_label ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated = new HIR::ContinueExpr (mapping, expr.get_locus (), + std ::move (break_label), + std::move (outer_attribs)); + } + private: ASTLoweringExpr () : ASTLoweringBase (), translated (nullptr), diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 3fd2ebc..95ba7f8 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -2724,6 +2724,8 @@ public: void accept_vis (HIRVisitor &vis) override; + Lifetime &get_label () { return label; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index 38a878c..d7bd6ab 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -327,6 +327,30 @@ public: ResolveExpr::go (expr.get_loop_block ().get (), expr.get_node_id ()); } + void visit (AST::ContinueExpr &expr) + { + if (expr.has_label ()) + { + auto label = expr.get_label (); + if (label.get_lifetime_type () != AST::Lifetime::LifetimeType::NAMED) + { + rust_error_at (label.get_locus (), + "Labels must be a named lifetime value"); + return; + } + + NodeId resolved_node = UNKNOWN_NODEID; + if (!resolver->get_label_scope ().lookup (label.get_lifetime_name (), + &resolved_node)) + { + rust_error_at (expr.get_label ().get_locus (), + "failed to resolve label"); + return; + } + resolver->insert_resolved_label (label.get_node_id (), resolved_node); + } + } + private: ResolveExpr (NodeId parent) : ResolverBase (parent) {} }; diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 7062f54..f8497db 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -823,6 +823,18 @@ public: infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); } + void visit (HIR::ContinueExpr &expr) + { + if (!inside_loop) + { + rust_error_at (expr.get_locus (), + "cannot `continue` outside of a loop"); + return; + } + + infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); + } + private: TypeCheckExpr (bool inside_loop) : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr), diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index 00a92b0..7f9bc69 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -127,7 +127,7 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) else if (resolved->get_kind () != TyTy::TypeKind::UNIT) { rust_error_at (s->get_locus_slow (), "expected () got %s", - infered->as_string ().c_str ()); + resolved->as_string ().c_str ()); } return true; diff --git a/gcc/testsuite/rust.test/compilable/loop7.rs b/gcc/testsuite/rust.test/compilable/loop7.rs new file mode 100644 index 0000000..0cd8445 --- /dev/null +++ b/gcc/testsuite/rust.test/compilable/loop7.rs @@ -0,0 +1,13 @@ +fn main() { + let mut a = 1; + let mut b = 1; + + let _fib = loop { + if (a % 2 == 0) { + continue; + } + let c = a + b; + a = b; + b = c; + }; +} diff --git a/gcc/testsuite/rust.test/fail_compilation/continue1.rs b/gcc/testsuite/rust.test/fail_compilation/continue1.rs new file mode 100644 index 0000000..2ec25a4 --- /dev/null +++ b/gcc/testsuite/rust.test/fail_compilation/continue1.rs @@ -0,0 +1,9 @@ +fn main() { + let mut a = 1; + let mut b = 1; + + let _fib = { + continue; + 123 + }; +} |