From daba927a81288057f3d85d7ae7d4a102386da91a Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 22 May 2026 15:34:02 +0100 Subject: [PATCH 1/4] Add dummy definition for referenced never-defined structs --- cpp2rust/converter/converter.cpp | 20 +++++++++- cpp2rust/converter/converter.h | 5 +++ cpp2rust/cpp2rust_lib.cpp | 3 ++ .../opaque_forward_decl/CMakeLists.txt | 3 ++ tests/multi-file/opaque_forward_decl/a.c | 12 ++++++ tests/multi-file/opaque_forward_decl/b.c | 6 +++ tests/multi-file/opaque_forward_decl/header.h | 11 ++++++ .../out/refcount/opaque_forward_decl.rs | 38 ++++++++++++++++++ .../out/unsafe/opaque_forward_decl.rs | 39 +++++++++++++++++++ 9 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 tests/multi-file/opaque_forward_decl/CMakeLists.txt create mode 100644 tests/multi-file/opaque_forward_decl/a.c create mode 100644 tests/multi-file/opaque_forward_decl/b.c create mode 100644 tests/multi-file/opaque_forward_decl/header.h create mode 100644 tests/multi-file/opaque_forward_decl/out/refcount/opaque_forward_decl.rs create mode 100644 tests/multi-file/opaque_forward_decl/out/unsafe/opaque_forward_decl.rs diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 976255ab..ef8ed8e2 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -23,6 +23,7 @@ std::unordered_set Converter::record_decls_; std::unordered_set Converter::decl_ids_; std::unordered_set Converter::globals_; std::unordered_set Converter::abstract_structs_; +std::unordered_map Converter::referenced_records_; void Converter::ConvertUniquePtrDeref(clang::CXXOperatorCallExpr *expr) { bool is_star = expr->getOperator() == clang::OverloadedOperatorKind::OO_Star; @@ -53,6 +54,19 @@ use std::rc::Rc; )"); } +std::string Converter::EmitOpaqueRecordMarkers() { + std::string out; + for (const auto &[id, name] : referenced_records_) { + if (record_decls_.contains(id)) { + continue; + } + out += "#[repr(C)] pub struct "; + out += name; + out += " { _opaque: [u8; 0] }\n"; + } + return out; +} + bool Converter::VisitRecoveryExpr(clang::RecoveryExpr *expr) { llvm::errs() << "RecoveryExpr: "; expr->dump(); @@ -160,7 +174,11 @@ bool Converter::VisitRecordType(clang::RecordType *type) { } } - StrCat(GetRecordName(decl)); + auto name = GetRecordName(decl); + StrCat(name); + if (!ctx_.getSourceManager().isInSystemHeader(decl->getLocation())) { + referenced_records_.try_emplace(GetID(decl), std::move(name)); + } Mapper::AddRuleForUserDefinedType(decl); return false; } diff --git a/cpp2rust/converter/converter.h b/cpp2rust/converter/converter.h index 07105383..9dbc3fa4 100644 --- a/cpp2rust/converter/converter.h +++ b/cpp2rust/converter/converter.h @@ -51,6 +51,10 @@ class Converter : public clang::RecursiveASTVisitor { virtual void EmitFilePreamble(); + // Returns Rust text emitting `pub struct N { _opaque: [u8; 0] }` for each + // record name referenced by some TU but never defined by any. + static std::string EmitOpaqueRecordMarkers(); + virtual bool VisitBuiltinType(clang::BuiltinType *type); virtual bool VisitRecordType(clang::RecordType *type); @@ -646,6 +650,7 @@ class Converter : public clang::RecursiveASTVisitor { static std::unordered_set decl_ids_; static std::unordered_set record_decls_; static std::unordered_set abstract_structs_; + static std::unordered_map referenced_records_; enum class ExprKind : uint8_t { Callee, diff --git a/cpp2rust/cpp2rust_lib.cpp b/cpp2rust/cpp2rust_lib.cpp index 75b2a2b7..d2b141ff 100644 --- a/cpp2rust/cpp2rust_lib.cpp +++ b/cpp2rust/cpp2rust_lib.cpp @@ -10,6 +10,7 @@ #include #include "compat/platform_flags.h" +#include "converter/converter.h" #include "frontend_action.h" namespace cpp2rust { @@ -29,6 +30,7 @@ std::string TranspileSrc(std::string_view cc_code, Model model, rules_dir), cc_code, tool_args, std::filesystem::path(filename).filename().string(), filename.ends_with(".c") ? CLANG_C_COMPILER : CLANG_CXX_COMPILER); + rs_code += Converter::EmitOpaqueRecordMarkers(); return rs_code; } @@ -68,6 +70,7 @@ std::string TranspileDir(std::string_view build_dir, Model model, std::string rs_code; FrontendActionFactory factory(rs_code, model, rules_dir); Tool.run(&factory); + rs_code += Converter::EmitOpaqueRecordMarkers(); return rs_code; } } // namespace cpp2rust diff --git a/tests/multi-file/opaque_forward_decl/CMakeLists.txt b/tests/multi-file/opaque_forward_decl/CMakeLists.txt new file mode 100644 index 00000000..c9192a90 --- /dev/null +++ b/tests/multi-file/opaque_forward_decl/CMakeLists.txt @@ -0,0 +1,3 @@ +cmake_minimum_required(VERSION 3.16) +project(opaque_forward_decl LANGUAGES C) +add_executable(app a.c b.c) diff --git a/tests/multi-file/opaque_forward_decl/a.c b/tests/multi-file/opaque_forward_decl/a.c new file mode 100644 index 00000000..18277f6f --- /dev/null +++ b/tests/multi-file/opaque_forward_decl/a.c @@ -0,0 +1,12 @@ +#include +#include + +#include "header.h" + +int main(void) { + struct container c = {NULL, 42}; + touch(&c); + assert(c.x == 42); + assert(c.p == NULL); + return 0; +} diff --git a/tests/multi-file/opaque_forward_decl/b.c b/tests/multi-file/opaque_forward_decl/b.c new file mode 100644 index 00000000..f8e3bae7 --- /dev/null +++ b/tests/multi-file/opaque_forward_decl/b.c @@ -0,0 +1,6 @@ +#include "header.h" + +void touch(struct container *c) { + /* read the opaque pointer field without dereferencing the opaque type */ + (void)c->p; +} diff --git a/tests/multi-file/opaque_forward_decl/header.h b/tests/multi-file/opaque_forward_decl/header.h new file mode 100644 index 00000000..2d5fba09 --- /dev/null +++ b/tests/multi-file/opaque_forward_decl/header.h @@ -0,0 +1,11 @@ +#pragma once + +/* Forward declaration only; no full definition exists anywhere in the build. */ +struct opaque; + +struct container { + struct opaque *p; + int x; +}; + +void touch(struct container *c); diff --git a/tests/multi-file/opaque_forward_decl/out/refcount/opaque_forward_decl.rs b/tests/multi-file/opaque_forward_decl/out/refcount/opaque_forward_decl.rs new file mode 100644 index 00000000..64e614f6 --- /dev/null +++ b/tests/multi-file/opaque_forward_decl/out/refcount/opaque_forward_decl.rs @@ -0,0 +1,38 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +#[derive(Default)] +pub struct container { + pub p: Value>, + pub x: Value, +} +impl ByteRepr for container {} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let c: Value = Rc::new(RefCell::new(container { + p: Rc::new(RefCell::new(Ptr::::null())), + x: Rc::new(RefCell::new(42)), + })); + ({ + let _c: Ptr = (c.as_pointer()); + touch_0(_c) + }); + assert!(((((*(*c.borrow()).x.borrow()) == 42) as i32) != 0)); + assert!(((((*(*c.borrow()).p.borrow()).is_null()) as i32) != 0)); + return 0; +} +pub fn touch_0(c: Ptr) { + let c: Value> = Rc::new(RefCell::new(c)); + (*(*(*c.borrow()).upgrade().deref()).p.borrow()).clone(); +} +#[repr(C)] +pub struct opaque { + _opaque: [u8; 0], +} diff --git a/tests/multi-file/opaque_forward_decl/out/unsafe/opaque_forward_decl.rs b/tests/multi-file/opaque_forward_decl/out/unsafe/opaque_forward_decl.rs new file mode 100644 index 00000000..bbea6ced --- /dev/null +++ b/tests/multi-file/opaque_forward_decl/out/unsafe/opaque_forward_decl.rs @@ -0,0 +1,39 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +#[repr(C)] +#[derive(Copy, Clone, Default)] +pub struct container { + pub p: *mut opaque, + pub x: i32, +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut c: container = container { + p: std::ptr::null_mut(), + x: 42, + }; + (unsafe { + let _c: *mut container = (&mut c as *mut container); + touch_0(_c) + }); + assert!(((((c.x) == (42)) as i32) != 0)); + assert!(((((c.p).is_null()) as i32) != 0)); + return 0; +} +pub unsafe fn touch_0(mut c: *mut container) { + &((*c).p); +} +#[repr(C)] +pub struct opaque { + _opaque: [u8; 0], +} From f46eae8c07b73a4d8b1b2f674aa075efa3736c14 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 22 May 2026 15:40:12 +0100 Subject: [PATCH 2/4] Add single-file test --- tests/unit/opaque_forward_decl.c | 15 +++++++++ .../unit/out/refcount/opaque_forward_decl.rs | 29 +++++++++++++++++ tests/unit/out/unsafe/opaque_forward_decl.rs | 31 +++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 tests/unit/opaque_forward_decl.c create mode 100644 tests/unit/out/refcount/opaque_forward_decl.rs create mode 100644 tests/unit/out/unsafe/opaque_forward_decl.rs diff --git a/tests/unit/opaque_forward_decl.c b/tests/unit/opaque_forward_decl.c new file mode 100644 index 00000000..1291ab63 --- /dev/null +++ b/tests/unit/opaque_forward_decl.c @@ -0,0 +1,15 @@ +#include + +/* Forward declaration only; no body for `opaque` anywhere in this TU. */ +struct opaque; + +struct container { + struct opaque *p; + int x; +}; + +int main(void) { + struct container c = {NULL, 42}; + (void)c.p; + return c.x - 42; +} diff --git a/tests/unit/out/refcount/opaque_forward_decl.rs b/tests/unit/out/refcount/opaque_forward_decl.rs new file mode 100644 index 00000000..90c7577d --- /dev/null +++ b/tests/unit/out/refcount/opaque_forward_decl.rs @@ -0,0 +1,29 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +#[derive(Default)] +pub struct container { + pub p: Value>, + pub x: Value, +} +impl ByteRepr for container {} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let c: Value = Rc::new(RefCell::new(container { + p: Rc::new(RefCell::new(Ptr::::null())), + x: Rc::new(RefCell::new(42)), + })); + (*(*c.borrow()).p.borrow()).clone(); + return ((*(*c.borrow()).x.borrow()) - 42); +} +#[repr(C)] +pub struct opaque { + _opaque: [u8; 0], +} diff --git a/tests/unit/out/unsafe/opaque_forward_decl.rs b/tests/unit/out/unsafe/opaque_forward_decl.rs new file mode 100644 index 00000000..17836ab1 --- /dev/null +++ b/tests/unit/out/unsafe/opaque_forward_decl.rs @@ -0,0 +1,31 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +#[repr(C)] +#[derive(Copy, Clone, Default)] +pub struct container { + pub p: *mut opaque, + pub x: i32, +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut c: container = container { + p: std::ptr::null_mut(), + x: 42, + }; + &(c.p); + return ((c.x) - (42)); +} +#[repr(C)] +pub struct opaque { + _opaque: [u8; 0], +} From 69be664e82974d142be889e0b36e607e39b7fb43 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 22 May 2026 16:34:22 +0100 Subject: [PATCH 3/4] Fix opaque then defined pattern --- cpp2rust/converter/converter.cpp | 16 +++---- cpp2rust/converter/converter.h | 34 +++++++++++++-- tests/multi-file/opaque_forward_decl/b.c | 5 +-- tests/multi-file/opaque_forward_decl/header.h | 1 - tests/unit/opaque_forward_decl.c | 1 - tests/unit/opaque_then_defined.c | 21 ++++++++++ .../unit/out/refcount/opaque_then_defined.rs | 42 +++++++++++++++++++ tests/unit/out/unsafe/opaque_then_defined.rs | 38 +++++++++++++++++ 8 files changed, 138 insertions(+), 20 deletions(-) create mode 100644 tests/unit/opaque_then_defined.c create mode 100644 tests/unit/out/refcount/opaque_then_defined.rs create mode 100644 tests/unit/out/unsafe/opaque_then_defined.rs diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index ef8ed8e2..45b915bc 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -19,11 +19,10 @@ namespace cpp2rust { std::unordered_map Converter::inner_structs_; -std::unordered_set Converter::record_decls_; std::unordered_set Converter::decl_ids_; std::unordered_set Converter::globals_; std::unordered_set Converter::abstract_structs_; -std::unordered_map Converter::referenced_records_; +Converter::RecordIndex Converter::record_decls_; void Converter::ConvertUniquePtrDeref(clang::CXXOperatorCallExpr *expr) { bool is_star = expr->getOperator() == clang::OverloadedOperatorKind::OO_Star; @@ -56,14 +55,11 @@ use std::rc::Rc; std::string Converter::EmitOpaqueRecordMarkers() { std::string out; - for (const auto &[id, name] : referenced_records_) { - if (record_decls_.contains(id)) { - continue; - } + record_decls_.ForEachUndefined([&](const std::string &name) { out += "#[repr(C)] pub struct "; out += name; out += " { _opaque: [u8; 0] }\n"; - } + }); return out; } @@ -177,7 +173,7 @@ bool Converter::VisitRecordType(clang::RecordType *type) { auto name = GetRecordName(decl); StrCat(name); if (!ctx_.getSourceManager().isInSystemHeader(decl->getLocation())) { - referenced_records_.try_emplace(GetID(decl), std::move(name)); + record_decls_.MarkReferenced(std::move(name)); } Mapper::AddRuleForUserDefinedType(decl); return false; @@ -635,7 +631,7 @@ bool Converter::VisitRecordDecl(clang::RecordDecl *decl) { return false; } - if (!record_decls_.insert(GetID(decl)).second) { + if (!record_decls_.MarkDefined(GetRecordName(decl))) { return false; } @@ -752,7 +748,7 @@ bool Converter::VisitCXXRecordDecl(clang::CXXRecordDecl *decl) { } } - if (!record_decls_.insert(GetID(decl)).second) { + if (!record_decls_.MarkDefined(GetRecordName(decl))) { return false; } diff --git a/cpp2rust/converter/converter.h b/cpp2rust/converter/converter.h index 9dbc3fa4..102d9bbf 100644 --- a/cpp2rust/converter/converter.h +++ b/cpp2rust/converter/converter.h @@ -51,8 +51,6 @@ class Converter : public clang::RecursiveASTVisitor { virtual void EmitFilePreamble(); - // Returns Rust text emitting `pub struct N { _opaque: [u8; 0] }` for each - // record name referenced by some TU but never defined by any. static std::string EmitOpaqueRecordMarkers(); virtual bool VisitBuiltinType(clang::BuiltinType *type); @@ -648,9 +646,37 @@ class Converter : public clang::RecursiveASTVisitor { ~ScopedMapIterDecl() { c.map_iter_decls_.erase(decl); } }; static std::unordered_set decl_ids_; - static std::unordered_set record_decls_; static std::unordered_set abstract_structs_; - static std::unordered_map referenced_records_; + + class RecordIndex { + public: + void MarkReferenced(std::string name) { + entries_.try_emplace(std::move(name), false); + } + // Returns false if `name` is already defined; otherwise marks it and + // returns true. + bool MarkDefined(const std::string &name) { + bool &defined = entries_[name]; + if (defined) { + return false; + } + defined = true; + return true; + } + template void ForEachUndefined(F &&f) const { + for (const auto &[name, defined] : entries_) { + if (!defined) { + f(name); + } + } + } + + private: + // record name -> true if a definition has been emitted, false if only + // referenced. + std::unordered_map entries_; + }; + static RecordIndex record_decls_; enum class ExprKind : uint8_t { Callee, diff --git a/tests/multi-file/opaque_forward_decl/b.c b/tests/multi-file/opaque_forward_decl/b.c index f8e3bae7..722d2675 100644 --- a/tests/multi-file/opaque_forward_decl/b.c +++ b/tests/multi-file/opaque_forward_decl/b.c @@ -1,6 +1,3 @@ #include "header.h" -void touch(struct container *c) { - /* read the opaque pointer field without dereferencing the opaque type */ - (void)c->p; -} +void touch(struct container *c) { (void)c->p; } diff --git a/tests/multi-file/opaque_forward_decl/header.h b/tests/multi-file/opaque_forward_decl/header.h index 2d5fba09..5d6fb56e 100644 --- a/tests/multi-file/opaque_forward_decl/header.h +++ b/tests/multi-file/opaque_forward_decl/header.h @@ -1,6 +1,5 @@ #pragma once -/* Forward declaration only; no full definition exists anywhere in the build. */ struct opaque; struct container { diff --git a/tests/unit/opaque_forward_decl.c b/tests/unit/opaque_forward_decl.c index 1291ab63..d08cbfe2 100644 --- a/tests/unit/opaque_forward_decl.c +++ b/tests/unit/opaque_forward_decl.c @@ -1,6 +1,5 @@ #include -/* Forward declaration only; no body for `opaque` anywhere in this TU. */ struct opaque; struct container { diff --git a/tests/unit/opaque_then_defined.c b/tests/unit/opaque_then_defined.c new file mode 100644 index 00000000..659dbaaa --- /dev/null +++ b/tests/unit/opaque_then_defined.c @@ -0,0 +1,21 @@ +#include + +struct node; + +struct list { + struct node *head; + int size; +}; + +struct node { + int value; + struct node *next; +}; + +int main(void) { + struct node n = {42, 0}; + struct list l = {&n, 1}; + assert(l.head->value == 42); + assert(l.size == 1); + return 0; +} diff --git a/tests/unit/out/refcount/opaque_then_defined.rs b/tests/unit/out/refcount/opaque_then_defined.rs new file mode 100644 index 00000000..3ce92afb --- /dev/null +++ b/tests/unit/out/refcount/opaque_then_defined.rs @@ -0,0 +1,42 @@ +extern crate libcc2rs; +use libcc2rs::*; +use std::cell::RefCell; +use std::collections::BTreeMap; +use std::io::prelude::*; +use std::io::{Read, Seek, Write}; +use std::os::fd::AsFd; +use std::rc::{Rc, Weak}; +#[derive(Default)] +pub struct list { + pub head: Value>, + pub size: Value, +} +impl ByteRepr for list {} +#[derive(Default)] +pub struct node { + pub value: Value, + pub next: Value>, +} +impl ByteRepr for node {} +pub fn main() { + std::process::exit(main_0()); +} +fn main_0() -> i32 { + let n: Value = Rc::new(RefCell::new(node { + value: Rc::new(RefCell::new(42)), + next: Rc::new(RefCell::new(Ptr::::null())), + })); + let l: Value = Rc::new(RefCell::new(list { + head: Rc::new(RefCell::new((n.as_pointer()))), + size: Rc::new(RefCell::new(1)), + })); + assert!( + ((((*(*(*(*l.borrow()).head.borrow()).upgrade().deref()) + .value + .borrow()) + == 42) as i32) + != 0) + ); + assert!(((((*(*l.borrow()).size.borrow()) == 1) as i32) != 0)); + return 0; +} diff --git a/tests/unit/out/unsafe/opaque_then_defined.rs b/tests/unit/out/unsafe/opaque_then_defined.rs new file mode 100644 index 00000000..bdd386e0 --- /dev/null +++ b/tests/unit/out/unsafe/opaque_then_defined.rs @@ -0,0 +1,38 @@ +extern crate libc; +use libc::*; +extern crate libcc2rs; +use libcc2rs::*; +use std::collections::BTreeMap; +use std::io::{Read, Seek, Write}; +use std::os::fd::{AsFd, FromRawFd, IntoRawFd}; +use std::rc::Rc; +#[repr(C)] +#[derive(Copy, Clone, Default)] +pub struct list { + pub head: *mut node, + pub size: i32, +} +#[repr(C)] +#[derive(Copy, Clone, Default)] +pub struct node { + pub value: i32, + pub next: *mut node, +} +pub fn main() { + unsafe { + std::process::exit(main_0() as i32); + } +} +unsafe fn main_0() -> i32 { + let mut n: node = node { + value: 42, + next: std::ptr::null_mut(), + }; + let mut l: list = list { + head: (&mut n as *mut node), + size: 1, + }; + assert!((((((*l.head).value) == (42)) as i32) != 0)); + assert!(((((l.size) == (1)) as i32) != 0)); + return 0; +} From bb1aa1bb288d397ca38c36b7e20e3094207e4026 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Fri, 22 May 2026 21:28:45 +0100 Subject: [PATCH 4/4] Named struct without body is enough --- cpp2rust/converter/converter.cpp | 6 +++--- cpp2rust/converter/converter.h | 2 +- cpp2rust/cpp2rust_lib.cpp | 4 ++-- .../opaque_forward_decl/out/refcount/opaque_forward_decl.rs | 5 +---- .../opaque_forward_decl/out/unsafe/opaque_forward_decl.rs | 5 +---- tests/unit/out/refcount/opaque_forward_decl.rs | 5 +---- tests/unit/out/unsafe/opaque_forward_decl.rs | 5 +---- 7 files changed, 10 insertions(+), 22 deletions(-) diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 45b915bc..c34d0d96 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -53,12 +53,12 @@ use std::rc::Rc; )"); } -std::string Converter::EmitOpaqueRecordMarkers() { +std::string Converter::EmitOpaqueRecords() { std::string out; record_decls_.ForEachUndefined([&](const std::string &name) { - out += "#[repr(C)] pub struct "; + out += "pub struct "; out += name; - out += " { _opaque: [u8; 0] }\n"; + out += ";\n"; }); return out; } diff --git a/cpp2rust/converter/converter.h b/cpp2rust/converter/converter.h index 102d9bbf..aa1ad22b 100644 --- a/cpp2rust/converter/converter.h +++ b/cpp2rust/converter/converter.h @@ -51,7 +51,7 @@ class Converter : public clang::RecursiveASTVisitor { virtual void EmitFilePreamble(); - static std::string EmitOpaqueRecordMarkers(); + static std::string EmitOpaqueRecords(); virtual bool VisitBuiltinType(clang::BuiltinType *type); diff --git a/cpp2rust/cpp2rust_lib.cpp b/cpp2rust/cpp2rust_lib.cpp index d2b141ff..100d6d93 100644 --- a/cpp2rust/cpp2rust_lib.cpp +++ b/cpp2rust/cpp2rust_lib.cpp @@ -30,7 +30,7 @@ std::string TranspileSrc(std::string_view cc_code, Model model, rules_dir), cc_code, tool_args, std::filesystem::path(filename).filename().string(), filename.ends_with(".c") ? CLANG_C_COMPILER : CLANG_CXX_COMPILER); - rs_code += Converter::EmitOpaqueRecordMarkers(); + rs_code += Converter::EmitOpaqueRecords(); return rs_code; } @@ -70,7 +70,7 @@ std::string TranspileDir(std::string_view build_dir, Model model, std::string rs_code; FrontendActionFactory factory(rs_code, model, rules_dir); Tool.run(&factory); - rs_code += Converter::EmitOpaqueRecordMarkers(); + rs_code += Converter::EmitOpaqueRecords(); return rs_code; } } // namespace cpp2rust diff --git a/tests/multi-file/opaque_forward_decl/out/refcount/opaque_forward_decl.rs b/tests/multi-file/opaque_forward_decl/out/refcount/opaque_forward_decl.rs index 64e614f6..db3db41a 100644 --- a/tests/multi-file/opaque_forward_decl/out/refcount/opaque_forward_decl.rs +++ b/tests/multi-file/opaque_forward_decl/out/refcount/opaque_forward_decl.rs @@ -32,7 +32,4 @@ pub fn touch_0(c: Ptr) { let c: Value> = Rc::new(RefCell::new(c)); (*(*(*c.borrow()).upgrade().deref()).p.borrow()).clone(); } -#[repr(C)] -pub struct opaque { - _opaque: [u8; 0], -} +pub struct opaque; diff --git a/tests/multi-file/opaque_forward_decl/out/unsafe/opaque_forward_decl.rs b/tests/multi-file/opaque_forward_decl/out/unsafe/opaque_forward_decl.rs index bbea6ced..e708f3f2 100644 --- a/tests/multi-file/opaque_forward_decl/out/unsafe/opaque_forward_decl.rs +++ b/tests/multi-file/opaque_forward_decl/out/unsafe/opaque_forward_decl.rs @@ -33,7 +33,4 @@ unsafe fn main_0() -> i32 { pub unsafe fn touch_0(mut c: *mut container) { &((*c).p); } -#[repr(C)] -pub struct opaque { - _opaque: [u8; 0], -} +pub struct opaque; diff --git a/tests/unit/out/refcount/opaque_forward_decl.rs b/tests/unit/out/refcount/opaque_forward_decl.rs index 90c7577d..206844e8 100644 --- a/tests/unit/out/refcount/opaque_forward_decl.rs +++ b/tests/unit/out/refcount/opaque_forward_decl.rs @@ -23,7 +23,4 @@ fn main_0() -> i32 { (*(*c.borrow()).p.borrow()).clone(); return ((*(*c.borrow()).x.borrow()) - 42); } -#[repr(C)] -pub struct opaque { - _opaque: [u8; 0], -} +pub struct opaque; diff --git a/tests/unit/out/unsafe/opaque_forward_decl.rs b/tests/unit/out/unsafe/opaque_forward_decl.rs index 17836ab1..966d4ee6 100644 --- a/tests/unit/out/unsafe/opaque_forward_decl.rs +++ b/tests/unit/out/unsafe/opaque_forward_decl.rs @@ -25,7 +25,4 @@ unsafe fn main_0() -> i32 { &(c.p); return ((c.x) - (42)); } -#[repr(C)] -pub struct opaque { - _opaque: [u8; 0], -} +pub struct opaque;