Fix member variable type which is typedef in same class

Type spelling included all scopes. See foonathan/standardese#82.
This commit is contained in:
Jonathan Müller 2017-12-07 20:39:04 +01:00
commit 2b3ddf360b
2 changed files with 89 additions and 60 deletions

View file

@ -85,9 +85,29 @@ namespace
return false;
}
std::string get_type_spelling(const CXType& type)
bool need_to_remove_scope(const CXCursor& cur, const CXType& type)
{
return detail::cxstring(clang_getTypeSpelling(type)).c_str();
if (type.kind != CXType_Typedef)
return false;
// typedefs declared in the same class include all scopes in the name)
// (because of course they do)
auto parent = clang_getCursorSemanticParent(cur);
auto decl_parent = clang_getCursorSemanticParent(clang_getTypeDeclaration(type));
return clang_equalCursors(parent, decl_parent) != 0;
}
std::string get_type_spelling(const CXCursor& cur, const CXType& type)
{
auto spelling = detail::cxstring(clang_getTypeSpelling(type)).std_str();
if (need_to_remove_scope(cur, type))
{
auto colon = spelling.rfind(':');
if (colon != std::string::npos)
spelling.erase(0, colon + 1u);
}
return spelling;
}
// const/volatile at the end (because people do that apparently!)
@ -186,9 +206,9 @@ namespace
}
template <typename Builder>
std::unique_ptr<cpp_type> make_leave_type(const CXType& type, Builder b)
std::unique_ptr<cpp_type> make_leave_type(const CXCursor& cur, const CXType& type, Builder b)
{
auto spelling = get_type_spelling(type);
auto spelling = get_type_spelling(cur, type);
// check for cv qualifiers on the leave type
auto prefix = prefix_cv(spelling);
@ -219,14 +239,14 @@ namespace
std::unique_ptr<cpp_type> parse_type_impl(const detail::parse_context& context,
const CXCursor& cur, const CXType& type);
std::unique_ptr<cpp_expression> parse_array_size(const CXType& type)
std::unique_ptr<cpp_expression> parse_array_size(const CXCursor& cur, const CXType& type)
{
auto size = clang_getArraySize(type);
if (size != -1)
return cpp_literal_expression::build(cpp_builtin_type::build(cpp_ulonglong),
std::to_string(size));
auto spelling = get_type_spelling(type);
auto spelling = get_type_spelling(cur, type);
DEBUG_ASSERT(spelling.size() > 2u && spelling.back() == ']', detail::parse_error_handler{},
type, "unexpected token");
@ -269,7 +289,7 @@ namespace
// only downside of this workaround: we've stripped away typedefs
}
auto size = parse_array_size(canonical); // type may not work, see above
auto size = parse_array_size(cur, canonical); // type may not work, see above
return cpp_array_type::build(parse_type_impl(context, cur, value_type), std::move(size));
}
@ -320,7 +340,7 @@ namespace
std::unique_ptr<cpp_type> parse_member_pointee_type(const detail::parse_context& context,
const CXCursor& cur, const CXType& type)
{
auto spelling = get_type_spelling(type);
auto spelling = get_type_spelling(cur, type);
auto ref = member_function_ref_qualifier(spelling);
auto cv = suffix_cv(spelling);
@ -383,28 +403,32 @@ namespace
// doesn't respect cv qualifiers properly
auto result =
make_leave_type(type, [&](std::string&& type_spelling) -> std::unique_ptr<cpp_type> {
// look at the template parameters,
// see if we find a matching one
auto param = clang_getNullCursor();
detail::visit_children(templ, [&](const CXCursor& child) {
if (clang_getCursorKind(child) == CXCursor_TemplateTypeParameter
&& get_type_spelling(clang_getCursorType(child)) == type_spelling)
{
// found one
DEBUG_ASSERT(clang_Cursor_isNull(param), detail::assert_handler{});
param = child;
}
});
make_leave_type(cur, type,
[&](std::string&& type_spelling) -> std::unique_ptr<cpp_type> {
// look at the template parameters,
// see if we find a matching one
auto param = clang_getNullCursor();
detail::visit_children(templ, [&](const CXCursor& child) {
if (clang_getCursorKind(child) == CXCursor_TemplateTypeParameter
&& get_type_spelling(child, clang_getCursorType(child))
== type_spelling)
{
// found one
DEBUG_ASSERT(clang_Cursor_isNull(param),
detail::assert_handler{});
param = child;
}
});
if (clang_Cursor_isNull(param))
return nullptr;
else
// found matching parameter
return cpp_template_parameter_type::build(
cpp_template_type_parameter_ref(detail::get_entity_id(param),
std::move(type_spelling)));
});
if (clang_Cursor_isNull(param))
return nullptr;
else
// found matching parameter
return cpp_template_parameter_type::build(
cpp_template_type_parameter_ref(detail::get_entity_id(
param),
std::move(type_spelling)));
});
if (result)
return result;
@ -442,7 +466,7 @@ namespace
std::unique_ptr<cpp_type> try_parse_instantiation_type(const detail::parse_context&,
const CXCursor& cur, const CXType& type)
{
return make_leave_type(type, [&](std::string&& spelling) -> std::unique_ptr<cpp_type> {
return make_leave_type(cur, type, [&](std::string&& spelling) -> std::unique_ptr<cpp_type> {
auto ptr = spelling.c_str();
std::string templ_name;
@ -478,7 +502,7 @@ namespace
if (clang_isExpression(clang_getCursorKind(cur)))
return nullptr; // don't use decltype here
return make_leave_type(type, [&](std::string&& spelling) -> std::unique_ptr<cpp_type> {
return make_leave_type(cur, type, [&](std::string&& spelling) -> std::unique_ptr<cpp_type> {
if (!remove_prefix(spelling, "decltype(", false))
return nullptr;
remove_suffix(spelling, "...", false); // variadic decltype. fun
@ -578,93 +602,93 @@ namespace
return ptype;
// fallthrough
case CXType_Complex:
return cpp_unexposed_type::build(get_type_spelling(type).c_str());
return cpp_unexposed_type::build(get_type_spelling(cur, type).c_str());
case CXType_Void:
return make_leave_type(type,
return make_leave_type(cur, type,
[](std::string&&) { return cpp_builtin_type::build(cpp_void); });
case CXType_Bool:
return make_leave_type(type,
return make_leave_type(cur, type,
[](std::string&&) { return cpp_builtin_type::build(cpp_bool); });
case CXType_UChar:
return make_leave_type(type, [](std::string&&) {
return make_leave_type(cur, type, [](std::string&&) {
return cpp_builtin_type::build(cpp_uchar);
});
case CXType_UShort:
return make_leave_type(type, [](std::string&&) {
return make_leave_type(cur, type, [](std::string&&) {
return cpp_builtin_type::build(cpp_ushort);
});
case CXType_UInt:
return make_leave_type(type,
return make_leave_type(cur, type,
[](std::string&&) { return cpp_builtin_type::build(cpp_uint); });
case CXType_ULong:
return make_leave_type(type, [](std::string&&) {
return make_leave_type(cur, type, [](std::string&&) {
return cpp_builtin_type::build(cpp_ulong);
});
case CXType_ULongLong:
return make_leave_type(type, [](std::string&&) {
return make_leave_type(cur, type, [](std::string&&) {
return cpp_builtin_type::build(cpp_ulonglong);
});
case CXType_UInt128:
return make_leave_type(type, [](std::string&&) {
return make_leave_type(cur, type, [](std::string&&) {
return cpp_builtin_type::build(cpp_uint128);
});
case CXType_SChar:
return make_leave_type(type, [](std::string&&) {
return make_leave_type(cur, type, [](std::string&&) {
return cpp_builtin_type::build(cpp_schar);
});
case CXType_Short:
return make_leave_type(type, [](std::string&&) {
return make_leave_type(cur, type, [](std::string&&) {
return cpp_builtin_type::build(cpp_short);
});
case CXType_Int:
return make_leave_type(type,
return make_leave_type(cur, type,
[](std::string&&) { return cpp_builtin_type::build(cpp_int); });
case CXType_Long:
return make_leave_type(type,
return make_leave_type(cur, type,
[](std::string&&) { return cpp_builtin_type::build(cpp_long); });
case CXType_LongLong:
return make_leave_type(type, [](std::string&&) {
return make_leave_type(cur, type, [](std::string&&) {
return cpp_builtin_type::build(cpp_longlong);
});
case CXType_Int128:
return make_leave_type(type, [](std::string&&) {
return make_leave_type(cur, type, [](std::string&&) {
return cpp_builtin_type::build(cpp_int128);
});
case CXType_Float:
return make_leave_type(type, [](std::string&&) {
return make_leave_type(cur, type, [](std::string&&) {
return cpp_builtin_type::build(cpp_float);
});
case CXType_Double:
return make_leave_type(type, [](std::string&&) {
return make_leave_type(cur, type, [](std::string&&) {
return cpp_builtin_type::build(cpp_double);
});
case CXType_LongDouble:
return make_leave_type(type, [](std::string&&) {
return make_leave_type(cur, type, [](std::string&&) {
return cpp_builtin_type::build(cpp_longdouble);
});
case CXType_Float128:
return make_leave_type(type, [](std::string&&) {
return make_leave_type(cur, type, [](std::string&&) {
return cpp_builtin_type::build(cpp_float128);
});
case CXType_Char_U:
case CXType_Char_S:
return make_leave_type(type,
return make_leave_type(cur, type,
[](std::string&&) { return cpp_builtin_type::build(cpp_char); });
case CXType_Char16:
return make_leave_type(type, [](std::string&&) {
return make_leave_type(cur, type, [](std::string&&) {
return cpp_builtin_type::build(cpp_char16);
});
case CXType_Char32:
return make_leave_type(type, [](std::string&&) {
return make_leave_type(cur, type, [](std::string&&) {
return cpp_builtin_type::build(cpp_char32);
});
case CXType_WChar:
return make_leave_type(type, [](std::string&&) {
return make_leave_type(cur, type, [](std::string&&) {
return cpp_builtin_type::build(cpp_wchar);
});
case CXType_NullPtr:
return make_leave_type(type, [](std::string&&) {
return make_leave_type(cur, type, [](std::string&&) {
return cpp_builtin_type::build(cpp_nullptr);
});
@ -676,7 +700,7 @@ namespace
case CXType_Record:
case CXType_Enum:
case CXType_Typedef:
return make_leave_type(type, [&](std::string&& spelling) {
return make_leave_type(cur, type, [&](std::string&& spelling) {
auto decl = clang_getTypeDeclaration(type);
if (remove_prefix(spelling, "(anonymous", false))
spelling = ""; // anonymous type
@ -689,7 +713,7 @@ namespace
auto pointee = parse_type_impl(context, cur, clang_getPointeeType(type));
auto pointer = cpp_pointer_type::build(std::move(pointee));
auto spelling = get_type_spelling(type);
auto spelling = get_type_spelling(cur, type);
auto cv = suffix_cv(spelling);
return make_cv_qualified(std::move(pointer), cv);
}
@ -714,7 +738,8 @@ namespace
return cpp_pointer_type::build(parse_member_pointee_type(context, cur, type));
case CXType_Auto:
return make_leave_type(type, [&](std::string&&) { return cpp_auto_type::build(); });
return make_leave_type(cur, type,
[&](std::string&&) { return cpp_auto_type::build(); });
}
DEBUG_UNREACHABLE(detail::assert_handler{});

View file

@ -24,7 +24,9 @@ using struct_=int;
struct_ var2;
struct foo{
int a;
using my_int=int;
my_int a;
auto func(int)->int(*(*)(int))[42];
@ -66,7 +68,9 @@ struct_ var2;
struct foo
{
int a;
using my_int = int;
my_int a;
auto func(int) -> int(*(*)(int))[42];