aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2021-02-10 17:01:48 +0000
committerPhilip Herron <herron.philip@googlemail.com>2021-02-10 18:10:57 +0000
commitd02ab5925b612678beb975d99951b1d2052958a1 (patch)
tree8d3aab8d2d2d4ede40eda66d6ed0a166000798b8 /gcc
parent06c9fd97bf3d86a08eadcadb1bc59cb392116d16 (diff)
downloadgcc-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.h84
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-implitem.h8
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.h2
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-stmt.h16
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-toplevel.h5
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc14
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc6
-rw-r--r--gcc/testsuite/rust.test/fail_compilation/break1.rs5
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;
+}