analyzer: avoid comparisons between uncomparable types (PR 93450)
authorDavid Malcolm <dmalcolm@redhat.com>
Thu, 30 Jan 2020 01:24:42 +0000 (20:24 -0500)
committerDavid Malcolm <dmalcolm@redhat.com>
Thu, 30 Jan 2020 14:21:20 +0000 (09:21 -0500)
commitd177c49cd31131c8cededb216da30877d8a3856d
tree44202900181a2c828182ebd265561e0453e1f48b
parent64464e5f369231d2998608138da760274f256581
analyzer: avoid comparisons between uncomparable types (PR 93450)

PR analyzer/93450 reports an ICE trying to fold an EQ_EXPR comparison
of (int)0 with (float)Inf.

Most comparisons inside the analyzer come from gimple conditions, for
which the necessary casts have already been added.

This one is done inside constant_svalue::eval_condition as part of
purging sm-state for an unknown function call, and fails to check
the types being compared, leading to the ICE.

sm_state_map::set_state calls region_model::eval_condition_without_cm in
order to handle pointer equality (so that e.g. (void *)&r and (foo *)&r
transition together), which leads to this code generating a bogus query
to see if the two constants are equal.

This patch fixes the ICE in two ways:

- It avoids generating comparisons within
  constant_svalue::eval_condition unless the types are equal (thus for
  constants, but not for pointer values, which are handled by
  region_svalue).

- It updates sm_state_map::set_state to bail immediately if the new
  state is the same as the old one, thus avoiding the above for the
  common case where an svalue_id has no sm-state (such as for the int
  and float constants in the reproducer), for which the above becomes a
  no-op.

gcc/analyzer/ChangeLog:
PR analyzer/93450
* program-state.cc (sm_state_map::set_state): For the overload
taking an svalue_id, bail out if the set_state on the ec does
nothing.  Convert the latter's return type from void to bool,
returning true if anything changed.
(sm_state_map::impl_set_state): Convert the return type from void
to bool, returning true if the state changed.
* program-state.h (sm_state_map::set_state): Convert return type
from void to bool.
(sm_state_map::impl_set_state): Likewise.
* region-model.cc (constant_svalue::eval_condition): Only call
fold_build2 if the types are the same.

gcc/testsuite/ChangeLog:
PR analyzer/93450
* gcc.dg/analyzer/torture/pr93450.c: New test.
gcc/analyzer/ChangeLog
gcc/analyzer/program-state.cc
gcc/analyzer/program-state.h
gcc/analyzer/region-model.cc
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/analyzer/torture/pr93450.c [new file with mode: 0644]