Opened 5 years ago

Closed 5 years ago

Last modified 5 years ago

#11605 closed defect (fixed)

Unicode build is broken with mingw-gcc.3.4.5

Reported by: catalin Owned by:
Priority: high Milestone:
Component: samples Version: stable-latest
Keywords: Cc: vslavik@…
Blocked By: Blocking:
Patch: yes

Description

Compiling the Release build for the sample infinitely compiles tests.cpp

mingw32-g++.exe  -Os -O2 -DWIN32 -D__WXMSW__ -D_UNICODE -D_WINDOWS -DNOPCH

Compiling the Debug build fails because wxPG_ATTR_INLINE_HELP is not defined. I was able to compile in Debug mode by replacing the above macro with its value (wxS("InlineHelp")).

mingw32-g++.exe  -g -DWIN32 -D_DEBUG -D__WXMSW__ -D_UNICODE -D_WINDOWS -DNOPCH

I am using the wxW trunk updated a few days ago.
wxW was compiled as static libs with no compatibility settings enabled (for 2.6 or 2.8).

p.s. In the code (include/wx/propgrid/property.h) there is a comment that wxPG_ATTR_INLINE_HELP is deprecated, but there is nothing in the docs about that.

Attachments (1)

fix_O_O1_11605.patch download (961 bytes) - added by catalin 5 years ago.

Download all attachments as: .zip

Change History (13)

comment:1 Changed 5 years ago by jmsalli

  • Status changed from new to confirmed

Thanks for reporting this.

comment:2 Changed 5 years ago by JMS

  • Resolution set to fixed
  • Status changed from confirmed to closed

(In [63093]) Do not use deprecated property attribute wxPG_ATTR_INLINE_HELP (fixes #11605)

comment:3 Changed 5 years ago by catalin

  • Resolution fixed deleted
  • Status changed from closed to reopened

Hmm, my Release build still would not compile - same behavior for tests.cpp

So I looked for the differences between the two builds. It seems to be because of the optimization flags.
Using -O2 and -Os, together or separately, will not show any errors or warnings as compiling that file never ends.
But using -O or -O1 flag instead throws the following errors:

.\..\..\include\wx\wxcrt.h|494|error: call of overloaded `wxStrcoll(const wchar_t*, const wxString&)' is ambiguous|
.\..\..\include\wx\wxcrt.h|494|error: call of overloaded `wxStrcoll(const wchar_t*, const wxCStrData&)' is ambiguous|

Using -O3 or no optimization the file compiles ok.

I'm reopening this for somebody to look into it, although this is most likely unrelated to propgrid.

comment:4 Changed 5 years ago by vadz

Where is the top level call to wxStrcoll() which triggers these errors?

comment:5 Changed 5 years ago by catalin

Being reproducible in a sample I didn't copy everything here, sorry. Here goes:

mingw32-g++.exe  -O1 -DWIN32 -D__WXMSW__ -D_UNICODE -D_WINDOWS -DNOPCH  -Wall  ...
In file included from ./../../include/wx/hashmap.h:16,
                 from ./../../include/wx/wx.h:21,
                 from samples/propgrid/tests.cpp:19:
./../../include/wx/wxcrt.h: In function `int wxStrcoll_String(const wxString&, const T&) [with T = wxString]':
./../../include/wx/wxcrt.h:502:   instantiated from here
./../../include/wx/wxcrt.h:494: error: call of overloaded `wxStrcoll(const wchar_t*, const wxString&)' is ambiguous
./../../include/wx/wxcrt.h:502: note: candidates are: int wxStrcoll(const wchar_t*, const wchar_t*)
./../../include/wx/wxcrt.h:502: note:                 int wxStrcoll(const wchar_t*, const char*)
./../../include/wx/wxcrt.h:502: note:                 int wxStrcoll(const wxString&, const char*)
./../../include/wx/wxcrt.h:502: note:                 int wxStrcoll(const wxString&, const wchar_t*)
./../../include/wx/wxcrt.h:502: note:                 int wxStrcoll(const wxString&, const wxString&)
./../../include/wx/wxcrt.h: In function `int wxStrcoll_String(const wxString&, const T&) [with T = wxCStrData]':
./../../include/wx/wxcrt.h:502:   instantiated from here
./../../include/wx/wxcrt.h:494: error: call of overloaded `wxStrcoll(const wchar_t*, const wxCStrData&)' is ambiguous
./../../include/wx/wxcrt.h:502: note: candidates are: int wxStrcoll(const wchar_t*, const wchar_t*)
./../../include/wx/wxcrt.h:502: note:                 int wxStrcoll(const wchar_t*, const char*)
./../../include/wx/wxcrt.h:502: note:                 int wxStrcoll(const wxString&, const char*)
./../../include/wx/wxcrt.h:502: note:                 int wxStrcoll(const wxString&, const wchar_t*)
./../../include/wx/wxcrt.h:502: note:                 int wxStrcoll(const wxString&, const wxString&)
./../../include/wx/wxcrt.h:502: note:                 int wxStrcoll(const wxString&, const wxCStrData&)

This is all there is.

comment:6 follow-up: Changed 5 years ago by vadz

  • Cc vslavik@… added
  • Keywords sample propgrid compilation fail wxPG_ATTR_INLINE_HELP removed
  • Priority changed from normal to high
  • Summary changed from [samples, propgrid] Compilation fails on MSW using mingw-gcc.3.4.5 to Unicode build is broken with mingw-gcc.3.4.5

Sorry, I didn't realize it was reproducible in the sample.

The problem is that it's not reproducible for me, but then I use (cross)mingw32 4.2.1-sjlj and not 3.4. And at least for g++ 4, there is a well-defined wxStrcoll(const wchar_t*, const wxString&) overload defined by WX_STRCMP_FUNC at line 502 (see line 422 of this macro expansion). I have really no idea why does the compiler fail to see it :-(

There are some workarounds for g++ 3.3 bugs in the code but you clearly don't use it because otherwise the line 502 wouldn't even be compiled. So I'm completely lost... could you please try replacing the macro at line 502 with its manual expansion to see if it provides any clues?

TIA!

comment:7 in reply to: ↑ 6 Changed 5 years ago by catalin

Replying to vadz:

could you please try replacing the macro at line 502 with its manual expansion

It hurt a bit :)

