tree-cfg.c (verify_expr_location, [...]): New functions.
authorRichard Biener <rguenther@suse.de>
Mon, 14 Jan 2013 14:59:20 +0000 (14:59 +0000)
committerRichard Biener <rguenth@gcc.gnu.org>
Mon, 14 Jan 2013 14:59:20 +0000 (14:59 +0000)
2013-01-14  Richard Biener  <rguenther@suse.de>

* tree-cfg.c (verify_expr_location, verify_expr_location_1,
verify_location, collect_subblocks): New functions.
(verify_gimple_in_cfg): Verify that locations only reference
BLOCKs in the functions BLOCK tree.

From-SVN: r195147

gcc/ChangeLog
gcc/tree-cfg.c

index 7b316199bdd4e494cb3f65d26d0897622562dd41..93947b6e34f8a66ec7bebcf5e2ac5b65f9f0d48e 100644 (file)
@@ -1,3 +1,10 @@
+2013-01-14  Richard Biener  <rguenther@suse.de>
+
+       * tree-cfg.c (verify_expr_location, verify_expr_location_1,
+       verify_location, collect_subblocks): New functions.
+       (verify_gimple_in_cfg): Verify that locations only reference
+       BLOCKs in the functions BLOCK tree.
+
 2013-01-14  Richard Biener  <rguenther@suse.de>
 
        * tree-cfgcleanup.c (remove_forwarder_block): Unshare propagated
index e0bf7ac6b3c1cd57ca75f54de47c4c785758f3fa..83003fb8b44cf762131909b80a10ba87e8610a91 100644 (file)
@@ -4499,6 +4499,63 @@ verify_eh_throw_stmt_node (void **slot, void *data)
   return 1;
 }
 
+/* Verify if the location LOCs block is in BLOCKS.  */
+
+static bool
+verify_location (pointer_set_t *blocks, location_t loc)
+{
+  tree block = LOCATION_BLOCK (loc);
+  if (block != NULL_TREE
+      && !pointer_set_contains (blocks, block))
+    {
+      error ("location references block not in block tree");
+      return true;
+    }
+  return false;
+}
+
+/* Called via walk_tree.  Verify locations of expressions.  */
+
+static tree
+verify_expr_location_1 (tree *tp, int *walk_subtrees, void *data)
+{
+  struct pointer_set_t *blocks = (struct pointer_set_t *) data;
+
+  if (!EXPR_P (*tp))
+    {
+      *walk_subtrees = false;
+      return NULL;
+    }
+
+  location_t loc = EXPR_LOCATION (*tp);
+  if (verify_location (blocks, loc))
+    return *tp;
+
+  return NULL;
+}
+
+/* Called via walk_gimple_op.  Verify locations of expressions.  */
+
+static tree
+verify_expr_location (tree *tp, int *walk_subtrees, void *data)
+{
+  struct walk_stmt_info *wi = (struct walk_stmt_info *) data;
+  return verify_expr_location_1 (tp, walk_subtrees, wi->info);
+}
+
+/* Insert all subblocks of BLOCK into BLOCKS and recurse.  */
+
+static void
+collect_subblocks (pointer_set_t *blocks, tree block)
+{
+  tree t;
+  for (t = BLOCK_SUBBLOCKS (block); t; t = BLOCK_CHAIN (t))
+    {
+      pointer_set_insert (blocks, t);
+      collect_subblocks (blocks, t);
+    }
+}
+
 /* Verify the GIMPLE statements in the CFG of FN.  */
 
 DEBUG_FUNCTION void
@@ -4506,12 +4563,20 @@ verify_gimple_in_cfg (struct function *fn)
 {
   basic_block bb;
   bool err = false;
-  struct pointer_set_t *visited, *visited_stmts;
+  struct pointer_set_t *visited, *visited_stmts, *blocks;
 
   timevar_push (TV_TREE_STMT_VERIFY);
   visited = pointer_set_create ();
   visited_stmts = pointer_set_create ();
 
+  /* Collect all BLOCKs referenced by the BLOCK tree of FN.  */
+  blocks = pointer_set_create ();
+  if (DECL_INITIAL (fn->decl))
+    {
+      pointer_set_insert (blocks, DECL_INITIAL (fn->decl));
+      collect_subblocks (blocks, DECL_INITIAL (fn->decl));
+    }
+
   FOR_EACH_BB_FN (bb, fn)
     {
       gimple_stmt_iterator gsi;
@@ -4532,6 +4597,13 @@ verify_gimple_in_cfg (struct function *fn)
 
          err2 |= verify_gimple_phi (phi);
 
+         /* Only PHI arguments have locations.  */
+         if (gimple_location (phi) != UNKNOWN_LOCATION)
+           {
+             error ("PHI node with location");
+             err2 = true;
+           }
+
          for (i = 0; i < gimple_phi_num_args (phi); i++)
            {
              tree arg = gimple_phi_arg_def (phi, i);
@@ -4543,6 +4615,20 @@ verify_gimple_in_cfg (struct function *fn)
                  debug_generic_expr (addr);
                  err2 |= true;
                }
+             location_t loc = gimple_phi_arg_location (phi, i);
+             if (virtual_operand_p (gimple_phi_result (phi))
+                 && loc != UNKNOWN_LOCATION)
+               {
+                 error ("virtual PHI with argument locations");
+                 err2 = true;
+               }
+             addr = walk_tree (&arg, verify_expr_location_1, blocks, NULL);
+             if (addr)
+               {
+                 debug_generic_expr (addr);
+                 err2 = true;
+               }
+             err2 |= verify_location (blocks, loc);
            }
 
          if (err2)
@@ -4567,6 +4653,7 @@ verify_gimple_in_cfg (struct function *fn)
            }
 
          err2 |= verify_gimple_stmt (stmt);
+         err2 |= verify_location (blocks, gimple_location (stmt));
 
          memset (&wi, 0, sizeof (wi));
          wi.info = (void *) visited;
@@ -4578,6 +4665,15 @@ verify_gimple_in_cfg (struct function *fn)
              err2 |= true;
            }
 
+         memset (&wi, 0, sizeof (wi));
+         wi.info = (void *) blocks;
+         addr = walk_gimple_op (stmt, verify_expr_location, &wi);
+         if (addr)
+           {
+             debug_generic_expr (addr);
+             err2 |= true;
+           }
+
          /* ???  Instead of not checking these stmts at all the walker
             should know its context via wi.  */
          if (!is_gimple_debug (stmt)
@@ -4632,6 +4728,7 @@ verify_gimple_in_cfg (struct function *fn)
 
   pointer_set_destroy (visited);
   pointer_set_destroy (visited_stmts);
+  pointer_set_destroy (blocks);
   verify_histograms ();
   timevar_pop (TV_TREE_STMT_VERIFY);
 }