SymbolDatabase: Better handling of smart pointers
This commit is contained in:
parent
8a63a5d824
commit
a0b22410cf
|
@ -1712,6 +1712,20 @@ void Variable::setValueType(const ValueType &valueType)
|
|||
setFlag(fIsConst, mValueType->constness & (1U << mValueType->pointer));
|
||||
}
|
||||
|
||||
const Type *Variable::smartPointerType() const
|
||||
{
|
||||
if (!isSmartPointer())
|
||||
return nullptr;
|
||||
|
||||
// TODO: Cache result
|
||||
const Token *ptrType = typeStartToken();
|
||||
while (Token::Match(ptrType, "%name%|::"))
|
||||
ptrType = ptrType->next();
|
||||
if (Token::Match(ptrType, "< %name% >"))
|
||||
return ptrType->next()->type();
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Function::Function(const Tokenizer *mTokenizer, const Token *tok, const Scope *scope, const Token *tokDef, const Token *tokArgDef)
|
||||
: tokenDef(tokDef),
|
||||
argDef(tokArgDef),
|
||||
|
@ -4441,6 +4455,8 @@ const Function* SymbolDatabase::findFunction(const Token *tok) const
|
|||
const Token *tok1 = tok->tokAt(-2);
|
||||
if (Token::Match(tok1, "%var% .")) {
|
||||
const Variable *var = getVariableFromVarId(tok1->varId());
|
||||
if (var && var->smartPointerType() && tok1->next()->originalName() == "->")
|
||||
return var->smartPointerType()->classScope->findFunction(tok, var->valueType()->constness == 1);
|
||||
if (var && var->typeScope())
|
||||
return var->typeScope()->findFunction(tok, var->valueType()->constness == 1);
|
||||
} else if (Token::simpleMatch(tok->previous()->astOperand1(), "(")) {
|
||||
|
@ -4858,6 +4874,7 @@ void SymbolDatabase::setValueType(Token *tok, const Variable &var)
|
|||
if (var.valueType()) {
|
||||
valuetype.container = var.valueType()->container;
|
||||
}
|
||||
valuetype.smartPointerType = var.smartPointerType();
|
||||
if (parsedecl(var.typeStartToken(), &valuetype, mDefaultSignedness, mSettings)) {
|
||||
if (tok->str() == "." && tok->astOperand1()) {
|
||||
const ValueType * const vt = tok->astOperand1()->valueType();
|
||||
|
@ -5192,8 +5209,10 @@ static const Token * parsedecl(const Token *type, ValueType * const valuetype, V
|
|||
while (Token::Match(type->previous(), "%name%"))
|
||||
type = type->previous();
|
||||
valuetype->sign = ValueType::Sign::UNKNOWN_SIGN;
|
||||
if (!valuetype->typeScope)
|
||||
if (!valuetype->typeScope && !valuetype->smartPointerType)
|
||||
valuetype->type = ValueType::Type::UNKNOWN_TYPE;
|
||||
else if (valuetype->smartPointerType)
|
||||
valuetype->type = ValueType::Type::NONSTD;
|
||||
else if (valuetype->typeScope->type == Scope::eEnum) {
|
||||
const Token * enum_type = valuetype->typeScope->enumType;
|
||||
if (enum_type) {
|
||||
|
@ -5798,6 +5817,8 @@ std::string ValueType::str() const
|
|||
ret += " container(" + container->startPattern + ')';
|
||||
} else if (type == ValueType::Type::ITERATOR && container) {
|
||||
ret += " iterator(" + container->startPattern + ')';
|
||||
} else if (smartPointerType) {
|
||||
ret += " smart-pointer<" + smartPointerType->name() + ">";
|
||||
}
|
||||
for (unsigned int p = 0; p < pointer; p++) {
|
||||
ret += " *";
|
||||
|
|
|
@ -560,6 +560,8 @@ public:
|
|||
return getFlag(fIsSmartPointer);
|
||||
}
|
||||
|
||||
const Type *smartPointerType() const;
|
||||
|
||||
/**
|
||||
* Checks if the variable is of any of the STL types passed as arguments ('std::')
|
||||
* E.g.:
|
||||
|
@ -1116,15 +1118,16 @@ public:
|
|||
unsigned int pointer; ///< 0=>not pointer, 1=>*, 2=>**, 3=>***, etc
|
||||
unsigned int constness; ///< bit 0=data, bit 1=*, bit 2=**
|
||||
const Scope *typeScope; ///< if the type definition is seen this point out the type scope
|
||||
const ::Type *smartPointerType; ///< Smart pointer type
|
||||
const Library::Container *container; ///< If the type is a container defined in a cfg file, this is the used container
|
||||
const Token *containerTypeToken; ///< The container type token. the template argument token that defines the container element type.
|
||||
std::string originalTypeName; ///< original type name as written in the source code. eg. this might be "uint8_t" when type is CHAR.
|
||||
|
||||
ValueType() : sign(UNKNOWN_SIGN), type(UNKNOWN_TYPE), bits(0), pointer(0U), constness(0U), typeScope(nullptr), container(nullptr), containerTypeToken(nullptr) {}
|
||||
ValueType(const ValueType &vt) : sign(vt.sign), type(vt.type), bits(vt.bits), pointer(vt.pointer), constness(vt.constness), typeScope(vt.typeScope), container(vt.container), containerTypeToken(vt.containerTypeToken), originalTypeName(vt.originalTypeName) {}
|
||||
ValueType(enum Sign s, enum Type t, unsigned int p) : sign(s), type(t), bits(0), pointer(p), constness(0U), typeScope(nullptr), container(nullptr), containerTypeToken(nullptr) {}
|
||||
ValueType(enum Sign s, enum Type t, unsigned int p, unsigned int c) : sign(s), type(t), bits(0), pointer(p), constness(c), typeScope(nullptr), container(nullptr), containerTypeToken(nullptr) {}
|
||||
ValueType(enum Sign s, enum Type t, unsigned int p, unsigned int c, const std::string &otn) : sign(s), type(t), bits(0), pointer(p), constness(c), typeScope(nullptr), container(nullptr), containerTypeToken(nullptr), originalTypeName(otn) {}
|
||||
ValueType() : sign(UNKNOWN_SIGN), type(UNKNOWN_TYPE), bits(0), pointer(0U), constness(0U), typeScope(nullptr), smartPointerType(nullptr), container(nullptr), containerTypeToken(nullptr) {}
|
||||
ValueType(const ValueType &vt) : sign(vt.sign), type(vt.type), bits(vt.bits), pointer(vt.pointer), constness(vt.constness), typeScope(vt.typeScope), smartPointerType(vt.smartPointerType), container(vt.container), containerTypeToken(vt.containerTypeToken), originalTypeName(vt.originalTypeName) {}
|
||||
ValueType(enum Sign s, enum Type t, unsigned int p) : sign(s), type(t), bits(0), pointer(p), constness(0U), typeScope(nullptr), smartPointerType(nullptr), container(nullptr), containerTypeToken(nullptr) {}
|
||||
ValueType(enum Sign s, enum Type t, unsigned int p, unsigned int c) : sign(s), type(t), bits(0), pointer(p), constness(c), typeScope(nullptr), smartPointerType(nullptr), container(nullptr), containerTypeToken(nullptr) {}
|
||||
ValueType(enum Sign s, enum Type t, unsigned int p, unsigned int c, const std::string &otn) : sign(s), type(t), bits(0), pointer(p), constness(c), typeScope(nullptr), smartPointerType(nullptr), container(nullptr), containerTypeToken(nullptr), originalTypeName(otn) {}
|
||||
ValueType &operator=(const ValueType &other) = delete;
|
||||
|
||||
static ValueType parseDecl(const Token *type, const Settings *settings);
|
||||
|
|
|
@ -340,6 +340,7 @@ private:
|
|||
TEST_CASE(findFunction21);
|
||||
TEST_CASE(findFunction22);
|
||||
TEST_CASE(findFunction23);
|
||||
TEST_CASE(findFunction24); // smart pointer
|
||||
|
||||
TEST_CASE(noexceptFunction1);
|
||||
TEST_CASE(noexceptFunction2);
|
||||
|
@ -5484,6 +5485,19 @@ private:
|
|||
ASSERT_EQUALS(true, f && f->isConst());
|
||||
}
|
||||
|
||||
void findFunction24() { // smart pointers
|
||||
GET_SYMBOL_DB("struct foo {\n"
|
||||
" void dostuff();\n"
|
||||
"}\n"
|
||||
"\n"
|
||||
"void f(std::shared_ptr<foo> p) {\n"
|
||||
" p->dostuff();\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());
|
||||
|
|
Loading…
Reference in New Issue