I expanded WX_STRCMP_FUNC first, then WX_STR_FUNC_NO_INVERT in wxcrt.h. After that there were 28 overloads for wxStrcoll, including the 2 that were signaled as missing by the compiler.

After some "experiments" with -O and -O1 flags I've discovered the followings:

  • the overload that takes (const wchar_t*, const wxCStrData&) must be defined before the one taking (const wxString&, const wxCStrData&), otherwise the compiler seems to not find it (optimize it out?).
  • the overload that takes (const wchar_t *, const wxString&) must be defined before the one taking (const wxString&, const wxString&).

So having this after expanding the macros compiled ok with -O and -O1:

    // start of WX_STRCMP_FUNC

    // start of WX_STR_FUNC_NO_INVERT
    inline int WX_STR_DECL(wxStrcoll, const char *, const char *)
        { return WX_STR_CALL(wxCRT_StrcollA, s1, s2); }
    inline int WX_STR_DECL(wxStrcoll, const char *, const wchar_t *)
        { return WX_STR_CALL(wxStrcoll_String, wxString(s1), wxString(s2)); }
    inline int WX_STR_DECL(wxStrcoll, const char *, const wxScopedCharBuffer&)
        { return WX_STR_CALL(wxCRT_StrcollA, s1, s2.data()); }
    inline int WX_STR_DECL(wxStrcoll, const char *, const wxScopedWCharBuffer&)
        { return WX_STR_CALL(wxStrcoll_String, wxString(s1), s2.data()); }

    inline int WX_STR_DECL(wxStrcoll, const wchar_t *, const wchar_t *)
        { return WX_STR_CALL(wxCRT_StrcollW, s1, s2); }
    inline int WX_STR_DECL(wxStrcoll, const wchar_t *, const char *)
        { return WX_STR_CALL(wxStrcoll_String, wxString(s1), wxString(s2)); }
    inline int WX_STR_DECL(wxStrcoll, const wchar_t *, const wxScopedWCharBuffer&)
        { return WX_STR_CALL(wxCRT_StrcollW, s1, s2.data()); }
    inline int WX_STR_DECL(wxStrcoll, const wchar_t *, const wxScopedCharBuffer&)
        { return WX_STR_CALL(wxStrcoll_String, wxString(s1), s2.data()); }

    inline int WX_STR_DECL(wxStrcoll, const wxScopedCharBuffer&, const char *)
        { return WX_STR_CALL(wxCRT_StrcollA, s1.data(), s2); }
    inline int WX_STR_DECL(wxStrcoll, const wxScopedCharBuffer&, const wchar_t *)
        { return WX_STR_CALL(wxStrcoll_String, wxString(s1), wxString(s2)); }
    inline int WX_STR_DECL(wxStrcoll, const wxScopedCharBuffer&, const wxScopedCharBuffer&)
        { return WX_STR_CALL(wxCRT_StrcollA, s1.data(), s2.data()); }
    inline int WX_STR_DECL(wxStrcoll, const wxScopedCharBuffer&, const wxScopedWCharBuffer&)
        { return WX_STR_CALL(wxStrcoll_String, wxString(s1), wxString(s2)); }

    inline int WX_STR_DECL(wxStrcoll, const wxScopedWCharBuffer&, const wchar_t *)
        { return WX_STR_CALL(wxCRT_StrcollW, s1.data(), s2); }
    inline int WX_STR_DECL(wxStrcoll, const wxScopedWCharBuffer&, const char *)
        { return WX_STR_CALL(wxStrcoll_String, wxString(s1), wxString(s2)); }
    inline int WX_STR_DECL(wxStrcoll, const wxScopedWCharBuffer&, const wxScopedWCharBuffer&)
        { return WX_STR_CALL(wxCRT_StrcollW, s1.data(), s2.data()); }
    inline int WX_STR_DECL(wxStrcoll, const wxScopedWCharBuffer&, const wxScopedCharBuffer&)
        { return WX_STR_CALL(wxStrcoll_String, wxString(s1), wxString(s2)); }

    inline int WX_STR_DECL(wxStrcoll, const wxString&, const char*)
        { return WX_STR_CALL(wxStrcoll_String, s1, s2); }
    inline int WX_STR_DECL(wxStrcoll, const wxString&, const wchar_t*)
        { return WX_STR_CALL(wxStrcoll_String, s1, s2); }
    inline int WX_STR_DECL(wxStrcoll, const wxString&, const wxScopedCharBuffer&)
        { return WX_STR_CALL(wxStrcoll_String, s1, s2); }
    inline int WX_STR_DECL(wxStrcoll, const wxString&, const wxScopedWCharBuffer&)
        { return WX_STR_CALL(wxStrcoll_String, s1, s2); }
