clang and a class with non-copyable and non-assignable member

I am using the latest clang built from source. I am seeing this situation:

class XXX { some_non_copyable_non_assignable_member_type member; }

An object of class XXX never gets copied or assigned (it's a singleton ) and yet clang is giving an errors of the form:

error: 'operator=' is a private member of 'some_non_assignable_member_type'.

and

error: field of type 'some_non_copyable_non_assignable_member_type' has private copy constructor

My understanding of C++ is that if a member of a class is non-copyable and non-assignable and an instance of that class is never copied or assigned it is not an error even if the compiler would be creating a default copy constructor and default assignment operator when the class does not have user-defined versions.

The command line options to the clang++.exe compiler are:

-c -x c++ -O0 -g -fno-inline -Wall -pedantic -g

Do you have a complete (standalone - preprocessed) example of this behavior?

Currently it come from trying to build Boost.Test on Windows using clang for Windows built for mingw/gcc-4.8.1.

There is an execution_monitor class in execution_monitor.hpp which has as a member:

boost::scoped_ptr<detail::translate_exception_base> m_custom_translators;

The detail::translate_exception_base class, which is an abstract class, itself has as a member:

boost::scoped_ptr<translate_exception_base> m_next;

boost::scoped_ptr is the inspiration for std::unique_ptr and is non-copyable, non-asignable. An execution_monitor instance is never copied or assigned.

Building Boost.Test with clang gives errors:

Do you have a complete (standalone - preprocessed) example of this
behavior?

Currently it come from trying to build Boost.Test on Windows using clang
for Windows built for mingw/gcc-4.8.1.

There is an execution_monitor class in execution_monitor.hpp which has as
a member:

boost::scoped_ptr<detail::translate_exception_base> m_custom_translators;

The detail::translate_exception_base class, which is an abstract class,
itself has as a member:

boost::scoped_ptr<translate_exception_base> m_next;

boost::scoped_ptr is the inspiration for std::unique_ptr and is
non-copyable, non-asignable. An execution_monitor instance is never copied
or assigned.

Building Boost.Test with clang gives errors:

-------------------------------------------------

"..\..\..\boost/test/execution_monitor.hpp:59:23: error: 'operator=' is a
private member of 'boost::scoped_ptr<boost::detail::translate_exception_
>'
class BOOST_TEST_DECL translate_exception_base {
                      ^
..\..\..\boost/smart_ptr/scoped_ptr.hpp:48:18: note: declared private here
    scoped_ptr & operator=(scoped_ptr const &);
                 ^
..\..\..\boost/test/execution_monitor.hpp:59:23: note: implicit copy
assignment operator for 'boost::detail::translate_exception_base' first
required here
class BOOST_TEST_DECL translate_exception_base {
                      ^
..\..\..\boost/test/execution_monitor.hpp:59:23: error: field of type
'boost::scoped_ptr<translate_exception_base>' has private copy constructor
class BOOST_TEST_DECL translate_exception_base {
                      ^
..\..\..\boost/smart_ptr/scoped_ptr.hpp:47:5: note: declared private here
    scoped_ptr(scoped_ptr const &);
    ^
..\..\..\boost/test/execution_monitor.hpp:59:23: note: implicit copy
constructor for 'boost::detail::translate_exception_base' first required
here
class BOOST_TEST_DECL translate_exception_base {
                      ^
..\..\..\boost/test/execution_monitor.hpp:143:23: error: field of type
'boost::scoped_ptr<detail::translate_exception_base>' has private copy
constructor
class BOOST_TEST_DECL execution_monitor {
                      ^
..\..\..\boost/smart_ptr/scoped_ptr.hpp:47:5: note: declared private here
    scoped_ptr(scoped_ptr const &);
    ^"

----------------------------------------------

Gcc 4.8.1, which is used to build clang has no problem with any of this.

I can try to work up as simple a standalone example as possible which will
replicate this behavior.

Step one is just to get the preprocessed source (compile with -E) and check
that that reproduces the behavior - you can at least share that with us
then we won't have to try to get exactly the same version of boost,
whatever other system headers you have, etc.

(though it might still be something that only reproduces in windows mode,
so knowing the full underlying command line (if you're running clang
manually, you can run with -### and give us the details it prints out) can
be useful too)

Ah, I think I see what it is (perhaps we could do a better job of the
diagnostic)

BOOST_TEST_DECL can expand to declspec(dllexport) (
http://www.boost.org/doc/libs/1_40_0/boost/test/detail/config.hpp ) - which
would (perhaps only on Clang?) cause all the implicit special members, like
assignment operators, to be generated. Since it can't be generated, it
fails.

Maybe the right behavior here is to only generate those that are valid?
(one of the Windows-y guys (cc'd) will probably test out the various corner
cases with MSVC here and see what the desired behavior is)

        Do you have a complete (standalone - preprocessed) example of
        this behavior?

    Currently it come from trying to build Boost.Test on Windows using
    clang for Windows built for mingw/gcc-4.8.1.

    There is an execution_monitor class in execution_monitor.hpp which
    has as a member:

    boost::scoped_ptr<detail::__translate_exception_base>
    m_custom_translators;

    The detail::translate_exception___base class, which is an abstract
    class, itself has as a member:

    boost::scoped_ptr<translate___exception_base> m_next;

    boost::scoped_ptr is the inspiration for std::unique_ptr and is
    non-copyable, non-asignable. An execution_monitor instance is never
    copied or assigned.

    Building Boost.Test with clang gives errors:

    ------------------------------__-------------------

    "..\..\..\boost/test/__execution_monitor.hpp:59:23: error:
    'operator=' is a private member of
    'boost::scoped_ptr<boost::__detail::translate_exception___base>'
    class BOOST_TEST_DECL translate_exception_base {
                           ^
    ..\..\..\boost/smart_ptr/__scoped_ptr.hpp:48:18: note: declared
    private here
         scoped_ptr & operator=(scoped_ptr const &);
                      ^
    ..\..\..\boost/test/execution___monitor.hpp:59:23: note: implicit
    copy assignment operator for
    'boost::detail::translate___exception_base' first required here
    class BOOST_TEST_DECL translate_exception_base {
                           ^
    ..\..\..\boost/test/execution___monitor.hpp:59:23: error: field of
    type 'boost::scoped_ptr<translate___exception_base>' has private
    copy constructor
    class BOOST_TEST_DECL translate_exception_base {
                           ^
    ..\..\..\boost/smart_ptr/__scoped_ptr.hpp:47:5: note: declared
    private here
         scoped_ptr(scoped_ptr const &);
         ^
    ..\..\..\boost/test/execution___monitor.hpp:59:23: note: implicit
    copy constructor for 'boost::detail::translate___exception_base'
    first required here
    class BOOST_TEST_DECL translate_exception_base {
                           ^
    ..\..\..\boost/test/execution___monitor.hpp:143:23: error: field of
    type 'boost::scoped_ptr<detail::__translate_exception_base>' has
    private copy constructor
    class BOOST_TEST_DECL execution_monitor {
                           ^
    ..\..\..\boost/smart_ptr/__scoped_ptr.hpp:47:5: note: declared
    private here
         scoped_ptr(scoped_ptr const &);
         ^"

    ------------------------------__----------------

    Gcc 4.8.1, which is used to build clang has no problem with any of this.

    I can try to work up as simple a standalone example as possible
    which will replicate this behavior.

Step one is just to get the preprocessed source (compile with -E) and
check that that reproduces the behavior - you can at least share that
with us then we won't have to try to get exactly the same version of
boost, whatever other system headers you have, etc.

(though it might still be something that only reproduces in windows
mode, so knowing the full underlying command line (if you're running
clang manually, you can run with -### and give us the details it prints
out) can be useful too)

Ah, I think I see what it is (perhaps we could do a better job of the
diagnostic)

BOOST_TEST_DECL can expand to declspec(dllexport) (
http://www.boost.org/doc/libs/1_40_0/boost/test/detail/config.hpp ) -
which would (perhaps only on Clang?) cause all the implicit special
members, like assignment operators, to be generated. Since it can't be
generated, it fails.

I think you have the reason. Thanks !

Maybe the right behavior here is to only generate those that are valid?
(one of the Windows-y guys (cc'd) will probably test out the various
corner cases with MSVC here and see what the desired behavior is)

This is clang targeting mingw/gcc not MSVC.

BOOST_TEST_DECL for clang targeting mingw/gcc becomes '__attribute__((__visibility__("default")))'.

Surely it is a clang bug to try to generate implicit special members which are never used, whether exporting a class or not.