[clang cleanup] Split CFrontend_utils module into CAst_utils and CGeneral_utils

Summary:
Module CFrontend_utils is a container for two modules: Ast_utils and General_utils.
Instead of opening CFrontend_utils in several places, it is now split into two separate modules CAst_utils and CGeneral_utils, which are now accessed directly.

Reviewed By: jberdine

Differential Revision: D4392710

fbshipit-source-id: ea756a2
master
Cristiano Calcagno 8 years ago committed by Facebook Github Bot
parent 2a4b29fedb
commit f605cb4b7e

@ -11,7 +11,6 @@ open! IStd
(** Utility module for retrieving types *)
open CFrontend_utils
module L = Logging
let add_pointer_to_typ typ =
@ -43,7 +42,7 @@ let is_class typ =
let rec return_type_of_function_type_ptr type_ptr =
let open Clang_ast_t in
match Ast_utils.get_type type_ptr with
match CAst_utils.get_type type_ptr with
| Some FunctionProtoType (_, function_type_info, _)
| Some FunctionNoProtoType (_, function_type_info) ->
function_type_info.Clang_ast_t.fti_return_type
@ -63,12 +62,12 @@ let return_type_of_function_type tp =
let is_block_type tp =
let open Clang_ast_t in
match Ast_utils.get_desugared_type tp with
match CAst_utils.get_desugared_type tp with
| Some BlockPointerType _ -> true
| _ -> false
let is_reference_type tp =
match Ast_utils.get_desugared_type tp with
match CAst_utils.get_desugared_type tp with
| Some Clang_ast_t.LValueReferenceType _ -> true
| Some Clang_ast_t.RValueReferenceType _ -> true
| _ -> false

@ -11,8 +11,6 @@ open! IStd
(** Processes types and record declarations by adding them to the tenv *)
open CFrontend_utils
module L = Logging
let add_predefined_objc_types tenv =
@ -25,13 +23,13 @@ let add_predefined_basic_types () =
let open Ast_expressions in
let add_basic_type tp 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 tp sil_type in
CAst_utils.update_sil_types_map tp sil_type in
let add_pointer_type tp sil_type =
let pointer_type = CType.add_pointer_to_typ sil_type in
Ast_utils.update_sil_types_map tp pointer_type in
CAst_utils.update_sil_types_map tp pointer_type in
let add_function_type tp return_type =
(* We translate function types as the return type of the function *)
Ast_utils.update_sil_types_map tp return_type in
CAst_utils.update_sil_types_map tp 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 = Typ.Tstruct (CType.mk_classname CFrontend_config.nsarray_cl Csu.Objc) in
@ -75,7 +73,7 @@ let get_record_name_csu decl =
(* types that have methods. And in C++ struct/class/union can have methods *)
name_info, Csu.Class Csu.CPP
| _-> assert false in
let name = Ast_utils.get_qualified_name name_info in
let name = CAst_utils.get_qualified_name name_info in
csu, name
let get_record_name decl = snd (get_record_name_csu decl)
@ -88,9 +86,9 @@ let get_class_methods class_name decl_list =
| Clang_ast_t.CXXDestructorDecl (_, name_info, _, fdi, mdi) ->
let method_name = name_info.Clang_ast_t.ni_name in
Logging.out_debug " ...Declaring method '%s'.\n" method_name;
let mangled = General_utils.get_mangled_method_name fdi mdi in
let mangled = CGeneral_utils.get_mangled_method_name fdi mdi in
let procname =
General_utils.mk_procname_from_cpp_method class_name method_name ~meth_decl mangled in
CGeneral_utils.mk_procname_from_cpp_method class_name method_name ~meth_decl mangled in
Some procname
| _ -> None in
(* poor mans list_filter_map *)
@ -103,7 +101,7 @@ let get_superclass_decls decl =
| ClassTemplateSpecializationDecl (_, _, _, _, _, _, _, cxx_rec_info, _) ->
(* there is no concept of virtual inheritance in the backend right now *)
let base_ptr = cxx_rec_info.Clang_ast_t.xrdi_bases @ cxx_rec_info.Clang_ast_t.xrdi_vbases in
let get_decl_or_fail typ_ptr = match Ast_utils.get_decl_from_typ_ptr typ_ptr with
let get_decl_or_fail typ_ptr = match CAst_utils.get_decl_from_typ_ptr typ_ptr with
| Some decl -> decl
| None -> assert false in
IList.map get_decl_or_fail base_ptr
@ -120,9 +118,9 @@ let get_superclass_list_cpp decl =
let get_translate_as_friend_decl decl_list =
let is_translate_as_friend_name (_, name_info) =
let translate_as_str = "infer_traits::TranslateAsType" in
String.is_substring ~substring:translate_as_str (Ast_utils.get_qualified_name name_info) in
String.is_substring ~substring:translate_as_str (CAst_utils.get_qualified_name name_info) in
let get_friend_decl_opt (decl : Clang_ast_t.decl) = match decl with
| FriendDecl (_, `Type type_ptr) -> Ast_utils.get_decl_from_typ_ptr type_ptr
| FriendDecl (_, `Type type_ptr) -> CAst_utils.get_decl_from_typ_ptr type_ptr
| _ -> None in
let is_translate_as_friend_decl decl =
match get_friend_decl_opt decl with
@ -145,7 +143,7 @@ let rec get_struct_fields tenv decl =
| _ -> [] in
let do_one_decl decl = match decl with
| FieldDecl (_, name_info, qt, _) ->
let id = General_utils.mk_class_field_name name_info in
let id = CGeneral_utils.mk_class_field_name name_info in
let typ = type_ptr_to_sil_type tenv qt.Clang_ast_t.qt_type_ptr in
let annotation_items = [] in (* For the moment we don't use them*)
[(id, typ, annotation_items)]
@ -185,15 +183,15 @@ and get_record_declaration_struct_type tenv decl =
if csu = Csu.Class Csu.CPP then Annot.Class.cpp
else Annot.Item.empty (* No annotations for structs *) in
if is_complete_definition then (
Ast_utils.update_sil_types_map type_ptr (Typ.Tstruct sil_typename);
CAst_utils.update_sil_types_map type_ptr (Typ.Tstruct sil_typename);
let non_statics = get_struct_fields tenv decl in
let fields = General_utils.append_no_duplicates_fields non_statics extra_fields in
let fields = CGeneral_utils.append_no_duplicates_fields non_statics extra_fields in
let statics = [] in (* Note: We treat static field same as global variables *)
let methods = get_class_methods name decl_list in (* C++ methods only *)
let supers = get_superclass_list_cpp decl in
ignore (Tenv.mk_struct tenv ~fields ~statics ~methods ~supers ~annots sil_typename);
let sil_type = Typ.Tstruct sil_typename in
Ast_utils.update_sil_types_map type_ptr sil_type;
CAst_utils.update_sil_types_map type_ptr sil_type;
sil_type
) else (
match Tenv.lookup tenv sil_typename with
@ -204,7 +202,7 @@ and get_record_declaration_struct_type tenv decl =
updated with a new struct including the other fields. *)
ignore (Tenv.mk_struct tenv ~fields:extra_fields sil_typename);
let tvar_type = Typ.Tstruct sil_typename in
Ast_utils.update_sil_types_map type_ptr tvar_type;
CAst_utils.update_sil_types_map type_ptr tvar_type;
tvar_type)
| _ -> assert false

