+2017-03-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/79345
+ PR c++/42000
+ * tree-ssa-alias.c (walk_aliased_vdefs_1): Take a limit
+ param and abort the walk, returning -1 if it is hit.
+ (walk_aliased_vdefs): Take a limit param and pass it on.
+ * tree-ssa-alias.h (walk_aliased_vdefs): Add a limit param,
+ defaulting to 0 and return a signed int.
+ * tree-ssa-uninit.c (struct check_defs_data): New struct.
+ (check_defs): New helper.
+ (warn_uninitialized_vars): Use walk_aliased_vdefs to warn
+ about uninitialized memory.
+ * fixed-value.c (fixed_from_string): Use ulow/uhigh to avoid
+ bogus uninitialized warning.
+ (fixed_convert_from_real): Likewise.
+
2017-03-02 Bin Cheng <bin.cheng@arm.com>
PR tree-optimization/66768
real_arithmetic (&fixed_value, MULT_EXPR, &real_value, &base_value);
wide_int w = real_to_integer (&fixed_value, &fail,
GET_MODE_PRECISION (mode));
- f->data.low = w.elt (0);
- f->data.high = w.elt (1);
+ f->data.low = w.ulow ();
+ f->data.high = w.uhigh ();
if (temp == FIXED_MAX_EPS && ALL_FRACT_MODE_P (f->mode))
{
wide_int w = real_to_integer (&fixed_value, &fail,
GET_MODE_PRECISION (mode));
- f->data.low = w.elt (0);
- f->data.high = w.elt (1);
+ f->data.low = w.ulow ();
+ f->data.high = w.uhigh ();
temp = check_real_for_fixed_mode (&real_value, mode);
if (temp == FIXED_UNDERFLOW) /* Minimum. */
{
+2017-03-02 Richard Biener <rguenther@suse.de>
+
+ PR tree-optimization/79345
+ PR c++/42000
+ * g++.dg/warn/Wuninitialized-7.C: New testcase.
+ * c-c++-common/ubsan/bounds-2.c: Add -Wno-uninitialized.
+ * gcc.dg/uninit-pr19430-2.c: Add expected warning.
+
2017-03-02 Richard Biener <rguenther@suse.de>
PR c/79756
/* { dg-do run } */
-/* { dg-options "-fsanitize=bounds -Wall -Wextra -Wno-unused -Wno-array-bounds" } */
+/* { dg-options "-fsanitize=bounds -Wall -Wextra -Wno-unused -Wno-array-bounds -Wno-uninitialized" } */
/* Test runtime errors. */
--- /dev/null
+// { dg-do compile }
+// { dg-require-effective-target c++11 }
+// { dg-options "-O -Wuninitialized" }
+
+struct A {
+ A (int);
+};
+
+struct B: A {
+ const bool x = true;
+
+ B (): A (x ? 3 : 7) { } // { dg-warning "x. is used uninitialized" }
+};
+
+void f (void*);
+void g ()
+{
+ B b;
+ f (&b);
+}
p = &i;
q = &j;
if (b)
- x = p;
+ x = p; /* { dg-warning "i. may be used uninitialized" } */
else
x = q;
return *x;
PHI argument (but only one walk continues on merge points), the
return value is true if any of the walks was successful.
- The function returns the number of statements walked. */
+ The function returns the number of statements walked or -1 if
+ LIMIT stmts were walked and the walk was aborted at this point.
+ If LIMIT is zero the walk is not aborted. */
-static unsigned int
+static int
walk_aliased_vdefs_1 (ao_ref *ref, tree vdef,
bool (*walker)(ao_ref *, tree, void *), void *data,
bitmap *visited, unsigned int cnt,
- bool *function_entry_reached)
+ bool *function_entry_reached, unsigned limit)
{
do
{
if (!*visited)
*visited = BITMAP_ALLOC (NULL);
for (i = 0; i < gimple_phi_num_args (def_stmt); ++i)
- cnt += walk_aliased_vdefs_1 (ref, gimple_phi_arg_def (def_stmt, i),
- walker, data, visited, 0,
- function_entry_reached);
+ {
+ int res = walk_aliased_vdefs_1 (ref,
+ gimple_phi_arg_def (def_stmt, i),
+ walker, data, visited, cnt,
+ function_entry_reached, limit);
+ if (res == -1)
+ return -1;
+ cnt = res;
+ }
return cnt;
}
/* ??? Do we want to account this to TV_ALIAS_STMT_WALK? */
cnt++;
+ if (cnt == limit)
+ return -1;
if ((!ref
|| stmt_may_clobber_ref_p_1 (def_stmt, ref))
&& (*walker) (ref, vdef, data))
while (1);
}
-unsigned int
+int
walk_aliased_vdefs (ao_ref *ref, tree vdef,
bool (*walker)(ao_ref *, tree, void *), void *data,
bitmap *visited,
- bool *function_entry_reached)
+ bool *function_entry_reached, unsigned int limit)
{
bitmap local_visited = NULL;
- unsigned int ret;
+ int ret;
timevar_push (TV_ALIAS_STMT_WALK);
ret = walk_aliased_vdefs_1 (ref, vdef, walker, data,
visited ? visited : &local_visited, 0,
- function_entry_reached);
+ function_entry_reached, limit);
if (local_visited)
BITMAP_FREE (local_visited);
void *(*)(ao_ref *, tree, void *, bool *),
tree (*)(tree),
void *);
-extern unsigned int walk_aliased_vdefs (ao_ref *, tree,
- bool (*)(ao_ref *, tree, void *),
- void *, bitmap *,
- bool *function_entry_reached = NULL);
+extern int walk_aliased_vdefs (ao_ref *, tree,
+ bool (*)(ao_ref *, tree, void *),
+ void *, bitmap *,
+ bool *function_entry_reached = NULL,
+ unsigned int limit = 0);
extern void dump_alias_info (FILE *);
extern void debug_alias_info (void);
extern void dump_points_to_solution (FILE *, struct pt_solution *);
}
}
+struct check_defs_data
+{
+ /* If we found any may-defs besides must-def clobbers. */
+ bool found_may_defs;
+};
+
+/* Callback for walk_aliased_vdefs. */
+
+static bool
+check_defs (ao_ref *ref, tree vdef, void *data_)
+{
+ check_defs_data *data = (check_defs_data *)data_;
+ gimple *def_stmt = SSA_NAME_DEF_STMT (vdef);
+ /* If this is a clobber then if it is not a kill walk past it. */
+ if (gimple_clobber_p (def_stmt))
+ {
+ if (stmt_kills_ref_p (def_stmt, ref))
+ return true;
+ return false;
+ }
+ /* Found a may-def on this path. */
+ data->found_may_defs = true;
+ return true;
+}
+
static unsigned int
warn_uninitialized_vars (bool warn_possibly_uninitialized)
{
gimple_stmt_iterator gsi;
basic_block bb;
+ unsigned int vdef_cnt = 0;
+ unsigned int oracle_cnt = 0;
+ unsigned limit = 0;
FOR_EACH_BB_FN (bb, cfun)
{
stmt, UNKNOWN_LOCATION);
}
- /* For memory the only cheap thing we can do is see if we
- have a use of the default def of the virtual operand.
- ??? Not so cheap would be to use the alias oracle via
- walk_aliased_vdefs, if we don't find any aliasing vdef
- warn as is-used-uninitialized, if we don't find an aliasing
- vdef that kills our use (stmt_kills_ref_p), warn as
- may-be-used-uninitialized. But this walk is quadratic and
- so must be limited which means we would miss warning
- opportunities. */
- use = gimple_vuse (stmt);
- if (use
- && gimple_assign_single_p (stmt)
- && !gimple_vdef (stmt)
- && SSA_NAME_IS_DEFAULT_DEF (use))
+ /* For limiting the alias walk below we count all
+ vdefs in the function. */
+ if (gimple_vdef (stmt))
+ vdef_cnt++;
+
+ if (gimple_assign_load_p (stmt)
+ && gimple_has_location (stmt))
{
tree rhs = gimple_assign_rhs1 (stmt);
- tree base = get_base_address (rhs);
+ if (TREE_NO_WARNING (rhs))
+ continue;
+
+ ao_ref ref;
+ ao_ref_init (&ref, rhs);
/* Do not warn if it can be initialized outside this function. */
+ tree base = ao_ref_base (&ref);
if (!VAR_P (base)
|| DECL_HARD_REGISTER (base)
- || is_global_var (base))
+ || is_global_var (base)
+ || TREE_NO_WARNING (base))
+ continue;
+
+ /* Limit the walking to a constant number of stmts after
+ we overcommit quadratic behavior for small functions
+ and O(n) behavior. */
+ if (oracle_cnt > 128 * 128
+ && oracle_cnt > vdef_cnt * 2)
+ limit = 32;
+ check_defs_data data;
+ data.found_may_defs = false;
+ use = gimple_vuse (stmt);
+ int res = walk_aliased_vdefs (&ref, use,
+ check_defs, &data, NULL,
+ NULL, limit);
+ if (res == -1)
+ {
+ oracle_cnt += limit;
+ continue;
+ }
+ oracle_cnt += res;
+ if (data.found_may_defs)
continue;
+ /* We didn't find any may-defs so on all paths either
+ reached function entry or a killing clobber. */
+ location_t location
+ = linemap_resolve_location (line_table, gimple_location (stmt),
+ LRK_SPELLING_LOCATION, NULL);
if (always_executed)
- warn_uninit (OPT_Wuninitialized, use, gimple_assign_rhs1 (stmt),
- base, "%qE is used uninitialized in this function",
- stmt, UNKNOWN_LOCATION);
+ {
+ if (warning_at (location, OPT_Wuninitialized,
+ "%qE is used uninitialized in this function",
+ rhs))
+ /* ??? This is only effective for decls as in
+ gcc.dg/uninit-B-O0.c. Avoid doing this for
+ maybe-uninit uses as it may hide important
+ locations. */
+ TREE_NO_WARNING (rhs) = 1;
+ }
else if (warn_possibly_uninitialized)
- warn_uninit (OPT_Wmaybe_uninitialized, use,
- gimple_assign_rhs1 (stmt), base,
- "%qE may be used uninitialized in this function",
- stmt, UNKNOWN_LOCATION);
+ warning_at (location, OPT_Wmaybe_uninitialized,
+ "%qE may be used uninitialized in this function",
+ rhs);
}
}
}