|
|
|
(*
|
|
|
|
* Copyright (c) 2009 - 2013 Monoidics ltd.
|
|
|
|
* 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.
|
|
|
|
*)
|
|
|
|
|
|
|
|
(** Program variables. *)
|
|
|
|
|
|
|
|
open! IStd
|
|
|
|
module F = Format
|
|
|
|
|
|
|
|
type translation_unit = TUFile of SourceFile.t | TUExtern [@@deriving compare]
|
|
|
|
|
|
|
|
(** Type for program variables. There are 4 kinds of variables:
|
|
|
|
1) local variables, used for local variables and formal parameters
|
|
|
|
2) callee program variables, used to handle recursion ([x | callee] is distinguished from [x])
|
|
|
|
3) global variables
|
|
|
|
4) seed variables, used to store the initial value of formal parameters
|
|
|
|
*)
|
|
|
|
type t [@@deriving compare]
|
|
|
|
|
|
|
|
val compare_modulo_this : t -> t -> int
|
|
|
|
(** Comparison considering all pvars named 'this' to be equal *)
|
|
|
|
|
|
|
|
val equal : t -> t -> bool
|
|
|
|
(** Equality for pvar's *)
|
|
|
|
|
|
|
|
val d : t -> unit
|
|
|
|
(** Dump a program variable. *)
|
|
|
|
|
|
|
|
val d_list : t list -> unit
|
|
|
|
(** Dump a list of program variables. *)
|
|
|
|
|
|
|
|
val get_name : t -> Mangled.t
|
|
|
|
(** Get the name component of a program variable. *)
|
|
|
|
|
|
|
|
val get_ret_pvar : Typ.Procname.t -> t
|
|
|
|
(** [get_ret_pvar proc_name] retuns the return pvar associated with the procedure name *)
|
|
|
|
|
|
|
|
val get_simplified_name : t -> string
|
|
|
|
(** Get a simplified version of the name component of a program variable. *)
|
|
|
|
|
|
|
|
val is_abduced : t -> bool
|
|
|
|
(** Check if the pvar is an abduced return var or param passed by ref *)
|
|
|
|
|
|
|
|
val is_callee : t -> bool
|
|
|
|
(** Check if the pvar is a callee var *)
|
|
|
|
|
|
|
|
val is_global : t -> bool
|
|
|
|
(** Check if the pvar is a global var or a static local var *)
|
|
|
|
|
|
|
|
val is_static_local : t -> bool
|
|
|
|
(** Check if the pvar is a static variable declared inside a function *)
|
|
|
|
|
|
|
|
val is_local : t -> bool
|
|
|
|
(** Check if the pvar is a (non-static) local var *)
|
|
|
|
|
|
|
|
val is_seed : t -> bool
|
|
|
|
(** Check if the pvar is a seed var *)
|
|
|
|
|
|
|
|
val is_return : t -> bool
|
|
|
|
(** Check if the pvar is a return var *)
|
|
|
|
|
|
|
|
val is_this : t -> bool
|
|
|
|
(** Check if a pvar is the special "this" var *)
|
|
|
|
|
|
|
|
val is_self : t -> bool
|
|
|
|
(** Check if a pvar is the special "self" var *)
|
|
|
|
|
|
|
|
val is_frontend_tmp : t -> bool
|
|
|
|
(** return true if [pvar] is a temporary variable generated by the frontend *)
|
|
|
|
|
|
|
|
val is_ssa_frontend_tmp : t -> bool
|
|
|
|
(** return true if [pvar] is a temporary variable generated by the frontend and is only assigned
|
|
|
|
once on a non-looping control-flow path *)
|
|
|
|
|
|
|
|
val mk : Mangled.t -> Typ.Procname.t -> t
|
|
|
|
(** [mk name proc_name suffix] creates a program var with the given function name and suffix *)
|
|
|
|
|
|
|
|
val mk_abduced_ref_param : Typ.Procname.t -> int -> Location.t -> t
|
|
|
|
(** create an abduced variable for a parameter passed by reference *)
|
|
|
|
|
|
|
|
val mk_abduced_ret : Typ.Procname.t -> Location.t -> t
|
|
|
|
(** create an abduced return variable for a call to [proc_name] at [loc] *)
|
|
|
|
|
|
|
|
val mk_callee : Mangled.t -> Typ.Procname.t -> t
|
|
|
|
(** [mk_callee name proc_name] creates a program var
|
|
|
|
for a callee function with the given function name *)
|
|
|
|
|
|
|
|
val mk_global :
|
|
|
|
?is_constexpr:bool -> ?is_pod:bool -> ?is_static_local:bool -> Mangled.t -> translation_unit -> t
|
|
|
|
(** create a global variable with the given name *)
|
|
|
|
|
|
|
|
val mk_tmp : string -> Typ.Procname.t -> t
|
|
|
|
(** create a fresh temporary variable local to procedure [pname]. for use in the frontends only! *)
|
|
|
|
|
|
|
|
val pp : Pp.env -> F.formatter -> t -> unit
|
|
|
|
(** Pretty print a program variable. *)
|
|
|
|
|
|
|
|
val pp_list : Pp.env -> F.formatter -> t list -> unit
|
|
|
|
(** Pretty print a list of program variables. *)
|
|
|
|
|
|
|
|
val pp_value : Pp.env -> F.formatter -> t -> unit
|
|
|
|
(** Pretty print a pvar which denotes a value, not an address *)
|
|
|
|
|
|
|
|
val pp_translation_unit : F.formatter -> translation_unit -> unit
|
|
|
|
|
|
|
|
val to_callee : Typ.Procname.t -> t -> t
|
|
|
|
(** Turn an ordinary program variable into a callee program variable *)
|
|
|
|
|
|
|
|
val to_seed : t -> t
|
|
|
|
(** Turn a pvar into a seed pvar (which stores the initial value of a stack var) *)
|
|
|
|
|
|
|
|
val to_string : t -> string
|
|
|
|
(** Convert a pvar to string. *)
|
|
|
|
|
|
|
|
val get_translation_unit : t -> translation_unit
|
|
|
|
(** Get the translation unit corresponding to a global. Raises Invalid_arg if not a global. *)
|
|
|
|
|
|
|
|
val is_compile_constant : t -> bool
|
|
|
|
(** Is the variable's value a compile-time constant? Always (potentially incorrectly) returns
|
|
|
|
[false] for non-globals. *)
|
|
|
|
|
|
|
|
val is_pod : t -> bool
|
|
|
|
(** Is the variable's type a "Plain Old Data" type (C++)? Always (potentially incorrectly) returns
|
|
|
|
[true] for non-globals. *)
|
|
|
|
|
|
|
|
val get_initializer_pname : t -> Typ.Procname.t option
|
|
|
|
(** Get the procname of the initializer function for the given global variable *)
|
[clang] Executing methods with blocks as parameters by instantiating the parameters with current blocks
Summary:
This diff adds a new way of executing blocks when they are passed as parameters to a method. So far we just skipped the block in this case.
Now we can execute it. Let's demonstrate with an example. Say we have
//foo has a block parameter that it executes in its body
foo (Block block) { block();}
// bar calls foo with a concrete block
bar() {
foo (^(){
self->x = 10;
});
};
Now, when we call the method foo with a concrete block, we create a copy of foo instantiated with the concrete block, which in itself is translated as a method with a made-up name.
The copy of foo will get a name that is foo extended with the name of the block parameter, the call to the block parameter will be replaced to a call to the concrete block, and the captured variables
of the concrete block (self in this case), will be added to the formals of the specialized method foo_block_name.
This is turned on at the moment for ObjC methods with ObjC blocks as parameters, and called with concrete blocks. Later on we can extend it to other types of methods, and to C++ lambdas, that are handled similarly to blocks.
Another extension is to check when the block has been called with nil instead of an actual block, and raise an error in that case.
After this diff, we can also model various methods and functions from the standard library that take blocks as parameters, and remove frontend hacks to deal with that.
Reviewed By: ddino
Differential Revision: D6260792
fbshipit-source-id: 0b6f22e
7 years ago
|
|
|
|
|
|
|
val get_name_of_local_with_procname : t -> Mangled.t
|
|
|
|
(** [get_name_of_local_with_procname var] Return a name that is composed of the name of
|
|
|
|
var and the name of the procname in case of locals *)
|