diff options
author | Philip Herron <philip.herron@embecosm.com> | 2021-02-10 17:01:48 +0000 |
---|---|---|
committer | Philip Herron <herron.philip@googlemail.com> | 2021-02-10 18:10:57 +0000 |
commit | d02ab5925b612678beb975d99951b1d2052958a1 (patch) | |
tree | 8d3aab8d2d2d4ede40eda66d6ed0a166000798b8 /gcc | |
parent | 06c9fd97bf3d86a08eadcadb1bc59cb392116d16 (diff) | |
download | gcc-d02ab5925b612678beb975d99951b1d2052958a1.zip gcc-d02ab5925b612678beb975d99951b1d2052958a1.tar.gz gcc-d02ab5925b612678beb975d99951b1d2052958a1.tar.bz2 |
Add check for break outside of a loop.
This will be needed to stop the compiler proceding to continue and break
expressions without a loop context.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-expr.h | 84 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-implitem.h | 8 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-item.h | 2 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-stmt.h | 16 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check-toplevel.h | 5 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-hir-type-check.cc | 14 | ||||
-rw-r--r-- | gcc/rust/typecheck/rust-tyty.cc | 6 | ||||
-rw-r--r-- | gcc/testsuite/rust.test/fail_compilation/break1.rs | 5 |
8 files changed, 85 insertions, 55 deletions
diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index c8493f0..6a45fef 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -32,9 +32,9 @@ namespace Resolver { class TypeCheckExpr : public TypeCheckBase { public: - static TyTy::TyBase *Resolve (HIR::Expr *expr) + static TyTy::TyBase *Resolve (HIR::Expr *expr, bool inside_loop) { - TypeCheckExpr resolver; + TypeCheckExpr resolver (inside_loop); expr->accept_vis (resolver); if (resolver.infered == nullptr) @@ -53,7 +53,8 @@ public: void visit (HIR::TupleIndexExpr &expr) { - auto resolved = TypeCheckExpr::Resolve (expr.get_tuple_expr ().get ()); + auto resolved + = TypeCheckExpr::Resolve (expr.get_tuple_expr ().get (), inside_loop); if (resolved == nullptr) { rust_error_at (expr.get_tuple_expr ()->get_locus_slow (), @@ -129,7 +130,7 @@ public: std::vector<HirId> fields; for (auto &elem : expr.get_tuple_elems ()) { - auto field_ty = TypeCheckExpr::Resolve (elem.get ()); + auto field_ty = TypeCheckExpr::Resolve (elem.get (), false); fields.push_back (field_ty->get_ref ()); } infered = new TyTy::TupleType (expr.get_mappings ().get_hirid (), fields); @@ -146,7 +147,7 @@ public: auto fn_return_tyty = context->peek_return_type (); rust_assert (fn_return_tyty != nullptr); - auto expr_ty = TypeCheckExpr::Resolve (expr.get_expr ()); + auto expr_ty = TypeCheckExpr::Resolve (expr.get_expr (), false); if (expr_ty == nullptr) { rust_error_at (expr.get_locus (), @@ -162,7 +163,8 @@ public: void visit (HIR::CallExpr &expr) { - TyTy::TyBase *function_tyty = TypeCheckExpr::Resolve (expr.get_fnexpr ()); + TyTy::TyBase *function_tyty + = TypeCheckExpr::Resolve (expr.get_fnexpr (), false); if (function_tyty == nullptr) return; @@ -178,7 +180,8 @@ public: void visit (HIR::MethodCallExpr &expr) { - auto receiver_tyty = TypeCheckExpr::Resolve (expr.get_receiver ().get ()); + auto receiver_tyty + = TypeCheckExpr::Resolve (expr.get_receiver ().get (), false); if (receiver_tyty == nullptr) { rust_error_at (expr.get_receiver ()->get_locus_slow (), @@ -239,8 +242,8 @@ public: { infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); - auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); - auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); + auto lhs = TypeCheckExpr::Resolve (expr.get_lhs (), false); + auto rhs = TypeCheckExpr::Resolve (expr.get_rhs (), false); auto result = lhs->combine (rhs); if (result == nullptr) @@ -446,8 +449,8 @@ public: void visit (HIR::ArithmeticOrLogicalExpr &expr) { - auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); - auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); + auto lhs = TypeCheckExpr::Resolve (expr.get_lhs (), false); + auto rhs = TypeCheckExpr::Resolve (expr.get_rhs (), false); bool valid_lhs = validate_arithmetic_type (lhs, expr.get_expr_type ()); bool valid_rhs = validate_arithmetic_type (rhs, expr.get_expr_type ()); @@ -467,8 +470,8 @@ public: void visit (HIR::ComparisonExpr &expr) { - auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); - auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); + auto lhs = TypeCheckExpr::Resolve (expr.get_lhs (), false); + auto rhs = TypeCheckExpr::Resolve (expr.get_rhs (), false); auto result = lhs->combine (rhs); if (result == nullptr || result->get_kind () == TyTy::TypeKind::ERROR) @@ -482,8 +485,8 @@ public: void visit (HIR::LazyBooleanExpr &expr) { - auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); - auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); + auto lhs = TypeCheckExpr::Resolve (expr.get_lhs (), false); + auto rhs = TypeCheckExpr::Resolve (expr.get_rhs (), false); // we expect the lhs and rhs must be bools at this point TyTy::BoolType elhs (expr.get_mappings ().get_hirid ()); @@ -503,7 +506,7 @@ public: void visit (HIR::NegationExpr &expr) { - auto negated_expr_ty = TypeCheckExpr::Resolve (expr.get_expr ()); + auto negated_expr_ty = TypeCheckExpr::Resolve (expr.get_expr (), false); // https://doc.rust-lang.org/reference/expressions/operator-expr.html#negation-operators switch (expr.get_negation_type ()) @@ -552,26 +555,29 @@ public: void visit (HIR::IfExpr &expr) { - TypeCheckExpr::Resolve (expr.get_if_condition ()); - TypeCheckExpr::Resolve (expr.get_if_block ()); + TypeCheckExpr::Resolve (expr.get_if_condition (), false); + TypeCheckExpr::Resolve (expr.get_if_block (), inside_loop); infered = new TyTy::UnitType (expr.get_mappings ().get_hirid ()); } void visit (HIR::IfExprConseqElse &expr) { - TypeCheckExpr::Resolve (expr.get_if_condition ()); - auto if_blk_resolved = TypeCheckExpr::Resolve (expr.get_if_block ()); - auto else_blk_resolved = TypeCheckExpr::Resolve (expr.get_else_block ()); + TypeCheckExpr::Resolve (expr.get_if_condition (), false); + auto if_blk_resolved + = TypeCheckExpr::Resolve (expr.get_if_block (), inside_loop); + auto else_blk_resolved + = TypeCheckExpr::Resolve (expr.get_else_block (), inside_loop); infered = if_blk_resolved->combine (else_blk_resolved); } void visit (HIR::IfExprConseqIf &expr) { - TypeCheckExpr::Resolve (expr.get_if_condition ()); - auto if_blk = TypeCheckExpr::Resolve (expr.get_if_block ()); - auto else_blk = TypeCheckExpr::Resolve (expr.get_conseq_if_expr ()); + TypeCheckExpr::Resolve (expr.get_if_condition (), false); + auto if_blk = TypeCheckExpr::Resolve (expr.get_if_block (), inside_loop); + auto else_blk + = TypeCheckExpr::Resolve (expr.get_conseq_if_expr (), inside_loop); infered = if_blk->combine (else_blk); } @@ -589,8 +595,8 @@ public: return; } - auto resolved_index_expr - = size_ty->combine (TypeCheckExpr::Resolve (expr.get_index_expr ())); + auto resolved_index_expr = size_ty->combine ( + TypeCheckExpr::Resolve (expr.get_index_expr (), false)); if (resolved_index_expr == nullptr) { rust_error_at (expr.get_index_expr ()->get_locus_slow (), @@ -637,7 +643,7 @@ public: { std::vector<TyTy::TyBase *> types; elems.iterate ([&] (HIR::Expr *e) mutable -> bool { - types.push_back (TypeCheckExpr::Resolve (e)); + types.push_back (TypeCheckExpr::Resolve (e, false)); return true; }); @@ -653,7 +659,8 @@ public: void visit (HIR::ArrayElemsCopied &elems) { - infered_array_elems = TypeCheckExpr::Resolve (elems.get_elem_to_copy ()); + infered_array_elems + = TypeCheckExpr::Resolve (elems.get_elem_to_copy (), false); } void visit (HIR::StructExprStructFields &struct_expr) @@ -667,13 +674,13 @@ public: expr.as_string ().c_str (), expr.get_expr_in_parens ()->as_string ().c_str ()); - infered = TypeCheckExpr::Resolve (expr.get_expr_in_parens ().get ()); + infered = TypeCheckExpr::Resolve (expr.get_expr_in_parens ().get (), false); } void visit (HIR::FieldAccessExpr &expr) { auto struct_base - = TypeCheckExpr::Resolve (expr.get_receiver_expr ().get ()); + = TypeCheckExpr::Resolve (expr.get_receiver_expr ().get (), false); bool is_valid_type = struct_base->get_kind () == TyTy::TypeKind::ADT; if (!is_valid_type) @@ -750,19 +757,26 @@ public: void visit (HIR::LoopExpr &expr) { - infered = TypeCheckExpr::Resolve (expr.get_loop_block ().get ()); + infered = TypeCheckExpr::Resolve (expr.get_loop_block ().get (), true); } void visit (HIR::BreakExpr &expr) { + if (!inside_loop) + { + rust_error_at (expr.get_locus (), "cannot `break` outside of a loop"); + return; + } + infered = expr.has_break_expr () - ? TypeCheckExpr::Resolve (expr.get_expr ().get ()) + ? TypeCheckExpr::Resolve (expr.get_expr ().get (), false) : new TyTy::UnitType (expr.get_mappings ().get_hirid ()); } private: - TypeCheckExpr () - : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr) + TypeCheckExpr (bool inside_loop) + : TypeCheckBase (), infered (nullptr), infered_array_elems (nullptr), + inside_loop (inside_loop) {} bool @@ -813,6 +827,8 @@ private: TyTy::TyBase *infered; TyTy::TyBase *infered_array_elems; + + bool inside_loop; }; } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check-implitem.h b/gcc/rust/typecheck/rust-hir-type-check-implitem.h index a0a4fda..3e835b7 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-implitem.h +++ b/gcc/rust/typecheck/rust-hir-type-check-implitem.h @@ -40,7 +40,8 @@ public: void visit (HIR::ConstantItem &constant) { TyTy::TyBase *type = TypeCheckType::Resolve (constant.get_type ()); - TyTy::TyBase *expr_type = TypeCheckExpr::Resolve (constant.get_expr ()); + TyTy::TyBase *expr_type + = TypeCheckExpr::Resolve (constant.get_expr (), false); context->insert_type (constant.get_mappings (), type->combine (expr_type)); } @@ -170,7 +171,7 @@ public: auto expected_ret_tyty = resolve_fn_type->return_type (); context->push_return_type (expected_ret_tyty); - auto result = TypeCheckExpr::Resolve (function.function_body.get ()); + auto result = TypeCheckExpr::Resolve (function.function_body.get (), false); auto ret_resolved = expected_ret_tyty->combine (result); if (ret_resolved == nullptr) return; @@ -202,7 +203,8 @@ public: auto expected_ret_tyty = resolve_fn_type->return_type (); context->push_return_type (expected_ret_tyty); - auto result = TypeCheckExpr::Resolve (method.get_function_body ().get ()); + auto result + = TypeCheckExpr::Resolve (method.get_function_body ().get (), false); auto ret_resolved = expected_ret_tyty->combine (result); if (ret_resolved == nullptr) return; diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index fbe2056..f54956c 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -75,7 +75,7 @@ public: auto expected_ret_tyty = resolve_fn_type->return_type (); context->push_return_type (expected_ret_tyty); - auto result = TypeCheckExpr::Resolve (function.function_body.get ()); + auto result = TypeCheckExpr::Resolve (function.function_body.get (), false); auto ret_resolved = expected_ret_tyty->combine (result); if (ret_resolved == nullptr) return; diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h index 83fdf11..195e483 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -30,21 +30,21 @@ namespace Resolver { class TypeCheckStmt : public TypeCheckBase { public: - static TyTy::TyBase *Resolve (HIR::Stmt *stmt) + static TyTy::TyBase *Resolve (HIR::Stmt *stmt, bool inside_loop) { - TypeCheckStmt resolver; + TypeCheckStmt resolver (inside_loop); stmt->accept_vis (resolver); return resolver.infered; } void visit (HIR::ExprStmtWithBlock &stmt) { - infered = TypeCheckExpr::Resolve (stmt.get_expr ()); + infered = TypeCheckExpr::Resolve (stmt.get_expr (), inside_loop); } void visit (HIR::ExprStmtWithoutBlock &stmt) { - infered = TypeCheckExpr::Resolve (stmt.get_expr ()); + infered = TypeCheckExpr::Resolve (stmt.get_expr (), inside_loop); } void visit (HIR::LetStmt &stmt) @@ -54,7 +54,8 @@ public: TyTy::TyBase *init_expr_ty = nullptr; if (stmt.has_init_expr ()) { - init_expr_ty = TypeCheckExpr::Resolve (stmt.get_init_expr ()); + init_expr_ty + = TypeCheckExpr::Resolve (stmt.get_init_expr (), inside_loop); if (init_expr_ty == nullptr) return; @@ -105,9 +106,12 @@ public: } private: - TypeCheckStmt () : TypeCheckBase (), infered (nullptr) {} + TypeCheckStmt (bool inside_loop) + : TypeCheckBase (), infered (nullptr), inside_loop (inside_loop) + {} TyTy::TyBase *infered; + bool inside_loop; }; } // namespace Resolver diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index 61823bf..6d4c876 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -86,7 +86,7 @@ public: void visit (HIR::StaticItem &var) { TyTy::TyBase *type = TypeCheckType::Resolve (var.get_type ()); - TyTy::TyBase *expr_type = TypeCheckExpr::Resolve (var.get_expr ()); + TyTy::TyBase *expr_type = TypeCheckExpr::Resolve (var.get_expr (), false); context->insert_type (var.get_mappings (), type->combine (expr_type)); } @@ -94,7 +94,8 @@ public: void visit (HIR::ConstantItem &constant) { TyTy::TyBase *type = TypeCheckType::Resolve (constant.get_type ()); - TyTy::TyBase *expr_type = TypeCheckExpr::Resolve (constant.get_expr ()); + TyTy::TyBase *expr_type + = TypeCheckExpr::Resolve (constant.get_expr (), false); context->insert_type (constant.get_mappings (), type->combine (expr_type)); } diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc index 3044a6f..00a92b0 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.cc +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -112,7 +112,7 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) bool is_final_expr = is_final_stmt && (!expr.has_expr () || !expr.tail_expr_reachable ()); - auto resolved = TypeCheckStmt::Resolve (s); + auto resolved = TypeCheckStmt::Resolve (s, inside_loop); if (resolved == nullptr) { rust_error_at (s->get_locus_slow (), "failure to resolve type"); @@ -137,7 +137,8 @@ TypeCheckExpr::visit (HIR::BlockExpr &expr) { delete block_tyty; - block_tyty = TypeCheckExpr::Resolve (expr.get_final_expr ().get ()); + block_tyty + = TypeCheckExpr::Resolve (expr.get_final_expr ().get (), inside_loop); } infered = block_tyty->clone (); @@ -160,7 +161,8 @@ TypeCheckStructExpr::visit (HIR::StructExprStructFields &struct_expr) if (struct_expr.has_struct_base ()) { TyTy::TyBase *base_resolved - = TypeCheckExpr::Resolve (struct_expr.struct_base->base_struct.get ()); + = TypeCheckExpr::Resolve (struct_expr.struct_base->base_struct.get (), + false); resolved = struct_path_resolved->combine (base_resolved); if (resolved == nullptr) { @@ -326,7 +328,7 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifierValue &field) } size_t field_index; - TyTy::TyBase *value = TypeCheckExpr::Resolve (field.get_value ()); + TyTy::TyBase *value = TypeCheckExpr::Resolve (field.get_value (), false); TyTy::StructFieldType *field_type = struct_path_resolved->get_field (field.field_name, &field_index); if (field_type == nullptr) @@ -355,7 +357,7 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIndexValue &field) } size_t field_index; - TyTy::TyBase *value = TypeCheckExpr::Resolve (field.get_value ()); + TyTy::TyBase *value = TypeCheckExpr::Resolve (field.get_value (), false); TyTy::StructFieldType *field_type = struct_path_resolved->get_field (field_name, &field_index); if (field_type == nullptr) @@ -395,7 +397,7 @@ TypeCheckStructExpr::visit (HIR::StructExprFieldIdentifier &field) // existing code to figure out the type HIR::IdentifierExpr expr (field.get_mappings (), field.get_field_name (), field.get_locus ()); - TyTy::TyBase *value = TypeCheckExpr::Resolve (&expr); + TyTy::TyBase *value = TypeCheckExpr::Resolve (&expr, false); resolved_field = field_type->get_field_type ()->combine (value); if (resolved_field != nullptr) diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 8b04209..e12d5ff 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -501,7 +501,7 @@ TypeCheckCallExpr::visit (ADTType &type) StructFieldType *field = type.get_field (i); TyBase *field_tyty = field->get_field_type (); - TyBase *arg = Resolver::TypeCheckExpr::Resolve (p); + TyBase *arg = Resolver::TypeCheckExpr::Resolve (p, false); if (arg == nullptr) { rust_error_at (p->get_locus_slow (), "failed to resolve argument type"); @@ -542,7 +542,7 @@ TypeCheckCallExpr::visit (FnType &type) size_t i = 0; call.iterate_params ([&] (HIR::Expr *param) mutable -> bool { auto fnparam = type.param_at (i); - auto argument_expr_tyty = Resolver::TypeCheckExpr::Resolve (param); + auto argument_expr_tyty = Resolver::TypeCheckExpr::Resolve (param, false); if (argument_expr_tyty == nullptr) { rust_error_at (param->get_locus_slow (), @@ -593,7 +593,7 @@ TypeCheckMethodCallExpr::visit (FnType &type) size_t i = 1; call.iterate_params ([&] (HIR::Expr *param) mutable -> bool { auto fnparam = type.param_at (i); - auto argument_expr_tyty = Resolver::TypeCheckExpr::Resolve (param); + auto argument_expr_tyty = Resolver::TypeCheckExpr::Resolve (param, false); if (argument_expr_tyty == nullptr) { rust_error_at (param->get_locus_slow (), diff --git a/gcc/testsuite/rust.test/fail_compilation/break1.rs b/gcc/testsuite/rust.test/fail_compilation/break1.rs new file mode 100644 index 0000000..401a575 --- /dev/null +++ b/gcc/testsuite/rust.test/fail_compilation/break1.rs @@ -0,0 +1,5 @@ +fn main() { + let a; + a = 1; + break a; +} |