/* Predicate aware uninitialized variable warning.
- Copyright (C) 2001-2018 Free Software Foundation, Inc.
+ Copyright (C) 2001-2020 Free Software Foundation, Inc.
Contributed by Xinliang David Li <davidxl@google.com>
This file is part of GCC.
#include "fold-const.h"
#include "gimple-iterator.h"
#include "tree-ssa.h"
-#include "params.h"
#include "tree-cfg.h"
#include "cfghooks.h"
cfun_loc = DECL_SOURCE_LOCATION (cfun->decl);
xloc = expand_location (location);
floc = expand_location (cfun_loc);
+ auto_diagnostic_group d;
if (warning_at (location, wc, gmsgid, expr))
{
TREE_NO_WARNING (expr) = 1;
bool found_cd_chain = false;
size_t cur_chain_len = 0;
- if (*num_calls > PARAM_VALUE (PARAM_UNINIT_CONTROL_DEP_ATTEMPTS))
+ if (*num_calls > param_uninit_control_dep_attempts)
return false;
++*num_calls;
for (idx = 0; idx < gimple_switch_num_labels (gs); ++idx)
{
tree tl = gimple_switch_label (gs, idx);
- if (e->dest == label_to_block (CASE_LABEL (tl)))
+ if (e->dest == label_to_block (cfun, CASE_LABEL (tl)))
{
if (!l)
l = tl;
return tc;
}
-/* Returns true if VAL falls in the range defined by BOUNDARY and CMPC, i.e.
- all values in the range satisfies (x CMPC BOUNDARY) == true. */
+/* Returns whether VAL CMPC BOUNDARY is true. */
static bool
is_value_included_in (tree val, tree boundary, enum tree_code cmpc)
{
bool inverted = false;
- bool is_unsigned;
bool result;
/* Only handle integer constant here. */
if (TREE_CODE (val) != INTEGER_CST || TREE_CODE (boundary) != INTEGER_CST)
return true;
- is_unsigned = TYPE_UNSIGNED (TREE_TYPE (val));
-
if (cmpc == GE_EXPR || cmpc == GT_EXPR || cmpc == NE_EXPR)
{
cmpc = invert_tree_comparison (cmpc, false);
inverted = true;
}
- if (is_unsigned)
- {
- if (cmpc == EQ_EXPR)
- result = tree_int_cst_equal (val, boundary);
- else if (cmpc == LT_EXPR)
- result = tree_int_cst_lt (val, boundary);
- else
- {
- gcc_assert (cmpc == LE_EXPR);
- result = tree_int_cst_le (val, boundary);
- }
- }
+ if (cmpc == EQ_EXPR)
+ result = tree_int_cst_equal (val, boundary);
+ else if (cmpc == LT_EXPR)
+ result = tree_int_cst_lt (val, boundary);
else
{
- if (cmpc == EQ_EXPR)
- result = tree_int_cst_equal (val, boundary);
- else if (cmpc == LT_EXPR)
- result = tree_int_cst_lt (val, boundary);
- else
- {
- gcc_assert (cmpc == LE_EXPR);
- result = (tree_int_cst_equal (val, boundary)
- || tree_int_cst_lt (val, boundary));
- }
+ gcc_assert (cmpc == LE_EXPR);
+ result = tree_int_cst_le (val, boundary);
}
if (inverted)
return result;
}
+/* Returns whether VAL satisfies (x CMPC BOUNDARY) predicate. CMPC can be
+ either one of the range comparison codes ({GE,LT,EQ,NE}_EXPR and the like),
+ or BIT_AND_EXPR. EXACT_P is only meaningful for the latter. It modifies the
+ question from whether VAL & BOUNDARY != 0 to whether VAL & BOUNDARY == VAL.
+ For other values of CMPC, EXACT_P is ignored. */
+
+static bool
+value_sat_pred_p (tree val, tree boundary, enum tree_code cmpc,
+ bool exact_p = false)
+{
+ if (cmpc != BIT_AND_EXPR)
+ return is_value_included_in (val, boundary, cmpc);
+
+ wide_int andw = wi::to_wide (val) & wi::to_wide (boundary);
+ if (exact_p)
+ return andw == wi::to_wide (val);
+ else
+ return andw.to_uhwi ();
+}
+
/* Returns true if PRED is common among all the predicate
chains (PREDS) (and therefore can be factored out).
NUM_PRED_CHAIN is the size of array PREDS. */
/* Returns true of the domain of single predicate expression
EXPR1 is a subset of that of EXPR2. Returns false if it
- can not be proved. */
+ cannot be proved. */
static bool
is_pred_expr_subset_of (pred_info expr1, pred_info expr2)
if (expr2.invert)
code2 = invert_tree_comparison (code2, false);
- if ((code1 == EQ_EXPR || code1 == BIT_AND_EXPR) && code2 == BIT_AND_EXPR)
- return (wi::to_wide (expr1.pred_rhs)
- == (wi::to_wide (expr1.pred_rhs) & wi::to_wide (expr2.pred_rhs)));
-
- if (code1 != code2 && code2 != NE_EXPR)
+ if (code2 == NE_EXPR && code1 == NE_EXPR)
return false;
- if (is_value_included_in (expr1.pred_rhs, expr2.pred_rhs, code2))
- return true;
+ if (code2 == NE_EXPR)
+ return !value_sat_pred_p (expr2.pred_rhs, expr1.pred_rhs, code1);
+
+ if (code1 == EQ_EXPR)
+ return value_sat_pred_p (expr1.pred_rhs, expr2.pred_rhs, code2);
+
+ if (code1 == code2)
+ return value_sat_pred_p (expr1.pred_rhs, expr2.pred_rhs, code2,
+ code1 == BIT_AND_EXPR);
return false;
}
/* Returns true if the domain of PRED1 is a subset
- of that of PRED2. Returns false if it can not be proved so. */
+ of that of PRED2. Returns false if it cannot be proved so. */
static bool
is_pred_chain_subset_of (pred_chain pred1, pred_chain pred2)
individual predicate chains (won't be a compile time problem
as the chains are pretty short). When the function returns
false, it does not necessarily mean *PREDS1 is not a superset
- of *PREDS2, but mean it may not be so since the analysis can
- not prove it. In such cases, false warnings may still be
+ of *PREDS2, but mean it may not be so since the analysis cannot
+ prove it. In such cases, false warnings may still be
emitted. */
static bool
return true;
}
-/* Returns true if TC is AND or OR. */
-
-static inline bool
-is_and_or_or_p (enum tree_code tc, tree type)
-{
- return (tc == BIT_IOR_EXPR
- || (tc == BIT_AND_EXPR
- && (type == 0 || TREE_CODE (type) == BOOLEAN_TYPE)));
-}
-
/* Returns true if X1 is the negate of X2. */
static inline bool
USE_STMT is guarded with a predicate set not overlapping with
predicate sets of all runtime paths that do not have a definition.
- Returns false if it is not or it can not be determined. USE_BB is
+ Returns false if it is not or it cannot be determined. USE_BB is
the bb of the use (for phi operand use, the bb is not the bb of
the phi stmt, but the src bb of the operand edge).
warn_uninitialized_vars (/*warn_possibly_uninitialized=*/!optimize);
- /* Post-dominator information can not be reliably updated. Free it
+ /* Post-dominator information cannot be reliably updated. Free it
after the use. */
free_dominance_info (CDI_POST_DOMINATORS);