Exemplo n.º 1
0
void java_record_outputs(
  const symbolt &function,
  const exprt::operandst &main_arguments,
  code_blockt &init_code,
  symbol_tablet &symbol_table)
{
  const code_typet::parameterst &parameters=
    to_code_type(function.type).parameters();

  exprt::operandst result;
  result.reserve(parameters.size()+1);

  bool has_return_value=
    to_code_type(function.type).return_type()!=empty_typet();

  if(has_return_value)
  {
    // record return value
    codet output(ID_output);
    output.operands().resize(2);

    const symbolt &return_symbol=symbol_table.lookup("return'");

    output.op0()=
      address_of_exprt(
        index_exprt(
          string_constantt(return_symbol.base_name),
          from_integer(0, index_type())));
    output.op1()=return_symbol.symbol_expr();
    output.add_source_location()=function.location;

    init_code.move_to_operands(output);
  }

  for(std::size_t param_number=0;
      param_number<parameters.size();
      param_number++)
  {
    const symbolt &p_symbol=
      symbol_table.lookup(parameters[param_number].get_identifier());

    if(p_symbol.type.id()==ID_pointer)
    {
      // record as an output
      codet output(ID_output);
      output.operands().resize(2);
      output.op0()=
        address_of_exprt(
          index_exprt(
            string_constantt(p_symbol.base_name),
            from_integer(0, index_type())));
      output.op1()=main_arguments[param_number];
      output.add_source_location()=function.location;

      init_code.move_to_operands(output);
    }
  }
}
Exemplo n.º 2
0
 T* alloc() {
   // I need to atomically advance freelisthead to the freelist[head]
   queue_ref_type oldhead;
   queue_ref_type newhead;
   do {
     oldhead.combined = freelisthead.combined;
     if (oldhead.q.val == index_type(-1)) return new T; // ran out of pool elements
     newhead.q.val = freelist[oldhead.q.val];
     newhead.q.counter = oldhead.q.counter + 1;
   } while(!atomic_compare_and_swap(freelisthead.combined, 
                                    oldhead.combined, 
                                    newhead.combined));
   freelist[oldhead.q.val] = index_type(-1);
   return &(data[oldhead.q.val]);
 }
Exemplo n.º 3
0
    void free(T* p) {
      // is this from the pool?
      // if it is below the pointer limits
      if (__unlikely__(p < lower_ptrlimit || p > upper_ptrlimit)) {
        delete p;
        return;
      }
    
      index_type cur = index_type(p - &(data[0]));

      // prepare for free list insertion
      // I need to atomically set freelisthead == cur
      // and freelist[cur] = freelisthead
      queue_ref_type oldhead;
      queue_ref_type newhead;
      do{
        oldhead.combined = freelisthead.combined;
        freelist[cur] = oldhead.q.val;
        newhead.q.val = cur;
        newhead.q.counter = oldhead.q.counter + 1;
        // now try to atomically move freelisthead
      } while(!atomic_compare_and_swap(freelisthead.combined, 
                                       oldhead.combined, 
                                       newhead.combined));
    }
            enumerator(succinct::bit_vector const& bv, uint64_t offset,
                       uint64_t universe, uint64_t n,
                       global_parameters const& params)
            {
                auto sparams = strict_params(params);

                if (all_ones_sequence::bitsize(params, universe, n) == 0) {
                    m_type = all_ones;
                } else {
                    m_type = index_type(bv.get_word56(offset)
                                        & ((uint64_t(1) << type_bits) - 1));
                }

                switch (m_type) {
                case elias_fano:
                    m_ef_enumerator = strict_elias_fano::enumerator(bv, offset + type_bits,
                                                                    universe, n,
                                                                    sparams);
                    break;
                case ranked_bitvector:
                    m_rb_enumerator = compact_ranked_bitvector::enumerator(bv, offset + type_bits,
                                                                           universe, n,
                                                                           sparams);
                    break;
                case all_ones:
                    m_ao_enumerator = all_ones_sequence::enumerator(bv, offset + type_bits,
                                                                    universe, n,
                                                                    sparams);
                    break;
                default:
                    throw std::invalid_argument("Unsupported type");
                }
            }
