Bug 47218 - [4.6 regression] C++ multiple definitions of non-virtual thunk problem
Summary: [4.6 regression] C++ multiple definitions of non-virtual thunk problem
Status: RESOLVED FIXED
Alias: None
Product: gcc
Classification: Unclassified
Component: c++ (show other bugs)
Version: 4.6.0
: P3 major
Target Milestone: 4.6.0
Assignee: Dave Korn
URL:
Keywords: link-failure
: 47116 (view as bug list)
Depends on:
Blocks: 43601
  Show dependency treegraph
 
Reported: 2011-01-07 18:11 UTC by Dave Korn
Modified: 2011-01-11 11:42 UTC (History)
2 users (show)

See Also:
Host: i686-pc-cygwin
Target: i686-pc-mingw32
Build: i686-pc-cygwin
Known to work:
Known to fail:
Last reconfirmed: 2011-01-07 21:05:02


Attachments
proposed patch (616 bytes, patch)
2011-01-09 00:47 UTC, Dave Korn
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Dave Korn 2011-01-07 18:11:31 UTC
Sometime between 2010-12-22 and rev.167484, something changed in the behaviour of the C++ compiler w.r.t the way it handles non-virtual thunks.  I have just discovered this while working on a patch for PR43601; a compiler built from trunk on the earlier date reproduces the problem described there, ending in an out-of-memory error during the final link:

Creating library file: /tmp/wx/obj-x-ming-new/lib/libwx_mswd_core-2.8.dll.a/opt/
mingw-new/lib/gcc/i686-pc-mingw32/4.6.0/../../../../i686-pc-mingw32/bin/ld: fina
l link failed: Memory exhausted
collect2: ld returned 1 exit status


... whereas a compiler built from r.167484 emits a whole lot of multiple-definition errors, and stops before trying to complete the link:

Creating library file: /tmp/wx/obj-x-ming-clean/lib/libwx_based-2.8.dll.abasedll_wfstream.o:/tmp/wx/wxWidgets-2.8.11/src/common/wfstream.cpp:407: multiple definition of `non-virtual thunk to wxFFileStream::~wxFFileStream()'
basedll_filesys.o:/tmp/wx/wxWidgets-2.8.11/src/common/filesys.cpp:697: first defined here
basedll_wfstream.o:/tmp/wx/wxWidgets-2.8.11/src/common/wfstream.cpp:407: multiple definition of `non-virtual thunk to wxFFileStream::~wxFFileStream()'
basedll_filesys.o:/tmp/wx/wxWidgets-2.8.11/src/common/filesys.cpp:697: first defined here
basedll_wfstream.o:/tmp/wx/wxWidgets-2.8.11/src/common/wfstream.cpp:407: multiple definition of `non-virtual thunk to wxFileStream::~wxFileStream()'
basedll_filesys.o:/tmp/wx/wxWidgets-2.8.11/src/common/filesys.cpp:697: first defined here
basedll_wfstream.o:/tmp/wx/wxWidgets-2.8.11/src/common/wfstream.cpp:407: multiple definition of `non-virtual thunk to wxFileStream::~wxFileStream()'
basedll_filesys.o:/tmp/wx/wxWidgets-2.8.11/src/common/filesys.cpp:697: first defined here
basedll_zipstrm.o:/tmp/wx/wxWidgets-2.8.11/src/common/zipstrm.cpp:2423: multiple definition of `non-virtual thunk to wxFFileStream::~wxFFileStream()'
basedll_filesys.o:/tmp/wx/wxWidgets-2.8.11/src/common/filesys.cpp:697: first defined here
basedll_zipstrm.o:/tmp/wx/wxWidgets-2.8.11/src/common/zipstrm.cpp:2423: multiple definition of `non-virtual thunk to wxFFileStream::~wxFFileStream()'
basedll_filesys.o:/tmp/wx/wxWidgets-2.8.11/src/common/filesys.cpp:697: first defined here
basedll_zipstrm.o:/tmp/wx/wxWidgets-2.8.11/src/common/zipstrm.cpp:2423: multiple definition of `non-virtual thunk to wxFileStream::~wxFileStream()'
basedll_filesys.o:/tmp/wx/wxWidgets-2.8.11/src/common/filesys.cpp:697: first defined here
basedll_zipstrm.o:/tmp/wx/wxWidgets-2.8.11/src/common/zipstrm.cpp:2423: multiple definition of `non-virtual thunk to wxFileStream::~wxFileStream()'
basedll_filesys.o:/tmp/wx/wxWidgets-2.8.11/src/common/filesys.cpp:697: first defined here
basedll_registry.o:/tmp/wx/wxWidgets-2.8.11/src/msw/registry.cpp:1428: multiple definition of `non-virtual thunk to wxFFileStream::~wxFFileStream()'
basedll_filesys.o:/tmp/wx/wxWidgets-2.8.11/src/common/filesys.cpp:697: first defined here
basedll_registry.o:/tmp/wx/wxWidgets-2.8.11/src/msw/registry.cpp:1428: multiple definition of `non-virtual thunk to wxFFileStream::~wxFFileStream()'
basedll_filesys.o:/tmp/wx/wxWidgets-2.8.11/src/common/filesys.cpp:697: first defined here
basedll_registry.o:/tmp/wx/wxWidgets-2.8.11/src/msw/registry.cpp:1428: multiple definition of `non-virtual thunk to wxFileStream::~wxFileStream()'
basedll_filesys.o:/tmp/wx/wxWidgets-2.8.11/src/common/filesys.cpp:697: first defined here
basedll_registry.o:/tmp/wx/wxWidgets-2.8.11/src/msw/registry.cpp:1428: multiple definition of `non-virtual thunk to wxFileStream::~wxFileStream()'
basedll_filesys.o:/tmp/wx/wxWidgets-2.8.11/src/common/filesys.cpp:697: first defined here
collect2: ld returned 1 exit status

