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));
|
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)
|
Function::Function(const Tokenizer *mTokenizer, const Token *tok, const Scope *scope, const Token *tokDef, const Token *tokArgDef)
|
||||||
: tokenDef(tokDef),
|
: tokenDef(tokDef),
|
||||||
argDef(tokArgDef),
|
argDef(tokArgDef),
|
||||||
|
@ -4441,6 +4455,8 @@ const Function* SymbolDatabase::findFunction(const Token *tok) const
|
||||||
const Token *tok1 = tok->tokAt(-2);
|
const Token *tok1 = tok->tokAt(-2);
|
||||||
if (Token::Match(tok1, "%var% .")) {
|
if (Token::Match(tok1, "%var% .")) {
|
||||||
const Variable *var = getVariableFromVarId(tok1->varId());
|
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())
|
if (var && var->typeScope())
|
||||||
return var->typeScope()->findFunction(tok, var->valueType()->constness == 1);
|
return var->typeScope()->findFunction(tok, var->valueType()->constness == 1);
|
||||||
} else if (Token::simpleMatch(tok->previous()->astOperand1(), "(")) {
|
} else if (Token::simpleMatch(tok->previous()->astOperand1(), "(")) {
|
||||||
|
@ -4858,6 +4874,7 @@ void SymbolDatabase::setValueType(Token *tok, const Variable &var)
|
||||||
if (var.valueType()) {
|
if (var.valueType()) {
|
||||||
valuetype.container = var.valueType()->container;
|
valuetype.container = var.valueType()->container;
|
||||||
}
|
}
|
||||||
|
valuetype.smartPointerType = var.smartPointerType();
|
||||||
if (parsedecl(var.typeStartToken(), &valuetype, mDefaultSignedness, mSettings)) {
|
if (parsedecl(var.typeStartToken(), &valuetype, mDefaultSignedness, mSettings)) {
|
||||||
if (tok->str() == "." && tok->astOperand1()) {
|
if (tok->str() == "." && tok->astOperand1()) {
|
||||||
const ValueType * const vt = tok->astOperand1()->valueType();
|
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%"))
|
while (Token::Match(type->previous(), "%name%"))
|
||||||
type = type->previous();
|
type = type->previous();
|
||||||
valuetype->sign = ValueType::Sign::UNKNOWN_SIGN;
|
valuetype->sign = ValueType::Sign::UNKNOWN_SIGN;
|
||||||
if (!valuetype->typeScope)
|
if (!valuetype->typeScope && !valuetype->smartPointerType)
|
||||||
valuetype->type = ValueType::Type::UNKNOWN_TYPE;
|
valuetype->type = ValueType::Type::UNKNOWN_TYPE;
|
||||||
|
else if (valuetype->smartPointerType)
|
||||||
|
valuetype->type = ValueType::Type::NONSTD;
|
||||||
else if (valuetype->typeScope->type == Scope::eEnum) {
|
else if (valuetype->typeScope->type == Scope::eEnum) {
|
||||||
const Token * enum_type = valuetype->typeScope->enumType;
|
const Token * enum_type = valuetype->typeScope->enumType;
|
||||||
if (enum_type) {
|
if (enum_type) {
|
||||||
|
@ -5798,6 +5817,8 @@ std::string ValueType::str() const
|
||||||
ret += " container(" + container->startPattern + ')';
|
ret += " container(" + container->startPattern + ')';
|
||||||
} else if (type == ValueType::Type::ITERATOR && container) {
|
} else if (type == ValueType::Type::ITERATOR && container) {
|
||||||
ret += " iterator(" + container->startPattern + ')';
|
ret += " iterator(" + container->startPattern + ')';
|
||||||
|
} else if (smartPointerType) {
|
||||||
|
ret += " smart-pointer<" + smartPointerType->name() + ">";
|
||||||
}
|
}
|
||||||
for (unsigned int p = 0; p < pointer; p++) {
|
for (unsigned int p = 0; p < pointer; p++) {
|
||||||
ret += " *";
|
ret += " *";
|
||||||
|
|
|
@ -560,6 +560,8 @@ public:
|
||||||
return getFlag(fIsSmartPointer);
|
return getFlag(fIsSmartPointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const Type *smartPointerType() const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the variable is of any of the STL types passed as arguments ('std::')
|
* Checks if the variable is of any of the STL types passed as arguments ('std::')
|
||||||
* E.g.:
|
* E.g.:
|
||||||
|
@ -1116,15 +1118,16 @@ public:
|
||||||
unsigned int pointer; ///< 0=>not pointer, 1=>*, 2=>**, 3=>***, etc
|
unsigned int pointer; ///< 0=>not pointer, 1=>*, 2=>**, 3=>***, etc
|
||||||
unsigned int constness; ///< bit 0=data, bit 1=*, bit 2=**
|
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 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 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.
|
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.
|
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() : 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), container(vt.container), containerTypeToken(vt.containerTypeToken), originalTypeName(vt.originalTypeName) {}
|
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), container(nullptr), containerTypeToken(nullptr) {}
|
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), 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), container(nullptr), containerTypeToken(nullptr), originalTypeName(otn) {}
|
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;
|
ValueType &operator=(const ValueType &other) = delete;
|
||||||
|
|
||||||
static ValueType parseDecl(const Token *type, const Settings *settings);
|
static ValueType parseDecl(const Token *type, const Settings *settings);
|
||||||
|
|
|
@ -340,6 +340,7 @@ private:
|
||||||
TEST_CASE(findFunction21);
|
TEST_CASE(findFunction21);
|
||||||
TEST_CASE(findFunction22);
|
TEST_CASE(findFunction22);
|
||||||
TEST_CASE(findFunction23);
|
TEST_CASE(findFunction23);
|
||||||
|
TEST_CASE(findFunction24); // smart pointer
|
||||||
|
|
||||||
TEST_CASE(noexceptFunction1);
|
TEST_CASE(noexceptFunction1);
|
||||||
TEST_CASE(noexceptFunction2);
|
TEST_CASE(noexceptFunction2);
|
||||||
|
@ -5484,6 +5485,19 @@ private:
|
||||||
ASSERT_EQUALS(true, f && f->isConst());
|
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()); \
|
#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