re PR debug/66691 (ICE on valid code at -O3 with -g enabled in simplify_subreg, at...
[gcc.git] / gcc / vtable-verify.c
index dabb77b9d106d7a63eed208a7aab21e053f667d7..8e24c924cc20e6938b1a9b549cfa1e3369a1b863 100644 (file)
@@ -1,5 +1,4 @@
-/*   Copyright (C) 2013
-    Free Software Foundation, Inc.
+/* Copyright (C) 2013-2015 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -136,12 +135,21 @@ along with GCC; see the file COPYING3.  If not see
 #include "config.h"
 #include "system.h"
 #include "coretypes.h"
+#include "alias.h"
+#include "symtab.h"
+#include "options.h"
 #include "tree.h"
+#include "fold-const.h"
+#include "predict.h"
+#include "tm.h"
+#include "hard-reg-set.h"
+#include "function.h"
+#include "dominance.h"
+#include "cfg.h"
 #include "basic-block.h"
 #include "tree-ssa-alias.h"
 #include "internal-fn.h"
 #include "gimple-expr.h"
-#include "is-a.h"
 #include "gimple.h"
 #include "gimple-iterator.h"
 #include "gimple-ssa.h"
@@ -183,11 +191,10 @@ vtbl_map_node_registration_find (struct vtbl_map_node *node,
   struct vtable_registration key;
   struct vtable_registration **slot;
 
-  gcc_assert (node && node->registered.is_created ());
+  gcc_assert (node && node->registered);
 
   key.vtable_decl = vtable_decl;
-  slot = (struct vtable_registration **) node->registered.find_slot (&key,
-                                                                     NO_INSERT);
+  slot = node->registered->find_slot (&key, NO_INSERT);
 
   if (slot && (*slot))
     {
@@ -213,12 +220,11 @@ vtbl_map_node_registration_insert (struct vtbl_map_node *node,
   struct vtable_registration **slot;
   bool inserted_something = false;
 
-  if (!node || !node->registered.is_created ())
+  if (!node || !node->registered)
     return false;
 
   key.vtable_decl = vtable_decl;
-  slot = (struct vtable_registration **) node->registered.find_slot (&key,
-                                                                     INSERT);
+  slot = node->registered->find_slot (&key, INSERT);
 
   if (! *slot)
     {
@@ -253,14 +259,15 @@ vtbl_map_node_registration_insert (struct vtbl_map_node *node,
 /* Hashtable functions for vtable_registration hashtables.  */
 
 inline hashval_t
-registration_hasher::hash (const value_type *p)
+registration_hasher::hash (const vtable_registration *p)
 {
   const struct vtable_registration *n = (const struct vtable_registration *) p;
   return (hashval_t) (DECL_UID (n->vtable_decl));
 }
 
 inline bool
-registration_hasher::equal (const value_type *p1, const compare_type *p2)
+registration_hasher::equal (const vtable_registration *p1,
+                           const vtable_registration *p2)
 {
   const struct vtable_registration *n1 =
                                     (const struct vtable_registration *) p1;
@@ -275,18 +282,16 @@ registration_hasher::equal (const value_type *p1, const compare_type *p2)
 
 /* Hashtable definition and functions for vtbl_map_hash.  */
 
-struct vtbl_map_hasher : typed_noop_remove <struct vtbl_map_node>
+struct vtbl_map_hasher : nofree_ptr_hash <struct vtbl_map_node>
 {
-  typedef struct vtbl_map_node value_type;
-  typedef struct vtbl_map_node compare_type;
-  static inline hashval_t hash (const value_type *);
-  static inline bool equal (const value_type *, const compare_type *);
+  static inline hashval_t hash (const vtbl_map_node *);
+  static inline bool equal (const vtbl_map_node *, const vtbl_map_node *);
 };
 
 /* Returns a hash code for P.  */
 
 inline hashval_t
-vtbl_map_hasher::hash (const value_type *p)
+vtbl_map_hasher::hash (const vtbl_map_node *p)
 {
   const struct vtbl_map_node n = *((const struct vtbl_map_node *) p);
   return (hashval_t) IDENTIFIER_HASH_VALUE (n.class_name);
@@ -295,7 +300,7 @@ vtbl_map_hasher::hash (const value_type *p)
 /* Returns nonzero if P1 and P2 are equal.  */
 
 inline bool
-vtbl_map_hasher::equal (const value_type *p1, const compare_type *p2)
+vtbl_map_hasher::equal (const vtbl_map_node *p1, const vtbl_map_node *p2)
 {
   const struct vtbl_map_node n1 = *((const struct vtbl_map_node *) p1);
   const struct vtbl_map_node n2 = *((const struct vtbl_map_node *) p2);
@@ -308,11 +313,11 @@ vtbl_map_hasher::equal (const value_type *p1, const compare_type *p2)
    to find the nodes for various tasks (see comments in vtable-verify.h
    for more details.  */
 
-typedef hash_table <vtbl_map_hasher> vtbl_map_table_type;
+typedef hash_table<vtbl_map_hasher> vtbl_map_table_type;
 typedef vtbl_map_table_type::iterator vtbl_map_iterator_type;
 
 /* Vtable map variable nodes stored in a hash table.  */
-static vtbl_map_table_type vtbl_map_hash;
+static vtbl_map_table_type *vtbl_map_hash;
 
 /* Vtable map variable nodes stored in a vector.  */
 vec<struct vtbl_map_node *> vtbl_map_nodes_vec;
@@ -329,7 +334,7 @@ vtbl_map_get_node (tree class_type)
   tree class_name;
   unsigned int type_quals;
 
-  if (!vtbl_map_hash.is_created ())
+  if (!vtbl_map_hash)
     return NULL;
 
   gcc_assert (TREE_CODE (class_type) == RECORD_TYPE);
@@ -347,8 +352,7 @@ vtbl_map_get_node (tree class_type)
   class_name = DECL_ASSEMBLER_NAME (class_type_decl);
 
   key.class_name = class_name;
-  slot = (struct vtbl_map_node **) vtbl_map_hash.find_slot (&key,
-                                                            NO_INSERT);
+  slot = (struct vtbl_map_node **) vtbl_map_hash->find_slot (&key, NO_INSERT);
   if (!slot)
     return NULL;
   return *slot;
@@ -366,8 +370,8 @@ find_or_create_vtbl_map_node (tree base_class_type)
   tree class_type_decl;
   unsigned int type_quals;
 
-  if (!vtbl_map_hash.is_created ())
-    vtbl_map_hash.create (10);
+  if (!vtbl_map_hash)
+    vtbl_map_hash = new vtbl_map_table_type (10);
 
   /* Find the TYPE_DECL for the class.  */
   class_type_decl = TYPE_NAME (base_class_type);
@@ -378,8 +382,7 @@ find_or_create_vtbl_map_node (tree base_class_type)
 
   gcc_assert (HAS_DECL_ASSEMBLER_NAME_P (class_type_decl));
   key.class_name = DECL_ASSEMBLER_NAME (class_type_decl);
-  slot = (struct vtbl_map_node **) vtbl_map_hash.find_slot (&key,
-                                                            INSERT);
+  slot = (struct vtbl_map_node **) vtbl_map_hash->find_slot (&key, INSERT);
 
   if (*slot)
     return *slot;
@@ -397,7 +400,7 @@ find_or_create_vtbl_map_node (tree base_class_type)
   (node->class_info->parents).create (4);
   (node->class_info->children).create (4);
 
-  node->registered.create (16);
+  node->registered = new register_table_type (16);
 
   node->is_used = false;
 
@@ -513,10 +516,10 @@ var_is_used_for_virtual_call_p (tree lhs, int *mem_ref_depth)
     {
       gimple stmt2 = USE_STMT (use_p);
 
-      if (gimple_code (stmt2) == GIMPLE_CALL)
+      if (is_gimple_call (stmt2))
         {
           tree fncall = gimple_call_fn (stmt2);
-          if (TREE_CODE (fncall) == OBJ_TYPE_REF)
+          if (fncall && TREE_CODE (fncall) == OBJ_TYPE_REF)
             found_vcall = true;
          else
            return false;
@@ -527,7 +530,7 @@ var_is_used_for_virtual_call_p (tree lhs, int *mem_ref_depth)
                                                    (gimple_phi_result (stmt2),
                                                     mem_ref_depth);
         }
-      else if (gimple_code (stmt2) == GIMPLE_ASSIGN)
+      else if (is_gimple_assign (stmt2))
         {
          tree rhs = gimple_assign_rhs1 (stmt2);
          if (TREE_CODE (rhs) == ADDR_EXPR
@@ -599,7 +602,7 @@ verify_bb_vtables (basic_block bb)
           tree vtbl_var_decl = NULL_TREE;
           struct vtbl_map_node *vtable_map_node;
           tree vtbl_decl = NULL_TREE;
-          gimple call_stmt;
+          gcall *call_stmt;
           const char *vtable_name = "<unknown>";
           tree tmp0;
           bool found;
@@ -724,31 +727,6 @@ verify_bb_vtables (basic_block bb)
     }
 }
 
-/* Main function, called from pass->excute().  Loop through all the
-   basic blocks in the current function, passing them to
-   verify_bb_vtables, which searches for virtual calls, and inserts
-   calls to __VLTVerifyVtablePointer.  */
-
-unsigned int
-vtable_verify_main (void)
-{
-  unsigned int ret = 1;
-  basic_block bb;
-
-  FOR_ALL_BB_FN (bb, cfun)
-      verify_bb_vtables (bb);
-
-  return ret;
-}
-
-/* Gate function for the pass.  */
-
-static bool
-gate_tree_vtable_verify (void)
-{
-  return (flag_vtable_verify);
-}
-
 /* Definition of this optimization pass.  */
 
 namespace {
@@ -758,8 +736,6 @@ const pass_data pass_data_vtable_verify =
   GIMPLE_PASS, /* type */
   "vtable-verify", /* name */
   OPTGROUP_NONE, /* optinfo_flags */
-  true, /* has_gate */
-  true, /* has_execute */
   TV_VTABLE_VERIFICATION, /* tv_id */
   ( PROP_cfg | PROP_ssa ), /* properties_required */
   0, /* properties_provided */
@@ -776,11 +752,27 @@ public:
   {}
 
   /* opt_pass methods: */
-  bool gate () { return gate_tree_vtable_verify (); }
-  unsigned int execute () { return vtable_verify_main (); }
+  virtual bool gate (function *) { return (flag_vtable_verify); }
+  virtual unsigned int execute (function *);
 
 }; // class pass_vtable_verify
 
+/* Loop through all the basic blocks in the current function, passing them to
+   verify_bb_vtables, which searches for virtual calls, and inserts
+   calls to __VLTVerifyVtablePointer.  */
+
+unsigned int
+pass_vtable_verify::execute (function *fun)
+{
+  unsigned int ret = 1;
+  basic_block bb;
+
+  FOR_ALL_BB_FN (bb, fun)
+      verify_bb_vtables (bb);
+
+  return ret;
+}
+
 } // anon namespace
 
 gimple_opt_pass *