ValueType: Improved type handling of containers when [] operator is used

This commit is contained in:
Daniel Marjamäki 2018-04-06 22:26:35 +02:00
parent 7e15e39f39
commit 0daa3bba30
4 changed files with 34 additions and 8 deletions

View File

@ -4963,6 +4963,14 @@ void SymbolDatabase::setValueType(Token *tok, const ValueType &valuetype)
}
}
if (vt1 && vt1->containerTypeToken && parent->str() == "[") {
ValueType vtParent;
if (parsedecl(vt1->containerTypeToken, &vtParent, defaultSignedness, _settings)) {
setValueType(parent, vtParent);
return;
}
}
if (!vt1)
return;
if (parent->astOperand2() && !vt2)
@ -5090,8 +5098,15 @@ static const Token * parsedecl(const Token *type, ValueType * const valuetype, V
valuetype->type = ValueType::Type::CONTAINER;
valuetype->container = container;
while (Token::Match(type, "%name%|::|<")) {
if (type->str() == "<" && type->link())
if (type->str() == "<" && type->link()) {
if (container->type_templateArgNo >= 0) {
const Token *templateType = type->next();
for (int j = 0; templateType && j < container->type_templateArgNo; j++)
templateType = templateType->nextTemplateArgument();
valuetype->containerTypeToken = templateType;
}
type = type->link();
}
type = type->next();
}
continue;

View File

@ -1059,13 +1059,14 @@ public:
unsigned int constness; // bit 0=data, bit 1=*, bit 2=**
const Scope *typeScope;
const Library::Container *container;
const Token *containerTypeToken;
std::string originalTypeName;
ValueType() : sign(UNKNOWN_SIGN), type(UNKNOWN_TYPE), pointer(0U), constness(0U), typeScope(nullptr), container(nullptr) {}
ValueType(const ValueType &vt) : sign(vt.sign), type(vt.type), pointer(vt.pointer), constness(vt.constness), typeScope(vt.typeScope), container(vt.container), originalTypeName(vt.originalTypeName) {}
ValueType(enum Sign s, enum Type t, unsigned int p) : sign(s), type(t), pointer(p), constness(0U), typeScope(nullptr), container(nullptr) {}
ValueType(enum Sign s, enum Type t, unsigned int p, unsigned int c) : sign(s), type(t), pointer(p), constness(c), typeScope(nullptr), container(nullptr) {}
ValueType(enum Sign s, enum Type t, unsigned int p, unsigned int c, const std::string &otn) : sign(s), type(t), pointer(p), constness(c), typeScope(nullptr), container(nullptr), originalTypeName(otn) {}
ValueType() : sign(UNKNOWN_SIGN), type(UNKNOWN_TYPE), pointer(0U), constness(0U), typeScope(nullptr), container(nullptr), containerTypeToken(nullptr) {}
ValueType(const ValueType &vt) : sign(vt.sign), type(vt.type), 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), 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), 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), pointer(p), constness(c), typeScope(nullptr), container(nullptr), containerTypeToken(nullptr), originalTypeName(otn) {}
static ValueType parseDecl(const Token *type, const Settings *settings);

View File

@ -2851,8 +2851,8 @@ private:
"void foo() {\n"
" printf(\"%d %u %f\", v[0], v[0], v[0]);\n"
"}\n");
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'int'.\n"
"[test.cpp:3]: (warning) %f in format string (no. 3) requires 'double' but the argument type is 'int'.\n", errout.str());
ASSERT_EQUALS("[test.cpp:3]: (warning) %u in format string (no. 2) requires 'unsigned int' but the argument type is 'signed int'.\n"
"[test.cpp:3]: (warning) %f in format string (no. 3) requires 'double' but the argument type is 'signed int'.\n", errout.str());
// #4999 (crash)
check("int bar(int a);\n"

View File

@ -4734,6 +4734,16 @@ private:
ASSERT_EQUALS("container(C) *", typeOf("C*c=new C;","new","test.cpp",&sC));
ASSERT_EQUALS("container(C) *", typeOf("x=(C*)c;","(","test.cpp",&sC));
}
{
// Container (vector)
Settings set;
Library::Container vector;
vector.startPattern = "Vector";
vector.type_templateArgNo = 0;
vector.arrayLike_indexOp = true;
set.library.containers["Vector"] = vector;
ASSERT_EQUALS("signed int", typeOf("Vector<int> v; v[0]=3;", "[", "test.cpp", &set));
}
// new
ASSERT_EQUALS("C *", typeOf("class C {}; x = new C();", "new"));