analyzer: add heuristics for switch on enum type [PR105273]
authorDavid Malcolm <dmalcolm@redhat.com>
Fri, 13 Jan 2023 22:51:26 +0000 (17:51 -0500)
committerDavid Malcolm <dmalcolm@redhat.com>
Fri, 13 Jan 2023 22:51:26 +0000 (17:51 -0500)
commitccd4df81aa6537c3c935b026905f6e2fd839654e
treefd538d541afa3f3394c81a32b0e1865942372d57
parent6071e495e5802a8949d2b02df6aa31a5f40f2af9
analyzer: add heuristics for switch on enum type [PR105273]

Assume that switch on an enum doesn't follow an implicit default
skipping all cases when all enum values are covered by cases.

Fixes various false positives from -Wanalyzer-use-of-uninitialized-value
such as this one seen in Doom:

p_maputl.c: In function 'P_BoxOnLineSide':
p_maputl.c:151:8: warning: use of uninitialized value 'p1' [CWE-457] [-Wanalyzer-use-of-uninitialized-value]
  151 |     if (p1 == p2)
      |        ^
  'P_BoxOnLineSide': events 1-5
    |
    |  115 |     int         p1;
    |      |                 ^~
    |      |                 |
    |      |                 (1) region created on stack here
    |      |                 (2) capacity: 4 bytes
    |......
    |  118 |     switch (ld->slopetype)
    |      |     ~~~~~~
    |      |     |
    |      |     (3) following 'default:' branch...
    |......
    |  151 |     if (p1 == p2)
    |      |        ~
    |      |        |
    |      |        (4) ...to here
    |      |        (5) use of uninitialized value 'p1' here
    |

where "ld->slopetype" is a "slopetype_t" enum, and for every value of
that enum the switch has a case that initializes "p1".

gcc/analyzer/ChangeLog:
PR analyzer/105273
* region-model.cc (has_nondefault_case_for_value_p): New.
(has_nondefault_cases_for_all_enum_values_p): New.
(region_model::apply_constraints_for_gswitch): Skip
implicitly-created "default" when switching on an enum
and all enum values have non-default cases.
(rejected_default_case::dump_to_pp): New.
* region-model.h (region_model_context::possibly_tainted_p): New
decl.
(class rejected_default_case): New.
* sm-taint.cc (region_model_context::possibly_tainted_p): New.
* supergraph.cc (switch_cfg_superedge::dump_label_to_pp): Dump
when implicitly_created_default_p.
(switch_cfg_superedge::implicitly_created_default_p): New.
* supergraph.h
(switch_cfg_superedge::implicitly_created_default_p): New decl.

gcc/testsuite/ChangeLog:
PR analyzer/105273
* gcc.dg/analyzer/switch-enum-1.c: New test.
* gcc.dg/analyzer/switch-enum-2.c: New test.
* gcc.dg/analyzer/switch-enum-pr105273-git-vreportf-2.c: New test.
* gcc.dg/analyzer/switch-enum-taint-1.c: New test.
* gcc.dg/analyzer/switch-wrong-enum.c: New test.
* gcc.dg/analyzer/torture/switch-enum-pr105273-doom-p_floor.c: New
test.
* gcc.dg/analyzer/torture/switch-enum-pr105273-doom-p_maputl.c:
New test.
* gcc.dg/analyzer/torture/switch-enum-pr105273-git-vreportf-1.c:
New test.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
13 files changed:
gcc/analyzer/region-model.cc
gcc/analyzer/region-model.h
gcc/analyzer/sm-taint.cc
gcc/analyzer/supergraph.cc
gcc/analyzer/supergraph.h
gcc/testsuite/gcc.dg/analyzer/switch-enum-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/switch-enum-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/switch-enum-pr105273-git-vreportf-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/switch-enum-taint-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/switch-wrong-enum.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/torture/switch-enum-pr105273-doom-p_floor.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/torture/switch-enum-pr105273-doom-p_maputl.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/analyzer/torture/switch-enum-pr105273-git-vreportf-1.c [new file with mode: 0644]