diff --git a/viper/parser/parser.py b/viper/parser/parser.py index 00a77114f0..4e58e9e8d4 100644 --- a/viper/parser/parser.py +++ b/viper/parser/parser.py @@ -275,6 +275,8 @@ def __init__(self, vars=None, globals=None, sigs=None, forvars=None, return_type self.origcode = origcode # In Loop status. Whether body is currently evaluating within a for-loop or not. self.in_for_loop = set() + # Count returns in function + self.function_return_count = 0 def set_in_for_loop(self, name_of_list): self.in_for_loop.add(name_of_list) @@ -282,6 +284,9 @@ def set_in_for_loop(self, name_of_list): def remove_in_for_loop(self, name_of_list): self.in_for_loop.remove(name_of_list) + def increment_return_counter(self): + self.function_return_count += 1 + # Add a new variable def new_variable(self, name, typ): if not is_varname_valid(name): @@ -470,6 +475,13 @@ def parse_func(code, _globals, sigs, origcode, _vars=None): ['eq', ['mload', 0], method_id_node], ['seq'] + clampers + [parse_body(c, context) for c in code.body] + ['stop'] ], typ=None, pos=getpos(code)) + + # Check for at leasts one return statement if necessary. + if context.return_type and context.function_return_count == 0: + raise StructureException( + "Missing return statement in function '%s' " % sig.name, code + ) + o.context = context o.total_gas = o.gas + calc_mem_gas(o.context.next_mem) o.func_name = sig.name diff --git a/viper/parser/stmt.py b/viper/parser/stmt.py index b123d1dfd5..aedced1961 100644 --- a/viper/parser/stmt.py +++ b/viper/parser/stmt.py @@ -320,6 +320,7 @@ def parse_return(self): if not self.stmt.value: raise TypeMismatchException("Expecting to return a value", self.stmt) sub = Expr(self.stmt.value, self.context).lll_node + self.context.increment_return_counter() # Returning a value (most common case) if isinstance(sub.typ, BaseType): if not isinstance(self.context.return_type, BaseType):