From 2b3ddf360b0415eb7abe7190cb8f8079ad0e1fb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonathan=20M=C3=BCller?= Date: Thu, 7 Dec 2017 20:39:04 +0100 Subject: [PATCH] Fix member variable type which is typedef in same class Type spelling included all scopes. See foonathan/standardese#82. --- src/libclang/type_parser.cpp | 141 +++++++++++++++++++++-------------- test/code_generator.cpp | 8 +- 2 files changed, 89 insertions(+), 60 deletions(-) diff --git a/src/libclang/type_parser.cpp b/src/libclang/type_parser.cpp index bfbd946..61abb86 100644 --- a/src/libclang/type_parser.cpp +++ b/src/libclang/type_parser.cpp @@ -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 - std::unique_ptr make_leave_type(const CXType& type, Builder b) + std::unique_ptr 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 parse_type_impl(const detail::parse_context& context, const CXCursor& cur, const CXType& type); - std::unique_ptr parse_array_size(const CXType& type) + std::unique_ptr 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 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 { - // 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 { + // 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 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 { + return make_leave_type(cur, type, [&](std::string&& spelling) -> std::unique_ptr { 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 { + return make_leave_type(cur, type, [&](std::string&& spelling) -> std::unique_ptr { 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{}); diff --git a/test/code_generator.cpp b/test/code_generator.cpp index d4e6dd5..0005a0f 100644 --- a/test/code_generator.cpp +++ b/test/code_generator.cpp @@ -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];