diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/ir/comp.rs | 3 | ||||
-rw-r--r-- | src/ir/item.rs | 3 | ||||
-rw-r--r-- | src/ir/ty.rs | 50 |
3 files changed, 52 insertions, 4 deletions
diff --git a/src/ir/comp.rs b/src/ir/comp.rs index 41e5c3d3..bd794a98 100644 --- a/src/ir/comp.rs +++ b/src/ir/comp.rs @@ -635,7 +635,7 @@ impl CompInfo { ci.has_vtable = cur.is_virtual_base(); } let type_id = - Item::from_ty(&cur.cur_type(), None, None, ctx) + Item::from_ty(&cur.cur_type(), Some(cur), None, ctx) .expect("BaseSpecifier"); ci.base_members.push(type_id); } @@ -763,6 +763,7 @@ impl CompInfo { CXCursor_UnionDecl => CompKind::Union, CXCursor_ClassDecl | CXCursor_StructDecl => CompKind::Struct, + CXCursor_CXXBaseSpecifier | CXCursor_ClassTemplatePartialSpecialization | CXCursor_ClassTemplate => { match cursor.template_kind() { diff --git a/src/ir/item.rs b/src/ir/item.rs index c6d80a08..691cfec2 100644 --- a/src/ir/item.rs +++ b/src/ir/item.rs @@ -1043,8 +1043,7 @@ impl ClangItemParser for Item { } } // If we have recursed into the AST all we know, and we still - // haven't found what we've got, let's - // just make a named type. + // haven't found what we've got, let's just make a named type. // // This is what happens with some template members, for example. // diff --git a/src/ir/ty.rs b/src/ir/ty.rs index 77dc61be..57490cc2 100644 --- a/src/ir/ty.rs +++ b/src/ir/ty.rs @@ -540,8 +540,56 @@ impl Type { } else if let Some(location) = location { match location.kind() { CXCursor_ClassTemplatePartialSpecialization | + CXCursor_CXXBaseSpecifier | CXCursor_ClassTemplate => { - name = location.spelling(); + if location.kind() == CXCursor_CXXBaseSpecifier { + // In the case we're parsing a base specifier + // inside an unexposed or invalid type, it means + // that we're parsing one of two things: + // + // * A template parameter. + // * A complex class that isn't exposed. + // + // This means, unfortunately, that there's no + // good way to differentiate between them. + // + // Probably we could try to look at the + // declaration and complicate more this logic, + // but we'll keep it simple... if it's a valid + // C++ identifier, we'll consider it as a + // template parameter. + // + // This is because: + // + // * We expect every other base that is a + // proper identifier (that is, a simple + // struct/union declaration), to be exposed, + // so this path can't be reached in that + // case. + // + // * Quite conveniently, complex base + // specifiers preserve their full names (that + // is: Foo<T> instead of Foo). We can take + // advantage of this. + // + // If we find some edge case where this doesn't + // work (which I guess is unlikely, see the + // different test cases[1][2][3][4]), we'd need + // to find more creative ways of differentiating + // these two cases. + // + // [1]: inherit_named.hpp + // [2]: forward-inherit-struct-with-fields.hpp + // [3]: forward-inherit-struct.hpp + // [4]: inherit-namespaced.hpp + if location.spelling() + .chars() + .all(|c| c.is_alphanumeric() || c == '_') { + return Err(ParseError::Recurse); + } + } else { + name = location.spelling(); + } let complex = CompInfo::from_ty(potential_id, ty, Some(location), |