You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

111 lines
4.6 KiB

(*
* Copyright (c) 2013 - present Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*)
(** 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 *)
open Utils
open CFrontend_utils
module L = Logging
let is_custom_var_pointer pointer =
Utils.string_is_prefix CFrontend_config.pointer_prefix pointer
let is_captured procdesc vname =
IList.exists
(fun (name, _) -> (Mangled.to_string name) = vname)
(Cfg.Procdesc.get_captured procdesc)
let sil_var_of_decl context var_decl procname =
let outer_procname = CContext.get_outer_procname context in
let procdesc = context.CContext.procdesc in
let open Clang_ast_t in
match var_decl with
| VarDecl (decl_info, name_info, type_ptr, var_decl_info) ->
let shoud_be_mangled =
not (is_custom_var_pointer decl_info.Clang_ast_t.di_pointer) &&
not (is_captured procdesc name_info.Clang_ast_t.ni_name) in
let var_decl_details = Some (decl_info, type_ptr, var_decl_info, shoud_be_mangled) in
General_utils.mk_sil_var name_info var_decl_details procname outer_procname
| ParmVarDecl (decl_info, name_info, type_ptr, var_decl_info) ->
let var_decl_details = Some (decl_info, type_ptr, var_decl_info, false) in
General_utils.mk_sil_var name_info var_decl_details procname outer_procname
| _ -> assert false
let sil_var_of_decl_ref context decl_ref procname =
let name =
match decl_ref.Clang_ast_t.dr_name with
| Some name_info -> name_info
| None -> assert false in
let pointer = decl_ref.Clang_ast_t.dr_decl_pointer in
match decl_ref.Clang_ast_t.dr_kind with
| `ImplicitParam ->
let outer_procname = CContext.get_outer_procname context in
General_utils.mk_sil_var name None procname outer_procname
| _ ->
if is_custom_var_pointer pointer then
Sil.mk_pvar (Mangled.from_string name.Clang_ast_t.ni_name) procname
else match Ast_utils.get_decl decl_ref.Clang_ast_t.dr_decl_pointer with
| Some var_decl -> sil_var_of_decl context var_decl procname
| None -> assert false
let add_var_to_locals procdesc var_decl sil_typ pvar =
let open Clang_ast_t in
match var_decl with
| VarDecl (di, var_name, type_ptr, vdi) ->
let is_block_var =
match var_name.Clang_ast_t.ni_qual_name with
| [name; qual_name] -> qual_name = CFrontend_config.block
| _ -> false in
if not vdi.Clang_ast_t.vdi_is_global && not is_block_var then
Cfg.Procdesc.append_locals procdesc [(Sil.pvar_get_name pvar, sil_typ)]
| _ -> assert false
let rec compute_autorelease_pool_vars context stmts =
let procname = Cfg.Procdesc.get_proc_name context.CContext.procdesc in
match stmts with
| [] -> []
| Clang_ast_t.DeclRefExpr (si, sl, ei, drei):: stmts' ->
(let res = compute_autorelease_pool_vars context stmts' in
match drei.Clang_ast_t.drti_decl_ref with
| Some decl_ref ->
(match decl_ref.Clang_ast_t.dr_type_ptr with
| Some type_ptr when decl_ref.Clang_ast_t.dr_kind = `Var ->
let typ = CTypes_decl.type_ptr_to_sil_type context.CContext.tenv type_ptr in
let pvar = sil_var_of_decl_ref context decl_ref procname in
if Sil.pvar_is_local pvar then
General_utils.append_no_duplicated_pvars [(Sil.Lvar pvar, typ)] res
else res
| _ -> res)
| _ -> res)
| s :: stmts' ->
let sl = snd (Clang_ast_proj.get_stmt_tuple s) in
compute_autorelease_pool_vars context (sl @ stmts')
(* Returns a list of captured variables as sil variables. *)
let captured_vars_from_block_info context cvl =
let procname = Cfg.Procdesc.get_proc_name context.CContext.procdesc in
let sil_var_of_captured_var cv vars =
match cv.Clang_ast_t.bcv_variable with
| Some dr ->
(match dr.Clang_ast_t.dr_name, dr.Clang_ast_t.dr_type_ptr with
| Some name_info, Some type_ptr ->
let n = name_info.Clang_ast_t.ni_name in
if n = CFrontend_config.self && not (CContext.is_objc_instance context) then
vars
else
let pvar = sil_var_of_decl_ref context dr procname in
let typ = CTypes_decl.type_ptr_to_sil_type context.CContext.tenv type_ptr in
(pvar, typ) :: vars
| _ -> assert false)
| _ -> assert false in
IList.fold_right sil_var_of_captured_var cvl []