logic: fix recording template parameter as local symbol instead of qualifier (#824)

This commit is contained in:
Malte Langkabel
2019-12-03 19:35:38 +01:00
committed by GitHub
parent fa6dd6c9e1
commit e6e0ecbcf5
2 changed files with 49 additions and 12 deletions
@@ -75,7 +75,7 @@ void CxxAstVisitorComponentIndexer::beginTraverseNestedNameSpecifierLoc(
if (symbolKind != SYMBOL_KIND_MAX) if (symbolKind != SYMBOL_KIND_MAX)
{ {
Id symbolId = getOrCreateSymbolId(recordDecl); const Id symbolId = getOrCreateSymbolId(recordDecl);
m_client->recordSymbolKind(symbolId, symbolKind); m_client->recordSymbolKind(symbolId, symbolKind);
m_client->recordLocation( m_client->recordLocation(
symbolId, getParseLocation(loc.getLocalBeginLoc()), ParseLocationType::QUALIFIER); symbolId, getParseLocation(loc.getLocalBeginLoc()), ParseLocationType::QUALIFIER);
@@ -83,9 +83,22 @@ void CxxAstVisitorComponentIndexer::beginTraverseNestedNameSpecifierLoc(
} }
else if (const clang::Type* type = loc.getNestedNameSpecifier()->getAsType()) else if (const clang::Type* type = loc.getNestedNameSpecifier()->getAsType())
{ {
Id symbolId = getOrCreateSymbolId(type); const ParseLocation parseLocation = getParseLocation(loc.getLocalBeginLoc());
m_client->recordLocation(
symbolId, getParseLocation(loc.getLocalBeginLoc()), ParseLocationType::QUALIFIER); if (const clang::TemplateTypeParmType* tpt =
clang::dyn_cast_or_null<clang::TemplateTypeParmType>(type))
{
clang::TemplateTypeParmDecl* d = tpt->getDecl();
if (d)
{
m_client->recordLocalSymbol(getLocalSymbolName(d->getLocation()), parseLocation);
}
}
else
{
const Id symbolId = getOrCreateSymbolId(type);
m_client->recordLocation(symbolId, parseLocation, ParseLocationType::QUALIFIER);
}
} }
} }
} }
@@ -104,10 +117,16 @@ void CxxAstVisitorComponentIndexer::beginTraverseTemplateArgumentLoc(
const ParseLocation parseLocation = getParseLocation(loc.getLocation()); const ParseLocation parseLocation = getParseLocation(loc.getLocation());
if (templateTemplateArgumentName.isDependent()) if (templateTemplateArgumentName.isDependent())
{ {
m_client->recordLocalSymbol( clang::SourceLocation declLocation;
getLocalSymbolName( if (templateTemplateArgumentName.getAsTemplateDecl())
templateTemplateArgumentName.getAsTemplateDecl()->getLocation()), {
parseLocation); declLocation = templateTemplateArgumentName.getAsTemplateDecl()->getLocation();
}
else
{
declLocation = loc.getLocation();
}
m_client->recordLocalSymbol(getLocalSymbolName(declLocation), parseLocation);
} }
else else
{ {
@@ -343,8 +362,9 @@ void CxxAstVisitorComponentIndexer::visitFunctionDecl(clang::FunctionDecl* d)
->isExplicitSpecialization()) ->isExplicitSpecialization())
{ {
// record edge from Foo<int>::bar<float>() to Foo<T>::bar<U>() instead of recording // record edge from Foo<int>::bar<float>() to Foo<T>::bar<U>() instead of recording
// an edge from Foo<int>::bar<float>() to Foo<int>::bar<U>() because there is not "written" // an edge from Foo<int>::bar<float>() to Foo<int>::bar<U>() because there is not
// code for Foo<int>::bar<U>() if Foo<int> is an implicit template specialization. // "written" code for Foo<int>::bar<U>() if Foo<int> is an implicit template
// specialization.
if (clang::CXXRecordDecl* declaringRecordDecl = if (clang::CXXRecordDecl* declaringRecordDecl =
clang::dyn_cast_or_null<clang::CXXRecordDecl>(d->getParent())) clang::dyn_cast_or_null<clang::CXXRecordDecl>(d->getParent()))
{ {
+19 -2
View File
@@ -844,8 +844,8 @@ TEST_CASE("cxx parser finds template argument of dependent non type template par
// ); // );
// TS_ASSERT(utility::containsElement<std::wstring>( // TS_ASSERT(utility::containsElement<std::wstring>(
// client->typeUses, // TODO: record edge between vector<int, Alloc<int>> and Alloc<int> (this is // client->typeUses, // TODO: record edge between vector<int, Alloc<int>> and Alloc<int> (this
//an issue because we dont have any typeloc for this edge -.- //is an issue because we dont have any typeloc for this edge -.-
// )); // ));
//} //}
@@ -2621,6 +2621,23 @@ TEST_CASE("cxx parser finds typedef in other class that depends on own template
client->typeUses, L"B<int>::type f -> B<int>::type <13:9 13:12>")); client->typeUses, L"B<int>::type f -> B<int>::type <13:9 13:12>"));
} }
TEST_CASE("cxx parser finds usage of template parameter in qualifier of other symbol")
{
std::shared_ptr<TestIntermediateStorage> client = parseCode(
"template <typename T>\n"
"struct find_if_impl;\n"
"\n"
"template <typename R, typename S>\n"
"struct find_if\n"
"{\n"
" template <typename... Ts>\n"
" using f = typename find_if_impl<S>::template f<R::template f, Ts...>;\n"
"};\n");
REQUIRE(utility::containsElement<std::wstring>(
client->localSymbols, L"input.cc<4:20> <8:49 8:49>"));
}
TEST_CASE("cxx parser finds use of dependent template specialization type") TEST_CASE("cxx parser finds use of dependent template specialization type")
{ {
std::shared_ptr<TestIntermediateStorage> client = parseCode( std::shared_ptr<TestIntermediateStorage> client = parseCode(