From b71e73bfb58a7c70d6e1561b258b4f648246a374 Mon Sep 17 00:00:00 2001 From: Patrick Walton Date: Fri, 30 Jul 2021 17:25:08 -0700 Subject: Detect and avoid cycles when resolving items. These can happen in certain cases involving incomplete qualified dependent types. To avoid looping forever, we need to check for them. Closes #2085. --- src/ir/context.rs | 8 ++++++++ tests/expectations/tests/qualified-dependent-types.rs | 17 +++++++++++++++++ tests/headers/qualified-dependent-types.hpp | 16 ++++++++++++++++ 3 files changed, 41 insertions(+) create mode 100644 tests/expectations/tests/qualified-dependent-types.rs create mode 100644 tests/headers/qualified-dependent-types.hpp diff --git a/src/ir/context.rs b/src/ir/context.rs index bd21058c..44df063a 100644 --- a/src/ir/context.rs +++ b/src/ir/context.rs @@ -2723,8 +2723,16 @@ impl ItemResolver { assert!(ctx.collected_typerefs()); let mut id = self.id; + let mut seen_ids = HashSet::default(); loop { let item = ctx.resolve_item(id); + + // Detect cycles and bail out. These can happen in certain cases + // involving incomplete qualified dependent types (#2085). + if !seen_ids.insert(id) { + return item; + } + let ty_kind = item.as_type().map(|t| t.kind()); match ty_kind { Some(&TypeKind::ResolvedTypeRef(next_id)) diff --git a/tests/expectations/tests/qualified-dependent-types.rs b/tests/expectations/tests/qualified-dependent-types.rs new file mode 100644 index 00000000..f1b2c845 --- /dev/null +++ b/tests/expectations/tests/qualified-dependent-types.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 Bar { + pub _address: u8, +} diff --git a/tests/headers/qualified-dependent-types.hpp b/tests/headers/qualified-dependent-types.hpp new file mode 100644 index 00000000..fcdfc87c --- /dev/null +++ b/tests/headers/qualified-dependent-types.hpp @@ -0,0 +1,16 @@ +// Issue #2085. + +template +struct Foo; + +template +struct Bar {}; + +template +struct Bar { + using BarDependent = typename Foo::Dependent; + void method(const BarDependent &); +}; + +template +void Bar::method(const BarDependent &) {} -- cgit v1.2.3