From: Jakub Jelinek Date: Mon, 30 Mar 2015 21:56:02 +0000 (+0200) Subject: re PR ipa/65610 (Compare debug failure with -g3 -fsanitize=undefined -fno-sanitize... X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=00a0ea64eec42da418a111bb4585b2ea007358dc;p=gcc.git re PR ipa/65610 (Compare debug failure with -g3 -fsanitize=undefined -fno-sanitize=vptr -O3) PR ipa/65610 * ipa-utils.h (inlined_polymorphic_ctor_dtor_block_p): Declare. * ipa-polymorphic-call.c (inlined_polymorphic_ctor_dtor_block_p): New function. (decl_maybe_in_construction_p, noncall_stmt_may_be_vtbl_ptr_store): Use it. * ipa-prop.c (param_type_may_change_p): Likewise. * tree-ssa-live.c: Include ipa-utils.h and its dependencies. (remove_unused_scope_block_p): Add in_ctor_dtor_block argument. Before inlining, preserve inlined_polymorphic_ctor_dtor_block_p blocks and the outermost block with FUNCTION_DECL BLOCK_ABSTRACT_ORIGIN inside of them. Adjust recursive calls. (remove_unused_locals): Adjust remove_unused_scope_block_p caller. * g++.dg/ubsan/pr65610.C: New test. From-SVN: r221781 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index e3d2a3d2af6..242eb507579 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2015-03-30 Jakub Jelinek + + PR ipa/65610 + * ipa-utils.h (inlined_polymorphic_ctor_dtor_block_p): Declare. + * ipa-polymorphic-call.c (inlined_polymorphic_ctor_dtor_block_p): New + function. + (decl_maybe_in_construction_p, noncall_stmt_may_be_vtbl_ptr_store): + Use it. + * ipa-prop.c (param_type_may_change_p): Likewise. + * tree-ssa-live.c: Include ipa-utils.h and its dependencies. + (remove_unused_scope_block_p): Add in_ctor_dtor_block + argument. Before inlining, preserve + inlined_polymorphic_ctor_dtor_block_p blocks and the outermost block + with FUNCTION_DECL BLOCK_ABSTRACT_ORIGIN inside of them. Adjust + recursive calls. + (remove_unused_locals): Adjust remove_unused_scope_block_p caller. + 2015-03-27 Jan Hubicka PR ipa/65076 diff --git a/gcc/ipa-polymorphic-call.c b/gcc/ipa-polymorphic-call.c index 90303f1bcfc..e0fd31ad523 100644 --- a/gcc/ipa-polymorphic-call.c +++ b/gcc/ipa-polymorphic-call.c @@ -513,6 +513,38 @@ contains_type_p (tree outer_type, HOST_WIDE_INT offset, } +/* Return a FUNCTION_DECL if BLOCK represents a constructor or destructor. + If CHECK_CLONES is true, also check for clones of ctor/dtors. */ + +tree +inlined_polymorphic_ctor_dtor_block_p (tree block, bool check_clones) +{ + tree fn = BLOCK_ABSTRACT_ORIGIN (block); + if (fn == NULL || TREE_CODE (fn) != FUNCTION_DECL) + return NULL_TREE; + + if (TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE + || (!DECL_CXX_CONSTRUCTOR_P (fn) && !DECL_CXX_DESTRUCTOR_P (fn))) + { + if (!check_clones) + return NULL_TREE; + + /* Watch for clones where we constant propagated the first + argument (pointer to the instance). */ + fn = DECL_ABSTRACT_ORIGIN (fn); + if (!fn + || TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE + || (!DECL_CXX_CONSTRUCTOR_P (fn) && !DECL_CXX_DESTRUCTOR_P (fn))) + return NULL_TREE; + } + + if (flags_from_decl_or_type (fn) & (ECF_PURE | ECF_CONST)) + return NULL_TREE; + + return fn; +} + + /* We know that the instance is stored in variable or parameter (not dynamically allocated) and we want to disprove the fact that it may be in construction at invocation of CALL. @@ -550,30 +582,11 @@ decl_maybe_in_construction_p (tree base, tree outer_type, && flags_from_decl_or_type (function) & (ECF_PURE | ECF_CONST)) return false; + bool check_clones = !base || is_global_var (base); for (tree block = gimple_block (call); block && TREE_CODE (block) == BLOCK; block = BLOCK_SUPERCONTEXT (block)) - if (BLOCK_ABSTRACT_ORIGIN (block) - && TREE_CODE (BLOCK_ABSTRACT_ORIGIN (block)) == FUNCTION_DECL) + if (tree fn = inlined_polymorphic_ctor_dtor_block_p (block, check_clones)) { - tree fn = BLOCK_ABSTRACT_ORIGIN (block); - - if (TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE - || (!DECL_CXX_CONSTRUCTOR_P (fn) - && !DECL_CXX_DESTRUCTOR_P (fn))) - { - /* Watch for clones where we constant propagated the first - argument (pointer to the instance). */ - fn = DECL_ABSTRACT_ORIGIN (fn); - if (!fn - || (base && !is_global_var (base)) - || TREE_CODE (TREE_TYPE (fn)) != METHOD_TYPE - || (!DECL_CXX_CONSTRUCTOR_P (fn) - && !DECL_CXX_DESTRUCTOR_P (fn))) - continue; - } - if (flags_from_decl_or_type (fn) & (ECF_PURE | ECF_CONST)) - continue; - tree type = TYPE_MAIN_VARIANT (method_class_type (TREE_TYPE (fn))); if (!outer_type || !types_odr_comparable (type, outer_type)) @@ -1163,15 +1176,7 @@ noncall_stmt_may_be_vtbl_ptr_store (gimple stmt) block = BLOCK_SUPERCONTEXT (block)) if (BLOCK_ABSTRACT_ORIGIN (block) && TREE_CODE (BLOCK_ABSTRACT_ORIGIN (block)) == FUNCTION_DECL) - { - tree fn = BLOCK_ABSTRACT_ORIGIN (block); - - if (flags_from_decl_or_type (fn) & (ECF_PURE | ECF_CONST)) - return false; - return (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE - && (DECL_CXX_CONSTRUCTOR_P (fn) - || DECL_CXX_DESTRUCTOR_P (fn))); - } + return inlined_polymorphic_ctor_dtor_block_p (block, false); return (TREE_CODE (TREE_TYPE (current_function_decl)) == METHOD_TYPE && (DECL_CXX_CONSTRUCTOR_P (current_function_decl) || DECL_CXX_DESTRUCTOR_P (current_function_decl))); diff --git a/gcc/ipa-prop.c b/gcc/ipa-prop.c index cfd9c16ed9c..89a4623e0c2 100644 --- a/gcc/ipa-prop.c +++ b/gcc/ipa-prop.c @@ -715,18 +715,8 @@ param_type_may_change_p (tree function, tree arg, gimple call) /* Walk the inline stack and watch out for ctors/dtors. */ for (tree block = gimple_block (call); block && TREE_CODE (block) == BLOCK; block = BLOCK_SUPERCONTEXT (block)) - if (BLOCK_ABSTRACT_ORIGIN (block) - && TREE_CODE (BLOCK_ABSTRACT_ORIGIN (block)) == FUNCTION_DECL) - { - tree fn = BLOCK_ABSTRACT_ORIGIN (block); - - if (flags_from_decl_or_type (fn) & (ECF_PURE | ECF_CONST)) - continue; - if (TREE_CODE (TREE_TYPE (fn)) == METHOD_TYPE - && (DECL_CXX_CONSTRUCTOR_P (fn) - || DECL_CXX_DESTRUCTOR_P (fn))) - return true; - } + if (inlined_polymorphic_ctor_dtor_block_p (block, false)) + return true; return false; } } diff --git a/gcc/ipa-utils.h b/gcc/ipa-utils.h index d302456ae94..0cf654163f7 100644 --- a/gcc/ipa-utils.h +++ b/gcc/ipa-utils.h @@ -70,6 +70,7 @@ bool possible_polymorphic_call_target_p (tree, HOST_WIDE_INT, const ipa_polymorphic_call_context &, struct cgraph_node *); tree method_class_type (const_tree); +tree inlined_polymorphic_ctor_dtor_block_p (tree, bool); bool decl_maybe_in_construction_p (tree, tree, gimple, tree); tree vtable_pointer_value_to_binfo (const_tree); bool vtable_pointer_value_to_vtable (const_tree, tree *, unsigned HOST_WIDE_INT *); diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d792b9f9537..708d8c65ad4 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2015-03-30 Jakub Jelinek + + PR ipa/65610 + * g++.dg/ubsan/pr65610.C: New test. + 2015-03-30 Marek Polacek PR c++/65398 diff --git a/gcc/testsuite/g++.dg/ubsan/pr65610.C b/gcc/testsuite/g++.dg/ubsan/pr65610.C new file mode 100644 index 00000000000..ced59a87430 --- /dev/null +++ b/gcc/testsuite/g++.dg/ubsan/pr65610.C @@ -0,0 +1,57 @@ +// PR ipa/65610 +// { dg-do compile } +// { dg-options "-std=c++11 -fsanitize=undefined -fno-sanitize=vptr -fcompare-debug" } + +class A; +class B {}; +enum C { D }; +class E; +class F; +class G; +class H +{ + F m1 (const A &t) const; + G m2 () const; +}; +class G {}; +template +class I; +template +class J +{ + friend class I ; + J *j; +}; +template +struct I +{ + virtual ~I (); + virtual void m3 (void *p) {} + J *i; + void m4 (J *& t); +}; +template +void I ::m4 (J * &t) +{ + m4 (t->j); + m3 (t); +} +template +I ::~I () +{ + m4 (i); +} +struct F +{ + explicit inline F (C v); + inline ~F (); + I f; +}; +inline F::F (C v) {} +inline F::~F () {} +F H::m1 (const A &t) const +{ + F q (D); + G r = m2 (); + return q; +} diff --git a/gcc/tree-ssa-live.c b/gcc/tree-ssa-live.c index e0c4266938f..df902292596 100644 --- a/gcc/tree-ssa-live.c +++ b/gcc/tree-ssa-live.c @@ -76,6 +76,10 @@ along with GCC; see the file COPYING3. If not see #include "diagnostic-core.h" #include "debug.h" #include "tree-ssa.h" +#include "lto-streamer.h" +#include "ipa-ref.h" +#include "cgraph.h" +#include "ipa-utils.h" #ifdef ENABLE_CHECKING static void verify_live_on_entry (tree_live_info_p); @@ -509,12 +513,29 @@ mark_scope_block_unused (tree scope) done by the inliner. */ static bool -remove_unused_scope_block_p (tree scope) +remove_unused_scope_block_p (tree scope, bool in_ctor_dtor_block) { tree *t, *next; bool unused = !TREE_USED (scope); int nsubblocks = 0; + /* For ipa-polymorphic-call.c purposes, preserve blocks: + 1) with BLOCK_ABSTRACT_ORIGIN of a ctor/dtor or their clones */ + if (inlined_polymorphic_ctor_dtor_block_p (scope, true)) + { + in_ctor_dtor_block = true; + unused = false; + } + /* 2) inside such blocks, the outermost block with BLOCK_ABSTRACT_ORIGIN + being a FUNCTION_DECL. */ + else if (in_ctor_dtor_block + && BLOCK_ABSTRACT_ORIGIN (scope) + && TREE_CODE (BLOCK_ABSTRACT_ORIGIN (scope)) == FUNCTION_DECL) + { + in_ctor_dtor_block = false; + unused = false; + } + for (t = &BLOCK_VARS (scope); *t; t = next) { next = &DECL_CHAIN (*t); @@ -594,7 +615,7 @@ remove_unused_scope_block_p (tree scope) } for (t = &BLOCK_SUBBLOCKS (scope); *t ;) - if (remove_unused_scope_block_p (*t)) + if (remove_unused_scope_block_p (*t, in_ctor_dtor_block)) { if (BLOCK_SUBBLOCKS (*t)) { @@ -959,7 +980,7 @@ remove_unused_locals (void) cfun->local_decls->truncate (dstidx); } - remove_unused_scope_block_p (DECL_INITIAL (current_function_decl)); + remove_unused_scope_block_p (DECL_INITIAL (current_function_decl), false); clear_unused_block_pointer (); BITMAP_FREE (usedvars);