@ -7,7 +7,6 @@
* of patent rights can be found in the PATENTS file in the same directory.
*)
open CFrontend_utils
open! IStd
let get_source_range an =
@ -30,21 +29,21 @@ let is_in_main_file translation_unit_context an =
let is_ck_context (context: CLintersContext.context) an =
context.is_ck_translation_unit
&& is_in_main_file context.translation_unit_context an
&& General_utils.is_objc_extension context.translation_unit_context
&& CGeneral_utils.is_objc_extension context.translation_unit_context
(** Recursively go up the inheritance hierarchy of a given ObjCInterfaceDecl.
(Returns false on decls other than that one.) *)
let is_component_or_controller_if decl =
let open CFrontend_config in
Ast_utils.is_objc_if_descendant decl [ckcomponent_cl; ckcomponentcontroller_cl]
CAst_utils.is_objc_if_descendant decl [ckcomponent_cl; ckcomponentcontroller_cl]
(** True if it's an objc class impl that extends from CKComponent or
CKComponentController, false otherwise *)
let rec is_component_or_controller_descendant_impl decl =
match decl with
| Clang_ast_t.ObjCImplementationDecl _ ->
is_component_or_controller_if (Ast_utils.get_super_if (Some decl))
is_component_or_controller_if (CAst_utils.get_super_if (Some decl))
| Clang_ast_t.LinkageSpecDecl (_, decl_list, _) ->
contains_ck_impl decl_list
| _ -> false
@ -83,10 +82,10 @@ and contains_ck_impl decl_list =
``` *)
let mutable_local_vars_advice context an =
let rec get_referenced_type (qual_type: Clang_ast_t.qual_type) : Clang_ast_t.decl option =
let typ_opt = Ast_utils.get_desugared_type qual_type.qt_type_ptr in
let typ_opt = CAst_utils.get_desugared_type qual_type.qt_type_ptr in
match (typ_opt : Clang_ast_t.c_type option) with
| Some ObjCInterfaceType (_, decl_ptr)
| Some RecordType (_, decl_ptr) -> Ast_utils.get_decl decl_ptr
| Some RecordType (_, decl_ptr) -> CAst_utils.get_decl decl_ptr
| Some PointerType (_, inner_qual_type)
| Some ObjCObjectPointerType (_, inner_qual_type)
| Some LValueReferenceType (_, inner_qual_type) -> get_referenced_type inner_qual_type
@ -104,13 +103,13 @@ let mutable_local_vars_advice context an =
match an with
| CTL.Decl (Clang_ast_t.VarDecl(decl_info, named_decl_info, qual_type, _) as decl)->
let is_const_ref = match Ast_utils.get_type qual_type.qt_type_ptr with
let is_const_ref = match CAst_utils.get_type qual_type.qt_type_ptr with
| Some LValueReferenceType (_, {Clang_ast_t.qt_is_const}) ->
qt_is_const
| _ -> false in
let is_const = qual_type.qt_is_const || is_const_ref in
let condition = is_ck_context context an
&& (not (Ast_utils.is_syntactically_global_var decl))
&& (not (CAst_utils.is_syntactically_global_var decl))
&& (not is_const)
&& not (is_of_whitelisted_type qual_type)
&& not decl_info.di_is_implicit in
@ -134,12 +133,12 @@ let mutable_local_vars_advice context an =
Any static function that returns a subclass of CKComponent will be flagged. *)
let component_factory_function_advice context an =
let is_component_if decl =
Ast_utils.is_objc_if_descendant decl [CFrontend_config.ckcomponent_cl] in
CAst_utils.is_objc_if_descendant decl [CFrontend_config.ckcomponent_cl] in
match an with
| CTL.Decl (Clang_ast_t.FunctionDecl (decl_info, _, (qual_type: Clang_ast_t.qual_type), _)) ->
let objc_interface =
Ast_utils.type_ptr_to_objc_interface qual_type.qt_type_ptr in
CAst_utils.type_ptr_to_objc_interface qual_type.qt_type_ptr in
let condition =
is_ck_context context an && is_component_if objc_interface in
if condition then
@ -165,7 +164,7 @@ let component_with_unconventional_superclass_advice context an =
match if_decl with
| Clang_ast_t.ObjCInterfaceDecl (_, _, _, _, _) ->
if is_component_or_controller_if (Some if_decl) then
let superclass_name = match Ast_utils.get_super_if (Some if_decl) with
let superclass_name = match CAst_utils.get_super_if (Some if_decl) with
| Some Clang_ast_t.ObjCInterfaceDecl (_, named_decl_info, _, _, _) ->
Some named_decl_info.ni_name
| _ -> None in
@ -203,7 +202,7 @@ let component_with_unconventional_superclass_advice context an =
match an with
| CTL.Decl (Clang_ast_t.ObjCImplementationDecl (_, _, _, _, impl_decl_info)) ->
let if_decl_opt =
Ast_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface in
CAst_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface in
if Option.is_some if_decl_opt && is_ck_context context an then
check_interface (Option.value_exn if_decl_opt)
else
@ -233,7 +232,7 @@ let component_with_multiple_factory_methods_advice context an =
| _ -> assert false in
let unavailable_attrs = (IList.filter is_unavailable_attr attrs) in
let is_available = IList.length unavailable_attrs = 0 in
(Ast_utils.is_objc_factory_method if_decl decl) && is_available in
(CAst_utils.is_objc_factory_method if_decl decl) && is_available in
let check_interface if_decl =
match if_decl with
@ -253,7 +252,7 @@ let component_with_multiple_factory_methods_advice context an =
match an with
| CTL.Decl (Clang_ast_t.ObjCImplementationDecl (_, _, _, _, impl_decl_info)) ->
let if_decl_opt =
Ast_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface in
CAst_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface in
(match if_decl_opt with
| Some d when is_ck_context context an -> check_interface d
| _ -> CTL.False, [])
@ -262,7 +261,7 @@ let component_with_multiple_factory_methods_advice context an =
let in_ck_class (context: CLintersContext.context) =
Option.value_map ~f:is_component_or_controller_descendant_impl ~default:false
context.current_objc_impl
&& General_utils.is_objc_extension context.translation_unit_context
&& CGeneral_utils.is_objc_extension context.translation_unit_context
(** Components shouldn't have side-effects in its initializer.
@ -288,7 +287,7 @@ let rec _component_initializer_with_side_effects_advice
| Clang_ast_t.DeclRefExpr (_, _, _, decl_ref_expr_info) ->
let refs = [decl_ref_expr_info.drti_decl_ref;
decl_ref_expr_info.drti_found_decl_ref] in
(match IList.find_map_opt Ast_utils.name_of_decl_ref_opt refs with
(match IList.find_map_opt CAst_utils.name_of_decl_ref_opt refs with
| Some "dispatch_after"
| Some "dispatch_async"
| Some "dispatch_sync" ->

@ -9,8 +9,6 @@
open! IStd
open CFrontend_utils
(** This module creates extra ast constructs that are needed for the translation *)
let dummy_source_range () =
@ -22,19 +20,19 @@ let dummy_source_range () =
(dummy_source_loc, dummy_source_loc)
let dummy_stmt_info () = {
Clang_ast_t.si_pointer = Ast_utils.get_fresh_pointer ();
Clang_ast_t.si_pointer = CAst_utils.get_fresh_pointer ();
si_source_range = dummy_source_range ();
}
(* given a stmt_info return the same stmt_info with a fresh pointer *)
let fresh_stmt_info stmt_info =
{ stmt_info with Clang_ast_t.si_pointer = Ast_utils.get_fresh_pointer () }
{ stmt_info with Clang_ast_t.si_pointer = CAst_utils.get_fresh_pointer () }
let fresh_decl_info decl_info =
{ decl_info with Clang_ast_t.di_pointer = Ast_utils.get_fresh_pointer () }
{ decl_info with Clang_ast_t.di_pointer = CAst_utils.get_fresh_pointer () }
let empty_decl_info = {
Clang_ast_t.di_pointer = Ast_utils.get_invalid_pointer ();
Clang_ast_t.di_pointer = CAst_utils.get_invalid_pointer ();
di_parent_pointer = None;
di_previous_decl = `None;
di_source_range = dummy_source_range ();
@ -61,7 +59,7 @@ let empty_var_decl_info = {
}
let stmt_info_with_fresh_pointer stmt_info = {
Clang_ast_t.si_pointer = Ast_utils.get_fresh_pointer ();
Clang_ast_t.si_pointer = CAst_utils.get_fresh_pointer ();
si_source_range = stmt_info.Clang_ast_t.si_source_range;
}
@ -69,7 +67,7 @@ let create_qual_type ?(is_const=false) qt_type_ptr =
{ Clang_ast_t.qt_type_ptr; qt_is_const=is_const }
let new_constant_type_ptr () =
let pointer = Ast_utils.get_fresh_pointer () in
let pointer = CAst_utils.get_fresh_pointer () in
`Prebuilt pointer
(* Whenever new type are added manually to the translation here, *)
@ -172,7 +170,7 @@ let create_nil stmt_info =
create_implicit_cast_expr stmt_info [paren_expr] create_id_type `NullToPointer
let dummy_stmt () =
let pointer = Ast_utils.get_fresh_pointer () in
let pointer = CAst_utils.get_fresh_pointer () in
let source_range = dummy_source_range () in
Clang_ast_t.NullStmt({ Clang_ast_t.si_pointer = pointer; si_source_range = source_range } ,[])
@ -192,7 +190,7 @@ let make_expr_info_with_objc_kind tp objc_kind =
let make_decl_ref_exp stmt_info expr_info drei =
let stmt_info = {
Clang_ast_t.si_pointer = Ast_utils.get_fresh_pointer ();
Clang_ast_t.si_pointer = CAst_utils.get_fresh_pointer ();
si_source_range = stmt_info.Clang_ast_t.si_source_range
} in
Clang_ast_t.DeclRefExpr(stmt_info, [], expr_info, drei)
@ -226,7 +224,7 @@ let make_decl_ref_no_tp k decl_ptr name is_hidden =
make_decl_ref k decl_ptr name is_hidden None
let make_decl_ref_invalid k name is_hidden tp =
make_decl_ref k (Ast_utils.get_invalid_pointer ()) name is_hidden (Some tp)
make_decl_ref k (CAst_utils.get_invalid_pointer ()) name is_hidden (Some tp)
let make_decl_ref_expr_info decl_ref = {
Clang_ast_t.drti_decl_ref = Some decl_ref;
@ -341,7 +339,7 @@ let build_PseudoObjectExpr tp_m o_cast_decl_ref_exp mname =
| Clang_ast_t.ImplicitCastExpr (si, _, ei, _) ->
let ove = build_OpaqueValueExpr si o_cast_decl_ref_exp ei in
let ei_opre = make_expr_info (pseudo_object_tp ()) in
let count_name = Ast_utils.make_name_decl CFrontend_config.count in
let count_name = CAst_utils.make_name_decl CFrontend_config.count in
let pointer = si.Clang_ast_t.si_pointer in
let obj_c_property_ref_expr_info = {
Clang_ast_t.oprei_kind =
@ -437,7 +435,7 @@ let translate_block_enumerate block_name stmt_info stmt_list ei =
{ Clang_ast_t.uttei_kind = `SizeOf; Clang_ast_t.uttei_type_ptr = type_opt}) in
let pointer = di.Clang_ast_t.di_pointer in
let stmt_info = fresh_stmt_info stmt_info in
let malloc_name = Ast_utils.make_name_decl CFrontend_config.malloc in
let malloc_name = CAst_utils.make_name_decl CFrontend_config.malloc in
let malloc = create_call stmt_info pointer malloc_name tp_fun [parameter] in
let tp = qt.Clang_ast_t.qt_type_ptr in
let init_exp = create_implicit_cast_expr (fresh_stmt_info stmt_info) [malloc] tp `BitCast in
@ -466,7 +464,7 @@ let translate_block_enumerate block_name stmt_info stmt_list ei =
let tp_fun = create_void_void_type in
let decl_ref = make_decl_ref_tp `Var di.Clang_ast_t.di_pointer name false tp in
let cast = cast_expr decl_ref tp in
let free_name = Ast_utils.make_name_decl CFrontend_config.free in
let free_name = CAst_utils.make_name_decl CFrontend_config.free in
let parameter =
create_implicit_cast_expr (fresh_stmt_info stmt_info) [cast] create_void_star_type `BitCast in
let pointer = di.Clang_ast_t.di_pointer in
@ -516,12 +514,12 @@ 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 di = { empty_decl_info with Clang_ast_t.di_pointer = CAst_utils.get_fresh_pointer () } in
let tp = create_qual_type @@ create_pointer_type @@ create_class_type
(CFrontend_config.nsarray_cl, `OBJC) 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 objects_name = Ast_utils.make_name_decl CFrontend_config.objects in
let objects_name = CAst_utils.make_name_decl CFrontend_config.objects in
let var_decl = Clang_ast_t.VarDecl (di, objects_name, tp, vdi) in
Clang_ast_t.DeclStmt (fresh_stmt_info stmt_info, [init], [var_decl]), [(CFrontend_config.objects, di.Clang_ast_t.di_pointer, tp)] in
@ -541,12 +539,12 @@ let translate_block_enumerate block_name stmt_info stmt_list ei =
cast_expr decl_ref tp
| _ -> assert false in
let qual_block_name = Ast_utils.make_name_decl block_name in
let qual_block_name = CAst_utils.make_name_decl block_name in
let make_block_decl be =
match be with
| Clang_ast_t.BlockExpr (bsi, _, bei, _) ->
let di = { empty_decl_info with Clang_ast_t.di_pointer = Ast_utils.get_fresh_pointer () } in
let di = { empty_decl_info with di_pointer = CAst_utils.get_fresh_pointer () } in
let vdi = { empty_var_decl_info with Clang_ast_t.vdi_init_expr = Some (be) } in
let qt = create_qual_type bei.Clang_ast_t.ei_type_ptr in
let var_decl = Clang_ast_t.VarDecl (di, qual_block_name, qt, vdi) in
@ -615,7 +613,7 @@ let create_assume_not_null_call decl_info var_name var_type =
let stmt_info_var = dummy_stmt_info () in
let decl_ref_info = make_decl_ref_expr_info decl_ref in
let var_decl_ref = Clang_ast_t.DeclRefExpr (stmt_info_var, [], (make_expr_info var_type), decl_ref_info) in
let var_decl_ptr = Ast_utils.get_invalid_pointer () in
let var_decl_ptr = CAst_utils.get_invalid_pointer () in
let expr_info = {
Clang_ast_t.ei_type_ptr = var_type;
ei_value_kind = `RValue;
@ -628,5 +626,5 @@ let create_assume_not_null_call decl_info var_name var_type =
let bin_op = make_binary_stmt decl_ref_exp_cast null_expr stmt_info bin_op_expr_info boi in
let parameters = [bin_op] in
let procname = Procname.to_string BuiltinDecl.__infer_assume in
let qual_procname = Ast_utils.make_name_decl procname in
let qual_procname = CAst_utils.make_name_decl procname in
create_call stmt_info var_decl_ptr qual_procname create_void_star_type parameters

@ -11,8 +11,6 @@ open! IStd
(** Utility module for translating unary and binary operations and compound assignments *)
open CFrontend_utils
(* Returns the translation of assignment when ARC mode is enabled in Obj-C *)
(* For __weak and __unsafe_unretained the translation is the same as non-ARC *)
(* (this is because, in these cases, there is no change in the reference counter *)
@ -150,7 +148,7 @@ let unary_operation_instruction translation_unit_context uoi e typ loc =
let id = Ident.create_fresh Ident.knormal in
let instr1 = Sil.Load (id, e, typ, loc) in
let e_plus_1 = Exp.BinOp(Binop.PlusA, Exp.Var id, Exp.Const(Const.Cint (IntLit.one))) in
let exp = if General_utils.is_cpp_translation translation_unit_context then
let exp = if CGeneral_utils.is_cpp_translation translation_unit_context then
e
else
e_plus_1 in
@ -164,7 +162,7 @@ let unary_operation_instruction translation_unit_context uoi e typ loc =
let id = Ident.create_fresh Ident.knormal in
let instr1 = Sil.Load (id, e, typ, loc) in
let e_minus_1 = Exp.BinOp(Binop.MinusA, Exp.Var id, Exp.Const(Const.Cint (IntLit.one))) in
let exp = if General_utils.is_cpp_translation translation_unit_context then
let exp = if CGeneral_utils.is_cpp_translation translation_unit_context then
e
else
e_minus_1 in

@ -0,0 +1,471 @@
(*
* Copyright (c) 2013 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! IStd
(** Functions for transformations of ast nodes *)
module L = Logging
module F = Format
type type_ptr_to_sil_type = Tenv.t -> Clang_ast_t.type_ptr -> Typ.t
let string_of_decl decl =
let name = Clang_ast_proj.get_decl_kind_string decl in
let info = Clang_ast_proj.get_decl_tuple decl in
Printf.sprintf "<\"%s\"> '%d'" name info.Clang_ast_t.di_pointer
let string_of_unary_operator_kind = function
| `PostInc -> "PostInc"
| `PostDec -> "PostDec"
| `PreInc -> "PreInc"
| `PreDec -> "PreDec"
| `AddrOf -> "AddrOf"
| `Deref -> "Deref"
| `Plus -> "Plus"
| `Minus -> "Minus"
| `Not -> "Not"
| `LNot -> "LNot"
| `Real -> "Real"
| `Imag -> "Imag"
| `Extension -> "Extension"
| `Coawait -> "Coawait"
let string_of_stmt stmt =
let name = Clang_ast_proj.get_stmt_kind_string stmt in
let info, _ = Clang_ast_proj.get_stmt_tuple stmt in
Printf.sprintf "<\"%s\"> '%d'" name info.Clang_ast_t.si_pointer
let get_stmts_from_stmt stmt =
let open Clang_ast_t in
match stmt with
| OpaqueValueExpr (_, lstmt, _, opaque_value_expr_info) ->
(match opaque_value_expr_info.Clang_ast_t.ovei_source_expr with
| Some stmt -> lstmt @ [stmt]
| _ -> lstmt)
(* given that this has not been translated, looking up for variables *)
(* inside leads to inconsistencies *)
| ObjCAtCatchStmt _ ->
[]
| _ -> snd (Clang_ast_proj.get_stmt_tuple stmt)
let fold_qual_name qual_name_list =
match qual_name_list with
| [] -> ""
| name :: quals ->
let s = (IList.fold_right (fun el res -> res ^ el ^ "::") quals "") ^ name in
let no_slash_space = Str.global_replace (Str.regexp "[/ ]") "_" s in
no_slash_space
let get_qualified_name name_info =
fold_qual_name name_info.Clang_ast_t.ni_qual_name
let get_unqualified_name name_info =
let name = match name_info.Clang_ast_t.ni_qual_name with
| name :: _ -> name
| [] -> name_info.Clang_ast_t.ni_name in
fold_qual_name [name]
let get_class_name_from_member member_name_info =
match member_name_info.Clang_ast_t.ni_qual_name with
| _ :: class_qual_list -> fold_qual_name class_qual_list
| [] -> assert false
let make_name_decl name = {
Clang_ast_t.ni_name = name;
ni_qual_name = [name];
}
let make_qual_name_decl class_name_quals name = {
Clang_ast_t.ni_name = name;
ni_qual_name = name :: class_name_quals;
}
let property_name property_impl_decl_info =
let no_property_name = make_name_decl "WARNING_NO_PROPERTY_NAME" in
match property_impl_decl_info.Clang_ast_t.opidi_property_decl with
| Some decl_ref ->
(match decl_ref.Clang_ast_t.dr_name with
| Some n -> n
| _ -> no_property_name)
| None -> no_property_name
let generated_ivar_name property_name =
match property_name.Clang_ast_t.ni_qual_name with
| [name; class_name] ->
let ivar_name = "_" ^ name in
{ Clang_ast_t.ni_name = ivar_name;
ni_qual_name = [ivar_name; class_name]
}
| _ -> make_name_decl property_name.Clang_ast_t.ni_name
let compare_property_attribute =
[%compare: [
`Readonly | `Assign | `Readwrite | `Retain | `Copy | `Nonatomic | `Atomic
| `Weak | `Strong | `Unsafe_unretained | `ExplicitGetter | `ExplicitSetter
]]
let equal_property_attribute att1 att2 =
compare_property_attribute att1 att2 = 0
let get_memory_management_attributes () =
[`Assign; `Retain; `Copy; `Weak; `Strong; `Unsafe_unretained]
let is_retain attribute_opt =
match attribute_opt with
| Some attribute ->
attribute = `Retain || attribute = `Strong
| _ -> false
let is_copy attribute_opt =
match attribute_opt with
| Some attribute ->
attribute = `Copy
| _ -> false
let name_opt_of_name_info_opt name_info_opt =
match name_info_opt with
| Some name_info -> Some (get_qualified_name name_info)
| None -> None
let pointer_counter = ref 0
let get_fresh_pointer () =
pointer_counter := !pointer_counter + 1;
let internal_pointer = -(!pointer_counter) in
internal_pointer
let get_invalid_pointer () =
CFrontend_config.invalid_pointer
let type_from_unary_expr_or_type_trait_expr_info info =
match info.Clang_ast_t.uttei_type_ptr with
| Some tp -> Some tp
| None -> None
let get_decl decl_ptr =
try
Some (Clang_ast_main.PointerMap.find decl_ptr !CFrontend_config.pointer_decl_index)
with Not_found -> Logging.out "decl with pointer %d not found\n" decl_ptr; None
let get_decl_opt decl_ptr_opt =
match decl_ptr_opt with
| Some decl_ptr -> get_decl decl_ptr
| None -> None
let get_stmt stmt_ptr =
try
Some (Clang_ast_main.PointerMap.find stmt_ptr !CFrontend_config.pointer_stmt_index)
with Not_found -> Logging.out "stmt with pointer %d not found\n" stmt_ptr; None
let get_stmt_opt stmt_ptr_opt =
match stmt_ptr_opt with
| Some stmt_ptr -> get_stmt stmt_ptr
| None -> None
let get_decl_opt_with_decl_ref decl_ref_opt =
match decl_ref_opt with
| Some decl_ref -> get_decl decl_ref.Clang_ast_t.dr_decl_pointer
| None -> None
let get_property_of_ivar decl_ptr =
try
Some (Clang_ast_main.PointerMap.find decl_ptr !CFrontend_config.ivar_to_property_index)
with Not_found -> Logging.out "property with pointer %d not found\n" decl_ptr; None
let update_sil_types_map type_ptr sil_type =
CFrontend_config.sil_types_map :=
Clang_ast_types.TypePointerMap.add type_ptr sil_type !CFrontend_config.sil_types_map
let update_enum_map enum_constant_pointer sil_exp =
let open Clang_ast_main in
let (predecessor_pointer_opt, _) =
try PointerMap.find enum_constant_pointer !CFrontend_config.enum_map
with Not_found -> assert false in
let enum_map_value = (predecessor_pointer_opt, Some sil_exp) in
CFrontend_config.enum_map :=
PointerMap.add enum_constant_pointer enum_map_value !CFrontend_config.enum_map
let add_enum_constant enum_constant_pointer predecessor_pointer_opt =
let enum_map_value = (predecessor_pointer_opt, None) in
CFrontend_config.enum_map :=
Clang_ast_main.PointerMap.add enum_constant_pointer enum_map_value !CFrontend_config.enum_map
let get_enum_constant_exp enum_constant_pointer =
Clang_ast_main.PointerMap.find enum_constant_pointer !CFrontend_config.enum_map
let get_type type_ptr =
try
(* There is chance for success only if type_ptr is in fact clang pointer *)
(let raw_ptr = Clang_ast_types.type_ptr_to_clang_pointer type_ptr in
try
Some (Clang_ast_main.PointerMap.find raw_ptr !CFrontend_config.pointer_type_index)
with Not_found -> Logging.out "type with pointer %d not found\n" raw_ptr; None)
with Clang_ast_types.Not_Clang_Pointer ->
(* otherwise, function fails *)
let type_str = Clang_ast_types.type_ptr_to_string type_ptr in
Logging.out "type %s is not clang pointer\n" type_str;
None
let get_desugared_type type_ptr =
let typ_opt = get_type type_ptr in
match typ_opt with
| Some typ ->
let type_info = Clang_ast_proj.get_type_tuple typ in
(match type_info.Clang_ast_t.ti_desugared_type with
| Some ptr -> get_type ptr
| _ -> typ_opt)
| _ -> typ_opt
let get_decl_from_typ_ptr typ_ptr =
let typ_opt = get_desugared_type typ_ptr in
let typ = match typ_opt with Some t -> t | _ -> assert false in
match typ with
| Clang_ast_t.RecordType (_, decl_ptr)
| Clang_ast_t.ObjCInterfaceType (_, decl_ptr) -> get_decl decl_ptr
| _ -> None
(* TODO take the attributes into account too. To be done after we get the attribute's arguments. *)
let is_type_nonnull type_ptr =
let open Clang_ast_t in
match get_type type_ptr with
| Some AttributedType (_, attr_info) -> attr_info.ati_attr_kind = `Nonnull
| _ -> false
let is_type_nullable type_ptr =
let open Clang_ast_t in
match get_type type_ptr with
| Some AttributedType (_, attr_info) -> attr_info.ati_attr_kind = `Nullable
| _ -> false
let string_of_type_ptr type_ptr = Clang_ast_j.string_of_type_ptr type_ptr
let name_of_typedef_type_info {Clang_ast_t.tti_decl_ptr} =
match get_decl tti_decl_ptr with
| Some TypedefDecl (_, name_decl_info, _, _, _) ->
get_qualified_name name_decl_info
| _ -> ""
let name_opt_of_typedef_type_ptr type_ptr =
match get_type type_ptr with
| Some Clang_ast_t.TypedefType (_, typedef_type_info) ->
Some (name_of_typedef_type_info typedef_type_info)
| _ -> None
let string_of_qual_type {Clang_ast_t.qt_type_ptr; qt_is_const} =
Printf.sprintf "%s%s" (if qt_is_const then "is_const " else "") (string_of_type_ptr qt_type_ptr)
let add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt fail_if_not_found =
match decl_ref_opt with (* translate interface first if found *)
| Some dr ->
ignore (type_ptr_to_sil_type tenv (`DeclPtr dr.Clang_ast_t.dr_decl_pointer));
| _ -> if fail_if_not_found then assert false else ()
let add_type_from_decl_ref_list type_ptr_to_sil_type tenv decl_ref_list =
let add_elem dr =
ignore (type_ptr_to_sil_type tenv (`DeclPtr dr.Clang_ast_t.dr_decl_pointer)) in
IList.iter add_elem decl_ref_list
let get_function_decl_with_body decl_ptr =
let open Clang_ast_t in
let decl_opt = get_decl decl_ptr in
let decl_ptr' = match decl_opt with
| Some (FunctionDecl (_, _, _, fdecl_info))
| Some (CXXMethodDecl (_, _, _, fdecl_info, _))
| Some (CXXConstructorDecl (_, _, _, fdecl_info, _))
| Some (CXXConversionDecl (_, _, _, fdecl_info, _))
| Some (CXXDestructorDecl (_, _, _, fdecl_info, _)) ->
fdecl_info.Clang_ast_t.fdi_decl_ptr_with_body
| _ -> Some decl_ptr in
if decl_ptr' = (Some decl_ptr) then decl_opt
else get_decl_opt decl_ptr'
let get_info_from_decl_ref decl_ref =
let name_info = match decl_ref.Clang_ast_t.dr_name with Some ni -> ni | _ -> assert false in
let decl_ptr = decl_ref.Clang_ast_t.dr_decl_pointer in
let type_ptr = match decl_ref.Clang_ast_t.dr_type_ptr with Some tp -> tp | _ -> assert false in
name_info, decl_ptr, type_ptr
(* st |= EF (atomic_pred param) *)
let rec exists_eventually_st atomic_pred param st =
if atomic_pred param st then true
else
let _, st_list = Clang_ast_proj.get_stmt_tuple st in
IList.exists (exists_eventually_st atomic_pred param) st_list
let is_syntactically_global_var decl =
match decl with
| Clang_ast_t.VarDecl (_, _ ,_, vdi) ->
vdi.vdi_is_global && not vdi.vdi_is_static_local
| _ -> false
let is_const_expr_var decl =
match decl with
| Clang_ast_t.VarDecl (_, _ ,_, vdi) -> vdi.vdi_is_const_expr
| _ -> false
let is_ptr_to_objc_class typ class_name =
match typ with
| Some Clang_ast_t.ObjCObjectPointerType (_, {Clang_ast_t.qt_type_ptr}) ->
(match get_desugared_type qt_type_ptr with
| Some ObjCInterfaceType (_, ptr) ->
(match get_decl ptr with
| Some ObjCInterfaceDecl (_, ndi, _, _, _) ->
String.compare ndi.ni_name class_name = 0
| _ -> false)
| _ -> false)
| _ -> false
let full_name_of_decl_opt decl_opt =
match decl_opt with
| Some decl ->
(match Clang_ast_proj.get_named_decl_tuple decl with
| Some (_, name_info) -> get_qualified_name name_info
| None -> "")
| None -> ""
(* Generates a unique number for each variant of a type. *)
let get_tag ast_item =
let item_rep = Obj.repr ast_item in
if Obj.is_block item_rep then
Obj.tag item_rep
else -(Obj.obj item_rep)
(* Generates a key for a statement based on its sub-statements and the statement tag. *)
let rec generate_key_stmt stmt =
let tag_str = string_of_int (get_tag stmt) in
let _, stmts = Clang_ast_proj.get_stmt_tuple stmt in
let tags = IList.map generate_key_stmt stmts in
let buffer = Buffer.create 16 in
let tags = tag_str :: tags in
IList.iter (fun tag -> Buffer.add_string buffer tag) tags;
Buffer.contents buffer
(* Generates a key for a declaration based on its name and the declaration tag. *)
let generate_key_decl decl =
let buffer = Buffer.create 16 in
let name = full_name_of_decl_opt (Some decl) in
Buffer.add_string buffer (string_of_int (get_tag decl));
Buffer.add_string buffer name;
Buffer.contents buffer
let rec get_super_if decl =
match decl with
| Some Clang_ast_t.ObjCImplementationDecl(_, _, _, _, impl_decl_info) ->
(* Try getting the super ref through the impl info, and fall back to
getting the if decl first and getting the super ref through it. *)
let super_ref = get_decl_opt_with_decl_ref impl_decl_info.oidi_super in
if Option.is_some super_ref then
super_ref
else
get_super_if (get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface)
| Some Clang_ast_t.ObjCInterfaceDecl(_, _, _, _, interface_decl_info) ->
get_decl_opt_with_decl_ref interface_decl_info.otdi_super
| _ -> None
let get_super_impl impl_decl_info =
let objc_interface_decl_current =
get_decl_opt_with_decl_ref
impl_decl_info.Clang_ast_t.oidi_class_interface in
let objc_interface_decl_super = get_super_if objc_interface_decl_current in
let objc_implementation_decl_super =
match objc_interface_decl_super with
| Some ObjCInterfaceDecl(_, _, _, _, interface_decl_info) ->
get_decl_opt_with_decl_ref
interface_decl_info.otdi_implementation
| _ -> None in
match objc_implementation_decl_super with
| Some ObjCImplementationDecl(_, _, decl_list, _, impl_decl_info) ->
Some (decl_list, impl_decl_info)
| _ -> None
let get_super_ObjCImplementationDecl impl_decl_info =
let objc_interface_decl_current =
get_decl_opt_with_decl_ref
impl_decl_info.Clang_ast_t.oidi_class_interface in
let objc_interface_decl_super = get_super_if objc_interface_decl_current in
let objc_implementation_decl_super =
match objc_interface_decl_super with
| Some ObjCInterfaceDecl(_, _, _, _, interface_decl_info) ->
get_decl_opt_with_decl_ref
interface_decl_info.otdi_implementation
| _ -> None in
objc_implementation_decl_super
let get_impl_decl_info dec =
match dec with
| Clang_ast_t.ObjCImplementationDecl (_, _, _, _, idi) -> Some idi
| _ -> None
let default_blacklist =
let open CFrontend_config in
[nsobject_cl; nsproxy_cl]
let rec is_objc_if_descendant ?(blacklist = default_blacklist) if_decl ancestors =
(* List of ancestors to check for and list of classes to short-circuit to
false can't intersect *)
if not String.Set.(is_empty (inter (of_list blacklist) (of_list ancestors))) then
failwith "Blacklist and ancestors must be mutually exclusive."
else
match if_decl with
| Some Clang_ast_t.ObjCInterfaceDecl (_, ndi, _, _, _) ->
let in_list some_list =
IList.mem String.equal ndi.Clang_ast_t.ni_name some_list in
not (in_list blacklist)
&& (in_list ancestors
|| is_objc_if_descendant ~blacklist:blacklist (get_super_if if_decl) ancestors)
| _ -> false
let rec type_ptr_to_objc_interface type_ptr =
let typ_opt = get_desugared_type type_ptr in
match (typ_opt : Clang_ast_t.c_type option) with
| Some ObjCInterfaceType (_, decl_ptr) -> get_decl decl_ptr
| Some ObjCObjectPointerType (_, (inner_qual_type: Clang_ast_t.qual_type)) ->
type_ptr_to_objc_interface inner_qual_type.qt_type_ptr
| Some FunctionProtoType (_, function_type_info, _)
| Some FunctionNoProtoType (_, function_type_info) ->
type_ptr_to_objc_interface function_type_info.Clang_ast_t.fti_return_type
| _ -> None
let if_decl_to_di_pointer_opt if_decl =
match if_decl with
| Clang_ast_t.ObjCInterfaceDecl (if_decl_info, _, _, _, _) ->
Some if_decl_info.di_pointer
| _ -> None
let is_instance_type type_ptr =
match name_opt_of_typedef_type_ptr type_ptr with
| Some name -> name = "instancetype"
| None -> false
let return_type_matches_class_type rtp type_decl_pointer =
if is_instance_type rtp then
true
else
let return_type_decl_opt = type_ptr_to_objc_interface rtp in
let return_type_decl_pointer_opt =
Option.map ~f:if_decl_to_di_pointer_opt return_type_decl_opt in
(Some type_decl_pointer) = return_type_decl_pointer_opt
let is_objc_factory_method if_decl meth_decl =
let if_type_decl_pointer = if_decl_to_di_pointer_opt if_decl in
match meth_decl with
| Clang_ast_t.ObjCMethodDecl (_, _, omdi) ->
(not omdi.omdi_is_instance_method) &&
(return_type_matches_class_type omdi.omdi_result_type if_type_decl_pointer)
| _ -> false
let name_of_decl_ref_opt (decl_ref_opt: Clang_ast_t.decl_ref option) =
match decl_ref_opt with
| Some decl_ref ->
(match decl_ref.dr_name with
| Some named_decl_info -> Some named_decl_info.ni_name
| _ -> None)
| _ -> None

@ -0,0 +1,172 @@
(*
* Copyright (c) 2013 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! IStd
(** Functions for transformations of ast nodes *)
val string_of_stmt : Clang_ast_t.stmt -> string
val get_stmts_from_stmt : Clang_ast_t.stmt -> Clang_ast_t.stmt list
val string_of_decl : Clang_ast_t.decl -> string
val string_of_unary_operator_kind : Clang_ast_t.unary_operator_kind -> string
val name_opt_of_name_info_opt : Clang_ast_t.named_decl_info option -> string option
val property_name : Clang_ast_t.obj_c_property_impl_decl_info -> Clang_ast_t.named_decl_info
val compare_property_attribute :
Clang_ast_t.property_attribute -> Clang_ast_t.property_attribute -> int
val generated_ivar_name :
Clang_ast_t.named_decl_info -> Clang_ast_t.named_decl_info
val equal_property_attribute :
Clang_ast_t.property_attribute -> Clang_ast_t.property_attribute -> bool
val get_memory_management_attributes : unit -> Clang_ast_t.property_attribute list
val is_retain : Clang_ast_t.property_attribute option -> bool
val is_copy : Clang_ast_t.property_attribute option -> bool
val is_type_nonnull : Clang_ast_t.type_ptr -> bool
val is_type_nullable : Clang_ast_t.type_ptr -> bool
val get_fresh_pointer : unit -> Clang_ast_t.pointer
val get_invalid_pointer : unit -> Clang_ast_t.pointer
val type_from_unary_expr_or_type_trait_expr_info :
Clang_ast_t.unary_expr_or_type_trait_expr_info -> Clang_ast_t.type_ptr option
val get_decl : Clang_ast_t.pointer -> Clang_ast_t.decl option
val get_decl_opt : Clang_ast_t.pointer option -> Clang_ast_t.decl option
val get_stmt : Clang_ast_t.pointer -> Clang_ast_t.stmt option
val get_stmt_opt : Clang_ast_t.pointer option -> Clang_ast_t.stmt option
val get_decl_opt_with_decl_ref : Clang_ast_t.decl_ref option -> Clang_ast_t.decl option
val get_property_of_ivar : Clang_ast_t.pointer -> Clang_ast_t.decl option
val update_sil_types_map : Clang_ast_t.type_ptr -> Typ.t -> unit
val update_enum_map : Clang_ast_t.pointer -> Exp.t -> unit
val add_enum_constant : Clang_ast_t.pointer -> Clang_ast_t.pointer option -> unit
val get_enum_constant_exp : Clang_ast_t.pointer -> Clang_ast_t.pointer option * Exp.t option
(** returns sanitized, fully qualified name given name info *)
val get_qualified_name : Clang_ast_t.named_decl_info -> string
(** returns sanitized unqualified name given name info *)
val get_unqualified_name : Clang_ast_t.named_decl_info -> string
(** returns qualified class name given member name info *)
val get_class_name_from_member : Clang_ast_t.named_decl_info -> string
(** looks up clang pointer to type and returns c_type. It requires type_ptr to be `TPtr. *)
val get_type : Clang_ast_t.type_ptr -> Clang_ast_t.c_type option
(** looks up clang pointer to type and resolves any sugar around it.
See get_type for more info and restrictions *)
val get_desugared_type : Clang_ast_t.type_ptr -> Clang_ast_t.c_type option
(** returns declaration of the type for certain types
(RecordType, ObjCInterfaceType and None for others *)
val get_decl_from_typ_ptr : Clang_ast_t.type_ptr -> Clang_ast_t.decl option
(** returns string representation of type_ptr
NOTE: this doesn't expand type, it only converts type_ptr to string *)
val string_of_type_ptr : Clang_ast_t.type_ptr -> string
val name_of_typedef_type_info : Clang_ast_t.typedef_type_info -> string
(** returns name of typedef if type_ptr points to Typedef, None otherwise *)
val name_opt_of_typedef_type_ptr : Clang_ast_t.type_ptr -> string option
val string_of_qual_type : Clang_ast_t.qual_type -> string
val make_name_decl : string -> Clang_ast_t.named_decl_info
val make_qual_name_decl : string list -> string -> Clang_ast_t.named_decl_info
type type_ptr_to_sil_type = Tenv.t -> Clang_ast_t.type_ptr -> Typ.t
val add_type_from_decl_ref : type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl_ref option ->
bool -> unit
val add_type_from_decl_ref_list : type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl_ref list ->
unit
val get_function_decl_with_body : Clang_ast_t.pointer -> Clang_ast_t.decl option
val get_info_from_decl_ref : Clang_ast_t.decl_ref ->
Clang_ast_t.named_decl_info * Clang_ast_t.pointer * Clang_ast_t.type_ptr
val exists_eventually_st : ('a -> Clang_ast_t.stmt -> bool) -> 'a -> Clang_ast_t.stmt -> bool
(** true if a declaration is a global variable *)
val is_syntactically_global_var : Clang_ast_t.decl -> bool
(** true if a declaration is a constexpr variable *)
val is_const_expr_var : Clang_ast_t.decl -> bool
val is_ptr_to_objc_class : Clang_ast_t.c_type option -> string -> bool
val full_name_of_decl_opt : Clang_ast_t.decl option -> string
(** Generates a key for a statement based on its sub-statements and the statement tag. *)
val generate_key_stmt : Clang_ast_t.stmt -> string
(** Generates a key for a declaration based on its name and the declaration tag. *)
val generate_key_decl : Clang_ast_t.decl -> string
(** Given an objc impl or interface decl, returns the objc interface decl of
the superclass, if any. *)
val get_super_if : Clang_ast_t.decl option -> Clang_ast_t.decl option
val get_impl_decl_info : Clang_ast_t.decl -> Clang_ast_t.obj_c_implementation_decl_info option
(** Given an objc impl decl info, return the super class's list of decls and
its objc impl decl info. *)
val get_super_impl :
Clang_ast_t.obj_c_implementation_decl_info ->
(Clang_ast_t.decl list *
Clang_ast_t.obj_c_implementation_decl_info)
option
(** Given an objc impl decl info, return its super class implementation decl *)
val get_super_ObjCImplementationDecl :
Clang_ast_t.obj_c_implementation_decl_info -> Clang_ast_t.decl option
(** Recursively go up the inheritance hierarchy of a given ObjCInterfaceDecl.
Returns true if the passed in decl is an objc interface decl that's an
eventual descendant of one of the classes passed in.
Ancestors param is a list of strings that represent the class names.
Will short-circuit on NSObject and NSProxy since those are known to be
common base classes.
The list of classes to short-circuit on can be overridden via specifying
the named `blacklist` argument. *)
val is_objc_if_descendant :
?blacklist:string list -> Clang_ast_t.decl option -> string list -> bool
val type_ptr_to_objc_interface : Clang_ast_types.t_ptr -> Clang_ast_t.decl option
(** A class method that returns an instance of the class is a factory method. *)
val is_objc_factory_method : Clang_ast_t.decl -> Clang_ast_t.decl -> bool
val name_of_decl_ref_opt : Clang_ast_t.decl_ref option -> string option

@ -12,17 +12,15 @@ open! IStd
(** Translate an enumeration declaration by adding it to the tenv and *)
(** translating the code and adding it to a fake procdesc *)
open CFrontend_utils
(*Check if the constant is in the map, in which case that means that all the *)
(* contants of this enum are in the map, by invariant. Otherwise, add the constant *)
(* to the map. *)
let add_enum_constant_to_map_if_needed decl_pointer pred_decl_opt =
try
ignore (Ast_utils.get_enum_constant_exp decl_pointer);
ignore (CAst_utils.get_enum_constant_exp decl_pointer);
true
with Not_found ->
Ast_utils.add_enum_constant decl_pointer pred_decl_opt;
CAst_utils.add_enum_constant decl_pointer pred_decl_opt;
false
(* Add the constants of this enum to the map if they are not in the map yet *)
@ -47,7 +45,7 @@ let enum_decl decl =
| EnumDecl (_, _, _, type_ptr, decl_list, _, _) ->
add_enum_constants_to_map (IList.rev decl_list);
let sil_type = Typ.Tint Typ.IInt in
Ast_utils.update_sil_types_map type_ptr sil_type;
CAst_utils.update_sil_types_map type_ptr sil_type;
sil_type
| _ -> assert false

@ -11,8 +11,6 @@ open! IStd
(** Utility module to retrieve fields of structs of classes *)
open CFrontend_utils
module L = Logging
type field_type = Ident.fieldname * Typ.t * (Annot.t * bool) list
@ -23,7 +21,7 @@ let rec get_fields_super_classes tenv super_class =
| None -> []
| Some { fields; supers = super_class :: _ } ->
let sc_fields = get_fields_super_classes tenv super_class in
General_utils.append_no_duplicates_fields fields sc_fields
CGeneral_utils.append_no_duplicates_fields fields sc_fields
| Some { fields } -> fields
let fields_superclass tenv interface_decl_info ck =
@ -31,7 +29,7 @@ let fields_superclass tenv interface_decl_info ck =
| Some dr ->
(match dr.Clang_ast_t.dr_name with
| Some sc ->
let classname = CType.mk_classname (Ast_utils.get_qualified_name sc) ck in
let classname = CType.mk_classname (CAst_utils.get_qualified_name sc) ck in
get_fields_super_classes tenv classname
| _ -> [])
| _ -> []
@ -43,7 +41,7 @@ let build_sil_field type_ptr_to_sil_type tenv field_name type_ptr prop_attribute
| Typ.Tptr (_, Typ.Pk_objc_weak) -> [Config.weak]
| Typ.Tptr (_, Typ.Pk_objc_unsafe_unretained) -> [Config.unsafe_unret]
| _ -> [] in
let fname = General_utils.mk_class_field_name field_name in
let fname = CGeneral_utils.mk_class_field_name field_name in
let typ = type_ptr_to_sil_type tenv type_ptr in
let item_annotations = match prop_atts with
| [] ->
@ -61,12 +59,12 @@ let rec get_fields type_ptr_to_sil_type tenv curr_class decl_list =
let fields = get_fields type_ptr_to_sil_type tenv curr_class decl_list' in
let field_tuple = build_sil_field type_ptr_to_sil_type tenv
name_info qt.Clang_ast_t.qt_type_ptr attributes in
General_utils.append_no_duplicates_fields [field_tuple] fields in
CGeneral_utils.append_no_duplicates_fields [field_tuple] fields in
match decl_list with
| [] -> []
| ObjCPropertyDecl (_, _, obj_c_property_decl_info) :: decl_list' ->
(let ivar_decl_ref = obj_c_property_decl_info.Clang_ast_t.opdi_ivar_decl in
match Ast_utils.get_decl_opt_with_decl_ref ivar_decl_ref with
match CAst_utils.get_decl_opt_with_decl_ref ivar_decl_ref with
| Some (ObjCIvarDecl (_, name_info, type_ptr, _, _)) ->
let attributes = obj_c_property_decl_info.Clang_ast_t.opdi_property_attributes in
add_field name_info type_ptr attributes decl_list'
@ -83,7 +81,7 @@ let add_missing_fields tenv class_name ck missing_fields =
let class_tn_name = Typename.TN_csu (Csu.Class ck, mang_name) in
match Tenv.lookup tenv class_tn_name with
| Some ({ fields } as struct_typ) ->
let new_fields = General_utils.append_no_duplicates_fields fields missing_fields in
let new_fields = CGeneral_utils.append_no_duplicates_fields fields missing_fields in
ignore (Tenv.mk_struct tenv ~default:struct_typ ~fields:new_fields ~statics:[] class_tn_name);
Logging.out_debug " Updating info for class '%s' in tenv\n" class_name
| _ -> ()
@ -96,8 +94,8 @@ let modelled_field class_name_info =
let modelled_field_in_class res (class_name, field_name, typ) =
if class_name = class_name_info.Clang_ast_t.ni_name then
let class_name_qualified = class_name_info.Clang_ast_t.ni_qual_name in
let field_name_qualified = Ast_utils.make_qual_name_decl class_name_qualified field_name in
let name = General_utils.mk_class_field_name field_name_qualified in
let field_name_qualified = CAst_utils.make_qual_name_decl class_name_qualified field_name in
let name = CGeneral_utils.mk_class_field_name field_name_qualified in
(name, typ, Annot.Item.empty) :: res
else res in
IList.fold_left modelled_field_in_class [] modelled_fields_in_classes

@ -10,17 +10,16 @@
open! IStd
(** Utility module to retrieve fields of structs of classes *)
open CFrontend_utils
type field_type = Ident.fieldname * Typ.t * (Annot.t * bool) list
val get_fields : Ast_utils.type_ptr_to_sil_type -> Tenv.t -> CContext.curr_class ->
val get_fields : CAst_utils.type_ptr_to_sil_type -> Tenv.t -> CContext.curr_class ->
Clang_ast_t.decl list -> field_type list
val fields_superclass :
Tenv.t -> Clang_ast_t.obj_c_interface_decl_info -> Csu.class_kind -> field_type list
val build_sil_field : Ast_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.named_decl_info ->
val build_sil_field : CAst_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.named_decl_info ->
Clang_ast_t.type_ptr -> Clang_ast_t.property_attribute list -> field_type
val add_missing_fields : Tenv.t -> string -> Csu.class_kind -> field_type list -> unit

@ -12,8 +12,6 @@ open! IStd
module L = Logging
open CFrontend_utils
module rec CTransImpl : CModule_type.CTranslation =
CTrans.CTrans_funct(CFrontend_declImpl)
and CFrontend_declImpl : CModule_type.CFrontend =
@ -37,7 +35,7 @@ let compute_icfg trans_unit_ctx tenv ast =
let init_global_state_capture () =
Ident.NameGenerator.reset ();
CFrontend_config.global_translation_unit_decls := [];
CFrontend_utils.General_utils.reset_block_counter ()
CGeneral_utils.reset_block_counter ()
let do_source_file translation_unit_context ast =
let tenv = Tenv.create () in
@ -62,7 +60,7 @@ let do_source_file translation_unit_context ast =
(*Logging.out "Tenv %a@." Sil.pp_tenv tenv;*)
(* Printing.print_tenv tenv; *)
(*Printing.print_procedures cfg; *)
General_utils.sort_fields_tenv tenv;
CGeneral_utils.sort_fields_tenv tenv;
Tenv.store_to_file tenv_file tenv;
if Config.stats_mode then Cfg.check_cfg_connectedness cfg;
if Config.stats_mode

@ -9,7 +9,6 @@
open! IStd
open CFrontend_utils
(* To create a new checker you should: *)
(* 1. Define a checker function, say my_checker, in this module. *)
(* my_checker should define: *)
@ -83,7 +82,7 @@ let ivar_name an =
| CTL.Stmt (ObjCIvarRefExpr (_, _, _, rei)) ->
let dr_ref = rei.ovrei_decl_ref in
let ivar_pointer = dr_ref.dr_decl_pointer in
(match Ast_utils.get_decl ivar_pointer with
(match CAst_utils.get_decl ivar_pointer with
| Some (ObjCIvarDecl (_, named_decl_info, _, _, _)) ->
named_decl_info.Clang_ast_t.ni_name
| _ -> "")

@ -8,7 +8,6 @@
*)
open! IStd
open CFrontend_utils
open Lexing
open Ctl_lexer
@ -54,7 +53,7 @@ let rec do_frontend_checks_stmt (context:CLintersContext.context) stmt =
IList.iter (do_frontend_checks_decl context') [decl]
| _ -> ());
do_frontend_checks_stmt context' stmt in
let stmts = Ast_utils.get_stmts_from_stmt stmt in
let stmts = CAst_utils.get_stmts_from_stmt stmt in
IList.iter (do_all_checks_on_stmts) stmts
and do_frontend_checks_decl (context: CLintersContext.context) decl =
@ -76,11 +75,11 @@ and do_frontend_checks_decl (context: CLintersContext.context) decl =
let if_decl_opt =
(match context.current_objc_impl with
| Some ObjCImplementationDecl (_, _, _, _, impl_decl_info) ->
Ast_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface
CAst_utils.get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface
| _ -> None) in
let is_factory_method =
(match if_decl_opt with
| Some if_decl -> Ast_utils.is_objc_factory_method if_decl decl
| Some if_decl -> CAst_utils.is_objc_factory_method if_decl decl
| _ -> false) in
let context' = {context with
CLintersContext.current_method = Some decl;

@ -13,8 +13,6 @@ open! IStd
module L = Logging
open CFrontend_utils
module CFrontend_decl_funct(T: CModule_type.CTranslation) : CModule_type.CFrontend =
struct
let model_exists procname =
@ -91,14 +89,14 @@ struct
let process_property_implementation cfg trans_unit_ctx obj_c_property_impl_decl_info =
let property_decl_opt = obj_c_property_impl_decl_info.Clang_ast_t.opidi_property_decl in
match Ast_utils.get_decl_opt_with_decl_ref property_decl_opt with
match CAst_utils.get_decl_opt_with_decl_ref property_decl_opt with
| Some ObjCPropertyDecl (_, _, obj_c_property_decl_info) ->
let ivar_decl_ref = obj_c_property_decl_info.Clang_ast_t.opdi_ivar_decl in
(match Ast_utils.get_decl_opt_with_decl_ref ivar_decl_ref with
(match CAst_utils.get_decl_opt_with_decl_ref ivar_decl_ref with
| Some ObjCIvarDecl (_, named_decl_info, _, _, _) ->
let field_name = General_utils.mk_class_field_name named_decl_info in
let field_name = CGeneral_utils.mk_class_field_name named_decl_info in
let process_accessor pointer ~getter =
(match Ast_utils.get_decl_opt_with_decl_ref pointer with
(match CAst_utils.get_decl_opt_with_decl_ref pointer with
| Some (ObjCMethodDecl (decl_info, _, _) as d) ->
let source_range = decl_info.Clang_ast_t.di_source_range in
let loc =
@ -108,7 +106,7 @@ struct
Some (ProcAttributes.Objc_getter field_name)
else
Some (ProcAttributes.Objc_setter field_name) in
let procname = General_utils.procname_of_decl trans_unit_ctx d in
let procname = CGeneral_utils.procname_of_decl trans_unit_ctx d in
let attrs = { (ProcAttributes.default procname Config.Clang) with
loc = loc;
objc_accessor = property_accessor; } in
@ -132,7 +130,8 @@ struct
| ObjCIvarDecl _ | ObjCPropertyDecl _ -> ()
| _ ->
Logging.out
"\nWARNING: found Method Declaration '%s' skipped. NEED TO BE FIXED\n\n" (Ast_utils.string_of_decl dec);
"\nWARNING: found Method Declaration '%s' skipped. NEED TO BE FIXED\n\n"
(CAst_utils.string_of_decl dec);
()
let process_methods trans_unit_ctx tenv cg cfg curr_class decl_list =
@ -221,26 +220,26 @@ struct
function_decl trans_unit_ctx tenv cfg cg dec None
| ObjCInterfaceDecl(_, name_info, decl_list, _, oi_decl_info) ->
let name = Ast_utils.get_qualified_name name_info in
let name = CAst_utils.get_qualified_name name_info in
let curr_class = ObjcInterface_decl.get_curr_class name oi_decl_info in
ignore
(ObjcInterface_decl.interface_declaration CType_decl.type_ptr_to_sil_type tenv dec);
process_methods trans_unit_ctx tenv cg cfg curr_class decl_list
| ObjCProtocolDecl(_, name_info, decl_list, _, _) ->
let name = Ast_utils.get_qualified_name name_info in
let name = CAst_utils.get_qualified_name name_info in
let curr_class = CContext.ContextProtocol name in
ignore (ObjcProtocol_decl.protocol_decl CType_decl.type_ptr_to_sil_type tenv dec);
process_methods trans_unit_ctx tenv cg cfg curr_class decl_list
| ObjCCategoryDecl(_, name_info, decl_list, _, ocdi) ->
let name = Ast_utils.get_qualified_name name_info in
let name = CAst_utils.get_qualified_name name_info in
let curr_class = ObjcCategory_decl.get_curr_class_from_category_decl name ocdi in
ignore (ObjcCategory_decl.category_decl CType_decl.type_ptr_to_sil_type tenv dec);
process_methods trans_unit_ctx tenv cg cfg curr_class decl_list
| ObjCCategoryImplDecl(_, name_info, decl_list, _, ocidi) ->
let name = Ast_utils.get_qualified_name name_info in
let name = CAst_utils.get_qualified_name name_info in
let curr_class = ObjcCategory_decl.get_curr_class_from_category_impl name ocidi in
ignore (ObjcCategory_decl.category_impl_decl CType_decl.type_ptr_to_sil_type tenv dec);
process_methods trans_unit_ctx tenv cg cfg curr_class decl_list;
@ -259,14 +258,14 @@ struct
| CXXDestructorDecl (decl_info, _, _, _, _) ->
(* di_parent_pointer has pointer to lexical context such as class.*)
let parent_ptr = Option.value_exn decl_info.Clang_ast_t.di_parent_pointer in
let class_decl = Ast_utils.get_decl parent_ptr in
let class_decl = CAst_utils.get_decl parent_ptr in
(match class_decl with
| Some (CXXRecordDecl _)
| Some (ClassTemplateSpecializationDecl _) when Config.cxx ->
let curr_class = CContext.ContextClsDeclPtr parent_ptr in
process_methods trans_unit_ctx tenv cg cfg curr_class [dec]
| Some dec ->
Logging.out "Methods of %s skipped\n" (Ast_utils.string_of_decl dec)
Logging.out "Methods of %s skipped\n" (CAst_utils.string_of_decl dec)
| None -> ())
| VarDecl (decl_info, named_decl_info, qt, ({ vdi_is_global; vdi_init_expr } as vdi))
when vdi_is_global && Option.is_some vdi_init_expr ->
@ -275,13 +274,13 @@ struct
let procname =
(* create the corresponding global variable to get the right pname for its
initializer *)
let global = General_utils.mk_sil_global_var trans_unit_ctx named_decl_info vdi qt in
let global = CGeneral_utils.mk_sil_global_var trans_unit_ctx named_decl_info vdi qt in
(* safe to Option.get because it's a global *)
Option.value_exn (Pvar.get_initializer_pname global) in
let ms = CMethod_signature.make_ms procname [] Ast_expressions.create_void_type
[] decl_info.Clang_ast_t.di_source_range false trans_unit_ctx.CFrontend_config.lang
None None None in
let stmt_info = { si_pointer = Ast_utils.get_fresh_pointer ();
let stmt_info = { si_pointer = CAst_utils.get_fresh_pointer ();
si_source_range = decl_info.di_source_range } in
let body = Clang_ast_t.DeclStmt (stmt_info, [], [dec]) in
ignore (CMethod_trans.create_local_procdesc trans_unit_ctx cfg tenv ms [body] [] false);

@ -9,8 +9,6 @@
open! IStd
open CFrontend_utils
let single_to_multi checker =
fun ctx an ->
let condition, issue_desc_opt = checker ctx an in
@ -178,7 +176,7 @@ let expand_checkers checkers =
let get_err_log translation_unit_context method_decl_opt =
let procname = match method_decl_opt with
| Some method_decl -> General_utils.procname_of_decl translation_unit_context method_decl
| Some method_decl -> CGeneral_utils.procname_of_decl translation_unit_context method_decl
| None -> Procname.Linters_dummy_method in
LintIssues.get_err_log procname
@ -192,7 +190,7 @@ let log_frontend_issue translation_unit_context method_decl_opt key issue_desc =
let exn = Exceptions.Frontend_warning (name, err_desc, __POS__) in
let trace = [ Errlog.make_trace_element 0 issue_desc.CIssue.loc "" [] ] in
let err_kind = issue_desc.CIssue.severity in
let method_name = Ast_utils.full_name_of_decl_opt method_decl_opt in
let method_name = CAst_utils.full_name_of_decl_opt method_decl_opt in
let key = Hashtbl.hash (key ^ method_name) in
Reporting.log_issue_from_errlog err_kind errlog exn ~loc ~ltr:trace
~node_id:(0, key)
@ -207,8 +205,8 @@ let fill_issue_desc_info_and_log context an key issue_desc loc =
(* Calls the set of hard coded checkers (if any) *)
let invoke_set_of_hard_coded_checkers_an an context =
let checkers, key = match an with
| CTL.Decl dec -> decl_checkers_list, Ast_utils.generate_key_decl dec
| CTL.Stmt st -> stmt_checkers_list, Ast_utils.generate_key_stmt st in
| CTL.Decl dec -> decl_checkers_list, CAst_utils.generate_key_decl dec
| CTL.Stmt st -> stmt_checkers_list, CAst_utils.generate_key_stmt st in
IList.iter (fun checker ->
let condition, issue_desc_list = checker context an in
if CTL.eval_formula condition an context then
@ -222,8 +220,8 @@ let invoke_set_of_hard_coded_checkers_an an context =
(* Calls the set of checkers parsed from files (if any) *)
let invoke_set_of_parsed_checkers_an an context =
let key = match an with
| CTL.Decl dec -> Ast_utils.generate_key_decl dec
| CTL.Stmt st -> Ast_utils.generate_key_stmt st in
| CTL.Decl dec -> CAst_utils.generate_key_decl dec
| CTL.Stmt st -> CAst_utils.generate_key_stmt st in
IList.iter (fun (condition, issue_desc) ->
if CIssue.should_run_check issue_desc.CIssue.mode &&
CTL.eval_formula condition an context then
@ -253,7 +251,7 @@ let run_translation_unit_checker (context: CLintersContext.context) dec =
let issue_desc_list = checker context dec in
IList.iter (fun issue_desc ->
if (CIssue.should_run_check issue_desc.CIssue.mode) then
let key = Ast_utils.generate_key_decl dec in
let key = CAst_utils.generate_key_decl dec in
log_frontend_issue context.CLintersContext.translation_unit_context
context.CLintersContext.current_method key issue_desc
) issue_desc_list) translation_unit_checkers_list

@ -1,781 +0,0 @@
(*
* Copyright (c) 2013 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! IStd
(** Module for utility functions for the whole frontend. Includes functions for transformations of
ast nodes and general utility functions such as functions on lists *)
module L = Logging
module F = Format
module Ast_utils =
struct
type type_ptr_to_sil_type = Tenv.t -> Clang_ast_t.type_ptr -> Typ.t
let string_of_decl decl =
let name = Clang_ast_proj.get_decl_kind_string decl in
let info = Clang_ast_proj.get_decl_tuple decl in
Printf.sprintf "<\"%s\"> '%d'" name info.Clang_ast_t.di_pointer
let string_of_unary_operator_kind = function
| `PostInc -> "PostInc"
| `PostDec -> "PostDec"
| `PreInc -> "PreInc"
| `PreDec -> "PreDec"
| `AddrOf -> "AddrOf"
| `Deref -> "Deref"
| `Plus -> "Plus"
| `Minus -> "Minus"
| `Not -> "Not"
| `LNot -> "LNot"
| `Real -> "Real"
| `Imag -> "Imag"
| `Extension -> "Extension"
| `Coawait -> "Coawait"
let string_of_stmt stmt =
let name = Clang_ast_proj.get_stmt_kind_string stmt in
let info, _ = Clang_ast_proj.get_stmt_tuple stmt in
Printf.sprintf "<\"%s\"> '%d'" name info.Clang_ast_t.si_pointer
let get_stmts_from_stmt stmt =
let open Clang_ast_t in
match stmt with
| OpaqueValueExpr (_, lstmt, _, opaque_value_expr_info) ->
(match opaque_value_expr_info.Clang_ast_t.ovei_source_expr with
| Some stmt -> lstmt @ [stmt]
| _ -> lstmt)
(* given that this has not been translated, looking up for variables *)
(* inside leads to inconsistencies *)
| ObjCAtCatchStmt _ ->
[]
| _ -> snd (Clang_ast_proj.get_stmt_tuple stmt)
let fold_qual_name qual_name_list =
match qual_name_list with
| [] -> ""
| name :: quals ->
let s = (IList.fold_right (fun el res -> res ^ el ^ "::") quals "") ^ name in
let no_slash_space = Str.global_replace (Str.regexp "[/ ]") "_" s in
no_slash_space
let get_qualified_name name_info =
fold_qual_name name_info.Clang_ast_t.ni_qual_name
let get_unqualified_name name_info =
let name = match name_info.Clang_ast_t.ni_qual_name with
| name :: _ -> name
| [] -> name_info.Clang_ast_t.ni_name in
fold_qual_name [name]
let get_class_name_from_member member_name_info =
match member_name_info.Clang_ast_t.ni_qual_name with
| _ :: class_qual_list -> fold_qual_name class_qual_list
| [] -> assert false
let make_name_decl name = {
Clang_ast_t.ni_name = name;
ni_qual_name = [name];
}
let make_qual_name_decl class_name_quals name = {
Clang_ast_t.ni_name = name;
ni_qual_name = name :: class_name_quals;
}
let property_name property_impl_decl_info =
let no_property_name = make_name_decl "WARNING_NO_PROPERTY_NAME" in
match property_impl_decl_info.Clang_ast_t.opidi_property_decl with
| Some decl_ref ->
(match decl_ref.Clang_ast_t.dr_name with
| Some n -> n
| _ -> no_property_name)
| None -> no_property_name
let generated_ivar_name property_name =
match property_name.Clang_ast_t.ni_qual_name with
| [name; class_name] ->
let ivar_name = "_" ^ name in
{ Clang_ast_t.ni_name = ivar_name;
ni_qual_name = [ivar_name; class_name]
}
| _ -> make_name_decl property_name.Clang_ast_t.ni_name
let compare_property_attribute =
[%compare: [
`Readonly | `Assign | `Readwrite | `Retain | `Copy | `Nonatomic | `Atomic
| `Weak | `Strong | `Unsafe_unretained | `ExplicitGetter | `ExplicitSetter
]]
let equal_property_attribute att1 att2 =
compare_property_attribute att1 att2 = 0
let get_memory_management_attributes () =
[`Assign; `Retain; `Copy; `Weak; `Strong; `Unsafe_unretained]
let is_retain attribute_opt =
match attribute_opt with
| Some attribute ->
attribute = `Retain || attribute = `Strong
| _ -> false
let is_copy attribute_opt =
match attribute_opt with
| Some attribute ->
attribute = `Copy
| _ -> false
let name_opt_of_name_info_opt name_info_opt =
match name_info_opt with
| Some name_info -> Some (get_qualified_name name_info)
| None -> None
let pointer_counter = ref 0
let get_fresh_pointer () =
pointer_counter := !pointer_counter + 1;
let internal_pointer = -(!pointer_counter) in
internal_pointer
let get_invalid_pointer () =
CFrontend_config.invalid_pointer
let type_from_unary_expr_or_type_trait_expr_info info =
match info.Clang_ast_t.uttei_type_ptr with
| Some tp -> Some tp
| None -> None
let get_decl decl_ptr =
try
Some (Clang_ast_main.PointerMap.find decl_ptr !CFrontend_config.pointer_decl_index)
with Not_found -> Logging.out "decl with pointer %d not found\n" decl_ptr; None
let get_decl_opt decl_ptr_opt =
match decl_ptr_opt with
| Some decl_ptr -> get_decl decl_ptr
| None -> None
let get_stmt stmt_ptr =
try
Some (Clang_ast_main.PointerMap.find stmt_ptr !CFrontend_config.pointer_stmt_index)
with Not_found -> Logging.out "stmt with pointer %d not found\n" stmt_ptr; None
let get_stmt_opt stmt_ptr_opt =
match stmt_ptr_opt with
| Some stmt_ptr -> get_stmt stmt_ptr
| None -> None
let get_decl_opt_with_decl_ref decl_ref_opt =
match decl_ref_opt with
| Some decl_ref -> get_decl decl_ref.Clang_ast_t.dr_decl_pointer
| None -> None
let get_property_of_ivar decl_ptr =
try
Some (Clang_ast_main.PointerMap.find decl_ptr !CFrontend_config.ivar_to_property_index)
with Not_found -> Logging.out "property with pointer %d not found\n" decl_ptr; None
let update_sil_types_map type_ptr sil_type =
CFrontend_config.sil_types_map :=
Clang_ast_types.TypePointerMap.add type_ptr sil_type !CFrontend_config.sil_types_map
let update_enum_map enum_constant_pointer sil_exp =
let open Clang_ast_main in
let (predecessor_pointer_opt, _) =
try PointerMap.find enum_constant_pointer !CFrontend_config.enum_map
with Not_found -> assert false in
let enum_map_value = (predecessor_pointer_opt, Some sil_exp) in
CFrontend_config.enum_map :=
PointerMap.add enum_constant_pointer enum_map_value !CFrontend_config.enum_map
let add_enum_constant enum_constant_pointer predecessor_pointer_opt =
let enum_map_value = (predecessor_pointer_opt, None) in
CFrontend_config.enum_map :=
Clang_ast_main.PointerMap.add enum_constant_pointer enum_map_value !CFrontend_config.enum_map
let get_enum_constant_exp enum_constant_pointer =
Clang_ast_main.PointerMap.find enum_constant_pointer !CFrontend_config.enum_map
let get_type type_ptr =
try
(* There is chance for success only if type_ptr is in fact clang pointer *)
(let raw_ptr = Clang_ast_types.type_ptr_to_clang_pointer type_ptr in
try
Some (Clang_ast_main.PointerMap.find raw_ptr !CFrontend_config.pointer_type_index)
with Not_found -> Logging.out "type with pointer %d not found\n" raw_ptr; None)
with Clang_ast_types.Not_Clang_Pointer ->
(* otherwise, function fails *)
let type_str = Clang_ast_types.type_ptr_to_string type_ptr in
Logging.out "type %s is not clang pointer\n" type_str;
None
let get_desugared_type type_ptr =
let typ_opt = get_type type_ptr in
match typ_opt with
| Some typ ->
let type_info = Clang_ast_proj.get_type_tuple typ in
(match type_info.Clang_ast_t.ti_desugared_type with
| Some ptr -> get_type ptr
| _ -> typ_opt)
| _ -> typ_opt
let get_decl_from_typ_ptr typ_ptr =
let typ_opt = get_desugared_type typ_ptr in
let typ = match typ_opt with Some t -> t | _ -> assert false in
match typ with
| Clang_ast_t.RecordType (_, decl_ptr)
| Clang_ast_t.ObjCInterfaceType (_, decl_ptr) -> get_decl decl_ptr
| _ -> None
(*TODO take the attributes into account too. To be done after we get the attribute's arguments. *)
let is_type_nonnull type_ptr =
let open Clang_ast_t in
match get_type type_ptr with
| Some AttributedType (_, attr_info) -> attr_info.ati_attr_kind = `Nonnull
| _ -> false
let is_type_nullable type_ptr =
let open Clang_ast_t in
match get_type type_ptr with
| Some AttributedType (_, attr_info) -> attr_info.ati_attr_kind = `Nullable
| _ -> false
let string_of_type_ptr type_ptr = Clang_ast_j.string_of_type_ptr type_ptr
let name_of_typedef_type_info {Clang_ast_t.tti_decl_ptr} =
match get_decl tti_decl_ptr with
| Some TypedefDecl (_, name_decl_info, _, _, _) ->
get_qualified_name name_decl_info
| _ -> ""
let name_opt_of_typedef_type_ptr type_ptr =
match get_type type_ptr with
| Some Clang_ast_t.TypedefType (_, typedef_type_info) ->
Some (name_of_typedef_type_info typedef_type_info)
| _ -> None
let string_of_qual_type {Clang_ast_t.qt_type_ptr; qt_is_const} =
Printf.sprintf "%s%s" (if qt_is_const then "is_const " else "") (string_of_type_ptr qt_type_ptr)
let add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt fail_if_not_found =
match decl_ref_opt with (* translate interface first if found *)
| Some dr ->
ignore (type_ptr_to_sil_type tenv (`DeclPtr dr.Clang_ast_t.dr_decl_pointer));
| _ -> if fail_if_not_found then assert false else ()
let add_type_from_decl_ref_list type_ptr_to_sil_type tenv decl_ref_list =
let add_elem dr =
ignore (type_ptr_to_sil_type tenv (`DeclPtr dr.Clang_ast_t.dr_decl_pointer)) in
IList.iter add_elem decl_ref_list
let get_function_decl_with_body decl_ptr =
let open Clang_ast_t in
let decl_opt = get_decl decl_ptr in
let decl_ptr' = match decl_opt with
| Some (FunctionDecl (_, _, _, fdecl_info))
| Some (CXXMethodDecl (_, _, _, fdecl_info, _))
| Some (CXXConstructorDecl (_, _, _, fdecl_info, _))
| Some (CXXConversionDecl (_, _, _, fdecl_info, _))
| Some (CXXDestructorDecl (_, _, _, fdecl_info, _)) ->
fdecl_info.Clang_ast_t.fdi_decl_ptr_with_body
| _ -> Some decl_ptr in
if decl_ptr' = (Some decl_ptr) then decl_opt
else get_decl_opt decl_ptr'
let get_info_from_decl_ref decl_ref =
let name_info = match decl_ref.Clang_ast_t.dr_name with Some ni -> ni | _ -> assert false in
let decl_ptr = decl_ref.Clang_ast_t.dr_decl_pointer in
let type_ptr = match decl_ref.Clang_ast_t.dr_type_ptr with Some tp -> tp | _ -> assert false in
name_info, decl_ptr, type_ptr
(* st |= EF (atomic_pred param) *)
let rec exists_eventually_st atomic_pred param st =
if atomic_pred param st then true
else
let _, st_list = Clang_ast_proj.get_stmt_tuple st in
IList.exists (exists_eventually_st atomic_pred param) st_list
let is_syntactically_global_var decl =
match decl with
| Clang_ast_t.VarDecl (_, _ ,_, vdi) ->
vdi.vdi_is_global && not vdi.vdi_is_static_local
| _ -> false
let is_const_expr_var decl =
match decl with
| Clang_ast_t.VarDecl (_, _ ,_, vdi) -> vdi.vdi_is_const_expr
| _ -> false
let is_ptr_to_objc_class typ class_name =
match typ with
| Some Clang_ast_t.ObjCObjectPointerType (_, {Clang_ast_t.qt_type_ptr}) ->
(match get_desugared_type qt_type_ptr with
| Some ObjCInterfaceType (_, ptr) ->
(match get_decl ptr with
| Some ObjCInterfaceDecl (_, ndi, _, _, _) ->
String.compare ndi.ni_name class_name = 0
| _ -> false)
| _ -> false)
| _ -> false
let full_name_of_decl_opt decl_opt =
match decl_opt with
| Some decl ->
(match Clang_ast_proj.get_named_decl_tuple decl with
| Some (_, name_info) -> get_qualified_name name_info
| None -> "")
| None -> ""
(* Generates a unique number for each variant of a type. *)
let get_tag ast_item =
let item_rep = Obj.repr ast_item in
if Obj.is_block item_rep then
Obj.tag item_rep
else -(Obj.obj item_rep)
(* Generates a key for a statement based on its sub-statements and the statement tag. *)
let rec generate_key_stmt stmt =
let tag_str = string_of_int (get_tag stmt) in
let _, stmts = Clang_ast_proj.get_stmt_tuple stmt in
let tags = IList.map generate_key_stmt stmts in
let buffer = Buffer.create 16 in
let tags = tag_str :: tags in
IList.iter (fun tag -> Buffer.add_string buffer tag) tags;
Buffer.contents buffer
(* Generates a key for a declaration based on its name and the declaration tag. *)
let generate_key_decl decl =
let buffer = Buffer.create 16 in
let name = full_name_of_decl_opt (Some decl) in
Buffer.add_string buffer (string_of_int (get_tag decl));
Buffer.add_string buffer name;
Buffer.contents buffer
let rec get_super_if decl =
match decl with
| Some Clang_ast_t.ObjCImplementationDecl(_, _, _, _, impl_decl_info) ->
(* Try getting the super ref through the impl info, and fall back to
getting the if decl first and getting the super ref through it. *)
let super_ref = get_decl_opt_with_decl_ref impl_decl_info.oidi_super in
if Option.is_some super_ref then
super_ref
else
get_super_if (get_decl_opt_with_decl_ref impl_decl_info.oidi_class_interface)
| Some Clang_ast_t.ObjCInterfaceDecl(_, _, _, _, interface_decl_info) ->
get_decl_opt_with_decl_ref interface_decl_info.otdi_super
| _ -> None
let get_super_impl impl_decl_info =
let objc_interface_decl_current =
get_decl_opt_with_decl_ref
impl_decl_info.Clang_ast_t.oidi_class_interface in
let objc_interface_decl_super = get_super_if objc_interface_decl_current in
let objc_implementation_decl_super =
match objc_interface_decl_super with
| Some ObjCInterfaceDecl(_, _, _, _, interface_decl_info) ->
get_decl_opt_with_decl_ref
interface_decl_info.otdi_implementation
| _ -> None in
match objc_implementation_decl_super with
| Some ObjCImplementationDecl(_, _, decl_list, _, impl_decl_info) ->
Some (decl_list, impl_decl_info)
| _ -> None
let get_super_ObjCImplementationDecl impl_decl_info =
let objc_interface_decl_current =
get_decl_opt_with_decl_ref
impl_decl_info.Clang_ast_t.oidi_class_interface in
let objc_interface_decl_super = get_super_if objc_interface_decl_current in
let objc_implementation_decl_super =
match objc_interface_decl_super with
| Some ObjCInterfaceDecl(_, _, _, _, interface_decl_info) ->
get_decl_opt_with_decl_ref
interface_decl_info.otdi_implementation
| _ -> None in
objc_implementation_decl_super
let get_impl_decl_info dec =
match dec with
| Clang_ast_t.ObjCImplementationDecl (_, _, _, _, idi) -> Some idi
| _ -> None
let default_blacklist =
let open CFrontend_config in
[nsobject_cl; nsproxy_cl]
let rec is_objc_if_descendant ?(blacklist = default_blacklist) if_decl ancestors =
(* List of ancestors to check for and list of classes to short-circuit to
false can't intersect *)
if not String.Set.(is_empty (inter (of_list blacklist) (of_list ancestors))) then
failwith "Blacklist and ancestors must be mutually exclusive."
else
match if_decl with
| Some Clang_ast_t.ObjCInterfaceDecl (_, ndi, _, _, _) ->
let in_list some_list =
IList.mem String.equal ndi.Clang_ast_t.ni_name some_list in
not (in_list blacklist)
&& (in_list ancestors
|| is_objc_if_descendant ~blacklist:blacklist (get_super_if if_decl) ancestors)
| _ -> false
let rec type_ptr_to_objc_interface type_ptr =
let typ_opt = get_desugared_type type_ptr in
match (typ_opt : Clang_ast_t.c_type option) with
| Some ObjCInterfaceType (_, decl_ptr) -> get_decl decl_ptr
| Some ObjCObjectPointerType (_, (inner_qual_type: Clang_ast_t.qual_type)) ->
type_ptr_to_objc_interface inner_qual_type.qt_type_ptr
| Some FunctionProtoType (_, function_type_info, _)
| Some FunctionNoProtoType (_, function_type_info) ->
type_ptr_to_objc_interface function_type_info.Clang_ast_t.fti_return_type
| _ -> None
let if_decl_to_di_pointer_opt if_decl =
match if_decl with
| Clang_ast_t.ObjCInterfaceDecl (if_decl_info, _, _, _, _) ->
Some if_decl_info.di_pointer
| _ -> None
let is_instance_type type_ptr =
match name_opt_of_typedef_type_ptr type_ptr with
| Some name -> name = "instancetype"
| None -> false
let return_type_matches_class_type rtp type_decl_pointer =
if is_instance_type rtp then
true
else
let return_type_decl_opt = type_ptr_to_objc_interface rtp in
let return_type_decl_pointer_opt =
Option.map ~f:if_decl_to_di_pointer_opt return_type_decl_opt in
(Some type_decl_pointer) = return_type_decl_pointer_opt
let is_objc_factory_method if_decl meth_decl =
let if_type_decl_pointer = if_decl_to_di_pointer_opt if_decl in
match meth_decl with
| Clang_ast_t.ObjCMethodDecl (_, _, omdi) ->
(not omdi.omdi_is_instance_method) &&
(return_type_matches_class_type omdi.omdi_result_type if_type_decl_pointer)
| _ -> false
let name_of_decl_ref_opt (decl_ref_opt: Clang_ast_t.decl_ref option) =
match decl_ref_opt with
| Some decl_ref ->
(match decl_ref.dr_name with
| Some named_decl_info -> Some named_decl_info.ni_name
| _ -> None)
| _ -> None
(*
let rec getter_attribute_opt attributes =
match attributes with
| [] -> None
| attr:: rest ->
match attr with
| `Getter getter -> getter.Clang_ast_t.dr_name
| _ -> (getter_attribute_opt rest)
let rec setter_attribute_opt attributes =
match attributes with
| [] -> None
| attr:: rest ->
match attr with
| `Setter setter -> setter.Clang_ast_t.dr_name
| _ -> (setter_attribute_opt rest)
*)
end
(* Global counter for anonymous block*)
let block_counter = ref 0
(* Returns a fresh index for a new anonymous block *)
let get_fresh_block_index () =
block_counter := !block_counter +1;
!block_counter
module General_utils =
struct
type var_info = Clang_ast_t.decl_info * Clang_ast_t.qual_type * Clang_ast_t.var_decl_info * bool
let rec swap_elements_list l =
match l with
| el1:: el2:: rest ->
el2:: el1:: (swap_elements_list rest)
| [] -> []
| _ -> assert false
let rec string_from_list l =
match l with
| [] -> ""
| [item] -> item
| item:: l' -> item^" "^(string_from_list l')
let rec append_no_duplicates eq list1 list2 =
match list2 with
| el:: rest2 ->
if (IList.mem eq el list1) then
(append_no_duplicates eq list1 rest2)
else (append_no_duplicates eq list1 rest2)@[el]
| [] -> list1
let append_no_duplicates_csu list1 list2 =
append_no_duplicates Typename.equal list1 list2
let append_no_duplicates_methods list1 list2 =
append_no_duplicates Procname.equal list1 list2
let append_no_duplicated_vars list1 list2 =
let eq (m1, t1) (m2, t2) = (Mangled.equal m1 m2) && (Typ.equal t1 t2) in
append_no_duplicates eq list1 list2
let append_no_duplicates_annotations list1 list2 =
let eq (annot1, _) (annot2, _) = annot1.Annot.class_name = annot2.Annot.class_name in
append_no_duplicates eq list1 list2
let add_no_duplicates_fields field_tuple l =
let rec replace_field field_tuple l found =
match field_tuple, l with
| (field, typ, annot), ((old_field, old_typ, old_annot) as old_field_tuple :: rest) ->
let ret_list, ret_found = replace_field field_tuple rest found in
if Ident.equal_fieldname field old_field && Typ.equal typ old_typ then
let annotations = append_no_duplicates_annotations annot old_annot in
(field, typ, annotations) :: ret_list, true
else old_field_tuple :: ret_list, ret_found
| _, [] -> [], found in
let new_list, found = replace_field field_tuple l false in
if found then new_list
else field_tuple :: l
let rec append_no_duplicates_fields list1 list2 =
match list1 with
| field_tuple :: rest ->
let updated_list2 = append_no_duplicates_fields rest list2 in
add_no_duplicates_fields field_tuple updated_list2
| [] -> list2
let sort_fields fields =
let compare (name1, _, _) (name2, _, _) =
Ident.compare_fieldname name1 name2 in
IList.sort compare fields
let sort_fields_tenv tenv =
let sort_fields_struct name ({StructTyp.fields} as st) =
ignore (Tenv.mk_struct tenv ~default:st ~fields:(sort_fields fields) name) in
Tenv.iter sort_fields_struct tenv
let rec collect_list_tuples l (a, a1, b, c, d) =
match l with
| [] -> (a, a1, b, c, d)
| (a', a1', b', c', d'):: l' -> collect_list_tuples l' (a@a', a1@a1', b@b', c@c', d@d')
let is_static_var var_decl_info =
match var_decl_info.Clang_ast_t.vdi_storage_class with
| Some sc -> sc = CFrontend_config.static
| _ -> false
let block_procname_with_index defining_proc i =
Config.anonymous_block_prefix^(Procname.to_string defining_proc)^Config.anonymous_block_num_sep^(string_of_int i)
(* Makes a fresh name for a block defined inside the defining procedure.*)
(* It updates the global block_counter *)
let mk_fresh_block_procname defining_proc =
let name = block_procname_with_index defining_proc (get_fresh_block_index ()) in
Procname.mangled_objc_block name
(* Returns the next fresh name for a block defined inside the defining procedure *)
(* It does not update the global block_counter *)
let get_next_block_pvar defining_proc =
let name = block_procname_with_index defining_proc (!block_counter +1) in
Pvar.mk_tmp name defining_proc
(* Reset block counter *)
let reset_block_counter () =
block_counter := 0
let rec zip xs ys =
match xs, ys with
| [], _
| _, [] -> []
| x :: xs, y :: ys -> (x, y) :: zip xs ys
let list_range i j =
let rec aux n acc =
if n < i then acc else aux (n -1) (n :: acc)
in aux j [] ;;
let replicate n el = IList.map (fun _ -> el) (list_range 0 (n -1))
let mk_class_field_name field_qual_name =
let field_name = field_qual_name.Clang_ast_t.ni_name in
let class_name = Ast_utils.get_class_name_from_member field_qual_name in
Ident.create_fieldname (Mangled.mangled field_name class_name) 0
let is_cpp_translation translation_unit_context =
let lang = translation_unit_context.CFrontend_config.lang in
lang = CFrontend_config.CPP || lang = CFrontend_config.ObjCPP
let is_objc_extension translation_unit_context =
let lang = translation_unit_context.CFrontend_config.lang in
lang = CFrontend_config.ObjC || lang = CFrontend_config.ObjCPP
let rec get_mangled_method_name function_decl_info method_decl_info =
(* For virtual methods return mangled name of the method from most base class
Go recursively until there is no method in any parent class. All names
of the same method need to be the same, otherwise dynamic dispatch won't
work. *)
let open Clang_ast_t in
match method_decl_info.xmdi_overriden_methods with
| [] -> function_decl_info.fdi_mangled_name
| base1_dr :: _ ->
(let base1 = match Ast_utils.get_decl base1_dr.dr_decl_pointer with
| Some b -> b
| _ -> assert false in
match base1 with
| CXXMethodDecl (_, _, _, fdi, mdi)
| CXXConstructorDecl (_, _, _, fdi, mdi)
| CXXConversionDecl (_, _, _, fdi, mdi)
| CXXDestructorDecl (_, _, _, fdi, mdi) ->
get_mangled_method_name fdi mdi
| _ -> assert false)
let mk_procname_from_function translation_unit_context name function_decl_info_opt =
let file =
match function_decl_info_opt with
| Some (decl_info, function_decl_info) ->
(match function_decl_info.Clang_ast_t.fdi_storage_class with
| Some "static" ->
let file_opt = (fst decl_info.Clang_ast_t.di_source_range).Clang_ast_t.sl_file in
Option.value_map ~f:SourceFile.to_string ~default:"" file_opt
| _ -> "")
| None -> "" in
let mangled_opt = match function_decl_info_opt with
| Some (_, function_decl_info) -> function_decl_info.Clang_ast_t.fdi_mangled_name
| _ -> None in
let mangled_name =
match mangled_opt with
| Some m when is_cpp_translation translation_unit_context -> m
| _ -> "" in
let mangled = (Utils.string_crc_hex32 file) ^ mangled_name in
if String.length file = 0 && String.length mangled_name = 0 then
Procname.from_string_c_fun name
else
Procname.C (Procname.c name mangled)
let mk_procname_from_objc_method class_name method_name method_kind =
Procname.ObjC_Cpp
(Procname.objc_cpp class_name method_name method_kind)
let mk_procname_from_cpp_method class_name method_name ?meth_decl mangled =
let method_kind = match meth_decl with
| Some (Clang_ast_t.CXXConstructorDecl (_, _, _, _, {xmdi_is_constexpr})) ->
Procname.CPPConstructor (mangled, xmdi_is_constexpr)
| _ ->
Procname.CPPMethod mangled in
Procname.ObjC_Cpp
(Procname.objc_cpp class_name method_name method_kind)
let get_objc_method_name name_info mdi class_name =
let method_name = name_info.Clang_ast_t.ni_name in
let is_instance = mdi.Clang_ast_t.omdi_is_instance_method in
let method_kind = Procname.objc_method_kind_of_bool is_instance in
mk_procname_from_objc_method class_name method_name method_kind
let procname_of_decl translation_unit_context meth_decl =
let open Clang_ast_t in
match meth_decl with
| FunctionDecl (decl_info, name_info, _, fdi) ->
let name = Ast_utils.get_qualified_name name_info in
let function_info = Some (decl_info, fdi) in
mk_procname_from_function translation_unit_context name function_info
| CXXMethodDecl (_, name_info, _, fdi, mdi)
| CXXConstructorDecl (_, name_info, _, fdi, mdi)
| CXXConversionDecl (_, name_info, _, fdi, mdi)
| CXXDestructorDecl (_, name_info, _, fdi, mdi) ->
let mangled = get_mangled_method_name fdi mdi in
let method_name = Ast_utils.get_unqualified_name name_info in
let class_name = Ast_utils.get_class_name_from_member name_info in
mk_procname_from_cpp_method class_name method_name ~meth_decl mangled
| ObjCMethodDecl (_, name_info, mdi) ->
let class_name = Ast_utils.get_class_name_from_member name_info in
get_objc_method_name name_info mdi class_name
| BlockDecl _ ->
let name = Config.anonymous_block_prefix ^ Config.anonymous_block_num_sep ^
(string_of_int (get_fresh_block_index ())) in
Procname.mangled_objc_block name
| _ -> assert false
let get_var_name_mangled name_info var_decl_info =
let clang_name = Ast_utils.get_qualified_name name_info in
let param_idx_opt = var_decl_info.Clang_ast_t.vdi_parm_index_in_function in
let name_string =
match clang_name, param_idx_opt with
| "", Some index -> "__param_" ^ string_of_int index
| "", None -> assert false
| _ -> clang_name in
let mangled = match param_idx_opt with
| Some index -> Mangled.mangled name_string (string_of_int index)
| None -> Mangled.from_string name_string in
name_string, mangled
let mk_sil_global_var {CFrontend_config.source_file} ?(mk_name=fun _ x -> x)
named_decl_info var_decl_info qt =
let name_string, simple_name = get_var_name_mangled named_decl_info var_decl_info in
let translation_unit =
match (var_decl_info.Clang_ast_t.vdi_storage_class,
var_decl_info.Clang_ast_t.vdi_init_expr) with
| Some "extern", None ->
(* some compilers simply disregard "extern" when the global is given some initialisation
code, which is why we make sure that [vdi_init_expr] is None here... *)
SourceFile.empty
| _ ->
source_file in
let is_constexpr = var_decl_info.Clang_ast_t.vdi_is_const_expr in
let is_pod =
Ast_utils.get_desugared_type qt.Clang_ast_t.qt_type_ptr
|> Fn.flip Option.bind (function
| Clang_ast_t.RecordType(_, decl_ptr) -> Ast_utils.get_decl decl_ptr
| _ -> None)
|> Option.value_map ~default:true ~f:(function
| Clang_ast_t.CXXRecordDecl(_, _, _, _, _, _, _, {xrdi_is_pod})
| Clang_ast_t.ClassTemplateSpecializationDecl(_, _, _, _, _, _, _, {xrdi_is_pod}, _) ->
xrdi_is_pod
| _ -> true) in
Pvar.mk_global ~is_constexpr ~is_pod
~is_static_local:(var_decl_info.Clang_ast_t.vdi_is_static_local)
(mk_name name_string simple_name) translation_unit
let mk_sil_var trans_unit_ctx named_decl_info decl_info_type_ptr_opt procname outer_procname =
match decl_info_type_ptr_opt with
| Some (decl_info, qt, var_decl_info, should_be_mangled) ->
let name_string, simple_name = get_var_name_mangled named_decl_info var_decl_info in
if var_decl_info.Clang_ast_t.vdi_is_global then
let mk_name =
if var_decl_info.Clang_ast_t.vdi_is_static_local then
Some (fun name_string _ ->
Mangled.from_string ((Procname.to_string outer_procname) ^ "_" ^ name_string))
else None in
mk_sil_global_var trans_unit_ctx ?mk_name named_decl_info var_decl_info qt
else if not should_be_mangled then Pvar.mk simple_name procname
else
let start_location = fst decl_info.Clang_ast_t.di_source_range in
let line_opt = start_location.Clang_ast_t.sl_line in
let line_str = match line_opt with | Some line -> string_of_int line | None -> "" in
let mangled = Utils.string_crc_hex32 line_str in
let mangled_name = Mangled.mangled name_string mangled in
Pvar.mk mangled_name procname
| None ->
let name_string = Ast_utils.get_qualified_name named_decl_info in
Pvar.mk (Mangled.from_string name_string) procname
end

@ -1,253 +0,0 @@
(*
* Copyright (c) 2013 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! IStd
(** Module for utility functions for the whole frontend. Includes functions for transformations of
ast nodes and general utility functions such as functions on lists *)
module Ast_utils :
sig
val string_of_stmt : Clang_ast_t.stmt -> string
val get_stmts_from_stmt : Clang_ast_t.stmt -> Clang_ast_t.stmt list
val string_of_decl : Clang_ast_t.decl -> string
val string_of_unary_operator_kind : Clang_ast_t.unary_operator_kind -> string
val name_opt_of_name_info_opt : Clang_ast_t.named_decl_info option -> string option
val property_name : Clang_ast_t.obj_c_property_impl_decl_info -> Clang_ast_t.named_decl_info
val compare_property_attribute :
Clang_ast_t.property_attribute -> Clang_ast_t.property_attribute -> int
val generated_ivar_name :
Clang_ast_t.named_decl_info -> Clang_ast_t.named_decl_info
val equal_property_attribute :
Clang_ast_t.property_attribute -> Clang_ast_t.property_attribute -> bool
val get_memory_management_attributes : unit -> Clang_ast_t.property_attribute list
val is_retain : Clang_ast_t.property_attribute option -> bool
val is_copy : Clang_ast_t.property_attribute option -> bool
val is_type_nonnull : Clang_ast_t.type_ptr -> bool
val is_type_nullable : Clang_ast_t.type_ptr -> bool
val get_fresh_pointer : unit -> Clang_ast_t.pointer
val get_invalid_pointer : unit -> Clang_ast_t.pointer
val type_from_unary_expr_or_type_trait_expr_info :
Clang_ast_t.unary_expr_or_type_trait_expr_info -> Clang_ast_t.type_ptr option
val get_decl : Clang_ast_t.pointer -> Clang_ast_t.decl option
val get_decl_opt : Clang_ast_t.pointer option -> Clang_ast_t.decl option
val get_stmt : Clang_ast_t.pointer -> Clang_ast_t.stmt option
val get_stmt_opt : Clang_ast_t.pointer option -> Clang_ast_t.stmt option
val get_decl_opt_with_decl_ref : Clang_ast_t.decl_ref option -> Clang_ast_t.decl option
val get_property_of_ivar : Clang_ast_t.pointer -> Clang_ast_t.decl option
val update_sil_types_map : Clang_ast_t.type_ptr -> Typ.t -> unit
val update_enum_map : Clang_ast_t.pointer -> Exp.t -> unit
val add_enum_constant : Clang_ast_t.pointer -> Clang_ast_t.pointer option -> unit
val get_enum_constant_exp : Clang_ast_t.pointer -> Clang_ast_t.pointer option * Exp.t option
(** returns sanitized, fully qualified name given name info *)
val get_qualified_name : Clang_ast_t.named_decl_info -> string
(** returns sanitized unqualified name given name info *)
val get_unqualified_name : Clang_ast_t.named_decl_info -> string
(** returns qualified class name given member name info *)
val get_class_name_from_member : Clang_ast_t.named_decl_info -> string
(** looks up clang pointer to type and returns c_type. It requires type_ptr to be `TPtr. *)
val get_type : Clang_ast_t.type_ptr -> Clang_ast_t.c_type option
(** looks up clang pointer to type and resolves any sugar around it.
See get_type for more info and restrictions *)
val get_desugared_type : Clang_ast_t.type_ptr -> Clang_ast_t.c_type option
(** returns declaration of the type for certain types
(RecordType, ObjCInterfaceType and None for others *)
val get_decl_from_typ_ptr : Clang_ast_t.type_ptr -> Clang_ast_t.decl option
(** returns string representation of type_ptr
NOTE: this doesn't expand type, it only converts type_ptr to string *)
val string_of_type_ptr : Clang_ast_t.type_ptr -> string
val name_of_typedef_type_info : Clang_ast_t.typedef_type_info -> string
(** returns name of typedef if type_ptr points to Typedef, None otherwise *)
val name_opt_of_typedef_type_ptr : Clang_ast_t.type_ptr -> string option
val string_of_qual_type : Clang_ast_t.qual_type -> string
val make_name_decl : string -> Clang_ast_t.named_decl_info
val make_qual_name_decl : string list -> string -> Clang_ast_t.named_decl_info
type type_ptr_to_sil_type = Tenv.t -> Clang_ast_t.type_ptr -> Typ.t
val add_type_from_decl_ref : type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl_ref option ->
bool -> unit
val add_type_from_decl_ref_list : type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl_ref list ->
unit
val get_function_decl_with_body : Clang_ast_t.pointer -> Clang_ast_t.decl option
val get_info_from_decl_ref : Clang_ast_t.decl_ref ->
Clang_ast_t.named_decl_info * Clang_ast_t.pointer * Clang_ast_t.type_ptr
val exists_eventually_st : ('a -> Clang_ast_t.stmt -> bool) -> 'a -> Clang_ast_t.stmt -> bool
(** true if a declaration is a global variable *)
val is_syntactically_global_var : Clang_ast_t.decl -> bool
(** true if a declaration is a constexpr variable *)
val is_const_expr_var : Clang_ast_t.decl -> bool
val is_ptr_to_objc_class : Clang_ast_t.c_type option -> string -> bool
val full_name_of_decl_opt : Clang_ast_t.decl option -> string
(** Generates a key for a statement based on its sub-statements and the statement tag. *)
val generate_key_stmt : Clang_ast_t.stmt -> string
(** Generates a key for a declaration based on its name and the declaration tag. *)
val generate_key_decl : Clang_ast_t.decl -> string
(** Given an objc impl or interface decl, returns the objc interface decl of
the superclass, if any. *)
val get_super_if : Clang_ast_t.decl option -> Clang_ast_t.decl option
val get_impl_decl_info : Clang_ast_t.decl -> Clang_ast_t.obj_c_implementation_decl_info option
(** Given an objc impl decl info, return the super class's list of decls and
its objc impl decl info. *)
val get_super_impl :
Clang_ast_t.obj_c_implementation_decl_info ->
(Clang_ast_t.decl list *
Clang_ast_t.obj_c_implementation_decl_info)
option
(** Given an objc impl decl info, return its super class implementation decl *)
val get_super_ObjCImplementationDecl :
Clang_ast_t.obj_c_implementation_decl_info -> Clang_ast_t.decl option
(** Recursively go up the inheritance hierarchy of a given ObjCInterfaceDecl.
Returns true if the passed in decl is an objc interface decl that's an
eventual descendant of one of the classes passed in.
Ancestors param is a list of strings that represent the class names.
Will short-circuit on NSObject and NSProxy since those are known to be
common base classes.
The list of classes to short-circuit on can be overridden via specifying
the named `blacklist` argument. *)
val is_objc_if_descendant :
?blacklist:string list -> Clang_ast_t.decl option -> string list -> bool
val type_ptr_to_objc_interface : Clang_ast_types.t_ptr -> Clang_ast_t.decl option
(** A class method that returns an instance of the class is a factory method. *)
val is_objc_factory_method : Clang_ast_t.decl -> Clang_ast_t.decl -> bool
val name_of_decl_ref_opt : Clang_ast_t.decl_ref option -> string option
end
module General_utils :
sig
type var_info = Clang_ast_t.decl_info * Clang_ast_t.qual_type * Clang_ast_t.var_decl_info * bool
val string_from_list : string list -> string
val append_no_duplicates_fields : (Ident.fieldname * Typ.t * Annot.Item.t) list ->
(Ident.fieldname * Typ.t * Annot.Item.t) list ->
(Ident.fieldname * Typ.t * Annot.Item.t) list
val append_no_duplicates_csu :
Typename.t list -> Typename.t list -> Typename.t list
val append_no_duplicates_methods : Procname.t list -> Procname.t list -> Procname.t list
val append_no_duplicated_vars :
(Mangled.t * Typ.t) list -> (Mangled.t * Typ.t) list -> (Mangled.t * Typ.t) list
val sort_fields :
(Ident.fieldname * Typ.t * Annot.Item.t) list ->
(Ident.fieldname * Typ.t * Annot.Item.t) list
val sort_fields_tenv : Tenv.t -> unit
val collect_list_tuples : ('a list * 'b list * 'c list * 'd list * 'e list) list ->
'a list * 'b list * 'c list * 'd list * 'e list ->
'a list * 'b list * 'c list * 'd list * 'e list
val swap_elements_list : 'a list -> 'a list
val is_static_var : Clang_ast_t.var_decl_info -> bool
val mk_fresh_block_procname : Procname.t -> Procname.t
val get_next_block_pvar : Procname.t -> Pvar.t
val reset_block_counter : unit -> unit
val zip: 'a list -> 'b list -> ('a * 'b) list
val list_range: int -> int -> int list
val replicate: int -> 'a -> 'a list
val mk_procname_from_objc_method : string -> string -> Procname.objc_cpp_method_kind -> Procname.t
val mk_procname_from_function : CFrontend_config.translation_unit_context -> string
-> (Clang_ast_t.decl_info * Clang_ast_t.function_decl_info) option -> Procname.t
val get_mangled_method_name : Clang_ast_t.function_decl_info ->
Clang_ast_t.cxx_method_decl_info -> string option
val mk_procname_from_cpp_method :
string -> string -> ?meth_decl:Clang_ast_t.decl -> string option -> Procname.t
val procname_of_decl : CFrontend_config.translation_unit_context -> Clang_ast_t.decl -> Procname.t
val mk_class_field_name : Clang_ast_t.named_decl_info -> Ident.fieldname
val get_var_name_mangled : Clang_ast_t.named_decl_info -> Clang_ast_t.var_decl_info ->
(string * Mangled.t)
val mk_sil_global_var : CFrontend_config.translation_unit_context ->
?mk_name:(string -> Mangled.t -> Mangled.t) ->
Clang_ast_t.named_decl_info -> Clang_ast_t.var_decl_info -> Clang_ast_t.qual_type -> Pvar.t
val mk_sil_var : CFrontend_config.translation_unit_context -> Clang_ast_t.named_decl_info ->
var_info option -> Procname.t -> Procname.t -> Pvar.t
(** true if the current language is C++ or ObjC++ *)
val is_cpp_translation : CFrontend_config.translation_unit_context -> bool
(** true if the current language is ObjC or ObjC++ *)
val is_objc_extension : CFrontend_config.translation_unit_context -> bool
end

@ -0,0 +1,296 @@
(*
* Copyright (c) 2013 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! IStd
(** General utility functions such as functions on lists *)
module L = Logging
module F = Format
type var_info = Clang_ast_t.decl_info * Clang_ast_t.qual_type * Clang_ast_t.var_decl_info * bool
let rec swap_elements_list l =
match l with
| el1:: el2:: rest ->
el2:: el1:: (swap_elements_list rest)
| [] -> []
| _ -> assert false
let rec string_from_list l =
match l with
| [] -> ""
| [item] -> item
| item:: l' -> item^" "^(string_from_list l')
let rec append_no_duplicates eq list1 list2 =
match list2 with
| el:: rest2 ->
if (IList.mem eq el list1) then
(append_no_duplicates eq list1 rest2)
else (append_no_duplicates eq list1 rest2)@[el]
| [] -> list1
let append_no_duplicates_csu list1 list2 =
append_no_duplicates Typename.equal list1 list2
let append_no_duplicates_methods list1 list2 =
append_no_duplicates Procname.equal list1 list2
let append_no_duplicates_annotations list1 list2 =
let eq (annot1, _) (annot2, _) = annot1.Annot.class_name = annot2.Annot.class_name in
append_no_duplicates eq list1 list2
let add_no_duplicates_fields field_tuple l =
let rec replace_field field_tuple l found =
match field_tuple, l with
| (field, typ, annot), ((old_field, old_typ, old_annot) as old_field_tuple :: rest) ->
let ret_list, ret_found = replace_field field_tuple rest found in
if Ident.equal_fieldname field old_field && Typ.equal typ old_typ then
let annotations = append_no_duplicates_annotations annot old_annot in
(field, typ, annotations) :: ret_list, true
else old_field_tuple :: ret_list, ret_found
| _, [] -> [], found in
let new_list, found = replace_field field_tuple l false in
if found then new_list
else field_tuple :: l
let rec append_no_duplicates_fields list1 list2 =
match list1 with
| field_tuple :: rest ->
let updated_list2 = append_no_duplicates_fields rest list2 in
add_no_duplicates_fields field_tuple updated_list2
| [] -> list2
let sort_fields fields =
let compare (name1, _, _) (name2, _, _) =
Ident.compare_fieldname name1 name2 in
IList.sort compare fields
let sort_fields_tenv tenv =
let sort_fields_struct name ({StructTyp.fields} as st) =
ignore (Tenv.mk_struct tenv ~default:st ~fields:(sort_fields fields) name) in
Tenv.iter sort_fields_struct tenv
let rec collect_list_tuples l (a, a1, b, c, d) =
match l with
| [] -> (a, a1, b, c, d)
| (a', a1', b', c', d'):: l' -> collect_list_tuples l' (a@a', a1@a1', b@b', c@c', d@d')
let is_static_var var_decl_info =
match var_decl_info.Clang_ast_t.vdi_storage_class with
| Some sc -> sc = CFrontend_config.static
| _ -> false
let block_procname_with_index defining_proc i =
Config.anonymous_block_prefix ^
(Procname.to_string defining_proc) ^
Config.anonymous_block_num_sep ^
(string_of_int i)
(* Global counter for anonymous block*)
let block_counter = ref 0
(* Returns a fresh index for a new anonymous block *)
let get_fresh_block_index () =
block_counter := !block_counter +1;
!block_counter
(* Makes a fresh name for a block defined inside the defining procedure.*)
(* It updates the global block_counter *)
let mk_fresh_block_procname defining_proc =
let name = block_procname_with_index defining_proc (get_fresh_block_index ()) in
Procname.mangled_objc_block name
(* Returns the next fresh name for a block defined inside the defining procedure *)
(* It does not update the global block_counter *)
let get_next_block_pvar defining_proc =
let name = block_procname_with_index defining_proc (!block_counter +1) in
Pvar.mk_tmp name defining_proc
(* Reset block counter *)
let reset_block_counter () =
block_counter := 0
let rec zip xs ys =
match xs, ys with
| [], _
| _, [] -> []
| x :: xs, y :: ys -> (x, y) :: zip xs ys
let list_range i j =
let rec aux n acc =
if n < i then acc else aux (n -1) (n :: acc)
in aux j [] ;;
let replicate n el = IList.map (fun _ -> el) (list_range 0 (n -1))
let mk_class_field_name field_qual_name =
let field_name = field_qual_name.Clang_ast_t.ni_name in
let class_name = CAst_utils.get_class_name_from_member field_qual_name in
Ident.create_fieldname (Mangled.mangled field_name class_name) 0
let is_cpp_translation translation_unit_context =
let lang = translation_unit_context.CFrontend_config.lang in
lang = CFrontend_config.CPP || lang = CFrontend_config.ObjCPP
let is_objc_extension translation_unit_context =
let lang = translation_unit_context.CFrontend_config.lang in
lang = CFrontend_config.ObjC || lang = CFrontend_config.ObjCPP
let rec get_mangled_method_name function_decl_info method_decl_info =
(* For virtual methods return mangled name of the method from most base class
Go recursively until there is no method in any parent class. All names
of the same method need to be the same, otherwise dynamic dispatch won't
work. *)
let open Clang_ast_t in
match method_decl_info.xmdi_overriden_methods with
| [] -> function_decl_info.fdi_mangled_name
| base1_dr :: _ ->
(let base1 = match CAst_utils.get_decl base1_dr.dr_decl_pointer with
| Some b -> b
| _ -> assert false in
match base1 with
| CXXMethodDecl (_, _, _, fdi, mdi)
| CXXConstructorDecl (_, _, _, fdi, mdi)
| CXXConversionDecl (_, _, _, fdi, mdi)
| CXXDestructorDecl (_, _, _, fdi, mdi) ->
get_mangled_method_name fdi mdi
| _ -> assert false)
let mk_procname_from_function translation_unit_context name function_decl_info_opt =
let file =
match function_decl_info_opt with
| Some (decl_info, function_decl_info) ->
(match function_decl_info.Clang_ast_t.fdi_storage_class with
| Some "static" ->
let file_opt = (fst decl_info.Clang_ast_t.di_source_range).Clang_ast_t.sl_file in
Option.value_map ~f:SourceFile.to_string ~default:"" file_opt
| _ -> "")
| None -> "" in
let mangled_opt = match function_decl_info_opt with
| Some (_, function_decl_info) -> function_decl_info.Clang_ast_t.fdi_mangled_name
| _ -> None in
let mangled_name =
match mangled_opt with
| Some m when is_cpp_translation translation_unit_context -> m
| _ -> "" in
let mangled = (Utils.string_crc_hex32 file) ^ mangled_name in
if String.length file = 0 && String.length mangled_name = 0 then
Procname.from_string_c_fun name
else
Procname.C (Procname.c name mangled)
let mk_procname_from_objc_method class_name method_name method_kind =
Procname.ObjC_Cpp
(Procname.objc_cpp class_name method_name method_kind)
let mk_procname_from_cpp_method class_name method_name ?meth_decl mangled =
let method_kind = match meth_decl with
| Some (Clang_ast_t.CXXConstructorDecl (_, _, _, _, {xmdi_is_constexpr})) ->
Procname.CPPConstructor (mangled, xmdi_is_constexpr)
| _ ->
Procname.CPPMethod mangled in
Procname.ObjC_Cpp
(Procname.objc_cpp class_name method_name method_kind)
let get_objc_method_name name_info mdi class_name =
let method_name = name_info.Clang_ast_t.ni_name in
let is_instance = mdi.Clang_ast_t.omdi_is_instance_method in
let method_kind = Procname.objc_method_kind_of_bool is_instance in
mk_procname_from_objc_method class_name method_name method_kind
let procname_of_decl translation_unit_context meth_decl =
let open Clang_ast_t in
match meth_decl with
| FunctionDecl (decl_info, name_info, _, fdi) ->
let name = CAst_utils.get_qualified_name name_info in
let function_info = Some (decl_info, fdi) in
mk_procname_from_function translation_unit_context name function_info
| CXXMethodDecl (_, name_info, _, fdi, mdi)
| CXXConstructorDecl (_, name_info, _, fdi, mdi)
| CXXConversionDecl (_, name_info, _, fdi, mdi)
| CXXDestructorDecl (_, name_info, _, fdi, mdi) ->
let mangled = get_mangled_method_name fdi mdi in
let method_name = CAst_utils.get_unqualified_name name_info in
let class_name = CAst_utils.get_class_name_from_member name_info in
mk_procname_from_cpp_method class_name method_name ~meth_decl mangled
| ObjCMethodDecl (_, name_info, mdi) ->
let class_name = CAst_utils.get_class_name_from_member name_info in
get_objc_method_name name_info mdi class_name
| BlockDecl _ ->
let name = Config.anonymous_block_prefix ^ Config.anonymous_block_num_sep ^
(string_of_int (get_fresh_block_index ())) in
Procname.mangled_objc_block name
| _ -> assert false
let get_var_name_mangled name_info var_decl_info =
let clang_name = CAst_utils.get_qualified_name name_info in
let param_idx_opt = var_decl_info.Clang_ast_t.vdi_parm_index_in_function in
let name_string =
match clang_name, param_idx_opt with
| "", Some index -> "__param_" ^ string_of_int index
| "", None -> assert false
| _ -> clang_name in
let mangled = match param_idx_opt with
| Some index -> Mangled.mangled name_string (string_of_int index)
| None -> Mangled.from_string name_string in
name_string, mangled
let mk_sil_global_var {CFrontend_config.source_file} ?(mk_name=fun _ x -> x)
named_decl_info var_decl_info qt =
let name_string, simple_name = get_var_name_mangled named_decl_info var_decl_info in
let translation_unit =
match (var_decl_info.Clang_ast_t.vdi_storage_class,
var_decl_info.Clang_ast_t.vdi_init_expr) with
| Some "extern", None ->
(* some compilers simply disregard "extern" when the global is given some initialisation
code, which is why we make sure that [vdi_init_expr] is None here... *)
SourceFile.empty
| _ ->
source_file in
let is_constexpr = var_decl_info.Clang_ast_t.vdi_is_const_expr in
let is_pod =
CAst_utils.get_desugared_type qt.Clang_ast_t.qt_type_ptr
|> Fn.flip Option.bind (function
| Clang_ast_t.RecordType(_, decl_ptr) -> CAst_utils.get_decl decl_ptr
| _ -> None)
|> Option.value_map ~default:true ~f:(function
| Clang_ast_t.CXXRecordDecl(_, _, _, _, _, _, _, {xrdi_is_pod})
| Clang_ast_t.ClassTemplateSpecializationDecl(_, _, _, _, _, _, _, {xrdi_is_pod}, _) ->
xrdi_is_pod
| _ -> true) in
Pvar.mk_global ~is_constexpr ~is_pod
~is_static_local:(var_decl_info.Clang_ast_t.vdi_is_static_local)
(mk_name name_string simple_name) translation_unit
let mk_sil_var trans_unit_ctx named_decl_info decl_info_type_ptr_opt procname outer_procname =
match decl_info_type_ptr_opt with
| Some (decl_info, qt, var_decl_info, should_be_mangled) ->
let name_string, simple_name = get_var_name_mangled named_decl_info var_decl_info in
if var_decl_info.Clang_ast_t.vdi_is_global then
let mk_name =
if var_decl_info.Clang_ast_t.vdi_is_static_local then
Some (fun name_string _ ->
Mangled.from_string ((Procname.to_string outer_procname) ^ "_" ^ name_string))
else None in
mk_sil_global_var trans_unit_ctx ?mk_name named_decl_info var_decl_info qt
else if not should_be_mangled then Pvar.mk simple_name procname
else
let start_location = fst decl_info.Clang_ast_t.di_source_range in
let line_opt = start_location.Clang_ast_t.sl_line in
let line_str = match line_opt with | Some line -> string_of_int line | None -> "" in
let mangled = Utils.string_crc_hex32 line_str in
let mangled_name = Mangled.mangled name_string mangled in
Pvar.mk mangled_name procname
| None ->
let name_string = CAst_utils.get_qualified_name named_decl_info in
Pvar.mk (Mangled.from_string name_string) procname

@ -0,0 +1,83 @@
(*
* Copyright (c) 2013 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
open! IStd
(** General utility functions such as functions on lists *)
type var_info = Clang_ast_t.decl_info * Clang_ast_t.qual_type * Clang_ast_t.var_decl_info * bool
val string_from_list : string list -> string
val append_no_duplicates_fields : (Ident.fieldname * Typ.t * Annot.Item.t) list ->
(Ident.fieldname * Typ.t * Annot.Item.t) list ->
(Ident.fieldname * Typ.t * Annot.Item.t) list
val append_no_duplicates_csu :
Typename.t list -> Typename.t list -> Typename.t list
val append_no_duplicates_methods : Procname.t list -> Procname.t list -> Procname.t list
val sort_fields :
(Ident.fieldname * Typ.t * Annot.Item.t) list ->
(Ident.fieldname * Typ.t * Annot.Item.t) list
val sort_fields_tenv : Tenv.t -> unit
val collect_list_tuples : ('a list * 'b list * 'c list * 'd list * 'e list) list ->
'a list * 'b list * 'c list * 'd list * 'e list ->
'a list * 'b list * 'c list * 'd list * 'e list
val swap_elements_list : 'a list -> 'a list
val is_static_var : Clang_ast_t.var_decl_info -> bool
val mk_fresh_block_procname : Procname.t -> Procname.t
val get_next_block_pvar : Procname.t -> Pvar.t
val reset_block_counter : unit -> unit
val zip: 'a list -> 'b list -> ('a * 'b) list
val list_range: int -> int -> int list
val replicate: int -> 'a -> 'a list
val mk_procname_from_objc_method : string -> string -> Procname.objc_cpp_method_kind -> Procname.t
val mk_procname_from_function : CFrontend_config.translation_unit_context -> string
-> (Clang_ast_t.decl_info * Clang_ast_t.function_decl_info) option -> Procname.t
val get_mangled_method_name : Clang_ast_t.function_decl_info ->
Clang_ast_t.cxx_method_decl_info -> string option
val mk_procname_from_cpp_method :
string -> string -> ?meth_decl:Clang_ast_t.decl -> string option -> Procname.t
val procname_of_decl : CFrontend_config.translation_unit_context -> Clang_ast_t.decl -> Procname.t
val mk_class_field_name : Clang_ast_t.named_decl_info -> Ident.fieldname
val get_var_name_mangled : Clang_ast_t.named_decl_info -> Clang_ast_t.var_decl_info ->
(string * Mangled.t)
val mk_sil_global_var : CFrontend_config.translation_unit_context ->
?mk_name:(string -> Mangled.t -> Mangled.t) ->
Clang_ast_t.named_decl_info -> Clang_ast_t.var_decl_info -> Clang_ast_t.qual_type -> Pvar.t
val mk_sil_var : CFrontend_config.translation_unit_context -> Clang_ast_t.named_decl_info ->
var_info option -> Procname.t -> Procname.t -> Pvar.t
(** true if the current language is C++ or ObjC++ *)
val is_cpp_translation : CFrontend_config.translation_unit_context -> bool
(** true if the current language is ObjC or ObjC++ *)
val is_objc_extension : CFrontend_config.translation_unit_context -> bool

@ -8,7 +8,6 @@
*)
open! IStd
open CFrontend_utils
(** Define the signature of a method consisting of its name, its arguments, *)
(** return type, location and whether its an instance method. *)
@ -100,7 +99,7 @@ let replace_name_ms ms name =
let ms_to_string ms =
"Method " ^ (Procname.to_string ms.name) ^ " " ^
IList.to_string
(fun (s1, s2) -> (Mangled.to_string s1) ^ ", " ^ (Ast_utils.string_of_qual_type s2))
(fun (s1, s2) -> (Mangled.to_string s1) ^ ", " ^ (CAst_utils.string_of_qual_type s2))
ms.args
^ "->" ^ (Ast_utils.string_of_type_ptr ms.ret_type) ^ " " ^
^ "->" ^ (CAst_utils.string_of_type_ptr ms.ret_type) ^ " " ^
Clang_ast_j.string_of_source_range ms.loc

@ -12,8 +12,6 @@ open! IStd
(** Methods for creating a procdesc from a method or function declaration
and for resolving a method call and finding the right callee *)
open CFrontend_utils
module L = Logging
exception Invalid_declaration
@ -109,11 +107,11 @@ let get_parameters trans_unit_ctx tenv function_method_decl_info =
let par_to_ms_par par =
match par with
| Clang_ast_t.ParmVarDecl (_, name_info, qt, var_decl_info) ->
let _, mangled = General_utils.get_var_name_mangled name_info var_decl_info in
let _, mangled = CGeneral_utils.get_var_name_mangled name_info var_decl_info in
let param_typ = CType_decl.type_ptr_to_sil_type tenv qt.Clang_ast_t.qt_type_ptr in
let qt_type_ptr =
match param_typ with
| Typ.Tstruct _ when General_utils.is_cpp_translation trans_unit_ctx ->
| Typ.Tstruct _ when CGeneral_utils.is_cpp_translation trans_unit_ctx ->
Ast_expressions.create_reference_type qt.Clang_ast_t.qt_type_ptr
| _ -> qt.Clang_ast_t.qt_type_ptr in
(mangled, {qt with qt_type_ptr})
@ -146,7 +144,7 @@ let build_method_signature trans_unit_ctx tenv decl_info procname function_metho
let get_assume_not_null_calls param_decls =
let do_one_param decl = match decl with
| Clang_ast_t.ParmVarDecl (decl_info, name, qt, _)
when CFrontend_utils.Ast_utils.is_type_nonnull qt.Clang_ast_t.qt_type_ptr ->
when CAst_utils.is_type_nonnull qt.Clang_ast_t.qt_type_ptr ->
let assume_call = Ast_expressions.create_assume_not_null_call
decl_info name qt.Clang_ast_t.qt_type_ptr in
[(`ClangStmt assume_call)]
@ -162,7 +160,7 @@ let method_signature_of_decl trans_unit_ctx tenv meth_decl block_data_opt =
match meth_decl, block_data_opt with
| FunctionDecl (decl_info, _, qt, fdi), _ ->
let func_decl = Func_decl_info (fdi, qt.Clang_ast_t.qt_type_ptr) in
let procname = General_utils.procname_of_decl trans_unit_ctx meth_decl in
let procname = CGeneral_utils.procname_of_decl trans_unit_ctx meth_decl in
let ms = build_method_signature trans_unit_ctx tenv decl_info procname func_decl None None in
let extra_instrs = get_assume_not_null_calls fdi.Clang_ast_t.fdi_parameters in
ms, fdi.Clang_ast_t.fdi_body, extra_instrs
@ -170,7 +168,7 @@ let method_signature_of_decl trans_unit_ctx tenv meth_decl block_data_opt =
| CXXConstructorDecl (decl_info, _, qt, fdi, mdi), _
| CXXConversionDecl (decl_info, _, qt, fdi, mdi), _
| CXXDestructorDecl (decl_info, _, qt, fdi, mdi), _ ->
let procname = General_utils.procname_of_decl trans_unit_ctx meth_decl in
let procname = CGeneral_utils.procname_of_decl trans_unit_ctx meth_decl in
let parent_ptr = Option.value_exn decl_info.di_parent_pointer in
let method_decl = Cpp_Meth_decl_info (fdi, mdi, parent_ptr, qt.Clang_ast_t.qt_type_ptr) in
let parent_pointer = decl_info.Clang_ast_t.di_parent_pointer in
@ -180,7 +178,7 @@ let method_signature_of_decl trans_unit_ctx tenv meth_decl block_data_opt =
let init_list_instrs = get_init_list_instrs mdi in (* it will be empty for methods *)
ms, fdi.Clang_ast_t.fdi_body, (init_list_instrs @ non_null_instrs)
| ObjCMethodDecl (decl_info, _, mdi), _ ->
let procname = General_utils.procname_of_decl trans_unit_ctx meth_decl in
let procname = CGeneral_utils.procname_of_decl trans_unit_ctx meth_decl in
let parent_ptr = Option.value_exn decl_info.di_parent_pointer in
let method_decl = ObjC_Meth_decl_info (mdi, parent_ptr) in
let parent_pointer = decl_info.Clang_ast_t.di_parent_pointer in
@ -201,7 +199,7 @@ let method_signature_of_decl trans_unit_ctx tenv meth_decl block_data_opt =
let method_signature_of_pointer trans_unit_ctx tenv pointer =
try
match Ast_utils.get_decl pointer with
match CAst_utils.get_decl pointer with
| Some meth_decl ->
let ms, _, _ = method_signature_of_decl trans_unit_ctx tenv meth_decl None in
Some ms
@ -211,7 +209,7 @@ let method_signature_of_pointer trans_unit_ctx tenv pointer =
let get_method_name_from_clang tenv ms_opt =
match ms_opt with
| Some ms ->
(match Ast_utils.get_decl_opt (CMethod_signature.ms_get_pointer_to_parent ms) with
(match CAst_utils.get_decl_opt (CMethod_signature.ms_get_pointer_to_parent ms) with
| Some decl ->
if ObjcProtocol_decl.is_protocol decl then None
else
@ -289,7 +287,7 @@ let get_objc_method_data obj_c_message_expr_info =
let skip_property_accessor ms =
let open Clang_ast_t in
let pointer_to_property_opt = CMethod_signature.ms_get_pointer_to_property_opt ms in
match Ast_utils.get_decl_opt pointer_to_property_opt with
match CAst_utils.get_decl_opt pointer_to_property_opt with
| Some (ObjCPropertyDecl _) -> true
| _ -> false
@ -344,7 +342,7 @@ let sil_method_annotation_of_args args : Annot.Method.t =
annot, default_visibility in
let arg_to_sil_annot (arg_mangled, {Clang_ast_t.qt_type_ptr}) acc =
let arg_name = Mangled.to_string arg_mangled in
if CFrontend_utils.Ast_utils.is_type_nullable qt_type_ptr then
if CAst_utils.is_type_nullable qt_type_ptr then
[mk_annot arg_name Annotations.nullable] :: acc
else Annot.Item.empty::acc in
let param_annots = IList.fold_right arg_to_sil_annot args [] in
@ -353,7 +351,7 @@ let sil_method_annotation_of_args args : Annot.Method.t =
retval_annot, param_annots
let is_pointer_to_const type_ptr = match Ast_utils.get_type type_ptr with
let is_pointer_to_const type_ptr = match CAst_utils.get_type type_ptr with
| Some PointerType (_, {Clang_ast_t.qt_is_const})
| Some ObjCObjectPointerType (_, {Clang_ast_t.qt_is_const})
| Some RValueReferenceType (_, {Clang_ast_t.qt_is_const})
@ -464,9 +462,9 @@ let create_procdesc_with_pointer context pointer class_name_opt name =
let callee_name =
match class_name_opt with
| Some class_name ->
General_utils.mk_procname_from_cpp_method class_name name None
CGeneral_utils.mk_procname_from_cpp_method class_name name None
| None ->
General_utils.mk_procname_from_function context.translation_unit_context name None in
CGeneral_utils.mk_procname_from_function context.translation_unit_context name None in
create_external_procdesc context.cfg callee_name false None;
callee_name
@ -482,7 +480,7 @@ let get_procname_from_cpp_lambda context dec =
| Clang_ast_t.CXXRecordDecl (_, _, _, _, _, _, _, cxx_rdi) ->
(match cxx_rdi.xrdi_lambda_call_operator with
| Some dr ->
let name_info, decl_ptr, _ = Ast_utils.get_info_from_decl_ref dr in
let name_info, decl_ptr, _ = CAst_utils.get_info_from_decl_ref dr in
create_procdesc_with_pointer context decl_ptr None name_info.ni_name
| _ -> assert false (* We should not get here *))
| _ -> assert false (* We should not get here *)

@ -9,8 +9,6 @@
open! IStd
open CFrontend_utils
(* This module defines a language to define checkers. These checkers
are intepreted over the AST of the program. A checker is defined by a
CTL formula which express a condition saying when the checker should
@ -331,9 +329,9 @@ let transition_decl_to_stmt d trs =
| _ -> None
let transition_decl_to_decl_via_super d =
match Ast_utils.get_impl_decl_info d with
match CAst_utils.get_impl_decl_info d with
| Some idi ->
(match Ast_utils.get_super_ObjCImplementationDecl idi with
(match CAst_utils.get_super_ObjCImplementationDecl idi with
| Some d -> Some (Decl d)
| _ -> None)
| None -> None
@ -351,11 +349,11 @@ let transition_stmt_to_decl_via_pointer stmt =
let open Clang_ast_t in
match stmt with
| ObjCMessageExpr (_, _, _, obj_c_message_expr_info) ->
(match Ast_utils.get_decl_opt obj_c_message_expr_info.Clang_ast_t.omei_decl_pointer with
(match CAst_utils.get_decl_opt obj_c_message_expr_info.Clang_ast_t.omei_decl_pointer with
| Some decl -> Some (Decl decl)
| None -> None)
| DeclRefExpr (_, _, _, decl_ref_expr_info) ->
(match Ast_utils.get_decl_opt_with_decl_ref decl_ref_expr_info.Clang_ast_t.drti_decl_ref with
(match CAst_utils.get_decl_opt_with_decl_ref decl_ref_expr_info.Clang_ast_t.drti_decl_ref with
| Some decl -> Some (Decl decl)
| None -> None)
| _ -> None

@ -12,9 +12,8 @@ open! IStd
(** Translates instructions: (statements and expressions) from the ast into sil *)
open CTrans_utils
open CFrontend_utils
open CTrans_utils.Nodes
module L = Logging
module CTrans_funct(F: CModule_type.CFrontend) : CModule_type.CTranslation =
@ -43,12 +42,12 @@ struct
| None -> (* fall back to our method resolution if clang's fails *)
let class_name = CMethod_trans.get_class_name_method_call_from_receiver_kind context
obj_c_message_expr_info act_params in
General_utils.mk_procname_from_objc_method class_name selector method_kind in
CGeneral_utils.mk_procname_from_objc_method class_name selector method_kind in
let predefined_ms_opt = match proc_name with
| Procname.ObjC_Cpp objc_cpp ->
let class_name = Procname.objc_cpp_get_class_name objc_cpp in
CTrans_models.get_predefined_model_method_signature class_name selector
General_utils.mk_procname_from_objc_method CFrontend_config.ObjC
CGeneral_utils.mk_procname_from_objc_method CFrontend_config.ObjC
| _ ->
None in
match predefined_ms_opt, ms_opt with
@ -108,8 +107,8 @@ struct
let procname = Procdesc.get_proc_name procdesc in
let mk_field_from_captured_var (var, typ) =
let vname = Pvar.get_name var in
let qual_name = Ast_utils.make_qual_name_decl [block_name] (Mangled.to_string vname) in
let fname = General_utils.mk_class_field_name qual_name in
let qual_name = CAst_utils.make_qual_name_decl [block_name] (Mangled.to_string vname) in
let fname = CGeneral_utils.mk_class_field_name qual_name in
let item_annot = Annot.Item.empty in
fname, typ, item_annot in
let fields = IList.map mk_field_from_captured_var captured_vars in
@ -403,7 +402,7 @@ struct
match unary_expr_or_type_trait_expr_info.Clang_ast_t.uttei_kind with
| `SizeOf ->
let tp =
Ast_utils.type_from_unary_expr_or_type_trait_expr_info
CAst_utils.type_from_unary_expr_or_type_trait_expr_info
unary_expr_or_type_trait_expr_info in
let sizeof_typ =
match tp with
@ -449,7 +448,7 @@ struct
| _ when CTrans_models.is_retain_builtin name type_ptr ->
Some BuiltinDecl.__objc_retain_cf
| _ when name = CFrontend_config.malloc &&
General_utils.is_objc_extension trans_unit_ctx ->
CGeneral_utils.is_objc_extension trans_unit_ctx ->
Some BuiltinDecl.malloc_no_fail
| _ -> None
@ -457,10 +456,10 @@ struct
let function_deref_trans trans_state decl_ref =
let open CContext in
let context = trans_state.context in
let name_info, decl_ptr, type_ptr = Ast_utils.get_info_from_decl_ref decl_ref in
let decl_opt = Ast_utils.get_function_decl_with_body decl_ptr in
let name_info, decl_ptr, type_ptr = CAst_utils.get_info_from_decl_ref decl_ref in
let decl_opt = CAst_utils.get_function_decl_with_body decl_ptr in
Option.iter ~f:(call_translation context) decl_opt;
let name = Ast_utils.get_qualified_name name_info in
let name = CAst_utils.get_qualified_name name_info in
let typ = CType_decl.type_ptr_to_sil_type context.tenv type_ptr in
let pname =
match get_builtin_pname_opt context.translation_unit_context name decl_opt type_ptr with
@ -472,7 +471,7 @@ struct
let open CContext in
let context = trans_state.context in
let sil_loc = CLocation.get_sil_location stmt_info context in
let name_info, _, type_ptr = Ast_utils.get_info_from_decl_ref decl_ref in
let name_info, _, type_ptr = CAst_utils.get_info_from_decl_ref decl_ref in
Logging.out_debug "!!!!! Dealing with field '%s' @." name_info.Clang_ast_t.ni_name;
let field_typ = CType_decl.type_ptr_to_sil_type context.tenv type_ptr in
let (obj_sil, class_typ) = extract_exp_from_list pre_trans_result.exps
@ -485,7 +484,7 @@ struct
| Typ.Tptr (t, _) -> t
| t -> t in
Logging.out_debug "Type is '%s' @." (Typ.to_string class_typ);
let field_name = General_utils.mk_class_field_name name_info in
let field_name = CGeneral_utils.mk_class_field_name name_info in
let field_exp = Exp.Lfield (obj_sil, field_name, class_typ) in
(* In certain cases, there is be no LValueToRValue cast, but backend needs dereference*)
(* there either way:*)
@ -509,11 +508,11 @@ struct
let open CContext in
let context = trans_state.context in
let sil_loc = CLocation.get_sil_location stmt_info context in
let name_info, decl_ptr, type_ptr = Ast_utils.get_info_from_decl_ref decl_ref in
let decl_opt = Ast_utils.get_function_decl_with_body decl_ptr in
let name_info, decl_ptr, type_ptr = CAst_utils.get_info_from_decl_ref decl_ref in
let decl_opt = CAst_utils.get_function_decl_with_body decl_ptr in
Option.iter ~f:(call_translation context) decl_opt;
let method_name = Ast_utils.get_unqualified_name name_info in
let class_name = Ast_utils.get_class_name_from_member name_info in
let method_name = CAst_utils.get_unqualified_name name_info in
let class_name = CAst_utils.get_class_name_from_member name_info in
Logging.out_debug "!!!!! Dealing with method '%s' @." method_name;
let method_typ = CType_decl.type_ptr_to_sil_type context.tenv type_ptr in
let ms_opt = CMethod_trans.method_signature_of_pointer
@ -548,7 +547,7 @@ struct
(* unlike field access, for method calls there is no need to expand class type *)
(* use qualified method name for builtin matching, but use unqualified name elsewhere *)
let qual_method_name = Ast_utils.get_qualified_name name_info in
let qual_method_name = CAst_utils.get_qualified_name name_info in
let pname =
match get_builtin_pname_opt context.translation_unit_context qual_method_name decl_opt
type_ptr with
@ -565,7 +564,7 @@ struct
let destructor_deref_trans trans_state pvar_trans_result class_type_ptr si =
let open Clang_ast_t in
let destruct_decl_ref_opt = match Ast_utils.get_decl_from_typ_ptr class_type_ptr with
let destruct_decl_ref_opt = match CAst_utils.get_decl_from_typ_ptr class_type_ptr with
| Some CXXRecordDecl (_, _, _ , _, _, _, _, cxx_record_info)
| Some ClassTemplateSpecializationDecl (_, _, _, _, _, _, _, cxx_record_info, _) ->
cxx_record_info.xrdi_destructor
@ -605,12 +604,12 @@ struct
and var_deref_trans trans_state stmt_info (decl_ref : Clang_ast_t.decl_ref) =
let context = trans_state.context in
let _, _, type_ptr = Ast_utils.get_info_from_decl_ref decl_ref in
let _, _, type_ptr = CAst_utils.get_info_from_decl_ref decl_ref in
let ast_typ = CType_decl.type_ptr_to_sil_type context.tenv type_ptr in
let typ =
match ast_typ with
| Tstruct _ when decl_ref.dr_kind = `ParmVar ->
if General_utils.is_cpp_translation context.translation_unit_context then
if CGeneral_utils.is_cpp_translation context.translation_unit_context then
Typ.Tptr (ast_typ, Pk_reference)
else ast_typ
| _ -> ast_typ in
@ -625,11 +624,11 @@ struct
(* place where it is used *)
let trans_result' =
let is_global_const, init_expr =
match Ast_utils.get_decl decl_ref.dr_decl_pointer with
match CAst_utils.get_decl decl_ref.dr_decl_pointer with
| Some VarDecl (_, _, qual_type, vdi) -> (
match ast_typ with
| Tstruct _
when not (General_utils.is_cpp_translation context.translation_unit_context) ->
when not (CGeneral_utils.is_cpp_translation context.translation_unit_context) ->
(* Do not convert a global struct to a local because SIL
values do not include structs, they must all be heap-allocated *)
(false, None)
@ -688,7 +687,7 @@ struct
(* evaluates an enum constant *)
and enum_const_eval context enum_constant_pointer prev_enum_constant_opt zero =
match Ast_utils.get_decl enum_constant_pointer with
match CAst_utils.get_decl enum_constant_pointer with
| Some Clang_ast_t.EnumConstantDecl (_, _, _, enum_constant_decl_info) ->
(match enum_constant_decl_info.Clang_ast_t.ecdi_init_expr with
| Some stmt ->
@ -707,18 +706,18 @@ struct
let zero = Exp.Const (Const.Cint IntLit.zero) in
try
let (prev_enum_constant_opt, sil_exp_opt) =
Ast_utils.get_enum_constant_exp enum_constant_pointer in
CAst_utils.get_enum_constant_exp enum_constant_pointer in
match sil_exp_opt with
| Some exp -> exp
| None ->
let exp = enum_const_eval context enum_constant_pointer prev_enum_constant_opt zero in
Ast_utils.update_enum_map enum_constant_pointer exp;
CAst_utils.update_enum_map enum_constant_pointer exp;
exp
with Not_found -> zero
and enum_constant_trans trans_state decl_ref =
let context = trans_state.context in
let _, _, type_ptr = Ast_utils.get_info_from_decl_ref decl_ref in
let _, _, type_ptr = CAst_utils.get_info_from_decl_ref decl_ref in
let typ = CType_decl.type_ptr_to_sil_type context.CContext.tenv type_ptr in
let const_exp = get_enum_constant_expr context decl_ref.Clang_ast_t.dr_decl_pointer in
{ empty_res_trans with exps = [(const_exp, typ)] }
@ -807,7 +806,7 @@ struct
if (is_binary_assign_op binary_operator_info)
(* assignment operator result is lvalue in CPP, rvalue in C, *)
(* hence the difference *)
&& (not (General_utils.is_cpp_translation context.translation_unit_context))
&& (not (CGeneral_utils.is_cpp_translation context.translation_unit_context))
&& ((not creating_node) || (is_return_temp trans_state.continuation)) then (
(* We are in this case when an assignment is inside *)
(* another operator that creates a node. Eg. another *)
@ -1104,7 +1103,7 @@ struct
and block_enumeration_trans trans_state stmt_info stmt_list ei =
Logging.out_debug "\n Call to a block enumeration function treated as special case...\n@.";
let procname = Procdesc.get_proc_name trans_state.context.CContext.procdesc in
let pvar = CFrontend_utils.General_utils.get_next_block_pvar procname in
let pvar = CGeneral_utils.get_next_block_pvar procname in
let transformed_stmt, _ =
Ast_expressions.translate_block_enumerate (Pvar.to_string pvar) stmt_info stmt_list ei in
instruction trans_state transformed_stmt
@ -1834,7 +1833,7 @@ struct
(* This gives the differnece among cast operations kind*)
let is_objc_bridged_cast_expr _ stmt =
match stmt with | Clang_ast_t.ObjCBridgedCastExpr _ -> true | _ -> false in
let is_objc_bridged = Ast_utils.exists_eventually_st is_objc_bridged_cast_expr () stmt in
let is_objc_bridged = CAst_utils.exists_eventually_st is_objc_bridged_cast_expr () stmt in
let cast_inst, cast_exp =
cast_operation trans_state cast_kind res_trans_stmt.exps typ sil_loc is_objc_bridged in
{ res_trans_stmt with
@ -1983,7 +1982,7 @@ struct
let dictionary_literal_s = Procname.get_method dictionary_literal_pname in
let obj_c_message_expr_info =
Ast_expressions.make_obj_c_message_expr_info_class dictionary_literal_s typ None in
let stmts = General_utils.swap_elements_list stmts in
let stmts = CGeneral_utils.swap_elements_list stmts in
let stmts = stmts @ [Ast_expressions.create_nil stmt_info] in
let message_stmt =
Clang_ast_t.ObjCMessageExpr
@ -2046,7 +2045,7 @@ struct
| Clang_ast_t.BlockDecl (_, block_decl_info) ->
let open CContext in
let type_ptr = expr_info.Clang_ast_t.ei_type_ptr in
let block_pname = CFrontend_utils.General_utils.mk_fresh_block_procname procname in
let block_pname = CGeneral_utils.mk_fresh_block_procname procname in
let typ = CType_decl.type_ptr_to_sil_type context.tenv type_ptr in
(* We need to set the explicit dependency between the newly created block and the *)
(* defining procedure. We add an edge in the call graph.*)
@ -2093,7 +2092,7 @@ struct
| _ ->
let stmt_res_trans = if is_dyn_array then
let init_stmt_info = { stmt_info with
Clang_ast_t.si_pointer = Ast_utils.get_fresh_pointer () } in
Clang_ast_t.si_pointer = CAst_utils.get_fresh_pointer () } in
init_expr_trans trans_state' (var_exp_inside, typ_inside) init_stmt_info (Some stmt)
else instruction trans_state' stmt in
stmt_res_trans :: rest_stmts_res_trans
@ -2121,7 +2120,7 @@ struct
let is_dyn_array = cxx_new_expr_info.Clang_ast_t.xnei_is_array in
let size_exp_opt, res_trans_size =
if is_dyn_array then
match Ast_utils.get_stmt_opt cxx_new_expr_info.Clang_ast_t.xnei_array_size_expr with
match CAst_utils.get_stmt_opt cxx_new_expr_info.Clang_ast_t.xnei_array_size_expr with
| Some stmt ->
let trans_state_size = { trans_state_pri with succ_nodes = []; } in
let res_trans_size = instruction trans_state_size stmt in
@ -2131,7 +2130,7 @@ struct
| None -> Some (Exp.Const (Const.Cint (IntLit.minus_one))), empty_res_trans
else None, empty_res_trans in
let res_trans_new = cpp_new_trans sil_loc typ size_exp_opt in
let stmt_opt = Ast_utils.get_stmt_opt cxx_new_expr_info.Clang_ast_t.xnei_initializer_expr in
let stmt_opt = CAst_utils.get_stmt_opt cxx_new_expr_info.Clang_ast_t.xnei_initializer_expr in
let trans_state_init = { trans_state_pri with succ_nodes = []; } in
let var_exp_typ = match res_trans_new.exps with
| [var_exp, Typ.Tptr (t, _)] -> (var_exp, t)
@ -2139,7 +2138,7 @@ struct
(* Need a new stmt_info for the translation of the initializer, so that it can create nodes *)
(* if it needs to, with the same stmt_info it doesn't work. *)
let init_stmt_info = { stmt_info with
Clang_ast_t.si_pointer = Ast_utils.get_fresh_pointer () } in
Clang_ast_t.si_pointer = CAst_utils.get_fresh_pointer () } in
let res_trans_init =
if is_dyn_array && Typ.is_pointer_to_cpp_class typ then
let rec create_stmts stmt_opt size_exp_opt =
@ -2182,7 +2181,7 @@ struct
let deleted_type = delete_expr_info.Clang_ast_t.xdei_destroyed_type in
(* create stmt_info with new pointer so that destructor call doesn't create a node *)
let destruct_stmt_info = { stmt_info with
Clang_ast_t.si_pointer = Ast_utils.get_fresh_pointer () } in
Clang_ast_t.si_pointer = CAst_utils.get_fresh_pointer () } in
(* use empty_res_trans to avoid ending up with same instruction twice *)
(* otherwise it would happen due to structutre of all_res_trans *)
let this_res_trans_destruct = { empty_res_trans with exps = result_trans_param.exps } in
@ -2290,8 +2289,8 @@ struct
let sil_fun = Exp.Const (Const.Cfun fun_name) in
let ret_id = Ident.create_fresh Ident.knormal in
let type_info_objc = (Exp.Sizeof (typ, None, Subtype.exact), Typ.Tvoid) in
let field_name_decl = Ast_utils.make_qual_name_decl ["type_info"; "std"] "__type_name" in
let field_name = General_utils.mk_class_field_name field_name_decl in
let field_name_decl = CAst_utils.make_qual_name_decl ["type_info"; "std"] "__type_name" in
let field_name = CGeneral_utils.mk_class_field_name field_name_decl in
let ret_exp = Exp.Var ret_id in
let field_exp = Exp.Lfield (ret_exp, field_name, typ) in
let args = [type_info_objc; (field_exp, Typ.Tvoid)] @ res_trans_subexpr.exps in
@ -2572,7 +2571,7 @@ struct
| CXXTryStmt (_, stmts) ->
(Logging.out
"\n!!!!WARNING: found statement %s. \nTranslation need to be improved.... \n"
(Ast_utils.string_of_stmt instr);
(CAst_utils.string_of_stmt instr);
compoundStmt_trans trans_state stmts)
| ObjCAtThrowStmt (stmt_info, stmts)
@ -2652,7 +2651,7 @@ struct
| s -> (Logging.out
"\n!!!!WARNING: found statement %s. \nACTION REQUIRED: \
Translation need to be defined. Statement ignored.... \n"
(Ast_utils.string_of_stmt s);
(CAst_utils.string_of_stmt s);
assert false)
(* Function similar to instruction function, but it takes C++ constructor initializer as

@ -9,7 +9,6 @@
open! IStd
open CFrontend_utils
open Objc_models
let is_cf_non_null_alloc pname =
@ -70,9 +69,9 @@ let is_modeled_attribute attr_name =
IList.mem String.equal attr_name CFrontend_config.modeled_function_attributes
let get_first_param_typedef_string_opt type_ptr =
match Ast_utils.get_desugared_type type_ptr with
match CAst_utils.get_desugared_type type_ptr with
| Some Clang_ast_t.FunctionProtoType (_, _, {pti_params_type = [param_ptr]}) ->
Ast_utils.name_opt_of_typedef_type_ptr param_ptr
CAst_utils.name_opt_of_typedef_type_ptr param_ptr
| _ -> None
let is_release_builtin funct fun_type =

@ -12,8 +12,6 @@ module Hashtbl = Caml.Hashtbl
(** Utility methods to support the translation of clang ast constructs into sil instructions. *)
open CFrontend_utils
module L = Logging
(* Extract the element of a singleton list. If the list is not a singleton *)
@ -337,7 +335,7 @@ let objc_new_trans trans_state loc stmt_info cls_name function_type =
let is_instance = true in
let call_flags = { CallFlags.default with CallFlags.cf_virtual = is_instance; } in
let pname =
General_utils.mk_procname_from_objc_method
CGeneral_utils.mk_procname_from_objc_method
cls_name CFrontend_config.init Procname.ObjCInstanceMethod in
CMethod_trans.create_external_procdesc trans_state.context.CContext.cfg pname is_instance None;
let args = [(alloc_ret_exp, alloc_ret_type)] in
@ -716,7 +714,7 @@ let is_block_enumerate_function mei =
(* be a list of LField expressions *)
let var_or_zero_in_init_list tenv e typ ~return_zero:return_zero =
let rec var_or_zero_in_init_list' e typ tns =
let open General_utils in
let open CGeneral_utils in
match typ with
| Typ.Tstruct tn -> (
match Tenv.lookup tenv tn with

@ -9,8 +9,6 @@
open! IStd
open CFrontend_utils
let get_builtin_objc_typename builtin_type =
match builtin_type with
| `ObjCId -> Typename.TN_csu (Csu.Struct, (Mangled.from_string CFrontend_config.objc_object))
@ -69,7 +67,7 @@ let rec build_array_type translate_decl tenv type_ptr n_opt =
and sil_type_of_attr_type translate_decl tenv type_info attr_info =
match type_info.Clang_ast_t.ti_desugared_type with
| Some type_ptr ->
(match Ast_utils.get_type type_ptr with
(match CAst_utils.get_type type_ptr with
| Some Clang_ast_t.ObjCObjectPointerType (_, {Clang_ast_t.qt_type_ptr}) ->
let typ = type_ptr_to_sil_type translate_decl tenv qt_type_ptr in
Typ.Tptr (typ, pointer_attribute_of_objc_attribute attr_info)
@ -132,7 +130,7 @@ and decl_ptr_to_sil_type translate_decl tenv decl_ptr =
let typ = `DeclPtr decl_ptr in
try Clang_ast_types.TypePointerMap.find typ !CFrontend_config.sil_types_map
with Not_found ->
match Ast_utils.get_decl decl_ptr with
match CAst_utils.get_decl decl_ptr with
| Some (CXXRecordDecl _ as d)
| Some (RecordDecl _ as d)
| Some (ClassTemplateSpecializationDecl _ as d)
@ -155,10 +153,10 @@ and clang_type_ptr_to_sil_type translate_decl tenv type_ptr =
try
Clang_ast_types.TypePointerMap.find type_ptr !CFrontend_config.sil_types_map
with Not_found ->
(match Ast_utils.get_type type_ptr with
(match CAst_utils.get_type type_ptr with
| Some c_type ->
let sil_type = sil_type_of_c_type translate_decl tenv c_type in
Ast_utils.update_sil_types_map type_ptr sil_type;
CAst_utils.update_sil_types_map type_ptr sil_type;
sil_type
| _ -> Typ.Tvoid)

@ -12,8 +12,6 @@ open! IStd
(** Process variable declarations by saving them as local or global variables. *)
(** Computes the local variables of a function or method to be added to the procdesc *)
open CFrontend_utils
module L = Logging
let is_custom_var_pointer pointer =
@ -29,11 +27,11 @@ let sil_var_of_decl context var_decl procname =
not (is_custom_var_pointer decl_info.Clang_ast_t.di_pointer) in
let var_decl_details = Some
(decl_info, qual_type, var_decl_info, shoud_be_mangled) in
General_utils.mk_sil_var trans_unit_ctx name_info var_decl_details procname outer_procname
CGeneral_utils.mk_sil_var trans_unit_ctx name_info var_decl_details procname outer_procname
| ParmVarDecl (decl_info, name_info, qual_type, var_decl_info) ->
let var_decl_details = Some
(decl_info, qual_type, var_decl_info, false) in
General_utils.mk_sil_var trans_unit_ctx name_info var_decl_details procname outer_procname
CGeneral_utils.mk_sil_var trans_unit_ctx name_info var_decl_details procname outer_procname
| _ -> assert false
let sil_var_of_decl_ref context decl_ref procname =
@ -46,11 +44,11 @@ let sil_var_of_decl_ref context decl_ref procname =
| `ImplicitParam ->
let outer_procname = CContext.get_outer_procname context in
let trans_unit_ctx = context.CContext.translation_unit_context in
General_utils.mk_sil_var trans_unit_ctx name None procname outer_procname
CGeneral_utils.mk_sil_var trans_unit_ctx name None procname outer_procname
| _ ->
if is_custom_var_pointer pointer then
Pvar.mk (Mangled.from_string name.Clang_ast_t.ni_name) procname
else match Ast_utils.get_decl decl_ref.Clang_ast_t.dr_decl_pointer with
else match CAst_utils.get_decl decl_ref.Clang_ast_t.dr_decl_pointer with
| Some var_decl -> sil_var_of_decl context var_decl procname
| None -> assert false

@ -9,8 +9,6 @@
open! IStd
open CFrontend_utils
module L = Logging
(** In this module an ObjC category declaration or implementation is processed. The category *)
@ -22,7 +20,7 @@ let noname_category class_name =
let cat_class_decl dr =
match dr.Clang_ast_t.dr_name with
| Some n -> Ast_utils.get_qualified_name n
| Some n -> CAst_utils.get_qualified_name n
| _ -> assert false
let get_curr_class_from_category name decl_ref_opt =
@ -40,15 +38,15 @@ let get_curr_class_from_category_impl name ocidi =
let add_category_decl type_ptr_to_sil_type tenv category_impl_info =
let decl_ref_opt = category_impl_info.Clang_ast_t.ocidi_category_decl in
Ast_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt true
CAst_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt true
let add_class_decl type_ptr_to_sil_type tenv category_decl_info =
let decl_ref_opt = category_decl_info.Clang_ast_t.odi_class_interface in
Ast_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt true
CAst_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt true
let add_category_implementation type_ptr_to_sil_type tenv category_decl_info =
let decl_ref_opt = category_decl_info.Clang_ast_t.odi_implementation in
Ast_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt false
CAst_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt false
let get_base_class_name_from_category decl =
let open Clang_ast_t in
@ -61,9 +59,9 @@ let get_base_class_name_from_category decl =
| _ -> None in
match base_class_pointer_opt with
| Some decl_ref ->
(match Ast_utils.get_decl decl_ref.Clang_ast_t.dr_decl_pointer with
(match CAst_utils.get_decl decl_ref.Clang_ast_t.dr_decl_pointer with
| Some ObjCInterfaceDecl (_, name_info, _, _, _) ->
Some (Ast_utils.get_qualified_name name_info)
Some (CAst_utils.get_qualified_name name_info)
| _ -> None)
| None -> None
@ -76,11 +74,11 @@ let process_category type_ptr_to_sil_type tenv curr_class decl_info decl_list =
let mang_name = Mangled.from_string class_name in
let class_tn_name = Typename.TN_csu (Csu.Class Csu.Objc, mang_name) in
let decl_key = `DeclPtr decl_info.Clang_ast_t.di_pointer in
Ast_utils.update_sil_types_map decl_key (Typ.Tstruct class_tn_name);
CAst_utils.update_sil_types_map decl_key (Typ.Tstruct class_tn_name);
(match Tenv.lookup tenv class_tn_name with
| Some ({ fields; methods } as struct_typ) ->
let new_fields = General_utils.append_no_duplicates_fields decl_fields fields in
let new_methods = General_utils.append_no_duplicates_methods decl_methods methods in
let new_fields = CGeneral_utils.append_no_duplicates_fields decl_fields fields in
let new_methods = CGeneral_utils.append_no_duplicates_methods decl_methods methods in
ignore(
Tenv.mk_struct tenv
~default:struct_typ ~fields:new_fields ~statics:[] ~methods:new_methods class_tn_name );
@ -92,7 +90,7 @@ let category_decl type_ptr_to_sil_type tenv decl =
let open Clang_ast_t in
match decl with
| ObjCCategoryDecl (decl_info, name_info, decl_list, _, cdi) ->
let name = Ast_utils.get_qualified_name name_info in
let name = CAst_utils.get_qualified_name name_info in
let curr_class = get_curr_class_from_category_decl name cdi in
Logging.out_debug "ADDING: ObjCCategoryDecl for '%s'\n" name;
let _ = add_class_decl type_ptr_to_sil_type tenv cdi in
@ -105,11 +103,10 @@ let category_impl_decl type_ptr_to_sil_type tenv decl =
let open Clang_ast_t in
match decl with
| ObjCCategoryImplDecl (decl_info, name_info, decl_list, _, cii) ->
let name = Ast_utils.get_qualified_name name_info in
let name = CAst_utils.get_qualified_name name_info in
let curr_class = get_curr_class_from_category_impl name cii in
Logging.out_debug "ADDING: ObjCCategoryImplDecl for '%s'\n" name;
let _ = add_category_decl type_ptr_to_sil_type tenv cii in
let typ = process_category type_ptr_to_sil_type tenv curr_class decl_info decl_list in
typ
| _ -> assert false

@ -12,11 +12,9 @@ open! IStd
(** In this module an ObjC category declaration or implementation is processed. The category *)
(** is saved in the tenv as a struct with the corresponding fields and methods , and the class it belongs to *)
open CFrontend_utils
val category_decl : CAst_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.t
val category_decl : Ast_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.t
val category_impl_decl : Ast_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.t
val category_impl_decl : CAst_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.t
val noname_category : string -> string

@ -16,8 +16,6 @@ open! IStd
(* ObjectiveC doesn't have a notion of static or class fields. *)
(* So, in this module we translate a class into a sil srtuct with an empty list of static fields.*)
open CFrontend_utils
module L = Logging
let is_pointer_to_objc_class typ =
@ -27,13 +25,13 @@ let is_pointer_to_objc_class typ =
let get_super_interface_decl otdi_super =
match otdi_super with
| Some dr -> Ast_utils.name_opt_of_name_info_opt dr.Clang_ast_t.dr_name
| Some dr -> CAst_utils.name_opt_of_name_info_opt dr.Clang_ast_t.dr_name
| _ -> None
let get_protocols protocols =
let protocol_names = IList.map (
fun decl -> match decl.Clang_ast_t.dr_name with
| Some name_info -> Ast_utils.get_qualified_name name_info
| Some name_info -> CAst_utils.get_qualified_name name_info
| None -> assert false
) protocols in
protocol_names
@ -47,30 +45,30 @@ let get_curr_class_impl oi =
let open Clang_ast_t in
match oi.Clang_ast_t.oidi_class_interface with
| Some decl_ref ->
(match Ast_utils.get_decl decl_ref.Clang_ast_t.dr_decl_pointer with
(match CAst_utils.get_decl decl_ref.Clang_ast_t.dr_decl_pointer with
| Some ObjCInterfaceDecl (_, name_info, _, _, obj_c_interface_decl_info) ->
let class_name = Ast_utils.get_qualified_name name_info in
let class_name = CAst_utils.get_qualified_name name_info in
get_curr_class class_name obj_c_interface_decl_info
| _ -> assert false)
| _ -> assert false
let add_class_decl type_ptr_to_sil_type tenv idi =
let decl_ref_opt = idi.Clang_ast_t.oidi_class_interface in
Ast_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt true
CAst_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt true
let add_super_class_decl type_ptr_to_sil_type tenv ocdi =
let decl_ref_opt = ocdi.Clang_ast_t.otdi_super in
Ast_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt false
CAst_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt false
let add_protocols_decl type_ptr_to_sil_type tenv protocols =
Ast_utils.add_type_from_decl_ref_list type_ptr_to_sil_type tenv protocols
CAst_utils.add_type_from_decl_ref_list type_ptr_to_sil_type tenv protocols
let add_categories_decl type_ptr_to_sil_type tenv categories =
Ast_utils.add_type_from_decl_ref_list type_ptr_to_sil_type tenv categories
CAst_utils.add_type_from_decl_ref_list type_ptr_to_sil_type tenv categories
let add_class_implementation type_ptr_to_sil_type tenv idi =
let decl_ref_opt = idi.Clang_ast_t.otdi_implementation in
Ast_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt false
CAst_utils.add_type_from_decl_ref type_ptr_to_sil_type tenv decl_ref_opt false
(*The superclass is the first element in the list of super classes of structs in the tenv, *)
(* then come the protocols and categories. *)
@ -95,11 +93,11 @@ let create_supers_fields type_ptr_to_sil_type tenv curr_class decl_list
(* Adds pairs (interface name, interface_type_info) to the global environment. *)
let add_class_to_tenv type_ptr_to_sil_type tenv curr_class decl_info name_info decl_list ocidi =
let class_name = Ast_utils.get_qualified_name name_info in
let class_name = CAst_utils.get_qualified_name name_info in
Logging.out_debug "ADDING: ObjCInterfaceDecl for '%s'\n" class_name;
let interface_name = CType.mk_classname class_name Csu.Objc in
let decl_key = `DeclPtr decl_info.Clang_ast_t.di_pointer in
Ast_utils.update_sil_types_map decl_key (Typ.Tstruct interface_name);
CAst_utils.update_sil_types_map decl_key (Typ.Tstruct interface_name);
let supers, fields =
create_supers_fields type_ptr_to_sil_type tenv curr_class decl_list
ocidi.Clang_ast_t.otdi_super
@ -113,14 +111,14 @@ let add_class_to_tenv type_ptr_to_sil_type tenv curr_class decl_info name_info d
let fields, (supers : Typename.t list), methods =
match Tenv.lookup tenv interface_name with
| Some ({ fields; supers; methods }) ->
General_utils.append_no_duplicates_fields fields fields,
General_utils.append_no_duplicates_csu supers supers,
General_utils.append_no_duplicates_methods methods methods
CGeneral_utils.append_no_duplicates_fields fields fields,
CGeneral_utils.append_no_duplicates_csu supers supers,
CGeneral_utils.append_no_duplicates_methods methods methods
| _ -> fields, supers, methods in
let fields = General_utils.append_no_duplicates_fields fields fields_sc in
let fields = CGeneral_utils.append_no_duplicates_fields fields fields_sc in
(* We add the special hidden counter_field for implementing reference counting *)
let modelled_fields = StructTyp.objc_ref_counter_field :: CField_decl.modelled_field name_info in
let all_fields = General_utils.append_no_duplicates_fields modelled_fields fields in
let all_fields = CGeneral_utils.append_no_duplicates_fields modelled_fields fields in
Logging.out_debug "Class %s field:\n" class_name;
IList.iter (fun (fn, _, _) ->
Logging.out_debug "-----> field: '%s'\n" (Ident.fieldname_to_string fn)) all_fields;
@ -140,11 +138,11 @@ let add_missing_methods tenv class_name ck decl_info decl_list curr_class =
let decl_methods = ObjcProperty_decl.get_methods curr_class decl_list in
let class_tn_name = Typename.TN_csu (Csu.Class ck, (Mangled.from_string class_name)) in
let decl_key = `DeclPtr decl_info.Clang_ast_t.di_pointer in
Ast_utils.update_sil_types_map decl_key (Typ.Tstruct class_tn_name);
CAst_utils.update_sil_types_map decl_key (Typ.Tstruct class_tn_name);
begin
match class_tn_name, Tenv.lookup tenv class_tn_name with
| TN_csu (Class _, _), Some ({ statics = []; methods; } as struct_typ) ->
let methods = General_utils.append_no_duplicates_methods methods decl_methods in
let methods = CGeneral_utils.append_no_duplicates_methods methods decl_methods in
ignore( Tenv.mk_struct tenv ~default:struct_typ ~methods class_tn_name )
| _ -> ()
end;
@ -155,7 +153,7 @@ let interface_declaration type_ptr_to_sil_type tenv decl =
let open Clang_ast_t in
match decl with
| ObjCInterfaceDecl (decl_info, name_info, decl_list, _, ocidi) ->
let name = Ast_utils.get_qualified_name name_info in
let name = CAst_utils.get_qualified_name name_info in
let curr_class = get_curr_class name ocidi in
let typ = add_class_to_tenv type_ptr_to_sil_type tenv curr_class decl_info name_info
decl_list ocidi in
@ -172,7 +170,7 @@ let interface_impl_declaration type_ptr_to_sil_type tenv decl =
let open Clang_ast_t in
match decl with
| ObjCImplementationDecl (decl_info, name_info, decl_list, _, idi) ->
let class_name = Ast_utils.get_qualified_name name_info in
let class_name = CAst_utils.get_qualified_name name_info in
Logging.out_debug "ADDING: ObjCImplementationDecl for class '%s'\n" class_name;
let _ = add_class_decl type_ptr_to_sil_type tenv idi in
let curr_class = get_curr_class_impl idi in

@ -11,12 +11,11 @@ open! IStd
(** In this module an ObjC interface declaration is processed. The class is saved in the tenv as a
struct with the corresponding fields, potential superclass and list of defined methods *)
open CFrontend_utils
val interface_declaration : Ast_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl ->
val interface_declaration : CAst_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl ->
Typ.t
val interface_impl_declaration : Ast_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl ->
val interface_impl_declaration : CAst_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl ->
Typ.t
val is_pointer_to_objc_class : Typ.t -> bool

@ -17,8 +17,6 @@ open! IStd
(* - Second, in the class implementation, if synthetize is available, create the getters and setters, *)
(* unless some of these methods has already been created before. *)
open CFrontend_utils
let is_strong_property obj_c_property_decl_info =
let attrs = obj_c_property_decl_info.Clang_ast_t.opdi_property_attributes in
IList.exists (fun a -> match a with
@ -41,7 +39,8 @@ let get_methods curr_class decl_list =
let method_kind = Procname.objc_method_kind_of_bool is_instance in
let method_name = name_info.Clang_ast_t.ni_name in
Logging.out_debug " ...Adding Method '%s' \n" (class_name^"_"^method_name);
let meth_name = General_utils.mk_procname_from_objc_method class_name method_name method_kind in
let meth_name =
CGeneral_utils.mk_procname_from_objc_method class_name method_name method_kind in
meth_name:: list_methods
| _ -> list_methods in
IList.fold_right get_method decl_list []

@ -9,19 +9,17 @@
open! IStd
open CFrontend_utils
module L = Logging
let add_protocol_super type_ptr_to_sil_type tenv obj_c_protocol_decl_info =
let protocols = obj_c_protocol_decl_info.Clang_ast_t.opcdi_protocols in
Ast_utils.add_type_from_decl_ref_list type_ptr_to_sil_type tenv protocols
CAst_utils.add_type_from_decl_ref_list type_ptr_to_sil_type tenv protocols
let protocol_decl type_ptr_to_sil_type tenv decl =
let open Clang_ast_t in
match decl with
| ObjCProtocolDecl(decl_info, name_info, decl_list, _, obj_c_protocol_decl_info) ->
let name = Ast_utils.get_qualified_name name_info in
let name = CAst_utils.get_qualified_name name_info in
let curr_class = CContext.ContextProtocol name in
(* Adds pairs (protocol name, protocol_type_info) to the global environment. *)
(* Protocol_type_info contains the methods composing the protocol. *)
@ -31,7 +29,7 @@ let protocol_decl type_ptr_to_sil_type tenv decl =
let mang_name = Mangled.from_string name in
let protocol_name = Typename.TN_csu (Csu.Protocol, mang_name) in
let decl_key = `DeclPtr decl_info.Clang_ast_t.di_pointer in
Ast_utils.update_sil_types_map decl_key (Typ.Tstruct protocol_name);
CAst_utils.update_sil_types_map decl_key (Typ.Tstruct protocol_name);
let methods = ObjcProperty_decl.get_methods curr_class decl_list in
ignore( Tenv.mk_struct tenv ~methods protocol_name );
add_protocol_super type_ptr_to_sil_type tenv obj_c_protocol_decl_info;

@ -12,8 +12,6 @@ open! IStd
(** In this module an ObjC protocol declaration or implementation is processed. The protocol *)
(** is saved in the tenv as a struct with the corresponding methods *)
open CFrontend_utils
val protocol_decl : Ast_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.t
val protocol_decl : CAst_utils.type_ptr_to_sil_type -> Tenv.t -> Clang_ast_t.decl -> Typ.t
val is_protocol : Clang_ast_t.decl -> bool

@ -9,8 +9,6 @@
open! IStd
open CFrontend_utils
let get_available_attr_ios_sdk decl =
let open Clang_ast_t in
let decl_info = Clang_ast_proj.get_decl_tuple decl in
@ -30,7 +28,7 @@ let get_ivar_attributes ivar_decl =
let open Clang_ast_t in
match ivar_decl with
| ObjCIvarDecl (ivar_decl_info, _, _, _, _) ->
(match Ast_utils.get_property_of_ivar ivar_decl_info.Clang_ast_t.di_pointer with
(match CAst_utils.get_property_of_ivar ivar_decl_info.Clang_ast_t.di_pointer with
| Some ObjCPropertyDecl (_, _, obj_c_property_decl_info) ->
obj_c_property_decl_info.Clang_ast_t.opdi_property_attributes
| _ -> [])
@ -40,11 +38,11 @@ let get_ivar_attributes ivar_decl =
let captured_variables_cxx_ref dec =
let capture_var_is_cxx_ref reference_captured_vars captured_var =
let decl_ref_opt = captured_var.Clang_ast_t.bcv_variable in
match Ast_utils.get_decl_opt_with_decl_ref decl_ref_opt with
match CAst_utils.get_decl_opt_with_decl_ref decl_ref_opt with
| Some VarDecl (_, named_decl_info, qual_type, _)
| Some ParmVarDecl (_, named_decl_info, qual_type, _)
| Some ImplicitParamDecl (_, named_decl_info, qual_type, _) ->
(match Ast_utils.get_desugared_type qual_type.Clang_ast_t.qt_type_ptr with
(match CAst_utils.get_desugared_type qual_type.Clang_ast_t.qt_type_ptr with
| Some RValueReferenceType _ | Some LValueReferenceType _ ->
named_decl_info::reference_captured_vars
| _ -> reference_captured_vars)
@ -81,25 +79,25 @@ let property_name_contains_word word decl =
| _ -> false
let is_objc_extension lcxt =
General_utils.is_objc_extension lcxt.CLintersContext.translation_unit_context
CGeneral_utils.is_objc_extension lcxt.CLintersContext.translation_unit_context
let is_syntactically_global_var decl =
Ast_utils.is_syntactically_global_var decl
CAst_utils.is_syntactically_global_var decl
let is_const_expr_var decl =
Ast_utils.is_const_expr_var decl
CAst_utils.is_const_expr_var decl
let decl_ref_is_in names st =
match st with
| Clang_ast_t.DeclRefExpr (_, _, _, drti) ->
(match drti.drti_decl_ref with
| Some dr -> let ndi, _, _ = CFrontend_utils.Ast_utils.get_info_from_decl_ref dr in
| Some dr -> let ndi, _, _ = CAst_utils.get_info_from_decl_ref dr in
IList.exists (fun n -> n = ndi.ni_name) names
| _ -> false)
| _ -> false
let call_function_named names st =
Ast_utils.exists_eventually_st decl_ref_is_in names st
CAst_utils.exists_eventually_st decl_ref_is_in names st
let is_strong_property decl =
match decl with
@ -117,12 +115,12 @@ let is_property_pointer_type decl =
let open Clang_ast_t in
match decl with
| ObjCPropertyDecl (_, _, pdi) ->
(match Ast_utils.get_desugared_type pdi.opdi_type_ptr with
(match CAst_utils.get_desugared_type pdi.opdi_type_ptr with
| Some MemberPointerType _
| Some ObjCObjectPointerType _
| Some BlockPointerType _ -> true
| Some TypedefType (_, tti) ->
(Ast_utils.name_of_typedef_type_info tti) = CFrontend_config.id_cl
(CAst_utils.name_of_typedef_type_info tti) = CFrontend_config.id_cl
| exception Not_found -> false
| _ -> false)
| _ -> false
@ -136,10 +134,10 @@ let is_ivar_atomic stmt =
| Clang_ast_t.ObjCIvarRefExpr (_, _, _, irei) ->
let dr_ref = irei.Clang_ast_t.ovrei_decl_ref in
let ivar_pointer = dr_ref.Clang_ast_t.dr_decl_pointer in
(match Ast_utils.get_decl ivar_pointer with
(match CAst_utils.get_decl ivar_pointer with
| Some d ->
let attributes = get_ivar_attributes d in
IList.exists (Ast_utils.equal_property_attribute `Atomic) attributes
IList.exists (CAst_utils.equal_property_attribute `Atomic) attributes
| _ -> false)
| _ -> false
@ -153,7 +151,7 @@ let is_method_property_accessor_of_ivar stmt context =
| Some ObjCMethodDecl (_, _, mdi) ->
if mdi.omdi_is_property_accessor then
let property_opt = mdi.omdi_property_decl in
match Ast_utils.get_decl_opt_with_decl_ref property_opt with
match CAst_utils.get_decl_opt_with_decl_ref property_opt with
| Some ObjCPropertyDecl (_, _, pdi) ->
(match pdi.opdi_ivar_decl with
| Some decl_ref -> decl_ref.dr_decl_pointer = ivar_pointer
@ -214,8 +212,8 @@ let is_decl nodename decl =
let isa classname stmt =
match Clang_ast_proj.get_expr_tuple stmt with
| Some (_, _, expr_info) ->
let typ = CFrontend_utils.Ast_utils.get_desugared_type expr_info.ei_type_ptr in
CFrontend_utils.Ast_utils.is_ptr_to_objc_class typ classname
let typ = CAst_utils.get_desugared_type expr_info.ei_type_ptr in
CAst_utils.is_ptr_to_objc_class typ classname
| _ -> false
let decl_unavailable_in_supported_ios_sdk decl =

Loading…
Cancel
Save