Boost logo

Boost :

Subject: [boost] [config] clang on Windows and BOOST_SYMBOL_EXPORT problem
From: Edward Diener (eldiener_at_[hidden])
Date: 2015-02-14 14:38:35

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

The bug manifests itself in such code, compiled with clang, as:

#include <boost/config.hpp>
#include <boost/scoped_ptr.hpp>
AClass { boost::scoped_ptr<int> sp_pointer; };
int main() { return 0; }

On Windows for clang the BOOST_SYMBOL_EXPORT becomes
__declspec(dllexport) whereas on Linux it becomes

Clang decides with __declspec(dllexport) or its equivalent
__attribute__((dllexport)), but not with
__attribute__((__visibility__("default"))), that after generating a
default copy constructor and assignment operator for a class which has
not defined is own, even if an object of that class is never copied or
assigned, if the default copy constructor or assignment operator is
invalid the compilation is in error. Since the above class has a member
which is non-copyable and non-assignable we get errors from clang along
the lines of:

> 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.

Boost list run by bdawes at, gregod at, cpdaniel at, john at