diff --git a/src/libclang/namespace_parser.cpp b/src/libclang/namespace_parser.cpp index 4d28f2c..864b730 100644 --- a/src/libclang/namespace_parser.cpp +++ b/src/libclang/namespace_parser.cpp @@ -128,17 +128,34 @@ namespace case CXCursor_TypeRef: case CXCursor_TemplateRef: case CXCursor_MemberRef: - case CXCursor_OverloadedDeclRef: case CXCursor_VariableRef: + { + auto referenced = clang_getCursorReferenced(child); + result = detail::get_entity_id(referenced); break; + } + + case CXCursor_OverloadedDeclRef: + { + auto size = clang_getNumOverloadedDecls(child); + DEBUG_ASSERT(size >= 1u, detail::assert_handler{}); + if (size == 1u) + result = detail::get_entity_id( + clang_getOverloadedDecl(child, 0u)); + else + result = detail::get_entity_id( + clang_getCursorReferenced(child)); + break; + } + + case CXCursor_NamespaceRef: + break; // wait for children default: DEBUG_UNREACHABLE(detail::parse_error_handler{}, cur, "unexpected target for using declaration"); } - auto referenced = clang_getCursorReferenced(child); - result = detail::get_entity_id(referenced); }, true); return result; diff --git a/test/cpp_namespace.cpp b/test/cpp_namespace.cpp index 23a030d..66032c0 100644 --- a/test/cpp_namespace.cpp +++ b/test/cpp_namespace.cpp @@ -164,5 +164,63 @@ using namespace outer::ns; TEST_CASE("cpp_using_declaration") { - // TODO: write test when actual entities can be parsed + // TODO: test overloaded functions + auto code = R"( +namespace ns1 +{ + enum a {}; + enum b {}; +} + +namespace ns2 +{ + enum a {}; + enum b {}; +} + +using ns1::a; +using ns2::b; + +namespace outer +{ + namespace ns + { + enum c {}; + } + + using ns::c; +} + +using outer::ns::c; +using outer::c; +)"; + + cpp_entity_index idx; + auto check_declaration = [&](const cpp_using_declaration& decl, const char* target_full_name) { + auto target = decl.target(); + + auto entity = target.get(idx); + REQUIRE(entity); + REQUIRE(full_name(entity.value()) == target_full_name); + }; + + auto file = parse(idx, "cpp_using_declaration.cpp", code); + auto count = test_visit(*file, [&](const cpp_using_declaration& decl) { + if (decl.target().name() == "ns1::a") + check_declaration(decl, "ns1::a"); + else if (decl.target().name() == "ns2::b") + check_declaration(decl, "ns2::b"); + else if (decl.target().name() == "ns::c") + { + check_parent(decl, "outer", ""); + check_declaration(decl, "outer::ns::c"); + } + else if (decl.target().name() == "outer::ns::c") + check_declaration(decl, "outer::ns::c"); + else if (decl.target().name() == "outer::c") + check_declaration(decl, "outer::ns::c"); + else + REQUIRE(false); + }); + REQUIRE(count == 5u); }