Esempio n. 1
0
void java_bytecode_parsert::rconstant_pool()
{
  u2 constant_pool_count=read_u2();
  if(constant_pool_count==0)
  {
    error() << "invalid constant_pool_count" << eom;
    throw 0;
  }

  constant_pool.resize(constant_pool_count);

  for(constant_poolt::iterator
      it=constant_pool.begin();
      it!=constant_pool.end();
      it++)
  {
    // the first entry isn't used
    if(it==constant_pool.begin())
      continue;

    it->tag=read_u1();

    switch(it->tag)
    {
    case CONSTANT_Class:
      it->ref1=read_u2();
      break;

    case CONSTANT_Fieldref:
    case CONSTANT_Methodref:
    case CONSTANT_InterfaceMethodref:
    case CONSTANT_NameAndType:
    case CONSTANT_InvokeDynamic:
      it->ref1=read_u2();
      it->ref2=read_u2();
      break;

    case CONSTANT_String:
    case CONSTANT_MethodType:
      it->ref1=read_u2();
      break;

    case CONSTANT_Integer:
    case CONSTANT_Float:
      it->number=read_u4();
      break;

    case CONSTANT_Long:
    case CONSTANT_Double:
      it->number=read_u8();
      // Eight-byte constants take up two entires
      // in the constant_pool table, for annoying this programmer.
      if(it==constant_pool.end())
      {
        error() << "invalid double entry" << eom;
        throw 0;
      }
      it++;
      it->tag=0;
      break;

    case CONSTANT_Utf8:
      {
        u2 bytes=read_u2();
        std::string s;
        s.resize(bytes);
        for(std::string::iterator s_it=s.begin(); s_it!=s.end(); s_it++)
          *s_it=read_u1();
        it->s=s; // hashes
      }
      break;

    case CONSTANT_MethodHandle:
      it->ref1=read_u1();
      it->ref2=read_u2();
      break;

    default:
      error() << "unknown constant pool entry (" << it->tag << ")"
              << eom;
      throw 0;
    }
  }

  // we do a bit of post-processing after we have them all
  for(constant_poolt::iterator
      it=constant_pool.begin();
      it!=constant_pool.end();
      it++)
  {
    // the first entry isn't used
    if(it==constant_pool.begin())
      continue;

    switch(it->tag)
    {
    case CONSTANT_Class:
      {
        const std::string &s=id2string(pool_entry(it->ref1).s);
        it->expr=type_exprt(java_classname(s));
      }
      break;

    case CONSTANT_Fieldref:
      {
        const pool_entryt &nameandtype_entry=pool_entry(it->ref2);
        const pool_entryt &name_entry=pool_entry(nameandtype_entry.ref1);
        const pool_entryt &class_entry=pool_entry(it->ref1);
        const pool_entryt &class_name_entry=pool_entry(class_entry.ref1);
        typet type=type_entry(nameandtype_entry.ref2);

        symbol_typet class_symbol=
          java_classname(id2string(class_name_entry.s));

        exprt fieldref("fieldref", type);
        fieldref.set(ID_class, class_symbol.get_identifier());
        fieldref.set(ID_component_name, name_entry.s);

        it->expr=fieldref;
      }
      break;

    case CONSTANT_Methodref:
    case CONSTANT_InterfaceMethodref:
      {
        const pool_entryt &nameandtype_entry=pool_entry(it->ref2);
        const pool_entryt &name_entry=pool_entry(nameandtype_entry.ref1);
        const pool_entryt &class_entry=pool_entry(it->ref1);
        const pool_entryt &class_name_entry=pool_entry(class_entry.ref1);
        typet type=type_entry(nameandtype_entry.ref2);

        symbol_typet class_symbol=
          java_classname(id2string(class_name_entry.s));

        irep_idt component_name=
          id2string(name_entry.s)+
          ":"+id2string(pool_entry(nameandtype_entry.ref2).s);

        irep_idt class_name=
          class_symbol.get_identifier();

        irep_idt identifier=
          id2string(class_name)+"."+id2string(component_name);

        exprt virtual_function(ID_virtual_function, type);
        virtual_function.set(ID_component_name, component_name);
        virtual_function.set(ID_C_class, class_name);
        virtual_function.set(ID_C_base_name, name_entry.s);
        virtual_function.set(ID_identifier, identifier);

        it->expr=virtual_function;
      }
      break;

    case CONSTANT_String:
      {
        // ldc turns these into references to java.lang.String
        exprt string_literal(ID_java_string_literal);
        string_literal.set(ID_value, pool_entry(it->ref1).s);
        it->expr=string_literal;
      }
      break;

    case CONSTANT_Integer:
      it->expr=from_integer(it->number, java_int_type());
      break;

    case CONSTANT_Float:
      {
        ieee_floatt value(ieee_float_spect::single_precision());
        value.unpack(it->number);
        it->expr=value.to_expr();
      }
      break;

    case CONSTANT_Long:
      it->expr=from_integer(it->number, java_long_type());
      break;

    case CONSTANT_Double:
      {
        ieee_floatt value(ieee_float_spect::double_precision());
        value.unpack(it->number);
        it->expr=value.to_expr();
      }
      break;

    case CONSTANT_NameAndType:
      {
        it->expr.id("nameandtype");
      }
      break;

    case CONSTANT_MethodHandle:
      {
        it->expr.id("methodhandle");
      }
      break;

    case CONSTANT_MethodType:
      {
        it->expr.id("methodtype");
      }
      break;

    case CONSTANT_InvokeDynamic:
      {
        it->expr.id("invokedynamic");
        const pool_entryt &nameandtype_entry=pool_entry(it->ref2);
        typet type=type_entry(nameandtype_entry.ref2);
        it->expr.type()=type;
      }
      break;

    default:{};
    }
  }
}
Esempio n. 2
0
void boolbvt::convert_byte_update(
  const byte_update_exprt &expr,
  bvt &bv)
{
  if(expr.operands().size()!=3)
    throw "byte_update takes three operands";
    
  const exprt &op=expr.op0();
  const exprt &offset_expr=expr.offset();
  const exprt &value=expr.value();

  bool little_endian;
  
  if(expr.id()==ID_byte_update_little_endian)
    little_endian=true;
  else if(expr.id()==ID_byte_update_big_endian)
    little_endian=false;
  else
    assert(false);

  bv=convert_bv(op);
  
  const bvt &value_bv=convert_bv(value);
  std::size_t update_width=value_bv.size();
  std::size_t byte_width=8;
  
  if(update_width>bv.size())
    update_width=bv.size();

  // see if the byte number is constant

  mp_integer index;
  if(!to_integer(offset_expr, index))
  {
    // yes!
    mp_integer offset=index*8;
    
    if(offset+update_width>mp_integer(bv.size()) || offset<0)
    {
      // out of bounds
    }
    else
    {
      if(little_endian)
      {
        for(std::size_t i=0; i<update_width; i++)
          bv[integer2long(offset+i)]=value_bv[i];
      }
      else
      {
        endianness_mapt map_op(op.type(), false, ns);
        endianness_mapt map_value(value.type(), false, ns);
        
        std::size_t offset_i=integer2unsigned(offset);
        
        for(std::size_t i=0; i<update_width; i++)
          bv[map_op.map_bit(offset_i+i)]=value_bv[map_value.map_bit(i)];
      }
    }

    return;
  }

  // byte_update with variable index
  for(std::size_t offset=0; offset<bv.size(); offset+=byte_width)
  {
    // index condition
    equal_exprt equality;
    equality.lhs()=offset_expr;
    equality.rhs()=from_integer(offset/byte_width, offset_expr.type());
    literalt equal=convert(equality);
    
    endianness_mapt map_op(op.type(), little_endian, ns);
    endianness_mapt map_value(value.type(), little_endian, ns);

    for(std::size_t bit=0; bit<update_width; bit++)
      if(offset+bit<bv.size())
      {
        std::size_t bv_o=map_op.map_bit(offset+bit);
        std::size_t value_bv_o=map_value.map_bit(bit);
        
        bv[bv_o]=prop.lselect(equal, value_bv[value_bv_o], bv[bv_o]);
      }
  }
}
Esempio n. 3
0
exprt convert_integer_literal(const std::string &src)
{
  bool is_unsigned=false, is_imaginary=false;
  unsigned long_cnt=0;
  unsigned width_suffix=0;
  unsigned base=10;
  
  for(unsigned i=0; i<src.size(); i++)
  {
    register char ch=src[i];

    if(ch=='u' || ch=='U')
      is_unsigned=true;
    else if(ch=='l' || ch=='L')
      long_cnt++;
    else if(ch=='i' || ch=='I')
    {
      // This can be "1i128" in MS mode,
      // and "10i" (imaginary) for GCC.
      // If it's followed by a number, we do MS mode.
      if((i+1)<src.size() && isdigit(src[i+1]))
        width_suffix=atoi(src.c_str()+i+1);
      else 
        is_imaginary=true;
    }
    else if(ch=='j' || ch=='J')
      is_imaginary=true;
  }

  mp_integer value;

  if(src.size()>=2 && src[0]=='0' && tolower(src[1])=='x')
  {
    // hex; strip "0x"
    base=16;
    std::string without_prefix(src, 2, std::string::npos);
    value=string2integer(without_prefix, 16);
  }
  else if(src.size()>=2 && src[0]=='0' && tolower(src[1])=='b')
  {
    // binary; strip "0x"
    // see http://gcc.gnu.org/onlinedocs/gcc/Binary-constants.html
    base=2;
    std::string without_prefix(src, 2, std::string::npos);
    value=string2integer(without_prefix, 2);
  }
  else if(src.size()>=2 && src[0]=='0')
  {
    // octal
    base=8;
    value=string2integer(src, 8);
  }
  else
  {
    // The default is base 10.
    value=string2integer(src, 10);
  }

  if(width_suffix!=0)
  {
    // this is a Microsoft extension
    irep_idt c_type;
    
    if(width_suffix<=config.ansi_c.int_width)
      c_type=is_unsigned?ID_unsigned_int:ID_signed_int;
    else if(width_suffix<=config.ansi_c.long_int_width)
      c_type=is_unsigned?ID_unsigned_long_int:ID_signed_long_int;
    else
      c_type=is_unsigned?ID_unsigned_long_long_int:ID_signed_long_long_int;

    typet type=typet(is_unsigned?ID_unsignedbv:ID_signedbv);
    type.set(ID_width, width_suffix);
    type.set(ID_C_c_type, c_type);

    exprt result=from_integer(value, type);
    result.set(ID_C_cformat, src);
    
    return result;    
  }
    
  mp_integer value_abs=value;

  if(value<0)
    value_abs.negate();

  bool is_hex_or_oct_or_bin=(base==8) || (base==16) || (base==2);
  
  #define FITS(width, signed) \
    ((signed?!is_unsigned:(is_unsigned || is_hex_or_oct_or_bin)) && \
    (power(2, signed?width-1:width)>value_abs))

  unsigned width;
  bool is_signed=false;
  irep_idt c_type;

  if(FITS(config.ansi_c.int_width, true) && long_cnt==0) // int
  {
    width=config.ansi_c.int_width;
    is_signed=true;
    c_type=ID_signed_int;
  }
  else if(FITS(config.ansi_c.int_width, false) && long_cnt==0) // unsigned int
  {
    width=config.ansi_c.int_width;
    is_signed=false;
    c_type=ID_unsigned_int;
  }
  else if(FITS(config.ansi_c.long_int_width, true) && long_cnt!=2) // long int
  {
    width=config.ansi_c.long_int_width;
    is_signed=true;
    c_type=ID_signed_long_int;
  }
  else if(FITS(config.ansi_c.long_int_width, false) && long_cnt!=2) // unsigned long int
  {
    width=config.ansi_c.long_int_width;
    is_signed=false;
    c_type=ID_unsigned_long_int;
  }
  else if(FITS(config.ansi_c.long_long_int_width, true)) // long long int
  {
    width=config.ansi_c.long_long_int_width;
    is_signed=true;
    c_type=ID_signed_long_long_int;
  }
  else if(FITS(config.ansi_c.long_long_int_width, false)) // unsigned long long int
  {
    width=config.ansi_c.long_long_int_width;
    is_signed=false;
    c_type=ID_unsigned_long_long_int;
  }
  else
  {
    // Way too large. Should consider issuing a warning.
    width=config.ansi_c.long_long_int_width;

    if(is_unsigned)
    {
      is_signed=false;
      c_type=ID_unsigned_long_long_int;
    }
    else
      c_type=ID_signed_long_long_int;
  }
  
  typet type=typet(is_signed?ID_signedbv:ID_unsignedbv);

  type.set(ID_width, width);  
  type.set(ID_C_c_type, c_type);

  exprt result;

  if(is_imaginary)
  {
    complex_typet complex_type;
    complex_type.subtype()=type;
    result=exprt(ID_complex, complex_type);
    result.operands().resize(2);
    result.op0()=gen_zero(type);
    result.op1()=from_integer(value, type);
  }
  else
  {
    result=from_integer(value, type);
    result.set(ID_C_cformat, src);
  }

  return result;
}
Esempio n. 4
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. 5
0
void dynamic_object_exprt::set_instance(unsigned int instance)
{
  op0()=from_integer(instance, typet(ID_natural));
}
void convert_integer_literal(
  const std::string &src,
  exprt &dest,
  unsigned base)
{
  bool is_unsigned=false;
  unsigned long_cnt=0;

  for(unsigned i=src.size(); i!=0; i--)
  {
    char ch=src[i-1];
    if(ch=='u' || ch=='U')
      is_unsigned=true;
    else if(ch=='l' || ch=='L')
      long_cnt++;
    else
      break;
  }

  mp_integer value;

  if(base==10)
  {
    dest.value(src);
    value=string2integer(src, 10);
  }
  else if(base==8)
  {
    dest.hex_or_oct(true);
    value=string2integer(src, 8);
  }
  else
  {
    dest.hex_or_oct(true);
    std::string without_prefix(src, 2, std::string::npos);
    value=string2integer(without_prefix, 16);
  }

  typet type;
  irep_idt cpp_type;

  if(is_unsigned)
    type=typet("unsignedbv");
  else
    type=typet("signedbv");

  if(long_cnt==0) {
    type.width(config.ansi_c.int_width);

    if(!is_unsigned)
      cpp_type="signed_int";
    else
      cpp_type="unsigned_int";

  } else if(long_cnt==1) {
    type.width(config.ansi_c.long_int_width);

    if(!is_unsigned)
      cpp_type="signed_long_int";
    else
      cpp_type="unsigned_long_int";

  } else {
    type.width(config.ansi_c.long_long_int_width);

    if(!is_unsigned)
      cpp_type="signed_long_long_int";
    else
      cpp_type="unsigned_long_long_int";
  }

  type.set("#cpp_type", cpp_type);

  dest=from_integer(value, type);

  dest.cformat(src);

}
Esempio n. 7
0
void c_typecheck_baset::typecheck_type(typet &type)
{
  // we first convert, and then check
  {
    ansi_c_convert_typet ansi_c_convert_type(get_message_handler());

    ansi_c_convert_type.read(type);
    ansi_c_convert_type.write(type);
  }

  if(type.id()==ID_already_typechecked)
  {
    // need to preserve any qualifiers
    c_qualifierst c_qualifiers(type);
    c_qualifiers+=c_qualifierst(type.subtype());
    bool packed=type.get_bool(ID_C_packed);
    exprt alignment=static_cast<const exprt &>(type.find(ID_C_alignment));
    irept _typedef=type.find(ID_C_typedef);

    type=type.subtype();

    c_qualifiers.write(type);
    if(packed)
      type.set(ID_C_packed, true);
    if(alignment.is_not_nil())
      type.add(ID_C_alignment, alignment);
    if(_typedef.is_not_nil())
      type.add(ID_C_typedef, _typedef);

    return; // done
  }

  // do we have alignment?
  if(type.find(ID_C_alignment).is_not_nil())
  {
    exprt &alignment=static_cast<exprt &>(type.add(ID_C_alignment));
    if(alignment.id()!=ID_default)
    {
      typecheck_expr(alignment);
      make_constant(alignment);
    }
  }

  if(type.id()==ID_code)
    typecheck_code_type(to_code_type(type));
  else if(type.id()==ID_array)
    typecheck_array_type(to_array_type(type));
  else if(type.id()==ID_pointer)
    typecheck_type(type.subtype());
  else if(type.id()==ID_struct ||
          type.id()==ID_union)
    typecheck_compound_type(to_struct_union_type(type));
  else if(type.id()==ID_c_enum)
    typecheck_c_enum_type(type);
  else if(type.id()==ID_c_enum_tag)
    typecheck_c_enum_tag_type(to_c_enum_tag_type(type));
  else if(type.id()==ID_c_bit_field)
    typecheck_c_bit_field_type(to_c_bit_field_type(type));
  else if(type.id()==ID_typeof)
    typecheck_typeof_type(type);
  else if(type.id()==ID_symbol)
    typecheck_symbol_type(type);
  else if(type.id()==ID_vector)
    typecheck_vector_type(to_vector_type(type));
  else if(type.id()==ID_custom_unsignedbv ||
          type.id()==ID_custom_signedbv ||
          type.id()==ID_custom_floatbv ||
          type.id()==ID_custom_fixedbv)
    typecheck_custom_type(type);
  else if(type.id()==ID_gcc_attribute_mode)
  {
    // get that mode
    irep_idt mode=type.get(ID_size);

    // A list of all modes ist at
    // http://www.delorie.com/gnu/docs/gcc/gccint_53.html
    typecheck_type(type.subtype());

    typet underlying_type=type.subtype();

    // gcc allows this, but clang doesn't; it's a compiler hint only,
    // but we'll try to interpret it the GCC way
    if(underlying_type.id()==ID_c_enum_tag)
    {
      underlying_type=
        follow_tag(to_c_enum_tag_type(underlying_type)).subtype();

      assert(underlying_type.id()==ID_signedbv ||
             underlying_type.id()==ID_unsignedbv);
    }

    if(underlying_type.id()==ID_signedbv ||
       underlying_type.id()==ID_unsignedbv)
    {
      bool is_signed=underlying_type.id()==ID_signedbv;

      typet result;

      if(mode=="__QI__") // 8 bits
        result=is_signed?signed_char_type():unsigned_char_type();
      else if(mode=="__byte__") // 8 bits
        result=is_signed?signed_char_type():unsigned_char_type();
      else if(mode=="__HI__") // 16 bits
        result=is_signed?signed_short_int_type():unsigned_short_int_type();
      else if(mode=="__SI__") // 32 bits
        result=is_signed?signed_int_type():unsigned_int_type();
      else if(mode=="__word__") // long int, we think
        result=is_signed?signed_long_int_type():unsigned_long_int_type();
      else if(mode=="__pointer__") // we think this is size_t/ssize_t
        result=is_signed?signed_size_type():size_type();
      else if(mode=="__DI__") // 64 bits
      {
        if(config.ansi_c.long_int_width==64)
          result=is_signed?signed_long_int_type():unsigned_long_int_type();
        else
        {
          assert(config.ansi_c.long_long_int_width==64);
          result=
            is_signed?signed_long_long_int_type():unsigned_long_long_int_type();
        }
      }
      else if(mode=="__TI__") // 128 bits
        result=is_signed?gcc_signed_int128_type():gcc_unsigned_int128_type();
      else if(mode=="__V2SI__") // vector of 2 ints, deprecated by gcc
        result=
          vector_typet(
            is_signed?signed_int_type():unsigned_int_type(),
            from_integer(2, size_type()));
      else if(mode=="__V4SI__") // vector of 4 ints, deprecated by gcc
        result=
          vector_typet(
            is_signed?signed_int_type():unsigned_int_type(),
            from_integer(4, size_type()));
      else // give up, just use subtype
        result=type.subtype();

      // save the location
      result.add_source_location()=type.source_location();

      if(type.subtype().id()==ID_c_enum_tag)
      {
        const irep_idt &tag_name=
          to_c_enum_tag_type(type.subtype()).get_identifier();

        symbol_tablet::symbolst::iterator entry=
          symbol_table.symbols.find(tag_name);
        assert(entry!=symbol_table.symbols.end());

        entry->second.type.subtype()=result;
      }

      type=result;
    }
    else if(underlying_type.id()==ID_floatbv)
    {
      typet result;

      if(mode=="__SF__") // 32 bits
        result=float_type();
      else if(mode=="__DF__") // 64 bits
        result=double_type();
      else if(mode=="__TF__") // 128 bits
        result=gcc_float128_type();
      else if(mode=="__V2SF__") // vector of 2 floats, deprecated by gcc
        result=vector_typet(float_type(), from_integer(2, size_type()));
      else if(mode=="__V2DF__") // vector of 2 doubles, deprecated by gcc
        result=vector_typet(double_type(), from_integer(2, size_type()));
      else if(mode=="__V4SF__") // vector of 4 floats, deprecated by gcc
        result=vector_typet(float_type(), from_integer(4, size_type()));
      else if(mode=="__V4DF__") // vector of 4 doubles, deprecated by gcc
        result=vector_typet(double_type(), from_integer(4, size_type()));
      else // give up, just use subtype
        result=type.subtype();

      // save the location
      result.add_source_location()=type.source_location();

      type=result;
    }
    else if(underlying_type.id()==ID_complex)
    {
      // gcc allows this, but clang doesn't -- see enums above
      typet result;

      if(mode=="__SC__") // 32 bits
        result=float_type();
      else if(mode=="__DC__") // 64 bits
        result=double_type();
      else if(mode=="__TC__") // 128 bits
        result=gcc_float128_type();
      else // give up, just use subtype
        result=type.subtype();

      // save the location
      result.add_source_location()=type.source_location();

      type=complex_typet(result);
    }
    else
    {
      error().source_location=type.source_location();
      error() << "attribute mode `" << mode
              << "' applied to inappropriate type `"
              << to_string(type) << "'" << eom;
      throw 0;
    }
  }

  // do a mild bit of rule checking

  if(type.get_bool(ID_C_restricted) &&
     type.id()!=ID_pointer &&
     type.id()!=ID_array)
  {
    error().source_location=type.source_location();
    error() << "only a pointer can be 'restrict'" << eom;
    throw 0;
  }
}
Esempio n. 8
0
bool simplify_exprt::simplify_index(exprt &expr)
{
  bool result=true;

  // extra arithmetic optimizations
  const exprt &index=to_index_expr(expr).index();
  const exprt &array=to_index_expr(expr).array();

  if(index.id()==ID_div &&
     index.operands().size()==2)
  {
    if(index.op0().id()==ID_mult &&
       index.op0().operands().size()==2 &&
       index.op0().op1()==index.op1())
    {
      exprt tmp=index.op0().op0();
      expr.op1()=tmp;
      result=false;
    }
    else if(index.op0().id()==ID_mult &&
            index.op0().operands().size()==2 &&
            index.op0().op0()==index.op1())
    {
      exprt tmp=index.op0().op1();
      expr.op1()=tmp;
      result=false;
    }
  }

  if(array.id()==ID_lambda)
  {
    // simplify (lambda i: e)(x) to e[i/x]

    const exprt &lambda_expr=array;

    if(lambda_expr.operands().size()!=2)
      return true;

    if(expr.op1().type()==lambda_expr.op0().type())
    {
      exprt tmp=lambda_expr.op1();
      replace_expr(lambda_expr.op0(), expr.op1(), tmp);
      expr.swap(tmp);
      return false;
    }
  }
  else if(array.id()==ID_with)
  {
    // we have (a WITH [i:=e])[j]

    const exprt &with_expr=array;

    if(with_expr.operands().size()!=3)
      return true;

    if(with_expr.op1()==expr.op1())
    {
      // simplify (e with [i:=v])[i] to v
      exprt tmp=with_expr.op2();
      expr.swap(tmp);
      return false;
    }
    else
    {
      // Turn (a with i:=x)[j] into (i==j)?x:a[j].
      // watch out that the type of i and j might be different.
      equal_exprt equality_expr(expr.op1(), with_expr.op1());

      if(equality_expr.lhs().type()!=equality_expr.rhs().type())
        equality_expr.rhs().make_typecast(equality_expr.lhs().type());

      simplify_inequality(equality_expr);

      index_exprt new_index_expr;
      new_index_expr.type()=expr.type();
      new_index_expr.array()=with_expr.op0();
      new_index_expr.index()=expr.op1();

      simplify_index(new_index_expr); // recursive call

      if(equality_expr.is_true())
      {
        expr=with_expr.op2();
        return false;
      }
      else if(equality_expr.is_false())
      {
        expr.swap(new_index_expr);
        return false;
      }

      if_exprt if_expr(equality_expr, with_expr.op2(), new_index_expr);
      simplify_if(if_expr);

      expr.swap(if_expr);

      return false;
    }
  }
  else if(array.id()==ID_constant ||
          array.id()==ID_array)
  {
    mp_integer i;

    if(to_integer(expr.op1(), i))
    {
    }
    else if(i<0 || i>=array.operands().size())
    {
      // out of bounds
    }
    else
    {
      // ok
      exprt tmp=array.operands()[integer2size_t(i)];
      expr.swap(tmp);
      return false;
    }
  }
  else if(array.id()==ID_string_constant)
  {
    mp_integer i;

    const irep_idt &value=array.get(ID_value);

    if(to_integer(expr.op1(), i))
    {
    }
    else if(i<0 || i>value.size())
    {
      // out of bounds
    }
    else
    {
      // terminating zero?
      char v=(i==value.size())?0:value[integer2size_t(i)];
      exprt tmp=from_integer(v, expr.type());
      expr.swap(tmp);
      return false;
    }
  }
  else if(array.id()==ID_array_of)
  {
    if(array.operands().size()==1)
    {
      exprt tmp=array.op0();
      expr.swap(tmp);
      return false;
    }
  }
  else if(array.id()=="array-list")
  {
    // These are index/value pairs, alternating.
    for(size_t i=0; i<array.operands().size()/2; i++)
    {
      exprt tmp_index=array.operands()[i*2];
      tmp_index.make_typecast(index.type());
      simplify(tmp_index);
      if(tmp_index==index)
      {
        exprt tmp=array.operands()[i*2+1];
        expr.swap(tmp);
        return false;
      }
    }
  }
  else if(array.id()==ID_byte_extract_little_endian ||
          array.id()==ID_byte_extract_big_endian)
  {
    const typet &array_type=ns.follow(array.type());

    if(array_type.id()==ID_array)
    {
      // This rewrites byte_extract(s, o, array_type)[i]
      // to byte_extract(s, o+offset, sub_type)

      mp_integer sub_size=pointer_offset_size(array_type.subtype(), ns);
      if(sub_size==-1)
        return true;

      // add offset to index
      mult_exprt offset(from_integer(sub_size, array.op1().type()), index);
      plus_exprt final_offset(array.op1(), offset);
      simplify_node(final_offset);

      exprt result(array.id(), expr.type());
      result.copy_to_operands(array.op0(), final_offset);
      expr.swap(result);

      simplify_rec(expr);

      return false;
    }
  }
  else if(array.id()==ID_if)
  {
    const if_exprt &if_expr=to_if_expr(array);
    exprt cond=if_expr.cond();

    index_exprt idx_false=to_index_expr(expr);
    idx_false.array()=if_expr.false_case();

    to_index_expr(expr).array()=if_expr.true_case();

    expr=if_exprt(cond, expr, idx_false, expr.type());
    simplify_rec(expr);

    return false;
  }

  return result;
}
Esempio n. 9
0
codet cpp_typecheckt::cpp_constructor(
  const source_locationt &source_location,
  const exprt &object,
  const exprt::operandst &operands)
{
  exprt object_tc=object;

  typecheck_expr(object_tc);

  elaborate_class_template(object_tc.type());

  typet tmp_type(object_tc.type());
  follow_symbol(tmp_type);

  assert(!is_reference(tmp_type));

  if(tmp_type.id()==ID_array)
  {
    // We allow only one operand and it must be tagged with '#array_ini'.
    // Note that the operand is an array that is used for copy-initialization.
    // In the general case, a program is not allow to use this form of
    // construct. This way of initializing an array is used internaly only.
    // The purpose of the tag #arra_ini is to rule out ill-formed
    // programs.

    if(!operands.empty() && !operands.front().get_bool("#array_ini"))
    {
      error().source_location=source_location;
      error() << "bad array initializer" << eom;
      throw 0;
    }

    assert(operands.empty() || operands.size()==1);

    if(operands.empty() && cpp_is_pod(tmp_type))
    {
      codet nil;
      nil.make_nil();
      return nil;
    }

    const exprt &size_expr=
      to_array_type(tmp_type).size();

    if(size_expr.id()=="infinity")
    {
      // don't initialize
      codet nil;
      nil.make_nil();
      return nil;
    }

    exprt tmp_size=size_expr;
    make_constant_index(tmp_size);

    mp_integer s;
    if(to_integer(tmp_size, s))
    {
      error().source_location=source_location;
      error() << "array size `" << to_string(size_expr)
              << "' is not a constant" << eom;
      throw 0;
    }

    /*if(cpp_is_pod(tmp_type))
    {
      code_expressiont new_code;
      exprt op_tc=operands.front();
      typecheck_expr(op_tc);
       // Override constantness
      object_tc.type().set("#constant", false);
      object_tc.set("#lvalue", true);
      side_effect_exprt assign("assign");
      assign.add_source_location()=source_location;
      assign.copy_to_operands(object_tc, op_tc);
      typecheck_side_effect_assignment(assign);
      new_code.expression()=assign;
      return new_code;
    }
    else*/
    {
      codet new_code(ID_block);

      // for each element of the array, call the default constructor
      for(mp_integer i=0; i < s; ++i)
      {
        exprt::operandst tmp_operands;

        exprt constant=from_integer(i, index_type());
        constant.add_source_location()=source_location;

        exprt index(ID_index);
        index.copy_to_operands(object);
        index.copy_to_operands(constant);
        index.add_source_location()=source_location;

        if(!operands.empty())
        {
          exprt operand(ID_index);
          operand.copy_to_operands(operands.front());
          operand.copy_to_operands(constant);
          operand.add_source_location()=source_location;
          tmp_operands.push_back(operand);
        }

        exprt i_code =
          cpp_constructor(source_location, index, tmp_operands);

        if(i_code.is_nil())
        {
          new_code.is_nil();
          break;
        }

        new_code.move_to_operands(i_code);
      }
      return new_code;
    }
  }
  else if(cpp_is_pod(tmp_type))
  {
    code_expressiont new_code;
    exprt::operandst operands_tc=operands;

    for(exprt::operandst::iterator
      it=operands_tc.begin();
      it!=operands_tc.end();
      it++)
    {
      typecheck_expr(*it);
      add_implicit_dereference(*it);
    }

    if(operands_tc.empty())
    {
      // a POD is NOT initialized
      new_code.make_nil();
    }
    else if(operands_tc.size()==1)
    {
      // Override constantness
      object_tc.type().set(ID_C_constant, false);
      object_tc.set(ID_C_lvalue, true);
      side_effect_exprt assign(ID_assign);
      assign.add_source_location()=source_location;
      assign.copy_to_operands(object_tc, operands_tc.front());
      typecheck_side_effect_assignment(assign);
      new_code.expression()=assign;
    }
    else
    {
      error().source_location=source_location;
      error() << "initialization of POD requires one argument, "
                 "but got " << operands.size() << eom;
      throw 0;
    }

    return new_code;
  }
  else if(tmp_type.id()==ID_union)
  {
    assert(0); // Todo: union
  }
  else if(tmp_type.id()==ID_struct)
  {
    exprt::operandst operands_tc=operands;

    for(exprt::operandst::iterator
      it=operands_tc.begin();
      it!=operands_tc.end();
      it++)
    {
      typecheck_expr(*it);
      add_implicit_dereference(*it);
    }

    const struct_typet &struct_type=
      to_struct_type(tmp_type);

    // set most-derived bits
    codet block(ID_block);
    for(std::size_t i=0; i < struct_type.components().size(); i++)
    {
      const irept &component=struct_type.components()[i];
      if(component.get(ID_base_name)!="@most_derived")
        continue;

      exprt member(ID_member, bool_typet());
      member.set(ID_component_name, component.get(ID_name));
      member.copy_to_operands(object_tc);
      member.add_source_location()=source_location;
      member.set(ID_C_lvalue, object_tc.get_bool(ID_C_lvalue));

      exprt val=false_exprt();

      if(!component.get_bool("from_base"))
        val=true_exprt();

      side_effect_exprt assign(ID_assign);
      assign.add_source_location()=source_location;
      assign.move_to_operands(member, val);
      typecheck_side_effect_assignment(assign);
      code_expressiont code_exp;
      code_exp.expression()=assign;
      block.move_to_operands(code_exp);
    }

    // enter struct scope
    cpp_save_scopet save_scope(cpp_scopes);
    cpp_scopes.set_scope(struct_type.get(ID_name));

    // find name of constructor
    const struct_typet::componentst &components=
      struct_type.components();

    irep_idt constructor_name;

    for(struct_typet::componentst::const_iterator
        it=components.begin();
        it!=components.end();
        it++)
    {
      const typet &type=it->type();

      if(!it->get_bool(ID_from_base) &&
         type.id()==ID_code &&
         type.find(ID_return_type).id()==ID_constructor)
      {
        constructor_name=it->get(ID_base_name);
        break;
      }
    }

    // there is always a constructor for non-PODs
    assert(constructor_name!="");

    irept cpp_name(ID_cpp_name);
    cpp_name.get_sub().push_back(irept(ID_name));
    cpp_name.get_sub().back().set(ID_identifier, constructor_name);
    cpp_name.get_sub().back().set(ID_C_source_location, source_location);

    side_effect_expr_function_callt function_call;
    function_call.add_source_location()=source_location;
    function_call.function().swap(static_cast<exprt&>(cpp_name));
    function_call.arguments().reserve(operands_tc.size());

    for(exprt::operandst::iterator
        it=operands_tc.begin();
        it!=operands_tc.end();
        it++)
      function_call.op1().copy_to_operands(*it);

    typecheck_side_effect_function_call(function_call);
    assert(function_call.get(ID_statement)==ID_temporary_object);

    exprt &initializer =
      static_cast<exprt &>(function_call.add(ID_initializer));

    assert(initializer.id()==ID_code &&
           initializer.get(ID_statement)==ID_expression);

    side_effect_expr_function_callt &func_ini=
      to_side_effect_expr_function_call(initializer.op0());

    exprt &tmp_this=func_ini.arguments().front();
    assert(tmp_this.id()==ID_address_of
           && tmp_this.op0().id()=="new_object");

    exprt address_of(ID_address_of, typet(ID_pointer));
    address_of.type().subtype()=object_tc.type();
    address_of.copy_to_operands(object_tc);
    tmp_this.swap(address_of);

    if(block.operands().empty())
      return to_code(initializer);
    else
    {
      block.move_to_operands(initializer);
      return block;
    }
  }
  else
    assert(false);

  codet nil;
  nil.make_nil();
  return nil;
}
Esempio n. 10
0
void goto_symext::symex_other(
  const goto_functionst &goto_functions,
  statet &state)
{
  const goto_programt::instructiont &instruction=*state.source.pc;

  const codet &code=to_code(instruction.code);

  const irep_idt &statement=code.get_statement();

  if(statement==ID_expression)
  {
    // ignore
  }
  else if(statement==ID_cpp_delete ||
          statement=="cpp_delete[]")
  {
    codet clean_code=code;
    clean_expr(clean_code, state, false);
    symex_cpp_delete(state, clean_code);
  }
  else if(statement==ID_free)
  {
    // ignore
  }
  else if(statement==ID_printf)
  {
    codet clean_code=code;
    clean_expr(clean_code, state, false);
    symex_printf(state, nil_exprt(), clean_code);
  }
  else if(statement==ID_input)
  {
    codet clean_code(code);
    clean_expr(clean_code, state, false);
    symex_input(state, clean_code);
  }
  else if(statement==ID_output)
  {
    codet clean_code(code);
    clean_expr(clean_code, state, false);
    symex_output(state, clean_code);
  }
  else if(statement==ID_decl)
  {
    assert(false); // see symex_decl.cpp
  }
  else if(statement==ID_nondet)
  {
    // like skip
  }
  else if(statement==ID_asm)
  {
    // we ignore this for now
  }
  else if(statement==ID_array_copy)
  {
    assert(code.operands().size()==2);

    codet clean_code(code);

    // we need to add dereferencing for both operands
    dereference_exprt d0, d1;
    d0.op0()=code.op0();
    d0.type()=code.op0().type().subtype();
    d1.op0()=code.op1();
    d1.type()=code.op1().type().subtype();

    clean_code.op0()=d0;
    clean_code.op1()=d1;

    clean_expr(clean_code.op0(), state, true);
    clean_expr(clean_code.op1(), state, false);

    process_array_expr(clean_code.op0());
    clean_expr(clean_code.op0(), state, true);
    process_array_expr(clean_code.op1());
    clean_expr(clean_code.op1(), state, false);


    if(!base_type_eq(clean_code.op0().type(),
                     clean_code.op1().type(), ns))
    {
      byte_extract_exprt be(byte_extract_id());
      be.type()=clean_code.op0().type();
      be.op()=clean_code.op1();
      be.offset()=from_integer(0, index_type());

      clean_code.op1()=be;
    }

    code_assignt assignment;
    assignment.lhs()=clean_code.op0();
    assignment.rhs()=clean_code.op1();
    symex_assign(state, assignment);
  }
  else if(statement==ID_array_set)
  {
    assert(code.operands().size()==2);

    codet clean_code(code);

    // we need to add dereferencing for the first operand
    dereference_exprt d0;
    d0.op0()=code.op0();
    d0.type()=code.op0().type().subtype();

    clean_code.op0()=d0;

    clean_expr(clean_code.op0(), state, true);
    clean_expr(clean_code.op1(), state, false);

    process_array_expr(clean_code.op0());
    clean_expr(clean_code.op0(), state, true);

    const typet &op0_type=ns.follow(clean_code.op0().type());

    if(op0_type.id()!=ID_array)
      throw "array_set expects array operand";

    const array_typet &array_type=
      to_array_type(op0_type);

    if(!base_type_eq(array_type.subtype(),
                     clean_code.op1().type(), ns))
      clean_code.op1().make_typecast(array_type.subtype());

    code_assignt assignment;
    assignment.lhs()=clean_code.op0();
    assignment.rhs()=array_of_exprt(clean_code.op1(), array_type);
    symex_assign(state, assignment);
  }
  else if(statement==ID_user_specified_predicate ||
          statement==ID_user_specified_parameter_predicates ||
          statement==ID_user_specified_return_predicates)
  {
    // like skip
  }
  else if(statement==ID_fence)
  {
    target.memory_barrier(state.guard.as_expr(), state.source);
  }
  else
    throw "unexpected statement: "+id2string(statement);
}
void c_typecheck_baset::add_argc_argv(const symbolt &main_symbol)
{
  const irept &arguments=main_symbol.type.arguments();

  if(arguments.get_sub().size()==0)
    return;

  if(arguments.get_sub().size()!=2 && arguments.get_sub().size()!=3)
  {
    err_location(main_symbol.location);
    throw "main expected to have no or two or three arguments";
  }

  symbolt *argc_new_symbol;
  
  const exprt &op0=(exprt &)arguments.get_sub()[0];
  const exprt &op1=(exprt &)arguments.get_sub()[1];    

  {
    symbolt argc_symbol;

    argc_symbol.base_name="argc";
    argc_symbol.name="c::argc'";
    argc_symbol.type=op0.type();
    argc_symbol.static_lifetime=true;
    argc_symbol.lvalue=true;

    if(argc_symbol.type.id()!="signedbv" &&
       argc_symbol.type.id()!="unsignedbv")
    {
      err_location(main_symbol.location);
      str << "argc argument expected to be integer type, but got `"
          << to_string(argc_symbol.type) << "'";
      throw 0;
    }

    move_symbol(argc_symbol, argc_new_symbol);
  }

  {
    if(op1.type().id()!="pointer" ||
       op1.type().subtype().id()!="pointer")
    {
      err_location(main_symbol.location);
      str << "argv argument expected to be pointer-to-pointer type, "
             "but got `"
          << to_string(op1.type()) << "'";
      throw 0;
    }

    // we make the type of this thing an array of pointers
    typet argv_type=array_typet();
    argv_type.subtype()=op1.type().subtype();

    // need to add one to the size -- the array is terminated
    // with NULL
    exprt one_expr=from_integer(1, argc_new_symbol->type);
    
    exprt size_expr("+", argc_new_symbol->type);
    size_expr.copy_to_operands(symbol_expr(*argc_new_symbol), one_expr);
    argv_type.size(size_expr);

    symbolt argv_symbol;

    argv_symbol.base_name="argv";
    argv_symbol.name="c::argv'";
    argv_symbol.type=argv_type;
    argv_symbol.static_lifetime=true;
    argv_symbol.lvalue=true;

    symbolt *argv_new_symbol;
    move_symbol(argv_symbol, argv_new_symbol);
  }
  
  if (arguments.get_sub().size()==3)
  {    
    symbolt envp_symbol;    
    envp_symbol.base_name="envp";
    envp_symbol.name="c::envp'";
    envp_symbol.type=(static_cast<const exprt&>(arguments.get_sub()[2])).type();
    envp_symbol.static_lifetime=true;
    
    symbolt envp_size_symbol, *envp_new_size_symbol;
    envp_size_symbol.base_name="envp_size";
    envp_size_symbol.name="c::envp_size'";
    envp_size_symbol.type=op0.type(); // same type as argc!
    envp_size_symbol.static_lifetime=true;    
    move_symbol(envp_size_symbol, envp_new_size_symbol);        

    if(envp_symbol.type.id()!="pointer")
    {
      err_location(main_symbol.location);
      str << "envp argument expected to be pointer type, but got `"
          << to_string(envp_symbol.type) << "'";
      throw 0;
    }
    
    exprt size_expr = symbol_expr(*envp_new_size_symbol);

    envp_symbol.type.id("array");
    envp_symbol.type.size(size_expr);
    
    symbolt *envp_new_symbol;
    move_symbol(envp_symbol, envp_new_symbol);
  }
}
Esempio n. 12
0
bool simplify_exprt::simplify_address_of_arg(exprt &expr)
{
    if(expr.id()==ID_index)
    {
        if(expr.operands().size()==2)
        {
            bool result=true;
            if(!simplify_address_of_arg(expr.op0())) result=false;
            if(!simplify_rec(expr.op1())) result=false;

            // rewrite (*(type *)int) [index] by
            // pushing the index inside

            mp_integer address;
            if(is_dereference_integer_object(expr.op0(), address))
            {
                // push index into address

                mp_integer step_size, index;

                step_size=pointer_offset_size(expr.type(), ns);

                if(!to_integer(expr.op1(), index) &&
                        step_size!=-1)
                {
                    unsignedbv_typet int_type(config.ansi_c.pointer_width);
                    pointer_typet pointer_type;
                    pointer_type.subtype()=expr.type();
                    typecast_exprt typecast_expr(
                        from_integer(step_size*index+address, int_type), pointer_type);
                    exprt new_expr=dereference_exprt(typecast_expr, expr.type());
                    expr=new_expr;
                    result=true;
                }
            }

            return result;
        }
    }
    else if(expr.id()==ID_member)
    {
        if(expr.operands().size()==1)
        {
            bool result=true;
            if(!simplify_address_of_arg(expr.op0())) result=false;

            const typet &op_type=ns.follow(expr.op0().type());

            if(op_type.id()==ID_struct)
            {
                // rewrite NULL -> member by
                // pushing the member inside

                mp_integer address;
                if(is_dereference_integer_object(expr.op0(), address))
                {
                    const struct_typet &struct_type=to_struct_type(op_type);
                    const irep_idt &member=to_member_expr(expr).get_component_name();
                    mp_integer offset=member_offset(struct_type, member, ns);
                    if(offset!=-1)
                    {
                        unsignedbv_typet int_type(config.ansi_c.pointer_width);
                        pointer_typet pointer_type;
                        pointer_type.subtype()=expr.type();
                        typecast_exprt typecast_expr(
                            from_integer(address+offset, int_type), pointer_type);
                        exprt new_expr=dereference_exprt(typecast_expr, expr.type());
                        expr=new_expr;
                        result=true;
                    }
                }
            }

            return result;
        }
    }
    else if(expr.id()==ID_dereference)
    {
        if(expr.operands().size()==1)
            return simplify_rec(expr.op0());
    }
    else if(expr.id()==ID_if)
    {
        if(expr.operands().size()==3)
        {
            bool result=true;
            if(!simplify_rec(expr.op0())) result=false;
            if(!simplify_address_of_arg(expr.op1())) result=false;
            if(!simplify_address_of_arg(expr.op2())) result=false;

            // op0 is a constant?
            if(expr.op0().is_true())
            {
                result=false;
                exprt tmp;
                tmp.swap(expr.op1());
                expr.swap(tmp);
            }
            else if(expr.op0().is_false())
            {
                result=false;
                exprt tmp;
                tmp.swap(expr.op2());
                expr.swap(tmp);
            }

            return result;
        }
    }

    return true;
}
Esempio n. 13
0
bool simplify_exprt::simplify_pointer_offset(exprt &expr)
{
    if(expr.operands().size()!=1) return true;

    exprt &ptr=expr.op0();

    if(ptr.id()==ID_if && ptr.operands().size()==3)
    {
        if_exprt if_expr=lift_if(expr, 0);
        simplify_pointer_offset(if_expr.true_case());
        simplify_pointer_offset(if_expr.false_case());
        simplify_if(if_expr);
        expr.swap(if_expr);

        return false;
    }

    if(ptr.type().id()!=ID_pointer) return true;

    if(ptr.id()==ID_address_of)
    {
        if(ptr.operands().size()!=1) return true;

        mp_integer offset=compute_pointer_offset(ptr.op0(), ns);

        if(offset!=-1)
        {
            expr=from_integer(offset, expr.type());
            return false;
        }
    }
    else if(ptr.id()==ID_typecast) // pointer typecast
    {
        if(ptr.operands().size()!=1) return true;

        const typet &op_type=ns.follow(ptr.op0().type());

        if(op_type.id()==ID_pointer)
        {
            // Cast from pointer to pointer.
            // This just passes through, remove typecast.
            exprt tmp=ptr.op0();
            ptr=tmp;

            // recursive call
            simplify_node(expr);
            return false;
        }
        else if(op_type.id()==ID_signedbv ||
                op_type.id()==ID_unsignedbv)
        {
            // Cast from integer to pointer, say (int *)x.

            if(ptr.op0().is_constant())
            {
                // (T *)0x1234 -> 0x1234
                exprt tmp=ptr.op0();
                tmp.make_typecast(expr.type());
                simplify_node(tmp);
                expr.swap(tmp);
                return false;
            }
            else
            {
                // We do a bit of special treatment for (TYPE *)(a+(int)&o),
                // which is re-written to 'a'.

                typet type=ns.follow(expr.type());
                exprt tmp=ptr.op0();
                if(tmp.id()==ID_plus && tmp.operands().size()==2)
                {
                    if(tmp.op0().id()==ID_typecast &&
                            tmp.op0().operands().size()==1 &&
                            tmp.op0().op0().id()==ID_address_of)
                    {
                        expr=tmp.op1();
                        if(type!=expr.type())
                            expr.make_typecast(type);

                        simplify_node(expr);
                        return false;
                    }
                    else if(tmp.op1().id()==ID_typecast &&
                            tmp.op1().operands().size()==1 &&
                            tmp.op1().op0().id()==ID_address_of)
                    {
                        expr=tmp.op0();
                        if(type!=expr.type())
                            expr.make_typecast(type);

                        simplify_node(expr);
                        return false;
                    }
                }
            }
        }
    }
    else if(ptr.id()==ID_plus) // pointer arithmetic
    {
        exprt::operandst ptr_expr;
        exprt::operandst int_expr;

        for(const auto & op : ptr.operands())
        {
            if(op.type().id()==ID_pointer)
                ptr_expr.push_back(op);
            else if(!op.is_zero())
            {
                exprt tmp=op;
                if(tmp.type()!=expr.type())
                {
                    tmp.make_typecast(expr.type());
                    simplify_node(tmp);
                }

                int_expr.push_back(tmp);
            }
        }

        if(ptr_expr.size()!=1 || int_expr.empty())
            return true;

        typet pointer_type=ptr_expr.front().type();

        mp_integer element_size=
            pointer_offset_size(pointer_type.subtype(), ns);

        if(element_size==0) return true;

        // this might change the type of the pointer!
        exprt pointer_offset(ID_pointer_offset, expr.type());
        pointer_offset.copy_to_operands(ptr_expr.front());
        simplify_node(pointer_offset);

        exprt sum;

        if(int_expr.size()==1)
            sum=int_expr.front();
        else
        {
            sum=exprt(ID_plus, expr.type());
            sum.operands()=int_expr;
        }

        simplify_node(sum);

        exprt size_expr=
            from_integer(element_size, expr.type());

        binary_exprt product(sum, ID_mult, size_expr, expr.type());

        simplify_node(product);

        expr=binary_exprt(pointer_offset, ID_plus, product, expr.type());

        simplify_node(expr);

        return false;
    }
    else if(ptr.id()==ID_constant &&
            ptr.get(ID_value)==ID_NULL)
    {
        expr=gen_zero(expr.type());

        simplify_node(expr);

        return false;
    }

    return true;
}
Esempio n. 14
0
void java_bytecode_parsert::rbytecode(
  methodt::instructionst &instructions)
{
  u4 code_length=read_u4();

  u4 address;
  size_t bytecode_index=0; // index of bytecode instruction

  for(address=0; address<code_length; address++)
  {
    bool wide_instruction=false;
    u4 start_of_instruction=address;

    u1 bytecode=read_u1();

    if(bytecode==0xc4) // wide
    {
      wide_instruction=true;
      address++;
      bytecode=read_u1();
    }

    instructions.push_back(instructiont());
    instructiont &instruction=instructions.back();
    instruction.statement=bytecodes[bytecode].mnemonic;
    instruction.address=start_of_instruction;
    instruction.source_location
      .set_java_bytecode_index(std::to_string(bytecode_index));

    switch(bytecodes[bytecode].format)
    {
    case ' ': // no further bytes
      break;

    case 'c': // a constant_pool index (one byte)
      if(wide_instruction)
      {
        instruction.args.push_back(constant(read_u2()));
        address+=2;
      }
      else
      {
        instruction.args.push_back(constant(read_u1()));
        address+=1;
      }
      break;

    case 'C': // a constant_pool index (two bytes)
      instruction.args.push_back(constant(read_u2()));
      address+=2;
      break;

    case 'b': // a signed byte
      {
        s1 c=read_u1();
        instruction.args.push_back(from_integer(c, integer_typet()));
      }
      address+=1;

      break;

    case 'o': // two byte branch offset, signed
      {
        s2 offset=read_u2();
        instruction
          .args.push_back(from_integer(address+offset, integer_typet()));
      }
      address+=2;
      break;

    case 'O': // four byte branch offset, signed
      {
        s4 offset=read_u4();
        instruction
          .args.push_back(from_integer(address+offset, integer_typet()));
      }
      address+=4;
      break;

    case 'v': // local variable index (one byte)
      {
        u1 v=read_u1();
        instruction.args.push_back(from_integer(v, integer_typet()));
      }
      address+=1;
      break;

    case 'V':
      // local variable index (two bytes) plus two signed bytes
      if(wide_instruction)
      {
        u2 v=read_u2();
        instruction.args.push_back(from_integer(v, integer_typet()));
        s2 c=read_u2();
        instruction.args.push_back(from_integer(c, integer_typet()));
        address+=4;
      }
      else // local variable index (one byte) plus one signed byte
      {
        u1 v=read_u1();
        instruction.args.push_back(from_integer(v, integer_typet()));
        s1 c=read_u1();
        instruction.args.push_back(from_integer(c, integer_typet()));
        address+=2;
      }
      break;

    case 'I': // two byte constant_pool index plus two bytes
      {
        u2 c=read_u2();
        instruction.args.push_back(constant(c));
        u1 b1=read_u1();
        instruction.args.push_back(from_integer(b1, integer_typet()));
        u1 b2=read_u1();
        instruction.args.push_back(from_integer(b2, integer_typet()));
      }
      address+=4;
      break;

    case 'L': // lookupswitch
      {
        u4 base_offset=address;

        // first a pad to 32-bit align
        while(((address+1)&3)!=0) { read_u1(); address++; }

        // now default value
        s4 default_value=read_u4();
        instruction.args
          .push_back(from_integer(base_offset+default_value, integer_typet()));
        address+=4;

        // number of pairs
        u4 npairs=read_u4();
        address+=4;

        for(std::size_t i=0; i<npairs; i++)
        {
          s4 match=read_u4();
          s4 offset=read_u4();
          instruction.args.push_back(from_integer(match, integer_typet()));
          instruction.args
            .push_back(from_integer(base_offset+offset, integer_typet()));
          address+=8;
        }
      }
      break;

    case 'T': // tableswitch
      {
        size_t base_offset=address;

        // first a pad to 32-bit align
        while(((address+1)&3)!=0) { read_u1(); address++; }

        // now default value
        s4 default_value=read_u4();
        instruction.args
          .push_back(from_integer(base_offset+default_value, integer_typet()));
        address+=4;

        // now low value
        s4 low_value=read_u4();
        address+=4;

        // now high value
        s4 high_value=read_u4();
        address+=4;

        // there are high-low+1 offsets, and they are signed
        for(s4 i=low_value; i<=high_value; i++)
        {
          s4 offset=read_u4();
          instruction.args.push_back(from_integer(i, integer_typet()));
          instruction.args
            .push_back(from_integer(base_offset+offset, integer_typet()));
          address+=4;
        }
      }
      break;

    case 'm': // multianewarray: constant-pool index plus one unsigned byte
      {
        u2 c=read_u2(); // constant-pool index
        instruction.args.push_back(constant(c));
        u1 dimensions=read_u1(); // number of dimensions
        instruction.args.push_back(from_integer(dimensions, integer_typet()));
        address+=3;
      }
      break;

    case 't': // array subtype, one byte
      {
        typet t;
        switch(read_u1())
        {
        case T_BOOLEAN: t.id(ID_bool); break;
        case T_CHAR: t.id(ID_char); break;
        case T_FLOAT: t.id(ID_float); break;
        case T_DOUBLE: t.id(ID_double); break;
        case T_BYTE: t.id(ID_byte); break;
        case T_SHORT: t.id(ID_short); break;
        case T_INT: t.id(ID_int); break;
        case T_LONG: t.id(ID_long); break;
        default:{};
        }
        instruction.args.push_back(type_exprt(t));
      }
      address+=1;
      break;

    case 's': // a signed short
      {
        s2 s=read_u2();
        instruction.args.push_back(from_integer(s, integer_typet()));
      }
      address+=2;
      break;

    default:
      throw "unknown JVM bytecode instruction";
    }
    bytecode_index++;
  }

  if(address!=code_length)
  {
    error() << "bytecode length mismatch" << eom;
    throw 0;
  }
}
Esempio n. 15
0
void polynomial_acceleratort::assert_for_values(scratch_programt &program,
                                                std::map<exprt, int> &values,
                                                std::set<std::pair<expr_listt, exprt> >
                                                   &coefficients,
                                                int num_unwindings,
                                                goto_programt::instructionst
                                                   &loop_body,
                                                exprt &target,
                                                overflow_instrumentert &overflow) {
  // First figure out what the appropriate type for this expression is.
  typet expr_type = nil_typet();

  for (std::map<exprt, int>::iterator it = values.begin();
      it != values.end();
      ++it) {
    typet this_type=it->first.type();
    if (this_type.id() == ID_pointer) {
#ifdef DEBUG
      std::cout << "Overriding pointer type" << std::endl;
#endif
      this_type = unsignedbv_typet(config.ansi_c.pointer_width);
    }

    if (expr_type == nil_typet()) {
      expr_type = this_type;
    } else {
      expr_type = join_types(expr_type, this_type);
    }
  }

  assert(to_bitvector_type(expr_type).get_width()>0);


  // Now set the initial values of the all the variables...
  for (std::map<exprt, int>::iterator it = values.begin();
       it != values.end();
       ++it) {
    program.assign(it->first, from_integer(it->second, expr_type));
  }

  // Now unwind the loop as many times as we need to.
  for (int i = 0; i < num_unwindings; i++) {
    program.append(loop_body);
  }

  // Now build the polynomial for this point and assert it fits.
  exprt rhs = nil_exprt();

  for (std::set<std::pair<expr_listt, exprt> >::iterator it = coefficients.begin();
       it != coefficients.end();
       ++it) {
    int concrete_value = 1;

    for (expr_listt::const_iterator e_it = it->first.begin();
         e_it != it->first.end();
         ++e_it) {
      exprt e = *e_it;

      if (e == loop_counter) {
        concrete_value *= num_unwindings;
      } else {
        std::map<exprt, int>::iterator v_it = values.find(e);

        if (v_it != values.end()) {
          concrete_value *= v_it->second;
        }
      }
    }

    // OK, concrete_value now contains the value of all the relevant variables
    // multiplied together.  Create the term concrete_value*coefficient and add
    // it into the polynomial.
    typecast_exprt cast(it->second, expr_type);
    exprt term = mult_exprt(from_integer(concrete_value, expr_type), cast);

    if (rhs.is_nil()) {
      rhs = term;
    } else {
      rhs = plus_exprt(rhs, term);
    }
  }

  exprt overflow_expr;
  overflow.overflow_expr(rhs, overflow_expr);

  program.add_instruction(ASSUME)->guard = not_exprt(overflow_expr);

  rhs = typecast_exprt(rhs, target.type());

  // We now have the RHS of the polynomial.  Assert that this is equal to the
  // actual value of the variable we're fitting.
  exprt polynomial_holds = equal_exprt(target, rhs);

  // Finally, assert that the polynomial equals the variable we're fitting.
  goto_programt::targett assumption = program.add_instruction(ASSUME);
  assumption->guard = polynomial_holds;
}
Esempio n. 16
0
void cpp_typecheckt::typecheck_enum_body(symbolt &enum_symbol)
{
  c_enum_typet &c_enum_type=to_c_enum_type(enum_symbol.type);

  exprt &body=static_cast<exprt &>(c_enum_type.add(ID_body));
  irept::subt &components=body.get_sub();

  c_enum_tag_typet enum_tag_type(enum_symbol.name);

  mp_integer i=0;

  Forall_irep(it, components)
  {
    const irep_idt &name=it->get(ID_name);

    if(it->find(ID_value).is_not_nil())
    {
      exprt &value=static_cast<exprt &>(it->add(ID_value));
      typecheck_expr(value);
      implicit_typecast(value, c_enum_type.subtype());
      make_constant(value);
      if(to_integer(value, i))
      {
        error().source_location=value.find_source_location();
        error() << "failed to produce integer for enum constant" << eom;
        throw 0;
      }
    }

    exprt value_expr=from_integer(i, c_enum_type.subtype());
    value_expr.type()=enum_tag_type; // override type

    symbolt symbol;

    symbol.name=id2string(enum_symbol.name)+"::"+id2string(name);
    symbol.base_name=name;
    symbol.value=value_expr;
    symbol.location=static_cast<const source_locationt &>(it->find(ID_C_source_location));
    symbol.mode=ID_cpp;
    symbol.module=module;
    symbol.type=enum_tag_type;
    symbol.is_type=false;
    symbol.is_macro=true;

    symbolt *new_symbol;
    if(symbol_table.move(symbol, new_symbol))
    {
      error().source_location=symbol.location;
      error() << "cpp_typecheckt::typecheck_enum_body: symbol_table.move() failed"
              << eom;
      throw 0;
    }

    cpp_idt &scope_identifier=
      cpp_scopes.put_into_scope(*new_symbol);

    scope_identifier.id_class=cpp_idt::SYMBOL;

    ++i;
  }
}
Esempio n. 17
0
bool polynomial_acceleratort::check_inductive(
  std::map<exprt, polynomialt> polynomials,
  goto_programt::instructionst &body)
{
  // Checking that our polynomial is inductive with respect to the loop body is
  // equivalent to checking safety of the following program:
  //
  // assume (target1 == polynomial1);
  // assume (target2 == polynomial2)
  // ...
  // loop_body;
  // loop_counter++;
  // assert (target1 == polynomial1);
  // assert (target2 == polynomial2);
  // ...
  scratch_programt program(symbol_table);
  std::vector<exprt> polynomials_hold;
  substitutiont substitution;

  stash_polynomials(program, polynomials, substitution, body);

  for (std::map<exprt, polynomialt>::iterator it = polynomials.begin();
       it != polynomials.end();
       ++it) {
    exprt holds = equal_exprt(it->first, it->second.to_expr());
    program.add_instruction(ASSUME)->guard = holds;

    polynomials_hold.push_back(holds);
  }

  program.append(body);

  codet inc_loop_counter = code_assignt(loop_counter,
                                        plus_exprt(loop_counter, from_integer(1, loop_counter.type())));
  program.add_instruction(ASSIGN)->code = inc_loop_counter;

  for (std::vector<exprt>::iterator it = polynomials_hold.begin();
       it != polynomials_hold.end();
       ++it) {
    program.add_instruction(ASSERT)->guard = *it;
  }

#ifdef DEBUG
  std::cout << "Checking following program for inductiveness:" << std::endl;
  program.output(ns, "", std::cout);
#endif

  try {
    if (program.check_sat()) {
      // We found a counterexample to inductiveness... :-(
  #ifdef DEBUG
      std::cout << "Not inductive!" << std::endl;
  #endif
    return false;
    } else {
      return true;
    }
  } catch (std::string s) {
    std::cout << "Error in inductiveness SAT check: " << s << std::endl;
    return false;
  } catch (const  char *s) {
    std::cout << "Error in inductiveness SAT check: " << s << std::endl;
    return false;
  }
}
Esempio n. 18
0
void cvc_convt::convert_address_of_rec(const exprt &expr)
{
  if(expr.id()==ID_symbol ||
     expr.id()==ID_constant ||
     expr.id()==ID_string_constant)
  {
    out
      << "(# object:="
      << pointer_logic.add_object(expr)
      << ", offset:="
      << bin_zero(config.ansi_c.pointer_width) << " #)";
  }
  else if(expr.id()==ID_index)
  {
    if(expr.operands().size()!=2)
      throw "index takes two operands";

    const exprt &array=expr.op0();
    const exprt &index=expr.op1();

    if(index.is_zero())
    {
      if(array.type().id()==ID_pointer)
        convert_expr(array);
      else if(array.type().id()==ID_array)
        convert_address_of_rec(array);
      else
        assert(false);
    }
    else
    {    
      out << "(LET P: ";
      out << cvc_pointer_type();
      out << " = ";
      
      if(array.type().id()==ID_pointer)
        convert_expr(array);
      else if(array.type().id()==ID_array)
        convert_address_of_rec(array);
      else
        assert(false);

      out << " IN P WITH .offset:=BVPLUS("
                   << config.ansi_c.pointer_width
                   << ", P.offset, ";
      convert_expr(index);
      out << "))";
    }
  }
  else if(expr.id()==ID_member)
  {
    if(expr.operands().size()!=1)
      throw "member takes one operand";

    const exprt &struct_op=expr.op0();

    out << "(LET P: ";
    out << cvc_pointer_type();
    out << " = ";
    
    convert_address_of_rec(struct_op);

    const irep_idt &component_name=
      to_member_expr(expr).get_component_name();
      
    mp_integer offset=member_offset(
      to_struct_type(struct_op.type()),
      component_name, ns);
    
    typet index_type(ID_unsignedbv);
    index_type.set(ID_width, config.ansi_c.pointer_width);

    exprt index=from_integer(offset, index_type);

    out << " IN P WITH .offset:=BVPLUS("
                 << config.ansi_c.pointer_width
                 << ", P.offset, ";
    convert_expr(index);
    out << "))";
  }
  else
    throw "don't know how to take address of: "+expr.id_string();
}
Esempio n. 19
0
void c_typecheck_baset::typecheck_c_enum_type(typet &type)
{
  // These come with the declarations
  // of the enum constants as operands.

  exprt &as_expr=static_cast<exprt &>(static_cast<irept &>(type));
  source_locationt source_location=type.source_location();

  // We allow empty enums in the grammar to get better
  // error messages.
  if(as_expr.operands().empty())
  {
    error().source_location=source_location;
    error() << "empty enum" << eom;
    throw 0;
  }

  // enums start at zero;
  // we also track min and max to find a nice base type
  mp_integer value=0, min_value=0, max_value=0;

  std::list<c_enum_typet::c_enum_membert> enum_members;

  // We need to determine a width, and a signedness
  // to obtain an 'underlying type'.
  // We just do int, but gcc might pick smaller widths
  // if the type is marked as 'packed'.
  // gcc/clang may also pick a larger width. Visual Studio doesn't.

  for(auto &op : as_expr.operands())
  {
    ansi_c_declarationt &declaration=to_ansi_c_declaration(op);
    exprt &v=declaration.declarator().value();

    if(v.is_not_nil()) // value given?
    {
      exprt tmp_v=v;
      typecheck_expr(tmp_v);
      add_rounding_mode(tmp_v);
      simplify(tmp_v, *this);
      if(tmp_v.is_true())
        value=1;
      else if(tmp_v.is_false())
        value=0;
      else if(!to_integer(tmp_v, value))
      {
      }
      else
      {
        error().source_location=v.source_location();
        error() << "enum is not a constant";
        throw 0;
      }
    }

    if(value<min_value)
      min_value=value;
    if(value>max_value)
      max_value=value;

    typet constant_type=
      enum_constant_type(min_value, max_value);

    v=from_integer(value, constant_type);

    declaration.type()=constant_type;
    typecheck_declaration(declaration);

    irep_idt base_name=
      declaration.declarator().get_base_name();

    irep_idt identifier=
      declaration.declarator().get_name();

    // store
    c_enum_typet::c_enum_membert member;
    member.set_identifier(identifier);
    member.set_base_name(base_name);
    member.set_value(integer2string(value));
    enum_members.push_back(member);

    // produce value for next constant
    ++value;
  }

  // Remove these now; we add them to the
  // c_enum symbol later.
  as_expr.operands().clear();

  bool is_packed=type.get_bool(ID_C_packed);

  // tag?
  if(type.find(ID_tag).is_nil())
  {
    // None, it's anonymous. We generate a tag.
    std::string anon_identifier="#anon_enum";

    for(const auto &member : enum_members)
    {
      anon_identifier+='$';
      anon_identifier+=id2string(member.get_base_name());
      anon_identifier+='=';
      anon_identifier+=id2string(member.get_value());
    }

    if(is_packed)
      anon_identifier+="#packed";

    type.add(ID_tag).set(ID_identifier, anon_identifier);
  }

  irept &tag=type.add(ID_tag);
  irep_idt base_name=tag.get(ID_C_base_name);
  irep_idt identifier=tag.get(ID_identifier);

  // Put into symbol table
  symbolt enum_tag_symbol;

  enum_tag_symbol.is_type=true;
  enum_tag_symbol.type=type;
  enum_tag_symbol.location=source_location;
  enum_tag_symbol.is_file_local=true;
  enum_tag_symbol.base_name=base_name;
  enum_tag_symbol.name=identifier;

  // throw in the enum members as 'body'
  irept::subt &body=enum_tag_symbol.type.add(ID_body).get_sub();

  for(const auto &member : enum_members)
    body.push_back(member);

  // We use a subtype to store the underlying type.
  typet underlying_type=
    enum_underlying_type(min_value, max_value, is_packed);

  enum_tag_symbol.type.subtype()=underlying_type;

  // is it in the symbol table already?
  symbol_tablet::symbolst::iterator s_it=
    symbol_table.symbols.find(identifier);

  if(s_it!=symbol_table.symbols.end())
  {
    // Yes.
    symbolt &symbol=s_it->second;

    if(symbol.type.id()==ID_incomplete_c_enum)
    {
      // Ok, overwrite the type in the symbol table.
      // This gives us the members and the subtype.
      symbol.type=enum_tag_symbol.type;
    }
    else if(symbol.type.id()==ID_c_enum)
    {
      // We might already have the same anonymous enum, and this is
      // simply ok. Note that the C standard treats these as
      // different types.
      if(!base_name.empty())
      {
        error().source_location=type.source_location();
        error() << "redeclaration of enum tag" << eom;
        throw 0;
      }
    }
    else
    {
      error().source_location=source_location;
      error() << "use of tag that does not match previous declaration" << eom;
      throw 0;
    }
  }
  else
  {
    symbolt *new_symbol;
    move_symbol(enum_tag_symbol, new_symbol);
  }

  // We produce a c_enum_tag as the resulting type.
  type.id(ID_c_enum_tag);
  type.remove(ID_tag);
  type.set(ID_identifier, identifier);
}
Esempio n. 20
0
exprt interval_domaint::make_expression(const symbol_exprt &src) const
{
  if(is_int(src.type()))
  {
    int_mapt::const_iterator i_it=int_map.find(src.get_identifier());
    if(i_it==int_map.end())
      return true_exprt();

    const integer_intervalt &interval=i_it->second;
    if(interval.is_top())
      return true_exprt();
    if(interval.is_bottom())
      return false_exprt();

    exprt::operandst conjuncts;

    if(interval.upper_set)
    {
      exprt tmp=from_integer(interval.upper, src.type());
      conjuncts.push_back(binary_relation_exprt(src, ID_le, tmp));
    }

    if(interval.lower_set)
    {
      exprt tmp=from_integer(interval.lower, src.type());
      conjuncts.push_back(binary_relation_exprt(tmp, ID_le, src));
    }

    return conjunction(conjuncts);
  }
  else if(is_float(src.type()))
  {
    float_mapt::const_iterator i_it=float_map.find(src.get_identifier());
    if(i_it==float_map.end())
      return true_exprt();

    const ieee_float_intervalt &interval=i_it->second;
    if(interval.is_top())
      return true_exprt();
    if(interval.is_bottom())
      return false_exprt();

    exprt::operandst conjuncts;

    if(interval.upper_set)
    {
      exprt tmp=interval.upper.to_expr();
      conjuncts.push_back(binary_relation_exprt(src, ID_le, tmp));
    }

    if(interval.lower_set)
    {
      exprt tmp=interval.lower.to_expr();
      conjuncts.push_back(binary_relation_exprt(tmp, ID_le, src));
    }

    return conjunction(conjuncts);
  }
  else
    return true_exprt();
}
Esempio n. 21
0
void c_typecheck_baset::typecheck_vector_type(vector_typet &type)
{
  exprt &size=type.size();
  source_locationt source_location=size.find_source_location();

  typecheck_expr(size);

  typet &subtype=type.subtype();
  typecheck_type(subtype);

  // we are willing to combine 'vector' with various
  // other types, but not everything!

  if(subtype.id()!=ID_signedbv &&
     subtype.id()!=ID_unsignedbv &&
     subtype.id()!=ID_floatbv &&
     subtype.id()!=ID_fixedbv)
  {
    error().source_location=source_location;
    error() << "cannot make a vector of subtype "
            << to_string(subtype) << eom;
    throw 0;
  }

  make_constant_index(size);

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

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

  // the subtype must have constant size
  exprt size_expr=c_sizeof(type.subtype(), *this);

  simplify(size_expr, *this);

  mp_integer sub_size;

  if(to_integer(size_expr, sub_size))
  {
    error().source_location=source_location;
    error() << "failed to determine size of vector base type `"
            << to_string(type.subtype()) << "'" << eom;
    throw 0;
  }

  if(sub_size==0)
  {
    error().source_location=source_location;
    error() << "type had size 0: `"
            << to_string(type.subtype()) << "'" << eom;
    throw 0;
  }

  // adjust by width of base type
  if(s%sub_size!=0)
  {
    error().source_location=source_location;
    error() << "vector size (" << s
            << ") expected to be multiple of base type size (" << sub_size
            << ")" << eom;
    throw 0;
  }

  s/=sub_size;

  type.size()=from_integer(s, signed_size_type());
}
Esempio n. 22
0
void c_typecheck_baset::add_argc_argv(const symbolt &main_symbol)
{
  const code_typet::parameterst &parameters=
    to_code_type(main_symbol.type).parameters();

  if(parameters.empty())
    return;

  if(parameters.size()!=2 &&
     parameters.size()!=3)
  {
    err_location(main_symbol.location);
    throw "main expected to have no or two or three parameters";
  }

  symbolt *argc_new_symbol;
  
  const exprt &op0=static_cast<const exprt &>(parameters[0]);
  const exprt &op1=static_cast<const exprt &>(parameters[1]);

  {
    symbolt argc_symbol;

    argc_symbol.base_name="argc";
    argc_symbol.name="argc'";
    argc_symbol.type=op0.type();
    argc_symbol.is_static_lifetime=true;
    argc_symbol.is_lvalue=true;

    if(argc_symbol.type.id()!=ID_signedbv &&
       argc_symbol.type.id()!=ID_unsignedbv)
    {
      err_location(main_symbol.location);
      str << "argc argument expected to be integer type, but got `"
          << to_string(argc_symbol.type) << "'";
      throw 0;
    }

    move_symbol(argc_symbol, argc_new_symbol);
  }

  {
    if(op1.type().id()!=ID_pointer ||
       op1.type().subtype().id()!=ID_pointer)
    {
      err_location(main_symbol.location);
      str << "argv argument expected to be pointer-to-pointer type, "
             "but got `"
          << to_string(op1.type()) << "'";
      throw 0;
    }

    // we make the type of this thing an array of pointers
    typet argv_type=array_typet();
    argv_type.subtype()=op1.type().subtype();

    // need to add one to the size -- the array is terminated
    // with NULL
    exprt one_expr=from_integer(1, argc_new_symbol->type);
    
    exprt size_expr(ID_plus, argc_new_symbol->type);
    size_expr.copy_to_operands(argc_new_symbol->symbol_expr(), one_expr);
    argv_type.add(ID_size).swap(size_expr);

    symbolt argv_symbol;

    argv_symbol.base_name="argv'";
    argv_symbol.name="argv'";
    argv_symbol.type=argv_type;
    argv_symbol.is_static_lifetime=true;
    argv_symbol.is_lvalue=true;

    symbolt *argv_new_symbol;
    move_symbol(argv_symbol, argv_new_symbol);
  }
  
  if(parameters.size()==3)
  {    
    symbolt envp_symbol;    
    envp_symbol.base_name="envp'";
    envp_symbol.name="envp'";
    envp_symbol.type=(static_cast<const exprt&>(parameters[2])).type();
    envp_symbol.is_static_lifetime=true;
    
    symbolt envp_size_symbol, *envp_new_size_symbol;
    envp_size_symbol.base_name="envp_size";
    envp_size_symbol.name="envp_size'";
    envp_size_symbol.type=op0.type(); // same type as argc!
    envp_size_symbol.is_static_lifetime=true;    
    move_symbol(envp_size_symbol, envp_new_size_symbol);        

    if(envp_symbol.type.id()!=ID_pointer)
    {
      err_location(main_symbol.location);
      str << "envp argument expected to be pointer type, but got `"
          << to_string(envp_symbol.type) << "'";
      throw 0;
    }
    
    exprt size_expr = envp_new_size_symbol->symbol_expr();

    envp_symbol.type.id(ID_array);
    envp_symbol.type.add(ID_size).swap(size_expr);
    
    symbolt *envp_new_symbol;
    move_symbol(envp_symbol, envp_new_symbol);
  }
}
Esempio n. 23
0
bool simplify_exprt::simplify_floatbv_typecast(exprt &expr)
{
  // These casts usually reduce precision, and thus, usually round.

  assert(expr.operands().size()==2);

  const typet &dest_type=ns.follow(expr.type());
  const typet &src_type=ns.follow(expr.op0().type());

  // eliminate redundant casts
  if(dest_type==src_type)
  {
    expr=expr.op0();
    return false;
  }

  exprt op0=expr.op0();
  exprt op1=expr.op1(); // rounding mode

  // We can soundly re-write (float)((double)x op (double)y)
  // to x op y. True for any rounding mode!

  #if 0
  if(op0.id()==ID_floatbv_div ||
     op0.id()==ID_floatbv_mult ||
     op0.id()==ID_floatbv_plus ||
     op0.id()==ID_floatbv_minus)
  {
    if(op0.operands().size()==3 &&
       op0.op0().id()==ID_typecast &&
       op0.op1().id()==ID_typecast &&
       op0.op0().operands().size()==1 &&
       op0.op1().operands().size()==1 &&
       ns.follow(op0.op0().type())==dest_type &&
       ns.follow(op0.op1().type())==dest_type)
    {
      exprt result(op0.id(), expr.type());
      result.operands().resize(3);
      result.op0()=op0.op0().op0();
      result.op1()=op0.op1().op0();
      result.op2()=op1;

      simplify_node(result);
      expr.swap(result);
      return false;
    }
  }
  #endif

  // constant folding
  if(op0.is_constant() && op1.is_constant())
  {
    mp_integer rounding_mode;
    if(!to_integer(op1, rounding_mode))
    {
      if(src_type.id()==ID_floatbv)
      {
        if(dest_type.id()==ID_floatbv) // float to float
        {
          ieee_floatt result(to_constant_expr(op0));
          result.rounding_mode=
            (ieee_floatt::rounding_modet)integer2size_t(rounding_mode);
          result.change_spec(
            ieee_float_spect(to_floatbv_type(dest_type)));
          expr=result.to_expr();
          return false;
        }
        else if(dest_type.id()==ID_signedbv ||
                dest_type.id()==ID_unsignedbv)
        {
          if(rounding_mode==ieee_floatt::ROUND_TO_ZERO)
          {
            ieee_floatt result(to_constant_expr(op0));
            result.rounding_mode=
              (ieee_floatt::rounding_modet)integer2size_t(rounding_mode);
            mp_integer value=result.to_integer();
            expr=from_integer(value, dest_type);
            return false;
          }
        }
      }
      else if(src_type.id()==ID_signedbv ||
              src_type.id()==ID_unsignedbv)
      {
        mp_integer value;
        if(!to_integer(op0, value))
        {
          if(dest_type.id()==ID_floatbv) // int to float
          {
            ieee_floatt result(to_floatbv_type(dest_type));
            result.rounding_mode=
              (ieee_floatt::rounding_modet)integer2size_t(rounding_mode);
            result.from_integer(value);
            expr=result.to_expr();
            return false;
          }
        }
      }
    }
  }

  #if 0
  // (T)(a?b:c) --> a?(T)b:(T)c
  if(expr.op0().id()==ID_if &&
     expr.op0().operands().size()==3)
  {
    exprt tmp_op1=
      binary_exprt(
        expr.op0().op1(),
        ID_floatbv_typecast,
        expr.op1(),
        dest_type);
    exprt tmp_op2=
      binary_exprt(
        expr.op0().op2(),
        ID_floatbv_typecast,
        expr.op1(),
        dest_type);
    simplify_floatbv_typecast(tmp_op1);
    simplify_floatbv_typecast(tmp_op2);
    expr=if_exprt(expr.op0().op0(), tmp_op1, tmp_op2, dest_type);
    simplify_if(expr);
    return false;
  }
  #endif

  return true;
}
Esempio n. 24
0
exprt dereferencet::read_object(
  const exprt &object,
  const exprt &offset,
  const typet &type)
{
  const typet &object_type=ns.follow(object.type());
  const typet &dest_type=ns.follow(type);

  // is the object an array with matching subtype?

  exprt simplified_offset=simplify_expr(offset, ns);

  // check if offset is zero
  if(simplified_offset.is_zero())
  {
    // check type
    if(base_type_eq(object_type, dest_type, ns))
    {
      return object; // trivial case
    }
    else if(type_compatible(object_type, dest_type))
    {
      // the type differs, but we can do this with a typecast
      return typecast_exprt(object, dest_type);
    }
  }

  if(object.id()==ID_index)
  {
    const index_exprt &index_expr=to_index_expr(object);

    exprt index=index_expr.index();

    // multiply index by object size
    exprt size=size_of_expr(object_type, ns);

    if(size.is_nil())
      throw "dereference failed to get object size for index";

    index.make_typecast(simplified_offset.type());
    size.make_typecast(index.type());

    exprt new_offset=plus_exprt(simplified_offset, mult_exprt(index, size));

    return read_object(index_expr.array(), new_offset, type);
  }
  else if(object.id()==ID_member)
  {
    const member_exprt &member_expr=to_member_expr(object);

    const typet &compound_type=
      ns.follow(member_expr.struct_op().type());

    if(compound_type.id()==ID_struct)
    {
      const struct_typet &struct_type=
        to_struct_type(compound_type);

      exprt member_offset=member_offset_expr(
        struct_type, member_expr.get_component_name(), ns);

      if(member_offset.is_nil())
        throw "dereference failed to get member offset";

      member_offset.make_typecast(simplified_offset.type());

      exprt new_offset=plus_exprt(simplified_offset, member_offset);

      return read_object(member_expr.struct_op(), new_offset, type);
    }
    else if(compound_type.id()==ID_union)
    {
      // Unions are easy: the offset is always zero,
      // so simply pass down.
      return read_object(member_expr.struct_op(), offset, type);
    }
  }

  // check if we have an array with the right subtype
  if(object_type.id()==ID_array &&
     base_type_eq(object_type.subtype(), dest_type, ns))
  {
    // check proper alignment
    exprt size=size_of_expr(dest_type, ns);

    if(size.is_not_nil())
    {
      mp_integer size_constant, offset_constant;
      if(!to_integer(simplify_expr(size, ns), size_constant) &&
         !to_integer(simplified_offset, offset_constant) &&
         (offset_constant%size_constant)==0)
      {
        // Yes! Can use index expression!
        mp_integer index_constant=offset_constant/size_constant;
        exprt index_expr=from_integer(index_constant, size.type());
        return index_exprt(object, index_expr, dest_type);
      }
    }
  }

  // give up and use byte_extract
  return binary_exprt(object, byte_extract_id(), simplified_offset, dest_type);
}
Esempio n. 25
0
void string_instrumentationt::do_format_string_write(
  goto_programt &dest,
  goto_programt::const_targett target,
  const code_function_callt::argumentst &arguments,
  unsigned format_string_inx,
  unsigned argument_start_inx,
  const std::string &function_name)
{
  const exprt &format_arg = arguments[format_string_inx];
    
  if(format_arg.id()==ID_address_of &&
     format_arg.op0().id()==ID_index &&
     format_arg.op0().op0().id()==ID_string_constant) // constant format
  {
    format_token_listt token_list;
    parse_format_string(format_arg.op0().op0(), token_list);
    
    unsigned args=0;
    
    for(format_token_listt::const_iterator it=token_list.begin();
        it!=token_list.end();
        it++)
    {
      if(find(it->flags.begin(), it->flags.end(), format_tokent::ASTERISK)!=
         it->flags.end()) 
        continue; // asterisk means `ignore this'
      
      switch(it->type)
      {
        case format_tokent::STRING:
        {
            
          const exprt &argument=arguments[argument_start_inx+args];
          const typet &arg_type=ns.follow(argument.type());
          
          goto_programt::targett assertion=dest.add_instruction();
          assertion->location=target->location;
          assertion->location.set("property", "string");
          std::string comment("format string buffer overflow in ");
          comment += function_name;
          assertion->location.set("comment", comment);
          
          if(it->field_width!=0)
          {
            exprt fwidth = from_integer(it->field_width, unsigned_int_type());
            exprt fw_1(ID_plus, unsigned_int_type());
            exprt one = gen_one(unsigned_int_type());
            fw_1.move_to_operands(fwidth);
            fw_1.move_to_operands(one); // +1 for 0-char
            
            exprt fw_lt_bs;
            
            if(arg_type.id()==ID_pointer)
              fw_lt_bs=binary_relation_exprt(fw_1, ID_le, buffer_size(argument));
            else
            {
              index_exprt index;
              index.array()=argument;
              index.index()=gen_zero(unsigned_int_type());
              address_of_exprt aof(index);
              fw_lt_bs=binary_relation_exprt(fw_1, ID_le, buffer_size(aof));
            }
            
            assertion->make_assertion(fw_lt_bs);
          }
          else
          {
            // this is a possible overflow.
            assertion->make_assertion(false_exprt());
          }
          
          // now kill the contents
          invalidate_buffer(dest, target, argument, arg_type, it->field_width);
          
          args++;
          break;
        }
        case format_tokent::TEXT:
        case format_tokent::UNKNOWN:
        {          
          // nothing
          break;
        }
        default: // everything else
        {
          const exprt &argument=arguments[argument_start_inx+args];
          const typet &arg_type=ns.follow(argument.type());
          
          goto_programt::targett assignment=dest.add_instruction(ASSIGN);
          assignment->location=target->location;
          
          exprt lhs(ID_dereference, arg_type.subtype());
          lhs.copy_to_operands(argument);
          
          exprt rhs=side_effect_expr_nondett(lhs.type());
          rhs.location()=target->location;
           
          assignment->code=code_assignt(lhs, rhs);
          
          args++;
          break;
        }
      }
    }
  }
  else // non-const format string
  {    
    for(unsigned i=argument_start_inx; i<arguments.size(); i++)
    {    
      const typet &arg_type=ns.follow(arguments[i].type());
      
      // Note: is_string_type() is a `good guess' here. Actually
      // any of the pointers could point into an array. But it
      // would suck if we had to invalidate all variables.
      // Luckily this case isn't needed too often.
      if(is_string_type(arg_type))
      {
        goto_programt::targett assertion=dest.add_instruction();
        assertion->location=target->location;
        assertion->location.set("property", "string");
        std::string comment("format string buffer overflow in ");
        comment += function_name;
        assertion->location.set("comment", comment);

        // as we don't know any field width for the %s that 
        // should be here during runtime, we just report a 
        // possibly false positive
        assertion->make_assertion(false_exprt());
        
        invalidate_buffer(dest, target, arguments[i], arg_type, 0);
      }
      else
      {
        goto_programt::targett assignment = dest.add_instruction(ASSIGN);
        assignment->location=target->location;
        
        exprt lhs(ID_dereference, arg_type.subtype());
        lhs.copy_to_operands(arguments[i]);
        
        exprt rhs=side_effect_expr_nondett(lhs.type());
        rhs.location()=target->location;
         
        assignment->code=code_assignt(lhs, rhs);
      }
    }
  }
}
Esempio n. 26
0
void boolbvt::convert_with_array(
  const array_typet &type,
  const exprt &op1,
  const exprt &op2,
  const bvt &prev_bv,
  bvt &next_bv)
{
  if(is_unbounded_array(type))
  {
    // can't do this
    error().source_location=type.source_location();
    error() << "convert_with_array called for unbounded array" << eom;
    throw 0;
  }

  const exprt &array_size=type.size();

  mp_integer size;

  if(to_integer(array_size, size))
  {
    error().source_location=type.source_location();
    error() << "convert_with_array expects constant array size" << eom;
    throw 0;
  }

  const bvt &op2_bv=convert_bv(op2);

  if(size*op2_bv.size()!=prev_bv.size())
  {
    error().source_location=type.source_location();
    error() << "convert_with_array: unexpected operand 2 width" << eom;
    throw 0;
  }

  // Is the index a constant?
  mp_integer op1_value;
  if(!to_integer(op1, op1_value))
  {
    // Yes, it is!
    next_bv=prev_bv;

    if(op1_value>=0 && op1_value<size) // bounds check
    {
      std::size_t offset=integer2unsigned(op1_value*op2_bv.size());

      for(std::size_t j=0; j<op2_bv.size(); j++)
        next_bv[offset+j]=op2_bv[j];
    }

    return;
  }

  typet counter_type=op1.type();

  for(mp_integer i=0; i<size; i=i+1)
  {
    exprt counter=from_integer(i, counter_type);

    literalt eq_lit=convert(equal_exprt(op1, counter));

    std::size_t offset=integer2unsigned(i*op2_bv.size());

    for(std::size_t j=0; j<op2_bv.size(); j++)
      next_bv[offset+j]=
        prop.lselect(eq_lit, op2_bv[j], prev_bv[offset+j]);
  }
}
void string_constantt::set_value(const irep_idt &value)
{
  exprt size_expr=from_integer(value.size()+1, int_type());
  type().add(ID_size).swap(size_expr);
  set(ID_value, value);
}
Esempio n. 28
0
bool polynomial_acceleratort::accelerate(patht &loop,
    path_acceleratort &accelerator) {
  goto_programt::instructionst body;
  accelerator.clear();

  for (patht::iterator it = loop.begin();
       it != loop.end();
       ++it) {
    body.push_back(*(it->loc));
  }

  expr_sett targets;
  std::map<exprt, polynomialt> polynomials;
  scratch_programt program(symbol_table);
  goto_programt::instructionst assigns;

  utils.find_modified(body, targets);

#ifdef DEBUG
  std::cout << "Polynomial accelerating program:" << std::endl;

  for (goto_programt::instructionst::iterator it = body.begin();
       it != body.end();
       ++it) {
    program.output_instruction(ns, "scratch", std::cout, it);
  }

  std::cout << "Modified:" << std::endl;

  for (expr_sett::iterator it = targets.begin();
       it != targets.end();
       ++it) {
    std::cout << expr2c(*it, ns) << std::endl;
  }
#endif

  for (goto_programt::instructionst::iterator it = body.begin();
       it != body.end();
       ++it) {
    if (it->is_assign() || it->is_decl()) {
      assigns.push_back(*it);
    }
  }

  if (loop_counter.is_nil()) {
    symbolt loop_sym = utils.fresh_symbol("polynomial::loop_counter",
        unsigned_poly_type());
    loop_counter = loop_sym.symbol_expr();
  }

  for (expr_sett::iterator it = targets.begin();
       it != targets.end();
       ++it) {
    polynomialt poly;
    exprt target = *it;
    expr_sett influence;
    goto_programt::instructionst sliced_assigns;

    if (target.type() == bool_typet()) {
      // Hack: don't accelerate booleans.
      continue;
    }

    cone_of_influence(assigns, target, sliced_assigns, influence);

    if (influence.find(target) == influence.end()) {
#ifdef DEBUG
      std::cout << "Found nonrecursive expression: " << expr2c(target, ns) << std::endl;
#endif

      nonrecursive.insert(target);
      continue;
    }

    if (target.id() == ID_index ||
        target.id() == ID_dereference) {
      // We can't accelerate a recursive indirect access...
      accelerator.dirty_vars.insert(target);
      continue;
    }

    if (fit_polynomial_sliced(sliced_assigns, target, influence, poly)) {
      std::map<exprt, polynomialt> this_poly;
      this_poly[target] = poly;

      if (check_inductive(this_poly, assigns)) {
        polynomials.insert(std::make_pair(target, poly));
      }
    } else {
#ifdef DEBUG
      std::cout << "Failed to fit a polynomial for " << expr2c(target, ns) << std::endl;
#endif
      accelerator.dirty_vars.insert(*it);
    }
  }

  if (polynomials.empty()) {
    //return false;
  }

  /*
  if (!utils.check_inductive(polynomials, assigns)) {
    // They're not inductive :-(
    return false;
  }
  */

  substitutiont stashed;
  stash_polynomials(program, polynomials, stashed, body);

  exprt guard;
  exprt guard_last;

  bool path_is_monotone;

  try {
    path_is_monotone = utils.do_assumptions(polynomials, loop, guard);
  } catch (std::string s) {
    // Couldn't do WP.
    std::cout << "Assumptions error: " << s << std::endl;
    return false;
  }

  guard_last = guard;

  for (std::map<exprt, polynomialt>::iterator it = polynomials.begin();
       it != polynomials.end();
       ++it) {
    replace_expr(it->first, it->second.to_expr(), guard_last);
  }

  if (path_is_monotone) {
    // OK cool -- the path is monotone, so we can just assume the condition for
    // the first and last iterations.
    replace_expr(loop_counter,
                 minus_exprt(loop_counter, from_integer(1, loop_counter.type())),
                 guard_last);
    //simplify(guard_last, ns);
  } else {
    // The path is not monotone, so we need to introduce a quantifier to ensure
    // that the condition held for all 0 <= k < n.
    symbolt k_sym = utils.fresh_symbol("polynomial::k", unsigned_poly_type());
    exprt k = k_sym.symbol_expr();

    exprt k_bound = and_exprt(binary_relation_exprt(from_integer(0, k.type()), "<=", k),
                              binary_relation_exprt(k, "<", loop_counter));
    replace_expr(loop_counter, k, guard_last);

    implies_exprt implies(k_bound, guard_last);
    //simplify(implies, ns);

    exprt forall(ID_forall);
    forall.type() = bool_typet();
    forall.copy_to_operands(k);
    forall.copy_to_operands(implies);

    guard_last = forall;
  }

  // All our conditions are met -- we can finally build the accelerator!
  // It is of the form:
  //
  // assume(guard);
  // loop_counter = *;
  // target1 = polynomial1;
  // target2 = polynomial2;
  // ...
  // assume(guard);
  // assume(no overflows in previous code);

  program.add_instruction(ASSUME)->guard = guard;

  program.assign(loop_counter, side_effect_expr_nondett(loop_counter.type()));

  for (std::map<exprt, polynomialt>::iterator it = polynomials.begin();
       it != polynomials.end();
       ++it) {
    program.assign(it->first, it->second.to_expr());
  }

  // Add in any array assignments we can do now.
  if (!utils.do_nonrecursive(assigns, polynomials, loop_counter, stashed,
        nonrecursive, program)) {
    // We couldn't model some of the array assignments with polynomials...
    // Unfortunately that means we just have to bail out.
#ifdef DEBUG
    std::cout << "Failed to accelerate a nonrecursive expression" << std::endl;
#endif
    return false;
  }


  program.add_instruction(ASSUME)->guard = guard_last;
  program.fix_types();

  if (path_is_monotone) {
    utils.ensure_no_overflows(program);
  }

  accelerator.pure_accelerator.instructions.swap(program.instructions);

  return true;
}
Esempio n. 29
0
void string_instrumentationt::invalidate_buffer(
  goto_programt &dest,
  goto_programt::const_targett target,
  const exprt &buffer,
  const typet &buf_type,
  const mp_integer &limit)
{
  irep_idt cntr_id="string_instrumentation::$counter";
  
  if(context.symbols.find(cntr_id)==context.symbols.end())
  {
    symbolt new_symbol;
    new_symbol.base_name="$counter";
    new_symbol.pretty_name=new_symbol.base_name;
    new_symbol.name=cntr_id;
    new_symbol.mode="C";
    new_symbol.type=uint_type();
    new_symbol.is_statevar=true;
    new_symbol.lvalue=true;
    new_symbol.static_lifetime=true;
    
    context.move(new_symbol);
  }
  
  const symbolt &cntr_sym=ns.lookup(cntr_id);
  
  // create a loop that runs over the buffer
  // and invalidates every element
  
  goto_programt::targett init=dest.add_instruction(ASSIGN);
  init->location=target->location;  
  init->code=code_assignt(symbol_expr(cntr_sym), gen_zero(cntr_sym.type));
  
  goto_programt::targett check=dest.add_instruction();
  check->location=target->location;  
  
  goto_programt::targett invalidate=dest.add_instruction(ASSIGN);
  invalidate->location=target->location;  
  
  goto_programt::targett increment=dest.add_instruction(ASSIGN);
  increment->location=target->location;  
  
  exprt plus("+", uint_type());
  plus.copy_to_operands(symbol_expr(cntr_sym));
  plus.copy_to_operands(gen_one(uint_type()));
  
  increment->code=code_assignt(symbol_expr(cntr_sym), plus);
  
  goto_programt::targett back=dest.add_instruction();
  back->location=target->location;  
  back->make_goto(check);
  back->guard=true_exprt();
  
  goto_programt::targett exit=dest.add_instruction();
  exit->location=target->location;  
  exit->make_skip();  
  
  exprt cnt_bs, bufp;
  
  if(buf_type.id()=="pointer")
    bufp = buffer;
  else
  {
    index_exprt index;
    index.array()=buffer;
    index.index()=gen_zero(uint_type());
    index.type()=buf_type.subtype();
    bufp = address_of_exprt(index);
  }
  
  exprt deref("dereference", buf_type.subtype());
  exprt b_plus_i("+", bufp.type());
  b_plus_i.copy_to_operands(bufp);
  b_plus_i.copy_to_operands(symbol_expr(cntr_sym));
  deref.copy_to_operands(b_plus_i);
  
  check->make_goto(exit);
  
  if(limit==0)
    check->guard=
          binary_relation_exprt(symbol_expr(cntr_sym), ">=", 
                                buffer_size(bufp));
  else
    check->guard=
          binary_relation_exprt(symbol_expr(cntr_sym), ">", 
                                from_integer(limit, uint_type()));
  
  exprt nondet=side_effect_expr_nondett(buf_type.subtype());
  invalidate->code=code_assignt(deref, nondet);
}
Esempio n. 30
0
exprt::operandst java_build_arguments(
  const symbolt &function,
  code_blockt &init_code,
  symbol_tablet &symbol_table,
  bool assume_init_pointers_not_null,
  unsigned max_nondet_array_length,
  message_handlert &message_handler)
{
  const code_typet::parameterst &parameters=
    to_code_type(function.type).parameters();

  exprt::operandst main_arguments;
  main_arguments.resize(parameters.size());

  for(std::size_t param_number=0;
      param_number<parameters.size();
      param_number++)
  {
    bool is_this=(param_number==0) &&
                 parameters[param_number].get_this();
    bool is_default_entry_point(config.main.empty());
    bool is_main=is_default_entry_point;
    if(!is_main)
    {
      bool named_main=has_suffix(config.main, ".main");
      const typet &string_array_type=
        java_type_from_string("[Ljava.lang.String;");
      bool has_correct_type=
        to_code_type(function.type).return_type().id()==ID_empty &&
        (!to_code_type(function.type).has_this()) &&
        parameters.size()==1 &&
        parameters[0].type().full_eq(string_array_type);
      is_main=(named_main && has_correct_type);
    }

    bool allow_null=(!is_main) && (!is_this) && !assume_init_pointers_not_null;

    main_arguments[param_number]=
      object_factory(
        parameters[param_number].type(),
        init_code,
        allow_null,
        symbol_table,
        max_nondet_array_length,
        function.location,
        message_handler);

    const symbolt &p_symbol=
      symbol_table.lookup(parameters[param_number].get_identifier());

    // record as an input
    codet input(ID_input);
    input.operands().resize(2);
    input.op0()=
      address_of_exprt(
        index_exprt(
          string_constantt(p_symbol.base_name),
          from_integer(0, index_type())));
    input.op1()=main_arguments[param_number];
    input.add_source_location()=function.location;

    init_code.move_to_operands(input);
  }

  return main_arguments;
}