diff --git a/infer/src/clang/cFrontend_decl.ml b/infer/src/clang/cFrontend_decl.ml index 688cee1ed..89a24a9d1 100644 --- a/infer/src/clang/cFrontend_decl.ml +++ b/infer/src/clang/cFrontend_decl.ml @@ -427,7 +427,7 @@ module CFrontend_decl_funct (T : CModule_type.CTranslation) : CModule_type.CFron (* create the corresponding global variable to get the right pname for its initializer *) let global = - CGeneral_utils.mk_sil_global_var trans_unit_ctx decl_info named_decl_info vdi qt + CVar_decl.mk_sil_global_var trans_unit_ctx decl_info named_decl_info vdi qt in (* safe to Option.get because it's a global *) Option.value_exn (Pvar.get_initializer_pname global) diff --git a/infer/src/clang/cGeneral_utils.ml b/infer/src/clang/cGeneral_utils.ml index 0a75c5fca..59cb51a27 100644 --- a/infer/src/clang/cGeneral_utils.ml +++ b/infer/src/clang/cGeneral_utils.ml @@ -6,12 +6,9 @@ *) open! IStd -module F = Format (** 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 - let rec swap_elements_list l = match l with | el1 :: el2 :: rest -> @@ -115,65 +112,3 @@ let is_type_pod qt = xrdi_is_pod | _ -> true ) - - -let mk_sil_global_var {CFrontend_config.source_file} ?(mk_name = fun _ x -> x) decl_info - named_decl_info var_decl_info qt = - let name_string, simple_name = get_var_name_mangled decl_info named_decl_info var_decl_info in - let translation_unit = - match Clang_ast_t.(var_decl_info.vdi_is_extern, var_decl_info.vdi_init_expr) with - | true, None -> - None - | _, None when var_decl_info.Clang_ast_t.vdi_is_static_data_member -> - (* non-const static data member get extern scope unless they are defined out of line here (in which case vdi_init_expr will not be None) *) - None - | true, Some _ - (* "extern" variables with initialisation code are not extern at all, but compilers accept this *) - | false, _ -> - Some source_file - in - let is_constexpr = var_decl_info.Clang_ast_t.vdi_is_const_expr in - let is_ice = var_decl_info.Clang_ast_t.vdi_is_init_ice in - let is_pod = is_type_pod qt in - let is_static_global = - var_decl_info.Clang_ast_t.vdi_is_global - (* only top level declarations are really have file scope, static field members have a global scope *) - && (not var_decl_info.Clang_ast_t.vdi_is_static_data_member) - && var_decl_info.Clang_ast_t.vdi_is_static - in - let is_const = qt.Clang_ast_t.qt_is_const in - let desugared_type = CAst_utils.get_desugared_type qt.Clang_ast_t.qt_type_ptr in - let is_constant_array = - Option.exists desugared_type ~f:(function Clang_ast_t.ConstantArrayType _ -> true | _ -> false) - in - Pvar.mk_global ~is_constexpr ~is_ice ~is_pod - ~is_static_local:var_decl_info.Clang_ast_t.vdi_is_static_local ~is_static_global - ~is_constant_array ?translation_unit (mk_name name_string simple_name) ~is_const - - -let mk_sil_var trans_unit_ctx named_decl_info decl_info_qual_type_opt procname outer_procname = - match decl_info_qual_type_opt with - | Some (decl_info, qt, var_decl_info, should_be_mangled) -> - let name_string, simple_name = get_var_name_mangled decl_info 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 (F.asprintf "%a.%s" Procname.pp outer_procname name_string) ) - else None - in - mk_sil_global_var trans_unit_ctx ?mk_name decl_info 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 |> QualifiedCppName.to_qual_string - in - Pvar.mk (Mangled.from_string name_string) procname diff --git a/infer/src/clang/cGeneral_utils.mli b/infer/src/clang/cGeneral_utils.mli index 21c34cc15..16d574ded 100644 --- a/infer/src/clang/cGeneral_utils.mli +++ b/infer/src/clang/cGeneral_utils.mli @@ -9,8 +9,6 @@ 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 add_no_duplicates_fields : Struct.field -> Struct.field list -> Struct.field list val append_no_duplicates_fields : Struct.field list -> Struct.field list -> Struct.field list @@ -29,23 +27,6 @@ val get_var_name_mangled : -> 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.decl_info - -> 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 - val is_cpp_translation : CFrontend_config.translation_unit_context -> bool (** true if the current language is C++ or ObjC++ *) diff --git a/infer/src/clang/cVar_decl.ml b/infer/src/clang/cVar_decl.ml index 4a93e2677..ec4e0fc82 100644 --- a/infer/src/clang/cVar_decl.ml +++ b/infer/src/clang/cVar_decl.ml @@ -6,12 +6,78 @@ *) open! IStd +module F = Format -(** Process variable declarations by saving them as local or global variables. *) +let is_custom_var_pointer pointer = pointer <= 0 -(** Computes the local variables of a function or method to be added to the procdesc *) +let mk_sil_global_var {CFrontend_config.source_file} ?(mk_name = fun _ x -> x) decl_info + named_decl_info var_decl_info qt = + let name_string, simple_name = + CGeneral_utils.get_var_name_mangled decl_info named_decl_info var_decl_info + in + let translation_unit = + match Clang_ast_t.(var_decl_info.vdi_is_extern, var_decl_info.vdi_init_expr) with + | true, None -> + None + | _, None when var_decl_info.Clang_ast_t.vdi_is_static_data_member -> + (* non-const static data member get extern scope unless they are defined out of line here + (in which case vdi_init_expr will not be None) *) + None + | true, Some _ + (* "extern" variables with initialisation code are not extern at all, but compilers accept this + *) + | false, _ -> + Some source_file + in + let is_constexpr = var_decl_info.Clang_ast_t.vdi_is_const_expr in + let is_ice = var_decl_info.Clang_ast_t.vdi_is_init_ice in + let is_pod = CGeneral_utils.is_type_pod qt in + let is_static_global = + var_decl_info.Clang_ast_t.vdi_is_global + (* only top-level declarations really have file scope, static field members have a global scope + *) + && (not var_decl_info.Clang_ast_t.vdi_is_static_data_member) + && var_decl_info.Clang_ast_t.vdi_is_static + in + let is_const = qt.Clang_ast_t.qt_is_const in + let desugared_type = CAst_utils.get_desugared_type qt.Clang_ast_t.qt_type_ptr in + let is_constant_array = + Option.exists desugared_type ~f:(function Clang_ast_t.ConstantArrayType _ -> true | _ -> false) + in + Pvar.mk_global ~is_constexpr ~is_ice ~is_pod + ~is_static_local:var_decl_info.Clang_ast_t.vdi_is_static_local ~is_static_global + ~is_constant_array ~is_const ?translation_unit (mk_name name_string simple_name) + + +let mk_sil_var trans_unit_ctx named_decl_info decl_info_qual_type_opt procname outer_procname = + match decl_info_qual_type_opt with + | Some (decl_info, qt, var_decl_info, should_be_mangled) -> + let name_string, simple_name = + CGeneral_utils.get_var_name_mangled decl_info 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 (F.asprintf "%a.%s" Procname.pp outer_procname name_string) ) + else None + in + mk_sil_global_var trans_unit_ctx ?mk_name decl_info 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 |> QualifiedCppName.to_qual_string + in + Pvar.mk (Mangled.from_string name_string) procname -let is_custom_var_pointer pointer = pointer <= 0 let sil_var_of_decl context var_decl procname = let outer_procname = CContext.get_outer_procname context in @@ -21,10 +87,10 @@ let sil_var_of_decl context var_decl procname = | VarDecl (decl_info, name_info, qual_type, var_decl_info) -> let shoud_be_mangled = 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 - CGeneral_utils.mk_sil_var trans_unit_ctx name_info var_decl_details procname outer_procname + 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 - CGeneral_utils.mk_sil_var trans_unit_ctx name_info var_decl_details procname outer_procname + mk_sil_var trans_unit_ctx name_info var_decl_details procname outer_procname | _ -> assert false @@ -37,7 +103,7 @@ let sil_var_of_decl_ref context source_range decl_ref procname = | `ImplicitParam -> let outer_procname = CContext.get_outer_procname context in let trans_unit_ctx = context.CContext.translation_unit_context in - CGeneral_utils.mk_sil_var trans_unit_ctx name None procname outer_procname + mk_sil_var trans_unit_ctx name None procname outer_procname | _ -> ( let pointer = decl_ref.Clang_ast_t.dr_decl_pointer in if is_custom_var_pointer pointer then diff --git a/infer/src/clang/cVar_decl.mli b/infer/src/clang/cVar_decl.mli index ec49b25d3..1c65a6eb4 100644 --- a/infer/src/clang/cVar_decl.mli +++ b/infer/src/clang/cVar_decl.mli @@ -9,9 +9,8 @@ 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 *) - val sil_var_of_decl : CContext.t -> Clang_ast_t.decl -> Procname.t -> Pvar.t +(** Computes the local variables of a function or method to be added to the procdesc *) val sil_var_of_decl_ref : CContext.t -> Clang_ast_t.source_range -> Clang_ast_t.decl_ref -> Procname.t -> Pvar.t @@ -38,3 +37,12 @@ val mk_temp_sil_var_for_expr : val materialize_cpp_temporary : CContext.t -> Clang_ast_t.stmt_info -> Clang_ast_t.expr_info -> Pvar.t * Typ.t + +val mk_sil_global_var : + CFrontend_config.translation_unit_context + -> ?mk_name:(string -> Mangled.t -> Mangled.t) + -> Clang_ast_t.decl_info + -> Clang_ast_t.named_decl_info + -> Clang_ast_t.var_decl_info + -> Clang_ast_t.qual_type + -> Pvar.t