/* Predicate aware uninitialized variable warning.
- Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008 Free Software
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2010 Free Software
Foundation, Inc.
Contributed by Xinliang David Li <davidxl@google.com>
#include "tm.h"
#include "tree.h"
#include "flags.h"
-#include "rtl.h"
#include "tm_p.h"
-#include "ggc.h"
#include "langhooks.h"
-#include "hard-reg-set.h"
#include "basic-block.h"
#include "output.h"
-#include "expr.h"
#include "function.h"
-#include "diagnostic.h"
+#include "gimple-pretty-print.h"
#include "bitmap.h"
#include "pointer-set.h"
#include "tree-flow.h"
#include "gimple.h"
#include "tree-inline.h"
-#include "varray.h"
#include "timevar.h"
#include "hashtab.h"
#include "tree-dump.h"
#include "tree-pass.h"
+#include "diagnostic-core.h"
#include "toplev.h"
#include "timevar.h"
if (TREE_CODE (var) == PARM_DECL)
return false;
+ /* When returning by reference the return address is actually a hidden
+ parameter. */
+ if (TREE_CODE (SSA_NAME_VAR (t)) == RESULT_DECL
+ && DECL_BY_REFERENCE (SSA_NAME_VAR (t)))
+ return false;
+
/* Hard register variables get their initial value from the ether. */
if (TREE_CODE (var) == VAR_DECL && DECL_HARD_REGISTER (var))
return false;
opnd_edge = gimple_phi_arg_edge (phi, i);
opnd = gimple_phi_arg_def (phi, i);
- if (TREE_CODE (opnd) != SSA_NAME
- || !ssa_undefined_value_p (opnd))
- VEC_safe_push (edge, heap, *edges, opnd_edge);
+ if (TREE_CODE (opnd) != SSA_NAME)
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "\n[CHECK] Found def edge %d in ", (int)i);
+ print_gimple_stmt (dump_file, phi, 0, 0);
+ }
+ VEC_safe_push (edge, heap, *edges, opnd_edge);
+ }
else
{
gimple def = SSA_NAME_DEF_STMT (opnd);
+
if (gimple_code (def) == GIMPLE_PHI
&& dominated_by_p (CDI_DOMINATORS,
gimple_bb (def), cd_root))
collect_phi_def_edges (def, cd_root, edges,
visited_phis);
+ else if (!ssa_undefined_value_p (opnd))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "\n[CHECK] Found def edge %d in ", (int)i);
+ print_gimple_stmt (dump_file, phi, 0, 0);
+ }
+ VEC_safe_push (edge, heap, *edges, opnd_edge);
+ }
}
}
}
if (dump_file)
dump_predicates (use_stmt, num_preds, preds,
- "Use in stmt ");
+ "\nUse in stmt ");
has_valid_preds = find_def_preds (&def_preds,
&num_def_preds, phi);
struct pointer_set_t *visited_phis;
basic_block use_bb;
- use_stmt = use_p->loc.stmt;
+ use_stmt = USE_STMT (use_p);
+ if (is_gimple_debug (use_stmt))
+ continue;
visited_phis = pointer_set_create ();
- use_bb = gimple_bb (use_stmt);
if (gimple_code (use_stmt) == GIMPLE_PHI)
- {
- unsigned i, n;
- n = gimple_phi_num_args (use_stmt);
-
- /* Find the matching phi argument of the use. */
- for (i = 0; i < n; ++i)
- {
- if (gimple_phi_arg_def_ptr (use_stmt, i) == use_p->use)
- {
- edge e = gimple_phi_arg_edge (use_stmt, i);
- use_bb = e->src;
- break;
- }
- }
- }
+ use_bb = gimple_phi_arg_edge (use_stmt,
+ PHI_ARG_INDEX_FROM_USE (use_p))->src;
+ else
+ use_bb = gimple_bb (use_stmt);
if (is_use_properly_guarded (use_stmt,
use_bb,
}
pointer_set_destroy (visited_phis);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "[CHECK]: Found unguarded use: ");
+ print_gimple_stmt (dump_file, use_stmt, 0, 0);
+ }
/* Found one real use, return. */
if (gimple_code (use_stmt) != GIMPLE_PHI)
- return use_stmt;
+ return use_stmt;
/* Found a phi use that is not guarded,
add the phi to the worklist. */
if (!pointer_set_insert (added_to_worklist,
use_stmt))
{
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "[WORKLIST]: Update worklist with phi: ");
+ print_gimple_stmt (dump_file, use_stmt, 0, 0);
+ }
+
VEC_safe_push (gimple, heap, *worklist, use_stmt);
pointer_set_insert (possibly_undefined_names,
phi_result);
if (MASK_EMPTY (uninit_opnds))
return;
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "[CHECK]: examining phi: ");
+ print_gimple_stmt (dump_file, phi, 0, 0);
+ }
+
/* Now check if we have any use of the value without proper guard. */
uninit_use_stmt = find_uninit_use (phi, uninit_opnds,
worklist, added_to_worklist);
{
VEC_safe_push (gimple, heap, worklist, phi);
pointer_set_insert (added_to_worklist, phi);
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ {
+ fprintf (dump_file, "[WORKLIST]: add to initial list: ");
+ print_gimple_stmt (dump_file, phi, 0, 0);
+ }
break;
}
}
cur_phi = VEC_pop (gimple, worklist);
warn_uninitialized_phi (cur_phi, &worklist, added_to_worklist);
}
-
+
VEC_free (gimple, heap, worklist);
pointer_set_destroy (added_to_worklist);
pointer_set_destroy (possibly_undefined_names);