From bc87e874e9154d82958028233153a54d34b40e0a Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Thu, 23 Mar 2017 20:14:49 -0400 Subject: [PATCH] Add variable and type information for auto and auto variables in range based for loops of containers. --- lib/symboldatabase.cpp | 30 +++++++-- test/testsymboldatabase.cpp | 127 ++++++++++++++++++++++++++++++++++++ 2 files changed, 152 insertions(+), 5 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index b48b0f7f5..04d4eb39b 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -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(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(membertok)->varId(membervar->nameToken()->varId()); + } + } + } } } } @@ -4600,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(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(parent->previous()->variable())->type(type->classScope->definedType); + } } } } diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 6696f20ce..a666b2f97 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -322,6 +322,8 @@ private: TEST_CASE(auto1); TEST_CASE(auto2); TEST_CASE(auto3); + TEST_CASE(auto4); + TEST_CASE(auto5); } void array() { @@ -4670,6 +4672,131 @@ private: 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 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"); } };