aboutsummaryrefslogtreecommitdiff
path: root/gcc/ipa-polymorphic-call.c
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2015-03-30 23:56:02 +0200
committerJakub Jelinek <jakub@gcc.gnu.org>2015-03-30 23:56:02 +0200
commit00a0ea64eec42da418a111bb4585b2ea007358dc (patch)
tree4a2145b3fd570aa231e78ea5f2d8819866f798a9 /gcc/ipa-polymorphic-call.c
parentef4bac7802534e52d3031dccf0cdfb2c53b2d836 (diff)
downloadgcc-00a0ea64eec42da418a111bb4585b2ea007358dc.zip
gcc-00a0ea64eec42da418a111bb4585b2ea007358dc.tar.gz
gcc-00a0ea64eec42da418a111bb4585b2ea007358dc.tar.bz2
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
Diffstat (limited to 'gcc/ipa-polymorphic-call.c')
-rw-r--r--gcc/ipa-polymorphic-call.c65
1 files changed, 35 insertions, 30 deletions
diff --git a/gcc/ipa-polymorphic-call.c b/gcc/ipa-polymorphic-call.c
index 90303f1..e0fd31a 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)));