[cfe-commits] Uninformative C++98 error when calling a ctor taking const&, where the type passed in has a deleted copy-ctor

Jeff Walden jwalden+clang at mit.edu
Fri Apr 13 16:13:51 PDT 2012


Just yesterday a few of us SpiderMonkey hackers stumbled upon the apparent C++98 oddity that binding a T temporary to a const U& (where U has a U(const T&) constructor) requires that T's copy constructor be accessible.  Here's a demonstration:

> [jwalden at wheres-wally minimal]$ cat test.cpp 
> class A
> {
>   public:
>     A() {}
> 
>   private:
>     A(const A& a)
> #ifdef DELETE_COPY_CTOR
>       = delete
> #endif
>       ;
> };
> 
> class B
> {
>   public:
>     B(const A& a) {}
> };
> 
> int main()
> {
>   B b = A();
> }

If you compile this without the =delete, you get warned that the copy constructor is inaccessible, and things still build.

> [jwalden at wheres-wally minimal]$ ~/Programs/clang-build/build/Release/bin/clang++ -Wno-c++11-extensions test.cpp 
> test.cpp:22:9: warning: C++98 requires an accessible copy constructor for class 'A' when binding a reference to a temporary; was private
>       [-Wbind-to-temporary-copy]
>   B b = A();
>         ^
> test.cpp:7:5: note: declared private here
>     A(const A& a)
>     ^
> 1 warning generated.

On the other hand, if you compile this with =delete (as SpiderMonkey's code was doing), you get an error that a deleted constructor was invoked.  But you *don't* get a warning telling you that C++98 requires the copy constructor to be accessible.

> [jwalden at wheres-wally minimal]$ ~/Programs/clang-build/build/Release/bin/clang++ -Wno-c++11-extensions -DDELETE_COPY_CTOR test.cpp 
> test.cpp:22:9: error: copying parameter of type 'A' invokes deleted constructor
>   B b = A();
>         ^~~
> test.cpp:7:5: note: function has been explicitly marked deleted here
>     A(const A& a)
>     ^
> 1 error generated.

We devised a hackaround specific to the situation where we were hitting this problem, but we didn't understand why it was happening.  Only later, when reducing it to report a bug or determine that it wasn't a bug, did we discover the C++98 oddity.  It would have been much more readily apparent what the problem was if we'd had both diagnostics.

I've attached a patch which, for this testcase at least, causes both errors to be emitted.  With it I get this:

> [jwalden at wheres-wally minimal]$ ~/Programs/clang-build/build/Release/bin/clang++ -Wno-c++11-extensions -DDELETE_COPY_CTOR test.cpp 
> test.cpp:22:9: error: copying parameter of type 'A' invokes deleted constructor
>   B b = A();
>         ^~~
> test.cpp:7:5: note: function has been explicitly marked deleted here
>     A(const A& a)
>     ^
> test.cpp:22:9: warning: C++98 requires an accessible copy constructor for class 'A' when binding a reference to a temporary; was private
>       [-Wbind-to-temporary-copy]
>   B b = A();
>         ^
> test.cpp:7:5: note: declared private here
>     A(const A& a)
>     ^
> 1 warning and 1 error generated.

Does this patch look reasonable?  I'm making pretty huge assumptions about error-toleration here, so please correct me if I'm doing something crazy.  :-)

Jeff
-------------- next part --------------
A non-text attachment was scrubbed...
Name: extra-diagnostics.diff
Type: text/x-patch
Size: 591 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/cfe-commits/attachments/20120413/7218496b/attachment.bin>


More information about the cfe-commits mailing list