Summary: We may want to use these traces more generally, so put them into their own module. Reviewed By: mbouaziz Differential Revision: D10084404 fbshipit-source-id: 8f87c17f4master
parent
e11ec33289
commit
9b02c497f8
@ -0,0 +1,77 @@
|
||||
(*
|
||||
* Copyright (c) 2018-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
|
||||
module F = Format
|
||||
module MF = MarkupFormatter
|
||||
|
||||
module type FiniteSet = sig
|
||||
include PrettyPrintable.PPSet
|
||||
|
||||
include AbstractDomain.WithBottom with type astate = t
|
||||
|
||||
val with_callsite : astate -> CallSite.t -> astate
|
||||
end
|
||||
|
||||
module type TraceElem = sig
|
||||
type elem_t
|
||||
|
||||
type t = private {elem: elem_t; loc: Location.t; trace: CallSite.t list}
|
||||
|
||||
include PrettyPrintable.PrintableOrderedType with type t := t
|
||||
|
||||
val make : elem_t -> Location.t -> t
|
||||
|
||||
val get_loc : t -> Location.t
|
||||
|
||||
val make_loc_trace : ?nesting:int -> t -> Errlog.loc_trace
|
||||
|
||||
val with_callsite : t -> CallSite.t -> t
|
||||
|
||||
module FiniteSet : FiniteSet with type elt = t
|
||||
end
|
||||
|
||||
module MakeTraceElem (Elem : PrettyPrintable.PrintableOrderedType) :
|
||||
TraceElem with type elem_t = Elem.t = struct
|
||||
type elem_t = Elem.t
|
||||
|
||||
module T = struct
|
||||
type t = {elem: Elem.t; loc: Location.t; trace: CallSite.t list [@compare.ignore]}
|
||||
[@@deriving compare]
|
||||
|
||||
let pp fmt {elem; loc} = F.fprintf fmt "%a at %a" Elem.pp elem Location.pp loc
|
||||
end
|
||||
|
||||
include T
|
||||
|
||||
let make elem loc = {elem; loc; trace= []}
|
||||
|
||||
let get_loc {loc; trace} = match trace with [] -> loc | hd :: _ -> CallSite.loc hd
|
||||
|
||||
let make_loc_trace ?(nesting = 0) e =
|
||||
let call_trace, nesting =
|
||||
List.fold e.trace ~init:([], nesting) ~f:(fun (tr, ns) callsite ->
|
||||
let elem_descr =
|
||||
F.asprintf "Method call: %a"
|
||||
(MF.wrap_monospaced Typ.Procname.pp)
|
||||
(CallSite.pname callsite)
|
||||
in
|
||||
let elem = Errlog.make_trace_element ns (CallSite.loc callsite) elem_descr [] in
|
||||
(elem :: tr, ns + 1) )
|
||||
in
|
||||
let endpoint_descr = F.asprintf "%a" Elem.pp e.elem in
|
||||
let endpoint = Errlog.make_trace_element nesting e.loc endpoint_descr [] in
|
||||
List.rev (endpoint :: call_trace)
|
||||
|
||||
|
||||
let with_callsite elem callsite = {elem with trace= callsite :: elem.trace}
|
||||
|
||||
module FiniteSet = struct
|
||||
include AbstractDomain.FiniteSet (T)
|
||||
|
||||
let with_callsite astate callsite = map (fun e -> with_callsite e callsite) astate
|
||||
end
|
||||
end
|
@ -0,0 +1,47 @@
|
||||
(*
|
||||
* Copyright (c) 2018-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
|
||||
|
||||
(** A powerset domain of traces, with bottom = empty and join = union *)
|
||||
module type FiniteSet = sig
|
||||
include PrettyPrintable.PPSet
|
||||
|
||||
include AbstractDomain.WithBottom with type astate = t
|
||||
|
||||
val with_callsite : astate -> CallSite.t -> astate
|
||||
(** Push given callsite onto all traces in set. Cf [TraceElem.with_callsite] *)
|
||||
end
|
||||
|
||||
module type TraceElem = sig
|
||||
type elem_t
|
||||
|
||||
(** An [elem] which occured at [loc], after the chain of steps (usually calls) in [trace].
|
||||
The [compare] function ignores traces, meaning any two traces leading to the same [elem] and
|
||||
[loc] are equal. This has consequences on the powerset domain. *)
|
||||
type t = private {elem: elem_t; loc: Location.t; trace: CallSite.t list}
|
||||
|
||||
include PrettyPrintable.PrintableOrderedType with type t := t
|
||||
|
||||
val make : elem_t -> Location.t -> t
|
||||
|
||||
val get_loc : t -> Location.t
|
||||
(** Starting location of the trace: this is either [loc] if [trace==[]], or the head of [trace]. *)
|
||||
|
||||
val make_loc_trace : ?nesting:int -> t -> Errlog.loc_trace
|
||||
|
||||
val with_callsite : t -> CallSite.t -> t
|
||||
(** Push given callsite onto trace, extending the call chain by one. *)
|
||||
|
||||
(** A powerset of traces, where there is at most one trace for each dinstinct pair of [elem] and
|
||||
[loc]. The traces in the set have priority over those [add]ed. [join] is non-deterministic
|
||||
as to which representative is kept (due to the implementation of [Set.union]). *)
|
||||
module FiniteSet : FiniteSet with type elt = t
|
||||
end
|
||||
|
||||
module MakeTraceElem (Elem : PrettyPrintable.PrintableOrderedType) :
|
||||
TraceElem with type elem_t = Elem.t
|
Loading…
Reference in new issue