Merge pull request #4175 from tautschnig/return-has-an-operand

Return statements always have one operand
This commit is contained in:
Michael Tautschnig 2019-02-13 13:57:51 +00:00 committed by GitHub
commit c0819f936e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 72 additions and 84 deletions

View File

@ -415,12 +415,10 @@ void java_bytecode_instrumentt::instrument_code(codet &code)
}
else if(statement==ID_return)
{
if(code.operands().size()==1)
{
code_blockt block;
add_expr_instrumentation(block, code.op0());
prepend_instrumentation(code, block);
}
code_blockt block;
code_returnt &code_return = to_code_return(code);
add_expr_instrumentation(block, code_return.return_value());
prepend_instrumentation(code, block);
}
else if(statement==ID_function_call)
{

View File

@ -52,8 +52,8 @@ void java_bytecode_typecheckt::typecheck_code(codet &code)
}
else if(statement==ID_return)
{
if(code.operands().size()==1)
typecheck_expr(code.op0());
code_returnt &code_return = to_code_return(code);
typecheck_expr(code_return.return_value());
}
else if(statement==ID_function_call)
{

View File

@ -138,7 +138,7 @@ protected:
virtual void typecheck_gcc_computed_goto(codet &code);
virtual void typecheck_gcc_switch_case_range(code_gcc_switch_case_ranget &);
virtual void typecheck_gcc_local_label(codet &code);
virtual void typecheck_return(codet &code);
virtual void typecheck_return(code_returnt &code);
virtual void typecheck_switch(code_switcht &code);
virtual void typecheck_while(code_whilet &code);
virtual void typecheck_dowhile(code_dowhilet &code);

View File

@ -68,7 +68,7 @@ void c_typecheck_baset::typecheck_code(codet &code)
else if(statement==ID_continue)
typecheck_continue(code);
else if(statement==ID_return)
typecheck_return(code);
typecheck_return(to_code_return(code));
else if(statement==ID_decl)
typecheck_decl(code);
else if(statement==ID_assign)
@ -630,49 +630,40 @@ void c_typecheck_baset::typecheck_start_thread(codet &code)
typecheck_code(to_code(code.op0()));
}
void c_typecheck_baset::typecheck_return(codet &code)
void c_typecheck_baset::typecheck_return(code_returnt &code)
{
if(code.operands().empty())
if(code.has_return_value())
{
if(
return_type.id() != ID_empty && return_type.id() != ID_constructor &&
return_type.id() != ID_destructor)
{
// gcc doesn't actually complain, it just warns!
warning().source_location = code.source_location();
warning() << "non-void function should return a value" << eom;
code.copy_to_operands(
side_effect_expr_nondett(return_type, code.source_location()));
}
}
else if(code.operands().size()==1)
{
typecheck_expr(code.op0());
typecheck_expr(code.return_value());
if(return_type.id() == ID_empty)
{
// gcc doesn't actually complain, it just warns!
if(code.op0().type().id() != ID_empty)
if(code.return_value().type().id() != ID_empty)
{
warning().source_location=code.source_location();
warning() << "function has return void ";
warning() << "but a return statement returning ";
warning() << to_string(code.op0().type());
warning() << to_string(code.return_value().type());
warning() << eom;
code.op0() = typecast_exprt(code.op0(), return_type);
code.return_value() = typecast_exprt(code.return_value(), return_type);
}
}
else
implicit_typecast(code.op0(), return_type);
implicit_typecast(code.return_value(), return_type);
}
else
else if(
return_type.id() != ID_empty && return_type.id() != ID_constructor &&
return_type.id() != ID_destructor)
{
error().source_location = code.source_location();
error() << "return expected to have 0 or 1 operands" << eom;
throw 0;
// gcc doesn't actually complain, it just warns!
warning().source_location = code.source_location();
warning() << "non-void function should return a value" << eom;
code.return_value() =
side_effect_expr_nondett(return_type, code.source_location());
}
}

View File

