Skip to content

Commit

Permalink
Don't assume that an inner class declaration always immediately yields a
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
pcwalton authored and emilio committed Jul 31, 2021
1 parent 5464546 commit d1d2eb6
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 14 deletions.
33 changes: 19 additions & 14 deletions src/ir/comp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1408,21 +1408,26 @@ impl CompInfo {
let inner = Item::parse(cur, Some(potential_id), ctx)
.expect("Inner ClassDecl");

let inner = inner.expect_type_id(ctx);

ci.inner_types.push(inner);

// A declaration of an union or a struct without name could
// also be an unnamed field, unfortunately.
if cur.spelling().is_empty() &&
cur.kind() != CXCursor_EnumDecl
{
let ty = cur.cur_type();
let public = cur.public_accessible();
let offset = cur.offset_of_field().ok();
// If we avoided recursion parsing this type (in
// `Item::from_ty_with_id()`), then this might not be a
// valid type ID, so check and gracefully handle this.
if ctx.resolve_item_fallible(inner).is_some() {
let inner = inner.expect_type_id(ctx);

ci.inner_types.push(inner);

// A declaration of an union or a struct without name
// could also be an unnamed field, unfortunately.
if cur.spelling().is_empty() &&
cur.kind() != CXCursor_EnumDecl
{
let ty = cur.cur_type();
let public = cur.public_accessible();
let offset = cur.offset_of_field().ok();

maybe_anonymous_struct_field =
Some((inner, ty, public, offset));
maybe_anonymous_struct_field =
Some((inner, ty, public, offset));
}
}
}
CXCursor_PackedAttr => {
Expand Down
17 changes: 17 additions & 0 deletions tests/expectations/tests/nested-template-typedef.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
#![allow(
dead_code,
non_snake_case,
non_camel_case_types,
non_upper_case_globals
)]

#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct Foo {
pub _address: u8,
}
#[repr(C)]
#[derive(Debug, Default, Copy, Clone)]
pub struct Foo_Bar {
pub _address: u8,
}
8 changes: 8 additions & 0 deletions tests/headers/nested-template-typedef.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
template<typename T>
class Foo {
public:
template<typename U>
struct Bar {
typedef Foo<U> FooU;
};
};

0 comments on commit d1d2eb6

Please sign in to comment.