[liveness] Fix liveness analysis not to kill constructor targets

Summary:
In the previous live analysis, it handled class constructor targets as
dead before its calling.  For example,

```
// BEFORE live variables {src}
A::A(&tgt, &src)
// AFTER live variables {tgt, src}
```

It *may* be correct if we says the field values written in `tgt` is
dead.  However, we cannot says the location of `tgt` is dead.

Because of this bug,

```
A x = y;
```

was translated to

```
VARIABLE_DECLARED(x)
EXIT_SCOPE(x)

// x was dead here
A::A(&x, &y)
```

See that `EXIT_SCOPE(x)` is added right after its declaration, since
the liveness analysis said `x` was dead there.

Reviewed By: ezgicicek

Differential Revision: D26048344

fbshipit-source-id: a172994e2
master
Sungkeun Cho 4 years ago committed by Facebook GitHub Bot
parent f185b35292
commit 63545b1e64

@ -107,21 +107,9 @@ module TransferFunctions (LConfig : LivenessConfig) (CFG : ProcCfg.S) = struct
Domain.add (Var.of_pvar pvar) astate_acc ) Domain.add (Var.of_pvar pvar) astate_acc )
let add_live_actuals actuals call_exp live_acc = let add_live_actuals actuals live_acc =
let add_live_actuals_ exps acc =
List.fold exps ~f:(fun acc_ exp -> exp_add_live exp acc_) ~init:acc
in
let actuals = List.map actuals ~f:(fun (e, _) -> Exp.ignore_cast e) in let actuals = List.map actuals ~f:(fun (e, _) -> Exp.ignore_cast e) in
match Exp.ignore_cast call_exp with List.fold actuals ~f:(fun acc_ exp -> exp_add_live exp acc_) ~init:live_acc
| Exp.Const (Cfun (Procname.ObjC_Cpp _ as pname)) when Procname.is_constructor pname -> (
(* first actual passed to a C++ constructor is actually written, not read *)
match actuals with
| Exp.Lvar pvar :: exps ->
Domain.remove (Var.of_pvar pvar) live_acc |> add_live_actuals_ exps
| exps ->
add_live_actuals_ exps live_acc )
| _ ->
add_live_actuals_ actuals live_acc
let exec_instr astate proc_desc _ = function let exec_instr astate proc_desc _ = function
@ -156,8 +144,7 @@ module TransferFunctions (LConfig : LivenessConfig) (CFG : ProcCfg.S) = struct
else (actuals, astate) else (actuals, astate)
in in
Domain.remove (Var.of_id ret_id) astate Domain.remove (Var.of_id ret_id) astate
|> exp_add_live call_exp |> exp_add_live call_exp |> add_live_actuals actuals_to_read
|> add_live_actuals actuals_to_read call_exp
| Sil.Metadata _ -> | Sil.Metadata _ ->
astate astate

Loading…
Cancel
Save