[config] clang on Windows and BOOST_SYMBOL_EXPORT problem
I have been recently discussing a problem regarding clang on Windows on
the clang developers mailing list, but without any final resolution yet.
This problem affects those using clang on Windows with Boost along with
exported classes. This combination occurs when testing Boost.Test but I
imagine also occurs with other Boost libraries and of course could
affect Boost end-users using clang on Windows. The problem does not
occur with clang on Linux for reasons which shall be understood in the
explanation.
The bug manifests itself in such code, compiled with clang, as:
#include
test_clang_bug.cpp:3:1: error: field of type 'boost::scoped_ptr<int>' has private copy constructor AClass { boost::scoped_ptr<int> sp_pointer; }; ^ ..\..\..\boost/smart_ptr/scoped_ptr.hpp:47:5: note: declared private here scoped_ptr(scoped_ptr const &); ^ test_clang_bug.cpp:3:1: note: implicit copy constructor for 'AClass' first required here AClass { boost::scoped_ptr<int> sp_pointer; }; ^ test_clang_bug.cpp:3:1: error: 'operator=' is a private member of 'boost::scoped_ptr<int>' AClass { boost::scoped_ptr<int> sp_pointer; }; ^ ..\..\..\boost/smart_ptr/scoped_ptr.hpp:48:18: note: declared private here scoped_ptr & operator=(scoped_ptr const &); ^ test_clang_bug.cpp:3:1: note: implicit copy assignment operator for 'AClass' first required here AClass { boost::scoped_ptr<int> sp_pointer; }; ^ 2 errors generated.
I have argued on the clang developers list that requiring C++ programmers to provide a default copy constructor for a class whose object is never meant to be copied or a default assignment operator for a class which is never meant to be assigned, even if that means private declarations in C++03 or deleted declarations in C++11, can never be a good idea and goes against the C++ standard. The clang answer has been that exporting classes is outside the C++ standard so the C++ standard rules do not apply in this case. Note again that having BOOST_SYMBOL_EXPORT become __attribute__((__visibility__("default"))) for clang on Windows targeting mingw/gcc fixes this problem for that compilation environment. In fact for gcc using mingw/gcc we do indeed use __attribute__((__visibility__("default"))) and that works fine with mingw/gcc in the exact same exporting situations. Similarly for VC++ compilation having BOOST_SYMBOL_EXPORT be __declspec(dllexport) works fine also. I have not yet been able to get from clang developer why exporting a class using __declspec(dllexport) or its equivalent __attribute__((dllexport)) works the way it does, but using __attribute__((__visibility__("default"))) gives no problems. The discussion still appears to be ongoing. Do we want to change BOOST_SYMBOL_EXPORT on clang with Windows targeting mingw/gcc to specify __attribute__((__visibility__("default"))) as we do with mingw/gcc ? It is a fairly simple change which I can make. I just wanted to bring this whole issue to the attention of Boost before I implement any change. I am of course still hoping tha clang changes the way it views the exporting situation and still think they are wrong.
On Saturday 14 February 2015 14:38:35 Edward Diener wrote:
Do we want to change BOOST_SYMBOL_EXPORT on clang with Windows targeting mingw/gcc to specify __attribute__((__visibility__("default"))) as we do with mingw/gcc ?
First, on Windows for gcc/mingw __attribute__((__dllexport__)) is used, not visibility. The way I understand it, __declspec(dllexport) (or the similar attribute) is not equivalent to __attribute__((__visibility__("default"))), even if the latter does have a sensible meaning on Windows. Exported symbols are mangled differently, and on the import side shims are generated for the imported functions (not sure if there are other consequences for classes and data, but there probably are, at least to support delayed library loading). Visibility attribute does not affect mangling nor generates anything but simply marks the symbol for the linker to be externally visible or not. This makes no sense on Windows since its linker only works with exported symbols. Note that by default all symbols are visible but certainly not exported. I suspect, if you make BOOST_SYMBOL_EXPORT to be __attribute__((__visibility__("default"))), you won't be able to link with those symbols from other libraries/applications compiled with clang or other compilers. And there is also GetProcAddress() to consider. My position on this issue is that as long as clang team aims for compatibility with MSVC, they should make clang work similarly to MSVC. If MSVC compiles that code, then it probably doesn't generate (nor export) these functions if they can't be generated. Such behavior would seem sensible to me because otherwise there would be no way to export non-copyable classes. IMHO, clang should follow.
On 2/14/2015 4:52 PM, Andrey Semashev wrote:
On Saturday 14 February 2015 14:38:35 Edward Diener wrote:
Do we want to change BOOST_SYMBOL_EXPORT on clang with Windows targeting mingw/gcc to specify __attribute__((__visibility__("default"))) as we do with mingw/gcc ?
First, on Windows for gcc/mingw __attribute__((__dllexport__)) is used, not visibility.
You are correct. It was my error in my explanation here of the situation. I did correctly point out to the clang developers that compiling with gcc/mingw using __attribute__((__dllexport__)) does compile the example I gave without errors, that compiling with VC++ using __declspec(dllexport) does compile the example I gave without errors, but that clang fails to do so using either.
The way I understand it, __declspec(dllexport) (or the similar attribute) is not equivalent to __attribute__((__visibility__("default"))), even if the latter does have a sensible meaning on Windows. Exported symbols are mangled differently, and on the import side shims are generated for the imported functions (not sure if there are other consequences for classes and data, but there probably are, at least to support delayed library loading). Visibility attribute does not affect mangling nor generates anything but simply marks the symbol for the linker to be externally visible or not. This makes no sense on Windows since its linker only works with exported symbols. Note that by default all symbols are visible but certainly not exported.
I suspect, if you make BOOST_SYMBOL_EXPORT to be __attribute__((__visibility__("default"))), you won't be able to link with those symbols from other libraries/applications compiled with clang or other compilers. And there is also GetProcAddress() to consider.
Thanks for the explanation. So we really have no way to solve this from within Boost.
My position on this issue is that as long as clang team aims for compatibility with MSVC, they should make clang work similarly to MSVC.
Actually clang only aims for compatibility with MSVC in their clang for Windows version which targets VC++. In their clang for Windows implementation which targets mingw/gcc they do aim for a certain amount of compatibility with mingw/gcc. I am using the version of clang on Windows targeting mingw/gcc. The version on Windows which targets VC++, which I have been able to build, I never use because 1) it replicates some of the VC++ preprocessor bugs breaking Boost PP and 2) It is not supported directly in Boost Build ( although I can workaround that problem ).
If MSVC compiles that code, then it probably doesn't generate (nor export) these functions if they can't be generated. Such behavior would seem sensible to me because otherwise there would be no way to export non-copyable classes. IMHO, clang should follow.
I agree with that but so far nobody at clang has continued the discussion after an initial flurry of responses. Thanks for the clarification and I apologize for the confusion reporting the issue here.
On Saturday 14 February 2015 17:53:51 Edward Diener wrote:
On 2/14/2015 4:52 PM, Andrey Semashev wrote:
My position on this issue is that as long as clang team aims for compatibility with MSVC, they should make clang work similarly to MSVC.
Actually clang only aims for compatibility with MSVC in their clang for Windows version which targets VC++. In their clang for Windows implementation which targets mingw/gcc they do aim for a certain amount of compatibility with mingw/gcc.
Hmm, I didn't know there were two clangs for Windows. Confusing... Anyway, since gcc compiles this code the same argument applies.
On 2/15/2015 3:22 AM, Andrey Semashev wrote:
On Saturday 14 February 2015 17:53:51 Edward Diener wrote:
On 2/14/2015 4:52 PM, Andrey Semashev wrote:
My position on this issue is that as long as clang team aims for compatibility with MSVC, they should make clang work similarly to MSVC.
Actually clang only aims for compatibility with MSVC in their clang for Windows version which targets VC++. In their clang for Windows implementation which targets mingw/gcc they do aim for a certain amount of compatibility with mingw/gcc.
Hmm, I didn't know there were two clangs for Windows. Confusing... Anyway, since gcc compiles this code the same argument applies.
The clang developers decided they wanted a version of clang which could replace VC++ in Visual Studio. Unfortunately to do so they have sought to replicate all VC++ bugs, including those of VC++'s broken preprocessor. I have worked with Paul on Boost PP and neither I nor he ( presumably ) are willing to find a further set of workarounds for yet a different set of VC++-like preprocessor bugs to accomodate clang for Windows targeting VC++. So I don't bother with trying to use that version of clang on Windows ( often called clang_cl ). The other clang for Windows targets mingw(64)/gcc and while it is very close to the Linux version of clang there are a few subtle differences due to the fact that it run under Windows and produces Windows dlls and exes. That's a version I can test with and which is supported in Boost and by Boost Build, and it's the version which shows the clang 'export' bug on Windows which I have brought up with the clang developers. The bug manifests itself using Boost with Boost.Test which exports the ExecutionMonitor class, which is non-copyable and non-assignable. In the past I had tried to convince the clang developers that the broken VC++ preprocessor that they are trying to replicate in the clang Windows version targeting VC++ should only manifest its brokenness when dealing with VC++ header files ( where evidently such brokenness is needed ), but should work like clang's normal C++ standard preprocessor otherwise. But they did not want to implement that AFAICS. In which case I do not believe that using that version with most Boost libraries is ever going to work. However using the clang version that targets mingw(64)/gcc on Windows should give one a very good C++ standard conforming compiler to test Boost with on Windows. This should give some explanation of the two different versions of clang on Windows. They can be distinguished in code by the fact that the clang version targeting VC++ defines the _MSC_VER macro and the version targeting mingw(64)/gcc does not define the _MSC_VER macro. Thanks for your concern here regarding Boost. I probably should not have brought up the issue of the bug here but I was thinking ( erroneously ) of finding a simple workaround in config for it until it gets officially fixed by clang.
On 2/14/2015 4:52 PM, Andrey Semashev wrote:
On Saturday 14 February 2015 14:38:35 Edward Diener wrote:
Do we want to change BOOST_SYMBOL_EXPORT on clang with Windows targeting mingw/gcc to specify __attribute__((__visibility__("default"))) as we do with mingw/gcc ?
First, on Windows for gcc/mingw __attribute__((__dllexport__)) is used, not visibility.
The way I understand it, __declspec(dllexport) (or the similar attribute) is not equivalent to __attribute__((__visibility__("default"))), even if the latter does have a sensible meaning on Windows. Exported symbols are mangled differently, and on the import side shims are generated for the imported functions (not sure if there are other consequences for classes and data, but there probably are, at least to support delayed library loading). Visibility attribute does not affect mangling nor generates anything but simply marks the symbol for the linker to be externally visible or not. This makes no sense on Windows since its linker only works with exported symbols. Note that by default all symbols are visible but certainly not exported.
I suspect, if you make BOOST_SYMBOL_EXPORT to be __attribute__((__visibility__("default"))), you won't be able to link with those symbols from other libraries/applications compiled with clang or other compilers. And there is also GetProcAddress() to consider.
My position on this issue is that as long as clang team aims for compatibility with MSVC, they should make clang work similarly to MSVC. If MSVC compiles that code, then it probably doesn't generate (nor export) these functions if they can't be generated. Such behavior would seem sensible to me because otherwise there would be no way to export non-copyable classes. IMHO, clang should follow.
After more comments on the clang developer's mailing list I have reported this bug to clang at http://llvm.org/bugs/show_bug.cgi?id=22591 after being asked to do so on the developer's mailing list.
participants (2)
-
Andrey Semashev
-
Edward Diener