logic: implemented recording references to symbols inside lambda capture lists

This commit is contained in:
malte_langkabel
2016-11-17 17:25:30 +01:00
parent 61df5ed96c
commit 6b1e3c6b7f
3 changed files with 87 additions and 24 deletions
+55 -23
View File
@@ -310,7 +310,33 @@ bool CxxAstVisitor::TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc
return base::TraverseTemplateArgumentLoc(loc);
}
void CxxAstVisitor::traverseDeclContextHelper(clang::DeclContext *d)
bool CxxAstVisitor::TraverseLambdaCapture(clang::LambdaExpr *lambdaExpr, const clang::LambdaCapture *capture)
{
clang::VarDecl* d = capture->getCapturedVar();
if (lambdaExpr->isInitCapture(capture))
{
TraverseDecl(d);
}
else
{
SymbolKind symbolKind = getSymbolKind(d);
if (symbolKind == SYMBOL_LOCAL_VARIABLE || symbolKind == SYMBOL_PARAMETER)
{
if (!d->getNameAsString().empty()) // don't record anonymous parameters
{
ParseLocation declLocation = getParseLocation(d->getLocation());
std::string name =
declLocation.filePath.fileName() + "<" +
std::to_string(declLocation.startLineNumber) + ":" +
std::to_string(declLocation.startColumnNumber) + ">";
m_client->onLocalSymbolParsed(name, getParseLocation(capture->getLocation()));
}
}
}
return true;
}
void CxxAstVisitor::traverseDeclContextHelper(clang::DeclContext* d)
{
if (!d)
return;
@@ -444,28 +470,7 @@ bool CxxAstVisitor::VisitVarDecl(clang::VarDecl* d)
{
if (shouldVisitDecl(d))
{
SymbolKind symbolKind = SYMBOL_KIND_MAX;
if (llvm::isa<clang::ParmVarDecl>(d))
{
symbolKind = SYMBOL_PARAMETER;
}
else if (d->getParentFunctionOrMethod() == NULL)
{
if (d->getAccess() == clang::AS_none)
{
symbolKind = SYMBOL_GLOBAL_VARIABLE;
}
else
{
symbolKind = SYMBOL_FIELD;
}
}
else
{
symbolKind = SYMBOL_LOCAL_VARIABLE;
}
SymbolKind symbolKind = getSymbolKind(d);
if (symbolKind == SYMBOL_LOCAL_VARIABLE || symbolKind == SYMBOL_PARAMETER)
{
if (!d->getNameAsString().empty()) // don't record anonymous parameters
@@ -1225,3 +1230,30 @@ ReferenceKind CxxAstVisitor::consumeDeclRefContextKind()
}
return refKind;
}
SymbolKind CxxAstVisitor::getSymbolKind(clang::VarDecl* d)
{
SymbolKind symbolKind = SYMBOL_KIND_MAX;
if (llvm::isa<clang::ParmVarDecl>(d))
{
symbolKind = SYMBOL_PARAMETER;
}
else if (d->getParentFunctionOrMethod() == NULL)
{
if (d->getAccess() == clang::AS_none)
{
symbolKind = SYMBOL_GLOBAL_VARIABLE;
}
else
{
symbolKind = SYMBOL_FIELD;
}
}
else
{
symbolKind = SYMBOL_LOCAL_VARIABLE;
}
return symbolKind;
}
+3 -1
View File
@@ -83,7 +83,8 @@ public:
virtual bool TraverseTemplateSpecializationTypeLoc(clang::TemplateSpecializationTypeLoc loc);
virtual bool TraverseUnresolvedLookupExpr(clang::UnresolvedLookupExpr* s);
virtual bool TraverseTemplateArgumentLoc(const clang::TemplateArgumentLoc& loc);
void traverseDeclContextHelper(clang::DeclContext *d);
virtual bool TraverseLambdaCapture(clang::LambdaExpr* lambdaExpr, const clang::LambdaCapture* capture);
void traverseDeclContextHelper(clang::DeclContext* d);
bool TraverseCallCommon(clang::CallExpr* s);
// Visitor methods. These actually record stuff and store it in the database.
@@ -129,6 +130,7 @@ protected:
private:
ReferenceKind consumeDeclRefContextKind();
SymbolKind getSymbolKind(clang::VarDecl* d);
typedef clang::RecursiveASTVisitor<CxxAstVisitor> base;
+29
View File
@@ -933,6 +933,20 @@ public:
TS_ASSERT_EQUALS(client->functions[1], "int lambdaWrapper::lambda at 3:2(int) <3:14 <3:2 3:2> 3:36>");
}
void test_cxx_parser_finds_local_variable_declared_in_lambda_capture()
{
std::shared_ptr<TestParserClient> client = parseCode(
"void lambdaWrapper()\n"
"{\n"
" [x(42)]() { return x; };\n"
"}\n"
);
TS_ASSERT_EQUALS(client->localSymbols.size(), 2);
TS_ASSERT_EQUALS(client->localSymbols[0], "input.cc<3:3> <3:3 3:3>");
TS_ASSERT_EQUALS(client->localSymbols[1], "input.cc<3:3> <3:21 3:21>");
}
void test_cxx_parser_finds_definition_of_local_symbol_in_function_parameter_list()
{
std::shared_ptr<TestParserClient> client = parseCode(
@@ -2940,6 +2954,21 @@ public:
TS_ASSERT_EQUALS(client->calls[1], "void lambdaCaller::lambda at 4:2() const -> void func() <6:3 6:6>");
}
void test_cxx_parser_finds_local_variable_in_lambda_capture()
{
std::shared_ptr<TestParserClient> client = parseCode(
"void lambdaWrapper()\n"
"{\n"
" int x = 2;\n"
" [x]() { return 1; }();\n"
"}\n"
);
TS_ASSERT_EQUALS(client->localSymbols.size(), 2);
TS_ASSERT_EQUALS(client->localSymbols[0], "input.cc<3:6> <3:6 3:6>");
TS_ASSERT_EQUALS(client->localSymbols[1], "input.cc<3:6> <4:3 4:3>");
}
void test_cxx_parser_finds_template_argument_of_unresolved_lookup_expression_as_type_use()
{
std::shared_ptr<TestParserClient> client = parseCode(