From e61b6fe7190885e1a6d51c73d2e1a035bc796d9b Mon Sep 17 00:00:00 2001 From: Andrzej Kotulski Date: Mon, 18 Jul 2016 07:06:05 -0700 Subject: [PATCH] Use pointers to decls instead of class names when creating a type Summary: Class names fragile, easy to break and they introduce another level of indirection. Since C++ translation doesn't need names, pass decl pointers everywhere. Doing otherwise will most likely result in assert false. Handling of class names in objc translation is more involving and it's left for now. Later, objc can use same mechanism as C++. Reviewed By: dulmarod Differential Revision: D3570176 fbshipit-source-id: b957aba --- infer/src/clang/cContext.ml | 20 ++++++++++++-------- infer/src/clang/cContext.mli | 5 +++-- infer/src/clang/cFrontend_decl.ml | 14 +++++--------- infer/src/clang/cMethod_trans.ml | 19 +++++++++++-------- infer/src/clang/cTrans.ml | 5 ++--- 5 files changed, 33 insertions(+), 30 deletions(-) diff --git a/infer/src/clang/cContext.ml b/infer/src/clang/cContext.ml index c618df8b4..6fef8499f 100644 --- a/infer/src/clang/cContext.ml +++ b/infer/src/clang/cContext.ml @@ -19,6 +19,7 @@ type curr_class = (*class name and name of (optional) super class , and a list of protocols *) | ContextCategory of string * string (* category name and corresponding class *) | ContextProtocol of string (* category name and corresponding class *) + | ContextClsDeclPtr of Clang_ast_t.pointer | ContextNoCls type str_node_map = (string, Cfg.Node.t) Hashtbl.t @@ -83,8 +84,14 @@ let get_curr_class_name curr_class = | ContextCls (name, _, _) -> name | ContextCategory (_, cls) -> cls | ContextProtocol name -> name + | ContextClsDeclPtr _ -> assert false | ContextNoCls -> assert false +let get_curr_class_decl_ptr curr_class = + match curr_class with + | ContextClsDeclPtr ptr -> ptr + | _ -> assert false + let curr_class_to_string curr_class = match curr_class with | ContextCls (name, superclass, protocols) -> @@ -92,6 +99,7 @@ let curr_class_to_string curr_class = ", protocols: " ^ (IList.to_string (fun x -> x) protocols)) | ContextCategory (name, cls) -> ("category " ^ name ^ " of class " ^ cls) | ContextProtocol name -> ("protocol " ^ name) + | ContextClsDeclPtr ptr -> ("decl_ptr: " ^ string_of_int ptr) | ContextNoCls -> "no class" let curr_class_compare curr_class1 curr_class2 = @@ -108,18 +116,15 @@ let curr_class_compare curr_class1 curr_class2 = String.compare name1 name2 | ContextProtocol _, _ -> -1 | _, ContextProtocol _ -> 1 + | ContextClsDeclPtr ptr1, ContextClsDeclPtr ptr2 -> + ptr1 - ptr2 + | ContextClsDeclPtr _, _ -> -1 + | _, ContextClsDeclPtr _ -> 1 | ContextNoCls, ContextNoCls -> 0 let curr_class_equal curr_class1 curr_class2 = curr_class_compare curr_class1 curr_class2 == 0 -let curr_class_hash curr_class = - match curr_class with - | ContextCls (name, _, _) -> Hashtbl.hash name - | ContextCategory (name, cls) -> Hashtbl.hash (name, cls) - | ContextProtocol name -> Hashtbl.hash name - | ContextNoCls -> Hashtbl.hash "no class" - let create_curr_class tenv class_name ck = let class_tn_name = Typename.TN_csu (Csu.Class ck, (Mangled.from_string class_name)) in match Tenv.lookup tenv class_tn_name with @@ -158,4 +163,3 @@ let rec get_outer_procname context = match context.outer_context with | Some outer_context -> get_outer_procname outer_context | None -> Cfg.Procdesc.get_proc_name context.procdesc - diff --git a/infer/src/clang/cContext.mli b/infer/src/clang/cContext.mli index ad5f221a2..0ea896e75 100644 --- a/infer/src/clang/cContext.mli +++ b/infer/src/clang/cContext.mli @@ -17,6 +17,7 @@ type curr_class = (*class name and name of (optional) super class , and a list of protocols *) | ContextCategory of string * string (* category name and corresponding class *) | ContextProtocol of string (* category name and corresponding class *) + | ContextClsDeclPtr of Clang_ast_t.pointer | ContextNoCls type str_node_map = (string, Cfg.Node.t) Hashtbl.t @@ -46,14 +47,14 @@ val get_curr_class : t -> curr_class val get_curr_class_name : curr_class -> string +val get_curr_class_decl_ptr : curr_class -> Clang_ast_t.pointer + val curr_class_to_string : curr_class -> string val curr_class_compare : curr_class -> curr_class -> int val curr_class_equal : curr_class -> curr_class -> bool -val curr_class_hash : curr_class -> int - val is_objc_method : t -> bool val get_tenv : t -> Tenv.t diff --git a/infer/src/clang/cFrontend_decl.ml b/infer/src/clang/cFrontend_decl.ml index 137c7413a..7e114933d 100644 --- a/infer/src/clang/cFrontend_decl.ml +++ b/infer/src/clang/cFrontend_decl.ml @@ -213,16 +213,12 @@ struct | CXXConversionDecl (decl_info, _, _, _, _) | CXXDestructorDecl (decl_info, _, _, _, _) -> (* di_parent_pointer has pointer to lexical context such as class.*) - let class_decl = match decl_info.Clang_ast_t.di_parent_pointer with - | Some ptr -> - Ast_utils.get_decl ptr - | None -> - assert false in + let parent_ptr = Option.get decl_info.Clang_ast_t.di_parent_pointer in + let class_decl = Ast_utils.get_decl parent_ptr in (match class_decl with - | Some (CXXRecordDecl _ as d) - | Some (ClassTemplateSpecializationDecl _ as d) -> - let class_name = CTypes_decl.get_record_name d in - let curr_class = CContext.ContextCls(class_name, None, []) in + | Some (CXXRecordDecl _) + | Some (ClassTemplateSpecializationDecl _) -> + let curr_class = CContext.ContextClsDeclPtr parent_ptr in if Config.cxx_experimental then process_methods tenv cg cfg curr_class [dec] | Some dec -> diff --git a/infer/src/clang/cMethod_trans.ml b/infer/src/clang/cMethod_trans.ml index b9ffb1180..07b1d6131 100644 --- a/infer/src/clang/cMethod_trans.ml +++ b/infer/src/clang/cMethod_trans.ml @@ -30,8 +30,8 @@ type method_call_type = type function_method_decl_info = | Func_decl_info of Clang_ast_t.function_decl_info * Clang_ast_t.type_ptr * Config.clang_lang - | Cpp_Meth_decl_info of Clang_ast_t.function_decl_info * Clang_ast_t.cxx_method_decl_info * string * Clang_ast_t.type_ptr - | ObjC_Meth_decl_info of Clang_ast_t.obj_c_method_decl_info * string + | Cpp_Meth_decl_info of Clang_ast_t.function_decl_info * Clang_ast_t.cxx_method_decl_info * Clang_ast_t.pointer * Clang_ast_t.type_ptr + | ObjC_Meth_decl_info of Clang_ast_t.obj_c_method_decl_info * Clang_ast_t.pointer | Block_decl_info of Clang_ast_t.block_decl_info * Clang_ast_t.type_ptr * CContext.t let is_instance_method function_method_decl_info = @@ -52,11 +52,11 @@ let get_original_return_type function_method_decl_info = let get_class_param function_method_decl_info = if (is_instance_method function_method_decl_info) then match function_method_decl_info with - | Cpp_Meth_decl_info (_, _, class_name, _) -> - let class_type = Ast_expressions.create_class_type (class_name, `CPP) in + | Cpp_Meth_decl_info (_, _, class_decl_ptr, _) -> + let class_type = `DeclPtr class_decl_ptr in [(Mangled.from_string CFrontend_config.this, class_type)] - | ObjC_Meth_decl_info (_, class_name) -> - let class_type = Ast_expressions.create_class_type (class_name, `OBJC) in + | ObjC_Meth_decl_info (_, class_decl_ptr) -> + let class_type = `DeclPtr class_decl_ptr in [(Mangled.from_string CFrontend_config.self, class_type)] | _ -> [] else [] @@ -181,7 +181,8 @@ let method_signature_of_decl tenv meth_decl block_data_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 procname = General_utils.mk_procname_from_cpp_method class_name method_name tp in - let method_decl = Cpp_Meth_decl_info (fdi, mdi, class_name, tp) in + let parent_ptr = Option.get decl_info.di_parent_pointer in + let method_decl = Cpp_Meth_decl_info (fdi, mdi, parent_ptr, tp) in let parent_pointer = decl_info.Clang_ast_t.di_parent_pointer in let ms = build_method_signature tenv decl_info procname method_decl parent_pointer None in let non_null_instrs = get_assume_not_null_calls fdi.Clang_ast_t.fdi_parameters in @@ -190,7 +191,8 @@ let method_signature_of_decl tenv meth_decl block_data_opt = | ObjCMethodDecl (decl_info, name_info, mdi), _ -> let class_name = Ast_utils.get_class_name_from_member name_info in let procname = get_objc_method_name name_info mdi class_name in - let method_decl = ObjC_Meth_decl_info (mdi, class_name) in + let parent_ptr = Option.get 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 let pointer_to_property_opt = match mdi.Clang_ast_t.omdi_property_decl with @@ -252,6 +254,7 @@ let get_superclass_curr_class_objc context = | CContext.ContextCategory (_, cls) -> retrive_super cls None | CContext.ContextNoCls + | CContext.ContextClsDeclPtr _ | CContext.ContextProtocol _ -> assert false (* Gets the class name from a method signature found by clang, if search is successful *) diff --git a/infer/src/clang/cTrans.ml b/infer/src/clang/cTrans.ml index 6a3254509..a46a32b47 100644 --- a/infer/src/clang/cTrans.ml +++ b/infer/src/clang/cTrans.ml @@ -2610,7 +2610,7 @@ struct (* an input parameter. *) and cxx_constructor_init_trans ctor_init trans_state = (*let tenv = trans_state.context.CContext.tenv in*) - let class_name = CContext.get_curr_class_name trans_state.context.CContext.curr_class in + let class_ptr = CContext.get_curr_class_decl_ptr trans_state.context.CContext.curr_class in let source_range = ctor_init.Clang_ast_t.xci_source_range in let sil_loc = CLocation.get_sil_location_from_range source_range true in (* its pointer will be used in PriorityNode *) @@ -2619,8 +2619,7 @@ struct let child_stmt_info = { (Ast_expressions.dummy_stmt_info ()) with Clang_ast_t.si_source_range = source_range } in let trans_state' = PriorityNode.try_claim_priority_node trans_state this_stmt_info in - let class_type_ptr = Ast_expressions.create_pointer_type - (Ast_expressions.create_class_type (class_name, `CPP)) in + let class_type_ptr = Ast_expressions.create_pointer_type (`DeclPtr class_ptr) in let this_res_trans = this_expr_trans trans_state' sil_loc class_type_ptr in let var_res_trans = match ctor_init.Clang_ast_t.xci_subject with | `Delegating _ | `BaseClass _ ->