From: Martin Jambor Date: Mon, 11 Oct 2010 18:45:23 +0000 (+0200) Subject: re PR middle-end/45699 (Incorrect copy constructor generated with -O) X-Git-Tag: releases/gcc-4.6.0~3618 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=3f1f0ae316e60e7d9c40e1fef5f24d92cd985a9a;p=thirdparty%2Fgcc.git re PR middle-end/45699 (Incorrect copy constructor generated with -O) 2010-10-11 Martin Jambor PR middle-end/45699 * gimple-fold.c (gimple_fold_obj_type_ref_known_binfo): Choose among thunks. * testsuite/g++.dg/torture/pr45699.C: New test. * testsuite/g++.dg/otr-fold-1.C: Adjusted. * testsuite/g++.dg/otr-fold-1.C: Likewise. From-SVN: r165327 --- diff --git a/gcc/ChangeLog b/gcc/ChangeLog index a0743bd3dce8..19016d348fe7 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,9 @@ +2010-10-11 Martin Jambor + + PR middle-end/45699 + * gimple-fold.c (gimple_fold_obj_type_ref_known_binfo): Choose among + thunks. + 2010-10-11 Ralf Wildenhues * Makefile.in ($(lang_checks_parallel)) diff --git a/gcc/gimple-fold.c b/gcc/gimple-fold.c index d412eb2a7473..ce232e609e1f 100644 --- a/gcc/gimple-fold.c +++ b/gcc/gimple-fold.c @@ -1463,7 +1463,7 @@ tree gimple_fold_obj_type_ref_known_binfo (HOST_WIDE_INT token, tree known_binfo) { HOST_WIDE_INT i; - tree v, fndecl; + tree v, fndecl, delta; v = BINFO_VIRTUALS (known_binfo); i = 0; @@ -1475,6 +1475,25 @@ gimple_fold_obj_type_ref_known_binfo (HOST_WIDE_INT token, tree known_binfo) } fndecl = TREE_VALUE (v); + delta = TREE_PURPOSE (v); + gcc_assert (host_integerp (delta, 0)); + + if (integer_nonzerop (delta)) + { + struct cgraph_node *node = cgraph_get_node (fndecl); + HOST_WIDE_INT off = tree_low_cst (delta, 0); + + if (!node) + return NULL; + for (node = node->same_body; node; node = node->next) + if (node->thunk.thunk_p && off == node->thunk.fixed_offset) + break; + if (node) + fndecl = node->decl; + else + return NULL; + } + /* When cgraph node is missing and function is not public, we cannot devirtualize. This can happen in WHOPR when the actual method ends up in other partition, because we found devirtualization diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index d49e1ee45b71..8d6d09f5ab6e 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2010-10-11 Martin Jambor + + PR middle-end/45699 + * g++.dg/torture/pr45699.C: New test. + * g++.dg/otr-fold-1.C: Adjusted. + * g++.dg/otr-fold-1.C: Likewise. + 2010-10-11 Nick Clifton * gcc.c-torture/compile/pr44197.c: Require visibility support. diff --git a/gcc/testsuite/g++.dg/otr-fold-1.C b/gcc/testsuite/g++.dg/otr-fold-1.C index cff5d072a9c5..2364730487e6 100644 --- a/gcc/testsuite/g++.dg/otr-fold-1.C +++ b/gcc/testsuite/g++.dg/otr-fold-1.C @@ -72,5 +72,5 @@ int main (int argc, char *argv[]) return 0; } -/* { dg-final { scan-tree-dump "= B::foo" "optimized" } } */ +/* { dg-final { scan-tree-dump "= B::.*foo" "optimized" } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/g++.dg/otr-fold-2.C b/gcc/testsuite/g++.dg/otr-fold-2.C index 04fbf4102682..a3cd1b5e66f2 100644 --- a/gcc/testsuite/g++.dg/otr-fold-2.C +++ b/gcc/testsuite/g++.dg/otr-fold-2.C @@ -84,5 +84,5 @@ int main (int argc, char *argv[]) return 0; } -/* { dg-final { scan-tree-dump "= B::foo" "optimized" } } */ +/* { dg-final { scan-tree-dump "= B::.*foo" "optimized" } } */ /* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/g++.dg/torture/pr45699.C b/gcc/testsuite/g++.dg/torture/pr45699.C new file mode 100644 index 000000000000..828c1ef8e579 --- /dev/null +++ b/gcc/testsuite/g++.dg/torture/pr45699.C @@ -0,0 +1,61 @@ +// { dg-do run } + +extern "C" void abort (); + +class A +{ +public: + virtual void foo () {abort();} +}; + +class B : public A +{ +public: + int z; + virtual void foo () {abort();} +}; + +class C : public A +{ +public: + void *a[32]; + unsigned long b; + long c[32]; + + virtual void foo () {abort();} +}; + +class D : public C, public B +{ +public: + D () : C(), B() + { + int i; + for (i = 0; i < 32; i++) + { + a[i] = (void *) 0; + c[i] = 0; + } + b = 0xaaaa; + } + + virtual void foo (); +}; + +void D::foo() +{ + if (b != 0xaaaa) + abort(); +} + +static inline void bar (B &b) +{ + b.foo (); +} + +int main() +{ + D d; + bar (d); + return 0; +}