diff options
Diffstat (limited to 'gcc/analyzer/region-model.cc')
-rw-r--r-- | gcc/analyzer/region-model.cc | 69 |
1 files changed, 56 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 <const gassign *> (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 <const gcall *> (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 <const gassign *> (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 '<unknown>'. |