Skip to content

Commit f597e27

Browse files
pcwaltonemilio
authored andcommitted
Translate types that were declared inside functions as opaque types.
This fixes a panic with the following header: template<typename T> struct Foo {}; template<typename T> Foo<T> foo{}; void f() { struct Bar { Bar() {} }; foo<Bar>; } Because we don't parse the insides of function bodies, code like this could cause us to parse a type (here, `Bar`) that we didn't see in our initial pass, which can cause subtle problems. Closes rust-lang#2036.
1 parent 91ec529 commit f597e27

File tree

5 files changed

+198
-1
lines changed

5 files changed

+198
-1
lines changed

src/ir/function.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,9 @@ pub enum FunctionKind {
2828
}
2929

3030
impl FunctionKind {
31-
fn from_cursor(cursor: &clang::Cursor) -> Option<FunctionKind> {
31+
/// Given a clang cursor, return the kind of function it represents, or
32+
/// `None` otherwise.
33+
pub fn from_cursor(cursor: &clang::Cursor) -> Option<FunctionKind> {
3234
// FIXME(emilio): Deduplicate logic with `ir::comp`.
3335
Some(match cursor.kind() {
3436
clang_sys::CXCursor_FunctionDecl => FunctionKind::Function,

src/ir/item.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1558,6 +1558,18 @@ impl ClangItemParser for Item {
15581558
}
15591559
}
15601560

1561+
// Treat all types that are declared inside functions as opaque. The Rust binding
1562+
// won't be able to do anything with them anyway.
1563+
//
1564+
// (If we don't do this check here, we can have subtle logic bugs because we generally
1565+
// ignore function bodies. See issue #2036.)
1566+
if let Some(ref parent) = ty.declaration().fallible_semantic_parent() {
1567+
if FunctionKind::from_cursor(parent).is_some() {
1568+
debug!("Skipping type declared inside function: {:?}", ty);
1569+
return Ok(Item::new_opaque_type(id, ty, ctx));
1570+
}
1571+
}
1572+
15611573
let decl = {
15621574
let decl = ty.declaration();
15631575
decl.definition().unwrap_or(decl)
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
#![allow(
2+
dead_code,
3+
non_snake_case,
4+
non_camel_case_types,
5+
non_upper_case_globals
6+
)]
7+
8+
#[repr(C)]
9+
#[derive(Debug, Default, Copy, Clone)]
10+
pub struct Foo {
11+
pub _address: u8,
12+
}
13+
extern "C" {
14+
#[link_name = "\u{1}_Z1fv"]
15+
pub fn f();
16+
}
17+
#[test]
18+
fn __bindgen_test_layout_Foo_open0__bindgen_ty_id_20_close0_instantiation() {
19+
assert_eq!(
20+
::std::mem::size_of::<Foo>(),
21+
1usize,
22+
concat!("Size of template specialization: ", stringify!(Foo))
23+
);
24+
assert_eq!(
25+
::std::mem::align_of::<Foo>(),
26+
1usize,
27+
concat!("Alignment of template specialization: ", stringify!(Foo))
28+
);
29+
}
30+
#[repr(C)]
31+
#[derive(Debug, Default, Copy, Clone)]
32+
pub struct Baz {
33+
pub _address: u8,
34+
}
35+
#[test]
36+
fn bindgen_test_layout_Baz() {
37+
assert_eq!(
38+
::std::mem::size_of::<Baz>(),
39+
1usize,
40+
concat!("Size of: ", stringify!(Baz))
41+
);
42+
assert_eq!(
43+
::std::mem::align_of::<Baz>(),
44+
1usize,
45+
concat!("Alignment of ", stringify!(Baz))
46+
);
47+
}
48+
#[test]
49+
fn __bindgen_test_layout_Foo_open0__bindgen_ty_id_21_close0_instantiation() {
50+
assert_eq!(
51+
::std::mem::size_of::<Foo>(),
52+
1usize,
53+
concat!("Size of template specialization: ", stringify!(Foo))
54+
);
55+
assert_eq!(
56+
::std::mem::align_of::<Foo>(),
57+
1usize,
58+
concat!("Alignment of template specialization: ", stringify!(Foo))
59+
);
60+
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
#![allow(
2+
dead_code,
3+
non_snake_case,
4+
non_camel_case_types,
5+
non_upper_case_globals
6+
)]
7+
8+
#[repr(C)]
9+
#[derive(Debug, Default, Copy, Clone)]
10+
pub struct Foo {
11+
pub _address: u8,
12+
}
13+
extern "C" {
14+
#[link_name = "\u{1}_Z1fv"]
15+
pub fn f();
16+
}
17+
#[test]
18+
fn __bindgen_test_layout_Foo_open0_Bar_close0_instantiation() {
19+
assert_eq!(
20+
::std::mem::size_of::<Foo>(),
21+
1usize,
22+
concat!("Size of template specialization: ", stringify!(Foo))
23+
);
24+
assert_eq!(
25+
::std::mem::align_of::<Foo>(),
26+
1usize,
27+
concat!("Alignment of template specialization: ", stringify!(Foo))
28+
);
29+
}
30+
#[repr(C)]
31+
#[derive(Debug, Default, Copy, Clone)]
32+
pub struct Baz {
33+
pub _address: u8,
34+
}
35+
#[test]
36+
fn bindgen_test_layout_Baz() {
37+
assert_eq!(
38+
::std::mem::size_of::<Baz>(),
39+
1usize,
40+
concat!("Size of: ", stringify!(Baz))
41+
);
42+
assert_eq!(
43+
::std::mem::align_of::<Baz>(),
44+
1usize,
45+
concat!("Alignment of ", stringify!(Baz))
46+
);
47+
}
48+
#[test]
49+
fn __bindgen_test_layout_Foo_open0_Boo_close0_instantiation() {
50+
assert_eq!(
51+
::std::mem::size_of::<Foo>(),
52+
1usize,
53+
concat!("Size of template specialization: ", stringify!(Foo))
54+
);
55+
assert_eq!(
56+
::std::mem::align_of::<Foo>(),
57+
1usize,
58+
concat!("Alignment of template specialization: ", stringify!(Foo))
59+
);
60+
}
61+
#[repr(C)]
62+
#[derive(Debug, Default, Copy, Clone)]
63+
pub struct Bar {
64+
pub _address: u8,
65+
}
66+
#[test]
67+
fn bindgen_test_layout_Bar() {
68+
assert_eq!(
69+
::std::mem::size_of::<Bar>(),
70+
1usize,
71+
concat!("Size of: ", stringify!(Bar))
72+
);
73+
assert_eq!(
74+
::std::mem::align_of::<Bar>(),
75+
1usize,
76+
concat!("Alignment of ", stringify!(Bar))
77+
);
78+
}
79+
#[repr(C)]
80+
#[derive(Debug, Default, Copy, Clone)]
81+
pub struct Boo {
82+
pub _address: u8,
83+
}
84+
#[test]
85+
fn bindgen_test_layout_Boo() {
86+
assert_eq!(
87+
::std::mem::size_of::<Boo>(),
88+
1usize,
89+
concat!("Size of: ", stringify!(Boo))
90+
);
91+
assert_eq!(
92+
::std::mem::align_of::<Boo>(),
93+
1usize,
94+
concat!("Alignment of ", stringify!(Boo))
95+
);
96+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// bindgen-flags: -- -std=c++14
2+
//
3+
// https://github.com/rust-lang/rust-bindgen/issues/2036
4+
5+
template<typename T>
6+
struct Foo {};
7+
template<typename T>
8+
Foo<T> foo{};
9+
10+
// Struct inside function
11+
void f() {
12+
struct Bar {
13+
Bar() {}
14+
};
15+
foo<Bar>;
16+
}
17+
18+
// Struct inside method
19+
class Baz {
20+
void f() {
21+
struct Boo {
22+
Boo() {}
23+
};
24+
foo<Boo>;
25+
}
26+
};
27+

0 commit comments

Comments
 (0)