@ -668,6 +668,16 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
None )
None )
let get_dictionaryWithObjects_forKeys_count_infos method_pointer =
Option . bind ( CAst_utils . get_decl_opt method_pointer ) ~ f : ( function
| Clang_ast_t . ObjCMethodDecl
( decl_info , { ni_name } , { omdi_parameters = ParmVarDecl ( _ , _ , objects_qual_typ , _ ) :: _ } )
when String . equal ni_name CFrontend_config . dictionaryWithObjects_forKeys_count ->
Some ( decl_info , objects_qual_typ )
| _ ->
None )
let this_expr_trans stmt_info ? class_qual_type trans_state sil_loc =
let this_expr_trans stmt_info ? class_qual_type trans_state sil_loc =
let this_pvar , this_typ = get_this_pvar_typ stmt_info ? class_qual_type trans_state . context in
let this_pvar , this_typ = get_this_pvar_typ stmt_info ? class_qual_type trans_state . context in
let return = ( Exp . Lvar this_pvar , this_typ ) in
let return = ( Exp . Lvar this_pvar , this_typ ) in
@ -2955,9 +2965,122 @@ module CTrans_funct (F : CModule_type.CFrontend) : CModule_type.CTranslation = s
and objCDictionaryLiteral_trans trans_state expr_info stmt_info stmts dict_literal_info =
and objCDictionaryLiteral_trans trans_state expr_info stmt_info stmts dict_literal_info =
let method_pointer = dict_literal_info . Clang_ast_t . odlei_dict_method in
let method_pointer = dict_literal_info . Clang_ast_t . odlei_dict_method in
let stmts = CGeneral_utils . swap_elements_list stmts in
match get_dictionaryWithObjects_forKeys_count_infos method_pointer with
let stmts = stmts @ [ Ast_expressions . create_nil stmt_info ] in
| Some infos ->
objCArrayDictLiteral_trans trans_state expr_info stmt_info stmts method_pointer
objCDictLiteral_dictionaryWithObjects_forKeys_count_trans trans_state expr_info stmt_info
stmts infos method_pointer
| None ->
let stmts = CGeneral_utils . swap_elements_list stmts in
let stmts = stmts @ [ Ast_expressions . create_nil stmt_info ] in
objCArrayDictLiteral_trans trans_state expr_info stmt_info stmts method_pointer
(* * Translates an dictionary literal @ [ @"firstName": @"Foo", @"lastName":@"Bar" ] to
{ [
n $ 1 = NSString . stringWithUTF8 : ( @ " firstName " )
n $ 2 = NSNumber . stringWithUTF8 : ( @ " Foo " )
n $ 3 = NSNumber . stringWithUTF8 : ( @ " lastName " )
n $ 4 = NSNumber . stringWithUTF8 : ( @ " Bar " )
temp1 [ 0 ] : objc_object * = n $ 1
temp1 [ 1 ] : objc_object * = n $ 3
temp2 [ 0 ] : objc_object * = n $ 2
temp2 [ 1 ] : objc_object * = n $ 4
n $ 3 = NSDictionary . dictionaryWithObjects : forKeys : count : ( temp2 : objc_object * const [ 2 * 8 ] ,
temp1 : objc_object * const [ 2 * 8 ] , 2 : int )
] }
where [ temp1 ] [ temp2 ] are additional local variables declared as array . * )
and objCDictLiteral_dictionaryWithObjects_forKeys_count_trans
( { context = { procdesc ; tenv ; translation_unit_context } as context } as trans_state ) expr_info
stmt_info stmts ( decl_info , objects_qual_typ ) method_pointer =
let loc = CLocation . location_of_stmt_info translation_unit_context . source_file stmt_info in
(* 1. Add a temporary local variable for an array *)
let temp1 =
CVar_decl . mk_temp_sil_var procdesc ~ name : " SIL_dictionaryWithObjects_forKeys_count1___ "
in
let temp2 =
CVar_decl . mk_temp_sil_var procdesc ~ name : " SIL_dictionaryWithObjects_forKeys_count2___ "
in
let length = List . length stmts | > IntLit . of_int in
let create_var = function
| temp ->
let array_typ =
match CType_decl . qual_type_to_sil_type tenv objects_qual_typ with
| Typ . { desc = Tptr ( t , _ ) } ->
Typ . mk_array ~ length ~ stride : ( IntLit . of_int 8 ) t
| _ ->
Typ . void_star
in
( Exp . Lvar temp , array_typ )
in
let append_var temp array_typ =
Procdesc . append_locals procdesc
[ { ProcAttributes . name = Pvar . get_name temp
; typ = array_typ
; modify_in_block = false
; is_constexpr = false
; is_declared_unused = false } ]
in
let ( ( temp1_var , array1_typ ) as temp1_with_typ ) = create_var temp1 in
let ( ( temp2_var , array2_typ ) as temp2_with_typ ) = create_var temp2 in
append_var temp1 array1_typ ;
append_var temp2 array2_typ ;
(* 2. Translate array elements *)
let res_trans_elems = List . mapi ~ f : ( exec_instruction_with_trans_state trans_state None ) stmts in
(* 3. Add array initialization ( elements assignments ) *)
let none_id = Ident . create_none () in
let array_init temp_var temp_with_typ idx_mod =
let instrs =
List . mapi res_trans_elems ~ f : ( fun i { return = e , typ } ->
if Int . equal ( i % 2 ) idx_mod then
let idx = Exp . Const ( Cint ( IntLit . of_int ( i / 2 ) ) ) in
[ Sil . Load { id = none_id ; e ; root_typ = typ ; typ ; loc }
; Sil . Store { e1 = Lindex ( temp_var , idx ) ; root_typ = typ ; typ ; e2 = e ; loc } ]
else [] )
| > List . concat
in
mk_trans_result temp_with_typ { empty_control with instrs }
in
let res_trans_array1 = array_init temp1_var temp1_with_typ 1 in
let res_trans_array2 = array_init temp2_var temp2_with_typ 0 in
(* 4. Add a function call. *)
let res_trans_call =
let method_type_no_ref = CType_decl . get_type_from_expr_info expr_info tenv in
let method_type = add_reference_if_glvalue method_type_no_ref expr_info in
let actuals =
[ temp1_with_typ
; temp2_with_typ
; ( Exp . Const ( Cint ( IntLit . div length ( IntLit . of_int 2 ) ) ) , Typ . int ) ]
in
let callee_name , method_call_type =
let typ =
CAst_utils . qual_type_of_decl_ptr
( Option . value_exn decl_info . Clang_ast_t . di_parent_pointer )
in
let obj_c_message_expr_info =
{ Clang_ast_t . omei_selector = CFrontend_config . dictionaryWithObjects_forKeys_count
; omei_receiver_kind = ` Class typ
; omei_is_definition_found = true
; omei_decl_pointer = method_pointer }
in
let callee_ms_opt =
Option . bind method_pointer ~ f : ( fun method_pointer ->
CMethod_trans . method_signature_of_pointer tenv method_pointer )
in
get_callee_objc_method context obj_c_message_expr_info callee_ms_opt actuals
in
let method_sil = Exp . Const ( Cfun callee_name ) in
let call_flags =
{ CallFlags . default with
cf_virtual = CMethod_trans . equal_method_call_type method_call_type CMethod_trans . MCVirtual
}
in
create_call_instr trans_state method_type method_sil actuals loc call_flags
~ is_objc_method : true ~ is_inherited_ctor : false
in
collect_trans_results procdesc ~ return : res_trans_call . return
( res_trans_elems @ [ res_trans_array1 ; res_trans_array2 ; res_trans_call ] )
and objCStringLiteral_trans trans_state stmt_info stmts info =
and objCStringLiteral_trans trans_state stmt_info stmts info =