In both cases the build was configured with a cygwin-x-mingw cross compiler using the same command line:

$ /tmp/wx/wxWidgets-2.8.11/configure --with-msw --enable-debug --enable-debug_gdb --enable-shared 2>&1 --host=i686-pc-mingw32 

More once I've diagnosed what's going on in some of the generated object files.  I've marked this major as it could easily affect a whole lot of c++ library builds, but may reduce that severity if it turns out to be something unusual that wx is doing.  However it's still a regression.
Comment 1 Dave Korn 2011-01-07 21:05:02 UTC
Yeah, confirmed that.  With the older compiler the NVT is emitted in a comdat section as you'd expect: the symbols ...

[6421](sec 2101)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000 __ZThn32_N13wxFFileStreamD1Ev
[6427](sec 2103)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000000 __ZThn32_N13wxFFileStreamD0Ev

... point to sections (note MS numbers sections from 1, objdump from zero) like so:

2100 .text$_ZThn32_N13wxFFileStreamD1Ev 0000000c  00000000  00000000  0002d368  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE, LINK_ONCE_DISCARD (COMDAT __ZThn32_N13wxFFileStreamD1Ev 6421)

2102 .text$_ZThn32_N13wxFFileStreamD0Ev 0000000c  00000000  00000000  0002d3e0  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE, LINK_ONCE_DISCARD (COMDAT __ZThn32_N13wxFFileStreamD0Ev 6427)

With the latest trunk however, the same symbols ... 

