@ -11,6 +11,86 @@ open! IStd
(* * Processes types and record declarations by adding them to the tenv *)
let get_struct_decls decl =
let open Clang_ast_t in
match decl with
| CapturedDecl ( _ , decl_list , _ )
| ClassTemplateSpecializationDecl ( _ , _ , _ , decl_list , _ , _ , _ , _ , _ , _ )
| ClassTemplatePartialSpecializationDecl ( _ , _ , _ , decl_list , _ , _ , _ , _ , _ , _ )
| CXXRecordDecl ( _ , _ , _ , decl_list , _ , _ , _ , _ )
| EnumDecl ( _ , _ , _ , decl_list , _ , _ , _ )
| LinkageSpecDecl ( _ , decl_list , _ )
| NamespaceDecl ( _ , _ , decl_list , _ , _ )
| ObjCCategoryDecl ( _ , _ , decl_list , _ , _ )
| ObjCCategoryImplDecl ( _ , _ , decl_list , _ , _ )
| ObjCImplementationDecl ( _ , _ , decl_list , _ , _ )
| ObjCInterfaceDecl ( _ , _ , decl_list , _ , _ )
| ObjCProtocolDecl ( _ , _ , decl_list , _ , _ )
| RecordDecl ( _ , _ , _ , decl_list , _ , _ , _ )
| TranslationUnitDecl ( _ , decl_list , _ , _ ) ->
decl_list
| AccessSpecDecl _
| BlockDecl _
| ClassScopeFunctionSpecializationDecl _
| EmptyDecl _
| ExportDecl _
| ExternCContextDecl _
| FileScopeAsmDecl _
| FriendDecl _
| FriendTemplateDecl _
| ImportDecl _
| LabelDecl _
| NamespaceAliasDecl _
| ObjCCompatibleAliasDecl _
| ObjCMethodDecl _
| ObjCPropertyDecl _
| BuiltinTemplateDecl _
| ClassTemplateDecl _
| FunctionTemplateDecl _
| TypeAliasTemplateDecl _
| VarTemplateDecl _
| TemplateTemplateParmDecl _
| TemplateTypeParmDecl _
| ObjCTypeParamDecl _
| TypeAliasDecl _
| TypedefDecl _
| UnresolvedUsingTypenameDecl _
| UsingDecl _
| UsingDirectiveDecl _
| UsingPackDecl _
| UsingShadowDecl _
| ConstructorUsingShadowDecl _
| BindingDecl _
| FieldDecl _
| ObjCAtDefsFieldDecl _
| ObjCIvarDecl _
| FunctionDecl _
| CXXDeductionGuideDecl _
| CXXMethodDecl _
| CXXConstructorDecl _
| CXXConversionDecl _
| CXXDestructorDecl _
| MSPropertyDecl _
| NonTypeTemplateParmDecl _
| VarDecl _
| DecompositionDecl _
| ImplicitParamDecl _
| OMPCapturedExprDecl _
| ParmVarDecl _
| VarTemplateSpecializationDecl _
| VarTemplatePartialSpecializationDecl _
| EnumConstantDecl _
| IndirectFieldDecl _
| OMPDeclareReductionDecl _
| UnresolvedUsingValueDecl _
| OMPThreadPrivateDecl _
| ObjCPropertyImplDecl _
| PragmaCommentDecl _
| PragmaDetectMismatchDecl _
| StaticAssertDecl _ ->
[]
let add_predefined_objc_types tenv =
ignore ( Tenv . mk_struct tenv ( CType_to_sil_type . get_builtin_objc_typename ` ObjCClass ) ) ;
ignore ( Tenv . mk_struct tenv ( CType_to_sil_type . get_builtin_objc_typename ` ObjCId ) )
@ -102,84 +182,52 @@ let get_record_definition decl =
decl
let get_struct_decls decl =
let is_decl_info_generic_model { Clang_ast_t . di_attributes } =
let f = function
| Clang_ast_t . AnnotateAttr { ai_parameters = [ _ ; name ; _ ] }
when String . equal name " __infer_generic_model " ->
true
| _ ->
false
in
List . exists ~ f di_attributes
(* * Global counter for anonymous block *)
let block_counter = ref 0
let get_fresh_block_index () =
block_counter := ! block_counter + 1 ;
! block_counter
let mk_objc_method class_typename method_name method_kind =
Typ . Procname . ObjC_Cpp
( Typ . Procname . ObjC_Cpp . make class_typename method_name method_kind Typ . NoTemplate
~ is_generic_model : false )
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 decl with
| CapturedDecl ( _ , decl_list , _ )
| ClassTemplateSpecializationDecl ( _ , _ , _ , decl_list , _ , _ , _ , _ , _ , _ )
| ClassTemplatePartialSpecializationDecl ( _ , _ , _ , decl_list , _ , _ , _ , _ , _ , _ )
| CXXRecordDecl ( _ , _ , _ , decl_list , _ , _ , _ , _ )
| EnumDecl ( _ , _ , _ , decl_list , _ , _ , _ )
| LinkageSpecDecl ( _ , decl_list , _ )
| NamespaceDecl ( _ , _ , decl_list , _ , _ )
| ObjCCategoryDecl ( _ , _ , decl_list , _ , _ )
| ObjCCategoryImplDecl ( _ , _ , decl_list , _ , _ )
| ObjCImplementationDecl ( _ , _ , decl_list , _ , _ )
| ObjCInterfaceDecl ( _ , _ , decl_list , _ , _ )
| ObjCProtocolDecl ( _ , _ , decl_list , _ , _ )
| RecordDecl ( _ , _ , _ , decl_list , _ , _ , _ )
| TranslationUnitDecl ( _ , decl_list , _ , _ ) ->
decl_list
| AccessSpecDecl _
| BlockDecl _
| ClassScopeFunctionSpecializationDecl _
| EmptyDecl _
| ExportDecl _
| ExternCContextDecl _
| FileScopeAsmDecl _
| FriendDecl _
| FriendTemplateDecl _
| ImportDecl _
| LabelDecl _
| NamespaceAliasDecl _
| ObjCCompatibleAliasDecl _
| ObjCMethodDecl _
| ObjCPropertyDecl _
| BuiltinTemplateDecl _
| ClassTemplateDecl _
| FunctionTemplateDecl _
| TypeAliasTemplateDecl _
| VarTemplateDecl _
| TemplateTemplateParmDecl _
| TemplateTypeParmDecl _
| ObjCTypeParamDecl _
| TypeAliasDecl _
| TypedefDecl _
| UnresolvedUsingTypenameDecl _
| UsingDecl _
| UsingDirectiveDecl _
| UsingPackDecl _
| UsingShadowDecl _
| ConstructorUsingShadowDecl _
| BindingDecl _
| FieldDecl _
| ObjCAtDefsFieldDecl _
| ObjCIvarDecl _
| FunctionDecl _
| CXXDeductionGuideDecl _
| CXXMethodDecl _
| CXXConstructorDecl _
| CXXConversionDecl _
| CXXDestructorDecl _
| MSPropertyDecl _
| NonTypeTemplateParmDecl _
| VarDecl _
| DecompositionDecl _
| ImplicitParamDecl _
| OMPCapturedExprDecl _
| ParmVarDecl _
| VarTemplateSpecializationDecl _
| VarTemplatePartialSpecializationDecl _
| EnumConstantDecl _
| IndirectFieldDecl _
| OMPDeclareReductionDecl _
| UnresolvedUsingValueDecl _
| OMPThreadPrivateDecl _
| ObjCPropertyImplDecl _
| PragmaCommentDecl _
| PragmaDetectMismatchDecl _
| StaticAssertDecl _ ->
[]
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 rec get_struct_fields tenv decl =
@ -293,49 +341,6 @@ and get_superclass_list_cpp tenv decl =
List . map ~ f : get_super_field base_decls
and get_record_struct_type tenv definition_decl : Typ . desc =
let open Clang_ast_t in
match definition_decl with
| ClassTemplateSpecializationDecl ( _ , _ , type_ptr , _ , _ , _ , record_decl_info , _ , _ , _ )
| CXXRecordDecl ( _ , _ , type_ptr , _ , _ , _ , record_decl_info , _ )
| RecordDecl ( _ , _ , type_ptr , _ , _ , _ , record_decl_info )
-> (
let sil_typename = get_record_typename ~ tenv definition_decl in
let sil_desc = Typ . Tstruct sil_typename in
match Tenv . lookup tenv sil_typename with
| Some _ ->
sil_desc (* just reuse what is already in tenv *)
| None ->
let is_translatable_definition =
let open Clang_ast_t in
record_decl_info . rdi_is_complete_definition
&& not record_decl_info . rdi_is_dependent_type
in
if is_translatable_definition then (
CAst_utils . update_sil_types_map type_ptr sil_desc ;
let fields = get_struct_fields tenv definition_decl in
let statics = [] in
(* Note: We treat static field same as global variables *)
let methods = [] in
(* C++ methods are not put into tenv ( info isn't used ) *)
let supers = get_superclass_list_cpp tenv definition_decl in
let annots =
if Typ . Name . Cpp . is_class sil_typename then Annot . Class . cpp
else (* No annotations for structs *) Annot . Item . empty
in
Tenv . mk_struct tenv ~ fields ~ statics ~ methods ~ supers ~ annots sil_typename | > ignore ;
CAst_utils . update_sil_types_map type_ptr sil_desc ;
sil_desc )
else (
(* There is no definition for that struct in whole translation unit.
Put empty struct into tenv to prevent backend problems * )
ignore ( Tenv . mk_struct tenv ~ fields : [] sil_typename ) ;
CAst_utils . update_sil_types_map type_ptr sil_desc ;
sil_desc ) )
| _ ->
assert false
and add_types_from_decl_to_tenv tenv decl =
let open Clang_ast_t in
match decl with
@ -379,31 +384,7 @@ and qual_type_to_sil_type tenv qual_type =
CType_to_sil_type . qual_type_to_sil_type add_types_from_decl_to_tenv tenv qual_type
module CProcname = struct
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 get_template_info tenv ( fdi : Clang_ast_t . function_decl_info ) =
and get_template_info tenv ( fdi : Clang_ast_t . function_decl_info ) =
match fdi . fdi_template_specialization with
| Some spec_info ->
Typ . Template { mangled = fdi . fdi_mangled_name ; args = get_template_args tenv spec_info }
@ -411,18 +392,7 @@ module CProcname = struct
Typ . NoTemplate
let is_decl_info_generic_model { Clang_ast_t . di_attributes } =
let f = function
| Clang_ast_t . AnnotateAttr { ai_parameters = [ _ ; name ; _ ] }
when String . equal name " __infer_generic_model " ->
true
| _ ->
false
in
List . exists ~ f di_attributes
let mk_c_function ? tenv ~ is_cpp name function_decl_info_opt =
and mk_c_function ? tenv ~ is_cpp name function_decl_info_opt =
let file =
match function_decl_info_opt with
| Some ( decl_info , function_decl_info ) -> (
@ -431,8 +401,7 @@ module CProcname = struct
(* when we model static functions, we cannot take the file into account to
create a mangled name because the file of the model is different to the real file ,
thus the model won't work * )
when not
( CTrans_models . is_modelled_static_function ( QualifiedCppName . to_qual_string name ) ) ->
when not ( CTrans_models . is_modelled_static_function ( QualifiedCppName . to_qual_string name ) ) ->
let file_opt =
( fst decl_info . Clang_ast_t . di_source_range ) . Clang_ast_t . sl_file
| > Option . map ~ f : SourceFile . from_abs_path
@ -465,7 +434,7 @@ module CProcname = struct
else Typ . Procname . C ( Typ . Procname . c name mangled template_info ~ is_generic_model )
let mk_cpp_method ? tenv class_name method_name ? meth_decl mangled =
and mk_cpp_method ? tenv class_name method_name ? meth_decl mangled =
let open Clang_ast_t in
let method_kind =
match meth_decl with
@ -497,37 +466,10 @@ module CProcname = struct
( Typ . NoTemplate , false )
in
Typ . Procname . ObjC_Cpp
( Typ . Procname . ObjC_Cpp . make class_name method_name method_kind template_info
~ is_generic_model )
let mk_objc_method class_typename method_name method_kind =
Typ . Procname . ObjC_Cpp
( Typ . Procname . ObjC_Cpp . make class_typename method_name method_kind Typ . NoTemplate
~ is_generic_model : false )
let block_procname_with_index defining_proc i =
Config . anonymous_block_prefix ^ Typ . Procname . to_string defining_proc
^ Config . anonymous_block_num_sep ^ string_of_int i
(* * Global counter for anonymous block *)
let block_counter = ref 0
let reset_block_counter () = block_counter := 0
let get_fresh_block_index () =
block_counter := ! block_counter + 1 ;
! block_counter
let mk_fresh_block_procname defining_proc =
let name = block_procname_with_index defining_proc ( get_fresh_block_index () ) in
Typ . Procname . mangled_objc_block name
( Typ . Procname . ObjC_Cpp . make class_name method_name method_kind template_info ~ is_generic_model )
let get_class_typename ? tenv method_decl_info =
and get_class_typename ? tenv method_decl_info =
let class_ptr = Option . value_exn method_decl_info . Clang_ast_t . di_parent_pointer in
match CAst_utils . get_decl class_ptr with
| Some class_decl ->
@ -537,28 +479,14 @@ module CProcname = struct
" Expecting class declaration when getting the class typename "
module NoAstDecl = struct
let c_function_of_string ~ is_cpp tenv name =
let qual_name = QualifiedCppName . of_qual_string name in
mk_c_function ~ is_cpp ~ tenv qual_name None
let cpp_method_of_string tenv class_name method_name =
mk_cpp_method ~ tenv class_name method_name None
let objc_method_of_string_kind class_name method_name method_kind =
mk_objc_method class_name method_name method_kind
end
let objc_method_procname ? tenv decl_info method_name mdi =
and objc_method_procname ? tenv decl_info method_name mdi =
let class_typename = get_class_typename ? tenv decl_info in
let is_instance = mdi . Clang_ast_t . omdi_is_instance_method in
let method_kind = Typ . Procname . ObjC_Cpp . objc_method_kind_of_bool is_instance in
mk_objc_method class_typename method_name method_kind
let from_decl ? tenv ~ is_cpp meth_decl =
and from_decl ? tenv ~ is_cpp meth_decl =
let open Clang_ast_t in
match meth_decl with
| FunctionDecl ( decl_info , name_info , _ , fdi ) ->
@ -586,6 +514,95 @@ module CProcname = struct
( Clang_ast_proj . get_decl_kind_string meth_decl )
and get_struct_methods struct_decl tenv =
let open Clang_ast_t in
List . filter_map ( get_struct_decls struct_decl ) ~ f : ( fun decl ->
match decl with
| FunctionDecl _
| CXXMethodDecl _
| CXXConstructorDecl _
| CXXConversionDecl _
| CXXDestructorDecl _
| ObjCMethodDecl _
| BlockDecl _ ->
Some ( from_decl ~ is_cpp : true ~ tenv decl )
| _ ->
None )
and get_record_struct_type tenv definition_decl : Typ . desc =
let open Clang_ast_t in
match definition_decl with
| ClassTemplateSpecializationDecl ( _ , _ , type_ptr , _ , _ , _ , record_decl_info , _ , _ , _ )
| CXXRecordDecl ( _ , _ , type_ptr , _ , _ , _ , record_decl_info , _ )
| RecordDecl ( _ , _ , type_ptr , _ , _ , _ , record_decl_info )
-> (
let sil_typename = get_record_typename ~ tenv definition_decl in
let sil_desc = Typ . Tstruct sil_typename in
match Tenv . lookup tenv sil_typename with
| Some _ ->
sil_desc (* just reuse what is already in tenv *)
| None ->
let is_translatable_definition =
let open Clang_ast_t in
record_decl_info . rdi_is_complete_definition
&& not record_decl_info . rdi_is_dependent_type
in
if is_translatable_definition then (
CAst_utils . update_sil_types_map type_ptr sil_desc ;
let fields = get_struct_fields tenv definition_decl in
(* Note: We treat static field same as global variables *)
let statics = [] in
let methods = get_struct_methods definition_decl tenv in
let supers = get_superclass_list_cpp tenv definition_decl in
let annots =
if Typ . Name . Cpp . is_class sil_typename then Annot . Class . cpp
else (* No annotations for structs *) Annot . Item . empty
in
Tenv . mk_struct tenv ~ fields ~ statics ~ methods ~ supers ~ annots sil_typename | > ignore ;
CAst_utils . update_sil_types_map type_ptr sil_desc ;
sil_desc )
else (
(* There is no definition for that struct in whole translation unit.
Put empty struct into tenv to prevent backend problems * )
ignore ( Tenv . mk_struct tenv ~ fields : [] sil_typename ) ;
CAst_utils . update_sil_types_map type_ptr sil_desc ;
sil_desc ) )
| _ ->
assert false
module CProcname = struct
let from_decl = from_decl
(* silly, but required to avoid circular dependencies *)
let reset_block_counter () = block_counter := 0
let block_procname_with_index defining_proc i =
Config . anonymous_block_prefix ^ Typ . Procname . to_string defining_proc
^ Config . anonymous_block_num_sep ^ string_of_int i
let mk_fresh_block_procname defining_proc =
let name = block_procname_with_index defining_proc ( get_fresh_block_index () ) in
Typ . Procname . mangled_objc_block name
module NoAstDecl = struct
let c_function_of_string ~ is_cpp tenv name =
let qual_name = QualifiedCppName . of_qual_string name in
mk_c_function ~ is_cpp ~ tenv qual_name None
let cpp_method_of_string tenv class_name method_name =
mk_cpp_method ~ tenv class_name method_name None
let objc_method_of_string_kind class_name method_name method_kind =
mk_objc_method class_name method_name method_kind
end
let from_decl_for_linters ~ is_cpp method_decl =
let open Clang_ast_t in
match method_decl with