Exemplo n.º 5
0
void pool::deallocate(index_type index)
{
	if (!owns(index))
		throw allocate_error(allocate_errc::invalid_ptr);
	*(index_type*)pointer(index) = index_type(head_);
	head_ = index;
	nfree_++;
}
Exemplo n.º 6
0
code_function_callt function_to_call(
  symbol_tablet &symbol_table,
  const irep_idt &id,
  const irep_idt &argument)
{
  // already there?

  symbol_tablet::symbolst::const_iterator s_it=
    symbol_table.symbols.find(id);

  if(s_it==symbol_table.symbols.end())
  {
    // not there
    pointer_typet p(char_type());
    p.subtype().set(ID_C_constant, true);

    code_typet function_type;
    function_type.return_type()=empty_typet();
    function_type.parameters().push_back(
      code_typet::parametert(p));

    symbolt new_symbol;
    new_symbol.name=id;
    new_symbol.base_name=id;
    new_symbol.type=function_type;

    symbol_table.move(new_symbol);

    s_it=symbol_table.symbols.find(id);
    assert(s_it!=symbol_table.symbols.end());
  }

  // signature is expected to be
  // (type *) -> ...
  if(s_it->second.type.id()!=ID_code ||
     to_code_type(s_it->second.type).parameters().size()!=1 ||
     to_code_type(s_it->second.type).parameters()[0].type().id()!=ID_pointer)
  {
    std::string error="function `"+id2string(id)+"' has wrong signature";
    throw error;
  }

  string_constantt function_id_string(argument);

  code_function_callt call;
  call.lhs().make_nil();
  call.function()=
    symbol_exprt(s_it->second.name, s_it->second.type);
  call.arguments().resize(1);
  call.arguments()[0]=
    typecast_exprt(
      address_of_exprt(
        index_exprt(
          function_id_string, from_integer(0, index_type()))),
      to_code_type(s_it->second.type).parameters()[0].type());

  return call;
}
Exemplo n.º 7
0
pool::index_type pool::allocate_index()
{
	index_type i = index_type(head_);
	if (i == nullidx)
		return nullidx;
	head_ = *(index_type*)pointer(i);
	nfree_--;
	return i;
}
Exemplo n.º 8
0
void c_typecastt::implicit_typecast_arithmetic(
  exprt &expr,
  c_typet c_type)
{
  typet new_type;
  
  const typet &expr_type=ns.follow(expr.type());
  
  switch(c_type)
  {
  case PTR:
    if(expr_type.id()==ID_array)
    {
      new_type.id(ID_pointer);
      new_type.subtype()=expr_type.subtype();
      break;
    }
    return;

  case BOOL:       new_type=bool_typet(); break;
  case CHAR:       assert(false); // should always be promoted to int
  case UCHAR:      assert(false); // should always be promoted to int
  case SHORT:      assert(false); // should always be promoted to int
  case USHORT:     assert(false); // should always be promoted to int
  case INT:        new_type=int_type(); break;
  case UINT:       new_type=uint_type(); break;
  case LONG:       new_type=long_int_type(); break;
  case ULONG:      new_type=long_uint_type(); break;
  case LONGLONG:   new_type=long_long_int_type(); break;
  case ULONGLONG:  new_type=long_long_uint_type(); break;
  case SINGLE:     new_type=float_type(); break;
  case DOUBLE:     new_type=double_type(); break;
  case LONGDOUBLE: new_type=long_double_type(); break;
  case RATIONAL:   new_type=rational_typet(); break;
  case REAL:       new_type=real_typet(); break;
  case INTEGER:    new_type=integer_typet(); break;
  case COMPLEX: return; // do nothing
  default: return;
  }

  if(new_type!=expr_type)
  {
    if(new_type.id()==ID_pointer &&
       expr_type.id()==ID_array)
    {
      exprt index_expr(ID_index, expr_type.subtype());
      index_expr.reserve_operands(2);
      index_expr.move_to_operands(expr);
      index_expr.copy_to_operands(gen_zero(index_type()));
      expr=exprt(ID_address_of, new_type);
      expr.move_to_operands(index_expr);
    }
    else
      do_typecast(expr, new_type);
  }
}
Exemplo n.º 9
0
std::set<symbol_exprt> concurrency_aware_abstractort::targets_of_lvalue(const exprt& lvalue, goto_programt::const_targett program_location)
{

	std::set<symbol_exprt> result;
	if(lvalue.id() == ID_index)
	{
		exprt array_name = lvalue.op0();
		if(array_name.id() == ID_symbol)
		{
			result.insert(to_symbol_expr(array_name));
		} else {
			return targets_of_lvalue(array_name, program_location);
		}
	} else if(lvalue.id() == ID_member) {
		assert(lvalue.operands().size() == 1);
		return targets_of_lvalue(lvalue.op0(), program_location);
	} else if(lvalue.id() == ID_symbol) {
		result.insert(to_symbol_expr(lvalue));
	} else if(lvalue.id() == ID_dereference) {
		// We would like to add anything the pointer can point to,
		// but not the pointer itself

		value_setst::valuest value_set;
		pointer_info.get_values(program_location, lvalue.op0(), value_set);
		for(value_setst::valuest::iterator it = value_set.begin(); it != value_set.end(); it++)
		{
			if(it->id() != ID_object_descriptor)
			{
				// TODO: We may need to deal with this situation more carefully
				continue;
			}
			object_descriptor_exprt& object_descriptor = to_object_descriptor_expr(*it);
			if(object_descriptor.offset() != from_integer(0, index_type()))
			{
				std::cout << "Pointer " << from_expr(lvalue.op0()) << " can point to " << from_expr(*it) << " at line " <<
						program_location->location.get_line() << ", we cannot handle this" << std::endl;
				  exit(1);
			  }

			  if(object_descriptor.object().id() != ID_symbol)
			  {
				  std::cout << "Pointer " << from_expr(lvalue.op0()) << " can point to " << from_expr(*it) << " at line " <<
					  program_location->location.get_line() << ", we cannot handle this" << std::endl;
				  exit(1);
			  }

			  result.insert(to_symbol_expr(object_descriptor.object()));
		}

	} else {
		std::cout << "Cannot currently handle lvalue: " << from_expr(lvalue) << std::endl;
		assert(false);
	}
	return result;
}
Exemplo n.º 10
0
void goto_symext::process_array_expr_rec(
  exprt &expr,
  const typet &type) const
{
  if(expr.id()==ID_if)
  {
    if_exprt &if_expr=to_if_expr(expr);
    process_array_expr_rec(if_expr.true_case(), type);
    process_array_expr_rec(if_expr.false_case(), type);
  }
  else if(expr.id()==ID_index)
  {
    // strip index
    index_exprt &index_expr=to_index_expr(expr);
    exprt tmp=index_expr.array();
    expr.swap(tmp);
  }
  else if(expr.id()==ID_typecast)
  {
    // strip
    exprt tmp=to_typecast_expr(expr).op0();
    expr.swap(tmp);
    process_array_expr_rec(expr, type);
  }
  else if(expr.id()==ID_address_of)
  {
    // strip
    exprt tmp=to_address_of_expr(expr).op0();
    expr.swap(tmp);
    process_array_expr_rec(expr, type);
  }
  else if(expr.id()==ID_symbol &&
          expr.get_bool(ID_C_SSA_symbol) &&
          to_ssa_expr(expr).get_original_expr().id()==ID_index)
  {
    const ssa_exprt &ssa=to_ssa_expr(expr);
    const index_exprt &index_expr=to_index_expr(ssa.get_original_expr());
    exprt tmp=index_expr.array();
    expr.swap(tmp);
  }
  else
    Forall_operands(it, expr)
      process_array_expr_rec(*it, it->type());

  if(!base_type_eq(expr.type(), type, ns))
  {
    byte_extract_exprt be(byte_extract_id());
    be.type()=type;
    be.op()=expr;
    be.offset()=gen_zero(index_type());

    expr.swap(be);
  }
}
Exemplo n.º 11
0
exprt dereferencet::dereference_rec(
  const exprt &address,
  const exprt &offset,
  const typet &type)
{
  if(address.id()==ID_address_of)
  {
    const address_of_exprt &address_of_expr=to_address_of_expr(address);

    const exprt &object=address_of_expr.object();

    return read_object(object, offset, type);
  }
  else if(address.id()==ID_typecast)
  {
    const typecast_exprt &typecast_expr=to_typecast_expr(address);

    return dereference_typecast(typecast_expr, offset, type);
  }
  else if(address.id()==ID_plus)
  {
    // pointer arithmetic
    if(address.operands().size()<2)
      throw "plus with less than two operands";

    return dereference_plus(address, offset, type);
  }
  else if(address.id()==ID_if)
  {
    const if_exprt &if_expr=to_if_expr(address);

    return dereference_if(if_expr, offset, type);
  }
  else if(address.id()==ID_constant)
  {
    const typet result_type=ns.follow(address.type()).subtype();

    // pointer-typed constant
    if(to_constant_expr(address).get_value()==ID_NULL) // NULL
    {
      // we turn this into (type *)0
      exprt zero=gen_zero(index_type());
      return dereference_rec(
        typecast_exprt(zero, address.type()), offset, type);
    }
    else
      throw "dereferencet: unexpected pointer constant "+address.pretty();
  }
  else
  {
    throw "failed to dereference `"+address.id_string()+"'";
  }
}
Exemplo n.º 12
0
// ---------------------------------------------------------------------------
//  synthesizeNext
// ---------------------------------------------------------------------------
//!	Synthesize next block of samples of the partials. The synthesizer
//! will resize the inner buffer as necessary. Previous contents of the buffer
//! are overwritten.
//!
//! \param  sample Number of samples to synthesize.
//! \return Nothing.
//! \post   Internal state of synthesizer changes - it is ready to synthesize
//!         next block of samples starting at 'previous count of samples' + samples.
void RealTimeSynthesizer::synthesizeNext( int samples ) noexcept
{
    //TODO: check processedSamples overflow
    processedSamples += samples;// for performance reason this is computed at the beginning
    PartialStruct *partial;
    
    // prepare buffer for new data
    if (buffer->capacity() < samples)
        buffer->reserve(samples);
    memset(buffer->data(), 0, samples * sizeof(decltype(buffer->data())));
    
    
    // process partials being processed
    int size = partialsBeingProcessed.size();
    for (int i = 0; i < size; i++)
    {
        partial = partialsBeingProcessed.front();
        synthesize( *partial, buffer->data(), samples );
        
        if ( partial->state.lastBreakpointIdx < partial->numBreakpoints - 1)
            partialsBeingProcessed.push( partial );
        
        partialsBeingProcessed.pop();
    }
    
    // partials to be processed
    int partialSize = partials.size();
    for (; partialIdx < partialSize; partialIdx++)
    {
        partial = &(partials[partialIdx]);
        
        // setup partial for synthesis
        partial->state.currentSamp = index_type( (partial->startTime * m_srateHz) + 0.5 );   //  cheap rounding

        if (partial->state.currentSamp > processedSamples)
            break;
        
        partial->state.lastBreakpointIdx = PartialStruct::NoBreakpointProcessed;
        partial->state.envelope = partial->breakpoints[0].second;
        partial->state.breakpointFinished = true;

        //  cache the previous frequency (in Hz) so that it can be used to reset the phase when necessary
        partial->state.prevFrequency = m_osc.frequencyScaling() * partial->breakpoints[1].second._frequency;// 0 is null breakpoint
        
        int sampleCount = processedSamples - partial->state.currentSamp; // how much sample to be processed during this call
        int sampleDelta = samples - sampleCount; // delta when partial should start

        synthesize( *partial, buffer->data() + sampleDelta, sampleCount );
        
        if ( partial->state.lastBreakpointIdx < partial->numBreakpoints - 1)
            partialsBeingProcessed.push(partial);
    }
}
Exemplo n.º 13
0
bool value_sett::eval_pointer_offset(
  exprt &expr,
  const namespacet &ns) const
{
  bool mod=false;

  if(expr.id()==ID_pointer_offset)
  {
    assert(expr.operands().size()==1);

    object_mapt reference_set;
    get_value_set(expr.op0(), reference_set, ns, true);

    exprt new_expr;
    mp_integer previous_offset=0;

    const object_map_dt &object_map=reference_set.read();
    for(object_map_dt::const_iterator
        it=object_map.begin();
        it!=object_map.end();
        it++)
      if(!it->second.offset_is_set)
        return false;
      else
      {
        const exprt &object=object_numbering[it->first];
        mp_integer ptr_offset=compute_pointer_offset(object, ns);

        if(ptr_offset<0)
          return false;

        ptr_offset+=it->second.offset;

        if(mod && ptr_offset!=previous_offset)
          return false;

        new_expr=from_integer(ptr_offset, index_type());
        previous_offset=ptr_offset;
        mod=true;
      }

    if(mod)
      expr.swap(new_expr);
  }
  else
  {
    Forall_operands(it, expr)
      mod=eval_pointer_offset(*it, ns) || mod;
  }

  return mod;
}
Exemplo n.º 14
0
exprt dereferencet::operator()(const exprt &pointer)
{
  if(pointer.type().id()!=ID_pointer)
    throw "dereference expected pointer type, but got "+
          pointer.type().pretty();

  // type of the object
  const typet &type=pointer.type().subtype();

  #ifdef DEBUG
  std::cout << "DEREF: " << from_expr(ns, "", pointer) << std::endl;
  #endif

  return dereference_rec(
    pointer,
    gen_zero(index_type()), // offset
    type);
}
Exemplo n.º 15
0
void c_typecastt::do_typecast(exprt &expr, const typet &type)
{
  // special case: array -> pointer is actually
  // something like address_of
  
  const typet &expr_type=ns.follow(expr.type());

  if(expr_type.id()==ID_array)
  {
    index_exprt index;
    index.array()=expr;
    index.index()=gen_zero(index_type());
    index.type()=expr_type.subtype();
    expr=address_of_exprt(index);
    if(ns.follow(expr.type())!=ns.follow(type))
      expr.make_typecast(type);
    return;
  }

  if(expr_type!=type)
  {
    // C booleans are special: we compile to ?0:1
    
    if(type.get(ID_C_c_type)==ID_bool)
    {
      if(expr_type.id()==ID_bool) // bool -> _Bool
      {
        exprt result=if_exprt(expr, gen_one(type), gen_zero(type));
        expr.swap(result);
      }
      else // * -> _Bool
      {
        equal_exprt equal_zero(expr, gen_zero(expr_type));
        exprt result=if_exprt(equal_zero, gen_zero(type), gen_one(type));
        expr.swap(result);
      }
    }
    else
    {    
      expr.make_typecast(type);
    }
  }
}
Exemplo n.º 16
0
exprt value_sett::to_expr(object_map_dt::const_iterator it) const
{
  const exprt &object=object_numbering[it->first];

  if(object.id()==ID_invalid ||
     object.id()==ID_unknown)
    return object;

  object_descriptor_exprt od;

  od.object()=object;

  if(it->second.offset_is_set)
    od.offset()=from_integer(it->second.offset, index_type());

  od.type()=od.object().type();

  return od;
}
Exemplo n.º 17
0
 void reset_pool(size_t poolsize) {
   if (poolsize == 0) {
     data.clear();
     freelist.clear();
     lower_ptrlimit = NULL;
     upper_ptrlimit = NULL;
   } else {
     data.resize(poolsize);
     freelist.resize(poolsize);
     for (index_type i = 0;i < freelist.size(); ++i) {
       freelist[i] = i + 1;
     }
     freelist[freelist.size() - 1] = index_type(-1);
     lower_ptrlimit = &(data[0]);
     upper_ptrlimit = &(data[data.size() - 1]);
   }
   freelisthead.q.val = 0;
   freelisthead.q.counter = 0;
 }
