summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ir/comp.rs3
-rw-r--r--src/ir/item.rs3
-rw-r--r--src/ir/ty.rs50
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),