// declaration inserted here
inline int WX_STR_DECL(wxStrcoll, const wchar_t *, const wxString&)
    { return -WX_STR_CALL(wxStrcoll_String, s2, s1); }
    inline int WX_STR_DECL(wxStrcoll, const wxString&, const wxString&)
        { return WX_STR_CALL(wxStrcoll_String, s1, s2); }
// declaration inserted here
inline int WX_STR_DECL(wxStrcoll, const wchar_t *, const wxCStrData&)
    { return -WX_STR_CALL(wxStrcoll_String, s2.AsString(), s1); }
    inline int WX_STR_DECL(wxStrcoll, const wxString&, const wxCStrData&)
        { return WX_STR_CALL(wxStrcoll_String, s1, s2); }

    inline int WX_STR_DECL(wxStrcoll, const wxCStrData&, const char*)
        { return WX_STR_CALL(wxStrcoll_String, s1.AsString(), s2); }
    inline int WX_STR_DECL(wxStrcoll, const wxCStrData&, const wchar_t*)
        { return WX_STR_CALL(wxStrcoll_String, s1.AsString(), s2); }
    inline int WX_STR_DECL(wxStrcoll, const wxCStrData&, const wxScopedCharBuffer&)
        { return WX_STR_CALL(wxStrcoll_String, s1.AsString(), s2); }
    inline int WX_STR_DECL(wxStrcoll, const wxCStrData&, const wxScopedWCharBuffer&)
        { return WX_STR_CALL(wxStrcoll_String, s1.AsString(), s2); }
    inline int WX_STR_DECL(wxStrcoll, const wxCStrData&, const wxString&)
        { return WX_STR_CALL(wxStrcoll_String, s1.AsString(), s2); }
    inline int WX_STR_DECL(wxStrcoll, const wxCStrData&, const wxCStrData&)
        { return WX_STR_CALL(wxStrcoll_String, s1.AsString(), s2); }
    // end of WX_STR_FUNC_NO_INVERT

    // ==================

    // the rest of WX_STRCMP_FUNC
    inline int WX_STR_DECL(wxStrcoll, const char *, const wxCStrData&)
        { return -WX_STR_CALL(wxStrcoll_String, s2.AsString(), s1); }
    inline int WX_STR_DECL(wxStrcoll, const char *, const wxString&)
        { return -WX_STR_CALL(wxStrcoll_String, s2, s1); }

