SymbolDatabase: Better handling of smart pointers

This commit is contained in:
Daniel Marjamäki 2019-07-09 17:32:19 +02:00
parent a05dfc9150
commit 58076bc672
2 changed files with 70 additions and 17 deletions

View File

@ -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<Variable *>(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<Variable *>(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);
}
}
}

View File

@ -341,6 +341,7 @@ private:
TEST_CASE(findFunction22);
TEST_CASE(findFunction23);
TEST_CASE(findFunction24); // smart pointer
TEST_CASE(findFunction25); // std::vector<std::shared_ptr<Fred>>
TEST_CASE(noexceptFunction1);
TEST_CASE(noexceptFunction2);
@ -5498,6 +5499,23 @@ private:
ASSERT(tok1->function());
}
void findFunction25() { // std::vector<std::shared_ptr<Fred>>
GET_SYMBOL_DB("struct foo {\n"
" void dostuff();\n"
"}\n"
"\n"
"void f1(std::vector<std::shared_ptr<foo>> 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());