[dead stores] don't warn on likely-harmless dead stores to default values

Reviewed By: jberdine

Differential Revision: D6223991

fbshipit-source-id: ff53e8b
master
Sam Blackshear 7 years ago committed by Facebook Github Bot
parent 0a1971a08d
commit ad522a8b19

@ -73,12 +73,23 @@ let checker {Callbacks.tenv; summary; proc_desc} : Specs.summary =
let invariant_map = let invariant_map =
Analyzer.exec_cfg cfg (ProcData.make_default proc_desc tenv) ~initial:Domain.empty ~debug:true Analyzer.exec_cfg cfg (ProcData.make_default proc_desc tenv) ~initial:Domain.empty ~debug:true
in in
(* we don't want to report in harmless cases like int i = 0; if (...) { i = ... } else { i = ... }
that create an intentional dead store as an attempt to imitate default value semantics.
use dead stores to a "sentinel" value as a heuristic for ignoring this case *)
let is_sentinel_exp = function
| Exp.Const Cint i ->
IntLit.iszero i || IntLit.isnull i
| Exp.Const Cfloat 0.0 ->
true
| _ ->
false
in
let report_dead_store live_vars = function let report_dead_store live_vars = function
| Sil.Store (Lvar pvar, _, _, loc) | Sil.Store (Lvar pvar, _, rhs_exp, loc)
when not when not
( Pvar.is_frontend_tmp pvar || Pvar.is_return pvar || Pvar.is_global pvar ( Pvar.is_frontend_tmp pvar || Pvar.is_return pvar || Pvar.is_global pvar
|| Domain.mem (Var.of_pvar pvar) live_vars || Procdesc.is_captured_var proc_desc pvar || Domain.mem (Var.of_pvar pvar) live_vars || Procdesc.is_captured_var proc_desc pvar
|| is_whitelisted_var pvar ) -> || is_whitelisted_var pvar || is_sentinel_exp rhs_exp ) ->
let issue_id = IssueType.dead_store.unique_id in let issue_id = IssueType.dead_store.unique_id in
let message = F.asprintf "The value written to %a is never used" (Pvar.pp Pp.text) pvar in let message = F.asprintf "The value written to %a is never used" (Pvar.pp Pp.text) pvar in
let ltr = [Errlog.make_trace_element 0 loc "Write of unused value" []] in let ltr = [Errlog.make_trace_element 0 loc "Write of unused value" []] in

@ -34,37 +34,37 @@ void dead_pointer_bad() {
} }
void plus_plus1_bad() { void plus_plus1_bad() {
int i = 0; int i = 1;
++i; ++i;
} }
void plus_plus2_bad() { void plus_plus2_bad() {
int i = 0; int i = 1;
i++; i++;
} }
int plus_plus3_bad() { int plus_plus3_bad() {
int i = 0; int i = 1;
return i++; return i++;
} }
void FN_capture_no_read_bad() { void FN_capture_no_read_bad() {
int x = 0; int x = 1;
[x]() { return; }(); [x]() { return; }();
} }
void init_capture_reassign_bad() { void init_capture_reassign_bad() {
int i = 0; // this is a dead store int i = 1; // this is a dead store
return [i = 0]() { return i; } return [i = 1]() { return i; }
(); ();
} }
void init_capture_no_call_bad() { void init_capture_no_call_bad() {
[i = 0]() { return i; }; [i = 1]() { return i; };
} }
int FN_init_capture_no_read_bad() { int FN_init_capture_no_read_bad() {
return [i = 0]() { return 0; } return [i = 1]() { return 0; }
(); ();
} }
@ -125,19 +125,19 @@ void by_ref1_ok(int& ref) { ref = 7; }
void by_ref2_ok(int& ref) { ref++; } void by_ref2_ok(int& ref) { ref++; }
int capture_by_ref3_ok() { int capture_by_ref3_ok() {
int x = 0; int x = 1;
[&](auto y) { x += y; }(3); [&](auto y) { x += y; }(3);
return x; return x;
} }
int plus_plus_ok() { int plus_plus_ok() {
int x = 0; int x = 1;
return ++x; return ++x;
} }
int plus_plus_loop_ok(int n) { int plus_plus_loop_ok(int n) {
int i; int i;
for (i = 0; i < n; i++) { for (i = 1; i < n; i++) {
i++; i++;
} }
return i; return i;
@ -162,14 +162,14 @@ void capture2_ok(int x) {
} }
int capture_by_ref1_ok() { int capture_by_ref1_ok() {
int x = 0; int x = 1;
[&x]() { x++; }(); [&x]() { x++; }();
return x; return x;
} }
int capture_by_ref2_ok() { int capture_by_ref2_ok() {
int x = 0; int x = 1;
int y = 0; int y = 1;
[&]() { [&]() {
x = x + y; x = x + y;
y = x; y = x;
@ -178,7 +178,7 @@ int capture_by_ref2_ok() {
} }
int FN_capture_by_ref_reuseBad() { int FN_capture_by_ref_reuseBad() {
int x = 0; int x = 1;
[&x]() { [&x]() {
x = 1; // dead, but we won't report x = 1; // dead, but we won't report
x = 2; x = 2;
@ -187,31 +187,31 @@ int FN_capture_by_ref_reuseBad() {
} }
int init_capture1_ok() { int init_capture1_ok() {
return [i = 0]() { return i; } return [i = 1]() { return i; }
(); ();
} }
int init_capture2_ok() { int init_capture2_ok() {
int i = 0; int i = 1;
return [j = i]() { return j; } return [j = i]() { return j; }
(); ();
} }
int init_capture3_ok() { int init_capture3_ok() {
int i = 0; int i = 1;
return [i = i]() { return i; } return [i = i]() { return i; }
(); ();
} }
int init_capture4_ok() { int init_capture4_ok() {
int i = 0; int i = 1;
int j = 0; int j = 1;
return [ a = 0, b = i, c = j ]() { return a + b + c; } return [ a = 1, b = i, c = j ]() { return a + b + c; }
(); ();
} }
int init_capture5_ok() { int init_capture5_ok() {
int i = 0; int i = 1;
int k = [j = i]() { return j; } int k = [j = i]() { return j; }
(); ();
i = 5; // should not be flagged i = 5; // should not be flagged
@ -219,7 +219,7 @@ int init_capture5_ok() {
} }
int init_capture6_ok() { int init_capture6_ok() {
int i = 0; int i = 1;
int k = [i = i + 1]() { return i; } int k = [i = i + 1]() { return i; }
(); ();
i = 5; // should not be flagged; i = 5; // should not be flagged;
@ -242,4 +242,42 @@ void placement_new_ok(int len, int* ptr) {
} }
} }
// we don't report on dead stores where the RHS is 0, 0.0, false, nullptr, etc.
bool sentinel_bool_ok() {
bool b = false;
b = true;
return b;
}
int sentinel_int_ok() {
int i = 0;
i = 1;
return i;
}
int sentinel_long_ok() {
long l = 0L;
l = 1L;
return l;
}
float sentinel_float_ok() {
float f = 0.0;
f = 1.0;
return f;
}
double sentinel_double_ok() {
double d = 0.0;
d = 1.0;
return d;
}
int* sentinel_ptr_ok(int* j) {
int* i = nullptr;
i = j;
return i;
}
} }

Loading…
Cancel
Save