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(); } }
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); } }
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 } } }
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); }
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! }
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"); }
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); }
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! } }
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"; } } }
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); }
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; } }
typet enum_constant_type() { // usually same as 'int', // but might be unsigned, or shorter than 'int' return signed_int_type(); }
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; } }
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(); } }