diff options
author | Patrick Walton <pcwalton@fb.com> | 2021-07-30 19:41:10 -0700 |
---|---|---|
committer | Emilio Cobos Álvarez <emilio@crisal.io> | 2021-07-31 13:33:42 +0200 |
commit | d1d2eb62d36c462416a606c680e6b4ba4716daab (patch) | |
tree | eff269a021df4cacbd8d84d3d8d4a8d3e40aace7 | |
parent | 546454625caa66eddc9400bc7a1048edf2a9fbc8 (diff) |
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.
-rw-r--r-- | src/ir/comp.rs | 33 | ||||
-rw-r--r-- | tests/expectations/tests/nested-template-typedef.rs | 17 | ||||
-rw-r--r-- | tests/headers/nested-template-typedef.hpp | 8 |
3 files changed, 44 insertions, 14 deletions
diff --git a/src/ir/comp.rs b/src/ir/comp.rs index e554f9a8..97983308 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -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 => { diff --git a/tests/expectations/tests/nested-template-typedef.rs b/tests/expectations/tests/nested-template-typedef.rs new file mode 100644 index 00000000..ab761d28 --- /dev/null +++ b/tests/expectations/tests/nested-template-typedef.rs @@ -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, +} diff --git a/tests/headers/nested-template-typedef.hpp b/tests/headers/nested-template-typedef.hpp new file mode 100644 index 00000000..8c83de5b --- /dev/null +++ b/tests/headers/nested-template-typedef.hpp @@ -0,0 +1,8 @@ +template<typename T> +class Foo { +public: + template<typename U> + struct Bar { + typedef Foo<U> FooU; + }; +}; |