diff --git a/convert.ml b/convert.ml index 6196db1ecd893c5de49de38232de2db8ad61a28c..6a3c47a58ee58fcc1bc0c4913c4a163f38afb761 100644 --- a/convert.ml +++ b/convert.ml @@ -570,6 +570,25 @@ let preserved_returned_object aux e = List.map transf aux | _ -> aux +let convert_class_name env name tc = + if Convert_env.is_extern_c_aggregate env name tc then name.decl_name + else + let s, t = Convert_env.typedef_normalize env name tc in + Mangling.mangle s t None + +let qual_vmt_content_name = Cxx_utils.empty_qual "_frama_c_vmt_content" +let qual_vmt_name = Cxx_utils.empty_qual "_frama_c_vmt" + +let mk_vmt_content_type env = + let name, tc = + Convert_env.typedef_normalize env qual_vmt_content_name TStandard + in + Tstruct (convert_class_name env name tc, None, []) + +let mk_vmt_type env = + let name, tc = Convert_env.typedef_normalize env qual_vmt_name TStandard in + Tstruct (convert_class_name env name tc, None, []) + let rec convert_base_type env spec decl typ does_remove_virtual = match typ with | Void -> env, (spec_type Tvoid :: spec, decl) @@ -610,12 +629,7 @@ let rec convert_base_type env spec decl typ does_remove_virtual = in env, (spec_type (Tenum(name,None,[]))::spec, decl) | Struct (s,t) -> - let name = - if Convert_env.is_extern_c_aggregate env s t then s.decl_name - else - let s, t = Convert_env.typedef_normalize env s t in - Mangling.mangle s t None - in + let name = convert_class_name env s t in env, (spec_type (Tstruct (name, None, [])) :: spec, decl) | Union (s,t) -> let name = @@ -837,9 +851,7 @@ and convert_expr_node ?(drop_temp=false) env aux e does_remove_virtual = Cxx_utils.( plain_obj_ptr (unqual_type (Struct (derived_name,td)))) in - let derived_name, td = - Convert_env.typedef_normalize env derived_name td - in + let name = convert_class_name env derived_name td in let init = if not is_reference then e else mk_expr env (UNARY(ADDROF, e)) in @@ -847,9 +859,7 @@ and convert_expr_node ?(drop_temp=false) env aux e does_remove_virtual = add_local_aux_def aux (DECDEF( None, - ([SpecType - (Tstruct - (Mangling.mangle derived_name td None, None, []))], + ([SpecType (Tstruct (name,None,[]))], [(var_name, PTR([], JUSTBASE),[], e.expr_loc), SINGLE_INIT(init)]), e.expr_loc)) in @@ -860,19 +870,14 @@ and convert_expr_node ?(drop_temp=false) env aux e does_remove_virtual = if (noeffect) then access, aux, env else begin let table_access = virtual_var_name () in - let qual_vmt_content_name = Cxx_utils.empty_qual "_frama_c_vmt_content" in let env = Convert_env.add_local_var env table_access Cxx_utils.( plain_obj_ptr ( unqual_type (Struct (qual_vmt_content_name, TStandard)))) in - let qual_vmt_content_name, _ = - Convert_env.typedef_normalize env qual_vmt_content_name TStandard - in let tmp_decl = DECDEF( None, - ([SpecType (Tstruct (Mangling.mangle - qual_vmt_content_name TStandard None, None, []))], + ([SpecType (mk_vmt_content_type env)], [(table_access,PTR( [], JUSTBASE),[],access.expr_loc), SINGLE_INIT (access)]), access.expr_loc) @@ -1006,10 +1011,11 @@ and convert_expr_node ?(drop_temp=false) env aux e does_remove_virtual = env (rt,decl JUSTBASE) (mk_addrof env (mk_expr env (MEMBEROF(e, cname))))) | RPKVirtualBasePointer(base_index, origin_type, noeffect) -> - let derived_name, td = + let derived_name,td = Convert_env.get_class_name_from_pointer env origin_type.plain_type in + let cderived_name= convert_class_name env derived_name td in let var_name = shift_ptr_var_name () in let env = Convert_env.add_local_var @@ -1020,26 +1026,16 @@ and convert_expr_node ?(drop_temp=false) env aux e does_remove_virtual = let def = DECDEF( None, - ([SpecType - (Tstruct - (Mangling.mangle derived_name td None, None, []))], + ([SpecType (Tstruct (cderived_name,None,[]))], [(var_name, PTR([], JUSTBASE),[], e.expr_loc), SINGLE_INIT(e)]), e.expr_loc) in let aux = add_local_aux_def aux def in - let qual_vmt_name = Cxx_utils.empty_qual "_frama_c_vmt" in let this_access, aux, env = create_this_access e origin_type aux env false noeffect in - let qual_vmt_name, _ = - Convert_env.typedef_normalize env qual_vmt_name TStandard - in let vmt_type = - [SpecType - (Tstruct - (Mangling.mangle qual_vmt_name - TStandard None, None, []))], - PTR ([], PTR ([], JUSTBASE)) + [SpecType (mk_vmt_type env)], PTR ([], PTR ([], JUSTBASE)) in let table_access_def = mk_expr env @@ -1075,16 +1071,8 @@ and convert_expr_node ?(drop_temp=false) env aux e does_remove_virtual = create_this_access e origin_type aux env true (* is_reference *) false (* noeffect *) in - let qual_vmt_name = Cxx_utils.empty_qual "_frama_c_vmt" in - let qual_vmt_name,_ = - Convert_env.typedef_normalize env qual_vmt_name TStandard - in let vmt_type = - [SpecType - (Tstruct - (Mangling.mangle - qual_vmt_name TStandard None, None, []))], - PTR ([], PTR ([], JUSTBASE)) + [SpecType (mk_vmt_type env)], PTR ([], PTR ([], JUSTBASE)) in let table_access_def = mk_expr env @@ -1374,7 +1362,6 @@ and convert_expr_node ?(drop_temp=false) env aux e does_remove_virtual = let qual_vmt_content_name = Cxx_utils.empty_qual "_frama_c_vmt_content" in - let qual_vmt_name = Cxx_utils.empty_qual "_frama_c_vmt" in let env = Convert_env.add_local_var env var_name @@ -1401,24 +1388,8 @@ and convert_expr_node ?(drop_temp=false) env aux e does_remove_virtual = ([SpecType Tchar], PTR ([], JUSTBASE)) (List.fold_left shift_expr this shiftPvmt)) in - let qual_vmt_content_name, _ = - Convert_env.typedef_normalize env qual_vmt_content_name TStandard - in - let qual_vmt_name, _ = - Convert_env.typedef_normalize env qual_vmt_name TStandard - in - let vmt_content_base_type = - [SpecType - (Tstruct - (Mangling.mangle qual_vmt_content_name TStandard None, - None, []))] - in - let vmt_base_type = - [SpecType - (Tstruct - (Mangling.mangle qual_vmt_name TStandard None, - None, []))] - in + let vmt_content_base_type = [SpecType (mk_vmt_content_type env)] in + let vmt_base_type = [SpecType (mk_vmt_type env)] in let vmt_access = mk_expr env (UNARY @@ -1470,6 +1441,7 @@ and convert_expr_node ?(drop_temp=false) env aux e does_remove_virtual = let class_name, tc = Convert_env.typedef_normalize env class_name tc in + let cclass_name = convert_class_name env class_name tc in env, add_local_aux_def aux tmp_decl, CALL( mk_expr env @@ -1485,9 +1457,7 @@ and convert_expr_node ?(drop_temp=false) env aux e does_remove_virtual = env (MEMBEROFPTR (mk_var env var_name, "method_ptr"))))), (mk_cast env - ([SpecType - (Tstruct - (Mangling.mangle class_name tc None, None, []))], + ([SpecType (Tstruct (cclass_name, None, []))], PTR ([], JUSTBASE)) (mk_expr env (BINARY @@ -2597,10 +2567,7 @@ let bare_or_derived_type env most_derived n = let make_class_decl env name tkind kind inherits fields body has_virtual = let n, t = Convert_env.typedef_normalize env name tkind in - let class_name = - if Convert_env.is_extern_c env then n.decl_name - else Mangling.mangle n t None - in + let class_name = convert_class_name env name tkind in let loc = Convert_env.get_loc env in let create_class_type base tb = { qualifier = []; plain_type = (Struct (base,tb)) } @@ -2639,14 +2606,11 @@ let make_class_decl env name tkind kind inherits fields body has_virtual = let n, t = Convert_env.typedef_normalize env base tb in let n' = if Class.has_virtual_base_class (base,tb) then bare_qname n else n - in (FIELD - ([SpecType - (Tstruct - (Mangling.mangle n' t None, - None, []))], - [(create_base_field_name env n t, - JUSTBASE, [], loc), - None]), + in + let cname = convert_class_name env n' t in + (FIELD + ([SpecType (Tstruct (cname, None, []))], + [(create_base_field_name env n t, JUSTBASE, [], loc), None]), (create_class_type base tb)) ::result) [] virtual_base_classes @@ -2675,14 +2639,11 @@ let make_class_decl env name tkind kind inherits fields body has_virtual = then bare_qname n else n in + let cname = convert_class_name env n' t in has_virtual, (FIELD - ([SpecType - (Tstruct - (Mangling.mangle n' t None, - None, []))], - [(create_base_field_name env n t, - JUSTBASE, [], loc), + ([SpecType (Tstruct (cname, None, []))], + [(create_base_field_name env n t, JUSTBASE, [], loc), None]), (create_class_type inherits.base inherits.templated_kind)) @@ -2716,7 +2677,7 @@ let make_class_decl env name tkind kind inherits fields body has_virtual = (List.fold_left create_field ([],[]) (List.append fields inherited_fields)) in - let bare = bare_qname name in + let bare = bare_qname n in let env = Convert_env.add_aggregate env bare CClass tkind false in Some bcfields, Convert_env.add_struct env (bare,tkind) bfields_typ @@ -2732,7 +2693,8 @@ let make_class_decl env name tkind kind inherits fields body has_virtual = match bare_fields, kind with | None, _ | Some _, CUnion -> None | Some fields, (CClass | CStruct) -> - Some (Tstruct (Mangling.mangle (bare_qname n) t None, Some fields,[])) + let bare_name = convert_class_name new_env (bare_qname n) t in + Some (Tstruct (bare_name, Some fields,[])) in let bare_class_decl = match bare_type_decl with | None -> None diff --git a/tests/class/extern_c_class.cpp b/tests/class/extern_c_class.cpp index 4af141d8c3daa5144f4c31b05ba9a1f4bb19e94d..14aa138321062005f75db113977d452c1d4d4760 100644 --- a/tests/class/extern_c_class.cpp +++ b/tests/class/extern_c_class.cpp @@ -1,6 +1,7 @@ extern "C"{ class C { - void set(int* t) { *t = get_x(); } + void set(int* t) { *t = get_x(); foo(); } int get_x() { return 0; } + virtual void foo(); }; } diff --git a/tests/class/oracle/extern_c_class.res.oracle b/tests/class/oracle/extern_c_class.res.oracle index ba5027bb2f3823f38afce26d80dafa0b75ca5a7f..900abea7d405005a2a08a4af3b4e6bd23aae9488 100644 --- a/tests/class/oracle/extern_c_class.res.oracle +++ b/tests/class/oracle/extern_c_class.res.oracle @@ -1,9 +1,37 @@ [kernel] Parsing extern_c_class.cpp (external front-end) Now output intermediate result /* Generated by Frama-C */ +struct _frama_c_vmt_content { + void (*method_ptr)() ; + int shift_this ; +}; +struct _frama_c_rtti_name_info_node; +struct _frama_c_vmt { + struct _frama_c_vmt_content *table ; + int table_size ; + struct _frama_c_rtti_name_info_node *rtti_info ; +}; +struct _frama_c_rtti_name_info_content { + struct _frama_c_rtti_name_info_node *value ; + int shift_object ; + int shift_vmt ; +}; +struct _frama_c_rtti_name_info_node { + char const *name ; + struct _frama_c_rtti_name_info_content *base_classes ; + int number_of_base_classes ; + struct _frama_c_vmt *pvmt ; +}; +struct C; struct C { - + struct _frama_c_vmt *pvmt ; }; +struct _frama_c_vmt _frama_c_vmt_header; + +struct _frama_c_rtti_name_info_node _frama_c_rtti_name_info; + +struct _frama_c_vmt_content _frama_c_vmt[1]; + void set(struct C *this, int *t); int get_x(struct C *this); @@ -12,9 +40,240 @@ int get_x(struct C *this); void set(struct C *this, int *t) { *t = get_x(this); + struct _frama_c_vmt_content *__virtual_tmp_0 = + (*((struct _frama_c_vmt **)this))->table + 0; + (*((void (*)(struct C *))__virtual_tmp_0->method_ptr))((struct C *)( + (char *)this - __virtual_tmp_0->shift_this)); return; } +int _frama_c_find_dynamic_cast_aux(struct _frama_c_rtti_name_info_node *target_info, + struct _frama_c_rtti_name_info_content *concrete_base, + int number_of_bases, + int found_shift_object, + int found_shift_vmt, int last_shift_vmt, + int *shift_object, int *distance) +{ + int result = 0; + struct _frama_c_rtti_name_info_content *cursor = concrete_base; + int is_over = 0; + int base_index = 0; + while (base_index < number_of_bases) { + if (cursor->value == target_info) { + if (*distance < 0) goto _LOR; + else + if (*distance >= 1) { + _LOR: + { + if (found_shift_vmt == cursor->shift_vmt) *distance = 0; + else *distance = 1; + *shift_object = found_shift_object - cursor->shift_object; + result = 1; + } + } + } + else + if (cursor->shift_vmt <= found_shift_vmt) { + int tmp_5; + if (base_index < number_of_bases - 1) tmp_5 = (cursor + 1)->shift_vmt > found_shift_vmt; + else { + int tmp_4; + if (last_shift_vmt == -1) tmp_4 = 1; + else + if (found_shift_vmt < last_shift_vmt) tmp_4 = 1; else tmp_4 = 0; + tmp_5 = tmp_4; + } + if (tmp_5) { + int tmp_0; + int tmp; + int local_distance = 0; + int local_shift_object = 0; + if (base_index < number_of_bases - 1) tmp = (cursor + 1)->shift_vmt; + else tmp = last_shift_vmt; + ; + ; + ; + ; + ; + tmp_0 = _frama_c_find_dynamic_cast_aux(target_info, + (cursor->value)->base_classes, + (cursor->value)->number_of_base_classes, + found_shift_object - cursor->shift_object, + found_shift_vmt - cursor->shift_vmt, + tmp,& local_shift_object, + & local_distance); + int local_result = tmp_0; + if (local_result != 0) + if (local_distance >= 0) + if (*distance < 0) goto _LOR_0; + else + if (*distance >= local_distance) { + _LOR_0: + { + result = local_result; + *shift_object = local_shift_object - cursor->shift_object; + *distance = local_distance; + } + } + is_over = 1; + } + else goto _LAND; + } + else { + _LAND: ; + if (*distance < 0) goto _LOR_2; + else + if (*distance >= 1) { + _LOR_2: + { + int tmp_2; + int tmp_1; + int local_distance_0 = 0; + int local_shift_object_0 = 0; + if (base_index < number_of_bases + 1) tmp_1 = (cursor + 1)->shift_vmt; + else tmp_1 = last_shift_vmt; + ; + ; + ; + ; + ; + tmp_2 = _frama_c_find_dynamic_cast_aux(target_info, + (cursor->value)->base_classes, + (cursor->value)->number_of_base_classes, + found_shift_object - cursor->shift_object, + found_shift_vmt - cursor->shift_vmt, + tmp_1, + & local_shift_object_0, + & local_distance_0); + int local_result_0 = tmp_2; + if (local_result_0 != 0) + if (local_distance_0 >= 0) + if (*distance < 0) goto _LOR_1; + else { + int tmp_3; + if (is_over == 0) tmp_3 = local_distance_0; + else tmp_3 = local_distance_0 + 1; + ; + if (*distance > tmp_3) { + _LOR_1: + { + result = local_result_0; + *shift_object = local_shift_object_0 - cursor->shift_object; + *distance = local_distance_0 + 1; + } + } + } + } + } + } + cursor ++; + base_index ++; + } + return result; +} + +int _frama_c_find_dynamic_cast(struct _frama_c_rtti_name_info_node *declared_info, + struct _frama_c_vmt *declared_vmt, + struct _frama_c_rtti_name_info_node *target_info, + int *shift_object) +{ + int __retres; + int shift_vmt; + int elaborated_shift_target; + struct _frama_c_rtti_name_info_content *cursor; + int number_of_bases; + int tmp_0; + struct _frama_c_rtti_name_info_node *concrete_info = + declared_vmt->rtti_info; + int elaborated_shift_vmt = 0; + int elaborated_shift_object = 0; + int cursor_index = 0; + int distance = -1; + if (concrete_info->pvmt > declared_vmt) { + __retres = 0; + goto return_label; + } + else + if (declared_vmt > concrete_info->pvmt + declared_vmt->table_size) { + __retres = 0; + goto return_label; + } + shift_vmt = declared_vmt - concrete_info->pvmt; + if (concrete_info == declared_info) { + *shift_object = 0; + __retres = target_info == declared_info; + goto return_label; + } + if (target_info == concrete_info) elaborated_shift_target = 0; + else elaborated_shift_target = -1; + cursor = concrete_info->base_classes; + number_of_bases = concrete_info->number_of_base_classes; + while (1) { + while (1) { + if (cursor_index < number_of_bases) { + if (! (elaborated_shift_vmt + cursor->shift_vmt < shift_vmt)) + break; + } + else break; + { + struct _frama_c_rtti_name_info_content *tmp; + if (cursor_index < number_of_bases - 1) tmp = cursor + 1; + else tmp = (struct _frama_c_rtti_name_info_content *)0; + struct _frama_c_rtti_name_info_content *next_cursor = tmp; + if (next_cursor != (struct _frama_c_rtti_name_info_content *)0) + if (elaborated_shift_vmt + next_cursor->shift_vmt <= shift_vmt) { + cursor = next_cursor; + cursor_index ++; + } + else break; + else break; + } + } + if (cursor_index < number_of_bases) { + elaborated_shift_vmt += cursor->shift_vmt; + elaborated_shift_object += cursor->shift_object; + if (cursor->value == target_info) elaborated_shift_target = elaborated_shift_object; + if (elaborated_shift_vmt == shift_vmt) + if (cursor->value == declared_info) { + if (elaborated_shift_target >= 0) { + *shift_object = elaborated_shift_target - elaborated_shift_object; + __retres = 1; + goto return_label; + } + break; + } + cursor = (cursor->value)->base_classes; + number_of_bases = (cursor->value)->number_of_base_classes; + cursor_index = 0; + } + if (! (cursor_index < number_of_bases)) break; + } + if (cursor_index >= number_of_bases) { + __retres = 0; + goto return_label; + } + tmp_0 = _frama_c_find_dynamic_cast_aux(target_info, + concrete_info->base_classes, + concrete_info->number_of_base_classes, + elaborated_shift_object,shift_vmt, + -1,shift_object,& distance); + __retres = tmp_0; + return_label: return __retres; +} + +void foo(struct C *this); + +struct _frama_c_vmt_content _frama_c_vmt[1] = + {{.method_ptr = (void (*)())(& foo), .shift_this = 0}}; +struct _frama_c_rtti_name_info_node _frama_c_rtti_name_info = + {.name = "C", + .base_classes = (struct _frama_c_rtti_name_info_content *)0, + .number_of_base_classes = 0, + .pvmt = & _frama_c_vmt_header}; +struct _frama_c_vmt _frama_c_vmt_header = + {.table = _frama_c_vmt, + .table_size = 1, + .rtti_info = & _frama_c_rtti_name_info}; int get_x(struct C *this) { int __retres;