aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2020-12-03 15:34:15 +0000
committerPhilip Herron <herron.philip@googlemail.com>2020-12-03 17:25:24 +0000
commit064c6e4815b212d72f008082939376f570897c19 (patch)
tree4090d53e54ea8565d9515b3668f432306a2ee697
parent03fc0e389fae2576a7f217fb0afb7cb0f18689f8 (diff)
downloadgcc-064c6e4815b212d72f008082939376f570897c19.zip
gcc-064c6e4815b212d72f008082939376f570897c19.tar.gz
gcc-064c6e4815b212d72f008082939376f570897c19.tar.bz2
Type Resolve ReturnExpr's to ensure they match the function type.
This an implementation to check return types for functions it needs work to handle structs and other data structures later on.
-rw-r--r--gcc/rust/analysis/rust-type-resolution.cc52
-rw-r--r--gcc/rust/analysis/rust-type-resolution.h8
-rw-r--r--gcc/rust/ast/rust-expr.h4
-rw-r--r--gcc/rust/backend/rust-compile.cc6
4 files changed, 63 insertions, 7 deletions
diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc
index 8558847..51c7380 100644
--- a/gcc/rust/analysis/rust-type-resolution.cc
+++ b/gcc/rust/analysis/rust-type-resolution.cc
@@ -774,9 +774,42 @@ TypeResolution::visit (AST::RangeFromToInclExpr &expr)
void
TypeResolution::visit (AST::RangeToInclExpr &expr)
{}
+
void
TypeResolution::visit (AST::ReturnExpr &expr)
-{}
+{
+ // Ensure the type of this matches the function
+ auto before = typeBuffer.size ();
+ expr.get_expr ()->accept_vis (*this);
+
+ if (typeBuffer.size () <= before)
+ {
+ rust_error_at (expr.get_expr ()->get_locus_slow (),
+ "unable to determine type for return expr");
+ return;
+ }
+
+ auto inferedType = typeBuffer.back ();
+ typeBuffer.pop_back ();
+
+ // check this is compatible with the return type
+ // this will again have issues with structs before we move to HIR
+
+ auto function = scope.CurrentFunction ();
+ if (!function->has_function_return_type ())
+ {
+ rust_error_at (expr.get_locus (), "return for void function %s",
+ function->as_string ().c_str ());
+ return;
+ }
+
+ if (!typesAreCompatible (function->return_type.get (), inferedType,
+ expr.get_locus_slow ()))
+ {
+ return;
+ }
+}
+
void
TypeResolution::visit (AST::UnsafeBlockExpr &expr)
{}
@@ -889,18 +922,26 @@ TypeResolution::visit (AST::Function &function)
// its a marker for a void function
scope.InsertType (function.function_name, function.return_type.get ());
scope.InsertFunction (function.function_name, &function);
+ scope.PushFunction (&function);
scope.Push ();
for (auto &param : function.function_params)
{
if (!isTypeInScope (param.type.get (), param.locus))
- return;
+ {
+ scope.Pop ();
+ scope.PopFunction ();
+ return;
+ }
auto before = letPatternBuffer.size ();
param.param_name->accept_vis (*this);
if (letPatternBuffer.size () <= before)
{
rust_error_at (param.locus, "failed to analyse parameter name");
+
+ scope.Pop ();
+ scope.PopFunction ();
return;
}
@@ -913,7 +954,11 @@ TypeResolution::visit (AST::Function &function)
if (function.has_function_return_type ())
{
if (!isTypeInScope (function.return_type.get (), function.locus))
- return;
+ {
+ scope.Pop ();
+ scope.PopFunction ();
+ return;
+ }
}
// walk the expression body
@@ -927,6 +972,7 @@ TypeResolution::visit (AST::Function &function)
function.locals.push_back (value);
scope.Pop ();
+ scope.PopFunction ();
}
void
diff --git a/gcc/rust/analysis/rust-type-resolution.h b/gcc/rust/analysis/rust-type-resolution.h
index d461b66..0fef2ae 100644
--- a/gcc/rust/analysis/rust-type-resolution.h
+++ b/gcc/rust/analysis/rust-type-resolution.h
@@ -55,6 +55,12 @@ public:
return functionScope.Lookup (ident, fn);
}
+ void PushFunction (AST::Function *fn) { functionStack.push_back (fn); }
+
+ void PopFunction () { functionStack.pop_back (); }
+
+ AST::Function *CurrentFunction () { return functionStack.back (); }
+
void InsertLocal (std::string ident, AST::LetStmt *let)
{
localsPerBlock.Insert (ident, let);
@@ -91,6 +97,8 @@ public:
}
private:
+ std::vector<AST::Function *> functionStack;
+
Scope<AST::Function *> functionScope;
Scope<AST::LetStmt *> localsPerBlock;
Scope<AST::StructStruct *> structsPerBlock;
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index 4971041..f587c00 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -3012,11 +3012,11 @@ protected:
// Return expression AST node representation
class ReturnExpr : public ExprWithoutBlock
{
-public:
std::unique_ptr<Expr> return_expr;
Location locus;
+public:
std::string as_string () const override;
/* Returns whether the object has an expression returned (i.e. not void return
@@ -3059,6 +3059,8 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ Expr *get_expr () { return return_expr.get (); }
+
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 2dbce16..820f880 100644
--- a/gcc/rust/backend/rust-compile.cc
+++ b/gcc/rust/backend/rust-compile.cc
@@ -805,10 +805,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_expr ()->get_locus_slow (), expr.get_expr (), ret, exprs);
if (ret == NULL)
{
- rust_fatal_error (expr.return_expr->get_locus_slow (),
+ rust_fatal_error (expr.get_expr ()->get_locus_slow (),
"failed to compile");
return;
}
@@ -816,7 +816,7 @@ Compilation::visit (AST::ReturnExpr &expr)
std::vector<Bexpression *> retstmts;
retstmts.push_back (ret);
auto s = backend->return_statement (scope.GetCurrentFndecl (), retstmts,
- expr.locus);
+ expr.get_locus ());
scope.AddStatement (s);
}