Skip to content

Commit 6a7dff0

Browse files
committed
Don't assume that an inner class declaration always immediately yields a
complete type. It might not if we had to avoid recursion when processing types. Detect that case and bail out. This bug was being masked by the fact that we didn't always find definitions for the recursion check and so it didn't trigger, but now that this check is more reliable we have to be careful in more places. The test case was reduced from the GCC STL allocator definition.
1 parent 2cb053a commit 6a7dff0

File tree

3 files changed

+44
-14
lines changed

3 files changed

+44
-14
lines changed

src/ir/comp.rs

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1408,21 +1408,26 @@ impl CompInfo {
14081408
let inner = Item::parse(cur, Some(potential_id), ctx)
14091409
.expect("Inner ClassDecl");
14101410

1411-
let inner = inner.expect_type_id(ctx);
1412-
1413-
ci.inner_types.push(inner);
1414-
1415-
// A declaration of an union or a struct without name could
1416-
// also be an unnamed field, unfortunately.
1417-
if cur.spelling().is_empty() &&
1418-
cur.kind() != CXCursor_EnumDecl
1419-
{
1420-
let ty = cur.cur_type();
1421-
let public = cur.public_accessible();
1422-
let offset = cur.offset_of_field().ok();
1411+
// If we avoided recursion parsing this type (in
1412+
// `Item::from_ty_with_id()`), then this might not be a
1413+
// valid type ID, so check and gracefully handle this.
1414+
if ctx.resolve_item_fallible(inner).is_some() {
1415+
let inner = inner.expect_type_id(ctx);
1416+
1417+
ci.inner_types.push(inner);
1418+
1419+
// A declaration of an union or a struct without name
1420+
// could also be an unnamed field, unfortunately.
1421+
if cur.spelling().is_empty() &&
1422+
cur.kind() != CXCursor_EnumDecl
1423+
{
1424+
let ty = cur.cur_type();
1425+
let public = cur.public_accessible();
1426+
let offset = cur.offset_of_field().ok();
14231427

1424-
maybe_anonymous_struct_field =
1425-
Some((inner, ty, public, offset));
1428+
maybe_anonymous_struct_field =
1429+
Some((inner, ty, public, offset));
1430+
}
14261431
}
14271432
}
14281433
CXCursor_PackedAttr => {
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
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+
#[repr(C)]
14+
#[derive(Debug, Default, Copy, Clone)]
15+
pub struct Foo_Bar {
16+
pub _address: u8,
17+
}
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
template<typename T>
2+
class Foo {
3+
public:
4+
template<typename U>
5+
struct Bar {
6+
typedef Foo<U> FooU;
7+
};
8+
};

0 commit comments

Comments
 (0)