[6419](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000fa8 __ZThn32_N13wxFFileStreamD1Ev
[6423](sec  1)(fl 0x00)(ty  20)(scl   2) (nx 0) 0x00000fb2 __ZThn32_N13wxFFileStreamD0Ev

... both point to section 1: the .text section.

  0 .text         00000fd0  00000000  00000000  0001633c  2**2
                  CONTENTS, ALLOC, LOAD, RELOC, READONLY, CODE


This being replicated across all object files, no wonder we have multiple defintion errors.  It's a bug that the NVT doesn't get emitted in a comdat, I expect.

(I think I remember some kind of recent change to section handling that I saw fly past on the patches list, wonder if it could be related.)
Comment 2 Yu Simin 2011-01-08 15:12:12 UTC
*** Bug 47116 has been marked as a duplicate of this bug. ***
Comment 3 Yu Simin 2011-01-08 15:13:42 UTC
A simple test in PR47116:
http://gcc.gnu.org/bugzilla/attachment.cgi?id=22866
Comment 4 Dave Korn 2011-01-08 16:35:31 UTC
(In reply to comment #3)
> A simple test in PR47116:
> http://gcc.gnu.org/bugzilla/attachment.cgi?id=22866


Thankyou, that should make debugging it easier :)
Comment 5 Dave Korn 2011-01-08 18:06:07 UTC
Bug is caused by the change at rev 167795 applied to fix PR46667.

http://gcc.gnu.org/viewcvs?view=revision&revision=167795
Comment 6 Dave Korn 2011-01-08 19:00:25 UTC
(In reply to comment #5)
> Bug is caused by the change at rev 167795 applied to fix PR46667.
> 
> http://gcc.gnu.org/viewcvs?view=revision&revision=167795

Full details at http://gcc.gnu.org/ml/gcc-patches/2011-01/msg00446.html:

>"  It turns out that resolve_unique_function() is not called at all for the
thunk function any more, where previously it was called from
assemble_start_function called from cgraph_expand_function.  This is because
gimple_expand_cfg() isn't called for these thunk functions; they are emitted
through a call chain that looks like:

> (gdb) bt
> #0  assemble_start_function (decl=0x7fe32f00,
>     fnname=0x7fe41860 "_ZThn4_N7FooBase3BarEv")
>     at /gnu/gcc/gcc-patched/gcc/varasm.c:1524
> #1  0x007aa73c in cgraph_expand_function (node=0x7ff80c30)
>     at /gnu/gcc/gcc-patched/gcc/cgraphunit.c:1328
> #2  0x007ad210 in cgraph_optimize ()
>     at /gnu/gcc/gcc-patched/gcc/cgraphunit.c:1567
> #3  0x007ad69a in cgraph_finalize_compilation_unit ()
>     at /gnu/gcc/gcc-patched/gcc/cgraphunit.c:1031
> #4  0x004ce825 in cp_write_global_declarations ()
>     at /gnu/gcc/gcc-patched/gcc/cp/decl2.c:3974
> #5  0x0080ed6d in toplev_main (argc=14, argv=0x5079f78)
>     at /gnu/gcc/gcc-patched/gcc/toplev.c:591
> #6  0x0060699f in main (argc=Cannot access memory at address 0x0
> ) at /gnu/gcc/gcc-patched/gcc/main.c:36  "

That's the main part of it.
Comment 7 Dave Korn 2011-01-09 00:47:15 UTC
Created attachment 22932 [details]
proposed patch

Ensures thunks get a section name assigned in cgraphunit.c#assemble_thunk().  Taking this for a bootstrap/test cycle.
Comment 8 Jan Hubicka 2011-01-09 00:57:12 UTC
Consider the patch pre-approved if it passes testing.  Thanks!
Comment 9 Dave Korn 2011-01-10 00:33:35 UTC
Author: davek
Date: Mon Jan 10 00:33:32 2011
New Revision: 168624

URL: http://gcc.gnu.org/viewcvs?root=gcc&view=rev&rev=168624
Log:
gcc/ChangeLog:

	PR c++/47218
	* cgraphunit.c (assemble_thunk): Call resolve_unique_section.

gcc/testsuite/ChangeLog:

	PR c++/47218
	* g++.dg/other/pr47218-1.C: New test file.
	* g++.dg/other/pr47218.C: Likewise.
	* g++.dg/other/pr47218.h: New supporting header.


Added:
    trunk/gcc/testsuite/g++.dg/other/pr47218-1.C
    trunk/gcc/testsuite/g++.dg/other/pr47218.C
    trunk/gcc/testsuite/g++.dg/other/pr47218.h
Modified:
    trunk/gcc/ChangeLog
    trunk/gcc/cgraphunit.c
    trunk/gcc/testsuite/ChangeLog
Comment 10 Dave Korn 2011-01-10 00:53:45 UTC
Done.