From 7d5e129ac0ab97e0cb3382ad7cab85225cb62545 Mon Sep 17 00:00:00 2001 From: Dulma Rodriguez Date: Fri, 13 Nov 2015 03:36:07 -0800 Subject: [PATCH] Translate categories on demand Summary: public Categories are now also only translated on demand. For this we needed links from the class to the categories which we have now. Reviewed By: akotulski Differential Revision: D2647072 fb-gh-sync-id: 4afdf5f --- infer/src/clang/cFrontend.ml | 136 ++++++++++++-------------- infer/src/clang/objcInterface_decl.ml | 5 + 2 files changed, 69 insertions(+), 72 deletions(-) diff --git a/infer/src/clang/cFrontend.ml b/infer/src/clang/cFrontend.ml index efaf91401..50f130149 100644 --- a/infer/src/clang/cFrontend.ml +++ b/infer/src/clang/cFrontend.ml @@ -21,6 +21,7 @@ open CGen_trans (* Translate one global declaration *) let rec translate_one_declaration tenv cg cfg namespace parent_dec dec = + let open Clang_ast_t in (* each procedure has different scope: start names from id 0 *) Ident.NameGenerator.reset (); @@ -29,85 +30,76 @@ let rec translate_one_declaration tenv cg cfg namespace parent_dec dec = CLocation.update_curr_file info; let source_range = info.Clang_ast_t.di_source_range in let should_translate_decl = CLocation.should_translate_lib source_range in - let open Clang_ast_t in + (if should_translate_decl then + match dec with + | FunctionDecl(di, name_info, tp, fdecl_info) -> + CMethod_declImpl.function_decl tenv cfg cg namespace dec None + + (* Currently C/C++ record decl treated in the same way *) + | CXXRecordDecl (_, _, _, _, decl_list, _, _, _) | RecordDecl (_, _, _, _, decl_list, _, _) -> + ignore (CTypes_decl.add_types_from_decl_to_tenv tenv namespace dec); + let method_decls = CTypes_decl.get_method_decls dec decl_list in + let tranlate_method (parent, decl) = + translate_one_declaration tenv cg cfg namespace parent decl in + IList.iter tranlate_method method_decls + + | ObjCInterfaceDecl(decl_info, name_info, decl_list, decl_context_info, oi_decl_info) -> + let name = name_info.Clang_ast_t.ni_name in + let curr_class = ObjcInterface_decl.get_curr_class name oi_decl_info in + ignore + (ObjcInterface_decl.interface_declaration CTypes_decl.type_ptr_to_sil_type tenv dec); + CMethod_declImpl.process_methods tenv cg cfg curr_class namespace decl_list + + | ObjCProtocolDecl(decl_info, name_info, decl_list, decl_context_info, _) -> + let name = name_info.Clang_ast_t.ni_name in + let curr_class = CContext.ContextProtocol name in + ignore (ObjcProtocol_decl.protocol_decl CTypes_decl.type_ptr_to_sil_type tenv dec); + CMethod_declImpl.process_methods tenv cg cfg curr_class namespace decl_list + + | ObjCCategoryDecl(decl_info, name_info, decl_list, decl_context_info, ocdi) -> + let name = name_info.Clang_ast_t.ni_name in + let curr_class = ObjcCategory_decl.get_curr_class_from_category_decl name ocdi in + ignore (ObjcCategory_decl.category_decl CTypes_decl.type_ptr_to_sil_type tenv dec); + CMethod_declImpl.process_methods tenv cg cfg curr_class namespace decl_list + + | ObjCCategoryImplDecl(decl_info, name_info, decl_list, decl_context_info, ocidi) -> + let name = name_info.Clang_ast_t.ni_name in + let curr_class = ObjcCategory_decl.get_curr_class_from_category_impl name ocidi in + ignore (ObjcCategory_decl.category_impl_decl CTypes_decl.type_ptr_to_sil_type tenv dec); + CMethod_declImpl.process_methods tenv cg cfg curr_class namespace decl_list + + | ObjCImplementationDecl(decl_info, name_info, decl_list, decl_context_info, idi) -> + let curr_class = ObjcInterface_decl.get_curr_class_impl idi in + let type_ptr_to_sil_type = CTypes_decl.type_ptr_to_sil_type in + ignore (ObjcInterface_decl.interface_impl_declaration type_ptr_to_sil_type tenv dec); + CMethod_declImpl.process_methods tenv cg cfg curr_class namespace decl_list; + CFrontend_errors.check_for_property_errors cfg curr_class + + | CXXMethodDecl (decl_info, name_info, type_ptr, function_decl_info, _) + | CXXConstructorDecl (decl_info, name_info, type_ptr, function_decl_info, _) -> + (* di_parent_pointer has pointer to lexical context such as class.*) + (* If it's not defined, then it's the same as parent in AST *) + let class_decl = match decl_info.Clang_ast_t.di_parent_pointer with + | Some ptr -> Ast_utils.get_decl ptr + | None -> Some parent_dec in + (match class_decl with + | Some (CXXRecordDecl _ as d) -> + let class_name = CTypes_decl.get_record_name d in + let curr_class = CContext.ContextCls(class_name, None, []) in + if !CFrontend_config.testing_mode then + CMethod_declImpl.process_methods tenv cg cfg curr_class namespace [dec] + | Some dec -> Printing.log_stats "Methods of %s skipped\n" (Ast_utils.string_of_decl dec) + | None -> ()) + | dec -> ()); match dec with - | FunctionDecl(di, name_info, tp, fdecl_info) when should_translate_decl -> - CMethod_declImpl.function_decl tenv cfg cg namespace dec None - | TypedefDecl (decl_info, name_info, opt_type, _, typedef_decl_info) -> - Printing.log_out "%s" "Skipping typedef declaration. Will expand the type in its occurrences." - (* Currently C/C++ record decl treated in the same way *) - | CXXRecordDecl (_, _, _, _, decl_list, _, _, _) - | RecordDecl (_, _, _, _, decl_list, _, _) when should_translate_decl -> - ignore (CTypes_decl.add_types_from_decl_to_tenv tenv namespace dec); - let method_decls = CTypes_decl.get_method_decls dec decl_list in - let tranlate_method (parent, decl) = - translate_one_declaration tenv cg cfg namespace parent decl in - IList.iter tranlate_method method_decls - - | VarDecl(decl_info, name_info, t, _) -> - Printing.log_out "Nothing to do for global variable %s " name_info.Clang_ast_t.ni_name - - | ObjCInterfaceDecl(decl_info, name_info, decl_list, decl_context_info, oi_decl_info) - when should_translate_decl -> - let name = name_info.Clang_ast_t.ni_name in - let curr_class = ObjcInterface_decl.get_curr_class name oi_decl_info in - ignore (ObjcInterface_decl.interface_declaration CTypes_decl.type_ptr_to_sil_type tenv dec); - CMethod_declImpl.process_methods tenv cg cfg curr_class namespace decl_list - - | ObjCProtocolDecl(decl_info, name_info, decl_list, decl_context_info, obj_c_protocol_decl_info) - when should_translate_decl -> - let name = name_info.Clang_ast_t.ni_name in - let curr_class = CContext.ContextProtocol name in - ignore (ObjcProtocol_decl.protocol_decl CTypes_decl.type_ptr_to_sil_type tenv dec); - CMethod_declImpl.process_methods tenv cg cfg curr_class namespace decl_list - - | ObjCCategoryDecl(decl_info, name_info, decl_list, decl_context_info, ocdi) -> - let name = name_info.Clang_ast_t.ni_name in - let curr_class = ObjcCategory_decl.get_curr_class_from_category_decl name ocdi in - ignore (ObjcCategory_decl.category_decl CTypes_decl.type_ptr_to_sil_type tenv dec); - CMethod_declImpl.process_methods tenv cg cfg curr_class namespace decl_list - - | ObjCCategoryImplDecl(decl_info, name_info, decl_list, decl_context_info, ocidi) -> - let name = name_info.Clang_ast_t.ni_name in - let curr_class = ObjcCategory_decl.get_curr_class_from_category_impl name ocidi in - ignore (ObjcCategory_decl.category_impl_decl CTypes_decl.type_ptr_to_sil_type tenv dec); - CMethod_declImpl.process_methods tenv cg cfg curr_class namespace decl_list - - | ObjCImplementationDecl(decl_info, name_info, decl_list, decl_context_info, idi) - when should_translate_decl -> - let curr_class = ObjcInterface_decl.get_curr_class_impl idi in - let type_ptr_to_sil_type = CTypes_decl.type_ptr_to_sil_type in - ignore (ObjcInterface_decl.interface_impl_declaration type_ptr_to_sil_type tenv dec); - CMethod_declImpl.process_methods tenv cg cfg curr_class namespace decl_list; - CFrontend_errors.check_for_property_errors cfg curr_class - - | CXXMethodDecl (decl_info, name_info, type_ptr, function_decl_info, _) - | CXXConstructorDecl (decl_info, name_info, type_ptr, function_decl_info, _) - when should_translate_decl -> - (* di_parent_pointer has pointer to lexical context such as class.*) - (* If it's not defined, then it's the same as parent in AST *) - let class_decl = match decl_info.Clang_ast_t.di_parent_pointer with - | Some ptr -> Ast_utils.get_decl ptr - | None -> Some parent_dec in - (match class_decl with - | Some (CXXRecordDecl _ as d) -> - let class_name = CTypes_decl.get_record_name d in - let curr_class = CContext.ContextCls(class_name, None, []) in - if !CFrontend_config.testing_mode then - CMethod_declImpl.process_methods tenv cg cfg curr_class namespace [dec] - | Some dec -> Printing.log_stats "Methods of %s skipped\n" (Ast_utils.string_of_decl dec) - | None -> ()) - | EnumDecl _ -> ignore (CEnum_decl.enum_decl dec) - | LinkageSpecDecl(decl_info, decl_list, decl_context_info) -> + | LinkageSpecDecl (decl_info, decl_list, decl_context_info) -> Printing.log_out "ADDING: LinkageSpecDecl decl list\n"; IList.iter (translate_one_declaration tenv cg cfg namespace dec) decl_list - | NamespaceDecl(decl_info, name_info, decl_list, decl_context_info, _) -> + | NamespaceDecl (decl_info, name_info, decl_list, decl_context_info, _) -> let name = ns_suffix^name_info.Clang_ast_t.ni_name in IList.iter (translate_one_declaration tenv cg cfg (Some name) dec) decl_list - | EmptyDecl _ -> - Printing.log_out "Passing from EmptyDecl. Treated as skip\n"; | dec -> () (* Translates a file by translating the ast into a cfg. *) diff --git a/infer/src/clang/objcInterface_decl.ml b/infer/src/clang/objcInterface_decl.ml index bc7b5d8d5..5620ff8e1 100644 --- a/infer/src/clang/objcInterface_decl.ml +++ b/infer/src/clang/objcInterface_decl.ml @@ -79,6 +79,9 @@ let add_super_class_decl type_ptr_to_sil_type tenv ocdi = 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 +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 + 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 @@ -170,6 +173,8 @@ let interface_declaration type_ptr_to_sil_type tenv decl = let _ = add_class_implementation type_ptr_to_sil_type tenv ocidi in let _ = add_super_class_decl type_ptr_to_sil_type tenv ocidi in let _ = add_protocols_decl type_ptr_to_sil_type tenv ocidi.Clang_ast_t.otdi_protocols in + let known_categories = ocidi.Clang_ast_t.otdi_known_categories in + let _ = add_categories_decl type_ptr_to_sil_type tenv known_categories in typ | _ -> assert false