diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 4ca093c3..dcf16532 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -579,6 +579,14 @@ bool Converter::RecordDerivesDefault(const clang::RecordDecl *decl) { if (f->getType()->isArrayType()) { return false; } + + // Records that contain libc types do not derive Default + if (auto record = f->getType()->getAsRecordDecl()) { + if (ctx_.getSourceManager().isInSystemHeader(record->getLocation()) && + f->getType().isPODType(ctx_)) { + return false; + } + } } return true; @@ -3162,7 +3170,8 @@ std::string Converter::GetDefaultAsStringFallback(clang::QualType qual_type) { if (auto record = qual_type->getAsRecordDecl()) { if (ctx_.getSourceManager().isInSystemHeader(record->getLocation()) && qual_type.isPODType(ctx_)) { - return std::format("std::mem::zeroed::<{}>()", ToString(qual_type)); + return std::format("unsafe {{ std::mem::zeroed::<{}>() }}", + ToString(qual_type)); } } diff --git a/tests/unit/libc_struct_without_default.cpp b/tests/unit/libc_struct_without_default.cpp index 39898cad..5b079bde 100644 --- a/tests/unit/libc_struct_without_default.cpp +++ b/tests/unit/libc_struct_without_default.cpp @@ -3,6 +3,7 @@ #include #include #include +#include #include #include #include @@ -12,6 +13,10 @@ struct UserDefined { std::vector v; }; +struct FieldIsLibcType { + struct sockaddr addr; +}; + int main() { struct pollfd p; p.fd = -1; @@ -40,5 +45,8 @@ int main() { UserDefined ud; assert(ud.a[0] == 0); assert(ud.v.size() == 0); + + FieldIsLibcType filt; + assert(filt.addr.sa_family == 0); return 0; } diff --git a/tests/unit/out/unsafe/libc_struct_without_default.rs b/tests/unit/out/unsafe/libc_struct_without_default.rs index 9b5a47d9..0de868de 100644 --- a/tests/unit/out/unsafe/libc_struct_without_default.rs +++ b/tests/unit/out/unsafe/libc_struct_without_default.rs @@ -20,34 +20,48 @@ impl Default for UserDefined { } } } +#[repr(C)] +#[derive(Copy, Clone)] +pub struct FieldIsLibcType { + pub addr: sockaddr, +} +impl Default for FieldIsLibcType { + fn default() -> Self { + FieldIsLibcType { + addr: unsafe { std::mem::zeroed::() }, + } + } +} pub fn main() { unsafe { std::process::exit(main_0() as i32); } } unsafe fn main_0() -> i32 { - let mut p: pollfd = std::mem::zeroed::(); + let mut p: pollfd = unsafe { std::mem::zeroed::() }; p.fd = -1_i32; p.events = 0_i16; p.revents = 2_i16; assert!(((p.fd) == (-1_i32))); assert!(((p.events as i32) == (0))); assert!(((p.revents as i32) == (2))); - let mut ia: in_addr = std::mem::zeroed::(); + let mut ia: in_addr = unsafe { std::mem::zeroed::() }; ia.s_addr = 1_u32; assert!(((ia.s_addr) == (1_u32))); - let mut t: tm = std::mem::zeroed::(); + let mut t: tm = unsafe { std::mem::zeroed::() }; t.tm_year = 124; t.tm_mon = 5; t.tm_mday = 15; assert!(((t.tm_year) == (124))); assert!(((t.tm_mon) == (5))); assert!(((t.tm_mday) == (15))); - let mut st: stat = std::mem::zeroed::(); + let mut st: stat = unsafe { std::mem::zeroed::() }; st.st_size = 1024_i64; assert!(((st.st_size) == (1024_i64))); let mut ud: UserDefined = ::default(); assert!(((ud.a[(0_u64) as usize]) == (0))); assert!(((ud.v.len() as u64) == (0_u64))); + let mut filt: FieldIsLibcType = ::default(); + assert!(((filt.addr.sa_family as i32) == (0))); return 0; } diff --git a/tests/unit/out/unsafe/socket_transparent_union.rs b/tests/unit/out/unsafe/socket_transparent_union.rs index a4bddaa0..f0092c8f 100644 --- a/tests/unit/out/unsafe/socket_transparent_union.rs +++ b/tests/unit/out/unsafe/socket_transparent_union.rs @@ -13,7 +13,7 @@ pub fn main() { } unsafe fn main_0() -> i32 { let mut fd: i32 = 0; - let mut ssloc: sockaddr_storage = std::mem::zeroed::(); + let mut ssloc: sockaddr_storage = unsafe { std::mem::zeroed::() }; let mut slen: u32 = (::std::mem::size_of::() as u64 as u32); assert!( ((((libc::getsockname( @@ -23,7 +23,7 @@ unsafe fn main_0() -> i32 { )) == (-1_i32)) as i32) != 0) ); - let mut sin: sockaddr_in = std::mem::zeroed::(); + let mut sin: sockaddr_in = unsafe { std::mem::zeroed::() }; let mut inlen: u32 = (::std::mem::size_of::() as u64 as u32); assert!( ((((libc::getsockname( diff --git a/tests/unit/out/unsafe/sys_stat.rs b/tests/unit/out/unsafe/sys_stat.rs index 4bfa9ef2..1f04dab3 100644 --- a/tests/unit/out/unsafe/sys_stat.rs +++ b/tests/unit/out/unsafe/sys_stat.rs @@ -18,7 +18,7 @@ pub unsafe fn test_stat_0() { fp, ); assert!(((((libc::fclose(fp)) == (0)) as i32) != 0)); - let mut st: stat = std::mem::zeroed::(); + let mut st: stat = unsafe { std::mem::zeroed::() }; assert!(((((libc::stat(path as *const i8, (&mut st as *mut stat))) == (0)) as i32) != 0)); assert!(((((st.st_size) == (5_i64)) as i32) != 0)); libc::unlink(path as *const i8); @@ -36,7 +36,7 @@ pub unsafe fn test_fstat_1() { ); libc::fflush(fp); let mut fd: i32 = libc::fileno(fp); - let mut st: stat = std::mem::zeroed::(); + let mut st: stat = unsafe { std::mem::zeroed::() }; assert!(((((libc::fstat(fd, (&mut st as *mut stat))) == (0)) as i32) != 0)); assert!(((((st.st_size) == (11_i64)) as i32) != 0)); assert!(((((libc::fclose(fp)) == (0)) as i32) != 0));