diff options
author | Caroline Tice <cmtice@google.com> | 2015-08-01 18:17:39 -0700 |
---|---|---|
committer | Caroline Tice <ctice@gcc.gnu.org> | 2015-08-01 18:17:39 -0700 |
commit | b0cca5ecbb2841811a6c6aeaa40a3040289aeba3 (patch) | |
tree | 542c49f18581e9f2ecf6316e769cb4cee782b47c /gcc/vtable-verify.c | |
parent | 68e3e6a259b235add2d0c0f7dc3f92e7a47c5e90 (diff) | |
download | gcc-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.c | 92 |
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 |