From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 2209) id 186D2385626A; Wed, 27 Jul 2022 21:55:54 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 186D2385626A MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Content-Type: text/plain; charset="utf-8" From: David Malcolm To: gcc-cvs@gcc.gnu.org Subject: [gcc r12-8637] analyzer: fix uninit false positive with -ftrivial-auto-var-init= [PR106204] X-Act-Checkin: gcc X-Git-Author: David Malcolm X-Git-Refname: refs/heads/releases/gcc-12 X-Git-Oldrev: 9fa11419ef59fde9d00ea8458235baa2bc83cd7a X-Git-Newrev: 09cb9c88ef8e2c0c89ada9cde2caf1a960db7a77 Message-Id: <20220727215554.186D2385626A@sourceware.org> Date: Wed, 27 Jul 2022 21:55:54 +0000 (GMT) X-BeenThere: gcc-cvs@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-cvs mailing list List-Unsubscribe: , List-Archive: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 27 Jul 2022 21:55:54 -0000 https://gcc.gnu.org/g:09cb9c88ef8e2c0c89ada9cde2caf1a960db7a77 commit r12-8637-g09cb9c88ef8e2c0c89ada9cde2caf1a960db7a77 Author: David Malcolm Date: Wed Jul 27 17:38:55 2022 -0400 analyzer: fix uninit false positive with -ftrivial-auto-var-init= [PR106204] (cherry picked from r13-1517-gb33dd7874523af) -fanalyzer handles -ftrivial-auto-var-init= by special-casing IFN_DEFERRED_INIT to be a no-op, so that e.g.: len_2 = .DEFERRED_INIT (4, 2, &"len"[0]); is treated as a no-op, so that len_2 is still uninitialized after the stmt. PR analyzer/106204 reports that -fanalyzer gives false positives from -Wanalyzer-use-of-uninitialized-value on locals that have their address taken, due to e.g.: _1 = .DEFERRED_INIT (4, 2, &"len"[0]); len = _1; where -fanalyzer leaves _1 uninitialized, and then complains about the assignment to "len". Fixed thusly by suppressing the warning when assigning from such SSA names. gcc/analyzer/ChangeLog: PR analyzer/106204 * region-model.cc (within_short_circuited_stmt_p): Move extraction of assign_stmt to caller. (due_to_ifn_deferred_init_p): New. (region_model::check_for_poison): Move extraction of assign_stmt from within_short_circuited_stmt_p to here. Share logic with call to due_to_ifn_deferred_init_p. gcc/testsuite/ChangeLog: PR analyzer/106204 * gcc.dg/analyzer/torture/uninit-pr106204.c: New test. * gcc.dg/analyzer/uninit-pr106204.c: New test. Signed-off-by: David Malcolm Diff: --- gcc/analyzer/region-model.cc | 69 ++++++++++++++++++---- .../gcc.dg/analyzer/torture/uninit-pr106204.c | 13 ++++ gcc/testsuite/gcc.dg/analyzer/uninit-pr106204.c | 17 ++++++ 3 files changed, 86 insertions(+), 13 deletions(-) diff --git a/gcc/analyzer/region-model.cc b/gcc/analyzer/region-model.cc index 816b4100f3a..23837a17346 100644 --- a/gcc/analyzer/region-model.cc +++ b/gcc/analyzer/region-model.cc @@ -895,17 +895,9 @@ region_model::get_gassign_result (const gassign *assign, static bool within_short_circuited_stmt_p (const region_model *model, - region_model_context *ctxt) + const gassign *assign_stmt) { - gcc_assert (ctxt); - const gimple *curr_stmt = ctxt->get_stmt (); - if (curr_stmt == NULL) - return false; - /* We must have an assignment to a temporary of _Bool type. */ - const gassign *assign_stmt = dyn_cast (curr_stmt); - if (!assign_stmt) - return false; tree lhs = gimple_assign_lhs (assign_stmt); if (TREE_TYPE (lhs) != boolean_type_node) return false; @@ -958,6 +950,47 @@ within_short_circuited_stmt_p (const region_model *model, return true; } +/* Workaround for discarding certain false positives from + -Wanalyzer-use-of-uninitialized-value + seen with -ftrivial-auto-var-init=. + + -ftrivial-auto-var-init= will generate calls to IFN_DEFERRED_INIT. + + If the address of the var is taken, gimplification will give us + something like: + + _1 = .DEFERRED_INIT (4, 2, &"len"[0]); + len = _1; + + The result of DEFERRED_INIT will be an uninit value; we don't + want to emit a false positive for "len = _1;" + + Return true if ASSIGN_STMT is such a stmt. */ + +static bool +due_to_ifn_deferred_init_p (const gassign *assign_stmt) + +{ + /* We must have an assignment to a decl from an SSA name that's the + result of a IFN_DEFERRED_INIT call. */ + if (gimple_assign_rhs_code (assign_stmt) != SSA_NAME) + return false; + tree lhs = gimple_assign_lhs (assign_stmt); + if (TREE_CODE (lhs) != VAR_DECL) + return false; + tree rhs = gimple_assign_rhs1 (assign_stmt); + if (TREE_CODE (rhs) != SSA_NAME) + return false; + const gimple *def_stmt = SSA_NAME_DEF_STMT (rhs); + const gcall *call = dyn_cast (def_stmt); + if (!call) + return false; + if (gimple_call_internal_p (call) + && gimple_call_internal_fn (call) == IFN_DEFERRED_INIT) + return true; + return false; +} + /* Check for SVAL being poisoned, adding a warning to CTXT. Return SVAL, or, if a warning is added, another value, to avoid repeatedly complaining about the same poisoned value in followup code. */ @@ -981,10 +1014,20 @@ region_model::check_for_poison (const svalue *sval, && is_empty_type (sval->get_type ())) return sval; - /* Special case to avoid certain false positives. */ - if (pkind == POISON_KIND_UNINIT - && within_short_circuited_stmt_p (this, ctxt)) - return sval; + if (pkind == POISON_KIND_UNINIT) + if (const gimple *curr_stmt = ctxt->get_stmt ()) + if (const gassign *assign_stmt + = dyn_cast (curr_stmt)) + { + /* Special case to avoid certain false positives. */ + if (within_short_circuited_stmt_p (this, assign_stmt)) + return sval; + + /* Special case to avoid false positive on + -ftrivial-auto-var-init=. */ + if (due_to_ifn_deferred_init_p (assign_stmt)) + return sval; + } /* If we have an SSA name for a temporary, we don't want to print ''. diff --git a/gcc/testsuite/gcc.dg/analyzer/torture/uninit-pr106204.c b/gcc/testsuite/gcc.dg/analyzer/torture/uninit-pr106204.c new file mode 100644 index 00000000000..25edcf5eecc --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/torture/uninit-pr106204.c @@ -0,0 +1,13 @@ +/* { dg-additional-options "-ftrivial-auto-var-init=zero" } */ + +int foo(unsigned *len); +int test_1() +{ + unsigned len; /* { dg-bogus "uninit" } */ + int rc; + + rc = foo(&len); + if (!rc) + rc = len; + return rc; +} diff --git a/gcc/testsuite/gcc.dg/analyzer/uninit-pr106204.c b/gcc/testsuite/gcc.dg/analyzer/uninit-pr106204.c new file mode 100644 index 00000000000..7d7cf7bfc7e --- /dev/null +++ b/gcc/testsuite/gcc.dg/analyzer/uninit-pr106204.c @@ -0,0 +1,17 @@ +/* { dg-additional-options "-ftrivial-auto-var-init=zero" } */ + +int foo(unsigned *len); + +/* Modified version of reproducer that does use "len" before init. */ + +int test_2() +{ + unsigned len; + int rc; + + rc = len; /* { dg-warning "use of uninitialized value 'len'" } */ + rc = foo(&len); + if (!rc) + rc = len; + return rc; +}