From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5137 invoked by alias); 7 Oct 2004 20:05:06 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 4843 invoked from network); 7 Oct 2004 20:05:04 -0000 Received: from unknown (HELO mx1.redhat.com) (66.187.233.31) by sourceware.org with SMTP; 7 Oct 2004 20:05:04 -0000 Received: from int-mx1.corp.redhat.com (int-mx1.corp.redhat.com [172.16.52.254]) by mx1.redhat.com (8.12.11/8.12.10) with ESMTP id i97K54bW017092 for ; Thu, 7 Oct 2004 16:05:04 -0400 Received: from devserv.devel.redhat.com (devserv.devel.redhat.com [172.16.58.1]) by int-mx1.corp.redhat.com (8.11.6/8.11.6) with ESMTP id i97K54r11972 for ; Thu, 7 Oct 2004 16:05:04 -0400 Received: from devserv.devel.redhat.com (localhost.localdomain [127.0.0.1]) by devserv.devel.redhat.com (8.12.11/8.12.10) with ESMTP id i97K4ku9004632; Thu, 7 Oct 2004 16:04:46 -0400 Received: (from jakub@localhost) by devserv.devel.redhat.com (8.12.11/8.12.11/Submit) id i97K4j7P004624; Thu, 7 Oct 2004 16:04:45 -0400 Date: Thu, 07 Oct 2004 20:13:00 -0000 From: Jakub Jelinek To: Richard Henderson , Diego Novillo Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] Fix PR tree-optimization/17724 Message-ID: <20041007200445.GN31909@devserv.devel.redhat.com> Reply-To: Jakub Jelinek Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="LSp5EJdfMPwZcMS1" Content-Disposition: inline User-Agent: Mutt/1.4.1i X-SW-Source: 2004-10/txt/msg00659.txt.bz2 --LSp5EJdfMPwZcMS1 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline Content-length: 1900 Hi! The fold_all_builtin patch to gimplify results of ccp_fold_builtin uncovered what it seems to be a latent problem - some basic block removals don't recompute dominators of their neighbouring basic blocks. Particularly in one of the attached testcases bb1->bb3, bb1->bb4 and bb3->bb4 are EH edges: +---+ |bb0| +---+ / \ / \ / \ v v +---+ +---+ |bb1|--->|bb2| +---+ +---+ / \ | / \ | / \ | v v | +---+ +---+ | |bb3|-->|bb4| | +---+ +---+ | \ | \ +---+ -------->|bb5| +---+ | --- - strcpy which due to the missing throw () in the testcase can throw is replaced by code that can't throw, thus the EH edges are removed (by tree_purge_dead_eh_edges) and in the end cleanup_tree_cfg kicks in. This in turn calls delete_unreachable_blocks that deletes bb3 and bb4 basic blocks. The problem is that immediate dominator of bb5 before all of this was bb0, but after bb3 and bb4 basic blocks are removed, immediate dominator is bb2; there is nothing that updates the dominator info of bb5 though. Attached are 3 patches, first and third patch were bootstrapped and regtested on i386-redhat-linux, the second one doesn't work but is included for completeness what I tried. The first patch calls free_dominance_info in cleanup_tree_cfg whenever delete_unreachable_blocks deleted some basic blocks. It should be safe, but might be expensive. The second patch tried to recompute dominators in a routine called from delete_basic_block, but apparently some callers of delete_basic_block don't expect the recomputation. The third one recomputes dominators (and post-dominators) of neighbours of unreachable basic blocks after they are deleted by delete_unreachable_blocks. Jakub --LSp5EJdfMPwZcMS1 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="delete-unreachable-blocks1.patch" Content-length: 5463 2004-10-07 Jakub Jelinek PR tree-optimization/17724 * tree-cfg.c (tree_purge_dead_eh_edges): Recompute dominator for the EH block. (cleanup_tree_cfg): Free dominators if any delete_unreachable_blocks deleted some basic block. * g++.dg/opt/pr17724-1.C: New test. * g++.dg/opt/pr17724-2.C: New test. * g++.dg/opt/pr17724-3.C: New test. * g++.dg/opt/pr17724-4.C: New test. * g++.dg/opt/pr17724-5.C: New test. * g++.dg/opt/pr17724-6.C: New test. --- gcc/tree-cfg.c.jj 2004-10-02 10:46:07.000000000 +0200 +++ gcc/tree-cfg.c 2004-10-02 11:19:53.042030301 +0200 @@ -713,11 +713,13 @@ bool cleanup_tree_cfg (void) { - bool retval = false; + bool retval; + bool blocks_deleted; timevar_push (TV_TREE_CLEANUP_CFG); retval = cleanup_control_flow (); - retval |= delete_unreachable_blocks (); + blocks_deleted = delete_unreachable_blocks (); + retval |= blocks_deleted; /* thread_jumps() sometimes leaves further transformation opportunities for itself, so iterate on it until nothing @@ -743,6 +745,13 @@ cleanup_tree_cfg (void) } #endif + /* If blocks were deleted, the dominance info might be outdated. */ + if (blocks_deleted) + { + free_dominance_info (CDI_DOMINATORS); + free_dominance_info (CDI_POST_DOMINATORS); + } + /* Merging the blocks creates no new opportunities for the other optimizations, so do it here. */ merge_seq_blocks (); @@ -5089,7 +5098,11 @@ tree_purge_dead_eh_edges (basic_block bb { if (e->flags & EDGE_EH) { + basic_block dest = e->dest, dom; + ssa_remove_edge (e); + dom = recount_dominator (CDI_DOMINATORS, dest); + set_immediate_dominator (CDI_DOMINATORS, dest, dom); changed = true; } else --- gcc/testsuite/g++.dg/opt/pr17724-4.C.jj 2004-10-02 11:27:29.000000000 +0200 +++ gcc/testsuite/g++.dg/opt/pr17724-4.C 2004-10-02 11:29:21.803990546 +0200 @@ -0,0 +1,24 @@ +// PR tree-optimization/17724 +// { dg-do compile } +// { dg-options "-O2" } + +extern "C" char *strcpy (char* d, const char* s); + +class A { public: A (); ~A (); }; + +inline char * B (char *s, const char *t) +{ return ::strcpy (s, t); } + +class C { int D (void); int E; }; + +int C::D (void) +{ + A a; + try + { + char z[22]; + if (this->E) B (z, ""); + return 0; + } + catch (int &f) { return -1; } +} --- gcc/testsuite/g++.dg/opt/pr17724-6.C.jj 2004-10-02 11:27:29.000000000 +0200 +++ gcc/testsuite/g++.dg/opt/pr17724-6.C 2004-10-02 11:28:39.000000000 +0200 @@ -0,0 +1,24 @@ +// PR tree-optimization/17724 +// { dg-do compile } +// { dg-options "-O2" } + +extern char *strcpy (char* d, const char* s); + +class A { public: A (); ~A (); }; + +inline char * B (char *s, const char *t) +{ return ::strcpy (s, t); } + +class C { int D (void); int E; }; + +int C::D (void) +{ + A a; + try + { + char z[22]; + if (this->E) B (z, ""); + return 0; + } + catch (int &f) { return -1; } +} --- gcc/testsuite/g++.dg/opt/pr17724-1.C.jj 2004-10-02 11:13:45.797278812 +0200 +++ gcc/testsuite/g++.dg/opt/pr17724-1.C 2004-10-02 11:13:45.797278812 +0200 @@ -0,0 +1,23 @@ +// PR tree-optimization/17724 +// { dg-do compile } +// { dg-options "-O2" } + +namespace N { char *strcpy (char *, const char *); } +extern "C" char *strcpy (char *, const char *) throw (); +inline char *N::strcpy (char *s, const char *t) { return ::strcpy (s, t); } + +struct S { ~S (); }; +int foo (); + +int +main () +{ + S s; + int a; + char b[64]; + N::strcpy (b, "ABCDEFGHIJKLM"); + while ((a = foo ()) != -1) + if (a) + return -1; + return 0; +} --- gcc/testsuite/g++.dg/opt/pr17724-2.C.jj 2004-10-02 11:13:45.797278812 +0200 +++ gcc/testsuite/g++.dg/opt/pr17724-2.C 2004-10-02 11:13:45.797278812 +0200 @@ -0,0 +1,23 @@ +// PR tree-optimization/17724 +// { dg-do compile } +// { dg-options "-O2" } + +namespace N { char *strcpy (char *, const char *); } +extern "C" char *strcpy (char *, const char *); +inline char *N::strcpy (char *s, const char *t) { return ::strcpy (s, t); } + +struct S { ~S (); }; +int foo (); + +int +main () +{ + S s; + int a; + char b[64]; + N::strcpy (b, "ABCDEFGHIJKLM"); + while ((a = foo ()) != -1) + if (a) + return -1; + return 0; +} --- gcc/testsuite/g++.dg/opt/pr17724-3.C.jj 2004-10-02 11:27:29.650919752 +0200 +++ gcc/testsuite/g++.dg/opt/pr17724-3.C 2004-10-02 11:29:13.933389195 +0200 @@ -0,0 +1,24 @@ +// PR tree-optimization/17724 +// { dg-do compile } +// { dg-options "-O2" } + +extern "C" char *strcpy (char* d, const char* s) throw (); + +class A { public: A (); ~A (); }; + +inline char * B (char *s, const char *t) +{ return ::strcpy (s, t); } + +class C { int D (void); int E; }; + +int C::D (void) +{ + A a; + try + { + char z[22]; + if (this->E) B (z, ""); + return 0; + } + catch (int &f) { return -1; } +} --- gcc/testsuite/g++.dg/opt/pr17724-5.C.jj 2004-10-02 11:27:29.000000000 +0200 +++ gcc/testsuite/g++.dg/opt/pr17724-5.C 2004-10-02 11:29:29.275662780 +0200 @@ -0,0 +1,24 @@ +// PR tree-optimization/17724 +// { dg-do compile } +// { dg-options "-O2" } + +extern char *strcpy (char* d, const char* s) throw (); + +class A { public: A (); ~A (); }; + +inline char * B (char *s, const char *t) +{ return ::strcpy (s, t); } + +class C { int D (void); int E; }; + +int C::D (void) +{ + A a; + try + { + char z[22]; + if (this->E) B (z, ""); + return 0; + } + catch (int &f) { return -1; } +} --LSp5EJdfMPwZcMS1 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="delete-unreachable-blocks2.patch" Content-length: 5738 2004-10-07 Jakub Jelinek PR tree-optimization/17724 * tree-cfg.c (tree_purge_dead_eh_edges): Recompute dominator for the EH block. (remove_phi_nodes_and_edges_for_unreachab): Recompute dominators and post-dominators for predecessors and successors. * g++.dg/opt/pr17724-1.C: New test. * g++.dg/opt/pr17724-2.C: New test. * g++.dg/opt/pr17724-3.C: New test. * g++.dg/opt/pr17724-4.C: New test. * g++.dg/opt/pr17724-5.C: New test. * g++.dg/opt/pr17724-6.C: New test. --- gcc/tree-cfg.c 2004-10-02 11:19:53.042030301 +0200 +++ gcc/tree-cfg.c 2004-10-02 23:17:12.229321933 +0200 @@ -1784,6 +1784,8 @@ remove_phi_nodes_and_edges_for_unreachable_block (basic_block bb) { tree phi; + basic_block *succs = NULL; + int nsuccs = 0; /* Since this block is no longer reachable, we can just delete all of its PHI nodes. */ @@ -1795,9 +1797,32 @@ phi = next; } + if (dom_computed[CDI_DOMINATORS]) + succs = xmalloc (sizeof (basic_block *) * EDGE_COUNT (bb->succs)); + /* Remove edges to BB's successors. */ while (EDGE_COUNT (bb->succs) > 0) - ssa_remove_edge (EDGE_SUCC (bb, 0)); + { + if (succs != NULL + && EDGE_SUCC (bb, 0)->dest != bb + && EDGE_COUNT (EDGE_SUCC (bb, 0)->dest->preds) > 1) + succs[nsuccs++] = EDGE_SUCC (bb, 0)->dest; + ssa_remove_edge (EDGE_SUCC (bb, 0)); + } + + if (succs) + { + int i; + + for (i = 0; i < nsuccs; ++i) + { + basic_block dom = recount_dominator (CDI_DOMINATORS, succs[i]); + + if (dom != get_immediate_dominator (CDI_DOMINATORS, succs[i])) + set_immediate_dominator (CDI_DOMINATORS, succs[i], dom); + } + free (succs); + } } @@ -5089,7 +5114,12 @@ { if (e->flags & EDGE_EH) { + basic_block dest = e->dest, dom; + ssa_remove_edge (e); + dom = recount_dominator (CDI_DOMINATORS, dest); + if (dom != get_immediate_dominator (CDI_DOMINATORS, dest)) + set_immediate_dominator (CDI_DOMINATORS, dest, dom); changed = true; } else --- gcc/testsuite/g++.dg/opt/pr17724-4.C.jj 2004-10-02 11:27:29.000000000 +0200 +++ gcc/testsuite/g++.dg/opt/pr17724-4.C 2004-10-02 11:29:21.803990546 +0200 @@ -0,0 +1,24 @@ +// PR tree-optimization/17724 +// { dg-do compile } +// { dg-options "-O2" } + +extern "C" char *strcpy (char* d, const char* s); + +class A { public: A (); ~A (); }; + +inline char * B (char *s, const char *t) +{ return ::strcpy (s, t); } + +class C { int D (void); int E; }; + +int C::D (void) +{ + A a; + try + { + char z[22]; + if (this->E) B (z, ""); + return 0; + } + catch (int &f) { return -1; } +} --- gcc/testsuite/g++.dg/opt/pr17724-6.C.jj 2004-10-02 11:27:29.000000000 +0200 +++ gcc/testsuite/g++.dg/opt/pr17724-6.C 2004-10-02 11:28:39.000000000 +0200 @@ -0,0 +1,24 @@ +// PR tree-optimization/17724 +// { dg-do compile } +// { dg-options "-O2" } + +extern char *strcpy (char* d, const char* s); + +class A { public: A (); ~A (); }; + +inline char * B (char *s, const char *t) +{ return ::strcpy (s, t); } + +class C { int D (void); int E; }; + +int C::D (void) +{ + A a; + try + { + char z[22]; + if (this->E) B (z, ""); + return 0; + } + catch (int &f) { return -1; } +} --- gcc/testsuite/g++.dg/opt/pr17724-1.C.jj 2004-10-02 11:13:45.797278812 +0200 +++ gcc/testsuite/g++.dg/opt/pr17724-1.C 2004-10-02 11:13:45.797278812 +0200 @@ -0,0 +1,23 @@ +// PR tree-optimization/17724 +// { dg-do compile } +// { dg-options "-O2" } + +namespace N { char *strcpy (char *, const char *); } +extern "C" char *strcpy (char *, const char *) throw (); +inline char *N::strcpy (char *s, const char *t) { return ::strcpy (s, t); } + +struct S { ~S (); }; +int foo (); + +int +main () +{ + S s; + int a; + char b[64]; + N::strcpy (b, "ABCDEFGHIJKLM"); + while ((a = foo ()) != -1) + if (a) + return -1; + return 0; +} --- gcc/testsuite/g++.dg/opt/pr17724-2.C.jj 2004-10-02 11:13:45.797278812 +0200 +++ gcc/testsuite/g++.dg/opt/pr17724-2.C 2004-10-02 11:13:45.797278812 +0200 @@ -0,0 +1,23 @@ +// PR tree-optimization/17724 +// { dg-do compile } +// { dg-options "-O2" } + +namespace N { char *strcpy (char *, const char *); } +extern "C" char *strcpy (char *, const char *); +inline char *N::strcpy (char *s, const char *t) { return ::strcpy (s, t); } + +struct S { ~S (); }; +int foo (); + +int +main () +{ + S s; + int a; + char b[64]; + N::strcpy (b, "ABCDEFGHIJKLM"); + while ((a = foo ()) != -1) + if (a) + return -1; + return 0; +} --- gcc/testsuite/g++.dg/opt/pr17724-3.C.jj 2004-10-02 11:27:29.650919752 +0200 +++ gcc/testsuite/g++.dg/opt/pr17724-3.C 2004-10-02 11:29:13.933389195 +0200 @@ -0,0 +1,24 @@ +// PR tree-optimization/17724 +// { dg-do compile } +// { dg-options "-O2" } + +extern "C" char *strcpy (char* d, const char* s) throw (); + +class A { public: A (); ~A (); }; + +inline char * B (char *s, const char *t) +{ return ::strcpy (s, t); } + +class C { int D (void); int E; }; + +int C::D (void) +{ + A a; + try + { + char z[22]; + if (this->E) B (z, ""); + return 0; + } + catch (int &f) { return -1; } +} --- gcc/testsuite/g++.dg/opt/pr17724-5.C.jj 2004-10-02 11:27:29.000000000 +0200 +++ gcc/testsuite/g++.dg/opt/pr17724-5.C 2004-10-02 11:29:29.275662780 +0200 @@ -0,0 +1,24 @@ +// PR tree-optimization/17724 +// { dg-do compile } +// { dg-options "-O2" } + +extern char *strcpy (char* d, const char* s) throw (); + +class A { public: A (); ~A (); }; + +inline char * B (char *s, const char *t) +{ return ::strcpy (s, t); } + +class C { int D (void); int E; }; + +int C::D (void) +{ + A a; + try + { + char z[22]; + if (this->E) B (z, ""); + return 0; + } + catch (int &f) { return -1; } +} --LSp5EJdfMPwZcMS1 Content-Type: text/plain; charset=us-ascii Content-Disposition: attachment; filename="delete-unreachable-blocks3.patch" Content-length: 7084 2004-10-07 Jakub Jelinek PR tree-optimization/17724 * tree-cfg.c (tree_purge_dead_eh_edges): Recompute dominator for the EH block. (cleanup_tree_cfg): Remove unnecessary retval initialization. * cfgcleanup.c (delete_unreachable_blocks): Recompute dominators and post-dominators for predecessors and successors of deleted unreachable basic blocks. * g++.dg/opt/pr17724-1.C: New test. * g++.dg/opt/pr17724-2.C: New test. * g++.dg/opt/pr17724-3.C: New test. * g++.dg/opt/pr17724-4.C: New test. * g++.dg/opt/pr17724-5.C: New test. * g++.dg/opt/pr17724-6.C: New test. --- gcc/cfgcleanup.c.jj 2004-09-28 04:19:43.000000000 -0400 +++ gcc/cfgcleanup.c 2004-10-07 12:30:11.000000000 -0400 @@ -2029,9 +2029,18 @@ delete_unreachable_blocks (void) { bool changed = false; basic_block b, next_bb; + basic_block *succs = NULL, *preds = NULL; + int nsuccs = 0, npreds = 0, i; + edge_iterator ei; + edge e; find_unreachable_blocks (); + if (dom_computed[CDI_DOMINATORS]) + succs = xmalloc (sizeof (basic_block *) * n_basic_blocks); + if (dom_computed[CDI_POST_DOMINATORS]) + preds = xmalloc (sizeof (basic_block *) * n_basic_blocks); + /* Delete all unreachable basic blocks. */ for (b = ENTRY_BLOCK_PTR->next_bb; b != EXIT_BLOCK_PTR; b = next_bb) @@ -2040,6 +2049,22 @@ delete_unreachable_blocks (void) if (!(b->flags & BB_REACHABLE)) { + if (succs) + FOR_EACH_EDGE (e, ei, b->succs) + if ((e->dest->flags & (BB_REACHABLE | BB_VISITED)) + == BB_REACHABLE) + { + succs[nsuccs++] = e->dest; + e->dest->flags |= BB_VISITED; + } + if (preds) + FOR_EACH_EDGE (e, ei, b->preds) + if ((e->src->flags & (BB_REACHABLE | BB_VISITED)) + == BB_REACHABLE) + { + preds[npreds++] = e->src; + e->src->flags |= BB_VISITED; + } delete_basic_block (b); changed = true; } @@ -2047,6 +2072,33 @@ delete_unreachable_blocks (void) if (changed) tidy_fallthru_edges (); + + if (succs) + { + for (i = 0; i < nsuccs; ++i) + { + basic_block dom = recount_dominator (CDI_DOMINATORS, succs[i]); + + succs[i]->flags &= ~BB_VISITED; + if (dom != get_immediate_dominator (CDI_DOMINATORS, succs[i])) + set_immediate_dominator (CDI_DOMINATORS, succs[i], dom); + } + free (succs); + } + + if (preds) + { + for (i = 0; i < npreds; ++i) + { + basic_block dom = recount_dominator (CDI_POST_DOMINATORS, preds[i]); + + preds[i]->flags &= ~BB_VISITED; + if (dom != get_immediate_dominator (CDI_POST_DOMINATORS, preds[i])) + set_immediate_dominator (CDI_POST_DOMINATORS, preds[i], dom); + } + free (preds); + } + return changed; } --- gcc/tree-cfg.c.jj 2004-10-02 04:46:07.000000000 -0400 +++ gcc/tree-cfg.c 2004-10-07 12:28:44.000000000 -0400 @@ -5089,7 +5089,12 @@ tree_purge_dead_eh_edges (basic_block bb { if (e->flags & EDGE_EH) { + basic_block dest = e->dest, dom; + ssa_remove_edge (e); + dom = recount_dominator (CDI_DOMINATORS, dest); + if (dom != get_immediate_dominator (CDI_DOMINATORS, dest)) + set_immediate_dominator (CDI_DOMINATORS, dest, dom); changed = true; } else --- gcc/testsuite/g++.dg/opt/pr17724-4.C.jj 2004-10-02 11:27:29.000000000 +0200 +++ gcc/testsuite/g++.dg/opt/pr17724-4.C 2004-10-02 11:29:21.803990546 +0200 @@ -0,0 +1,24 @@ +// PR tree-optimization/17724 +// { dg-do compile } +// { dg-options "-O2" } + +extern "C" char *strcpy (char* d, const char* s); + +class A { public: A (); ~A (); }; + +inline char * B (char *s, const char *t) +{ return ::strcpy (s, t); } + +class C { int D (void); int E; }; + +int C::D (void) +{ + A a; + try + { + char z[22]; + if (this->E) B (z, ""); + return 0; + } + catch (int &f) { return -1; } +} --- gcc/testsuite/g++.dg/opt/pr17724-6.C.jj 2004-10-02 11:27:29.000000000 +0200 +++ gcc/testsuite/g++.dg/opt/pr17724-6.C 2004-10-02 11:28:39.000000000 +0200 @@ -0,0 +1,24 @@ +// PR tree-optimization/17724 +// { dg-do compile } +// { dg-options "-O2" } + +extern char *strcpy (char* d, const char* s); + +class A { public: A (); ~A (); }; + +inline char * B (char *s, const char *t) +{ return ::strcpy (s, t); } + +class C { int D (void); int E; }; + +int C::D (void) +{ + A a; + try + { + char z[22]; + if (this->E) B (z, ""); + return 0; + } + catch (int &f) { return -1; } +} --- gcc/testsuite/g++.dg/opt/pr17724-1.C.jj 2004-10-02 11:13:45.797278812 +0200 +++ gcc/testsuite/g++.dg/opt/pr17724-1.C 2004-10-02 11:13:45.797278812 +0200 @@ -0,0 +1,23 @@ +// PR tree-optimization/17724 +// { dg-do compile } +// { dg-options "-O2" } + +namespace N { char *strcpy (char *, const char *); } +extern "C" char *strcpy (char *, const char *) throw (); +inline char *N::strcpy (char *s, const char *t) { return ::strcpy (s, t); } + +struct S { ~S (); }; +int foo (); + +int +main () +{ + S s; + int a; + char b[64]; + N::strcpy (b, "ABCDEFGHIJKLM"); + while ((a = foo ()) != -1) + if (a) + return -1; + return 0; +} --- gcc/testsuite/g++.dg/opt/pr17724-2.C.jj 2004-10-02 11:13:45.797278812 +0200 +++ gcc/testsuite/g++.dg/opt/pr17724-2.C 2004-10-02 11:13:45.797278812 +0200 @@ -0,0 +1,23 @@ +// PR tree-optimization/17724 +// { dg-do compile } +// { dg-options "-O2" } + +namespace N { char *strcpy (char *, const char *); } +extern "C" char *strcpy (char *, const char *); +inline char *N::strcpy (char *s, const char *t) { return ::strcpy (s, t); } + +struct S { ~S (); }; +int foo (); + +int +main () +{ + S s; + int a; + char b[64]; + N::strcpy (b, "ABCDEFGHIJKLM"); + while ((a = foo ()) != -1) + if (a) + return -1; + return 0; +} --- gcc/testsuite/g++.dg/opt/pr17724-3.C.jj 2004-10-02 11:27:29.650919752 +0200 +++ gcc/testsuite/g++.dg/opt/pr17724-3.C 2004-10-02 11:29:13.933389195 +0200 @@ -0,0 +1,24 @@ +// PR tree-optimization/17724 +// { dg-do compile } +// { dg-options "-O2" } + +extern "C" char *strcpy (char* d, const char* s) throw (); + +class A { public: A (); ~A (); }; + +inline char * B (char *s, const char *t) +{ return ::strcpy (s, t); } + +class C { int D (void); int E; }; + +int C::D (void) +{ + A a; + try + { + char z[22]; + if (this->E) B (z, ""); + return 0; + } + catch (int &f) { return -1; } +} --- gcc/testsuite/g++.dg/opt/pr17724-5.C.jj 2004-10-02 11:27:29.000000000 +0200 +++ gcc/testsuite/g++.dg/opt/pr17724-5.C 2004-10-02 11:29:29.275662780 +0200 @@ -0,0 +1,24 @@ +// PR tree-optimization/17724 +// { dg-do compile } +// { dg-options "-O2" } + +extern char *strcpy (char* d, const char* s) throw (); + +class A { public: A (); ~A (); }; + +inline char * B (char *s, const char *t) +{ return ::strcpy (s, t); } + +class C { int D (void); int E; }; + +int C::D (void) +{ + A a; + try + { + char z[22]; + if (this->E) B (z, ""); + return 0; + } + catch (int &f) { return -1; } +} --LSp5EJdfMPwZcMS1--