cppfront icon indicating copy to clipboard operation
cppfront copied to clipboard

[BUG] `@copyable` type with `this` member isn't `std::copyable`

Open JohelEGP opened this issue 2 years ago • 1 comments

Title: @copyable with this member isn't std::copyable.

Description:

@copyable is documented as https://github.com/hsutter/cppfront/blob/083c8a0d48df3d3d0d768b9a8b7ab2d26b98b515/source/reflect.h2#L704

But it's implemented as https://github.com/hsutter/cppfront/blob/083c8a0d48df3d3d0d768b9a8b7ab2d26b98b515/source/reflect.h2#L723

So when t has a this member, only a copy constructor is generated.

Minimal reproducer (https://cpp2.godbolt.org/z/xnoEzc6GE):

sf_vertices: @basic_value type = { }
my_vertices: @basic_value type = {
  this: sf_vertices = ();
  operator=: (out this, size: i32) = _ = size;
}
tiles: type = {
  public vertices: my_vertices;
  operator=: (out this, size: i32) = vertices = size;
  private operator=: (inout this, _: i32) = vertices = my_vertices(0);
}
main: () = { }
Commands:
cppfront main.cpp2
clang++18 -std=c++23 -stdlib=libc++ -lc++abi -pedantic-errors -Wall -Wextra -Wconversion -Werror=unused-result -I . main.cpp

Expected result: An ill-formed program, or my_vertices to model std::copyable.

Actual result and error:

Cpp2 lowered to Cpp1:


//=== Cpp2 type declarations ====================================================


#include "cpp2util.h"

class sf_vertices;
class my_vertices;
  

class tiles;
  

//=== Cpp2 type definitions and function declarations ===========================

class sf_vertices {
public: sf_vertices([[maybe_unused]] sf_vertices const& that);

public: auto operator=([[maybe_unused]] sf_vertices const& that) -> sf_vertices& ;
public: sf_vertices([[maybe_unused]] sf_vertices&& that) noexcept;
public: auto operator=([[maybe_unused]] sf_vertices&& that) noexcept -> sf_vertices& ;
public: explicit sf_vertices();

};
class my_vertices: public sf_vertices {

  public: explicit my_vertices(cpp2::in<cpp2::i32> size);

public: my_vertices(my_vertices const& that);
public: explicit my_vertices();
};
class tiles {
  public: my_vertices vertices; 
  public: explicit tiles(cpp2::in<cpp2::i32> size);
  private: auto operator=([[maybe_unused]] cpp2::in<cpp2::i32> param2) -> tiles& ;

  public: tiles(tiles const&) = delete; /* No 'that' constructor, suppress copy */
  public: auto operator=(tiles const&) -> void = delete;
};
auto main() -> int;


//=== Cpp2 function definitions =================================================



sf_vertices::sf_vertices([[maybe_unused]] sf_vertices const& that){}
auto sf_vertices::operator=([[maybe_unused]] sf_vertices const& that) -> sf_vertices& {
                                return *this;}
sf_vertices::sf_vertices([[maybe_unused]] sf_vertices&& that) noexcept{}
auto sf_vertices::operator=([[maybe_unused]] sf_vertices&& that) noexcept -> sf_vertices& {
                                return *this;}
sf_vertices::sf_vertices(){}
  my_vertices::my_vertices(cpp2::in<cpp2::i32> size)
                                     : sf_vertices{  }
   { static_cast<void>(size);  }

  my_vertices::my_vertices(my_vertices const& that)
                                : sf_vertices{ static_cast<sf_vertices const&>(that) }{}
my_vertices::my_vertices()
                          : sf_vertices{  }{}

  tiles::tiles(cpp2::in<cpp2::i32> size)
                                     : vertices{ size }
   {  }
  auto tiles::operator=([[maybe_unused]] cpp2::in<cpp2::i32> param2) -> tiles&  { 
                                            vertices = my_vertices(0);
                                            return *this;
   }

auto main() -> int{}
Output:
main.cpp2:24:9: warning: definition of implicit copy assignment operator for 'my_vertices' is deprecated because it has a user-provided copy constructor [-Wdeprecated-copy-with-user-provided-copy]
   24 | public: my_vertices(my_vertices const& that);
      |         ^
main.cpp2:10:54: note: in implicit copy assignment operator for 'my_vertices' first required here
   10 |                                             vertices = my_vertices(0);
      |                                                      ^
1 warning generated.

See also:

JohelEGP avatar Oct 25 '23 02:10 JohelEGP

The same is true for the types in reflect.h2. Those use @polymorphic_base @copyable. They have a copy constructor, but not copy assignment or move operations. For compiler_services in particular, which has no this member, I suspect this is caused by the virtual destructor.

JohelEGP avatar Dec 25 '23 14:12 JohelEGP