Exemplo n.º 1
0
typet c_typecheck_baset::enum_constant_type(
  const mp_integer &min_value,
  const mp_integer &max_value) const
{
  if(config.ansi_c.mode==configt::ansi_ct::flavourt::VISUAL_STUDIO)
  {
    return signed_int_type();
  }
  else
  {
    // enum constants are at least 'int', but may be made larger.
    // 'Packing' has no influence.
    if(max_value<(mp_integer(1)<<(config.ansi_c.int_width-1)) &&
       min_value>=-(mp_integer(1)<<(config.ansi_c.int_width-1)))
      return signed_int_type();
    else if(max_value<(mp_integer(1)<<config.ansi_c.int_width) &&
            min_value>=0)
      return unsigned_int_type();
    else if(max_value<(mp_integer(1)<<config.ansi_c.long_int_width) &&
            min_value>=0)
      return unsigned_long_int_type();
    else if(max_value<(mp_integer(1)<<config.ansi_c.long_long_int_width) &&
            min_value>=0)
      return unsigned_long_long_int_type();
    else if(max_value<(mp_integer(1)<<(config.ansi_c.long_int_width-1)) &&
            min_value>=-(mp_integer(1)<<(config.ansi_c.long_int_width-1)))
      return signed_long_int_type();
    else
      return signed_long_long_int_type();
  }
}
Exemplo n.º 2
0
typet c_typecheck_baset::enum_underlying_type(
  const mp_integer &min_value,
  const mp_integer &max_value,
  bool is_packed) const
{
  if(config.ansi_c.mode==configt::ansi_ct::flavourt::VISUAL_STUDIO)
  {
    return signed_int_type();
  }
  else
  {
    if(min_value<0)
    {
      // We'll want a signed type.

      if(is_packed)
      {
        // If packed, there are smaller options.
        if(max_value<(mp_integer(1)<<(config.ansi_c.char_width-1)) &&
           min_value>=-(mp_integer(1)<<(config.ansi_c.char_width-1)))
          return signed_char_type();
        else if(max_value<(mp_integer(1)<<(config.ansi_c.short_int_width-1)) &&
                min_value>=-(mp_integer(1)<<(config.ansi_c.short_int_width-1)))
          return signed_short_int_type();
      }

      if(max_value<(mp_integer(1)<<(config.ansi_c.int_width-1)) &&
         min_value>=-(mp_integer(1)<<(config.ansi_c.int_width-1)))
        return signed_int_type();
      else if(max_value<(mp_integer(1)<<(config.ansi_c.long_int_width-1)) &&
              min_value>=-(mp_integer(1)<<(config.ansi_c.long_int_width-1)))
        return signed_long_int_type();
      else
        return signed_long_long_int_type();
    }
    else
    {
      // We'll want an unsigned type.

      if(is_packed)
      {
        // If packed, there are smaller options.
        if(max_value<(mp_integer(1)<<config.ansi_c.char_width))
          return unsigned_char_type();
        else if(max_value<(mp_integer(1)<<config.ansi_c.short_int_width))
          return unsigned_short_int_type();
      }

      if(max_value<(mp_integer(1)<<config.ansi_c.int_width))
        return unsigned_int_type();
      else if(max_value<(mp_integer(1)<<config.ansi_c.long_int_width))
        return unsigned_long_int_type();
      else
        return unsigned_long_long_int_type();
    }
  }
}
void java_internal_additions(symbol_tablet &dest)
{
  // add __CPROVER_rounding_mode

  {
    symbolt symbol;
    symbol.base_name="__CPROVER_rounding_mode";
    symbol.name=CPROVER_PREFIX "rounding_mode";
    symbol.type=signed_int_type();
    symbol.mode=ID_C;
    symbol.is_lvalue=true;
    symbol.is_state_var=true;
    symbol.is_thread_local=true;
    dest.add(symbol);
  }

  // add __CPROVER_malloc_object

  {
    symbolt symbol;
    symbol.base_name="__CPROVER_malloc_object";
    symbol.name=CPROVER_PREFIX "malloc_object";
    symbol.type=pointer_type(empty_typet());
    symbol.mode=ID_C;
    symbol.is_lvalue=true;
    symbol.is_state_var=true;
    symbol.is_thread_local=true;
    dest.add(symbol);
  }
}
Exemplo n.º 4
0
void cpp_declarator_convertert::main_function_rules(
  const symbolt &symbol)
{
  if(symbol.name==ID_main)
  {
    if(symbol.type.id()!=ID_code)
    {
      cpp_typecheck.error().source_location=symbol.location;
      cpp_typecheck.error() << "main must be function" << messaget::eom;
      throw 0;
    }

    const typet &return_type=
      to_code_type(symbol.type).return_type();

    if(return_type!=signed_int_type())
    {
      // Too many embedded compilers ignore this rule.
      #if 0
      cpp_typecheck.error().source_location=symbol.location;
      throw "main must return int";
      #endif
    }
  }
}
Exemplo n.º 5
0
void c_typecheck_baset::typecheck_c_enum_tag_type(c_enum_tag_typet &type)
{
  // It's just a tag.

  if(type.find(ID_tag).is_nil())
  {
    error().source_location=type.source_location();
    error() << "anonymous enum tag without members" << eom;
    throw 0;
  }

  source_locationt source_location=type.source_location();

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

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

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

    if(symbol.type.id()!=ID_c_enum &&
       symbol.type.id()!=ID_incomplete_c_enum)
    {
      error().source_location=source_location;
      error() << "use of tag that does not match previous declaration" << eom;
      throw 0;
    }
  }
  else
  {
    // no, add it as an incomplete c_enum
    typet new_type(ID_incomplete_c_enum);
    new_type.subtype()=signed_int_type(); // default
    new_type.add(ID_tag)=tag;

    symbolt enum_tag_symbol;

    enum_tag_symbol.is_type=true;
    enum_tag_symbol.type=new_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;

    symbolt *new_symbol;
    move_symbol(enum_tag_symbol, new_symbol);
  }

  // Clean up resulting type
  type.remove(ID_tag);
  type.set_identifier(identifier);
}
Exemplo n.º 6
0
typet pointer_diff_type()
{
  // The pointer-diff type varies. This is signed int on some systems,
  // and signed long int on others, and signed long long on say Windows.

  if(config.ansi_c.pointer_width==config.ansi_c.int_width)
    return signed_int_type();
  else if(config.ansi_c.pointer_width==config.ansi_c.long_int_width)
    return signed_long_int_type();
  else if(config.ansi_c.pointer_width==config.ansi_c.long_long_int_width)
    return signed_long_long_int_type();
  else
    assert(false); // aaah!
}
Exemplo n.º 7
0
signedbv_typet pointer_diff_type()
{
  // The pointer-diff type varies. This is signed int on some systems,
  // and signed long int on others, and signed long long on say Windows.

  if(config.ansi_c.pointer_width==config.ansi_c.int_width)
    return signed_int_type();
  else if(config.ansi_c.pointer_width==config.ansi_c.long_int_width)
    return signed_long_int_type();
  else if(config.ansi_c.pointer_width==config.ansi_c.long_long_int_width)
    return signed_long_long_int_type();
  else
    INVARIANT(false, "width of pointer difference");
}
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:       assert(false); // should always be promoted to int
  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=signed_int_type(); break;
  case UINT:       new_type=unsigned_int_type(); break;
  case LONG:       new_type=signed_long_int_type(); break;
  case ULONG:      new_type=unsigned_long_int_type(); break;
  case LONGLONG:   new_type=signed_long_long_int_type(); break;
  case ULONGLONG:  new_type=unsigned_long_long_int_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 FLOAT128:   new_type=ieee_float_spect::quadruple_precision().to_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)
    do_typecast(expr, new_type);
}
Exemplo n.º 9
0
void c_typecheck_baset::adjust_function_parameter(typet &type) const
{
  if(type.id()==ID_array)
  {
    type.id(ID_pointer);
    type.remove(ID_size);
    type.remove(ID_C_constant);
  }
  else if(type.id()==ID_code)
  {
    // see ISO/IEC 9899:1999 page 199 clause 8
    pointer_typet tmp;
    tmp.subtype()=type;
    type.swap(tmp);
  }
  else if(type.id()==ID_KnR)
  {
    // any KnR args without type yet?
    type=signed_int_type(); // the default is integer!
  }
}
Exemplo n.º 10
0
void cpp_declarator_convertert::main_function_rules(
    const symbolt &symbol)
{
    if(symbol.name==ID_main)
    {
        if(symbol.type.id()!=ID_code)
        {
            cpp_typecheck.err_location(symbol.location);
            throw "main must be function";
        }

        const typet &return_type=
            to_code_type(symbol.type).return_type();

        if(return_type!=signed_int_type())
        {
            // Too many embedded compilers ignore this rule.
            //
            //cpp_typecheck.err_location(symbol.location);
            //throw "main must return int";
        }
    }
}
Exemplo n.º 11
0
void cpp_typecheckt::typecheck_enum_type(typet &type)
{
  // first save qualifiers
  c_qualifierst qualifiers;
  qualifiers.read(type);
  
  cpp_enum_typet &enum_type=to_cpp_enum_type(type);
  bool anonymous=!enum_type.has_tag();
  irep_idt base_name;
  
  if(anonymous)
  {
    // we fabricate a tag based on the enum constants contained
    base_name=enum_type.generate_anon_tag();
  }
  else
  {
    const cpp_namet &tag=enum_type.tag();
    
    if(tag.is_simple_name())
      base_name=tag.get_base_name();
    else
    {
      err_location(type);
      throw "enum tag is expected to be a simple name";
    }
  }

  bool has_body=enum_type.has_body();
  bool tag_only_declaration=enum_type.get_tag_only_declaration();

  cpp_scopet &dest_scope=
    tag_scope(base_name, has_body, tag_only_declaration);

  const irep_idt symbol_name=
    dest_scope.prefix+"tag-"+id2string(base_name);

  // check if we have it
  
  symbol_tablet::symbolst::iterator previous_symbol=
    symbol_table.symbols.find(symbol_name);
    
  if(previous_symbol!=symbol_table.symbols.end())
  {
    // we do!

    symbolt &symbol=previous_symbol->second;

    if(has_body)
    {
      err_location(type);
      str << "error: enum symbol `" << base_name
          << "' declared previously\n";
      str << "location of previous definition: "
          << symbol.location;
      throw 0;
    }
  }
  else if(has_body)
  {
    std::string pretty_name=
      cpp_scopes.current_scope().prefix+id2string(base_name);
      
    // C++11 enumerations have an underlying type,
    // which defaults to int.
    // enums without underlying type may be 'packed'.
    if(type.subtype().is_nil())
      type.subtype()=signed_int_type();
    else
    {
      typecheck_type(type.subtype());
      if(type.subtype().id()==ID_signedbv ||
         type.subtype().id()==ID_unsignedbv)
      {
      }
      else
      {
        err_location(type);
        str << "underlying type must be integral";
        throw 0;
      }
    }

    symbolt symbol;

    symbol.name=symbol_name;
    symbol.base_name=base_name;
    symbol.value.make_nil();
    symbol.location=type.source_location();
    symbol.mode=ID_cpp;
    symbol.module=module;
    symbol.type.swap(type);
    symbol.is_type=true;
    symbol.is_macro=false;
    symbol.pretty_name=pretty_name;
    
    // move early, must be visible before doing body
    symbolt *new_symbol;
    if(symbol_table.move(symbol, new_symbol))
      throw "cpp_typecheckt::typecheck_enum_type: symbol_table.move() failed";    

    // put into scope
    cpp_idt &scope_identifier=
      cpp_scopes.put_into_scope(*new_symbol, dest_scope);
    
    scope_identifier.id_class=cpp_idt::CLASS;

    typecheck_enum_body(*new_symbol);
  }
  else
  {
    err_location(type);
    str << "use of enum `" << base_name
        << "' without previous declaration";
    throw 0;
  }

  // create enum tag expression, and add the qualifiers
  type=c_enum_tag_typet(symbol_name);
  qualifiers.write(type);
}
Exemplo n.º 12
0
void printf_formattert::process_format(std::ostream &out)
{
  exprt tmp;
  format_constantt format_constant;

  format_constant.precision=6;
  format_constant.min_width=0;
  format_constant.zero_padding=false;

  char ch=next();

  if(ch=='0') // leading zeros
  {
    format_constant.zero_padding=true;
    ch=next();
  }

  while(isdigit(ch)) // width
  {
    format_constant.min_width*=10;
    format_constant.min_width+=ch-'0';
    ch=next();
  }

  if(ch=='.') // precision
  {
    format_constant.precision=0;
    ch=next();

    while(isdigit(ch))
    {
      format_constant.precision*=10;
      format_constant.precision+=ch-'0';
      ch=next();
    }
  }

  switch(ch)
  {
  case '%':
    out << ch;
    break;

  case 'e':
  case 'E':
    format_constant.style=format_spect::stylet::SCIENTIFIC;
    if(next_operand==operands.end())
      break;
    out << format_constant(
      make_type(*(next_operand++), double_type()));
    break;

  case 'f':
  case 'F':
    format_constant.style=format_spect::stylet::DECIMAL;
    if(next_operand==operands.end())
      break;
    out << format_constant(
      make_type(*(next_operand++), double_type()));
    break;

  case 'g':
  case 'G':
    format_constant.style=format_spect::stylet::AUTOMATIC;
    if(format_constant.precision==0)
      format_constant.precision=1;
    if(next_operand==operands.end())
      break;
    out << format_constant(
      make_type(*(next_operand++), double_type()));
    break;

  case 's':
    {
      if(next_operand==operands.end())
        break;
      // this is the address of a string
      const exprt &op=*(next_operand++);
      if(op.id()==ID_address_of &&
         op.operands().size()==1 &&
         op.op0().id()==ID_index &&
         op.op0().operands().size()==2 &&
         op.op0().op0().id()==ID_string_constant)
        out << format_constant(op.op0().op0());
    }
    break;

  case 'd':
    if(next_operand==operands.end())
      break;
    out << format_constant(
      make_type(*(next_operand++), signed_int_type()));
    break;

  case 'D':
    if(next_operand==operands.end())
      break;
    out << format_constant(
      make_type(*(next_operand++), signed_long_int_type()));
    break;

  case 'u':
    if(next_operand==operands.end())
      break;
    out << format_constant(
      make_type(*(next_operand++), unsigned_int_type()));
    break;

  case 'U':
    if(next_operand==operands.end())
      break;
    out << format_constant(
      make_type(*(next_operand++), unsigned_long_int_type()));
    break;

  default:
    out << '%' << ch;
  }
}
Exemplo n.º 13
0
typet enum_constant_type()
{
  // usually same as 'int',
  // but might be unsigned, or shorter than 'int'
  return signed_int_type();
}
Exemplo n.º 14
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;
  }
}
Exemplo n.º 15
0
typet get_type(const format_tokent &token)
{
  switch(token.type)
  {
  case format_tokent::INT:
    switch(token.length_modifier)
    {
    case format_tokent::LEN_h:
      if(token.representation==format_tokent::SIGNED_DEC)
        return signed_char_type();
      else
        return unsigned_char_type();

    case format_tokent::LEN_hh:
      if(token.representation==format_tokent::SIGNED_DEC)
        return signed_short_int_type();
      else
        return unsigned_short_int_type();

    case format_tokent::LEN_l:
      if(token.representation==format_tokent::SIGNED_DEC)
        return signed_long_int_type();
      else
        return unsigned_long_int_type();

    case format_tokent::LEN_ll:
      if(token.representation==format_tokent::SIGNED_DEC)
        return signed_long_long_int_type();
      else
        return unsigned_long_long_int_type();

    default:
      if(token.representation==format_tokent::SIGNED_DEC)
        return signed_int_type();
      else
        return unsigned_int_type();
    }

  case format_tokent::FLOAT:
    switch(token.length_modifier)
    {
    case format_tokent::LEN_l: return double_type();
    case format_tokent::LEN_L: return long_double_type();
    default: return float_type();
    }

  case format_tokent::CHAR:
    switch(token.length_modifier)
    {
    case format_tokent::LEN_l: return wchar_t_type();
    default: return char_type();
    }

  case format_tokent::POINTER:
    return pointer_type(void_type());

  case format_tokent::STRING:
    switch(token.length_modifier)
    {
    case format_tokent::LEN_l: return array_typet(wchar_t_type(), nil_exprt());
    default: return array_typet(char_type(), nil_exprt());
    }

  default:
    return nil_typet();
  }
}