Skip to content

Commit 540902a

Browse files
authored
Don't use uninstantiated default argument (#398)
1 parent ebd5a6d commit 540902a

7 files changed

Lines changed: 369 additions & 5 deletions

File tree

‎cpp2rust/converter/converter.cpp‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,7 @@ bool Converter::ConvertVarDeclSkipInit(clang::VarDecl *decl) {
551551

552552
bool is_parm_with_default_value = false;
553553
if (auto parm = clang::dyn_cast<clang::ParmVarDecl>(decl)) {
554-
is_parm_with_default_value = parm->hasDefaultArg();
554+
is_parm_with_default_value = HasUsableDefaultArg(parm);
555555
}
556556

557557
if (is_parm_with_default_value) {
@@ -1229,7 +1229,7 @@ void Converter::EmitFunctionPreamble(clang::FunctionDecl *decl) {
12291229
auto params = decl->getDefinition() ? decl->getDefinition()->parameters()
12301230
: decl->parameters();
12311231
for (auto *param : params) {
1232-
if (param->hasDefaultArg()) {
1232+
if (HasUsableDefaultArg(param)) {
12331233
auto name = GetNamedDeclAsString(param);
12341234
auto type = ToString(param->getType());
12351235
auto init = std::format("{}.unwrap_or({})", name,
@@ -1946,7 +1946,8 @@ Converter::CallInfo Converter::CollectCallInfo(clang::CallExpr *expr) {
19461946
.param_type = function ? function->getParamDecl(i)->getType()
19471947
: proto->getParamType(i),
19481948
.expr = arg,
1949-
.has_default = function && function->getParamDecl(i)->hasDefaultArg(),
1949+
.has_default =
1950+
function && HasUsableDefaultArg(function->getParamDecl(i)),
19501951
.kind = (IsLiteral(arg) || info.is_libc_passthrough) ? Kind::Inline
19511952
: Kind::Hoisted,
19521953
};
@@ -3583,7 +3584,7 @@ void Converter::ConvertCXXConstructExprArgs(clang::CXXConstructExpr *expr) {
35833584
for (unsigned param_idx = 0; param_idx < ctor->getNumParams(); ++param_idx) {
35843585
auto param = ctor->getParamDecl(param_idx);
35853586
auto param_type = param->getType();
3586-
bool has_default = param->hasDefaultArg();
3587+
bool has_default = HasUsableDefaultArg(param);
35873588

35883589
if (arg_idx < expr->getNumArgs() &&
35893590
clang::isa<clang::CXXDefaultArgExpr>(expr->getArg(arg_idx))) {

‎cpp2rust/converter/converter_lib.cpp‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -528,6 +528,10 @@ GetUserDefinedDefaultConstructor(const clang::CXXRecordDecl *decl) {
528528
return nullptr;
529529
}
530530

531+
bool HasUsableDefaultArg(const clang::ParmVarDecl *param) {
532+
return param->hasDefaultArg() && !param->hasUninstantiatedDefaultArg();
533+
}
534+
531535
std::string GetMainFileName(const clang::ASTContext &ctx) {
532536
const auto &src_mgr = ctx.getSourceManager();
533537
auto file_id = src_mgr.getMainFileID();

‎cpp2rust/converter/converter_lib.h‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,6 +132,8 @@ unsigned GetCtorIndex(clang::CXXConstructorDecl *ctor);
132132
clang::CXXConstructorDecl *
133133
GetUserDefinedDefaultConstructor(const clang::CXXRecordDecl *decl);
134134

135+
bool HasUsableDefaultArg(const clang::ParmVarDecl *param);
136+
135137
std::string GetMainFileName(const clang::ASTContext &ctx);
136138

137139
std::string GetFileName(const clang::Decl *decl);

‎cpp2rust/converter/models/converter_refcount.cpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -675,7 +675,7 @@ void ConverterRefCount::EmitFunctionPreamble(clang::FunctionDecl *decl) {
675675
auto type = ToString(param->getType());
676676
auto init = name;
677677

678-
if (param->hasDefaultArg()) {
678+
if (HasUsableDefaultArg(param)) {
679679
init = std::format("{}.unwrap_or({})", name,
680680
ToString(param->getDefaultArg()));
681681
}
Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
extern crate libcc2rs;
2+
use libcc2rs::*;
3+
use std::cell::RefCell;
4+
use std::collections::BTreeMap;
5+
use std::io::prelude::*;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::AsFd;
8+
use std::rc::{Rc, Weak};
9+
#[derive()]
10+
pub struct A {
11+
pub v: Value<i32>,
12+
}
13+
impl A {
14+
pub fn A1() -> Self {
15+
let __this: Value<A> = Rc::new(RefCell::new(Self {
16+
v: Rc::new(RefCell::new(1)),
17+
}));
18+
let this: Ptr<A> = __this.as_pointer();
19+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
20+
}
21+
pub fn A2(v: i32) -> Self {
22+
let v: Value<i32> = Rc::new(RefCell::new(v));
23+
let __this: Value<A> = Rc::new(RefCell::new(Self {
24+
v: Rc::new(RefCell::new((*v.borrow()))),
25+
}));
26+
let this: Ptr<A> = __this.as_pointer();
27+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
28+
}
29+
}
30+
impl Clone for A {
31+
fn clone(&self) -> Self {
32+
let __this: Value<A> = Rc::new(RefCell::new(Self {
33+
v: Rc::new(RefCell::new((*self.v.borrow()))),
34+
}));
35+
let this: Ptr<A> = __this.as_pointer();
36+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
37+
}
38+
}
39+
impl Default for A {
40+
fn default() -> Self {
41+
{ A::A1() }
42+
}
43+
}
44+
impl ByteRepr for A {
45+
fn byte_size() -> usize {
46+
4
47+
}
48+
fn to_bytes(&self, buf: &mut [u8]) {
49+
(*self.v.borrow()).to_bytes(&mut buf[0..4]);
50+
}
51+
fn from_bytes(buf: &[u8]) -> Self {
52+
Self {
53+
v: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
54+
}
55+
}
56+
}
57+
#[derive()]
58+
pub struct B {
59+
pub v: Value<i32>,
60+
}
61+
impl B {
62+
pub fn B() -> Self {
63+
let __this: Value<B> = Rc::new(RefCell::new(Self {
64+
v: Rc::new(RefCell::new(2)),
65+
}));
66+
let this: Ptr<B> = __this.as_pointer();
67+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
68+
}
69+
}
70+
impl Clone for B {
71+
fn clone(&self) -> Self {
72+
let __this: Value<B> = Rc::new(RefCell::new(Self {
73+
v: Rc::new(RefCell::new((*self.v.borrow()))),
74+
}));
75+
let this: Ptr<B> = __this.as_pointer();
76+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
77+
}
78+
}
79+
impl Default for B {
80+
fn default() -> Self {
81+
{ B::B() }
82+
}
83+
}
84+
impl ByteRepr for B {
85+
fn byte_size() -> usize {
86+
4
87+
}
88+
fn to_bytes(&self, buf: &mut [u8]) {
89+
(*self.v.borrow()).to_bytes(&mut buf[0..4]);
90+
}
91+
fn from_bytes(buf: &[u8]) -> Self {
92+
Self {
93+
v: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
94+
}
95+
}
96+
}
97+
#[derive(Default)]
98+
pub struct NoDefault {
99+
pub v: Value<i32>,
100+
}
101+
impl NoDefault {
102+
pub fn NoDefault(v: i32) -> Self {
103+
let v: Value<i32> = Rc::new(RefCell::new(v));
104+
let __this: Value<NoDefault> = Rc::new(RefCell::new(Self {
105+
v: Rc::new(RefCell::new((*v.borrow()))),
106+
}));
107+
let this: Ptr<NoDefault> = __this.as_pointer();
108+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
109+
}
110+
}
111+
impl Clone for NoDefault {
112+
fn clone(&self) -> Self {
113+
let __this: Value<NoDefault> = Rc::new(RefCell::new(Self {
114+
v: Rc::new(RefCell::new((*self.v.borrow()))),
115+
}));
116+
let this: Ptr<NoDefault> = __this.as_pointer();
117+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
118+
}
119+
}
120+
impl ByteRepr for NoDefault {
121+
fn byte_size() -> usize {
122+
4
123+
}
124+
fn to_bytes(&self, buf: &mut [u8]) {
125+
(*self.v.borrow()).to_bytes(&mut buf[0..4]);
126+
}
127+
fn from_bytes(buf: &[u8]) -> Self {
128+
Self {
129+
v: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
130+
}
131+
}
132+
}
133+
pub fn used_0(x: Option<A>) -> i32 {
134+
let x: Value<A> = Rc::new(RefCell::new(x.unwrap_or(A::A1())));
135+
return (*(*x.borrow()).v.borrow());
136+
}
137+
pub fn used_1(x: Option<B>) -> i32 {
138+
let x: Value<B> = Rc::new(RefCell::new(x.unwrap_or(B::B())));
139+
return (*(*x.borrow()).v.borrow());
140+
}
141+
pub fn scaled_2(x: A, n: Option<i32>) -> i32 {
142+
let x: Value<A> = Rc::new(RefCell::new(x));
143+
let n: Value<i32> = Rc::new(RefCell::new(n.unwrap_or((4usize as i32))));
144+
return ((*(*x.borrow()).v.borrow()) * (*n.borrow()));
145+
}
146+
pub fn always_given_3(x: NoDefault) -> i32 {
147+
let x: Value<NoDefault> = Rc::new(RefCell::new(x));
148+
return (*(*x.borrow()).v.borrow());
149+
}
150+
#[derive(Default)]
151+
pub struct S_NoDefault_ {
152+
pub v: Value<i32>,
153+
}
154+
impl S_NoDefault_ {
155+
pub fn S_NoDefault_(v: i32) -> Self {
156+
let v: Value<i32> = Rc::new(RefCell::new(v));
157+
let __this: Value<S_NoDefault_> = Rc::new(RefCell::new(Self {
158+
v: Rc::new(RefCell::new((*v.borrow()))),
159+
}));
160+
let this: Ptr<S_NoDefault_> = __this.as_pointer();
161+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
162+
}
163+
}
164+
impl Clone for S_NoDefault_ {
165+
fn clone(&self) -> Self {
166+
let __this: Value<S_NoDefault_> = Rc::new(RefCell::new(Self {
167+
v: Rc::new(RefCell::new((*self.v.borrow()))),
168+
}));
169+
let this: Ptr<S_NoDefault_> = __this.as_pointer();
170+
Rc::try_unwrap(__this).ok().unwrap().into_inner()
171+
}
172+
}
173+
impl ByteRepr for S_NoDefault_ {
174+
fn byte_size() -> usize {
175+
4
176+
}
177+
fn to_bytes(&self, buf: &mut [u8]) {
178+
(*self.v.borrow()).to_bytes(&mut buf[0..4]);
179+
}
180+
fn from_bytes(buf: &[u8]) -> Self {
181+
Self {
182+
v: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
183+
}
184+
}
185+
}
186+
pub fn main() {
187+
__cpp2rust_init_globals();
188+
std::process::exit(main_0());
189+
}
190+
fn main_0() -> i32 {
191+
assert!((({ used_0(None,) }) == 1));
192+
assert!((({ used_0(Some(A::A2({ 5 },)),) }) == 5));
193+
assert!((({ used_1(None,) }) == 2));
194+
assert!((({ scaled_2(A::A2({ 3 },), None,) }) == (3 * (4usize as i32))));
195+
assert!((({ scaled_2(A::A2({ 3 },), Some(2),) }) == 6));
196+
assert!((({ always_given_3(NoDefault::NoDefault({ 3 },),) }) == 3));
197+
let s: Value<S_NoDefault_> = Rc::new(RefCell::new(S_NoDefault_::S_NoDefault_({ 1 })));
198+
assert!((({ S_NoDefault_Impl::get(&s.as_pointer(), NoDefault::NoDefault({ 4 },),) }) == 5));
199+
return 0;
200+
}
201+
pub trait S_NoDefault_Impl {
202+
fn get(&self, t: NoDefault) -> i32;
203+
}
204+
impl S_NoDefault_Impl for Ptr<S_NoDefault_> {
205+
fn get(&self, t: NoDefault) -> i32 {
206+
let t: Value<NoDefault> = Rc::new(RefCell::new(t));
207+
return ((*(*(*self).upgrade().deref()).v.borrow()) + (*(*t.borrow()).v.borrow()));
208+
}
209+
}
210+
pub fn __cpp2rust_init_globals() {}
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
extern crate libc;
2+
use libc::*;
3+
extern crate libcc2rs;
4+
use libcc2rs::*;
5+
use std::collections::BTreeMap;
6+
use std::io::{Read, Seek, Write};
7+
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
8+
use std::rc::Rc;
9+
#[repr(C)]
10+
#[derive(Copy, Clone)]
11+
pub struct A {
12+
pub v: i32,
13+
}
14+
impl A {
15+
pub unsafe fn A1() -> Self {
16+
let mut this = Self { v: 1 };
17+
this
18+
}
19+
pub unsafe fn A2(mut v: i32) -> Self {
20+
let mut this = Self { v: v };
21+
this
22+
}
23+
}
24+
impl Default for A {
25+
fn default() -> Self {
26+
unsafe { A::A1() }
27+
}
28+
}
29+
#[repr(C)]
30+
#[derive(Copy, Clone)]
31+
pub struct B {
32+
pub v: i32,
33+
}
34+
impl B {
35+
pub unsafe fn B() -> Self {
36+
let mut this = Self { v: 2 };
37+
this
38+
}
39+
}
40+
impl Default for B {
41+
fn default() -> Self {
42+
unsafe { B::B() }
43+
}
44+
}
45+
#[repr(C)]
46+
#[derive(Copy, Clone, Default)]
47+
pub struct NoDefault {
48+
pub v: i32,
49+
}
50+
impl NoDefault {
51+
pub unsafe fn NoDefault(mut v: i32) -> Self {
52+
let mut this = Self { v: v };
53+
this
54+
}
55+
}
56+
pub unsafe fn used_0(mut x: Option<A>) -> i32 {
57+
let mut x: A = x.unwrap_or(A::A1());
58+
return x.v;
59+
}
60+
pub unsafe fn used_1(mut x: Option<B>) -> i32 {
61+
let mut x: B = x.unwrap_or(B::B());
62+
return x.v;
63+
}
64+
pub unsafe fn scaled_2(mut x: A, mut n: Option<i32>) -> i32 {
65+
let mut n: i32 = n.unwrap_or((::std::mem::size_of::<A>() as i32));
66+
return ((x.v) * (n));
67+
}
68+
pub unsafe fn always_given_3(mut x: NoDefault) -> i32 {
69+
return x.v;
70+
}
71+
#[repr(C)]
72+
#[derive(Copy, Clone, Default)]
73+
pub struct S_NoDefault_ {
74+
pub v: i32,
75+
}
76+
impl S_NoDefault_ {
77+
pub unsafe fn S_NoDefault_(mut v: i32) -> Self {
78+
let mut this = Self { v: v };
79+
this
80+
}
81+
pub unsafe fn get(&self, mut t: NoDefault) -> i32 {
82+
return ((self.v) + (t.v));
83+
}
84+
}
85+
pub fn main() {
86+
unsafe {
87+
__cpp2rust_init_globals();
88+
std::process::exit(main_0() as i32);
89+
}
90+
}
91+
unsafe fn main_0() -> i32 {
92+
assert!(((unsafe { used_0(None,) }) == (1)));
93+
assert!(((unsafe { used_0(Some(A::A2({ 5 },)),) }) == (5)));
94+
assert!(((unsafe { used_1(None,) }) == (2)));
95+
assert!(
96+
((unsafe { scaled_2(A::A2({ 3 },), None,) })
97+
== ((3) * (::std::mem::size_of::<A>() as i32)))
98+
);
99+
assert!(((unsafe { scaled_2(A::A2({ 3 },), Some(2),) }) == (6)));
100+
assert!(((unsafe { always_given_3(NoDefault::NoDefault({ 3 },),) }) == (3)));
101+
let mut s: S_NoDefault_ = S_NoDefault_::S_NoDefault_({ 1 });
102+
assert!(((unsafe { S_NoDefault_::get(&s, NoDefault::NoDefault({ 4 },),) }) == (5)));
103+
return 0;
104+
}
105+
pub unsafe fn __cpp2rust_init_globals() {}

0 commit comments

Comments
 (0)