Skip to content

Commit 999aabf

Browse files
authored
Translate default pointers in globals (#63)
Previously, we used `Default::default()` for initializing pointers to null. This is not compatible with initializing global variables because they are declared in static context. In static context, only const functions can be used. `Default::default()` is not const, `std::ptr::null()/null_mut()` are const.
1 parent 157f292 commit 999aabf

34 files changed

Lines changed: 229 additions & 95 deletions

cpp2rust/converter/converter.cpp

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1862,7 +1862,9 @@ bool Converter::VisitImplicitCastExpr(clang::ImplicitCastExpr *expr) {
18621862
if (type->isFunctionPointerType()) {
18631863
StrCat("None");
18641864
} else {
1865-
StrCat(keyword_default_);
1865+
StrCat(type->getPointeeType().isConstQualified()
1866+
? "std::ptr::null()"
1867+
: "std::ptr::null_mut()");
18661868
}
18671869
computed_expr_type_ = ComputedExprType::FreshPointer;
18681870
break;
@@ -2966,12 +2968,13 @@ std::string Converter::GetDefaultAsString(clang::QualType qual_type) {
29662968
}
29672969

29682970
if (qual_type->isPointerType()) {
2969-
if (qual_type->getPointeeType()->isFunctionType()) {
2971+
auto pointee = qual_type->getPointeeType();
2972+
if (pointee->isFunctionType()) {
29702973
return "None";
2971-
} else {
2972-
computed_expr_type_ = ComputedExprType::FreshPointer;
2973-
return keyword_default_;
29742974
}
2975+
computed_expr_type_ = ComputedExprType::FreshPointer;
2976+
return pointee.isConstQualified() ? "std::ptr::null()"
2977+
: "std::ptr::null_mut()";
29752978
}
29762979

29772980
computed_expr_type_ = ComputedExprType::FreshValue;

tests/benchmarks/out/unsafe/bfs.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -134,14 +134,14 @@ unsafe fn main_0() -> i32 {
134134
V: (V as u32),
135135
adj: Box::leak(
136136
(0..V)
137-
.map(|_| Default::default())
137+
.map(|_| std::ptr::null_mut())
138138
.collect::<Box<[*mut GraphNode]>>(),
139139
)
140140
.as_mut_ptr(),
141141
};
142142
let mut i: u32 = 0_u32;
143143
'loop_: while ((i as u64) < (V)) {
144-
(*graph.adj.offset((i) as isize)) = Default::default();
144+
(*graph.adj.offset((i) as isize)) = std::ptr::null_mut();
145145
i.prefix_inc();
146146
}
147147
let mut i: u32 = 0_u32;

tests/benchmarks/out/unsafe/bst.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ pub unsafe fn find_0(mut node: *mut node_t, mut value: i32) -> *mut node_t {
2929
} else if ((value) == ((*node).value)) {
3030
return node;
3131
}
32-
return Default::default();
32+
return std::ptr::null_mut();
3333
}
3434
pub unsafe fn insert_1(mut node: *mut node_t, mut new_node: *mut node_t) -> *mut node_t {
3535
if (node).is_null() {
@@ -58,17 +58,17 @@ pub fn main() {
5858
unsafe fn main_0() -> i32 {
5959
let N: i32 = 25000;
6060
let mut tree: *mut node_t = (Box::leak(Box::new(node_t {
61-
left: Default::default(),
62-
right: Default::default(),
61+
left: std::ptr::null_mut(),
62+
right: std::ptr::null_mut(),
6363
value: 0,
6464
})) as *mut node_t);
6565
let mut i: i32 = 0;
6666
'loop_: while ((i) < (N)) {
6767
(unsafe {
6868
let _node: *mut node_t = tree;
6969
let _new_node: *mut node_t = (Box::leak(Box::new(node_t {
70-
left: Default::default(),
71-
right: Default::default(),
70+
left: std::ptr::null_mut(),
71+
right: std::ptr::null_mut(),
7272
value: i,
7373
})) as *mut node_t);
7474
insert_1(_node, _new_node)

tests/ub/out/unsafe/ub2.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::io::{Read, Seek, Write};
77
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
88
use std::rc::Rc;
99
pub unsafe fn null_0() -> *mut i32 {
10-
let mut p: *mut i32 = Default::default();
10+
let mut p: *mut i32 = std::ptr::null_mut();
1111
return p;
1212
}
1313
pub fn main() {

tests/ub/out/unsafe/ub4.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ pub fn main() {
1515
}
1616
}
1717
unsafe fn main_0() -> i32 {
18-
let mut out: *mut i32 = Default::default();
18+
let mut out: *mut i32 = std::ptr::null_mut();
1919
let mut x1: i32 = 1;
2020
if (x1 != 0) {
2121
let mut x2: i32 = -1_i32;

tests/ub/out/unsafe/ub5.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::io::{Read, Seek, Write};
77
use std::os::fd::{AsFd, FromRawFd, IntoRawFd};
88
use std::rc::Rc;
99
pub unsafe fn null_0(mut p: *mut *mut i32) {
10-
(*p) = Default::default();
10+
(*p) = std::ptr::null_mut();
1111
}
1212
pub fn main() {
1313
unsafe {

tests/unit/null_in_statics.cpp

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#include <cassert>
2+
#include <cstddef>
3+
4+
static int *p_mut;
5+
static const int *p_const;
6+
static const char *cp;
7+
static int *arr_of_ptr[4];
8+
static int **pp;
9+
static const int *const_arr_of_ptr[3];
10+
static const char *cp_explicit_null = nullptr;
11+
static int *p_zero = 0;
12+
13+
int main() {
14+
assert(p_mut == nullptr);
15+
assert(p_const == nullptr);
16+
assert(cp == nullptr);
17+
for (int i = 0; i < 4; ++i) {
18+
assert(arr_of_ptr[i] == nullptr);
19+
}
20+
assert(pp == nullptr);
21+
for (int i = 0; i < 3; ++i) {
22+
assert(const_arr_of_ptr[i] == nullptr);
23+
}
24+
assert(cp_explicit_null == nullptr);
25+
assert(p_zero == nullptr);
26+
return 0;
27+
}
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
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+
thread_local!(
10+
pub static p_mut: Value<Ptr<i32>> = Rc::new(RefCell::new(Ptr::<i32>::null()));
11+
);
12+
thread_local!(
13+
pub static p_const: Value<Ptr<i32>> = Rc::new(RefCell::new(Ptr::<i32>::null()));
14+
);
15+
thread_local!(
16+
pub static cp: Value<Ptr<u8>> = Rc::new(RefCell::new(Ptr::<u8>::null()));
17+
);
18+
thread_local!(
19+
pub static arr_of_ptr: Value<Box<[Ptr<i32>]>> = Rc::new(RefCell::new(
20+
(0..4)
21+
.map(|_| Ptr::<i32>::null())
22+
.collect::<Box<[Ptr<i32>]>>(),
23+
));
24+
);
25+
thread_local!(
26+
pub static pp: Value<Ptr<Ptr<i32>>> = Rc::new(RefCell::new(Ptr::<Ptr<i32>>::null()));
27+
);
28+
thread_local!(
29+
pub static const_arr_of_ptr: Value<Box<[Ptr<i32>]>> = Rc::new(RefCell::new(
30+
(0..3)
31+
.map(|_| Ptr::<i32>::null())
32+
.collect::<Box<[Ptr<i32>]>>(),
33+
));
34+
);
35+
thread_local!(
36+
pub static cp_explicit_null: Value<Ptr<u8>> = Rc::new(RefCell::new(Default::default()));
37+
);
38+
thread_local!(
39+
pub static p_zero: Value<Ptr<i32>> = Rc::new(RefCell::new(Default::default()));
40+
);
41+
pub fn main() {
42+
std::process::exit(main_0());
43+
}
44+
fn main_0() -> i32 {
45+
assert!((*p_mut.with(Value::clone).borrow()).is_null());
46+
assert!((*p_const.with(Value::clone).borrow()).is_null());
47+
assert!((*cp.with(Value::clone).borrow()).is_null());
48+
let i: Value<i32> = Rc::new(RefCell::new(0));
49+
'loop_: while ((*i.borrow()) < 4) {
50+
assert!(((*arr_of_ptr.with(Value::clone).borrow())[(*i.borrow()) as usize]).is_null());
51+
(*i.borrow_mut()).prefix_inc();
52+
}
53+
assert!((*pp.with(Value::clone).borrow()).is_null());
54+
let i: Value<i32> = Rc::new(RefCell::new(0));
55+
'loop_: while ((*i.borrow()) < 3) {
56+
assert!(
57+
((*const_arr_of_ptr.with(Value::clone).borrow())[(*i.borrow()) as usize]).is_null()
58+
);
59+
(*i.borrow_mut()).prefix_inc();
60+
}
61+
assert!((*cp_explicit_null.with(Value::clone).borrow()).is_null());
62+
assert!((*p_zero.with(Value::clone).borrow()).is_null());
63+
return 0;
64+
}

tests/unit/out/unsafe/10_struct.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ pub fn main() {
3838
unsafe fn main_0() -> i32 {
3939
let mut g: Graph = Graph {
4040
V: 5_u32,
41-
adj: Default::default(),
41+
adj: std::ptr::null_mut(),
4242
};
4343
return 0;
4444
}

tests/unit/out/unsafe/bool_condition_logical.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ unsafe fn main_0() -> i32 {
4444
let mut zero: i32 = 0;
4545
let mut storage: i32 = 7;
4646
let mut p: *mut i32 = (&mut storage as *mut i32);
47-
let mut np: *mut i32 = Default::default();
47+
let mut np: *mut i32 = std::ptr::null_mut();
4848
let mut u: u32 = 4_u32;
4949
let mut code: Code = Code::CODE_OK;
5050
if (n != 0) && (!(p).is_null()) {
@@ -124,7 +124,7 @@ unsafe fn main_0() -> i32 {
124124
assert!(true);
125125
}
126126
let mut cp: *const u8 = b"hi\0".as_ptr();
127-
let mut cnp: *const u8 = Default::default();
127+
let mut cnp: *const u8 = std::ptr::null();
128128
if ((x) > (y)) && (!(cp).is_null()) {
129129
assert!(true);
130130
}

0 commit comments

Comments
 (0)