[Bug libstdc++/13631] Problems in messages
--- Comment #11 from mrsam at courier-mta dot com 2009-06-14 14:54 --- The first part of this bug can be solved by using dcgettext(). do_open() needs to save the text domain in the std::messages object, and do_get() needs to use it to invoke dgettext(). The patch appears to be straightforward. I have no idea about the second part of this bug. -- mrsam at courier-mta dot com changed: What|Removed |Added CC||mrsam at courier-mta dot com http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13631
[Bug libstdc++/13631] Problems in messages
--- Comment #12 from mrsam at courier-mta dot com 2009-06-14 17:14 --- Created an attachment (id=17994) --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=17994&action=view) Untested patch to fix the first issue Here's an untested patch to fix at least the first issue. I'll try to test it, as soon as I figure out the build system. Includes an soname bump. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13631
[Bug libstdc++/13631] Problems in messages
--- Comment #15 from mrsam at courier-mta dot com 2009-06-14 18:57 --- Although I'm the last person who'd shy away from dirty tricks, when it suits my purposes, I see none here. The catalog name received by open() needs to be stashed away somewhere, and passed as a parameter to dgettext(), by do_get(). That's the only way to eliminate the global reference, and I don't see any The only possibility I see is to define an entirely new, a replacement facet structure for std::messages, and somehow arrange newly-compiled code to bind to it, then keep both classes around. Existing code would continue to be bound to the old class, and newly-compiled code would then get bound to the new class. I'm not really familiar with the required compiler-fu that would be necessary to pull this off, though. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13631
[Bug libstdc++/13631] Problems in messages
--- Comment #16 from mrsam at courier-mta dot com 2009-06-15 11:13 --- After staring at the code for a while, I'm leaning towards thinking that this change does not really change the application ABI, so the soname bump is not needed. As far as I can tell, there are no public members of std::messages, so applications never access instances of std::messages, the only thing they do is invoke the inlined methods, which call the virtual methods. I don't think that the addition of a class member affects the instances' vtable. Applications do not construct instances of std::messages. I don't think anything gets exposed that does that, this is done by libstdc++, so as long as libstdc++ gets rebuilt using the new class definition, that's all that's needed. use_facet() does not expose any code that constructs the class, that's done elsewhere. So, without any class members being accessed, and no constructions or destructions occuring as part of the ABI, scratch the soname bump -- I don't think it's needed. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13631
[Bug libstdc++/13631] Problems in messages
--- Comment #18 from mrsam at courier-mta dot com 2009-06-15 21:53 --- Yes, the patch does add a new data member to the class. I see that this would fall under item #8 under "prohibited changes", although, as I said, AFAIK it won't actually break binary compatibility with existing applications, for the reasons I outlined. I think I see a way of doing this without changing the existing std::messages class, but it's ugly. Basically -- I think I can subclass std::messages and put the new data member into the subclass (__gnu_internal::messages?), then override all the virtual methods and find all places in libstdc++ that instantiate std::messages, and change them to instantiate __gnu_internal::messages. I was able to find two places in libstdc++ that instantiate std::messages, which would be changed to instantiate __gnu_internal::messages instead. If I missed any, the results won't be catastrophic -- I think anything that falls through the cracks would just fall back to using the existing implementation, and that can always be fixed up later. This patch would be bigger and uglier (and I'd still like my first one better), but before I try to write it up, is there any reason, that I'm missing, why this approach wouldn't work? One other detail -- anyone know which version of glibc first had libintl that implemented dgettext()? -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13631
[Bug libstdc++/13631] Problems in messages
--- Comment #23 from mrsam at courier-mta dot com 2009-06-16 03:51 --- Created an attachment (id=18004) --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=18004&action=view) Revised patch Well, this is approximately what I have in mind. Aside from the formatting style, which I can clean up, as far as I can tell no existing classes get modified. -- mrsam at courier-mta dot com changed: What|Removed |Added Attachment #17994|0 |1 is obsolete|| http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13631
[Bug libstdc++/13631] Problems in messages
--- Comment #25 from mrsam at courier-mta dot com 2009-06-16 11:07 --- Yes, but, unfortunately, I just realized that this only partially fixes the original issue. This would fix the use case where different parts of the application use different locales, and different instances of std::messages to open different message catalogs. However, the use case of two different message catalogs being opened in the same locale would still be broken, since there would still be one std::messages bound to that locale. So, the application opening a message catalog in the current locale, and a shared library opening a message catalog in the current locale in order to retrieve messages using the shared library's text domain, that's still broken here. The text domain is not really an attribute of the std::messages object, but rather an attribute of the opened catalog. Currently, do_open() always returns 0, and do_get() ignores the catalog parameter. There's the real problem. do_open() needs to return a real handle, and the text domain needs to be associated with the handle (and not saved in the messages object), and do_get() must retrieve the text domain associated with that handle, and pass it to dgettext(). This way, in this particular use case, the application and the shared library will now use different catalog handles, and there's no longer any text domain confusion. It looks to me like there's really no choice here but to wait until libstdc++ major version can be bumped, and the ABI can be changed :-(. This whole thing will have to wait for then. I tried to shoehorn this into the existing ABI, and it simply doesn't fit all the way in. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13631
[Bug libstdc++/13631] Problems in messages
--- Comment #27 from mrsam at courier-mta dot com 2009-06-16 21:54 --- I thought of that, but using a vector will not be thread safe. Although I don't believe that the C++ standard requires thread safety for std::messages, applications will definitely expect thread safety here. The underlying libintl functions are thread safe. libstdc++ does include some thread and mutex support, but it's not in the current C++ standard, AFAIK, and I'm not sure if mutexes can be used in the localization library. Using a vector does give rise to a couple of other issues, though: * Applications may rely on the libstdc++ existing implementation of ignoring the return value of open(). I don't know if breaking those applications would be permitted. * It's going to be extra-messy. Even though the only change to the class is the addition of a static class member, which should have only minimal ABI considerations, the existing do_open() code is declared in application-exportable headers (but not do_get()). I think that means that existing applications may have the existing do_open() code compiled into them, so this requires the approach in my last patch, of bundling it into the subclass. If someone can confirm that there won't be any issues with using static mutex objects in code that supports std::messages, I can try to write this patch. -- http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13631
[Bug libstdc++/13631] Problems in messages
--- Comment #29 from mrsam at courier-mta dot com 2009-06-19 00:47 --- Created an attachment (id=18022) --> (http://gcc.gnu.org/bugzilla/attachment.cgi?id=18022&action=view) Revised revised patch Here's a whack at actually keeping track of different message catalogs. It compiles, but I haven't tested it yet, I haven't yet figured out how to add a new testsuite to the source tree. Testing welcome. -- mrsam at courier-mta dot com changed: What|Removed |Added Attachment #18004|0 |1 is obsolete|| http://gcc.gnu.org/bugzilla/show_bug.cgi?id=13631
[Bug c++/34696] New: Overloaded template losing type in invoking a superclass method?
Given the following test program: #include #include class X : private std::ostringstream { public: template X &operator<<(a arg) { #if 0 std::ostringstream &o= *this; o << arg; #else std::ostringstream::operator<<(arg); #endif return *this; } using std::ostringstream::str; }; int main(int argc, char **argv) { X x; x << "foo"; std::cerr << x.str() << std::endl; } The output that I get is: $ ./t 0x4014f0 ... or some other hexadecimal pointer value. If I change the "#if 0" to "#if 1" and compile the alternate version, I get the expected results: $ ./t foo After staring at this for a while, I can't see what the difference is here. It almost looks like "std::ostringstream::operator<<(arg)" ends up invoking std::ostringstream::operator<<(void *) even though arg's type is char * (or a const char *). -- Summary: Overloaded template losing type in invoking a superclass method? Product: gcc Version: 4.1.2 Status: UNCONFIRMED Severity: normal Priority: P3 Component: c++ AssignedTo: unassigned at gcc dot gnu dot org ReportedBy: mrsam at courier-mta dot com GCC build triplet: x86_64-redhat-linux GCC host triplet: x86_64-redhat-linux GCC target triplet: x86_64-redhat-linux http://gcc.gnu.org/bugzilla/show_bug.cgi?id=34696