[clang] Pass template instantiation info to procnames in clang

Summary:
Read template arguments from the AST and if argument is a type, translate it into Sil type. Then, save this information into procname.

There is one ugly change - linters now may populate tenv (it's not saved anytwhere though)

Reviewed By: dulmarod

Differential Revision: D4635508

fbshipit-source-id: e806ca7
master
Andrzej Kotulski 8 years ago committed by Facebook Github Bot
parent 925d73efce
commit 06ac72c311

@ -29,7 +29,16 @@ let rec get_mangled_method_name function_decl_info method_decl_info =
get_mangled_method_name fdi mdi
| _ -> assert false)
let mk_c_function translation_unit_context name function_decl_info_opt =
let get_template_info tenv (fdi : Clang_ast_t.function_decl_info) : Typ.template_spec_info =
match fdi.fdi_template_specialization with
| Some spec_info -> Typ.Template (
"",
List.map spec_info.tsi_specialization_args ~f:(function
| `Type type_ptr -> Some (CType_decl.type_ptr_to_sil_type tenv type_ptr)
| _ -> None))
| None -> Typ.NoTemplate
let mk_c_function translation_unit_context ?tenv name function_decl_info_opt =
let file =
match function_decl_info_opt with
| Some (decl_info, function_decl_info) ->
@ -45,20 +54,34 @@ let mk_c_function translation_unit_context name function_decl_info_opt =
let mangled_name = match mangled_opt with
| Some m when CGeneral_utils.is_cpp_translation translation_unit_context -> m
| _ -> "" in
let template_info = match function_decl_info_opt, tenv with
| Some (_, function_decl_info), Some t -> get_template_info t function_decl_info
| _ -> Typ.NoTemplate in
let mangled = (Utils.string_crc_hex32 file) ^ mangled_name in
if String.is_empty file && String.is_empty mangled_name then
Typ.Procname.from_string_c_fun name
else
Typ.Procname.C (Typ.Procname.c name mangled Typ.NoTemplate)
Typ.Procname.C (Typ.Procname.c name mangled template_info)
let mk_cpp_method class_name method_name ?meth_decl mangled =
let mk_cpp_method ?tenv class_name method_name ?meth_decl mangled =
let open Clang_ast_t in
let method_kind = match meth_decl with
| Some (Clang_ast_t.CXXConstructorDecl (_, _, _, _, {xmdi_is_constexpr})) ->
Typ.Procname.CPPConstructor (mangled, xmdi_is_constexpr)
| _ ->
Typ.Procname.CPPMethod mangled in
let template_info = match meth_decl with
| Some (CXXMethodDecl (_, _, _, fdi, _))
| Some (CXXConstructorDecl (_, _, _, fdi, _))
| Some (CXXConversionDecl (_, _, _, fdi, _))
| Some (CXXDestructorDecl (_, _, _, fdi, _)) -> (
match tenv with
| Some t -> get_template_info t fdi
| None -> Typ.NoTemplate
)
| _ -> Typ.NoTemplate in
Typ.Procname.ObjC_Cpp
(Typ.Procname.objc_cpp class_name method_name method_kind Typ.NoTemplate)
(Typ.Procname.objc_cpp class_name method_name method_kind template_info)
let mk_objc_method class_typename method_name method_kind =
Typ.Procname.ObjC_Cpp
@ -96,24 +119,23 @@ let get_class_typename method_decl_info =
| None -> assert false
module NoAstDecl = struct
let c_function_of_string translation_unit_context name =
mk_c_function translation_unit_context name None
let c_function_of_string translation_unit_context tenv name =
mk_c_function translation_unit_context ~tenv name None
let cpp_method_of_string class_name method_name =
mk_cpp_method class_name method_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 translation_unit_context meth_decl =
let from_decl translation_unit_context ?tenv 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_c_function translation_unit_context name function_info
mk_c_function translation_unit_context ?tenv name function_info
| CXXMethodDecl (decl_info, name_info, _, fdi, mdi)
| CXXConstructorDecl (decl_info, name_info, _, fdi, mdi)
| CXXConversionDecl (decl_info, name_info, _, fdi, mdi)
@ -121,7 +143,7 @@ let from_decl translation_unit_context meth_decl =
let mangled = get_mangled_method_name fdi mdi in
let method_name = CAst_utils.get_unqualified_name name_info in
let class_typename = get_class_typename decl_info in
mk_cpp_method class_typename method_name ~meth_decl mangled
mk_cpp_method ?tenv class_typename method_name ~meth_decl mangled
| ObjCMethodDecl (decl_info, name_info, mdi) ->
let class_typename = get_class_typename decl_info in
let method_name = name_info.Clang_ast_t.ni_name in

@ -11,14 +11,15 @@ open! IStd
(** Given decl, return its procname. This function should be used for all procedures
present in original AST *)
val from_decl : CFrontend_config.translation_unit_context -> Clang_ast_t.decl -> Typ.Procname.t
val from_decl :
CFrontend_config.translation_unit_context -> ?tenv:Tenv.t -> Clang_ast_t.decl -> Typ.Procname.t
(** WARNING: functions from this module should not be used if full decl is available in AST *)
module NoAstDecl : sig
val c_function_of_string : CFrontend_config.translation_unit_context -> string -> Typ.Procname.t
val c_function_of_string :
CFrontend_config.translation_unit_context -> Tenv.t -> string -> Typ.Procname.t
val cpp_method_of_string : Typename.t -> string -> Typ.Procname.t
val cpp_method_of_string : Tenv.t -> Typename.t -> string -> Typ.Procname.t
val objc_method_of_string_kind : Typename.t -> string -> Typ.Procname.objc_cpp_method_kind ->
Typ.Procname.t

@ -162,7 +162,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 = CProcname.from_decl trans_unit_ctx meth_decl in
let procname = CProcname.from_decl trans_unit_ctx ~tenv 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 +170,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 = CProcname.from_decl trans_unit_ctx meth_decl in
let procname = CProcname.from_decl trans_unit_ctx ~tenv 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 +180,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 = CProcname.from_decl trans_unit_ctx meth_decl in
let procname = CProcname.from_decl trans_unit_ctx ~tenv 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
@ -478,9 +478,10 @@ let create_procdesc_with_pointer context pointer class_name_opt name =
let callee_name =
match class_name_opt with
| Some class_name ->
CProcname.NoAstDecl.cpp_method_of_string class_name name
CProcname.NoAstDecl.cpp_method_of_string context.tenv class_name name
| None ->
CProcname.NoAstDecl.c_function_of_string context.translation_unit_context name in
CProcname.NoAstDecl.c_function_of_string
context.translation_unit_context context.tenv name in
create_external_procdesc context.cfg callee_name false None;
callee_name

Loading…
Cancel
Save