[cfe-dev] clang and gcc -O3 bug amongst other issues?

G M gmisocpp at gmail.com
Tue Aug 27 19:05:37 PDT 2013


Hello Everyone

The following program exhibits a few interesting things to me regarding
clang/gcc/libcxx and maybe also the C/C++ standard.
I would appreciate anyone's comments on this, particularly those of Richard
Smith who has a keen eye on much of this subject area.

* If I, take this program:.

#include <cwchar>
using namespace std;
#include <windows.h>
int main()
{
}

Then if I compile it on a platform that has Windows.h using libcxx, e.g.
svn co http://llvm.org/svn/llvm-project/libcxx/trunk /libcxx
clang++ -nostdinc++ -I/libcxx/include -std=c++11 -O3 -c wc.cpp
Then I observe compiler errors with-O3 but with -O0 or no option it
compiles without error. The same happens with g++.

The example code was actually distilled from compiling with the popular
Ninja code base FWIW.

The errors are:
-------------------------------------------
// The above program generates errors when compiled.
/* With clang:
clang++ -nostdinc++ -I/libcxx/include -std=c++11 -O3 -c wc.cpp
wc.cpp:6:23: error: call to 'wcschr' is ambiguous
    const wchar_t*p = wcschr(s, L'x');
                      ^~~~~~
c:\mingw\bin\..\lib\clang\3.4\../../../x86_64-w64-mingw32/include\wchar.h:840:34:
note: candidate function
  _CONST_RETURN wchar_t *__cdecl wcschr(const wchar_t *_Str,wchar_t _Ch);
                                 ^
/libcxx/include\cwchar:180:49: note: candidate function
inline _LIBCPP_INLINE_VISIBILITY const wchar_t* wcschr(const wchar_t* __s,
wchar_t __c) {return ::wcschr(__s, __c);}
                                                ^
1 error generated.
*/
/* With g++
++ -nostdinc++ -I/libcxx/include -std=c++11 -O3 -c wc.cpp
wc.cpp: In function 'int main()':
wc.cpp:9:37: error: call of overloaded 'wcschr(const wchar_t*&, wchar_t)'
is ambiguous
     const wchar_t*p = wcschr(s, L'x');
                                     ^
wc.cpp:9:37: note: candidates are:
In file included from /libcxx/include/iosfwd:90:0,
                 from /libcxx/include/string:435,
                 from wc.cpp:2:
c:\mingw\x86_64-w64-mingw32\include\wchar.h:840:34: note: wchar_t*
wcschr(const wchar_t*, wchar_t)
   _CONST_RETURN wchar_t *__cdecl wcschr(const wchar_t *_Str,wchar_t _Ch);
                                  ^
In file included from /libcxx/include/string:438:0,
                 from wc.cpp:2:
/libcxx/include/cwchar:181:49: note: wchar_t* std::__1::wcschr(wchar_t*,
wchar_t) <near match>
 inline _LIBCPP_INLINE_VISIBILITY       wchar_t* wcschr(      wchar_t* __s,
wchar_t __c) {return ::wcschr(__s, __c);}
                                                 ^
/libcxx/include/cwchar:181:49: note:   no known conversion for argument 1
from 'const wchar_t*' to 'wchar_t*'
/libcxx/include/cwchar:180:49: note: const wchar_t* std::__1::wcschr(const
wchar_t*, wchar_t)
 inline _LIBCPP_INLINE_VISIBILITY const wchar_t* wcschr(const wchar_t* __s,
wchar_t __c) {return ::wcschr(__s, __c);}
*/
-----------------------------------

Surprisingly (to me) both clang++ and g++ both fail and succeed in the same
circumstances with much the same error messages.
I am thinking the first problem is that this is a compiler bug in both
clang++ and g++ that -O3 should lead to compiler errors when  -O0 or no
such option compiles without error?
Any ideas on this Richard etc.?

The second "problem" is about having an error at all. Why?

Howard's initial thoughts were these:

"The function signature wcschr(const wchar_t*, wchar_t) shall be replaced
by the two declarations:
 const wchar_t* wcschr(const wchar_t* s, wchar_t c);
 wchar_t* wcschr( wchar_t* s, wchar_t c);
I.e. if you want to implement this correctly, in both C and C++, the C
header <wchar.h> has to #ifdef on __cplusplus and provide the proper wcschr
signatures in each branch of that #ifdef. If the C header doesn't do this,
the C++ header <cwchar> is left with no option that works 100% of the time
and is C++ conforming.
libc++ has a #define: _WCHAR_H_CPLUSPLUS_98_CONFORMANCE_
If this is defined, libc++ assumes <wchar.h> has accommodated us and is
giving us the right signatures. Otherwise libc++ sets up the correct
signatures.
In the case that libc++ sets up its own signatures, client code can avoid
your ambiguity by choosing the C or C++ signatures with :: or std::
qualifiers.
This design decision impacts wcschr, wcspbrk, wcsrchr, wcsstr and wmemchr.
Also in <cstring> we have _STRING_H_CPLUSPLUS_98_CONFORMANCE_ guarding
strchr, strpbrk, strrchr, memchr and strstr for the same issue.
I recommend setting (or not) _WCHAR_H_CPLUSPLUS_98_CONFORMANCE_ and
_STRING_H_CPLUSPLUS_98_CONFORMANCE_ in <__config>.
"

Does anyone else share this view and we saying windows.h can't compile
without some change to __config to handle code like this? Is that
realistic/reasonable or no other choice?
Windows.h is a pretty important header.

Is there a better/other solution than having to change something in
__config?
OriIs there a default we can pick up in some way to make things "just
work"? Is that reasonable?

My ideal goal in mentioning this beyond identifying if clang++/g++ has a
bug in compiling with optimization options, is to kick start a process that
enables the above program to compile and link without error as at sometime
in the history of computing it would have done so.

I appreciate that might not be realistic, but if it is, I'd like to
identify how it can be done and which parties should come together to make
that happen if it in fact a problem or solvable.

FWIW, I have proposed a patch to cfe-commits that just so happens to make
this situation "go away" but it wasn't intentional nor the primary goal of
the patch and I'd like to understand why this situation is what it is
before it gets lost by applying my patch as I think it's interesting and
the discussion that might improve things. I suspect my patch might just
bring Windows.h in before any using statement or something so that things
compile but I may be way of base on that. Still, it shouldn't be affected
by optimization levels in either case is my thought.

So in summary. 1. is there a compiler bug? 2. is there a way to make the
above program just work without changing __config or whatever. Does
windows.h need changing or benefit from one relating to this? Or gcc/gnu?
If there is something of merit here to be done on this subject, who can
bring this together, who?

Thanks for your help.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/cfe-dev/attachments/20130828/757f0570/attachment.html>


More information about the cfe-dev mailing list