@ -2587,8 +2587,7 @@ std::string expr2ct::convert_code_return(
const codet &src,
unsigned indent)
{
if(!src.operands().empty() &&
src.operands().size()!=1)
if(src.operands().size() != 1)
{
unsigned precedence;
return convert_norep(src, precedence);

View File

@ -2426,7 +2426,11 @@ jump_statement:
| TOK_BREAK ';'
{ $$=$1; statement($$, ID_break); }
| TOK_RETURN ';'
{ $$=$1; statement($$, ID_return); }
{
$$=$1;
statement($$, ID_return);
stack($$).operands().push_back(nil_exprt());
}
| TOK_RETURN comma_expression ';'
{ $$=$1; statement($$, ID_return); mto($$, $2); }
;

View File

@ -7344,7 +7344,7 @@ bool Parser::rStatement(codet &statement)
lex.get_token(tk1);
statement=codet(ID_return);
statement = code_returnt();
set_location(statement, tk1);
if(lex.LookAhead(0)==';')
@ -7375,7 +7375,7 @@ bool Parser::rStatement(codet &statement)
if(lex.get_token(tk2)!=';')
return false;
statement.add_to_operands(std::move(exp));
to_code_return(statement).return_value() = std::move(exp);
}
return true;

View File

@ -1510,11 +1510,13 @@ void value_sett::apply_code_rec(
}
else if(statement==ID_return)
{
const code_returnt &code_return = to_code_return(code);
// this is turned into an assignment
if(code.operands().size()==1)
if(code_return.has_return_value())
{
symbol_exprt lhs("value_set::return_value", code.op0().type());
assign(lhs, code.op0(), ns, false, false);
symbol_exprt lhs(
"value_set::return_value", code_return.return_value().type());
assign(lhs, code_return.return_value(), ns, false, false);
}
}
else if(statement==ID_array_set)

View File

@ -1310,16 +1310,14 @@ void value_set_fit::do_end_function(
assign(lhs, rhs, ns);
}
void value_set_fit::apply_code(
const exprt &code,
const namespacet &ns)
void value_set_fit::apply_code(const codet &code, const namespacet &ns)
{
const irep_idt &statement=code.get(ID_statement);
if(statement==ID_block)
{
forall_operands(it, code)
apply_code(*it, ns);
for(const auto &stmt : to_code_block(code).statements())
apply_code(stmt, ns);
}
else if(statement==ID_function_call)
{
@ -1372,12 +1370,13 @@ void value_set_fit::apply_code(
}
else if(statement==ID_return)
{
const code_returnt &code_return = to_code_return(code);
// this is turned into an assignment
if(code.operands().size()==1)
if(code_return.has_return_value())
{
std::string rvs="value_set::return_value"+std::to_string(from_function);
symbol_exprt lhs(rvs, code.op0().type());
assign(lhs, code.op0(), ns);
symbol_exprt lhs(rvs, code_return.return_value().type());
assign(lhs, code_return.return_value(), ns);
}
}
else if(statement==ID_fence)

View File

@ -24,6 +24,8 @@ Author: Daniel Kroening, kroening@kroening.com
#include "object_numbering.h"
class codet;
class value_set_fit
{
public:
@ -271,9 +273,7 @@ public:
return make_union(new_values.values);
}
void apply_code(
const exprt &code,
const namespacet &ns);
void apply_code(const codet &code, const namespacet &ns);
void assign(
const exprt &lhs,

View File

@ -1460,16 +1460,14 @@ void value_set_fivrt::do_end_function(
assign(lhs, rhs, ns);
}
void value_set_fivrt::apply_code(
const exprt &code,
const namespacet &ns)
void value_set_fivrt::apply_code(const codet &code, const namespacet &ns)
{
const irep_idt &statement=code.get(ID_statement);
if(statement==ID_block)
{
forall_operands(it, code)
apply_code(*it, ns);
for(const auto &stmt : to_code_block(code).statements())
apply_code(stmt, ns);
}
else if(statement==ID_function_call)
{
@ -1522,12 +1520,14 @@ void value_set_fivrt::apply_code(
}
else if(statement==ID_return)
{
const code_returnt &code_return = to_code_return(code);
// this is turned into an assignment
if(code.operands().size()==1)
if(code_return.has_return_value())
{
std::string rvs="value_set::return_value" + std::to_string(from_function);
symbol_exprt lhs(rvs, code.op0().type());
assign(lhs, code.op0(), ns);
std::string rvs =
"value_set::return_value" + std::to_string(from_function);
symbol_exprt lhs(rvs, code_return.return_value().type());
assign(lhs, code_return.return_value(), ns);
}
}
else if(statement==ID_input || statement==ID_output)

View File

@ -24,6 +24,8 @@ Author: Daniel Kroening, kroening@kroening.com
#include "object_numbering.h"
class codet;
class value_set_fivrt
{
public:
@ -307,9 +309,7 @@ public:
object_mapt &dest,
const object_mapt &src) const;
void apply_code(
const exprt &code,
const namespacet &ns);
void apply_code(const codet &code, const namespacet &ns);
bool handover();

View File

@ -1123,16 +1123,14 @@ void value_set_fivrnst::do_end_function(
assign(lhs, rhs, ns);
}
void value_set_fivrnst::apply_code(
const exprt &code,
const namespacet &ns)
void value_set_fivrnst::apply_code(const codet &code, const namespacet &ns)
{
const irep_idt &statement=code.get(ID_statement);
if(statement==ID_block)
{
forall_operands(it, code)
apply_code(*it, ns);
for(const auto &stmt : to_code_block(code).statements())
apply_code(stmt, ns);
}
else if(statement==ID_function_call)
{
@ -1185,14 +1183,15 @@ void value_set_fivrnst::apply_code(
}
else if(statement==ID_return)
{
const code_returnt &code_return = to_code_return(code);
// this is turned into an assignment
if(code.operands().size()==1)
if(code_return.has_return_value())
{
irep_idt rvs = std::string("value_set::return_value") +
std::to_string(from_function);
std::string rvs =
"value_set::return_value" + std::to_string(from_function);
add_var(rvs);
symbol_exprt lhs(rvs, code.op0().type());
assign(lhs, code.op0(), ns);
symbol_exprt lhs(rvs, code_return.return_value().type());
assign(lhs, code_return.return_value(), ns);
}
}
else if(statement==ID_input || statement==ID_output)

View File

@ -25,6 +25,8 @@ Author: Daniel Kroening, kroening@kroening.com
#include "object_numbering.h"
class codet;
class value_set_fivrnst
{
public:
@ -304,9 +306,7 @@ public:
object_mapt &dest,
const object_mapt &src) const;
void apply_code(
const exprt &code,
const namespacet &ns);
void apply_code(const codet &code, const namespacet &ns);
bool handover();

View File

@ -1255,10 +1255,8 @@ inline void validate_expr(const code_function_callt &x)
class code_returnt:public codet
{
public:
code_returnt():codet(ID_return)
code_returnt() : codet(ID_return, {nil_exprt()})
{
operands().resize(1);
op0().make_nil();
}
explicit code_returnt(const exprt &_op) : codet(ID_return, {_op})
@ -1277,8 +1275,6 @@ public:
bool has_return_value() const
{
if(operands().empty())
return false; // backwards compatibility
return return_value().is_not_nil();
}