summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Walton <pcwalton@fb.com>2021-07-30 19:41:10 -0700
committerEmilio Cobos Álvarez <emilio@crisal.io>2021-07-31 13:33:42 +0200
commitd1d2eb62d36c462416a606c680e6b4ba4716daab (patch)
treeeff269a021df4cacbd8d84d3d8d4a8d3e40aace7
parent546454625caa66eddc9400bc7a1048edf2a9fbc8 (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.rs33
-rw-r--r--tests/expectations/tests/nested-template-typedef.rs17
-rw-r--r--tests/headers/nested-template-typedef.hpp8
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;
+ };
+};