aboutsummaryrefslogtreecommitdiff
path: root/gcc/vtable-verify.c
diff options
context:
space:
mode:
authorCaroline Tice <cmtice@google.com>2015-08-01 18:17:39 -0700
committerCaroline Tice <ctice@gcc.gnu.org>2015-08-01 18:17:39 -0700
commitb0cca5ecbb2841811a6c6aeaa40a3040289aeba3 (patch)
tree542c49f18581e9f2ecf6316e769cb4cee782b47c /gcc/vtable-verify.c
parent68e3e6a259b235add2d0c0f7dc3f92e7a47c5e90 (diff)
downloadgcc-b0cca5ecbb2841811a6c6aeaa40a3040289aeba3.zip
gcc-b0cca5ecbb2841811a6c6aeaa40a3040289aeba3.tar.gz
gcc-b0cca5ecbb2841811a6c6aeaa40a3040289aeba3.tar.bz2
re PR bootstrap/66521 (xgcc: cc1plus segfaults when compiling libstdc++-v3/src/c++11/ostream-inst.cc)
Fix PR 66521 libvtv/ChangeLog 2015-08-01 Caroline Tice <cmtice@google.com> PR 66521 * Makefile.am: Update to match latest tree. * Makefile.in: Regenerate. * testsuite/lib/libvtv: Brought up to date. * vtv_malloc.cc (VTV_DEBUG): Update function call to match renamed function (old bug!). * vtv_rts.cc (debug_functions, debug_init, debug_verify_vtable): Update initializations to work correctly with VTV_DEBUG defined. gcc/ChangeLog: 2015-08-01 Caroline Tice <cmtice@google.com> PR 66521 * vtable-verify.c (vtbl_mangled_name_types, vtbl_mangled_name_ids): New global variables. (vtbl_find_mangled_name): New function. (vtbl_register_mangled_name): New function. (vtbl_map_get_node): If DECL_ASSEMBLER_NAME is "<anon>", look up mangled name in mangled name vectors. (find_or_create_vtbl_map_node): Ditto. (var_is_used_for_virtual_call_p): Add recursion_depth parameter; update recursion_depth on function entry; pass it to every recursive call; automatically exit if depth > 25 (give up looking at that point). (verify_bb_vtables): Initialize recursion_depth and pass it to var_is_used_for_virtual_call_p. * vtable-verify.h (vtbl_mangbled_name_types, vtbl_mangled_name_ids): New global variable decls. (vtbl_register_mangled_name): New extern function decl. gcc/cp/ChangeLog: 2015-08-01 Caroline Tice <cmtice@google.com> PR 66521 * mangle.c : Add vtable-verify.h to include files. (get_mangled_vtable_map_var_name): If the DECL_ASSEMBLER_NAME is "<anon>" get the real mangled name for the class instead, and also store the real mangled name in a vector for use later. From-SVN: r226471
Diffstat (limited to 'gcc/vtable-verify.c')
-rw-r--r--gcc/vtable-verify.c92
1 files changed, 88 insertions, 4 deletions
diff --git a/gcc/vtable-verify.c b/gcc/vtable-verify.c
index 46506af..a834588 100644
--- a/gcc/vtable-verify.c
+++ b/gcc/vtable-verify.c
@@ -310,6 +310,70 @@ 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;
+/* Vector of mangled names for anonymous classes. */
+extern GTY(()) vec<tree, va_gc> *vtbl_mangled_name_types;
+extern GTY(()) vec<tree, va_gc> *vtbl_mangled_name_ids;
+vec<tree, va_gc> *vtbl_mangled_name_types;
+vec<tree, va_gc> *vtbl_mangled_name_ids;
+
+/* Look up class_type (a type decl for record types) in the vtbl_mangled_names_*
+ vectors. This is a linear lookup. Return the associated mangled name for
+ the class type. This is for handling types from anonymous namespaces, whose
+ DECL_ASSEMBLER_NAME ends up being "<anon>", which is useless for our
+ purposes.
+
+ We use two vectors of trees to keep track of the mangled names: One is a
+ vector of class types and the other is a vector of the mangled names. The
+ assumption is that these two vectors are kept in perfect lock-step so that
+ vtbl_mangled_name_ids[i] is the mangled name for
+ vtbl_mangled_name_types[i]. */
+
+static tree
+vtbl_find_mangled_name (tree class_type)
+{
+ tree result = NULL_TREE;
+ unsigned i;
+
+ if (!vtbl_mangled_name_types or !vtbl_mangled_name_ids)
+ return result;
+
+ if (vtbl_mangled_name_types->length() != vtbl_mangled_name_ids->length())
+ return result;
+
+ for (i = 0; i < vtbl_mangled_name_types->length(); ++i)
+ if ((*vtbl_mangled_name_types)[i] == class_type)
+ {
+ result = (*vtbl_mangled_name_ids)[i];
+ break;
+ }
+
+ return result;
+}
+
+/* Store a class type decl and its mangled name, for an anonymous RECORD_TYPE,
+ in the vtbl_mangled_names vector. Make sure there is not already an
+ entry for the class type before adding it. */
+
+void
+vtbl_register_mangled_name (tree class_type, tree mangled_name)
+{
+ if (!vtbl_mangled_name_types)
+ vec_alloc (vtbl_mangled_name_types, 10);
+
+ if (!vtbl_mangled_name_ids)
+ vec_alloc (vtbl_mangled_name_ids, 10);
+
+ gcc_assert (vtbl_mangled_name_types->length() ==
+ vtbl_mangled_name_ids->length());
+
+
+ if (vtbl_find_mangled_name (class_type) == NULL_TREE)
+ {
+ vec_safe_push (vtbl_mangled_name_types, class_type);
+ vec_safe_push (vtbl_mangled_name_ids, mangled_name);
+ }
+}
+
/* Return vtbl_map node for CLASS_NAME without creating a new one. */
struct vtbl_map_node *
@@ -339,6 +403,9 @@ vtbl_map_get_node (tree class_type)
gcc_assert (HAS_DECL_ASSEMBLER_NAME_P (class_type_decl));
class_name = DECL_ASSEMBLER_NAME (class_type_decl);
+ if (strstr (IDENTIFIER_POINTER (class_name), "<anon>") != NULL)
+ class_name = vtbl_find_mangled_name (class_type_decl);
+
key.class_name = class_name;
slot = (struct vtbl_map_node **) vtbl_map_hash->find_slot (&key, NO_INSERT);
if (!slot)
@@ -370,6 +437,10 @@ 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);
+
+ if (strstr (IDENTIFIER_POINTER (key.class_name), "<anon>") != NULL)
+ key.class_name = vtbl_find_mangled_name (class_type_decl);
+
slot = (struct vtbl_map_node **) vtbl_map_hash->find_slot (&key, INSERT);
if (*slot)
@@ -482,7 +553,8 @@ extract_object_class_type (tree rhs)
the use chain. */
static bool
-var_is_used_for_virtual_call_p (tree lhs, int *mem_ref_depth)
+var_is_used_for_virtual_call_p (tree lhs, int *mem_ref_depth,
+ int *recursion_depth)
{
imm_use_iterator imm_iter;
bool found_vcall = false;
@@ -494,6 +566,14 @@ var_is_used_for_virtual_call_p (tree lhs, int *mem_ref_depth)
if (*mem_ref_depth > 2)
return false;
+ if (*recursion_depth > 25)
+ /* If we've recursed this far the chances are pretty good that
+ we're not going to find what we're looking for, and that we've
+ gone down a recursion black hole. Time to stop. */
+ return false;
+
+ *recursion_depth = *recursion_depth + 1;
+
/* Iterate through the immediate uses of the current variable. If
it's a virtual function call, we're done. Otherwise, if there's
an LHS for the use stmt, add the ssa var to the work list
@@ -516,7 +596,8 @@ var_is_used_for_virtual_call_p (tree lhs, int *mem_ref_depth)
{
found_vcall = var_is_used_for_virtual_call_p
(gimple_phi_result (stmt2),
- mem_ref_depth);
+ mem_ref_depth,
+ recursion_depth);
}
else if (is_gimple_assign (stmt2))
{
@@ -538,7 +619,8 @@ var_is_used_for_virtual_call_p (tree lhs, int *mem_ref_depth)
if (*mem_ref_depth < 3)
found_vcall = var_is_used_for_virtual_call_p
(gimple_assign_lhs (stmt2),
- mem_ref_depth);
+ mem_ref_depth,
+ recursion_depth);
}
else
@@ -595,9 +677,11 @@ verify_bb_vtables (basic_block bb)
tree tmp0;
bool found;
int mem_ref_depth = 0;
+ int recursion_depth = 0;
/* Make sure this vptr field access is for a virtual call. */
- if (!var_is_used_for_virtual_call_p (lhs, &mem_ref_depth))
+ if (!var_is_used_for_virtual_call_p (lhs, &mem_ref_depth,
+ &recursion_depth))
continue;
/* Now we have found the virtual method dispatch and