From 8b52ed590e85f04700b3cfbeeeade63ec4109909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Mon, 9 Nov 2020 14:50:23 +0100 Subject: [PATCH] Clang import: Better handling of const methods --- lib/clangimport.cpp | 36 +++++++++++++++++++++++------------- lib/symboldatabase.cpp | 5 ++++- lib/symboldatabase.h | 2 +- test/testclangimport.cpp | 14 ++++++++++++++ 4 files changed, 42 insertions(+), 15 deletions(-) diff --git a/lib/clangimport.cpp b/lib/clangimport.cpp index e35db70a9..d0e95f239 100644 --- a/lib/clangimport.cpp +++ b/lib/clangimport.cpp @@ -306,6 +306,7 @@ namespace clangimport { Token *createTokensVarDecl(TokenList *tokenList); std::string getSpelling() const; std::string getType(int index = 0) const; + std::string getFullType(int index = 0) const; bool isDefinition() const; std::string getTemplateParameters() const; const Scope *getNestedInScope(TokenList *tokenList); @@ -357,18 +358,7 @@ std::string clangimport::AstNode::getSpelling() const std::string clangimport::AstNode::getType(int index) const { - int typeIndex = 1; - while (typeIndex < mExtTokens.size() && mExtTokens[typeIndex][0] != '\'') - typeIndex++; - if (typeIndex >= mExtTokens.size()) - return ""; - std::string type = mExtTokens[typeIndex]; - if (type.find("\':\'") != std::string::npos) { - if (index == 0) - type.erase(type.find("\':\'") + 1); - else - type.erase(0, type.find("\':\'") + 2); - } + std::string type = getFullType(index); if (type.find(" (") != std::string::npos) { std::string::size_type pos = type.find(" ("); type[pos] = '\''; @@ -387,6 +377,23 @@ std::string clangimport::AstNode::getType(int index) const return unquote(type); } +std::string clangimport::AstNode::getFullType(int index) const +{ + int typeIndex = 1; + while (typeIndex < mExtTokens.size() && mExtTokens[typeIndex][0] != '\'') + typeIndex++; + if (typeIndex >= mExtTokens.size()) + return ""; + std::string type = mExtTokens[typeIndex]; + if (type.find("\':\'") != std::string::npos) { + if (index == 0) + type.erase(type.find("\':\'") + 1); + else + type.erase(0, type.find("\':\'") + 2); + } + return type; +} + bool clangimport::AstNode::isDefinition() const { return contains(mExtTokens, "definition"); @@ -1188,7 +1195,7 @@ void clangimport::AstNode::createTokensFunctionDecl(TokenList *tokenList) mData->ref(addr, nameToken); } if (!nameToken->function()) { - nestedIn->functionList.push_back(Function(nameToken)); + nestedIn->functionList.push_back(Function(nameToken, unquote(getFullType()))); mData->funcDecl(mExtTokens.front(), nameToken, &nestedIn->functionList.back()); if (nodeType == CXXConstructorDecl) nestedIn->functionList.back().type = Function::Type::eConstructor; @@ -1254,6 +1261,9 @@ void clangimport::AstNode::createTokensFunctionDecl(TokenList *tokenList) par1->link(par2); par2->link(par1); + if (function->isConst()) + addtoken(tokenList, "const"); + // Function body if (hasBody) { symbolDatabase->functionScopes.push_back(scope); diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 8eaeed7e6..0bbb49de4 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -2177,7 +2177,7 @@ Function::Function(const Tokenizer *mTokenizer, } } -Function::Function(const Token *tokenDef) +Function::Function(const Token *tokenDef, const std::string &clangType) : tokenDef(tokenDef), argDef(nullptr), token(nullptr), @@ -2205,6 +2205,9 @@ Function::Function(const Token *tokenDef) } setFlags(tokenDef, tokenDef->scope()); + + if (endsWith(clangType, " const", 6)) + isConst(true); } const Token *Function::setFlags(const Token *tok1, const Scope *scope) diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index d07e5e6e6..2c16f2c44 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -739,7 +739,7 @@ public: enum Type { eConstructor, eCopyConstructor, eMoveConstructor, eOperatorEqual, eDestructor, eFunction, eLambda }; Function(const Tokenizer *mTokenizer, const Token *tok, const Scope *scope, const Token *tokDef, const Token *tokArgDef); - explicit Function(const Token *tokenDef); + Function(const Token *tokenDef, const std::string &clangType); const std::string &name() const { return tokenDef->str(); diff --git a/test/testclangimport.cpp b/test/testclangimport.cpp index a823fe187..f4bddde9b 100644 --- a/test/testclangimport.cpp +++ b/test/testclangimport.cpp @@ -106,6 +106,7 @@ private: TEST_CASE(symbolDatabaseFunction1); TEST_CASE(symbolDatabaseFunction2); TEST_CASE(symbolDatabaseFunction3); + TEST_CASE(symbolDatabaseFunctionConst); TEST_CASE(symbolDatabaseNodeType1); TEST_CASE(valueFlow1); @@ -1044,6 +1045,19 @@ private: ASSERT_EQUALS(true, func->getArgumentVar(1)->isReference()); } + void symbolDatabaseFunctionConst() { + const char clang[] = "`-CXXRecordDecl 0x7e2d98 <1.cpp:2:1, line:5:1> line:2:7 class foo definition\n" + " `-CXXMethodDecl 0x7e3000 col:8 f 'void () const'"; + + GET_SYMBOL_DB(clang); + + // There is a function f that is const + ASSERT_EQUALS(2, db->scopeList.size()); + ASSERT_EQUALS(1, db->scopeList.back().functionList.size()); + const Function &func = db->scopeList.back().functionList.back(); + ASSERT(func.isConst()); + } + void symbolDatabaseNodeType1() { const char clang[] = "`-FunctionDecl 0x32438c0 line:5:6 foo 'a::b (a::b)'\n" " |-ParmVarDecl 0x32437b0 col:15 used i 'a::b':'long'\n"