diff options
author | Philip Herron <philip.herron@embecosm.com> | 2020-12-03 15:34:15 +0000 |
---|---|---|
committer | Philip Herron <herron.philip@googlemail.com> | 2020-12-03 17:25:24 +0000 |
commit | 064c6e4815b212d72f008082939376f570897c19 (patch) | |
tree | 4090d53e54ea8565d9515b3668f432306a2ee697 | |
parent | 03fc0e389fae2576a7f217fb0afb7cb0f18689f8 (diff) | |
download | gcc-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.cc | 52 | ||||
-rw-r--r-- | gcc/rust/analysis/rust-type-resolution.h | 8 | ||||
-rw-r--r-- | gcc/rust/ast/rust-expr.h | 4 | ||||
-rw-r--r-- | gcc/rust/backend/rust-compile.cc | 6 |
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 ¶m : 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); } |