/*******************************************************************\
Module:
Author: Daniel Kroening, [email protected]
\*******************************************************************/
#include "expr2cpp.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "cpp_name.h"
#include "cpp_template_type.h"
class expr2cppt:public expr2ct
{
public:
explicit expr2cppt(const namespacet &_ns):expr2ct(_ns) { }
protected:
std::string convert_with_precedence(
const exprt &src, unsigned &precedence) override;
std::string convert_cpp_this();
std::string convert_cpp_new(const exprt &src);
std::string convert_extractbit(const exprt &src);
std::string convert_code_cpp_delete(const exprt &src, unsigned indent);
std::string convert_code_cpp_new(const exprt &src, unsigned indent);
std::string convert_struct(const exprt &src, unsigned &precedence) override;
std::string convert_code(const codet &src, unsigned indent) override;
// NOLINTNEXTLINE(whitespace/line_length)
std::string convert_constant(const constant_exprt &src, unsigned &precedence) override;
std::string convert_rec(
const typet &src,
const c_qualifierst &qualifiers,
const std::string &declarator) override;
};
std::string expr2cppt::convert_struct(
const exprt &src,
unsigned &precedence)
{
if(src.type().id() != ID_struct && src.type().id() != ID_struct_tag)
return convert_norep(src, precedence);
const struct_typet &struct_type =
src.type().id() == ID_struct_tag
? ns.follow_tag(to_struct_tag_type(src.type()))
: to_struct_type(src.type());
std::string dest="{ ";
const struct_typet::componentst &components=
struct_type.components();
DATA_INVARIANT(
components.size() == src.operands().size(), "component count mismatch");
exprt::operandst::const_iterator o_it=src.operands().begin();
bool first=true;
size_t last_size=0;
for(const auto &c : components)
{
if(c.type().id() == ID_code)
{
}
else
{
std::string tmp=convert(*o_it);
std::string sep;
if(first)
first=false;
else
{
if(last_size+40 clone = qualifiers.clone();
c_qualifierst &new_qualifiers = *clone;
new_qualifiers.read(src);
const std::string d = declarator.empty() ? declarator : (" " + declarator);
const std::string q=
new_qualifiers.as_string();
if(is_reference(src))
{
return q + convert(to_reference_type(src).base_type()) + " &" + d;
}
else if(is_rvalue_reference(src))
{
return q + convert(to_pointer_type(src).base_type()) + " &&" + d;
}
else if(!src.get(ID_C_c_type).empty())
{
const irep_idt c_type=src.get(ID_C_c_type);
if(c_type == ID_bool)
return q+"bool"+d;
else
return expr2ct::convert_rec(src, qualifiers, declarator);
}
else if(src.id() == ID_struct)
{
std::string dest=q;
if(src.get_bool(ID_C_class))
dest+="class";
else if(src.get_bool(ID_C_interface))
dest+="__interface"; // MS-specific
else
dest+="struct";
dest+=d;
return dest;
}
else if(src.id() == ID_struct_tag)
{
const struct_typet &struct_type = ns.follow_tag(to_struct_tag_type(src));
std::string dest = q;
if(src.get_bool(ID_C_class))
dest += "class";
else if(src.get_bool(ID_C_interface))
dest += "__interface"; // MS-specific
else
dest += "struct";
const irept &tag = struct_type.find(ID_tag);
if(!tag.id().empty())
{
if(tag.id() == ID_cpp_name)
dest += " " + to_cpp_name(tag).to_string();
else
dest += " " + id2string(tag.id());
}
dest += d;
return dest;
}
else if(src.id() == ID_union_tag)
{
const union_typet &union_type = ns.follow_tag(to_union_tag_type(src));
std::string dest = q + "union";
const irept &tag = union_type.find(ID_tag);
if(!tag.id().empty())
{
if(tag.id() == ID_cpp_name)
dest += " " + to_cpp_name(tag).to_string();
else
dest += " " + id2string(tag.id());
}
dest += d;
return dest;
}
else if(src.id()==ID_constructor)
{
return "constructor ";
}
else if(src.id()==ID_destructor)
{
return "destructor ";
}
else if(src.id()=="cpp-template-type")
{
return "typename";
}
else if(src.id()==ID_template)
{
std::string dest="template<";
const irept::subt &arguments=src.find(ID_arguments).get_sub();
for(auto it = arguments.begin(); it != arguments.end(); ++it)
{
if(it!=arguments.begin())
dest+=", ";
const exprt &argument=(const exprt &)*it;
if(argument.id()==ID_symbol)
{
dest+=convert(argument.type())+" ";
dest+=convert(argument);
}
else if(argument.id()==ID_type)
dest+=convert(argument.type());
else
{
lispexprt lisp;
irep2lisp(argument, lisp);
dest+="irep(\""+MetaString(lisp.expr2string())+"\")";
}
}
dest += "> " + convert(to_template_type(src).subtype());
return dest;
}
else if(
src.id() == ID_pointer &&
to_pointer_type(src).base_type().id() == ID_nullptr)
{
return "std::nullptr_t";
}
else if(src.id() == ID_pointer && src.find(ID_to_member).is_not_nil())
{
typet tmp=src;
typet member;
member.swap(tmp.add(ID_to_member));
std::string dest = "(" + convert(member) + ":: *)";
const auto &base_type = to_pointer_type(src).base_type();
if(base_type.id() == ID_code)
{
const code_typet &code_type = to_code_type(base_type);
const typet &return_type = code_type.return_type();
dest = convert(return_type) + " " + dest;
const code_typet::parameterst &args = code_type.parameters();
dest+="(";
for(code_typet::parameterst::const_iterator it=args.begin();
it!=args.end();
++it)
{
if(it!=args.begin())
dest+=", ";
dest += convert(it->type());
}
dest+=")";
dest+=d;
}
else
dest = convert(base_type) + " " + dest + d;
return dest;
}
else if(src.id()==ID_verilog_signedbv ||
src.id()==ID_verilog_unsignedbv)
return "sc_lv[" + std::to_string(to_bitvector_type(src).get_width()) + "]" +
d;
else if(src.id()==ID_unassigned)
return "?";
else if(src.id()==ID_code)
{
const code_typet &code_type=to_code_type(src);
// C doesn't really have syntax for function types,
// so we use C++11 trailing return types!
std::string dest="auto";
// qualifiers, declarator?
if(d.empty())
dest+=' ';
else
dest+=d;
dest+='(';
const code_typet::parameterst ¶meters=code_type.parameters();
for(code_typet::parameterst::const_iterator
it=parameters.begin();
it!=parameters.end();
it++)
{
if(it!=parameters.begin())
dest+=", ";
dest+=convert(it->type());
}
if(code_type.has_ellipsis())
{
if(!parameters.empty())
dest+=", ";
dest+="...";
}
dest+=')';
const typet &return_type=code_type.return_type();
dest+=" -> "+convert(return_type);
return dest;
}
else if(src.id()==ID_initializer_list)
{
// only really used in error messages
return "{ ... }";
}
else if(src.id() == ID_c_bool)
{
return q + "bool" + d;
}
else
return expr2ct::convert_rec(src, qualifiers, declarator);
}
std::string expr2cppt::convert_cpp_this()
{
return id2string(ID_this);
}
std::string expr2cppt::convert_cpp_new(const exprt &src)
{
std::string dest;
if(src.get(ID_statement)==ID_cpp_new_array)
{
dest="new";
std::string tmp_size=
convert(static_cast(src.find(ID_size)));
dest+=' ';
dest += convert(to_pointer_type(src.type()).base_type());
dest+='[';
dest+=tmp_size;
dest+=']';
}
else
dest = "new " + convert(to_pointer_type(src.type()).base_type());
return dest;
}
std::string expr2cppt::convert_code_cpp_new(const exprt &src, unsigned indent)
{
return indent_str(indent) + convert_cpp_new(src) + ";\n";
}
std::string expr2cppt::convert_code_cpp_delete(
const exprt &src,
unsigned indent)
{
std::string dest=indent_str(indent)+"delete ";
if(src.operands().size()!=1)
{
unsigned precedence;
return convert_norep(src, precedence);
}
std::string tmp = convert(to_unary_expr(src).op());
dest+=tmp+";\n";
return dest;
}
std::string expr2cppt::convert_with_precedence(
const exprt &src,
unsigned &precedence)
{
if(src.id()=="cpp-this")
{
precedence = 15;
return convert_cpp_this();
}
if(src.id()==ID_extractbit)
{
precedence = 15;
return convert_extractbit(src);
}
else if(src.id()==ID_side_effect &&
(src.get(ID_statement)==ID_cpp_new ||
src.get(ID_statement)==ID_cpp_new_array))
{
precedence = 15;
return convert_cpp_new(src);
}
else if(src.id()==ID_side_effect &&
src.get(ID_statement)==ID_throw)
{
precedence = 16;
return convert_function(src, "throw");
}
else if(src.is_constant() && src.type().id()==ID_verilog_signedbv)
return "'"+id2string(src.get(ID_value))+"'";
else if(src.is_constant() && src.type().id()==ID_verilog_unsignedbv)
return "'"+id2string(src.get(ID_value))+"'";
else if(src.is_constant() && to_constant_expr(src).get_value()==ID_nullptr)
return "nullptr";
else if(src.id()==ID_unassigned)
return "?";
else if(src.id() == ID_pod_constructor)
return "pod_constructor";
else
return expr2ct::convert_with_precedence(src, precedence);
}
std::string expr2cppt::convert_code(
const codet &src,
unsigned indent)
{
const irep_idt &statement=src.get(ID_statement);
if(statement==ID_cpp_delete ||
statement==ID_cpp_delete_array)
return convert_code_cpp_delete(src, indent);
if(statement==ID_cpp_new ||
statement==ID_cpp_new_array)
return convert_code_cpp_new(src, indent);
return expr2ct::convert_code(src, indent);
}
std::string expr2cppt::convert_extractbit(const exprt &src)
{
const auto &extractbit_expr = to_extractbit_expr(src);
return convert(extractbit_expr.op0()) + "[" + convert(extractbit_expr.op1()) +
"]";
}
std::string expr2cpp(const exprt &expr, const namespacet &ns)
{
expr2cppt expr2cpp(ns);
expr2cpp.get_shorthands(expr);
return expr2cpp.convert(expr);
}
std::string type2cpp(const typet &type, const namespacet &ns)
{
expr2cppt expr2cpp(ns);
return expr2cpp.convert(type);
}