Esempio n. 1
0
irep_idt cpp_namet::get_base_name() const
{
  const subt &sub=get_sub();

  // find last "::"
  unsigned base=0;

  for(unsigned i=0; i<sub.size(); i++)
  {
    if(sub[i].id()=="::")
      base=i+1;
  }

  if(base>=sub.size())
    return irep_idt();

  if(sub[base].id()==ID_name)
    return sub[base].get(ID_identifier);
  else if(base+1<sub.size() && sub[base].id()==ID_operator)
    return "operator"+sub[base+1].id_string();
  else if(base+1<sub.size() && sub[base].id()=="~" && sub[base+1].id()==ID_name)
    return "~"+sub[base+1].get_string(ID_identifier);

  return irep_idt();
}
Esempio n. 2
0
std::pair<irep_idt, irep_idt> ssa_exprt::build_identifier(
  const exprt &expr,
  const irep_idt &l0,
  const irep_idt &l1,
  const irep_idt &l2)
{
  std::ostringstream oss;
  std::ostringstream l1_object_oss;

  build_ssa_identifier_rec(expr, l0, l1, l2, oss, l1_object_oss);

  return std::make_pair(irep_idt(oss.str()), irep_idt(l1_object_oss.str()));
}
string_constantt::string_constantt():
  exprt(ID_string_constant)
{
  set_value(irep_idt());
  type()=typet(ID_array);
  type().subtype()=char_type();
}
Esempio n. 4
0
var_mapt::var_infot & var_mapt::operator()(
  const irep_idt &symbol,
  const irep_idt &suffix,
  const typet &type)
{
  assert(symbol!=irep_idt());

  std::string full_identifier=
    id2string(symbol)+id2string(suffix);

  std::pair<id_mapt::iterator, bool> result;

  result=id_map.insert(std::pair<irep_idt, var_infot>(
    full_identifier, var_infot()));

  if(result.second) // inserted?
  {
    result.first->second.full_identifier=full_identifier;
    result.first->second.symbol=symbol;
    result.first->second.suffix=suffix;
    result.first->second.type=type;
    init(result.first->second);
  }

  return result.first->second;
}
bool refined_string_typet::is_c_string_type(const typet &type)
{
  if (type.id() == ID_struct) {
    irep_idt tag = to_struct_type(type).get_tag();
    return (tag == irep_idt("__CPROVER_string"));
  } else return false;
}
Esempio n. 6
0
void c_typecheck_baset::typecheck_new_symbol(symbolt &symbol)
{
  if(symbol.is_parameter)
    adjust_function_parameter(symbol.type);

  // check initializer, if needed

  if(symbol.type.id()==ID_code)
  {
    if(symbol.value.is_not_nil() &&
       !symbol.is_macro)
      typecheck_function_body(symbol);
    else
    {
      // we don't need the identifiers
      code_typet &code_type=to_code_type(symbol.type);
      for(code_typet::parameterst::iterator
          it=code_type.parameters().begin();
          it!=code_type.parameters().end();
          it++)
        it->set_identifier(irep_idt());
    }
  }
  else
  {
    // check the initializer
    do_initializer(symbol);
  }
}
Esempio n. 7
0
void replace_location(
  source_locationt &dest,
  const source_locationt &new_location)
{
  // we copy, and then adjust for property_id, property_class
  // and comment, if necessary

  irep_idt comment=dest.get_comment();
  irep_idt property_class=dest.get_property_class();
  irep_idt property_id=dest.get_property_id();

  dest=new_location;
  
  if(comment!=irep_idt()) dest.set_comment(comment);
  if(property_class!=irep_idt()) dest.set_property_class(property_class);
  if(property_id!=irep_idt()) dest.set_property_id(property_id);
}
bool refined_string_typet::is_java_deref_string_type(const typet &type)
{
  if(type.id() == ID_struct) {
    irep_idt tag = to_struct_type(type).get_tag();
    return (tag == irep_idt("java.lang.String"));
  } 
  else return false;
}
bool refined_string_typet::is_java_char_sequence_type(const typet &type)
{
  if(type.id() == ID_pointer) {
    pointer_typet pt = to_pointer_type(type);
    typet subtype = pt.subtype();
    if(subtype.id() == ID_struct) {
      irep_idt tag = to_struct_type(subtype).get_tag();
      return (tag == irep_idt("java.lang.CharSequence"));
    } 
    else return false;
  } else return false;
}
Esempio n. 10
0
exprt get_failed_symbol(
  const symbol_exprt &expr,
  const namespacet &ns)
{
  const symbolt &symbol=ns.lookup(expr);
  irep_idt failed_symbol_id=symbol.type.get("#failed_symbol");

  if(failed_symbol_id==irep_idt())
    return nil_exprt();
    
  const symbolt &failed_symbol=ns.lookup(failed_symbol_id);
  
  return symbol_exprt(failed_symbol_id, failed_symbol.type);
}
Esempio n. 11
0
void c_typecheck_baset::typecheck_new_symbol(symbolt &symbol)
{
  if(symbol.is_parameter)
    adjust_function_parameter(symbol.type);

  // check initializer, if needed

  if(symbol.type.id()==ID_code)
  {
    if(symbol.value.is_not_nil())
      typecheck_function_body(symbol);
    else
    {
      // we don't need the identifiers
      code_typet &code_type=to_code_type(symbol.type);
      for(code_typet::parameterst::iterator
          it=code_type.parameters().begin();
          it!=code_type.parameters().end();
          it++)
        it->set_identifier(irep_idt());
    }
  }
  else
  {
    if(symbol.type.id()==ID_array &&
       to_array_type(symbol.type).size().is_nil() &&
       !symbol.is_type)
    {
      // Insert a new type symbol for the array.
      // We do this because we want a convenient way
      // of adjusting the size of the type later on.

      type_symbolt new_symbol(symbol.type);
      new_symbol.name=id2string(symbol.name)+"$type";
      new_symbol.base_name=id2string(symbol.base_name)+"$type"; 
      new_symbol.location=symbol.location;
      new_symbol.mode=symbol.mode;
      new_symbol.module=symbol.module;
    
      symbol.type=symbol_typet(new_symbol.name);
    
      symbolt *new_sp;
      symbol_table.move(new_symbol, new_sp);
    }

    // check the initializer
    do_initializer(symbol);
  }
}
Esempio n. 12
0
void java_bytecode_parse_treet::membert::output(std::ostream &out) const
{
  out << "  ";

  if(is_static)
    out << "static ";
  
  if(is_native)
    out << "native ";
  
  out << name;

  if(is_method)
  {
    out << "\n";

    out << "  {" << "\n";

    for(instructionst::const_iterator
        i_it=instructions.begin();
        i_it!=instructions.end();
        i_it++)
    {
      if(i_it->source_location.get_line()!=irep_idt())
        out << "    // " << i_it->source_location << "\n";

      out << "    " << i_it->address << ": ";
      out << i_it->statement;
      
      for(std::vector<exprt>::const_iterator
          a_it=i_it->args.begin(); a_it!=i_it->args.end(); a_it++)
      {
        if(a_it!=i_it->args.begin()) out << ",";
        out << " " << *a_it;
      }

      out << "\n";
    }

    out << "  }" << "\n";
  }
  else
  {
    out << ";";
  }

  out << "\n";
}
Esempio n. 13
0
irep_idt cpp_namet::get_base_name() const
{
  assert(is_simple_name());

  const subt &sub=get_sub();

  if(sub.size()==1 && sub.front().id()==ID_name)
    return sub.front().get(ID_identifier);
  else if(sub.size()==2 && sub.front().id()==ID_operator)
    return "operator"+sub[1].id_string();
  else if(sub.size()==2 && sub[0].id()=="~" && sub[1].id()==ID_name)
    return sub[0].id_string()+sub[1].get_string(ID_identifier); 
  else
    assert(false);

  return irep_idt();
}
Esempio n. 14
0
bool goto_program_dereferencet::has_failed_symbol(
  const exprt &expr,
  const symbolt *&symbol)
{
  if(expr.id()==ID_symbol)
  {
    if(expr.get_bool("#invalid_object"))
      return false;

    const symbolt &ptr_symbol=ns.lookup(expr);

    const irep_idt &failed_symbol=
      ptr_symbol.type.get("#failed_symbol");    
      
    if(failed_symbol==irep_idt()) return false;

    return !ns.lookup(failed_symbol, symbol);
  }
  
  return false;
}
Esempio n. 15
0
void ansi_c_declaratort::build(irept &src)
{
  typet *p=static_cast<typet *>(&src);
  
  // walk down subtype until we hit symbol or "abstract"
  while(true)
  {
    typet &t=*p;

    if(t.id()==ID_symbol)
    {
      set_base_name(t.get(ID_C_base_name));
      add_source_location()=t.source_location();
      t.make_nil();
      break;
    }
    else if(t.id()==irep_idt() ||
            t.is_nil())
    {
      //std::cerr << "D: " << src.pretty() << std::endl;
      assert(0);
    }
    else if(t.id()==ID_abstract)
    {
      t.make_nil();
      break;
    }
    else if(t.id()==ID_merged_type)
    {
      // we always walk down the _last_ member of a merged type
      assert(!t.subtypes().empty());
      p=&(t.subtypes().back());
    }
    else
      p=&t.subtype();
  }
  
  type()=static_cast<const typet &>(src);
  value().make_nil();
}
void remove_function_pointerst::fix_return_type(
  code_function_callt &function_call,
  goto_programt &dest)
{
  // are we returning anything at all?
  if(function_call.lhs().is_nil())
    return;

  const code_typet &code_type=
    to_code_type(ns.follow(function_call.function().type()));

  // type already ok?
  if(type_eq(
       function_call.lhs().type(),
       code_type.return_type(), ns))
    return;

  symbolt &tmp_symbol=
    get_fresh_aux_symbol(
      code_type.return_type(),
      "remove_function_pointers",
      "tmp_return_val",
      function_call.source_location(),
      irep_idt(),
      symbol_table);

  symbol_exprt tmp_symbol_expr;
  tmp_symbol_expr.type()=tmp_symbol.type;
  tmp_symbol_expr.set_identifier(tmp_symbol.name);

  exprt old_lhs=function_call.lhs();
  function_call.lhs()=tmp_symbol_expr;

  goto_programt::targett t_assign=dest.add_instruction();
  t_assign->make_assignment();
  t_assign->code=code_assignt(
    old_lhs, typecast_exprt(tmp_symbol_expr, old_lhs.type()));
}
Esempio n. 17
0
void goto_inlinet::parameter_destruction(
  const source_locationt &source_location,
  const irep_idt &function_name,
  const code_typet &code_type,
  goto_programt &dest)
{
  const code_typet::parameterst &parameter_types=
    code_type.parameters();
  
  // iterates over the types of the parameters
  for(code_typet::parameterst::const_iterator
      it=parameter_types.begin();
      it!=parameter_types.end();
      it++)
  {
    const code_typet::parametert &parameter=*it;

    const irep_idt &identifier=parameter.get_identifier();

    if(identifier==irep_idt())
    {
      error().source_location=source_location;
      error() << "no identifier for function parameter" << eom;
      throw 0;
    }

    {
      const symbolt &symbol=ns.lookup(identifier);

      goto_programt::targett dead=dest.add_instruction();
      dead->make_dead();
      dead->code=code_deadt(symbol.symbol_expr());
      dead->code.add_source_location()=source_location;
      dead->source_location=source_location;
      dead->function=function_name; 
    }
  }
}
Esempio n. 18
0
void c_typecheck_baset::typecheck_code_type(code_typet &type)
{
  // the return type is still 'subtype()'
  type.return_type()=type.subtype();
  type.remove_subtype();

  code_typet::parameterst &parameters=type.parameters();

  // if we don't have any parameters, we assume it's (...)
  if(parameters.empty())
  {
    type.make_ellipsis();
  }
  else // we do have parameters
  {
    // is the last one ellipsis?
    if(type.parameters().back().id()==ID_ellipsis)
    {
      type.make_ellipsis();
      type.parameters().pop_back();
    }

    parameter_map.clear();

    for(auto &param : type.parameters())
    {
      // turn the declarations into parameters
      if(param.id()==ID_declaration)
      {
        ansi_c_declarationt &declaration=
          to_ansi_c_declaration(param);

        code_typet::parametert parameter;

        // first fix type
        typet &type=parameter.type();
        type=declaration.full_type(declaration.declarator());
        std::list<codet> tmp_clean_code;
        tmp_clean_code.swap(clean_code); // ignore side-effects
        typecheck_type(type);
        tmp_clean_code.swap(clean_code);
        adjust_function_parameter(type);

        // adjust the identifier
        irep_idt identifier=declaration.declarator().get_name();

        // abstract or not?
        if(identifier==irep_idt())
        {
          // abstract
          parameter.add_source_location()=declaration.type().source_location();
        }
        else
        {
          // make visible now, later parameters might use it
          parameter_map[identifier]=type;
          parameter.set_base_name(declaration.declarator().get_base_name());
          parameter.add_source_location()=
            declaration.declarator().source_location();
        }

        // put the parameter in place of the declaration
        param.swap(parameter);
      }
    }

    parameter_map.clear();

    if(parameters.size()==1 &&
       follow(parameters[0].type()).id()==ID_empty)
    {
      // if we just have one parameter of type void, remove it
      parameters.clear();
    }
  }

  typecheck_type(type.return_type());

  // 6.7.6.3:
  // "A function declarator shall not specify a return type that
  // is a function type or an array type."

  const typet &return_type=follow(type.return_type());

  if(return_type.id()==ID_array)
  {
    error().source_location=type.source_location();
    error() << "function must not return array" << eom;
    throw 0;
  }

  if(return_type.id()==ID_code)
  {
    error().source_location=type.source_location();
    error() << "function must not return function type" << eom;
    throw 0;
  }
}
Esempio n. 19
0
unsigned floatbv_typet::get_f() const
{
  const irep_idt &f=get(ID_f);
  assert(f!=irep_idt());
  return unsafe_string2unsigned(id2string(f));
}
Esempio n. 20
0
unsigned fixedbv_typet::get_integer_bits() const
{
  const irep_idt integer_bits=get(ID_integer_bits);
  assert(integer_bits!=irep_idt());
  return unsafe_string2unsigned(id2string(integer_bits));
}
Esempio n. 21
0
exprt boolbvt::bv_get_rec(
    const bvt &bv,
    const std::vector<bool> &unknown,
    std::size_t offset,
    const typet &type) const
{
    if(type.id()==ID_symbol)
        return bv_get_rec(bv, unknown, offset, ns.follow(type));

    std::size_t width=boolbv_width(type);

    assert(bv.size()==unknown.size());
    assert(bv.size()>=offset+width);

    if(type.id()==ID_bool)
    {
        if(!unknown[offset])
        {
            switch(prop.l_get(bv[offset]).get_value())
            {
            case tvt::tv_enumt::TV_FALSE:
                return false_exprt();
            case tvt::tv_enumt::TV_TRUE:
                return true_exprt();
            default:
                return false_exprt(); // default
            }
        }

        return nil_exprt();
    }

    bvtypet bvtype=get_bvtype(type);

    if(bvtype==IS_UNKNOWN)
    {
        if(type.id()==ID_array)
        {
            const typet &subtype=type.subtype();
            std::size_t sub_width=boolbv_width(subtype);

            if(sub_width!=0)
            {
                exprt::operandst op;
                op.reserve(width/sub_width);

                for(std::size_t new_offset=0;
                        new_offset<width;
                        new_offset+=sub_width)
                {
                    op.push_back(
                        bv_get_rec(bv, unknown, offset+new_offset, subtype));
                }

                exprt dest=exprt(ID_array, type);
                dest.operands().swap(op);
                return dest;
            }
        }
        else if(type.id()==ID_struct_tag)
        {
            return bv_get_rec(bv, unknown, offset, ns.follow_tag(to_struct_tag_type(type)));
        }
        else if(type.id()==ID_union_tag)
        {
            return bv_get_rec(bv, unknown, offset, ns.follow_tag(to_union_tag_type(type)));
        }
        else if(type.id()==ID_struct)
        {
            const struct_typet &struct_type=to_struct_type(type);
            const struct_typet::componentst &components=struct_type.components();
            std::size_t new_offset=0;
            exprt::operandst op;
            op.reserve(components.size());

            for(struct_typet::componentst::const_iterator
                    it=components.begin();
                    it!=components.end();
                    it++)
            {
                const typet &subtype=ns.follow(it->type());
                op.push_back(nil_exprt());

                std::size_t sub_width=boolbv_width(subtype);

                if(sub_width!=0)
                {
                    op.back()=bv_get_rec(bv, unknown, offset+new_offset, subtype);
                    new_offset+=sub_width;
                }
            }

            struct_exprt dest(type);
            dest.operands().swap(op);
            return dest;
        }
        else if(type.id()==ID_union)
        {
            const union_typet &union_type=to_union_type(type);
            const union_typet::componentst &components=union_type.components();

            assert(!components.empty());

            // Any idea that's better than just returning the first component?
            std::size_t component_nr=0;

            union_exprt value(union_type);

            value.set_component_name(
                components[component_nr].get_name());

            const typet &subtype=components[component_nr].type();

            value.op()=bv_get_rec(bv, unknown, offset, subtype);

            return value;
        }
        else if(type.id()==ID_vector)
        {
            const typet &subtype=ns.follow(type.subtype());
            std::size_t sub_width=boolbv_width(subtype);

            if(sub_width!=0 && width%sub_width==0)
            {
                std::size_t size=width/sub_width;
                exprt value(ID_vector, type);
                value.operands().resize(size);

                for(std::size_t i=0; i<size; i++)
                    value.operands()[i]=
                        bv_get_rec(bv, unknown, i*sub_width, subtype);

                return value;
            }
        }
        else if(type.id()==ID_complex)
        {
            const typet &subtype=ns.follow(type.subtype());
            std::size_t sub_width=boolbv_width(subtype);

            if(sub_width!=0 && width==sub_width*2)
            {
                exprt value(ID_complex, type);
                value.operands().resize(2);

                value.op0()=bv_get_rec(bv, unknown, 0*sub_width, subtype);
                value.op1()=bv_get_rec(bv, unknown, 1*sub_width, subtype);

                return value;
            }
        }
    }

    std::string value;

    for(std::size_t bit_nr=offset; bit_nr<offset+width; bit_nr++)
    {
        char ch;
        if(unknown[bit_nr])
            ch='0';
        else
            switch(prop.l_get(bv[bit_nr]).get_value())
            {
            case tvt::tv_enumt::TV_FALSE:
                ch='0';
                break;
            case tvt::tv_enumt::TV_TRUE:
                ch='1';
                break;
            case tvt::tv_enumt::TV_UNKNOWN:
                ch='0';
                break;
            default:
                assert(false);
            }

        value=ch+value;
    }

    switch(bvtype)
    {
    case IS_UNKNOWN:
        if(type.id()==ID_string)
        {
            mp_integer int_value=binary2integer(value, false);
            irep_idt s;
            if(int_value>=string_numbering.size())
                s=irep_idt();
            else
                s=string_numbering[int_value.to_long()];

            return constant_exprt(s, type);
        }
        break;

    case IS_RANGE:
    {
        mp_integer int_value=binary2integer(value, false);
        mp_integer from=string2integer(type.get_string(ID_from));

        constant_exprt value_expr(type);
        value_expr.set_value(integer2string(int_value+from));
        return value_expr;
    }
    break;

    default:
    case IS_C_ENUM:
        constant_exprt value_expr(type);
        value_expr.set_value(value);
        return value_expr;
    }

    return nil_exprt();
}
Esempio n. 22
0
void legacy_message_streamt::error_parse_line(
  unsigned level,
  const std::string &line)
{
  std::string error_msg=line;

  if(has_prefix(line, "file "))
  {
    const char *tptr=line.c_str();
    int state=0;
    std::string file, line_no, column, _error_msg, function;

    tptr+=5;

    char previous=0;

    while(*tptr!=0)
    {
      if(strncmp(tptr, " line ", 6)==0 && state!=4)
      {
        state=1;
        tptr+=6;
        continue;
      }
      else if(strncmp(tptr, " column ", 8)==0 && state!=4)
      {
        state=2;
        tptr+=8;
        continue;
      }
      else if(strncmp(tptr, " function ", 10)==0 && state!=4)
      {
        state=3;
        tptr+=10;
        continue;
      }
      else if(*tptr==':' && state!=4)
      {
        if(tptr[1]==' ' && previous!=':')
        {
          state=4;
          tptr++;
          while(*tptr==' ') tptr++;
          continue;
        }
      }

      if(state==0) // file
        file+=*tptr;
      else if(state==1) // line number
        line_no+=*tptr;
      else if(state==2) // column
        column+=*tptr;
      else if(state==3) // function
        function+=*tptr;
      else if(state==4) // error message
        _error_msg+=*tptr;

      previous=*tptr;

      tptr++;
    }

    if(state==4)
    {
      saved_error_location.id(irep_idt());
      saved_error_location.set_line(line_no);
      saved_error_location.set_file(file);
      saved_error_location.set_column(column);
      error_msg=_error_msg;
      saved_error_location.set_function(function);
    }
  }
  else if(has_prefix(line, "In file included from "))
  {
  }
  else
  {
    const char *tptr=line.c_str();
    int state=0;
    std::string file, line_no;

    while(*tptr!=0)
    {
      if(state==0)
      {
        if(*tptr==':')
          state++;
        else
          file+=*tptr;
      }
      else if(state==1)
      {
        if(*tptr==':')
          state++;
        else if(isdigit(*tptr))
          line_no+=*tptr;
        else
          state=3;
      }

      tptr++;
    }

    if(state==2)
    {
      saved_error_location.id(irep_idt());
      saved_error_location.set_line(line_no);
      saved_error_location.set_file(file);
      saved_error_location.set_function("");
      saved_error_location.set_column("");
    }
  }

  if(message_handler!=NULL)
    message_handler->print(
      level, error_msg, sequence_number++, saved_error_location);
}
Esempio n. 23
0
exprt convert_float_literal(const std::string &src)
{
  mp_integer significand;
  mp_integer exponent;
  bool is_float, is_long, is_imaginary;
  bool is_decimal, is_float80, is_float128; // GCC extensions
  unsigned base;
  
  parse_float(src, significand, exponent, base,
              is_float, is_long, is_imaginary,
              is_decimal, is_float80, is_float128);

  exprt result=exprt(ID_constant);
  
  result.set(ID_C_cformat, src);
  
  // In ANSI-C, float literals are double by default,
  // unless marked with 'f'.
  // All of these can be complex as well.
  // This can be overriden with
  // config.ansi_c.single_precision_constant.

  if(is_float)
    result.type()=float_type();
  else if(is_long)
    result.type()=long_double_type();
  else if(is_float80)
  {
    result.type()=ieee_float_spect(64, 15).to_type();
    result.type().set(ID_C_c_type, ID_long_double);
  }
  else if(is_float128)
  {
    result.type()=ieee_float_spect::quadruple_precision().to_type();
    result.type().set(ID_C_c_type, ID_gcc_float128);
  }
  else
  {
    // default
    if(config.ansi_c.single_precision_constant)
      result.type()=float_type(); // default
    else
      result.type()=double_type(); // default
  }

  if(is_decimal)
  {
    // TODO - should set ID_gcc_decimal32/ID_gcc_decimal64/ID_gcc_decimal128,
    // but these aren't handled anywhere
  }
  
  if(config.ansi_c.use_fixed_for_float)
  {
    unsigned width=result.type().get_int(ID_width);
    unsigned fraction_bits;
    const irep_idt integer_bits=result.type().get(ID_integer_bits);
    
    assert(width!=0);

    if(integer_bits==irep_idt())
      fraction_bits=width/2; // default
    else
      fraction_bits=width-safe_string2int(id2string(integer_bits));

    mp_integer factor=mp_integer(1)<<fraction_bits;
    mp_integer value=significand*factor;
    
    if(value!=0)
    {
      if(exponent<0)
        value/=power(base, -exponent);
      else
      {
        value*=power(base, exponent);    

        if(value>=power(2, width-1))
        {
          // saturate: use "biggest value"
          value=power(2, width-1)-1;
        }
        else if(value<=-power(2, width-1)-1)
        {
          // saturate: use "smallest value"
          value=-power(2, width-1);
        }
      }
    }

    result.set(ID_value, integer2binary(value, width));  
  }
  else
  {
    ieee_floatt a;

    a.spec=to_floatbv_type(result.type());
    
    if(base==10)
      a.from_base10(significand, exponent);
    else if(base==2) // hex
      a.build(significand, exponent);
    else
      assert(false);

    result.set(ID_value,
      integer2binary(a.pack(), a.spec.width()));  
  }

  if(is_imaginary)
  {
    complex_typet complex_type;
    complex_type.subtype()=result.type();
    exprt complex_expr(ID_complex, complex_type);
    complex_expr.operands().resize(2);
    complex_expr.op0()=gen_zero(result.type());
    complex_expr.op1()=result;
    return complex_expr;
  }
  
  return result;
}
Esempio n. 24
0
void c_typecheck_baset::typecheck_function_body(symbolt &symbol)
{
  code_typet &code_type=to_code_type(symbol.type);
  
  assert(symbol.value.is_not_nil());
  
  // reset labels
  labels_used.clear();
  labels_defined.clear();

  // fix type
  symbol.value.type()=code_type;
    
  // set return type
  return_type=code_type.return_type();
  
  unsigned anon_counter=0;
  
  // Add the parameter declarations into the symbol table.
  code_typet::parameterst &parameters=code_type.parameters();
  for(code_typet::parameterst::iterator
      p_it=parameters.begin();
      p_it!=parameters.end();
      p_it++)
  {
    // may be anonymous
    if(p_it->get_base_name()==irep_idt())
    {
      irep_idt base_name="#anon"+i2string(anon_counter++);
      p_it->set_base_name(base_name);
    }
    
    // produce identifier
    irep_idt base_name=p_it->get_base_name();
    irep_idt identifier=id2string(symbol.name)+"::"+id2string(base_name);

    p_it->set_identifier(identifier);

    parameter_symbolt p_symbol;
    
    p_symbol.type=p_it->type();
    p_symbol.name=identifier;
    p_symbol.base_name=base_name;
    p_symbol.location=p_it->source_location();

    symbolt *new_p_symbol;
    move_symbol(p_symbol, new_p_symbol);
  }

  // typecheck the body code  
  typecheck_code(to_code(symbol.value));

  // special case for main()  
  if(symbol.name==ID_main)
    add_argc_argv(symbol);

  // check the labels
  for(std::map<irep_idt, source_locationt>::const_iterator
      it=labels_used.begin(); it!=labels_used.end(); it++)
  {
    if(labels_defined.find(it->first)==labels_defined.end())
    {
      err_location(it->second);
      str << "branching label `" << it->first
          << "' is not defined in function";
      throw 0;
    }
  }
}
Esempio n. 25
0
void c_typecheck_baset::typecheck_compound_body(
  struct_union_typet &type)
{
  struct_union_typet::componentst &components=type.components();

  struct_union_typet::componentst old_components;
  old_components.swap(components);

  // We get these as declarations!
  for(auto &decl : old_components)
  {
    // the arguments are member declarations or static assertions
    assert(decl.id()==ID_declaration);

    ansi_c_declarationt &declaration=
      to_ansi_c_declaration(static_cast<exprt &>(decl));

    if(declaration.get_is_static_assert())
    {
      struct_union_typet::componentt new_component;
      new_component.id(ID_static_assert);
      new_component.add_source_location()=declaration.source_location();
      new_component.operands().swap(declaration.operands());
      assert(new_component.operands().size()==2);
      components.push_back(new_component);
    }
    else
    {
      // do first half of type
      typecheck_type(declaration.type());
      make_already_typechecked(declaration.type());

      for(const auto &declarator : declaration.declarators())
      {
        struct_union_typet::componentt new_component;

        new_component.add_source_location()=
          declarator.source_location();
        new_component.set(ID_name, declarator.get_base_name());
        new_component.set(ID_pretty_name, declarator.get_base_name());
        new_component.type()=declaration.full_type(declarator);

        typecheck_type(new_component.type());

        if(!is_complete_type(new_component.type()) &&
           (new_component.type().id()!=ID_array ||
            !to_array_type(new_component.type()).is_incomplete()))
        {
          error().source_location=new_component.type().source_location();
          error() << "incomplete type not permitted here" << eom;
          throw 0;
        }

        components.push_back(new_component);
      }
    }
  }

  unsigned anon_member_counter=0;

  // scan for anonymous members, and name them
  for(auto &member : components)
  {
    if(member.get_name()!=irep_idt())
      continue;

    member.set_name("$anon"+std::to_string(anon_member_counter++));
    member.set_anonymous(true);
  }

  // scan for duplicate members

  {
    std::unordered_set<irep_idt, irep_id_hash> members;

    for(struct_union_typet::componentst::iterator
        it=components.begin();
        it!=components.end();
        it++)
    {
      if(!members.insert(it->get_name()).second)
      {
        error().source_location=it->source_location();
        error() << "duplicate member '" << it->get_name() << '\'' << eom;
        throw 0;
      }
    }
  }

  // We allow an incomplete (C99) array as _last_ member!
  // Zero-length is allowed everywhere.

  if(type.id()==ID_struct ||
     type.id()==ID_union)
  {
    for(struct_union_typet::componentst::iterator
        it=components.begin();
        it!=components.end();
        it++)
    {
      typet &c_type=it->type();

      if(c_type.id()==ID_array &&
         to_array_type(c_type).is_incomplete())
      {
        // needs to be last member
        if(type.id()==ID_struct && it!=--components.end())
        {
          error().source_location=it->source_location();
          error() << "flexible struct member must be last member" << eom;
          throw 0;
        }

        // make it zero-length
        c_type.id(ID_array);
        c_type.set(ID_size, from_integer(0, index_type()));
      }
    }
  }

  // We may add some minimal padding inside and at
  // the end of structs and
  // as additional member for unions.

  if(type.id()==ID_struct)
    add_padding(to_struct_type(type), *this);
  else if(type.id()==ID_union)
    add_padding(to_union_type(type), *this);

  // Now remove zero-width bit-fields, these are just
  // for adjusting alignment.
  for(struct_typet::componentst::iterator
      it=components.begin();
      it!=components.end();
      ) // blank
  {
    if(it->type().id()==ID_c_bit_field &&
       to_c_bit_field_type(it->type()).get_width()==0)
      it=components.erase(it);
    else
      it++;
  }

  // finally, check _Static_assert inside the compound
  for(struct_union_typet::componentst::iterator
      it=components.begin();
      it!=components.end();
      ) // no it++
  {
    if(it->id()==ID_static_assert)
    {
      assert(it->operands().size()==2);
      exprt &assertion=it->op0();
      typecheck_expr(assertion);
      typecheck_expr(it->op1());
      assertion.make_typecast(bool_typet());
      make_constant(assertion);

      if(assertion.is_false())
      {
        error().source_location=it->source_location();
        error() << "failed _Static_assert" << eom;
        throw 0;
      }
      else if(!assertion.is_true())
      {
        // should warn/complain
      }

      it=components.erase(it);
    }
    else
      it++;
  }
}
Esempio n. 26
0
void c_typecheck_baset::typecheck_array_type(array_typet &type)
{
  exprt &size=type.size();
  source_locationt source_location=size.find_source_location();

  // check subtype
  typecheck_type(type.subtype());

  // we don't allow void as subtype
  if(follow(type.subtype()).id()==ID_empty)
  {
    error().source_location=type.source_location();
    error() << "array of voids" << eom;
    throw 0;
  }

  // check size, if any

  if(size.is_not_nil())
  {
    typecheck_expr(size);
    make_index_type(size);

    // The size need not be a constant!
    // We simplify it, for the benefit of array initialisation.

    exprt tmp_size=size;
    add_rounding_mode(tmp_size);
    simplify(tmp_size, *this);

    if(tmp_size.is_constant())
    {
      mp_integer s;
      if(to_integer(tmp_size, s))
      {
        error().source_location=source_location;
        error() << "failed to convert constant: "
                << tmp_size.pretty() << eom;
        throw 0;
      }

      if(s<0)
      {
        error().source_location=source_location;
        error() << "array size must not be negative, "
                   "but got " << s << eom;
        throw 0;
      }

      size=tmp_size;
    }
    else if(tmp_size.id()==ID_infinity)
    {
      size=tmp_size;
    }
    else if(tmp_size.id()==ID_symbol &&
            tmp_size.type().get_bool(ID_C_constant))
    {
      // We allow a constant variable as array size, assuming
      // it won't change.
      // This criterion can be tricked:
      // Of course we can modify a 'const' symbol, e.g.,
      // using a pointer type cast. Interestingly,
      // at least gcc 4.2.1 makes the very same mistake!
      size=tmp_size;
    }
    else
    {
      // not a constant and not infinity

      assert(current_symbol_id!=irep_idt());

      const symbolt &base_symbol=lookup(current_symbol_id);

      // Need to pull out! We insert new symbol.
      source_locationt source_location=size.find_source_location();
      unsigned count=0;
      irep_idt temp_identifier;
      std::string suffix;

      do
      {
        suffix="$array_size"+std::to_string(count);
        temp_identifier=id2string(base_symbol.name)+suffix;
        count++;
      }
      while(symbol_table.symbols.find(temp_identifier)!=
            symbol_table.symbols.end());

      // add the symbol to symbol table
      auxiliary_symbolt new_symbol;
      new_symbol.name=temp_identifier;
      new_symbol.pretty_name=id2string(base_symbol.pretty_name)+suffix;
      new_symbol.base_name=id2string(base_symbol.base_name)+suffix;
      new_symbol.type=size.type();
      new_symbol.type.set(ID_C_constant, true);
      new_symbol.is_type=false;
      new_symbol.is_static_lifetime=false;
      new_symbol.value.make_nil();
      new_symbol.location=source_location;

      symbol_table.add(new_symbol);

      // produce the code that declares and initializes the symbol
      symbol_exprt symbol_expr;
      symbol_expr.set_identifier(temp_identifier);
      symbol_expr.type()=new_symbol.type;

      code_declt declaration(symbol_expr);
      declaration.add_source_location()=source_location;

      code_assignt assignment;
      assignment.lhs()=symbol_expr;
      assignment.rhs()=size;
      assignment.add_source_location()=source_location;

      // store the code
      clean_code.push_back(declaration);
      clean_code.push_back(assignment);

      // fix type
      size=symbol_expr;
    }
  }
}
Esempio n. 27
0
void goto_checkt::goto_check(goto_functiont &goto_function)
{
  {
    const symbolt *init_symbol;
    if(!ns.lookup(CPROVER_PREFIX "initialize", init_symbol))
      mode=init_symbol->mode;
  }

  assertions.clear();

  local_bitvector_analysist local_bitvector_analysis_obj(goto_function);
  local_bitvector_analysis=&local_bitvector_analysis_obj;

  goto_programt &goto_program=goto_function.body;

  Forall_goto_program_instructions(it, goto_program)
  {
    t=it;
    goto_programt::instructiont &i=*it;

    new_code.clear();

    // we clear all recorded assertions if
    // 1) we want to generate all assertions or
    // 2) the instruction is a branch target
    if(retain_trivial ||
       i.is_target())
      assertions.clear();

    check(i.guard);

    // magic ERROR label?
    for(optionst::value_listt::const_iterator
        l_it=error_labels.begin();
        l_it!=error_labels.end();
        l_it++)
    {
      if(std::find(i.labels.begin(), i.labels.end(), *l_it)!=i.labels.end())
      {
        goto_program_instruction_typet type=
          enable_assert_to_assume?ASSUME:ASSERT;

        goto_programt::targett t=new_code.add_instruction(type);

        t->guard=false_exprt();
        t->source_location=i.source_location;
        t->source_location.set_property_class("error label");
        t->source_location.set_comment("error label "+*l_it);
        t->source_location.set("user-provided", true);
      }
    }

    if(i.is_other())
    {
      const irep_idt &statement=i.code.get(ID_statement);

      if(statement==ID_expression)
      {
        check(i.code);
      }
      else if(statement==ID_printf)
      {
        forall_operands(it, i.code)
          check(*it);
      }
    }
    else if(i.is_assign())
    {
      const code_assignt &code_assign=to_code_assign(i.code);

      check(code_assign.lhs());
      check(code_assign.rhs());

      // the LHS might invalidate any assertion
      invalidate(code_assign.lhs());
    }
    else if(i.is_function_call())
    {
      const code_function_callt &code_function_call=
        to_code_function_call(i.code);

      // for Java, need to check whether 'this' is null
      // on non-static method invocations
      if(mode==ID_java &&
         enable_pointer_check &&
         !code_function_call.arguments().empty() &&
         code_function_call.function().type().id()==ID_code &&
         to_code_type(code_function_call.function().type()).has_this())
      {
        exprt pointer=code_function_call.arguments()[0];

        local_bitvector_analysist::flagst flags=
          local_bitvector_analysis->get(t, pointer);

        if(flags.is_unknown() || flags.is_null())
        {
          notequal_exprt not_eq_null(pointer, gen_zero(pointer.type()));

          add_guarded_claim(
            not_eq_null,
            "this is null on method invokation",
            "pointer dereference",
            i.source_location,
            pointer,
            guardt());
        }
      }

      forall_operands(it, code_function_call)
        check(*it);

      // the call might invalidate any assertion
      assertions.clear();
    }
    else if(i.is_return())
    {
      if(i.code.operands().size()==1)
      {
        check(i.code.op0());
        // the return value invalidate any assertion
        invalidate(i.code.op0());
      }
    }
    else if(i.is_throw())
    {
      if(i.code.get_statement()==ID_expression &&
         i.code.operands().size()==1 &&
         i.code.op0().operands().size()==1)
      {
        // must not throw NULL

        exprt pointer=i.code.op0().op0();

        if(pointer.type().subtype().get(ID_identifier)!="java::java.lang.AssertionError")
        {
          notequal_exprt not_eq_null(pointer, gen_zero(pointer.type()));

          add_guarded_claim(
            not_eq_null,
            "throwing null",
            "pointer dereference",
            i.source_location,
            pointer,
            guardt());
        }
      }

      // this has no successor
      assertions.clear();
    }
    else if(i.is_assert())
    {
      if(i.source_location.get_bool("user-provided") &&
         i.source_location.get_property_class()!="error label" &&
         !enable_assertions)
        i.type=SKIP;
    }
    else if(i.is_assume())
    {
      if(!enable_assumptions)
        i.type=SKIP;
    }
    else if(i.is_dead())
    {
      if(enable_pointer_check)
      {
        assert(i.code.operands().size()==1);
        const symbol_exprt &variable=to_symbol_expr(i.code.op0());

        // is it dirty?
        if(local_bitvector_analysis->dirty(variable))
        {
          // need to mark the dead variable as dead
          goto_programt::targett t=new_code.add_instruction(ASSIGN);
          exprt address_of_expr=address_of_exprt(variable);
          exprt lhs=ns.lookup(CPROVER_PREFIX "dead_object").symbol_expr();
          if(!base_type_eq(lhs.type(), address_of_expr.type(), ns))
            address_of_expr.make_typecast(lhs.type());
          exprt rhs=if_exprt(
            side_effect_expr_nondett(bool_typet()), address_of_expr, lhs, lhs.type());
          t->source_location=i.source_location;
          t->code=code_assignt(lhs, rhs);
          t->code.add_source_location()=i.source_location;
        }
      }
    }
    else if(i.is_end_function())
    {
      if(i.function==goto_functionst::entry_point() &&
         enable_memory_leak_check)
      {
        const symbolt &leak=ns.lookup(CPROVER_PREFIX "memory_leak");
        const symbol_exprt leak_expr=leak.symbol_expr();

        // add self-assignment to get helpful counterexample output
        goto_programt::targett t=new_code.add_instruction();
        t->make_assignment();
        t->code=code_assignt(leak_expr, leak_expr);

        source_locationt source_location;
        source_location.set_function(i.function);

        equal_exprt eq(leak_expr, gen_zero(ns.follow(leak.type)));
        add_guarded_claim(
          eq,
          "dynamically allocated memory never freed",
          "memory-leak",
          source_location,
          eq,
          guardt());
      }
    }

    for(goto_programt::instructionst::iterator
        i_it=new_code.instructions.begin();
        i_it!=new_code.instructions.end();
        i_it++)
    {
      if(i_it->source_location.is_nil())
      {
        i_it->source_location.id(irep_idt());

        if(it->source_location.get_file()!=irep_idt())
          i_it->source_location.set_file(it->source_location.get_file());

        if(it->source_location.get_line()!=irep_idt())
          i_it->source_location.set_line(it->source_location.get_line());

        if(it->source_location.get_function()!=irep_idt())
          i_it->source_location.set_function(it->source_location.get_function());

        if(it->source_location.get_column()!=irep_idt())
          i_it->source_location.set_column(it->source_location.get_column());
      }

      if(i_it->function==irep_idt()) i_it->function=it->function;
    }

    // insert new instructions -- make sure targets are not moved

    while(!new_code.instructions.empty())
    {
      goto_program.insert_before_swap(it, new_code.instructions.front());
      new_code.instructions.pop_front();
      it++;
    }
  }
Esempio n. 28
0
std::string type2name(const typet &type)
{
  std::string result;
  
  // qualifiers first
  if(type.get_bool(ID_C_constant))
    result+="c";

  if(type.get_bool(ID_C_restricted))
    result+="r";

  if(type.get_bool(ID_C_volatile))
    result+="v";

  if(type.id()==irep_idt())
    throw "Empty type encountered.";
  else if(type.id()==ID_empty)
    result+="V";   
  else if(type.id()==ID_signedbv)
    result+="S" + type.get_string(ID_width);
  else if(type.id()==ID_unsignedbv)
    result+="U" + type.get_string(ID_width);
  else if(type.id()==ID_bool) 
    result+="B";
  else if(type.id()==ID_integer) 
    result+="I";
  else if(type.id()==ID_real) 
    result+="R";
  else if(type.id()==ID_complex) 
    result+="C";
  else if(type.id()==ID_floatbv) 
    result+="F" + type.get_string(ID_width);
  else if(type.id()==ID_fixedbv) 
    result+="X" + type.get_string(ID_width);
  else if(type.id()==ID_natural)
    result+="N";
  else if(type.id()==ID_pointer)
    result+="*";
  else if(type.id()==ID_reference)
    result+="&";
  else if(type.id()==ID_code)
  {
    const code_typet &t=to_code_type(type);
    const code_typet::argumentst arguments=t.arguments();
    result+="P(";

    for(code_typet::argumentst::const_iterator it=arguments.begin();
        it!=arguments.end();
        it++)
    {      
      result+=type2name(it->type());
      result+="'" + id2string(it->get_identifier()) + "'|";
    }
    result.resize(result.size()-1);
    result+=")";
  }
  else if(type.id()==ID_array)
  {
    const array_typet &t=to_array_type(type);
    if(t.size().is_nil())
      result+="ARR?";
    else
      result+="ARR"+t.size().get_string(ID_value);
  }
  else if(type.id()==ID_symbol)
  {
    result+="SYM#"+type.get_string(ID_identifier)+"#";
  }
  else if(type.id()==ID_struct || 
          type.id()==ID_union)
  {
    if(type.id()==ID_struct) result+="ST";
    if(type.id()==ID_union) result+="UN";
    const struct_union_typet &t=to_struct_union_type(type);
    const struct_union_typet::componentst &components = t.components();
    result+="[";
    for(struct_union_typet::componentst::const_iterator
        it=components.begin();
        it!=components.end();
        it++)
    {            
      if(it!=components.begin()) result+="|";
      result+=type2name(it->type());
      result+="'"+it->get_string(ID_name)+"'|";
    }
    result+="]";
  }
  else if(type.id()==ID_incomplete_struct)
    result +="ST?";
  else if(type.id()==ID_incomplete_union)
    result +="UN?";
  else if(type.id()==ID_c_enum)
    result +="EN"+type.get_string(ID_width);
  else if(type.id()==ID_incomplete_c_enum)
    result +="EN?";
  else if(type.id()==ID_c_bitfield)
    result+="BF"+type.get_string(ID_size);
  else if(type.id()==ID_vector)
    result+="VEC"+type.get_string(ID_size);
  else
    throw (std::string("Unknown type '") + 
           type.id_string() + 
           "' encountered."); 
    
  if(type.has_subtype())
  {
    result+="{";
    result+=type2name(type.subtype());    
    result+="}";
  }

  if(type.has_subtypes())
  {
    result+="$";
    forall_subtypes(it, type)
    {      
      result+=type2name(*it);
      result+="|";      
    }
exprt convert_float_literal(const std::string &src)
{
  mp_integer significand;
  mp_integer exponent;
  bool is_float, is_long, is_fixed, is_accum;
  unsigned base;
  
  parse_float(src, significand, exponent, base, is_float, is_long, is_fixed, is_accum);

  exprt result=exprt(ID_constant);
  
  result.set(ID_C_cformat, src);
  
  // In ANSI-C, float literals are double by default
  // unless marked with 'f'.

  if(is_float)
  {
    result.type()=float_type();
    result.type().set(ID_C_cpp_type, ID_float);
  }
  else if(is_long)
  {
    result.type()=long_double_type();
    result.type().set(ID_C_cpp_type, ID_long_double);
  }
  else if(is_fixed)
  {
    result.type()=fixed_type();
    result.type().set(ID_C_cpp_type, ID_fixed);
  }
  else if(is_accum)
  {
    result.type()=accum_type();
    result.type().set(ID_C_cpp_type, ID_accum);
  }
  else
  {
    result.type()=double_type(); // default
    result.type().set(ID_C_cpp_type, ID_double);
  }


  if(config.ansi_c.use_fixed_for_float || is_fixed || is_accum)
  {
    unsigned width=result.type().get_int(ID_width);
    unsigned fraction_bits;
    const irep_idt integer_bits=result.type().get(ID_integer_bits);
    
    assert(width!=0);

    if(is_fixed)
    {
      fraction_bits = width - 1;
    }
    else if(is_accum)
    {
      fraction_bits = width - 9;
    }
    else if(integer_bits==irep_idt())
      fraction_bits=width/2; // default
    else
      fraction_bits=width-safe_string2int(id2string(integer_bits));

    mp_integer factor=mp_integer(1)<<fraction_bits;
    mp_integer value=significand*factor;
    
    if(value!=0)
    {
      if(exponent<0)
        value/=power(base, -exponent);
      else
      {
        value*=power(base, exponent);    

        if(value>=power(2, width-1))
        {
          // saturate: use "biggest value"
          value=power(2, width-1)-1;
        }
        else if(value<=-power(2, width-1)-1)
        {
          // saturate: use "smallest value"
          value=-power(2, width-1);
        }
      }
    }

    result.set(ID_value, integer2binary(value, width));  
  }
  else
  {
    ieee_floatt a;

    a.spec=to_floatbv_type(result.type());
    
    if(base==10)
      a.from_base10(significand, exponent);
    else if(base==2) // hex
      a.build(significand, exponent);
    else
      assert(false);

    result.set(ID_value,
      integer2binary(a.pack(), a.spec.width()));  
  }
  
  return result;
}
Esempio n. 30
0
void build_goto_trace(
  const path_symex_statet &state,
  const decision_proceduret &decision_procedure,
  goto_tracet &goto_trace)
{
  // follow the history in the state,
  // but in a forwards-fashion

  std::vector<path_symex_step_reft> steps;
  state.history.build_history(steps);

  unsigned step_nr;

  for(step_nr=0; step_nr<steps.size(); step_nr++)
  {
    const path_symex_stept &step=*steps[step_nr];

    goto_trace_stept trace_step;

    assert(!step.pc.is_nil());
    trace_step.pc=state.locs[step.pc].target;
    trace_step.thread_nr=step.thread_nr;
    trace_step.step_nr=step_nr;

    const goto_programt::instructiont &instruction=*trace_step.pc;

    switch(instruction.type)
    {
    case ASSIGN:
      trace_step.type=goto_trace_stept::ASSIGNMENT;
      trace_step.full_lhs=step.full_lhs;
      trace_step.full_lhs_value=decision_procedure.get(step.ssa_lhs);
      break;

    case DECL:
      trace_step.type=goto_trace_stept::DECL;
      trace_step.full_lhs=step.full_lhs;
      trace_step.lhs_object=ssa_exprt(step.full_lhs);
      trace_step.full_lhs_value=decision_procedure.get(step.ssa_lhs);
      break;

    case DEAD:
      trace_step.type=goto_trace_stept::DEAD;
      break;

    case ASSUME:
      trace_step.type=goto_trace_stept::ASSUME;
      break;

    case FUNCTION_CALL:
      trace_step.type=goto_trace_stept::FUNCTION_CALL;
      break;

    case END_FUNCTION:
      trace_step.type=goto_trace_stept::FUNCTION_RETURN;
      break;

    case START_THREAD:
      trace_step.type=goto_trace_stept::SPAWN;
      break;

    case ATOMIC_BEGIN:
      trace_step.type=goto_trace_stept::ATOMIC_BEGIN;
      break;

    case ATOMIC_END:
      trace_step.type=goto_trace_stept::ATOMIC_END;
      break;

    default:
      trace_step.type=goto_trace_stept::LOCATION;
    }

    goto_trace.add_step(trace_step);
  }

  // add assertion
  const goto_programt::instructiont &instruction=
    *state.get_instruction();

  assert(instruction.is_assert());

  {
    goto_trace_stept trace_step;

    trace_step.pc=state.get_instruction();
    trace_step.thread_nr=state.get_current_thread();
    trace_step.step_nr=step_nr;
    trace_step.type=goto_trace_stept::ASSERT;

    const irep_idt &comment=
      instruction.source_location.get_comment();

    if(comment!=irep_idt())
      trace_step.comment=id2string(comment);
    else
      trace_step.comment="assertion";

    goto_trace.add_step(trace_step);
  }
}