diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 4ca093c3..08ffe54f 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -584,7 +584,7 @@ bool Converter::RecordDerivesDefault(const clang::RecordDecl *decl) { return true; } -static bool recordDerivesCopy(const clang::RecordDecl *decl) { +bool Converter::RecordDerivesCopy(const clang::RecordDecl *decl) { for (auto f : decl->fields()) { // Records that contain std::vector, std::array, std::string or anything // that is translated to Vec<>, do not derive Copy @@ -601,16 +601,17 @@ static bool recordDerivesCopy(const clang::RecordDecl *decl) { return false; } - // Records that contain function pointer do not derive Copy if (auto ptr_ty = f->getType()->getAs()) { if (ptr_ty->getPointeeType()->isFunctionType()) { - return false; + if (!FunctionPointerImplementsCopy()) { + return false; + } } } // Look recursively into fields that are RecordDecl if (auto field_record = f->getType()->getAsRecordDecl()) { - if (!recordDerivesCopy(field_record)) { + if (!RecordDerivesCopy(field_record)) { return false; } } @@ -3220,7 +3221,7 @@ Converter::GetStructAttributes(const clang::RecordDecl *decl) { std::vector struct_attrs = {}; - if (recordDerivesCopy(decl)) { + if (RecordDerivesCopy(decl)) { struct_attrs.emplace_back("Copy"); } diff --git a/cpp2rust/converter/converter.h b/cpp2rust/converter/converter.h index d96eb44c..8743067d 100644 --- a/cpp2rust/converter/converter.h +++ b/cpp2rust/converter/converter.h @@ -226,6 +226,9 @@ class Converter : public clang::RecursiveASTVisitor { virtual void ConvertFunctionToFunctionPointer(const clang::FunctionDecl *fn_decl); + // Option implements Copy + virtual bool FunctionPointerImplementsCopy() const { return true; } + virtual void ConvertPrintf(clang::CallExpr *expr); void ConvertVAArgCall(clang::CallExpr *expr); @@ -528,6 +531,8 @@ class Converter : public clang::RecursiveASTVisitor { virtual bool RecordDerivesDefault(const clang::RecordDecl *decl); + bool RecordDerivesCopy(const clang::RecordDecl *decl); + bool ShouldReplaceWithMappedBody(clang::DeclRefExpr *expr) const; std::string *rs_code_; diff --git a/cpp2rust/converter/models/converter_refcount.h b/cpp2rust/converter/models/converter_refcount.h index 23505c39..70f34018 100644 --- a/cpp2rust/converter/models/converter_refcount.h +++ b/cpp2rust/converter/models/converter_refcount.h @@ -72,6 +72,9 @@ class ConverterRefCount final : public Converter { void ConvertFunctionToFunctionPointer(const clang::FunctionDecl *fn_decl) override; + // FnPtr does not implement Copy + bool FunctionPointerImplementsCopy() const override { return false; } + bool VisitCallExpr(clang::CallExpr *expr) override; bool VisitStringLiteral(clang::StringLiteral *expr) override; diff --git a/tests/unit/out/unsafe/default_in_statics.rs b/tests/unit/out/unsafe/default_in_statics.rs index e6916de2..3b767a89 100644 --- a/tests/unit/out/unsafe/default_in_statics.rs +++ b/tests/unit/out/unsafe/default_in_statics.rs @@ -13,7 +13,7 @@ pub struct Inner { pub name: *const u8, } #[repr(C)] -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Outer { pub p1: *mut i32, pub p2: *const i32, @@ -39,7 +39,7 @@ impl Default for Outer { } } #[repr(C)] -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Foo { pub s1: *const u8, pub s2: *const u8, diff --git a/tests/unit/out/unsafe/fn_ptr_struct.rs b/tests/unit/out/unsafe/fn_ptr_struct.rs index 6e4a0466..25e2ec47 100644 --- a/tests/unit/out/unsafe/fn_ptr_struct.rs +++ b/tests/unit/out/unsafe/fn_ptr_struct.rs @@ -7,7 +7,7 @@ use std::io::{Read, Seek, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; #[repr(C)] -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Handler { pub tag: i32, pub cb: Option i32>, diff --git a/tests/unit/out/unsafe/fn_ptr_vtable.rs b/tests/unit/out/unsafe/fn_ptr_vtable.rs index 2c2a2eb9..c4cdb2a6 100644 --- a/tests/unit/out/unsafe/fn_ptr_vtable.rs +++ b/tests/unit/out/unsafe/fn_ptr_vtable.rs @@ -7,7 +7,7 @@ use std::io::{Read, Seek, Write}; use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; use std::rc::Rc; #[repr(C)] -#[derive(Clone)] +#[derive(Copy, Clone)] pub struct Vtable { pub create: Option *mut ::libc::c_void>, pub get: Option i32>,