analyzer: ignore uninitialized uses of empty types [PR104274]

PR analyzer/104274 reports a false positive from
-Wanalyzer-use-of-uninitialized-value on hppa when passing
an empty struct as a function parameter.

pa_pass_by_reference returns true for empty structs, so the
call is turned into:

  struct empty arg.0;
  arg.0 = arg
  called_function (arg.0);

by gimplify_parameters.

However, gimplify_modify_expr discards assignments statments
of empty types, so that we end up with:

  struct empty arg.0;
  called_function (arg.0);

which the analyzer considers to be a use of uninitialized "arg.0";

Given that gimplify_modify_expr will discard any assignments to
such types, it seems simplest for -Wanalyzer-use-of-uninitialized-value
to ignore values of empty types.

gcc/analyzer/ChangeLog:
	PR analyzer/104274
	* region-model.cc (region_model::check_for_poison): Ignore
	uninitialized uses of empty types.

gcc/testsuite/ChangeLog:
	PR analyzer/104274
	* gcc.dg/analyzer/torture/empty-struct-1.c: New test.

Signed-off-by: David Malcolm <dmalcolm@redhat.com>
This commit is contained in:
David Malcolm 2022-02-10 19:01:30 -05:00
parent ae117af439
commit cc68ad8701
2 changed files with 27 additions and 1 deletions

View file

@ -843,13 +843,21 @@ region_model::check_for_poison (const svalue *sval,
if (const poisoned_svalue *poisoned_sval = sval->dyn_cast_poisoned_svalue ())
{
enum poison_kind pkind = poisoned_sval->get_poison_kind ();
/* Ignore uninitialized uses of empty types; there's nothing
to initialize. */
if (pkind == POISON_KIND_UNINIT
&& sval->get_type ()
&& is_empty_type (sval->get_type ()))
return sval;
/* If we have an SSA name for a temporary, we don't want to print
'<unknown>'.
Poisoned values are shared by type, and so we can't reconstruct
the tree other than via the def stmts, using
fixup_tree_for_diagnostic. */
tree diag_arg = fixup_tree_for_diagnostic (expr);
enum poison_kind pkind = poisoned_sval->get_poison_kind ();
const region *src_region = NULL;
if (pkind == POISON_KIND_UNINIT)
src_region = get_region_for_poisoned_expr (expr);

View file

@ -0,0 +1,18 @@
struct empty {};
struct empty g;
extern void sink (struct empty e);
void test_1 (struct empty a)
{
sink (a); /* { dg-bogus "uninit" } */
}
void test_2 ()
{
struct empty a, b;
b = a;
g = b;
sink (b); /* { dg-bogus "uninit" } */
/* ...as there's nothing to initialize. */
}