From 58076bc6720dca2a24dae0d7c5a45a4438d3a9eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Tue, 9 Jul 2019 17:32:19 +0200 Subject: [PATCH] SymbolDatabase: Better handling of smart pointers --- lib/symboldatabase.cpp | 69 ++++++++++++++++++++++++++++--------- test/testsymboldatabase.cpp | 18 ++++++++++ 2 files changed, 70 insertions(+), 17 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index af0a0822f..111902478 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1710,6 +1710,8 @@ void Variable::setValueType(const ValueType &valueType) if ((mValueType->pointer > 0) && (!isArray() || Token::Match(mNameToken->previous(), "( * %name% )"))) setFlag(fIsPointer, true); setFlag(fIsConst, mValueType->constness & (1U << mValueType->pointer)); + if (mValueType->smartPointerType) + setFlag(fIsSmartPointer, true); } const Type *Variable::smartPointerType() const @@ -1717,6 +1719,9 @@ const Type *Variable::smartPointerType() const if (!isSmartPointer()) return nullptr; + if (mValueType->smartPointerType) + return mValueType->smartPointerType; + // TODO: Cache result const Token *ptrType = typeStartToken(); while (Token::Match(ptrType, "%name%|::")) @@ -4939,6 +4944,13 @@ void SymbolDatabase::setValueType(Token *tok, const ValueType &valuetype) return; } + if (vt1 && vt1->smartPointerType && Token::Match(parent, ". %name% (") && parent->originalName() == "->" && !parent->next()->function()) { + const Scope *scope = valuetype.smartPointerType->classScope; + const Function *f = scope ? scope->findFunction(parent->next(), false) : nullptr; + if (f) + parent->next()->function(f); + } + if (parent->isAssignmentOp()) { if (vt1) setValueType(parent, *vt1); @@ -5085,24 +5097,47 @@ void SymbolDatabase::setValueType(Token *tok, const ValueType &valuetype) else break; } + + const Token *containerElementType = typeStart; + while (Token::Match(containerElementType, "%name%|::")) + containerElementType = containerElementType->next(); + + // Try to determine type of "auto" token. // TODO: Get type better - if (Token::Match(typeStart, "std :: %type% < %type% *| *| >")) { - ValueType autovt; - if (parsedecl(typeStart->tokAt(4), &autovt, mDefaultSignedness, mSettings)) { - setValueType(autoToken, autovt); - setAutoTokenProperties(autoToken); - ValueType varvt(autovt); - if (isconst) - varvt.constness |= 1; - setValueType(parent->previous(), varvt); - Variable * var = const_cast(parent->previous()->variable()); - if (var) { - var->setValueType(varvt); - const Type * type = typeStart->tokAt(4)->type(); - if (type && type->classScope && type->classScope->definedType) { - autoToken->type(type->classScope->definedType); - var->type(type->classScope->definedType); - } + bool setType = false; + ValueType autovt; + const Type *templateArgType = nullptr; // container element type / smart pointer type + if (Token::Match(containerElementType, "< %type% *| *| >")) { + if (parsedecl(containerElementType->next(), &autovt, mDefaultSignedness, mSettings)) { + setType = true; + templateArgType = containerElementType->next()->type(); + } + } else if (mSettings->library.isSmartPointer(containerElementType->next())) { + const Token *smartPointerTypeTok = containerElementType->next(); + while (Token::Match(smartPointerTypeTok, "%name%|::")) + smartPointerTypeTok = smartPointerTypeTok->next(); + if (Token::Match(smartPointerTypeTok, "< %name% > >") && smartPointerTypeTok->next()->type()) { + setType = true; + templateArgType = smartPointerTypeTok->next()->type(); + autovt.smartPointerType = templateArgType; + autovt.type = ValueType::Type::NONSTD; + } + } + + if (setType) { + // Type of "auto" has been determined.. set type information for "auto" and variable tokens + setValueType(autoToken, autovt); + setAutoTokenProperties(autoToken); + ValueType varvt(autovt); + if (isconst) + varvt.constness |= 1; + setValueType(parent->previous(), varvt); + Variable * var = const_cast(parent->previous()->variable()); + if (var) { + var->setValueType(varvt); + if (templateArgType && templateArgType->classScope && templateArgType->classScope->definedType) { + autoToken->type(templateArgType->classScope->definedType); + var->type(templateArgType->classScope->definedType); } } } diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index cae783edd..295ca740f 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -341,6 +341,7 @@ private: TEST_CASE(findFunction22); TEST_CASE(findFunction23); TEST_CASE(findFunction24); // smart pointer + TEST_CASE(findFunction25); // std::vector> TEST_CASE(noexceptFunction1); TEST_CASE(noexceptFunction2); @@ -5498,6 +5499,23 @@ private: ASSERT(tok1->function()); } + void findFunction25() { // std::vector> + GET_SYMBOL_DB("struct foo {\n" + " void dostuff();\n" + "}\n" + "\n" + "void f1(std::vector> v)\n" + "{\n" + " for (auto p : v)\n" + " {\n" + " p->dostuff();\n" + " }\n" + "}"); + ASSERT(db != nullptr); + const Token *tok1 = Token::findsimplematch(tokenizer.tokens(), ". dostuff ( ) ;")->next(); + ASSERT(tok1->function()); + } + #define FUNC(x) const Function *x = findFunctionByName(#x, &db->scopeList.front()); \ ASSERT_EQUALS(true, x != nullptr); \ if (x) ASSERT_EQUALS(true, x->isNoExcept());