From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 5331 invoked by alias); 2 Sep 2014 14:57:11 -0000 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org Received: (qmail 5292 invoked by uid 48); 2 Sep 2014 14:57:07 -0000 From: "david.d.kretzmer at gmail dot com" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/63139] New: Class-scope typedef overwrites typedef of previously defined class Date: Tue, 02 Sep 2014 14:57:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: new X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Version: 4.9.1 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: david.d.kretzmer at gmail dot com X-Bugzilla-Status: UNCONFIRMED X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: bug_id short_desc product version bug_status bug_severity priority component assigned_to reporter Message-ID: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-SW-Source: 2014-09/txt/msg00854.txt.bz2 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=3D63139 Bug ID: 63139 Summary: Class-scope typedef overwrites typedef of previously defined class Product: gcc Version: 4.9.1 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ Assignee: unassigned at gcc dot gnu.org Reporter: david.d.kretzmer at gmail dot com In GCC 4.8 and 4.9 (4.7 seems to work correctly) a type alias inside a class seems to overwrite under certain conditions a type alias of the same name i= n a previously defined class. Code to reproduce this bug: ------------------------------------------------------------ #include template struct type_list {}; template struct make_type_list { using type =3D type_list; }; // The bug disappears if you use make_type_list directly. template using make_type_list_t =3D typename make_type_list::type; struct ContainerEndA {}; template struct ContainerA { using type =3D make_type_list_t; }; struct ContainerEndB {}; //template // If you use this line ins= tead of the next a Internal compiler error is generated. template struct ContainerB { using type =3D make_type_list_t; }; int main() { // To see the types in ContainerA<>::type uncomment the following line. // //ContainerA<>::type::doesnt_exist;=20 // // GCC error: =E2=80=98doesnt_exist=E2=80=99 is not a member of =E2=80= =98ContainerA<>::type {aka type_list}=E2=80=99. // So according to GCC ContainerA<>::type contains ContainerEndB, but it clearly contains only ContainerEndB! static_assert( // It doesn't matter which types you use to instantiate ContainerA = and ContainerB std::is_same::type, ContainerB::type>::value, "This assert doesn't fail but it clearly should!" ); } ------------------------------------------------------------ I have tried to minimize the code further but any time I remove something t= he bug disappears. >>From gcc-bugs-return-461021-listarch-gcc-bugs=gcc.gnu.org@gcc.gnu.org Tue Sep 02 15:08:57 2014 Return-Path: Delivered-To: listarch-gcc-bugs@gcc.gnu.org Received: (qmail 24632 invoked by alias); 2 Sep 2014 15:08:57 -0000 Mailing-List: contact gcc-bugs-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-bugs-owner@gcc.gnu.org Delivered-To: mailing list gcc-bugs@gcc.gnu.org Received: (qmail 24082 invoked by uid 48); 2 Sep 2014 15:08:49 -0000 From: "jakub at gcc dot gnu.org" To: gcc-bugs@gcc.gnu.org Subject: [Bug c++/62306] [4.9/5 Regression?] Change in the comdat used for constructors Date: Tue, 02 Sep 2014 15:08:00 -0000 X-Bugzilla-Reason: CC X-Bugzilla-Type: changed X-Bugzilla-Watch-Reason: None X-Bugzilla-Product: gcc X-Bugzilla-Component: c++ X-Bugzilla-Version: 5.0 X-Bugzilla-Keywords: X-Bugzilla-Severity: normal X-Bugzilla-Who: jakub at gcc dot gnu.org X-Bugzilla-Status: NEW X-Bugzilla-Priority: P3 X-Bugzilla-Assigned-To: unassigned at gcc dot gnu.org X-Bugzilla-Target-Milestone: --- X-Bugzilla-Flags: X-Bugzilla-Changed-Fields: Message-ID: In-Reply-To: References: Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: 7bit X-Bugzilla-URL: http://gcc.gnu.org/bugzilla/ Auto-Submitted: auto-generated MIME-Version: 1.0 X-SW-Source: 2014-09/txt/msg00855.txt.bz2 Content-length: 10990 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=62306 --- Comment #3 from Jakub Jelinek --- I don't remember, but IRC log does something: IRC #gcc on oftc Dec 1 2009 jason: so, I have a patch to handle the implicit cdtors in extern template class by exporting the cdtors at the explicit instantiation side and never emit them at the side with just extern template class jason: which cures the dtor either D[012], or none of them check for virtual dtors I would only do that for virtual dtors jason: unfortunately it is probably an incompatible ABI change, given that we weren't previously exporting them all at the point of explicit instantiation mm true jason: with the patch a few libstdc++ tests fail, because _ZNSt15basic_stringbufIcSt11char_traitsIcESaIcEED2Ev is not exported from libstdc++.so.6 that's with an old libstdc++? jason: while we could export it now, similar issue could be with other C++ shared libraries - compiled with older g++ they wouldn't export some dtors that new g++ compiled code would now expect in it right jason: that is with new libstdc++, which has now those dtors emitted, but hidden by the linker script so, I don't think that's worth doing jason: as I wrote, in the libstdc++ case we could export them at GLIBCXX_3.4.14 jason: so, can I change the patch not to emit *D0* deleting dtor in the *D5* group then? jason: or do you see other options? what's the problem with just emitting them as needed like we do now? jason: if the *D5* comdat group is emitted sometimes with all of *D[012]* and sometimes with just *D[12]* (and perhaps sometimes with just *D0* symbols in it emit them as needed outside of any comdat group? jason: then the linker will pick just one of the *D5* comdat groups, and depending on which symbols that group has, it will either allow stuff to be linked or not the D5 comdat group should always be emitted with all of D[012]. that's separate from what we export from libstdc++ (D[012] or D[12] depending on whether or not D0 exists) jason: if it is a requirement that we always emit all of D[012] if dtor is virtual, then we'll just emit bloat why? jason: because we don't need the D0 anywhere I see jason: say we have libfoo.so which contains extern template class S<5>; template class S<5>; where S has trivial virtual dtor jason: that library will likely have D[012] emitted jason: then in some other DSO we just use extern template class S<5>;, current g++ (unfortunately) will emit D[12] when those are referenced by the code jason: if we need D[012] in D5 comdat group, it would mean we have to also emit *D0* in that other DSO but D0 is just two calls and we won't emit anything if inlining is on oddly, the ABI doesn't seem to say anything about explicit instantiation jason: true, D0 is just two calls jason: it is not true that we don't emit anything if inlining is on, the inliner apparently doesn't inline in many cases when it thinks the caller is cold ah jason: plus, I have no idea how to teach cgraph etc. that it should either emit all of D[012], or none of them jason: this is quite different case than the same body aliases, in this case it is two different functions jason: that's going to be quite non-trivial especially on the lto side :( My thinking was that the ABI change should also support implementations that implement D0 as another entry point into the destructor jason: I understand that reason (though I think the 2 calls solution is far more likely, as D0 is really D1 plus delete) jason: I'm just saying that it has a lot of issues jason: perhaps we could avoid doing the same body optimization (== use D5 group at all) when 1) DECL_ONE_ONLY 2) the virtual dtor is trivial 3) extern template class was seen jason: at least as a short term solution, to at least optimize all the other cases jakub: I suppose that's ok as a short term solution s/trivial/implicitly defined/ what do we do for user-defined inline [cd]tors? jason: those are either inlined successfully, or external symbol references so we handle synthesized methods differently from user inlines? oops they ought to work the same jason: the problem is that do_type_instantiation ignores FUNCTION_DECLs with !DECL_TEMPLATE_INSTANTIATION and that's the case for artificial methods jason: let me post the patch jason: pt.c patch with description posted jason: is there a way to check for the extern template class seen? DECL_EXPLICIT_INSTANTIATION && DECL_REALLY_EXTERN or CLASSTYPE_ jason: these synthetized methods never have any DECL_TEMPLATE_USE non-zero right, would need to check CLASSTYPE_ jason: CLASSTYPE_EXPLICIT_INSTANTIATION (DECL_CONTEXT ()) will also trigger for just template class XXX; without any extern jason: though perhaps it is valid to use just template class XXX; on one side and extern template class XXX; ont eh other side ah, right, you want CLASSTYPE_INTERFACE_ONLY as well actually, probably not, because then in the same library we would mix D5 comdat group and D0/D1/D2 groups jason: so, do you think: @@ -291,7 +291,16 @@ maybe_clone_body (tree fn) && DECL_INTERFACE_KNOWN (fns[0]) && (SUPPORTS_ONE_ONLY || !DECL_WEAK (fns[0])) && (!DECL_ONE_ONLY (fns[0]) - || (HAVE_COMDAT_GROUP && DECL_WEAK (fns[0]))) + || (HAVE_COMDAT_GROUP + && DECL_WEAK (fns[0]) + /* Don't optimize synthetized virtual dtors of + explicitly instantiated classes, because then + the deleting and other dtors are emitted when needed + and so it is not certain we would emit both + deleting and complete/base dtors in the comdat group. */ + && (fns[2] == NULL + || !CLASSTYPE_EXPLICIT_INSTANTIATION (DECL_CONTEXT (fn)) + || !DECL_ARTIFICIAL (fn)))) && cgraph_same_body_alias (clone, fns[0])) { alias = true; would be ok? It works on the cplx.ii testcase at least jakub: hmm...if we have a 'template class ...' without an 'extern template class...' I think that would mean emitting D5 in one .o and D[12] comdats in another jason: I believe we'll use D[012] comdats in both cases, let me check that patch I mean if one object has and explicit instation, and another has none s/and/an/ jason: other has implicit one you mean? right jason: true :( jason: so that would mean not optimizing any synthetized virtual dtors, right? jason: perhaps they aren't so common or accepting the bloat, or leaving D0 out of D5 jason: accepting the bloat means spending a few days in cgraph trying to teach it to do this, so nothing I'd love to do right now jason: leaving D0 out of D5 would be easiest, but would perhaps be a problem for other implementations - && !DECL_ONE_ONLY (fns[0]) + && (SUPPORTS_ONE_ONLY || !DECL_WEAK (fns[0])) + && (!DECL_ONE_ONLY (fns[0]) + || (HAVE_COMDAT_GROUP + && DECL_WEAK (fns[0]) + /* Don't optimize synthetized virtual dtors, because then + the deleting and other dtors are emitted when needed + and so it is not certain we would emit both + deleting and complete/base dtors in the comdat group. */ + && (fns[2] == NULL || !DECL_ARTIFICIAL (fn)))) jason: I guess both "accepting the bloat" and leaving D0 out of D5 are irreversible decisions right jason: while this one would allow us to think about it some more yep so let's go ahead with this one for now jason: ok, I'll test that right now (with the checking patch applied on top of it of course) jason: perhaps this change will also make the gnu.ver changes unnecessary, let me check that jason: libstdc++.so.6 size grows with that change compared to the posted patch by 128 bytes, that would be acceptable jason: and gnu.ver change is really unnecessary in that case It may be masked for GCC because we use weak comdat symbols. Why do we even do that? jakub: Interestingly, armcc just puts both in the C1 comdat group. AREA ||i._ZN1XC1Ev||, COMGROUP=_ZN1XC1Ev, CODE, READONLY, ALIGN=2 _ZN1XC2Ev ; Alternate entry point _ZN1XC1Ev PROC And I can produce all sorts of COMDAT-related link errors without any trouble :-( * drow gets it now, switches back to email. Thanks. drow: the [CD]5 comdat group names was something that was discussed on cxx-abi ml Oh. Well then. I should obviously shut up as you're still several steps ahead of me. drow: it was Jason who discussed it there; anyway, if the mixing of .o files would be very common, it might be a reason to consider some linker extension to allow to say that this SHT_GROUP obsoletes a list of other SHT_GROUP comdat groups drow: but I believe the usual case is that the whole shared library or executable is compiled with the same compiler Yeah. I'm reading the cxx-abi-dev archives to see how this fits together and the consensus seems to be 'it's wildly broken' :-) We have a case to consider that I suspect icc does too; GCC used to build libstdc++ and some system libraries, realview or icc used to build the application. But I don't expect a lot of this sort of problem from that scenario drow: sure, this should have been talked about many years ago drow: well, if you build shared libraries with one compiler and binary with another one, it is not a problem, only if you link *.a libs into the binary or shared libraries drow: that happens from time to time as well, but icc has always an option to do the same as gcc (perhaps under some option) and even if it doesn't, it is just some bloat drow: emitting the complete and base dtors or ctors as aliases doesn't only save .text space, but e.g. allows you to say store &&label in ctor or dtor static variables which is not possible if the ctor or dtor has two different bodies, but the static vars in it are obviously shared jakub: Dare I ask... what happens if a constructor has a static var, anyway? Do the in-charge and not-in-charge versions get the same variable? I don't remember the ABI mandating naming.