Travis Vitek wrote:
Martin Sebor wrote:

Travis Vitek wrote:
Travis Vitek commented on STDCXX-742:
-------------------------------------

This is happening because we don't use the -qrtti=dynamiccast option. We internally use a dynamic_cast to determine if the facet is of the correct derived type, but if dynamic_cast isn't supported we use a C style cast, and that returns bad results.

This case is essentially the same as STDCXX-664. We didn't add -qrtti=dynamiccast back then, and we just worked around the issue in the test. It seems to me that we should have added the flag. Would this be a binary compatible change?

What are the thoughts on this? There was some discussion
[http://tinyurl.com/3xfdma] of enabling -qrtti=dynamiccast for the
VisualAge C++ compiler, but it petered out.
Is there any way to turn on rtti using a pragma? That way we could
enable it only for translation units that included <locale> and we
wouldn't be shoving the option down the throats of users who don't
care about named locales.

No, there is no pragma for this. Even if there were we would need to do
some hacking to get it to work. We try determine if dynamic_cast<>()
exists and is functioning correctly at configuration time. If that
config test fails, we define _RWSTD_NO_DYNAMIC_CAST. So even if we
managed to enable rtti when <locale> was included, we would need to
'fix' the _RWSTD_NO_DYNAMIC_CAST and _RWSTD_DYNAMIC_CAST macros. Ewww..

Or just add a special implementation just for XLC++. But sounds
like that's not possible anyway.


Btw., does XLC++ itself correctly handle the test case mentioned
in the thread, even without -qrtti? (It's possible to get some
simple cases to work even w/o the option but not all of them).


I'm not absolutely sure what you're asking. It sounds like you are
asking if the Standard C++ Library implementation that ships with XLC++
has this same problem.

That's exactly what I was asking, thanks.

The answer to that is no...

I wonder if it would get this right:

    struct MyMessages: std::messages<char> { };
    assert (!std::has_facet<MyMessages>(std::locale::classic ()));

If not, they probably have their own simple version of "RTTI" built
into the facet (e.g., via a virtual function) but they still can't
handle tricky cases like this one. Unfortunately, we can't even do
this much w/o breaking binary compatibility.

All in all, I'm still not sure this fairly obscure corner case is
worth the effort of adding a compiler option for. C++ locales are
used by only a small community of users, and I suspect that this
case (calling has_facet or use_facet with a facet derived from one
of the standard ones) is unlikely to come up even in their "advanced"
uses. I say we open an issue for this just for the record and keep
deferring it until we feel like adding the option or until IBM
decides to enable RTTI by default.

Martin


    $ type t.cpp
    #include <locale>
    #include <cstring>
    #include <cassert>

    template <class charT>
    void test_has_facet (const char *loc_name, const char *cname)
    {
        const std::locale loc =
            loc_name ? std::locale (loc_name) : std::locale ();

        typedef std::messages_byname<charT> ByName;

        const bool byname = loc_name
            && std::strcmp (loc_name, "C");

        const bool facet_exists = std::has_facet<ByName>(loc);

        assert (byname == facet_exists);

        try {
            // verify that use facet throws an exception only
            // for the default and "C" locales
            std::use_facet<ByName>(loc);

            assert (byname);
        }
        catch (std::exception &ex) {
            assert (!byname);
        }
    }

    template <class charT>
    void test_messages (charT, const char *cname)
    {
        // exercise has_facet and use_facet in the default locale
        test_has_facet<charT>(0, cname);

        // exercise has_facet and use_facet in locale("C")
        test_has_facet<charT>("C", cname);
    }

    int main (int, char*[])
    {
        test_messages (char (), "char");

        return 0;
    }

  $ xlC t.cpp -o t && ./t
  $

If I run the same code under stdcxx, I get the following

  $ gmake t && ./t

  <snip>

  Assertion failed: byname == facet_exists, file t.cpp, line 18
  IOT/Abort trap (core dumped)
  $

Travis


Reply via email to