diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 682328effbd..f22f848d0bb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,12 @@ 2013-08-13 Jakub Jelinek + PR tree-optimization/57661 + * tree-inline.h (struct copy_body_data): Add blocks_to_copy field. + * tree-inline.c (tree_function_versioning): Initialize it. + (remap_gimple_stmt): Return GIMPLE_NOP for MEM_REF lhs clobber stmts + if id->blocks_to_copy and MEM_REF's SSA_NAME is defined in a block + that is not being copied. + PR sanitizer/56417 * asan.c (instrument_strlen_call): Fix typo in comment. Use char * type even for the lhs of POINTER_PLUS_EXPR. diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 6e1b6309e7e..f962249b233 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2013-08-13 Jakub Jelinek + PR tree-optimization/57661 + * g++.dg/opt/pr57661.C: New test. + PR sanitizer/56417 * gcc.dg/asan/pr56417.c: New test. diff --git a/gcc/testsuite/g++.dg/opt/pr57661.C b/gcc/testsuite/g++.dg/opt/pr57661.C new file mode 100644 index 00000000000..8be9f09b633 --- /dev/null +++ b/gcc/testsuite/g++.dg/opt/pr57661.C @@ -0,0 +1,76 @@ +// PR tree-optimization/57661 +// { dg-do compile } +// { dg-options "-O2 -fno-tree-forwprop -std=gnu++11" } + +template +struct A +{ + ~A () {} +}; +template +using B = A <_Tp>; +template +class C : B <_Tp> {}; +namespace N { enum D { d }; } +template +struct E +{ + ~E (); +}; +template +struct F : V {}; +template +struct G : F +{ + N::D g1; + void g2 (); + void g3 (); + void g4 () { g3 (); } + static void g5 (G *__t) { __t->g4 (); } +}; +template +struct H : G +{ + E *h1; + bool h2; + ~H () throw () + { + this->g2 (); + if (h2) + delete h1; + } +}; +template +struct I : H , E +{ + G *i; + ~I () throw () + { + i->g4 (); + } +}; +struct J +{ + typedef C j1; + typedef G > j2; + J (); + j2 *j3; +}; +struct K : J +{ + typedef G > j2; + K () { j2::g5 (this->j3); } +}; +template +void G ::g3 () +{ + switch (g1) + { + case N::d: + { + I *q = (I *) this; + q->I ::~I (); + } + } +} +K r; diff --git a/gcc/tree-inline.c b/gcc/tree-inline.c index 00e31982957..55e527014f1 100644 --- a/gcc/tree-inline.c +++ b/gcc/tree-inline.c @@ -1387,6 +1387,23 @@ remap_gimple_stmt (gimple stmt, copy_body_data *id) } } + /* For *ptr_N ={v} {CLOBBER}, if ptr_N is SSA_NAME defined + in a block that we aren't copying during tree_function_versioning, + just drop the clobber stmt. */ + if (id->blocks_to_copy && gimple_clobber_p (stmt)) + { + tree lhs = gimple_assign_lhs (stmt); + if (TREE_CODE (lhs) == MEM_REF + && TREE_CODE (TREE_OPERAND (lhs, 0)) == SSA_NAME) + { + gimple def_stmt = SSA_NAME_DEF_STMT (TREE_OPERAND (lhs, 0)); + if (gimple_bb (def_stmt) + && !bitmap_bit_p (id->blocks_to_copy, + gimple_bb (def_stmt)->index)) + return gimple_build_nop (); + } + } + if (gimple_debug_bind_p (stmt)) { copy = gimple_build_debug_bind (gimple_debug_bind_get_var (stmt), @@ -5161,6 +5178,7 @@ tree_function_versioning (tree old_decl, tree new_decl, id.src_node = old_version_node; id.dst_node = new_version_node; id.src_cfun = DECL_STRUCT_FUNCTION (old_decl); + id.blocks_to_copy = blocks_to_copy; if (id.src_node->ipa_transforms_to_apply.exists ()) { vec old_transforms_to_apply diff --git a/gcc/tree-inline.h b/gcc/tree-inline.h index b65dee9350b..620ec977768 100644 --- a/gcc/tree-inline.h +++ b/gcc/tree-inline.h @@ -115,6 +115,10 @@ typedef struct copy_body_data /* Entry basic block to currently copied body. */ basic_block entry_bb; + /* For partial function versioning, bitmap of bbs to be copied, + otherwise NULL. */ + bitmap blocks_to_copy; + /* Debug statements that need processing. */ vec debug_stmts;