Exemplo n.º 18
0
array_exprt string_constantt::to_array_expr() const
{
  const std::string &str=get_string(ID_value);
  unsigned string_size=str.size()+1; // we add the zero
  const typet &char_type=type().subtype();
  bool char_is_unsigned=char_type.id()==ID_unsignedbv;

  exprt size=from_integer(string_size, index_type());

  array_exprt dest;
  dest.type()=array_typet();
  dest.type().subtype()=char_type;
  dest.type().set(ID_size, size);

  dest.operands().resize(string_size);

  exprt::operandst::iterator it=dest.operands().begin();
  for(unsigned i=0; i<string_size; i++, it++)
  {
    // Are we at the end? Do implicit zero.
    int ch=i==string_size-1?0:str[i];

    if(char_is_unsigned)
      ch=(unsigned char)ch;

    exprt &op=*it;

    op=from_integer(ch, char_type);

    if(ch>=32 && ch<=126)
    {
      std::string ch_str="'";
      if(ch=='\'' || ch=='\\') ch_str+='\\';
      ch_str+=(char)ch;
      ch_str+="'";

      op.set(ID_C_cformat, ch_str);
    }
  }
  
  return dest;
}
Exemplo n.º 19
0
void c_typecastt::do_typecast(exprt &expr, const typet &dest_type)
{
  // special case: array -> pointer is actually
  // something like address_of
  
  const typet &src_type=ns.follow(expr.type());

  if(src_type.id()==ID_array)
  {
    index_exprt index;
    index.array()=expr;
    index.index()=gen_zero(index_type());
    index.type()=src_type.subtype();
    expr=address_of_exprt(index);
    if(ns.follow(expr.type())!=ns.follow(dest_type))
      expr.make_typecast(dest_type);
    return;
  }

  if(src_type!=dest_type)
  {
    // C booleans are special; we produce the
    // explicit comparision with zero.
    // Note that this requires ieee_float_notequal
    // in case of floating-point numbers.
    
    if(dest_type.get(ID_C_c_type)==ID_bool)
    {
      expr=is_not_zero(expr, ns);
      expr.make_typecast(dest_type);
    }
    else if(dest_type.id()==ID_bool)
    {
      expr=is_not_zero(expr, ns);
    }
    else
    {    
      expr.make_typecast(dest_type);
    }
  }
}
Exemplo n.º 20
0
array_exprt string_constantt::to_array_expr() const
{
  const std::string &str=get_string(ID_value);
  unsigned string_size=str.size()+1; // zero
  const typet &char_type=type().subtype();
  bool char_is_unsigned=char_type.id()==ID_unsignedbv;

  exprt size=from_integer(string_size, index_type());

  array_exprt dest;
  dest.type()=array_typet();
  dest.type().subtype()=char_type;
  dest.type().set(ID_size, size);

  dest.operands().resize(string_size);

  exprt::operandst::iterator it=dest.operands().begin();
  for(unsigned i=0; i<string_size; i++, it++)
  {
    int ch=i==string_size-1?0:str[i];

    if(char_is_unsigned)
      ch=(unsigned char)ch;

    exprt &op=*it;

    op=from_integer(ch, char_type);

    if(ch>=32 && ch<=126)
    {
      char ch_str[2];
      ch_str[0]=ch;
      ch_str[1]=0;

      op.set(ID_C_cformat, "'"+std::string(ch_str)+"'");
    }
  }
  
  return dest;
}
Exemplo n.º 21
0
bool ssa_may_alias(
  const exprt &e1,
  const exprt &e2,
  const namespacet &ns)
{
  #ifdef DEBUG
  std::cout << "MAY ALIAS1 " << from_expr(ns, "", e1) << " "
                             << from_expr(ns, "", e2) << "\n";
  #endif

  // The same?
  if(e1==e2)
    return true;

  // Both symbol?
  if(e1.id()==ID_symbol &&
     e2.id()==ID_symbol)
  {
    return to_symbol_expr(e1).get_identifier()==
           to_symbol_expr(e2).get_identifier();
  }

  // __CPROVER symbols
  if(e1.id()==ID_symbol &&
     has_prefix(
       id2string(to_symbol_expr(e1).get_identifier()), CPROVER_PREFIX))
    return false;

  if(e2.id()==ID_symbol &&
     has_prefix(
       id2string(to_symbol_expr(e2).get_identifier()), CPROVER_PREFIX))
    return false;

  if(e1.id()==ID_symbol &&
     has_suffix(
       id2string(to_symbol_expr(e1).get_identifier()), "#return_value"))
    return false;

  if(e2.id()==ID_symbol &&
     has_suffix(
       id2string(to_symbol_expr(e2).get_identifier()), "#return_value"))
    return false;

  // Both member?
  if(e1.id()==ID_member &&
     e2.id()==ID_member)
  {
    const member_exprt &m1=to_member_expr(e1);
    const member_exprt &m2=to_member_expr(e2);

    // same component?
    if(m1.get_component_name()!=m2.get_component_name())
      return false;

    return ssa_may_alias(m1.struct_op(), m2.struct_op(), ns);
  }

  // Both index?
  if(e1.id()==ID_index &&
     e2.id()==ID_index)
  {
    const index_exprt &i1=to_index_expr(e1);
    const index_exprt &i2=to_index_expr(e2);

    return ssa_may_alias(i1.array(), i2.array(), ns);
  }

  const typet &t1=ns.follow(e1.type());
  const typet &t2=ns.follow(e2.type());

  // If one is an array and the other not, consider the elements
  if(t1.id()==ID_array && t2.id()!=ID_array)
    if(ssa_may_alias(
         index_exprt(e1, gen_zero(index_type()), t1.subtype()), e2, ns))
      return true;

  if(t2.id()==ID_array && t2.id()!=ID_array)
    if(ssa_may_alias(
         e1, index_exprt(e2, gen_zero(index_type()), t2.subtype()), ns))
      return true;

  // Pointers only alias with other pointers,
  // which is a restriction.
  if(t1.id()==ID_pointer)
    return t2.id()==ID_pointer;

  if(t2.id()==ID_pointer)
    return t1.id()==ID_pointer;

  // Is one a scalar pointer?
  if(e1.id()==ID_dereference &&
     (t1.id()==ID_signedbv || t1.id()==ID_unsignedbv || t1.id()==ID_floatbv))
    return true;

  if(e2.id()==ID_dereference &&
     (t2.id()==ID_signedbv || t2.id()==ID_unsignedbv || t1.id()==ID_floatbv))
    return true;

  // Is one a pointer?
  if(e1.id()==ID_dereference ||
     e2.id()==ID_dereference)
  {
    // look at the types

    // same type?
    if(base_type_eq(t1, t2, ns))
    {
      return true;
    }

    // should consider further options, e.g., struct prefixes
    return false;
  }

  return false; // both different objects
}
Exemplo n.º 22
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();
}
Exemplo n.º 23
0
std::set<symbol_exprt> locations_of_expression_rec(const predicatet& phi, const goto_programt::const_targett program_location, value_set_analysist& pointer_info, const namespacet& ns)
{
	if(phi.id()==ID_address_of)
	{
		// Addresses are constant -- don't need to read the symbol whose address we are taking
		return std::set<symbol_exprt>();
	}

	if(phi.id()==ID_constant)
	{
		// No symbols associated with a constant
		return std::set<symbol_exprt>();
	}

	if(phi.id()==ID_symbol)
	{
		std::set<symbol_exprt> result;
		result.insert(to_symbol_expr(phi));
		return result;
	}

	if(phi.id()==ID_dereference)
	{
		// We would like to add the pointer itself (which for now we require to be a variable)
		// and anything it can point to

		std::set<symbol_exprt> result;

		result = locations_of_expression_rec(phi.op0(), program_location, pointer_info, ns); // if we have *p, we insert the locations of p itself

		value_setst::valuest value_set;
		pointer_info.get_values(program_location, phi.op0(), value_set);

		for(value_setst::valuest::iterator it = value_set.begin(); it != value_set.end(); it++)
		{
			if(it->id() != ID_object_descriptor)
			{
				// TODO: We may need to deal with this situation more carefully
				continue;
			}

			object_descriptor_exprt& object_descriptor = to_object_descriptor_expr(*it);

			if(object_descriptor.object().id() == "NULL-object")
			{
				// No locations associated with NULL
				continue;
			}

			if(object_descriptor.offset() != from_integer(0, index_type()))
			{
				std::cout << "(*) Warning: pointer " << from_expr(ns, "", phi.op0()) << " can point to " << from_expr(ns, "", *it) << " at " <<
						program_location->location << ", this needs further investigation" << std::endl;
				continue;
			}

			if(object_descriptor.object().id() != ID_symbol)
			{
				std::cout << "(**) Warning: pointer " << from_expr(ns, "", phi.op0()) << " can point to " << from_expr(ns, "", *it) << " at " <<
						program_location->location << ", this needs further investigation" << std::endl;
				continue;
			}

			result.insert(to_symbol_expr(object_descriptor.object()));
		}

		return result;
	}

	if(phi.id()=="invalid-pointer" || phi.id()=="pointer_arithmetic" || phi.id()=="pointer_difference")
	{
		std::cout << "(***) Warning: cannot yet handle " << from_expr(ns, "", phi) << ", ignoring it" << std::endl;
		return std::set<symbol_exprt>();
	}


	{
		/* Default case: iterate through the operands of the expression, adding all locations referenced therein */
		std::set<symbol_exprt> result;
		for(unsigned int i = 0; i < phi.operands().size(); i++)
		{
			std::set<symbol_exprt> symbols_i = locations_of_expression_rec(phi.operands()[i], program_location, pointer_info, ns);
			for(std::set<symbol_exprt>::iterator it = symbols_i.begin(); it != symbols_i.end(); it++)
			{
				result.insert(*it);
			}
		}
		return result;
	}

}
Exemplo n.º 24
0
void c_typecheck_baset::typecheck_compound_type(struct_union_typet &type)
{
  struct_union_typet::componentst &components=type.components();

  // mark bit-fields
  for(struct_union_typet::componentst::iterator
      it=components.begin();
      it!=components.end();
      it++)
    if(it->type().id()==ID_c_bitfield)
    {
      it->set_is_bit_field(true);
      typet tmp=it->type().subtype();
      typecheck_type(tmp);
      it->set_bit_field_type(tmp);
    }

  // check subtypes
  for(struct_union_typet::componentst::iterator
      it=components.begin();
      it!=components.end();
      it++)
    typecheck_type(it->type());

  unsigned anon_member_counter=0;

  // scan for anonymous members, and name them
  for(struct_union_typet::componentst::iterator
      it=components.begin();
      it!=components.end();
      it++)
  {
    if(it->get_name()!=irep_idt()) continue;

    it->set_name("$anon"+i2string(anon_member_counter++));
    it->set_anonymous(true);
  }

  // scan for duplicate members

  {
    hash_set_cont<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)
      {
        // we do nothing (as gcc won't complain)
      }
    }
  }
  
  // We allow an incomplete (C99) array as _last_ member!
  // Zero-length is allowed everywhere.

  if(type.id()==ID_struct)
  {
    for(struct_union_typet::componentst::iterator
        it=components.begin();
        it!=components.end();
        it++)
    {
      typet &type=it->type();
    
      if(type.id()==ID_array &&
         to_array_type(type).is_incomplete())
      {
        // needs to be last member
        if(it!=--components.end())
        {
          err_location(*it);
          throw "flexible struct member must be last member";
        }
        
        // make it zero-length
        type.id(ID_array);
        type.set(ID_size, gen_zero(index_type()));
      }
    }  
  }

  // we may add some minimal padding inside structs (not unions)
  // unless there is an attribute that says that the struct is
  // 'packed'

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

  // 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_code && it->get(ID_statement)==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())
      {
        err_location(*it);
        throw "failed _Static_assert";
      }
      else if(!assertion.is_true())
      {
        // should warn/complain
      }
      
      it=components.erase(it);
    }
    else
      it++;
  }  
}
Exemplo n.º 25
0
void c_typecheck_baset::typecheck_compound_body(
  struct_union_typet &type)
{
  struct_union_typet::componentst &components=type.components();

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

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

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

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

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

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

        typecheck_type(new_component.type());

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

        components.push_back(new_component);
      }
    }
  }

  unsigned anon_member_counter=0;

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

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

  // scan for duplicate members

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

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

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

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

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

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

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

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

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

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

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

      it=components.erase(it);
    }
    else
      it++;
  }
}
Exemplo n.º 26
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(symbol_table.symbols.find(cntr_id)==symbol_table.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=ID_C;
    new_symbol.type=size_type();
    new_symbol.is_state_var=true;
    new_symbol.is_lvalue=true;
    new_symbol.is_static_lifetime=true;
    
    symbol_table.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(cntr_sym.symbol_expr(), 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(ID_plus, unsigned_int_type());
  plus.copy_to_operands(cntr_sym.symbol_expr());
  plus.copy_to_operands(gen_one(unsigned_int_type()));
  
  increment->code=code_assignt(cntr_sym.symbol_expr(), 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()==ID_pointer)
    bufp = buffer;
  else
  {
    index_exprt index;
    index.array()=buffer;
    index.index()=gen_zero(index_type());
    index.type()=buf_type.subtype();
    bufp = address_of_exprt(index);
  }
  
  exprt deref(ID_dereference, buf_type.subtype());
  exprt b_plus_i(ID_plus, bufp.type());
  b_plus_i.copy_to_operands(bufp);
  b_plus_i.copy_to_operands(cntr_sym.symbol_expr());
  deref.copy_to_operands(b_plus_i);
  
  check->make_goto(exit);
  
  if(limit==0)
    check->guard=
          binary_relation_exprt(cntr_sym.symbol_expr(), ID_ge, 
                                buffer_size(bufp));
  else
    check->guard=
          binary_relation_exprt(cntr_sym.symbol_expr(), ID_gt, 
                                from_integer(limit, unsigned_int_type()));
  
  exprt nondet=side_effect_expr_nondett(buf_type.subtype());
  invalidate->code=code_assignt(deref, nondet);
}
Exemplo n.º 27
0
void string_instrumentationt::do_format_string_read(
  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)
  {
    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(it->type==format_tokent::STRING)
      {
        const exprt &arg = arguments[argument_start_inx+args];
        const typet &arg_type = ns.follow(arg.type());
        
        if(arg.id()!=ID_string_constant) // we don't need to check constants
        {
          goto_programt::targett assertion=dest.add_instruction();
          assertion->location=target->location;
          assertion->location.set("property", "string");
          std::string comment("zero-termination of string argument of ");
          comment += function_name;
          assertion->location.set("comment", comment);
          
          exprt temp(arg);
          
          if(arg_type.id()!=ID_pointer)
          {
            index_exprt index;
            index.array()=temp;
            index.index()=gen_zero(index_type());
            index.type()=arg_type.subtype();            
            temp=address_of_exprt(index);            
          }
          
          assertion->make_assertion(is_zero_string(temp));
        }
      }
      
      if(it->type!=format_tokent::TEXT && 
         it->type!=format_tokent::UNKNOWN) args++;
      
      if(find(it->flags.begin(), it->flags.end(), format_tokent::ASTERISK)!=
         it->flags.end())
        args++; // just eat the additional argument          
    }
  }
  else // non-const format string
  {
    goto_programt::targett format_ass=dest.add_instruction();
    format_ass->make_assertion(is_zero_string(arguments[1]));
    format_ass->location=target->location;
    format_ass->location.set("property", "string");
    std::string comment("zero-termination of format string of ");
    comment += function_name;
    format_ass->location.set("comment", comment);
    
    for(unsigned i=2; i<arguments.size(); i++)
    {
      const exprt &arg = arguments[i];
      const typet &arg_type=ns.follow(arguments[i].type());
      
      if(arguments[i].id()!=ID_string_constant &&
         is_string_type(arg_type))
      {
        goto_programt::targett assertion=dest.add_instruction();        
        assertion->location=target->location;
        assertion->location.set("property", "string");
        std::string comment("zero-termination of string argument of ");
        comment += function_name;
        assertion->location.set("comment", comment);
        
        exprt temp(arg);
                  
        if(arg_type.id()!=ID_pointer)
        {
          index_exprt index;
          index.array()=temp;
          index.index()=gen_zero(index_type());
          index.type()=arg_type.subtype();            
          temp=address_of_exprt(index);            
        }
        
        assertion->make_assertion(is_zero_string(temp));
      }
    }
  }
}
Exemplo n.º 28
0
pool::index_type pool::index(void* ptr) const
{
	return ptr ? index_type(((uint8_t*)ptr - blocks_) / stride_) : nullidx;
}
Exemplo n.º 29
0
void string_instrumentationt::do_strerror(
  goto_programt &dest,
  goto_programt::targett it,
  code_function_callt &call)
{
  if(call.lhs().is_nil())
  {
    it->make_skip();
    return;
  }

  irep_idt identifier_buf="c::__strerror_buffer";
  irep_idt identifier_size="c::__strerror_buffer_size";

  if(symbol_table.symbols.find(identifier_buf)==symbol_table.symbols.end())
  {
    symbolt new_symbol_size;
    new_symbol_size.base_name="__strerror_buffer_size";
    new_symbol_size.pretty_name=new_symbol_size.base_name;
    new_symbol_size.name=identifier_size;
    new_symbol_size.mode=ID_C;
    new_symbol_size.type=size_type();
    new_symbol_size.is_state_var=true;
    new_symbol_size.is_lvalue=true;
    new_symbol_size.is_static_lifetime=true;

    array_typet type;
    type.subtype()=char_type();
    type.size()=new_symbol_size.symbol_expr();
    symbolt new_symbol_buf;
    new_symbol_buf.mode=ID_C;
    new_symbol_buf.type=type;
    new_symbol_buf.is_state_var=true;
    new_symbol_buf.is_lvalue=true;
    new_symbol_buf.is_static_lifetime=true;
    new_symbol_buf.base_name="__strerror_buffer";
    new_symbol_buf.pretty_name=new_symbol_buf.base_name;
    new_symbol_buf.name="c::"+id2string(new_symbol_buf.base_name);

    symbol_table.move(new_symbol_buf);
    symbol_table.move(new_symbol_size);
  }

  const symbolt &symbol_size=ns.lookup(identifier_size);
  const symbolt &symbol_buf=ns.lookup(identifier_buf);

  goto_programt tmp;

  {  
    goto_programt::targett assignment1=tmp.add_instruction(ASSIGN);
    exprt nondet_size=side_effect_expr_nondett(size_type());

    assignment1->code=code_assignt(symbol_size.symbol_expr(), nondet_size);
    assignment1->location=it->location;
    
    goto_programt::targett assumption1=tmp.add_instruction();

    assumption1->make_assumption(binary_relation_exprt(
      symbol_size.symbol_expr(), ID_notequal,
      gen_zero(symbol_size.type)));

    assumption1->location=it->location;
  }

  // return a pointer to some magic buffer
  exprt index=exprt(ID_index, char_type());
  index.copy_to_operands(symbol_buf.symbol_expr(), gen_zero(index_type()));

  exprt ptr=exprt(ID_address_of, pointer_typet());
  ptr.type().subtype()=char_type();
  ptr.copy_to_operands(index);

  // make that zero-terminated
  {
    goto_programt::targett assignment2=tmp.add_instruction(ASSIGN);
    assignment2->code=code_assignt(is_zero_string(ptr, true), true_exprt());
    assignment2->location=it->location;
  }

  // assign address
  {
    goto_programt::targett assignment3=tmp.add_instruction(ASSIGN);
    exprt rhs=ptr;
    make_type(rhs, call.lhs().type());
    assignment3->code=code_assignt(call.lhs(), rhs);
    assignment3->location=it->location;
  }

  it->make_skip();
  dest.insert_before_swap(it, tmp);
}
Exemplo n.º 30
0
void goto_convertt::do_java_new_array(
  const exprt &lhs,
  const side_effect_exprt &rhs,
  goto_programt &dest)
{
  if(lhs.is_nil())
    throw "do_java_new_array without lhs is yet to be implemented";
    
  source_locationt location=rhs.source_location();

  assert(rhs.operands().size()>=1); // one per dimension
  
  if(rhs.type().id()!=ID_pointer)
    throw "do_java_new_array returns pointer";

  typet object_type=rhs.type().subtype();
  
  // build size expression
  exprt object_size=size_of_expr(object_type, ns);
  
  if(object_size.is_nil())
    throw "do_java_new_array got nil object_size";

  // we produce a malloc side-effect, which stays
  side_effect_exprt malloc_expr(ID_malloc);
  malloc_expr.copy_to_operands(object_size);
  malloc_expr.type()=pointer_typet(object_type);

  goto_programt::targett t_n=dest.add_instruction(ASSIGN);
  t_n->code=code_assignt(lhs, malloc_expr);
  t_n->source_location=location;
  
  // multi-dimensional?
  
  assert(ns.follow(object_type).id()==ID_struct);
  const struct_typet &struct_type=to_struct_type(ns.follow(object_type));
  assert(struct_type.components().size()==3);

  // if it's an array, we need to set the length field
  dereference_exprt deref(lhs, object_type);
  member_exprt length(deref, struct_type.components()[1].get_name(), struct_type.components()[1].type());
  goto_programt::targett t_s=dest.add_instruction(ASSIGN);
  t_s->code=code_assignt(length, rhs.op0());
  t_s->source_location=location;
  
  // we also need to allocate space for the data
  member_exprt data(deref, struct_type.components()[2].get_name(), struct_type.components()[2].type());
  side_effect_exprt data_cpp_new_expr(ID_cpp_new_array, data.type());
  data_cpp_new_expr.set(ID_size, rhs.op0());
  goto_programt::targett t_p=dest.add_instruction(ASSIGN);
  t_p->code=code_assignt(data, data_cpp_new_expr);
  t_p->source_location=location;
  
  // zero-initialize the data
  exprt zero_element=gen_zero(data.type().subtype());
  codet array_set(ID_array_set);
  array_set.copy_to_operands(data, zero_element);
  goto_programt::targett t_d=dest.add_instruction(OTHER);
  t_d->code=array_set;
  t_d->source_location=location;

  if(rhs.operands().size()>=2)
  {
    // produce
    // for(int i=0; i<size; i++) tmp[i]=java_new(dim-1);
    // This will be converted recursively.
    
    goto_programt tmp;

    symbol_exprt tmp_i=
      new_tmp_symbol(index_type(), "index", tmp, location).symbol_expr();

    code_fort for_loop;
    
    side_effect_exprt sub_java_new=rhs;
    sub_java_new.operands().erase(sub_java_new.operands().begin());
    
    side_effect_exprt inc(ID_assign);
    inc.operands().resize(2);
    inc.op0()=tmp_i;
    inc.op1()=plus_exprt(tmp_i, gen_one(tmp_i.type()));
    
    dereference_exprt deref_expr(plus_exprt(data, tmp_i), data.type().subtype());
    
    for_loop.init()=code_assignt(tmp_i, gen_zero(tmp_i.type()));
    for_loop.cond()=binary_relation_exprt(tmp_i, ID_lt, rhs.op0());
    for_loop.iter()=inc;
    for_loop.body()=code_skipt();
    for_loop.body()=code_assignt(deref_expr, sub_java_new);

    convert(for_loop, tmp);
    dest.destructive_append(tmp);
  }
}