[clang] [2 of 3] Dealing with custom ast expressions and flow of types in the frontend.

Summary:
This is the second of 3 stack diffs to deal with replacing the parser of types.
This diff is about general changes to the frontend to make it cope with the change. There
are two main challenges:
1. We create pieces of ast in ast_expressions, such as getters and setters. For that we create
custom types.
2. We store types in cMethod_signature for parameters and return type of functions. This was
stored as strings, but that means losing the pointer information which is vital to get the
sil types.
So this diff consists mostly of dealing with these challenges. It change the signature of
cMethod_signature and update modules accordingly.
To deal with the custom types, we build methods in ast_expressions for creating those types,
with a custom type pointer, like "internal_typeint". At the beginning of the translation we save
all these custom types in the map from type pointers to sil types that we build as we compute the
types, so that they are available later.
Another custom type that we build is a type of classes or pointer of classes based on the current
class. I found a simple way to deal with it, giving it a pointer "class_name", and then we know
how to translate those. Something I tried is to save the declaration of the current class and pass
that declaration around, but somehow that lead to pref regression, so I removed it in favor of this
more lightweight version.
master
Dulma Rodriguez 9 years ago
parent 8e547d197d
commit 51e0e40bc7

@ -83,34 +83,78 @@ let create_qual_type s = {
qt_type_ptr = Ast_utils.get_invalid_pointer ();
}
let create_pointer_type s =
create_qual_type (s^" *")
let create_qual_type_with_just_pointer pointer =
{
Clang_ast_t.qt_raw = "";
qt_desugared = None;
qt_type_ptr = pointer;
}
let create_int_type () = create_qual_type "int"
let get_constant_qual_type s =
let pointer = CFrontend_config.type_pointer_prefix ^ s in
{
Clang_ast_t.qt_raw = s;
qt_desugared = None;
qt_type_ptr = pointer
}
let create_void_type () = create_qual_type "void *"
(* Whenever new type are added manually to the translation here, *)
(* they should be added to the map in cTypes_decl too!! *)
let create_int_type =
get_constant_qual_type "int"
let create_id_type () = create_qual_type "id"
let create_void_type =
get_constant_qual_type "void"
let create_char_type () = create_qual_type "char *"
let create_void_star_type =
get_constant_qual_type "void *"
(* pointer needs to be set when we start using these, non trivial to do though *)
let create_BOOL_type () = {
Clang_ast_t.qt_raw = "BOOL";
qt_desugared = Some ("signed char");
qt_type_ptr = Ast_utils.get_invalid_pointer ();
}
let create_id_type =
get_constant_qual_type CFrontend_config.id_cl
let create_nsarray_star_type =
get_constant_qual_type (CFrontend_config.nsarray_cl ^ " *")
let create_char_star_type =
get_constant_qual_type "char *"
let create_void_unsigned_long_type () = create_qual_type "void *(unsigned long)"
let create_BOOL_type =
get_constant_qual_type "signed char"
let create_unsigned_long_type () = create_qual_type "unsigned long"
let create_unsigned_long_type =
get_constant_qual_type "unsigned long"
let create_void_void_type () = create_qual_type "void (void *)"
let create_void_unsigned_long_type =
get_constant_qual_type "void *(unsigned long)"
let create_void_void_type =
get_constant_qual_type "void (void *)"
let create_class_type class_name =
{
Clang_ast_t.qt_raw = "";
qt_desugared = None;
qt_type_ptr = "custom_class_name*" ^ class_name;
}
let create_struct_type struct_name =
{
Clang_ast_t.qt_raw = "";
qt_desugared = None;
qt_type_ptr = "custom_struct_name*" ^ struct_name;
}
let create_pointer_type class_type =
{
Clang_ast_t.qt_raw = "";
qt_desugared = None;
qt_type_ptr = "custom_pointer_"^class_type.Clang_ast_t.qt_type_ptr
}
let create_integer_literal stmt_info n =
let stmt_info = dummy_stmt_info () in
let expr_info = {
Clang_ast_t.ei_qual_type = create_int_type ();
Clang_ast_t.ei_qual_type = create_int_type;
ei_value_kind = `RValue;
ei_object_kind = `Ordinary;
} in
@ -123,7 +167,7 @@ let create_integer_literal stmt_info n =
let create_cstyle_cast_expr stmt_info stmts qt =
let expr_info = {
Clang_ast_t.ei_qual_type = create_void_type ();
Clang_ast_t.ei_qual_type = create_void_type;
ei_value_kind = `RValue;
ei_object_kind = `Ordinary;
} in
@ -135,7 +179,7 @@ let create_cstyle_cast_expr stmt_info stmts qt =
let create_parent_expr stmt_info stmts =
let expr_info = {
Clang_ast_t.ei_qual_type = create_void_type ();
Clang_ast_t.ei_qual_type = create_void_type;
ei_value_kind = `RValue;
ei_object_kind = `Ordinary;
} in
@ -155,10 +199,9 @@ let create_implicit_cast_expr stmt_info stmts typ cast_kind =
let create_nil stmt_info =
let integer_literal = create_integer_literal stmt_info "0" in
let cstyle_cast_expr = create_cstyle_cast_expr stmt_info [integer_literal] (create_int_type ()) in
let cstyle_cast_expr = create_cstyle_cast_expr stmt_info [integer_literal] create_int_type in
let paren_expr = create_parent_expr stmt_info [cstyle_cast_expr] in
let implicit_cast_expr = create_implicit_cast_expr stmt_info [paren_expr] (create_id_type ()) `NullToPointer in
implicit_cast_expr
create_implicit_cast_expr stmt_info [paren_expr] create_id_type `NullToPointer
let dummy_stmt () =
let pointer = Ast_utils.get_fresh_pointer () in
@ -201,7 +244,7 @@ let make_obj_c_message_expr_info_instance sel = {
let make_obj_c_message_expr_info_class selector qt = {
Clang_ast_t.omei_selector = selector;
omei_receiver_kind = `Class (create_qual_type qt);
omei_receiver_kind = `Class (create_class_type qt);
omei_is_definition_found = false;
omei_decl_pointer = None (* TODO look into it *)
}
@ -262,7 +305,7 @@ let make_cast_expr qt di decl_ref_expr_info objc_kind =
(* Build AST expression self.field_name as `LValue *)
let make_self_field class_type di qt field_name =
let qt_class = create_qual_type class_type in
let qt_class = create_pointer_type (create_class_type class_type) in
let expr_info = make_expr_info_with_objc_kind qt `ObjCProperty in
let stmt_info = make_stmt_info di in
let cast_exp = make_cast_expr qt_class di (make_decl_ref_expr_info (make_decl_ref_self di.Clang_ast_t.di_pointer qt_class)) `ObjCProperty in
@ -310,7 +353,7 @@ let make_general_expr_info qt vk ok = {
}
let make_ObjCBoolLiteralExpr stmt_info value =
let ei = make_expr_info (create_BOOL_type ()) in
let ei = make_expr_info create_BOOL_type in
Clang_ast_t.ObjCBoolLiteralExpr((fresh_stmt_info stmt_info),[], ei, value)
let make_decl_ref_exp_var (var_name, var_qt, var_ptr) var_kind stmt_info =
@ -354,7 +397,7 @@ let make_next_object_exp stmt_info item items =
Clang_ast_t.DeclRefExpr (stmt_info_var, [], expr_info, decl_ref_expr_info),
var_type
| _ -> assert false in
let message_call = make_message_expr (create_qual_type CFrontend_config.id_cl)
let message_call = make_message_expr create_id_type
CFrontend_config.next_object items stmt_info false in
let boi = { Clang_ast_t.boi_kind = `Assign } in
make_binary_stmt var_decl_ref message_call stmt_info (make_expr_info_with_objc_kind var_type `ObjCProperty) boi
@ -386,7 +429,7 @@ let translate_dispatch_function block_name stmt_info stmt_list ei n =
let block_var_decl = VarDecl(decl_info, block_name_info, ei.ei_qual_type, var_decl_info) in
let decl_stmt = DeclStmt(stmt_info,[], [block_var_decl]) in
let expr_info_call = make_general_expr_info (create_void_type ()) `XValue `Ordinary in
let expr_info_call = make_general_expr_info create_void_type `XValue `Ordinary in
let expr_info_dre = make_expr_info_with_objc_kind qt `Ordinary in
let decl_ref = make_decl_ref_qt `Var stmt_info.si_pointer block_name false qt in
let decl_ref_expr_info = make_decl_ref_expr_info decl_ref in
@ -412,8 +455,7 @@ let build_OpaqueValueExpr si source_expr ei =
let opaque_value_expr_info = { Clang_ast_t.ovei_source_expr = Some source_expr } in
Clang_ast_t.OpaqueValueExpr (si, [], ei, opaque_value_expr_info)
let pseudo_object_qt () =
create_qual_type CFrontend_config.pseudo_object_type
let pseudo_object_qt () = create_class_type CFrontend_config.pseudo_object_type
(* Create expression PseudoObjectExpr for 'o.m' *)
let build_PseudoObjectExpr qt_m o_cast_decl_ref_exp mname =
@ -436,7 +478,7 @@ let build_PseudoObjectExpr qt_m o_cast_decl_ref_exp mname =
let create_call stmt_info decl_pointer function_name qt parameters =
let expr_info_call = {
Clang_ast_t.ei_qual_type = create_void_type ();
Clang_ast_t.ei_qual_type = create_void_type;
ei_value_kind = `XValue;
ei_object_kind = `Ordinary
} in
@ -502,12 +544,15 @@ let translate_block_enumerate block_name stmt_info stmt_list ei =
let build_stop pstop =
match pstop with
| Clang_ast_t.ParmVarDecl (di, name, qt, _) ->
let qt_fun = create_void_unsigned_long_type () in
let qt_fun = create_void_unsigned_long_type in
let type_opt = Some create_BOOL_type in
let parameter = Clang_ast_t.UnaryExprOrTypeTraitExpr
((fresh_stmt_info stmt_info), [],
make_expr_info (create_unsigned_long_type ()),
{ Clang_ast_t.uttei_kind = `SizeOf; Clang_ast_t.uttei_qual_type = Some (create_BOOL_type ()) }) in
let malloc = create_call (fresh_stmt_info stmt_info) di.Clang_ast_t.di_pointer CFrontend_config.malloc qt_fun [parameter] in
make_expr_info create_unsigned_long_type,
{ Clang_ast_t.uttei_kind = `SizeOf; Clang_ast_t.uttei_qual_type = type_opt}) in
let pointer = di.Clang_ast_t.di_pointer in
let stmt_info = fresh_stmt_info stmt_info in
let malloc = create_call stmt_info pointer CFrontend_config.malloc qt_fun [parameter] in
let init_exp = create_implicit_cast_expr (fresh_stmt_info stmt_info) [malloc] qt `BitCast in
make_DeclStmt (fresh_stmt_info stmt_info) di qt name (Some init_exp)
| _ -> assert false in
@ -529,11 +574,11 @@ let translate_block_enumerate block_name stmt_info stmt_list ei =
let free_stop pstop =
match pstop with
| Clang_ast_t.ParmVarDecl (di, name, qt, _) ->
let qt_fun = create_void_void_type () in
let qt_fun = create_void_void_type in
let decl_ref = make_decl_ref_qt `Var di.Clang_ast_t.di_pointer name.Clang_ast_t.ni_name false qt in
let cast = cast_expr decl_ref qt in
let parameter =
create_implicit_cast_expr (fresh_stmt_info stmt_info) [cast] (create_void_type ()) `BitCast in
create_implicit_cast_expr (fresh_stmt_info stmt_info) [cast] create_void_type `BitCast in
create_call (fresh_stmt_info stmt_info) di.Clang_ast_t.di_pointer CFrontend_config.free qt_fun [parameter]
| _ -> assert false in
@ -542,7 +587,8 @@ let translate_block_enumerate block_name stmt_info stmt_list ei =
let idx_decl_stmt, idx_decl_ref_exp, idx_cast, idx_qt = build_idx_decl pidx in
let rhs = build_PseudoObjectExpr idx_qt array_decl_ref_exp CFrontend_config.count in
let lt = { Clang_ast_t.boi_kind = `LT } in
Clang_ast_t.BinaryOperator (fresh_stmt_info stmt_info, [idx_cast; rhs], make_expr_info (create_int_type ()), lt) in
let exp_info = make_expr_info create_int_type in
Clang_ast_t.BinaryOperator (fresh_stmt_info stmt_info, [idx_cast; rhs], exp_info, lt) in
(* idx++ *)
let un_op idx_decl_ref_expr qt_idx =
@ -579,7 +625,7 @@ let translate_block_enumerate block_name stmt_info stmt_list ei =
(* NSArray *objects = a *)
let objects_array_DeclStmt init =
let di = { empty_decl_info with Clang_ast_t.di_pointer = Ast_utils.get_fresh_pointer () } in
let qt = create_qual_type CFrontend_config.ns_array_ptr in
let qt = create_pointer_type (create_class_type CFrontend_config.nsarray_cl) in
(* init should be ImplicitCastExpr of array a *)
let vdi = { empty_var_decl_info with Clang_ast_t.vdi_init_expr = Some (init) } in
let var_decl = Clang_ast_t.VarDecl (di, make_name_decl CFrontend_config.objects, qt, vdi) in
@ -611,12 +657,12 @@ let translate_block_enumerate block_name stmt_info stmt_list ei =
let make_block_call block_qt object_cast idx_cast stop_cast =
let decl_ref = make_decl_ref_invalid `Var block_name false block_qt in
let fun_cast = cast_expr decl_ref block_qt in
let ei_call = make_expr_info (create_void_type ()) in
let ei_call = make_expr_info create_void_type in
Clang_ast_t.CallExpr (fresh_stmt_info stmt_info, [fun_cast; object_cast; idx_cast; stop_cast], ei_call) in
(* build statement "if (stop) break;" *)
let build_if_stop stop_cast =
let bool_qt = create_BOOL_type () in
let bool_qt = create_BOOL_type in
let ei = make_expr_info bool_qt in
let unary_op = Clang_ast_t.UnaryOperator (fresh_stmt_info stmt_info, [stop_cast], ei, { Clang_ast_t.uoi_kind = `Deref; uoi_is_postfix = true }) in
let cond = create_implicit_cast_expr (fresh_stmt_info stmt_info) [unary_op] bool_qt `LValueToRValue in
@ -691,4 +737,5 @@ let create_assume_not_null_call decl_info var_name var_type =
let null_expr = create_integer_literal stmt_info "0" in
let bin_op = make_binary_stmt decl_ref_exp_cast null_expr stmt_info (make_lvalue_obc_prop_expr_info var_type) boi in
let parameters = [bin_op] in
create_call stmt_info var_decl_ptr (Procname.to_string SymExec.ModelBuiltins.__infer_assume) (create_void_type ()) parameters
let procname = Procname.to_string SymExec.ModelBuiltins.__infer_assume in
create_call stmt_info var_decl_ptr procname create_void_type parameters

@ -23,7 +23,33 @@ val dummy_stmt_info : unit -> stmt_info
val create_qual_type : string -> qual_type
val create_pointer_type : string -> qual_type
val create_char_star_type : qual_type
val create_id_type : qual_type
val create_nsarray_star_type : qual_type
val create_void_type : qual_type
val create_int_type : qual_type
val create_void_star_type : qual_type
val create_BOOL_type : qual_type
val create_unsigned_long_type : qual_type
val create_void_unsigned_long_type : qual_type
val create_void_void_type : qual_type
val create_class_type : string -> qual_type
val create_struct_type : string -> qual_type
val create_pointer_type : qual_type -> qual_type
val create_qual_type_with_just_pointer : Clang_ast_t.pointer -> qual_type
val make_objc_ivar_decl : decl_info -> qual_type -> obj_c_property_impl_decl_info -> string -> decl
@ -51,8 +77,6 @@ val create_nil : stmt_info -> stmt
val create_implicit_cast_expr : stmt_info -> stmt list -> qual_type -> cast_kind -> stmt
val create_char_type : unit -> qual_type
val make_message_expr : qual_type -> string -> stmt -> stmt_info -> bool -> stmt
val make_compound_stmt : stmt list -> stmt_info -> stmt

@ -287,9 +287,6 @@ let curr_class_hash curr_class =
| ContextProtocol name -> Hashtbl.hash name
| ContextNoCls -> Hashtbl.hash "no class"
let get_qt_curr_class curr_class =
(get_curr_class_name curr_class)^" *"
let get_captured_vars context = context.captured_vars
let create_curr_class tenv class_name =

@ -58,8 +58,6 @@ val get_curr_class : t -> curr_class
val get_curr_class_name : curr_class -> string
val get_qt_curr_class : curr_class -> string
val curr_class_to_string : curr_class -> string
val curr_class_compare : curr_class -> curr_class -> int

@ -161,3 +161,7 @@ let strong_attribtue = "__strong"
let unsafe_unretained_attribute = "__unsafe_unretained"
let autoreleasing_atribute = "__autoreleasing"
let type_pointer_prefix = "internal_type"
let nsarray_cl = "NSArray"

@ -158,3 +158,7 @@ val strong_attribtue : string
val unsafe_unretained_attribute : string
val autoreleasing_atribute : string
val type_pointer_prefix : string
val nsarray_cl : string

@ -12,8 +12,8 @@
type method_signature = {
_name : Procname.t;
_args : (string * string * Clang_ast_t.stmt option) list; (* (name, type, default value) *)
_ret_type : string;
_args : (string * Clang_ast_t.qual_type * Clang_ast_t.stmt option) list;
_ret_type : Clang_ast_t.qual_type;
_attributes : Clang_ast_t.attribute list;
_loc : Clang_ast_t.source_range;
_is_instance : bool;
@ -58,5 +58,8 @@ let replace_name_ms ms name =
let ms_to_string ms =
let gen = if ms._is_generated then " (generated)" else "" in
"Method " ^ (Procname.to_string ms._name) ^ gen ^ " " ^
(Utils.list_to_string (fun (s1, s2, _) -> s1^", "^s2) ms._args)^"->"^ms._ret_type^" "^
Utils.list_to_string
(fun (s1, s2, _) -> s1 ^ ", " ^ (Clang_ast_j.string_of_qual_type s2))
ms._args
^ "->" ^ (Clang_ast_j.string_of_qual_type ms._ret_type) ^ " " ^
Clang_ast_j.string_of_source_range ms._loc

@ -14,9 +14,10 @@ type method_signature
val ms_get_name : method_signature -> Procname.t
val ms_get_args : method_signature -> (string * string * Clang_ast_t.stmt option) list
val ms_get_args : method_signature ->
(string * Clang_ast_t.qual_type * Clang_ast_t.stmt option) list
val ms_get_ret_type : method_signature -> string
val ms_get_ret_type : method_signature -> Clang_ast_t.qual_type
val ms_get_attributes : method_signature -> Clang_ast_t.attribute list
@ -24,8 +25,9 @@ val ms_get_loc : method_signature -> Clang_ast_t.source_range
val ms_is_instance : method_signature -> bool
val make_ms : Procname.t -> (string * string * Clang_ast_t.stmt option) list -> string -> Clang_ast_t.attribute list ->
Clang_ast_t.source_range -> bool -> bool -> method_signature
val make_ms : Procname.t -> (string * Clang_ast_t.qual_type * Clang_ast_t.stmt option) list ->
Clang_ast_t.qual_type -> Clang_ast_t.attribute list -> Clang_ast_t.source_range -> bool -> bool ->
method_signature
val replace_name_ms : method_signature -> Procname.t -> method_signature

@ -28,10 +28,10 @@ type method_call_type =
| MCStatic
type function_method_decl_info =
| Func_decl_info of Clang_ast_t.function_decl_info * string
| Cpp_Meth_decl_info of Clang_ast_t.function_decl_info * string (* class_name *) * string (* ret_type *)
| Func_decl_info of Clang_ast_t.function_decl_info * Clang_ast_t.qual_type
| Cpp_Meth_decl_info of Clang_ast_t.function_decl_info * string * Clang_ast_t.qual_type
| ObjC_Meth_decl_info of Clang_ast_t.obj_c_method_decl_info * string
| Block_decl_info of Clang_ast_t.block_decl_info * string
| Block_decl_info of Clang_ast_t.block_decl_info * Clang_ast_t.qual_type
let is_instance_method function_method_decl_info is_instance =
match function_method_decl_info with
@ -44,8 +44,12 @@ let is_instance_method function_method_decl_info is_instance =
let get_class_param function_method_decl_info =
if (is_instance_method function_method_decl_info false) then
match function_method_decl_info with
| Cpp_Meth_decl_info (_, class_name, _) -> [(CFrontend_config.this, class_name, None)]
| ObjC_Meth_decl_info (_, class_name) -> [(CFrontend_config.self, class_name, None)]
| Cpp_Meth_decl_info (_, class_name, _) ->
let class_type = Ast_expressions.create_struct_type class_name in
[(CFrontend_config.this, class_type, None)]
| ObjC_Meth_decl_info (_, class_name) ->
let class_type = Ast_expressions.create_class_type class_name in
[(CFrontend_config.self, class_type, None)]
| _ -> []
else []
@ -61,9 +65,7 @@ let get_parameters function_method_decl_info =
match par with
| Clang_ast_t.ParmVarDecl (decl_info, name_info, qtype, var_decl_info) ->
let name = name_info.Clang_ast_t.ni_name in
Printing.log_out "Adding param '%s' " name;
Printing.log_out "with pointer %s@." decl_info.Clang_ast_t.di_pointer;
(name, CTypes.get_type qtype, var_decl_info.Clang_ast_t.vdi_init_expr)
(name, qtype, var_decl_info.Clang_ast_t.vdi_init_expr)
| _ -> assert false in
let pars = list_map par_to_ms_par (get_param_decls function_method_decl_info) in
@ -73,10 +75,9 @@ let get_return_type function_method_decl_info =
match function_method_decl_info with
| Func_decl_info (_, typ)
| Cpp_Meth_decl_info (_, _, typ)
| Block_decl_info (_, typ) -> typ
| ObjC_Meth_decl_info (method_decl_info, _) ->
let qt = method_decl_info.Clang_ast_t.omdi_result_type in
CTypes.get_type qt
| Block_decl_info (_, typ) ->
Ast_expressions.create_qual_type_with_just_pointer (CTypes.return_type_of_function_type typ)
| ObjC_Meth_decl_info (method_decl_info, _) -> method_decl_info.Clang_ast_t.omdi_result_type
let build_method_signature decl_info procname function_method_decl_info is_instance is_anonym_block is_generated =
let source_range = decl_info.Clang_ast_t.di_source_range in
@ -91,7 +92,7 @@ let method_signature_of_decl class_name_opt meth_decl block_data_opt =
match meth_decl, block_data_opt, class_name_opt with
| FunctionDecl (decl_info, name_info, qt, fdi), _, _ ->
let name = name_info.ni_name in
let func_decl = Func_decl_info (fdi, CTypes.get_type qt) in
let func_decl = Func_decl_info (fdi, qt) in
let procname = General_utils.mk_procname_from_function name (CTypes.get_type qt) in
let ms = build_method_signature decl_info procname func_decl false false false in
ms, fdi.Clang_ast_t.fdi_body, fdi.Clang_ast_t.fdi_parameters
@ -99,7 +100,7 @@ let method_signature_of_decl class_name_opt meth_decl block_data_opt =
let method_name = name_info.Clang_ast_t.ni_name in
let typ = CTypes.get_type qt in
let procname = General_utils.mk_procname_from_cpp_method class_name method_name typ in
let method_decl = Cpp_Meth_decl_info (fdi, class_name, typ) in
let method_decl = Cpp_Meth_decl_info (fdi, class_name, qt) in
let ms = build_method_signature decl_info procname method_decl false false false in
ms, fdi.Clang_ast_t.fdi_body, fdi.Clang_ast_t.fdi_parameters
| ObjCMethodDecl (decl_info, name_info, mdi), _, Some class_name ->
@ -113,7 +114,7 @@ let method_signature_of_decl class_name_opt meth_decl block_data_opt =
ms, mdi.omdi_body, mdi.omdi_parameters
| BlockDecl (decl_info, decl_list, decl_context_info, bdi),
Some (qt, is_instance, procname, _, _), _ ->
let func_decl = Block_decl_info (bdi, CTypes.get_type qt) in
let func_decl = Block_decl_info (bdi, qt) in
let ms = build_method_signature decl_info procname func_decl is_instance true false in
ms, bdi.bdi_body, bdi.bdi_parameters
| _ -> raise Invalid_declaration
@ -151,7 +152,9 @@ let get_class_selector_instance context obj_c_message_expr_info act_params =
let selector = obj_c_message_expr_info.Clang_ast_t.omei_selector in
let pointer = obj_c_message_expr_info.Clang_ast_t.omei_decl_pointer in
match obj_c_message_expr_info.Clang_ast_t.omei_receiver_kind with
| `Class qt -> (CTypes.get_type qt, selector, pointer, MCStatic)
| `Class qt ->
let sil_type = CTypes_decl.qual_type_to_sil_type context.CContext.tenv qt in
((CTypes.classname_of_type sil_type), selector, pointer, MCStatic)
| `Instance ->
(match act_params with
| (instance_obj, Sil.Tptr(t, _)):: _
@ -173,7 +176,7 @@ let get_formal_parameters tenv ms =
let qt =
if (name = CFrontend_config.self && CMethod_signature.ms_is_instance ms) then
(Ast_expressions.create_pointer_type raw_type)
else Ast_expressions.create_qual_type raw_type in
else raw_type in
let typ = CTypes_decl.qual_type_to_sil_type tenv qt in
(name, typ):: defined_parameters pl' in
defined_parameters (CMethod_signature.ms_get_args ms)
@ -208,9 +211,8 @@ let captured_vars_from_block_info context cvl =
list_flatten (f cvl)
let get_return_type tenv ms =
let qt = CMethod_signature.ms_get_ret_type ms in
CTypes_decl.qual_type_to_sil_type tenv
(Ast_expressions.create_qual_type (CTypes.get_function_return_type qt))
let return_type = CMethod_signature.ms_get_ret_type ms in
CTypes_decl.qual_type_to_sil_type tenv return_type
let sil_func_attributes_of_attributes attrs =
let rec do_translation acc al = match al with

@ -184,8 +184,9 @@ struct
f trans_state stmt
with Self.SelfClassException class_name ->
let typ = CTypes_decl.type_name_to_sil_type trans_state.context.CContext.tenv class_name in
let expanded_type = CTypes.expand_structured_type trans_state.context.CContext.tenv typ in
{ empty_res_trans with
exps = [(Sil.Sizeof(typ, Sil.Subtype.exact), Sil.Tint Sil.IULong)] }
exps = [(Sil.Sizeof(expanded_type, Sil.Subtype.exact), Sil.Tint Sil.IULong)] }
(* Execute translation of e forcing to release priority (if it's not free) and then setting it back.*)
(* This is used in conditional operators where we need to force the priority to be free for the *)
@ -320,11 +321,10 @@ struct
if CTrans_models.is_modeled_builtin name then ("infer" ^ name)
else name in
let qt = CTypes.get_raw_qual_type_decl_ref_exp_info decl_ref_expr_info in
let pname, type_opt =
let pname =
match qt with
| Some v ->
(General_utils.mk_procname_from_function name v, CTypes_decl.parse_func_type name v)
| None -> (Procname.from_string_c_fun name, None) in
| Some v -> General_utils.mk_procname_from_function name v
| None -> Procname.from_string_c_fun name in
CMethod_trans.create_procdesc_with_pointer context (Some pointer) pname;
let address_of_function = not context.CContext.is_callee_expression in
(* If we are not translating a callee expression, then the address of the function is being taken.*)
@ -1541,7 +1541,7 @@ struct
"WARNING: in MemberExpr we expect the translation of the stmt to return an expression\n" in
let class_typ =
(match class_typ with
| Sil.Tptr (t, _) -> CTypes_decl.expand_structured_type trans_state.context.CContext.tenv t
| Sil.Tptr (t, _) -> CTypes.expand_structured_type trans_state.context.CContext.tenv t
| t -> t) in
match decl_ref.Clang_ast_t.dr_kind with
| `Field | `ObjCIvar ->
@ -1552,7 +1552,12 @@ struct
let tenv = trans_state.context.CContext.tenv in
(match ObjcInterface_decl.find_field tenv field_name (Some class_typ) false with
| Some (fn, _, _) -> Sil.Lfield (obj_sil, fn, class_typ)
| None -> assert false) in
| None ->
let class_name = CTypes.classname_of_type class_typ in
let default_name = (General_utils.mk_class_field_name class_name field_name) in
Printing.log_out "Warning: Field not found %s in class %s " field_name
(Sil.typ_to_string class_typ);
Sil.Lfield (obj_sil, default_name, class_typ)) in
{ result_trans_exp_stmt with
exps = [(exp, field_typ)] }
| `CXXMethod ->
@ -1685,7 +1690,7 @@ struct
and objCStringLiteral_trans trans_state stmt_info stmts info =
let stmts = [Ast_expressions.create_implicit_cast_expr stmt_info stmts
(Ast_expressions.create_char_type ()) `ArrayToPointerDecay] in
Ast_expressions.create_char_star_type `ArrayToPointerDecay] in
let typ = CTypes_decl.class_from_pointer_type trans_state.context.CContext.tenv info.Clang_ast_t.ei_qual_type in
let obj_c_message_expr_info =
Ast_expressions.make_obj_c_message_expr_info_class CFrontend_config.string_with_utf8_m typ in

@ -135,14 +135,15 @@ let get_predefined_ms_stringWithUTF8String class_name method_name mk_procname =
let condition =
class_name = CFrontend_config.nsstring_cl
&& method_name = CFrontend_config.string_with_utf8_m in
let id_type = Ast_expressions.create_id_type in
get_predefined_ms_method condition class_name method_name Procname.Class_objc_method
mk_procname [("x", "char *", None)] CFrontend_config.id_cl [] None
mk_procname [("x", Ast_expressions.create_char_star_type, None)] id_type [] None
let get_predefined_ms_retain_release class_name method_name mk_procname =
let condition = is_retain_or_release method_name in
let return_type =
if is_retain_method method_name || is_autorelease_method method_name
then CFrontend_config.id_cl else CFrontend_config.void in
then Ast_expressions.create_id_type else Ast_expressions.create_void_type in
get_predefined_ms_method condition CFrontend_config.nsobject_cl method_name Procname.Instance_objc_method
mk_procname [(CFrontend_config.self, class_name, None)] return_type [] (get_builtinname method_name)
@ -150,22 +151,25 @@ let get_predefined_ms_autoreleasepool_init class_name method_name mk_procname =
let condition =
method_name = CFrontend_config.init
&& class_name = CFrontend_config.nsautorelease_pool_cl in
let class_type = Ast_expressions.create_class_type class_name in
get_predefined_ms_method condition class_name method_name Procname.Instance_objc_method
mk_procname [(CFrontend_config.self, class_name, None)] CFrontend_config.void [] None
mk_procname [(CFrontend_config.self, class_type, None)] Ast_expressions.create_void_type [] None
let get_predefined_ms_nsautoreleasepool_release class_name method_name mk_procname =
let condition =
(method_name = CFrontend_config.release || method_name = CFrontend_config.drain)
&& class_name = CFrontend_config.nsautorelease_pool_cl in
let class_type = Ast_expressions.create_class_type class_name in
get_predefined_ms_method condition class_name method_name Procname.Instance_objc_method
mk_procname [(CFrontend_config.self, class_name, None)]
CFrontend_config.void [] (Some SymExec.ModelBuiltins.__objc_release_autorelease_pool)
mk_procname [(CFrontend_config.self, class_type, None)]
Ast_expressions.create_void_type [] (Some SymExec.ModelBuiltins.__objc_release_autorelease_pool)
let get_predefined_model_method_signature class_name method_name mk_procname =
match get_predefined_ms_nsautoreleasepool_release class_name method_name mk_procname with
| Some ms -> Some ms
| None ->
match get_predefined_ms_retain_release class_name method_name mk_procname with
let class_type = Ast_expressions.create_class_type class_name in
match get_predefined_ms_retain_release class_type method_name mk_procname with
| Some ms -> Some ms
| None ->
match get_predefined_ms_stringWithUTF8String class_name method_name mk_procname with

@ -278,8 +278,9 @@ let create_alloc_instrs context sil_loc function_type fname =
| Sil.Tptr (styp, Sil.Pk_objc_weak)
| Sil.Tptr (styp, Sil.Pk_objc_unsafe_unretained)
| Sil.Tptr (styp, Sil.Pk_objc_autoreleasing) ->
function_type, CTypes_decl.expand_structured_type context.CContext.tenv styp
function_type, styp
| _ -> Sil.Tptr (function_type, Sil.Pk_pointer), function_type in
let function_type_np = CTypes.expand_structured_type context.CContext.tenv function_type_np in
let sizeof_exp = Sil.Sizeof (function_type_np, Sil.Subtype.exact) in
let exp = (sizeof_exp, Sil.Tint Sil.IULong) in
let ret_id = Ident.create_fresh Ident.knormal in
@ -333,8 +334,8 @@ let cpp_new_trans trans_state sil_loc stmt_info function_type =
let create_cast_instrs context exp cast_from_typ cast_to_typ sil_loc =
let ret_id = Ident.create_fresh Ident.knormal in
let cast_typ_no_pointer =
CTypes_decl.expand_structured_type context.CContext.tenv (CTypes.remove_pointer_to_typ cast_to_typ) in
let typ = CTypes.remove_pointer_to_typ cast_to_typ in
let cast_typ_no_pointer = CTypes.expand_structured_type context.CContext.tenv typ in
let sizeof_exp = Sil.Sizeof (cast_typ_no_pointer, Sil.Subtype.exact) in
let pname = SymExec.ModelBuiltins.__objc_cast in
let args = [(exp, cast_from_typ); (sizeof_exp, Sil.Tint Sil.IULong)] in

@ -13,20 +13,6 @@ open Utils
open CFrontend_utils
module L = Logging
let get_function_return_type s =
let regexp = Str.regexp_string " (" in
let matches = try let _ = Str.search_forward regexp s 0 in true with Not_found -> false in
let regexp' =
if matches then regexp
else Str.regexp_string "(" in (* match e.g. "char *()" *)
let buf = Str.split regexp' s in
match buf with
| ret:: _ ->
let ret'= String.trim ret in
Printing.log_out "return type ='%s'@." ret';
ret'
| _ -> assert false
let get_type qt =
match qt.Clang_ast_t.qt_desugared with
| Some t -> t

@ -23,8 +23,6 @@ val search_enum_type_by_name : Sil.tenv -> string -> Sil.const option
val classname_of_type : Sil.typ -> string
val get_function_return_type : string -> string
val mk_classname : string -> Sil.typename
val mk_structname : string -> Sil.typename

@ -15,26 +15,57 @@ open CFrontend_utils
module L = Logging
exception Typename_not_found
(* Adds the predefined types objc_class which is a struct, and Class, *)
(* which is a pointer to objc_class. *)
let add_predefined_types tenv =
let add_predefined_objc_types tenv =
let objc_class_mangled = Mangled.from_string CFrontend_config.objc_class in
let objc_class_name = Sil.TN_csu (Sil.Class, objc_class_mangled) in
let objc_class_type_info =
Sil.Tstruct ([], [], Sil.Struct,
Some (Mangled.from_string CFrontend_config.objc_class), [], [], []) in
Sil.tenv_add tenv objc_class_name objc_class_type_info;
let mn = Mangled.from_string CFrontend_config.class_type in
let class_typename = Sil.TN_typedef(mn) in
let class_typ = Sil.Tptr ((Sil.Tvar
(Sil.TN_csu (Sil.Struct, objc_class_mangled))), Sil.Pk_pointer) in
let class_typename = CType_to_sil_type.get_builtin_objc_typename `ObjCClass in
let class_typ = Sil.Tvar (Sil.TN_csu (Sil.Struct, objc_class_mangled)) in
Sil.tenv_add tenv class_typename class_typ;
let typename_objc_object =
Sil.TN_csu (Sil.Struct, Mangled.from_string CFrontend_config.objc_object) in
let id_typedef = Sil.Tptr (Sil.Tvar (typename_objc_object), Sil.Pk_pointer) in
let id_typename = Sil.TN_typedef (Mangled.from_string CFrontend_config.id_cl) in
let id_typedef = Sil.Tvar (typename_objc_object) in
let id_typename = CType_to_sil_type.get_builtin_objc_typename `ObjCId in
Sil.tenv_add tenv id_typename id_typedef
(* Whenever new type are added manually to the translation in ast_expressions, *)
(* they should be added here too!! *)
let add_predefined_basic_types tenv =
let open Ast_expressions in
let open Clang_ast_t in
let add_basic_type qt basic_type_kind =
let sil_type = CType_to_sil_type.sil_type_of_builtin_type_kind basic_type_kind in
Ast_utils.update_sil_types_map qt.Clang_ast_t.qt_type_ptr sil_type in
let add_pointer_type qt sil_type =
let pointer_type = CTypes.add_pointer_to_typ sil_type in
Ast_utils.update_sil_types_map qt.Clang_ast_t.qt_type_ptr pointer_type in
let add_function_type qt return_type =
(* We translate function types as the return type of the function *)
Ast_utils.update_sil_types_map qt.Clang_ast_t.qt_type_ptr return_type in
let sil_void_type = CType_to_sil_type.sil_type_of_builtin_type_kind `Void in
let sil_char_type = CType_to_sil_type.sil_type_of_builtin_type_kind `Char_S in
let sil_nsarray_type = Sil.Tvar (CTypes.mk_classname CFrontend_config.nsarray_cl) in
let sil_id_type = CType_to_sil_type.get_builtin_objc_type `ObjCId in
add_basic_type create_int_type `Int;
add_basic_type create_void_type `Void;
add_basic_type create_char_star_type `Char_S;
add_basic_type create_BOOL_type `SChar;
add_basic_type create_unsigned_long_type `ULong;
add_pointer_type create_void_star_type sil_void_type;
add_pointer_type create_char_star_type sil_char_type;
add_pointer_type create_char_star_type sil_char_type;
add_pointer_type create_nsarray_star_type sil_nsarray_type;
add_pointer_type create_id_type sil_id_type;
add_function_type create_void_unsigned_long_type sil_void_type;
add_function_type create_void_void_type sil_void_type
let add_predefined_types tenv =
add_predefined_objc_types tenv;
add_predefined_basic_types tenv
let rec search_for_named_type tenv typ =
let search typename =
match typename with

@ -270,8 +270,9 @@ let make_getter curr_class prop_name prop_type =
match getter with
| Some (ObjCMethodDecl(di, name_info, mdi), _) ->
let dummy_info = Ast_expressions.dummy_decl_info_in_curr_file di in
let class_name = CContext.get_curr_class_name curr_class in
let deref_self_field = Ast_expressions.make_deref_self_field
(CContext.get_qt_curr_class curr_class) dummy_info mdi.Clang_ast_t.omdi_result_type ivar_name in
class_name dummy_info mdi.Clang_ast_t.omdi_result_type ivar_name in
let body = ReturnStmt(Ast_expressions.make_stmt_info dummy_info, [deref_self_field]) in
let mdi'= Ast_expressions.make_method_decl_info mdi body in
let generated_name_info = create_generated_method_name name_info in
@ -302,7 +303,7 @@ let make_setter curr_class prop_name prop_type =
let stmt_info = Ast_expressions.make_stmt_info dummy_info in
let rhs_exp = Ast_expressions.make_cast_expr qt_param di decl_ref_expr_info' `ObjCProperty in
let lhs_exp = Ast_expressions.make_self_field
(CContext.get_qt_curr_class curr_class) di qt_param ivar_name in
(CContext.get_curr_class_name curr_class) di qt_param ivar_name in
let boi = { Clang_ast_t.boi_kind = `Assign } in
let setter = Ast_expressions.make_binary_stmt lhs_exp rhs_exp stmt_info expr_info boi in
let memory_management_attribute = (get_memory_management_attribute attributes) in

Loading…
Cancel
Save