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.

100 lines
3.9 KiB

(*
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
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 *)
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
let trans_unit_ctx = context.CContext.translation_unit_context in
let open Clang_ast_t in
match var_decl with
| 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
| 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
| _ ->
assert false
let sil_var_of_decl_ref context source_range decl_ref procname =
let name =
match decl_ref.Clang_ast_t.dr_name with Some name_info -> name_info | None -> assert false
in
match decl_ref.Clang_ast_t.dr_kind with
| `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
| _ ->
let pointer = decl_ref.Clang_ast_t.dr_decl_pointer in
if is_custom_var_pointer pointer then
Pvar.mk (Mangled.from_string name.Clang_ast_t.ni_name) procname
else
match CAst_utils.get_decl pointer with
| Some var_decl ->
sil_var_of_decl context var_decl procname
| None ->
(* FIXME(t21762295) *)
CFrontend_config.incorrect_assumption __POS__ source_range
"pointer '%d' for var decl not found. The var decl was: %a" pointer
(Pp.to_string ~f:Clang_ast_j.string_of_decl_ref)
decl_ref
let get_var_attribute decl_info =
let open Clang_ast_t in
let has_block_attribute =
List.exists decl_info.Clang_ast_t.di_attributes ~f:(fun attr ->
match attr with BlocksAttr _ -> true | _ -> false )
in
if has_block_attribute then [ProcAttributes.Modify_in_block] else []
let add_var_to_locals procdesc var_decl typ pvar =
let open Clang_ast_t in
match var_decl with
| VarDecl (decl_info, _, _, vdi) ->
if not vdi.Clang_ast_t.vdi_is_global then
let attributes = get_var_attribute decl_info in
let var_data : ProcAttributes.var_data = {name= Pvar.get_name pvar; typ; attributes} in
Procdesc.append_locals procdesc [var_data]
| _ ->
assert false
let sil_var_of_captured_var decl_ref context source_range procname =
match decl_ref with
| {Clang_ast_t.dr_qual_type= Some qual_type} ->
( sil_var_of_decl_ref context source_range decl_ref procname
, CType_decl.qual_type_to_sil_type context.CContext.tenv qual_type )
| _ ->
assert false
(* Returns a list of captured variables as sil variables. *)
let captured_vars_from_block_info context source_range cvl =
let procname = Procdesc.get_proc_name context.CContext.procdesc in
let sil_var_of_captured_var {Clang_ast_t.bcv_variable} vars_acc =
match bcv_variable with
| Some ({Clang_ast_t.dr_name= Some {Clang_ast_t.ni_name}} as decl_ref) ->
if String.equal ni_name CFrontend_config.self && not (CContext.is_objc_instance context)
then vars_acc
else sil_var_of_captured_var decl_ref context source_range procname :: vars_acc
| _ ->
assert false
in
List.fold_right ~f:sil_var_of_captured_var cvl ~init:[]