From 9093f275e0a3430e4517e782e7f5419d403113f7 Mon Sep 17 00:00:00 2001 From: David Malcolm Date: Wed, 20 Mar 2024 18:33:11 -0400 Subject: analyzer: fix -Wanalyzer-deref-before-check false positive seen in loop header macro [PR109251] gcc/analyzer/ChangeLog: PR analyzer/109251 * sm-malloc.cc (deref_before_check::emit): Reject cases where the check is in a loop header within a macro expansion. (deref_before_check::loop_header_p): New. gcc/testsuite/ChangeLog: PR analyzer/109251 * c-c++-common/analyzer/deref-before-check-pr109251-1.c: New test. * c-c++-common/analyzer/deref-before-check-pr109251-2.c: New test. Signed-off-by: David Malcolm --- gcc/analyzer/sm-malloc.cc | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) (limited to 'gcc/analyzer/sm-malloc.cc') diff --git a/gcc/analyzer/sm-malloc.cc b/gcc/analyzer/sm-malloc.cc index a518816..4e11d6d 100644 --- a/gcc/analyzer/sm-malloc.cc +++ b/gcc/analyzer/sm-malloc.cc @@ -1563,6 +1563,21 @@ public: if (linemap_location_from_macro_definition_p (line_table, check_loc)) return false; + /* Reject warning if the check is in a loop header within a + macro expansion. This rejects cases like: + | deref of x; + | [...snip...] + | FOR_EACH(x) { + | [...snip...] + | } + where the FOR_EACH macro tests for non-nullness of x, since + the user is hoping to encapsulate the details of iteration + in the macro, and the extra check on the first iteration + would just be noise if we reported it. */ + if (loop_header_p (m_check_enode->get_point ()) + && linemap_location_from_macro_expansion_p (line_table, check_loc)) + return false; + /* Reject if m_deref_expr is sufficiently different from m_arg for cases where the dereference is spelled differently from the check, which is probably two different ways to get the @@ -1618,6 +1633,21 @@ public: } private: + static bool loop_header_p (const program_point &point) + { + const supernode *snode = point.get_supernode (); + if (!snode) + return false; + for (auto &in_edge : snode->m_preds) + { + if (const cfg_superedge *cfg_in_edge + = in_edge->dyn_cast_cfg_superedge ()) + if (cfg_in_edge->back_edge_p ()) + return true; + } + return false; + } + static bool sufficiently_similar_p (tree expr_a, tree expr_b) { pretty_printer *pp_a = global_dc->printer->clone (); -- cgit v1.1