Beispiel #1
0
void c_typecheck_baset::typecheck_c_bit_field_type(typet &type)
{
  typecheck_type(type.subtype());

  exprt &width_expr=static_cast<exprt &>(type.add(ID_size));

  typecheck_expr(width_expr);
  make_constant_index(width_expr);

  mp_integer i;
  if(to_integer(width_expr, i))
  {
    err_location(type);
    throw "failed to convert bit field width";
  }

  if(i<0)
  {
    err_location(type);
    throw "bit field width is negative";
  }

  const typet &base_type=follow(type.subtype());
  
  if(base_type.id()==ID_bool)
  {
    if(i>1)
    {
      err_location(type);
      throw "bit field width too large";
    }

    // We don't use bool, as it's really a byte long.
    type.id(ID_unsignedbv);
    type.set(ID_width, integer2long(i));
  }
  else if(base_type.id()==ID_signedbv ||
          base_type.id()==ID_unsignedbv ||
          base_type.id()==ID_c_enum)
  {
    unsigned width=base_type.get_int(ID_width);

    if(i>width)
    {
      err_location(type);
      throw "bit field width too large";
    }

    typet tmp(base_type);
    type.swap(tmp);
    type.set(ID_width, integer2string(i));
  }
  else
  {
    err_location(type);
    str << "bit field with non-integer type: "
        << to_string(base_type);
    throw 0;
  }
}
Beispiel #2
0
void cpp_typecheckt::typecheck_enum_body(symbolt &enum_symbol)
{
  typet &type=enum_symbol.type;
  
  exprt &body=static_cast<exprt &>(type.add(ID_body));
  irept::subt &components=body.get_sub();
  
  typet enum_type(ID_symbol);
  enum_type.set(ID_identifier, 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);
      make_constant_index(value);
      if(to_integer(value, i))
        throw "failed to produce integer for enum";
    }
    
    exprt final_value(ID_constant, enum_type);
    final_value.set(ID_value, integer2string(i));
    
    symbolt symbol;

    symbol.name=id2string(enum_symbol.name)+"::"+id2string(name);
    symbol.base_name=name;
    symbol.value.swap(final_value);
    symbol.location=static_cast<const locationt &>(it->find(ID_C_location));
    symbol.mode=ID_cpp;
    symbol.module=module;
    symbol.type=enum_type;
    symbol.is_type=false;
    symbol.is_macro=true;
    
    symbolt *new_symbol;
    if(symbol_table.move(symbol, new_symbol))
      throw "cpp_typecheckt::typecheck_enum_body: symbol_table.move() failed";

    cpp_idt &scope_identifier=
      cpp_scopes.put_into_scope(*new_symbol);
    
    scope_identifier.id_class=cpp_idt::SYMBOL;
    
    ++i;
  }
}
void cpp_typecheckt::check_fixed_size_array(typet &type)
{
  if(type.id()==ID_array)
  {
    array_typet &array_type=to_array_type(type);
    
    if(array_type.size().is_not_nil())
      make_constant_index(array_type.size());

    // recursive call for multi-dimensional arrays
    check_fixed_size_array(array_type.subtype());
  }
}
designatort c_typecheck_baset::make_designator(
  const typet &src_type,
  const exprt &src)
{
  assert(!src.operands().empty());

  typet type=src_type;
  designatort designator;

  forall_operands(it, src)
  {
    const exprt &d_op=*it;
    designatort::entryt entry;
    entry.type=type;
    const typet &full_type=follow(entry.type);

    if(full_type.id()==ID_array)
    {
      if(d_op.id()!=ID_index)
      {
        err_location(d_op);
        error() << "expected array index designator" << eom;
        throw 0;
      }

      assert(d_op.operands().size()==1);
      exprt tmp_index=d_op.op0();
      make_constant_index(tmp_index);

      mp_integer index, size;

      if(to_integer(tmp_index, index))
      {
        err_location(d_op.op0());
        error() << "expected constant array index designator" << eom;
        throw 0;
      }

      if(to_array_type(full_type).size().is_nil())
        size=0;
      else if(to_integer(to_array_type(full_type).size(), size))
      {
        err_location(d_op.op0());
        error() << "expected constant array size" << eom;
        throw 0;
      }

      entry.index=integer2size_t(index);
      entry.size=integer2size_t(size);
      entry.subtype=full_type.subtype();
    }
    else if(full_type.id()==ID_struct ||
            full_type.id()==ID_union)
    {
      const struct_union_typet &struct_union_type=
        to_struct_union_type(full_type);

      if(d_op.id()!=ID_member)
      {
        err_location(d_op);
        error() << "expected member designator" << eom;
        throw 0;
      }

      const irep_idt &component_name=d_op.get(ID_component_name);

      if(struct_union_type.has_component(component_name))
      {
        // a direct member
        entry.index=struct_union_type.component_number(component_name);
        entry.size=struct_union_type.components().size();
        entry.subtype=struct_union_type.components()[entry.index].type();
      }
      else
      {
        // We will search for anonymous members,
        // in a loop. This isn't supported by gcc, but icc does allow it.

        bool found=false, repeat;
        typet tmp_type=entry.type;

        do
        {
          repeat=false;
          unsigned number=0;
          const struct_union_typet::componentst &components=
            to_struct_union_type(follow(tmp_type)).components();

          for(struct_union_typet::componentst::const_iterator
              c_it=components.begin();
              c_it!=components.end();
              c_it++, number++)
          {
            if(c_it->get_name()==component_name)
            {
              // done!
              entry.index=number;
              entry.size=components.size();
              entry.subtype=components[entry.index].type();
              entry.type=tmp_type;
            }
            else if(c_it->get_anonymous() &&
                    (follow(c_it->type()).id()==ID_struct ||
                     follow(c_it->type()).id()==ID_union) &&
                    has_component_rec(
                      c_it->type(), component_name, *this))
            {
              entry.index=number;
              entry.size=components.size();
              entry.subtype=c_it->type();
              entry.type=tmp_type;
              tmp_type=entry.subtype;
              designator.push_entry(entry);
              found=repeat=true;
              break;
            }
          }
        }
        while(repeat);

        if(!found)
        {
          err_location(d_op);
          error() << "failed to find struct component `"
                  << component_name << "' in initialization of `"
                  << to_string(struct_union_type) << "'" << eom;
          throw 0;
        }
      }
    }
    else
    {
      err_location(d_op);
      error() << "designated initializers cannot initialize `"
              << to_string(full_type) << "'" << eom;
      throw 0;
    }

    type=entry.subtype;
    designator.push_entry(entry);
  }

  assert(!designator.empty());

  return designator;
}
Beispiel #5
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());
}
Beispiel #6
0
void c_typecheck_baset::typecheck_custom_type(typet &type)
{
  // they all have a width
  exprt size_expr=
    static_cast<const exprt &>(type.find(ID_size));

  typecheck_expr(size_expr);
  source_locationt source_location=size_expr.source_location();
  make_constant_index(size_expr);

  mp_integer size_int;
  if(to_integer(size_expr, size_int))
  {
    error().source_location=source_location;
    error() << "failed to convert bit vector width to constant" << eom;
    throw 0;
  }

  if(size_int<1)
  {
    error().source_location=source_location;
    error() << "bit vector width invalid" << eom;
    throw 0;
  }

  type.remove(ID_size);
  type.set(ID_width, integer2string(size_int));

  // depending on type, there may be a number of fractional bits

  if(type.id()==ID_custom_unsignedbv)
    type.id(ID_unsignedbv);
  else if(type.id()==ID_custom_signedbv)
    type.id(ID_signedbv);
  else if(type.id()==ID_custom_fixedbv)
  {
    type.id(ID_fixedbv);

    exprt f_expr=
      static_cast<const exprt &>(type.find(ID_f));

    source_locationt source_location=f_expr.find_source_location();

    typecheck_expr(f_expr);

    make_constant_index(f_expr);

    mp_integer f_int;
    if(to_integer(f_expr, f_int))
    {
      error().source_location=source_location;
      error() << "failed to convert number of fraction bits to constant" << eom;
      throw 0;
    }

    if(f_int<0 || f_int>size_int)
    {
      error().source_location=source_location;
      error() << "fixedbv fraction width invalid" << eom;
      throw 0;
    }

    type.remove(ID_f);
    type.set(ID_integer_bits, integer2string(size_int-f_int));
  }
  else if(type.id()==ID_custom_floatbv)
  {
    type.id(ID_floatbv);

    exprt f_expr=
      static_cast<const exprt &>(type.find(ID_f));

    source_locationt source_location=f_expr.find_source_location();

    typecheck_expr(f_expr);

    make_constant_index(f_expr);

    mp_integer f_int;
    if(to_integer(f_expr, f_int))
    {
      error().source_location=source_location;
      error() << "failed to convert number of fraction bits to constant" << eom;
      throw 0;
    }

    if(f_int<1 || f_int+1>=size_int)
    {
      error().source_location=source_location;
      error() << "floatbv fraction width invalid" << eom;
      throw 0;
    }

    type.remove(ID_f);
    type.set(ID_f, integer2string(f_int));
  }
  else
    assert(false);
}
Beispiel #7
0
void c_typecheck_baset::typecheck_c_bit_field_type(c_bit_field_typet &type)
{
  typecheck_type(type.subtype());

  mp_integer i;

  {
    exprt &width_expr=static_cast<exprt &>(type.add(ID_size));

    typecheck_expr(width_expr);
    make_constant_index(width_expr);

    if(to_integer(width_expr, i))
    {
      error().source_location=type.source_location();
      error() << "failed to convert bit field width" << eom;
      throw 0;
    }

    if(i<0)
    {
      error().source_location=type.source_location();
      error() << "bit field width is negative" << eom;
      throw 0;
    }

    type.set_width(integer2size_t(i));
    type.remove(ID_size);
  }

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

  std::size_t sub_width=0;

  if(subtype.id()==ID_bool)
  {
    // This is the 'proper' bool.
    sub_width=1;
  }
  else if(subtype.id()==ID_signedbv ||
          subtype.id()==ID_unsignedbv ||
          subtype.id()==ID_c_bool)
  {
    sub_width=to_bitvector_type(subtype).get_width();
  }
  else if(subtype.id()==ID_c_enum_tag)
  {
    // These point to an enum, which has a sub-subtype,
    // which may be smaller or larger than int, and we thus have
    // to check.
    const typet &c_enum_type=
      follow_tag(to_c_enum_tag_type(subtype));

    if(c_enum_type.id()==ID_incomplete_c_enum)
    {
      error().source_location=type.source_location();
      error() << "bit field has incomplete enum type" << eom;
      throw 0;
    }

    sub_width=c_enum_type.subtype().get_int(ID_width);
  }
  else
  {
    error().source_location=type.source_location();
    error() << "bit field with non-integer type: "
            << to_string(subtype) << eom;
    throw 0;
  }

  if(i>sub_width)
  {
    error().source_location=type.source_location();
    error() << "bit field (" << i
            << " bits) larger than type (" << sub_width << " bits)"
            << eom;
    throw 0;
  }
}
Beispiel #8
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;
}