//    inline int WX_STR_DECL(wxStrcoll, const wchar_t *, const wxCStrData&)
//        { return -WX_STR_CALL(wxStrcoll_String, s2.AsString(), s1); }
//    inline int WX_STR_DECL(wxStrcoll, const wchar_t *, const wxString&)
//        { return -WX_STR_CALL(wxStrcoll_String, s2, s1); }

    inline int WX_STR_DECL(wxStrcoll, const wxScopedCharBuffer&, const wxCStrData&)
        { return -WX_STR_CALL(wxStrcoll_String, s2.AsString(), s1.data()); }
    inline int WX_STR_DECL(wxStrcoll, const wxScopedCharBuffer&, const wxString&)
        { return -WX_STR_CALL(wxStrcoll_String, s2, s1.data()); }

    inline int WX_STR_DECL(wxStrcoll, const wxScopedWCharBuffer&, const wxCStrData&)
        { return -WX_STR_CALL(wxStrcoll_String, s2.AsString(), s1.data()); }
    inline int WX_STR_DECL(wxStrcoll, const wxScopedWCharBuffer&, const wxString&)
        { return -WX_STR_CALL(wxStrcoll_String, s2, s1.data()); }
    // end of WX_STRCMP_FUNC

I found nothing to make the compilation end for -O2 or -Os flags, with or without errors...

comment:8 Changed 5 years ago by vadz

Thanks for taking time to test/debug this!

It really looks like a compiler bug and I'm not sure if it's worth to uglify the code (because AFAICS it won't be easy to change the order of functions) if it still doesn't help with the most common case of -O2 builds.

Unfortunately I don't know what else can we do :-( Might testing for 3.5 instead of 3.4 in wxCHECK_GCC_VERSION tests in this file help by chance?

Changed 5 years ago by catalin

comment:9 follow-up: Changed 5 years ago by catalin

  • Patch set

Replying to vadz:

It really looks like a compiler bug

Yes, looks like it...

Might testing for 3.5 instead of 3.4 in wxCHECK_GCC_VERSION tests in this file help by chance?

Yes, changing wxCHECK_GCC_VERSION to 3.5 will compile ok using -O and -O1. I attached a small patch for that.

Compiling with -O2 and -Os still loops infinitely somewhere. I don't know how to check/debug this case. If you have any ideas I can try them out.

comment:10 in reply to: ↑ 9 Changed 5 years ago by catalin

Replying to catalin:

Compiling with -O2 and -Os still loops infinitely somewhere.

No, I was wrong. It compiles ok; it just takes a log time to finish (more than 8 minutes for tests.cpp). So I must have lacked the patience before.

Just changing the gcc version check looks like is enough for this ticket.

comment:11 Changed 5 years ago by VZ

  • Resolution set to fixed
  • Status changed from reopened to closed

(In [63236]) Apply workaround for wxStrcoll() template for g++ to 3.4 too.

At least mingw32 version of g++ 3.4.5 needs the same workaround to be able to
compile wx.

Closes #11605.

comment:12 Changed 5 years ago by VZ

(In [63237]) Use a helper wxNEEDS_DECL_BEFORE_TEMPLATE symbol in wxStrcoll() workaround.

The condition for which this workaround is needed has already changed once
(see #11605) and may change again in the future as we test with more compilers
so use a symbolic name for it.

No real changes otherwise.

Note: See TracTickets for help on using tickets.