Merge pull request #881 from IOBYTE/master
Add auto type and variable information to tokens for range based for loops of arrays and containers.
This commit is contained in:
commit
a60d588cbe
|
@ -1219,7 +1219,7 @@ void SymbolDatabase::createSymbolDatabaseSetVariablePointers()
|
|||
// Set Token::variable pointer for array member variable
|
||||
// Since it doesn't point at a fixed location it doesn't have varid
|
||||
if (tok->variable() != nullptr &&
|
||||
tok->variable()->typeScope() &&
|
||||
(tok->variable()->typeScope() || (tok->valueType() && tok->valueType()->type == ValueType::CONTAINER)) &&
|
||||
Token::Match(tok, "%name% [|.")) {
|
||||
|
||||
Token *tok2 = tok->next();
|
||||
|
@ -1241,6 +1241,17 @@ void SymbolDatabase::createSymbolDatabaseSetVariablePointers()
|
|||
membertok->variable(membervar);
|
||||
const_cast<Token *>(membertok)->varId(membervar->nameToken()->varId());
|
||||
}
|
||||
} else if (var && tok->valueType() && tok->valueType()->type == ValueType::CONTAINER) {
|
||||
if (Token::Match(var->typeStartToken(), "std :: %type% < %type% *| *| >")) {
|
||||
const Type * type = var->typeStartToken()->tokAt(4)->type();
|
||||
if (type && type->classScope && type->classScope->definedType) {
|
||||
const Variable *membervar = type->classScope->getVariable(membertok->str());
|
||||
if (membervar) {
|
||||
membertok->variable(membervar);
|
||||
const_cast<Token *>(membertok)->varId(membervar->nameToken()->varId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4566,20 +4577,27 @@ void SymbolDatabase::setValueType(Token *tok, const ValueType &valuetype)
|
|||
// range for loop, auto
|
||||
if (vt2 &&
|
||||
parent->str() == ":" &&
|
||||
Token::Match(parent->astParent(), "( const| auto *| %var% :") &&
|
||||
Token::Match(parent->astParent(), "( const| auto *|&| %var% :") &&
|
||||
!parent->previous()->valueType() &&
|
||||
Token::simpleMatch(parent->astParent()->astOperand1(), "for")) {
|
||||
bool isconst = Token::simpleMatch(parent->astParent()->next(), "const");
|
||||
const bool isconst = Token::simpleMatch(parent->astParent()->next(), "const");
|
||||
Token * const autoToken = const_cast<Token *>(parent->astParent()->tokAt(isconst ? 2 : 1));
|
||||
if (vt2->pointer) {
|
||||
ValueType vt(*vt2);
|
||||
vt.pointer--;
|
||||
if (isconst)
|
||||
vt.constness |= 1;
|
||||
setValueType(autoToken, vt);
|
||||
ValueType autovt(*vt2);
|
||||
autovt.pointer--;
|
||||
autovt.constness = 0;
|
||||
setValueType(autoToken, autovt);
|
||||
setAutoTokenProperties(autoToken);
|
||||
setValueType(parent->previous(), vt);
|
||||
const_cast<Variable *>(parent->previous()->variable())->setFlags(vt);
|
||||
ValueType varvt(*vt2);
|
||||
varvt.pointer--;
|
||||
if (isconst)
|
||||
varvt.constness |= 1;
|
||||
setValueType(parent->previous(), varvt);
|
||||
const_cast<Variable *>(parent->previous()->variable())->setFlags(varvt);
|
||||
if (vt2->typeScope && vt2->typeScope->definedType) {
|
||||
const_cast<Variable *>(parent->previous()->variable())->type(vt2->typeScope->definedType);
|
||||
autoToken->type(vt2->typeScope->definedType);
|
||||
}
|
||||
} else if (vt2->container) {
|
||||
// TODO: Determine exact type of RHS
|
||||
const Token *typeStart = parent->astOperand2();
|
||||
|
@ -4593,11 +4611,20 @@ void SymbolDatabase::setValueType(Token *tok, const ValueType &valuetype)
|
|||
}
|
||||
// TODO: Get type better
|
||||
if (Token::Match(typeStart, "std :: %type% < %type% *| *| >")) {
|
||||
ValueType vt;
|
||||
if (parsedecl(typeStart->tokAt(4), &vt, defaultSignedness, _settings)) {
|
||||
setValueType(autoToken, vt);
|
||||
ValueType autovt;
|
||||
if (parsedecl(typeStart->tokAt(4), &autovt, defaultSignedness, _settings)) {
|
||||
setValueType(autoToken, autovt);
|
||||
setAutoTokenProperties(autoToken);
|
||||
setValueType(parent->previous(), vt);
|
||||
ValueType varvt(autovt);
|
||||
if (isconst)
|
||||
varvt.constness |= 1;
|
||||
setValueType(parent->previous(), varvt);
|
||||
const_cast<Variable *>(parent->previous()->variable())->setFlags(varvt);
|
||||
const Type * type = typeStart->tokAt(4)->type();
|
||||
if (type && type->classScope && type->classScope->definedType) {
|
||||
autoToken->type(type->classScope->definedType);
|
||||
const_cast<Variable *>(parent->previous()->variable())->type(type->classScope->definedType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -322,6 +322,8 @@ private:
|
|||
TEST_CASE(auto1);
|
||||
TEST_CASE(auto2);
|
||||
TEST_CASE(auto3);
|
||||
TEST_CASE(auto4);
|
||||
TEST_CASE(auto5);
|
||||
}
|
||||
|
||||
void array() {
|
||||
|
@ -4567,13 +4569,13 @@ private:
|
|||
}
|
||||
|
||||
void auto3() {
|
||||
GET_SYMBOL_DB("enum class E : unsigned short { A, B, C };\n"
|
||||
GET_SYMBOL_DB("enum E : unsigned short { A, B, C };\n"
|
||||
"int foo() {\n"
|
||||
" auto a = new E;\n"
|
||||
" auto * b = new E;\n"
|
||||
" auto c = new E[10];\n"
|
||||
" auto * d = new E[10];\n"
|
||||
" return a + b + c + d;\n"
|
||||
" return *a + *b + c[0] + d[0];\n"
|
||||
"}");
|
||||
const Token *autotok = Token::findsimplematch(tokenizer.tokens(), "auto");
|
||||
ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 1 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "E" && autotok->type() == nullptr);
|
||||
|
@ -4614,6 +4616,189 @@ private:
|
|||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E");
|
||||
}
|
||||
|
||||
void auto4() {
|
||||
GET_SYMBOL_DB("struct S { int i; };\n"
|
||||
"int foo() {\n"
|
||||
" S array[10];\n"
|
||||
" for (auto a : array)\n"
|
||||
" a.i = 0;\n"
|
||||
" for (auto & b : array)\n"
|
||||
" b.i = 1;\n"
|
||||
" for (const auto & c : array)\n"
|
||||
" auto ci = c.i;\n"
|
||||
" for (auto * d : array)\n"
|
||||
" d->i = 0;\n"
|
||||
" for (const auto * e : array)\n"
|
||||
" auto ei = e->i;\n"
|
||||
" return array[0].i;\n"
|
||||
"}");
|
||||
const Token *autotok = Token::findsimplematch(tokenizer.tokens(), "auto a");
|
||||
ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
|
||||
|
||||
autotok = Token::findsimplematch(autotok->next(), "auto & b");
|
||||
ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
|
||||
|
||||
autotok = Token::findsimplematch(autotok->next(), "auto & c");
|
||||
ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
|
||||
|
||||
autotok = Token::findsimplematch(autotok->next(), "auto * d");
|
||||
ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
|
||||
|
||||
autotok = Token::findsimplematch(autotok->next(), "auto * e");
|
||||
ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
|
||||
|
||||
vartok = Token::findsimplematch(tokenizer.tokens(), "a :");
|
||||
ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isReference() && !vartok->variable()->isPointer());
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "b :");
|
||||
ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->isReference() && !vartok->variable()->isPointer() && !vartok->variable()->isConst());
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "c :");
|
||||
ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->isReference() && !vartok->variable()->isPointer() && vartok->variable()->isConst());
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "d :");
|
||||
ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isReference() && vartok->variable()->isPointer() && !vartok->variable()->isConst());
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "e :");
|
||||
ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isReference() && vartok->variable()->isPointer() && vartok->variable()->isConst());
|
||||
|
||||
vartok = Token::findsimplematch(tokenizer.tokens(), "a . i");
|
||||
ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isPointer() && !vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
|
||||
|
||||
vartok = Token::findsimplematch(vartok, "i");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "b . i");
|
||||
ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isPointer() && vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "i");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "c . i");
|
||||
ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isPointer() && vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "i");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "d . i");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && !vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "i");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "e . i");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && !vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "i");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "i");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
|
||||
}
|
||||
|
||||
void auto5() {
|
||||
GET_SYMBOL_DB("struct S { int i; };\n"
|
||||
"int foo() {\n"
|
||||
" std::vector<S> vec(10);\n"
|
||||
" for (auto a : vec)\n"
|
||||
" a.i = 0;\n"
|
||||
" for (auto & b : vec)\n"
|
||||
" b.i = 0;\n"
|
||||
" for (const auto & c : vec)\n"
|
||||
" auto ci = c.i;\n"
|
||||
" for (auto * d : vec)\n"
|
||||
" d.i = 0;\n"
|
||||
" for (const auto * e : vec)\n"
|
||||
" auto ei = e->i;\n"
|
||||
" return vec[0].i;\n"
|
||||
"}");
|
||||
const Token *autotok = Token::findsimplematch(tokenizer.tokens(), "auto a");
|
||||
ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
|
||||
|
||||
autotok = Token::findsimplematch(autotok->next(), "auto & b");
|
||||
ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
|
||||
|
||||
autotok = Token::findsimplematch(autotok->next(), "auto & c");
|
||||
ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
|
||||
|
||||
autotok = Token::findsimplematch(autotok->next(), "auto * d");
|
||||
ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
|
||||
|
||||
autotok = Token::findsimplematch(autotok->next(), "auto * e");
|
||||
ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->constness == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && autotok && autotok->type() && autotok->type()->name() == "S");
|
||||
|
||||
vartok = Token::findsimplematch(tokenizer.tokens(), "a :");
|
||||
ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isReference() && !vartok->variable()->isPointer());
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "b :");
|
||||
ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->isReference() && !vartok->variable()->isPointer() && !vartok->variable()->isConst());
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "c :");
|
||||
ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->isReference() && !vartok->variable()->isPointer() && vartok->variable()->isConst());
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "d :");
|
||||
ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isReference() && vartok->variable()->isPointer() && !vartok->variable()->isConst());
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "e :");
|
||||
ASSERT(db && vartok && vartok->valueType() && vartok->valueType()->typeScope && vartok->valueType()->typeScope->definedType && vartok->valueType()->typeScope->definedType->name() == "S");
|
||||
ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isReference() && vartok->variable()->isPointer() && vartok->variable()->isConst());
|
||||
|
||||
|
||||
vartok = Token::findsimplematch(tokenizer.tokens(), "a . i");
|
||||
ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isPointer() && !vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
|
||||
|
||||
vartok = Token::findsimplematch(vartok, "i");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "b . i");
|
||||
ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isPointer() && vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "i");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "c . i");
|
||||
ASSERT(db && vartok && vartok->variable() && !vartok->variable()->isPointer() && vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "i");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "d . i");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && !vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "i");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "e . i");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && !vartok->variable()->isReference() && vartok->variable()->type() && vartok->variable()->type()->name() == "S");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "i");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
|
||||
|
||||
vartok = Token::findsimplematch(vartok->next(), "i");
|
||||
ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int");
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
REGISTER_TEST(TestSymbolDatabase)
|
||||
|
|
Loading…
Reference in New Issue