+2016-04-14 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/70594
+ * ipa-utils.h (polymorphic_ctor_dtor_p): New prototype.
+ * ipa-polymorphic-call.c (polymorphic_ctor_dtor_p): New function.
+ (inlined_polymorphic_ctor_dtor_block_p): Use it.
+ * tree-ssa-live.c (remove_unused_scope_block_p): When
+ in_ctor_dtor_block, avoid discarding not just BLOCKs with
+ BLOCK_ABSTRACT_ORIGIN being FUNCTION_DECL, but even when
+ block_ultimate_origin is FUNCTION_DECL.
+ (remove_unused_locals): If current_function_decl is
+ polymorphic_ctor_dtor_p, pass initial true to
+ remove_unused_scope_block_p' is_ctor_dtor_block.
+
2016-04-14 Martin Sebor <msebor@redhat.com>
PR c++/69517
}
-/* Return a FUNCTION_DECL if BLOCK represents a constructor or destructor.
+/* Return a FUNCTION_DECL if FN represent 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)
+polymorphic_ctor_dtor_p (tree fn, bool check_clones)
{
- tree fn = block_ultimate_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)))
{
return fn;
}
+/* 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_ultimate_origin (block);
+ if (fn == NULL || TREE_CODE (fn) != FUNCTION_DECL)
+ return NULL_TREE;
+
+ return polymorphic_ctor_dtor_p (fn, check_clones);
+}
+
/* We know that the instance is stored in variable or parameter
(not dynamically allocated) and we want to disprove the fact
bool possible_polymorphic_call_target_p (tree, HOST_WIDE_INT,
const ipa_polymorphic_call_context &,
struct cgraph_node *);
+tree polymorphic_ctor_dtor_p (tree, bool);
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);
in_ctor_dtor_block = true;
unused = false;
}
- /* 2) inside such blocks, the outermost block with BLOCK_ABSTRACT_ORIGIN
+ /* 2) inside such blocks, the outermost block with block_ultimate_origin
being a FUNCTION_DECL. */
- else if (in_ctor_dtor_block
- && BLOCK_ABSTRACT_ORIGIN (scope)
- && TREE_CODE (BLOCK_ABSTRACT_ORIGIN (scope)) == FUNCTION_DECL)
+ else if (in_ctor_dtor_block)
{
- in_ctor_dtor_block = false;
- unused = false;
+ tree fn = block_ultimate_origin (scope);
+ if (fn && TREE_CODE (fn) == FUNCTION_DECL)
+ {
+ in_ctor_dtor_block = false;
+ unused = false;
+ }
}
for (t = &BLOCK_VARS (scope); *t; t = next)
cfun->local_decls->truncate (dstidx);
}
- remove_unused_scope_block_p (DECL_INITIAL (current_function_decl), false);
+ remove_unused_scope_block_p (DECL_INITIAL (current_function_decl),
+ polymorphic_ctor_dtor_p (current_function_decl,
+ true) != NULL_TREE);
clear_unused_block_pointer ();
BITMAP_FREE (usedvars);