SymbolDatabase: Better handling of smart pointers
This commit is contained in:
parent
a05dfc9150
commit
58076bc672
|
@ -1710,6 +1710,8 @@ void Variable::setValueType(const ValueType &valueType)
|
||||||
if ((mValueType->pointer > 0) && (!isArray() || Token::Match(mNameToken->previous(), "( * %name% )")))
|
if ((mValueType->pointer > 0) && (!isArray() || Token::Match(mNameToken->previous(), "( * %name% )")))
|
||||||
setFlag(fIsPointer, true);
|
setFlag(fIsPointer, true);
|
||||||
setFlag(fIsConst, mValueType->constness & (1U << mValueType->pointer));
|
setFlag(fIsConst, mValueType->constness & (1U << mValueType->pointer));
|
||||||
|
if (mValueType->smartPointerType)
|
||||||
|
setFlag(fIsSmartPointer, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Type *Variable::smartPointerType() const
|
const Type *Variable::smartPointerType() const
|
||||||
|
@ -1717,6 +1719,9 @@ const Type *Variable::smartPointerType() const
|
||||||
if (!isSmartPointer())
|
if (!isSmartPointer())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
|
||||||
|
if (mValueType->smartPointerType)
|
||||||
|
return mValueType->smartPointerType;
|
||||||
|
|
||||||
// TODO: Cache result
|
// TODO: Cache result
|
||||||
const Token *ptrType = typeStartToken();
|
const Token *ptrType = typeStartToken();
|
||||||
while (Token::Match(ptrType, "%name%|::"))
|
while (Token::Match(ptrType, "%name%|::"))
|
||||||
|
@ -4939,6 +4944,13 @@ void SymbolDatabase::setValueType(Token *tok, const ValueType &valuetype)
|
||||||
return;
|
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 (parent->isAssignmentOp()) {
|
||||||
if (vt1)
|
if (vt1)
|
||||||
setValueType(parent, *vt1);
|
setValueType(parent, *vt1);
|
||||||
|
@ -5085,24 +5097,47 @@ void SymbolDatabase::setValueType(Token *tok, const ValueType &valuetype)
|
||||||
else
|
else
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Token *containerElementType = typeStart;
|
||||||
|
while (Token::Match(containerElementType, "%name%|::"))
|
||||||
|
containerElementType = containerElementType->next();
|
||||||
|
|
||||||
|
// Try to determine type of "auto" token.
|
||||||
// TODO: Get type better
|
// TODO: Get type better
|
||||||
if (Token::Match(typeStart, "std :: %type% < %type% *| *| >")) {
|
bool setType = false;
|
||||||
ValueType autovt;
|
ValueType autovt;
|
||||||
if (parsedecl(typeStart->tokAt(4), &autovt, mDefaultSignedness, mSettings)) {
|
const Type *templateArgType = nullptr; // container element type / smart pointer type
|
||||||
setValueType(autoToken, autovt);
|
if (Token::Match(containerElementType, "< %type% *| *| >")) {
|
||||||
setAutoTokenProperties(autoToken);
|
if (parsedecl(containerElementType->next(), &autovt, mDefaultSignedness, mSettings)) {
|
||||||
ValueType varvt(autovt);
|
setType = true;
|
||||||
if (isconst)
|
templateArgType = containerElementType->next()->type();
|
||||||
varvt.constness |= 1;
|
}
|
||||||
setValueType(parent->previous(), varvt);
|
} else if (mSettings->library.isSmartPointer(containerElementType->next())) {
|
||||||
Variable * var = const_cast<Variable *>(parent->previous()->variable());
|
const Token *smartPointerTypeTok = containerElementType->next();
|
||||||
if (var) {
|
while (Token::Match(smartPointerTypeTok, "%name%|::"))
|
||||||
var->setValueType(varvt);
|
smartPointerTypeTok = smartPointerTypeTok->next();
|
||||||
const Type * type = typeStart->tokAt(4)->type();
|
if (Token::Match(smartPointerTypeTok, "< %name% > >") && smartPointerTypeTok->next()->type()) {
|
||||||
if (type && type->classScope && type->classScope->definedType) {
|
setType = true;
|
||||||
autoToken->type(type->classScope->definedType);
|
templateArgType = smartPointerTypeTok->next()->type();
|
||||||
var->type(type->classScope->definedType);
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -341,6 +341,7 @@ private:
|
||||||
TEST_CASE(findFunction22);
|
TEST_CASE(findFunction22);
|
||||||
TEST_CASE(findFunction23);
|
TEST_CASE(findFunction23);
|
||||||
TEST_CASE(findFunction24); // smart pointer
|
TEST_CASE(findFunction24); // smart pointer
|
||||||
|
TEST_CASE(findFunction25); // std::vector<std::shared_ptr<Fred>>
|
||||||
|
|
||||||
TEST_CASE(noexceptFunction1);
|
TEST_CASE(noexceptFunction1);
|
||||||
TEST_CASE(noexceptFunction2);
|
TEST_CASE(noexceptFunction2);
|
||||||
|
@ -5498,6 +5499,23 @@ private:
|
||||||
ASSERT(tok1->function());
|
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()); \
|
#define FUNC(x) const Function *x = findFunctionByName(#x, &db->scopeList.front()); \
|
||||||
ASSERT_EQUALS(true, x != nullptr); \
|
ASSERT_EQUALS(true, x != nullptr); \
|
||||||
if (x) ASSERT_EQUALS(true, x->isNoExcept());
|
if (x) ASSERT_EQUALS(true, x->isNoExcept());
|
||||||
|
|
Loading…
Reference in New Issue