From 662bc6f846e4e5535b1f5b1756db8639e1d367f0 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Wed, 22 Mar 2017 22:09:40 -0400 Subject: [PATCH] Add variable or type information to auto and auto variable tokens. Changing the auto variable type requires rerunning the variable pointer pass to correct the symbol database for the new type. --- lib/symboldatabase.cpp | 22 ++++++- test/testsymboldatabase.cpp | 119 +++++++++++++++++++++++++++++++++++- test/testvarid.cpp | 2 +- 3 files changed, 136 insertions(+), 7 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 308176f70..b763c0fb9 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1237,8 +1237,10 @@ void SymbolDatabase::createSymbolDatabaseSetVariablePointers() const Variable *var = tok->variable(); if (var && var->typeScope()) { const Variable *membervar = var->typeScope()->getVariable(membertok->str()); - if (membervar) + if (membervar) { membertok->variable(membervar); + const_cast(membertok)->varId(membervar->nameToken()->varId()); + } } } } @@ -4493,13 +4495,24 @@ void SymbolDatabase::setValueType(Token *tok, const ValueType &valuetype) else if (Token::Match(var1Tok->tokAt(-3), "[;{}] auto *")) autoTok = var1Tok->tokAt(-2); if (autoTok) { - setValueType(autoTok, *vt2); + ValueType vt(*vt2); + if (autoTok->strAt(1) == "*" && vt.pointer) + vt.pointer--; + if (autoTok->strAt(-1) == "const") + vt.constness |= 1; + setValueType(autoTok, vt); setAutoTokenProperties(autoTok); setValueType(var1Tok, *vt2); setValueType(parent->previous(), *vt2); const Variable *var = parent->previous()->variable(); - if (var) + if (var) { const_cast(var)->setFlags(*vt2); + if (vt2->typeScope && vt2->typeScope->definedType) { + const_cast(var)->type(vt2->typeScope->definedType); + if (autoTok->valueType()->pointer == 0) + autoTok->type(vt2->typeScope->definedType); + } + } } } return; @@ -4957,6 +4970,9 @@ void SymbolDatabase::setValueTypeInTokenList() setValueType(tok, vt); } } + + // Update auto variables with new type information. + createSymbolDatabaseSetVariablePointers(); } ValueType ValueType::parseDecl(const Token *type, const Settings *settings) diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index eba49feb3..47c6c624d 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -320,6 +320,8 @@ private: TEST_CASE(noReturnType); TEST_CASE(auto1); + TEST_CASE(auto2); + TEST_CASE(auto3); } void array() { @@ -812,7 +814,7 @@ private: tok = tok ? tok->next() : nullptr; ASSERT(db != nullptr); ASSERT(tok && tok->variable() && Token::simpleMatch(tok->variable()->typeStartToken(), "int x ;")); - ASSERT(tok && tok->varId() == 0U); // It's possible to set a varId + ASSERT(tok && tok->varId() == 1U); // It's possible to set a varId } void arrayMemberVar2() { @@ -828,7 +830,7 @@ private: tok = tok ? tok->next() : nullptr; ASSERT(db != nullptr); ASSERT(tok && tok->variable() && Token::simpleMatch(tok->variable()->typeStartToken(), "int x ;")); - ASSERT(tok && tok->varId() == 0U); // It's possible to set a varId + ASSERT(tok && tok->varId() == 1U); // It's possible to set a varId } void arrayMemberVar3() { @@ -844,7 +846,7 @@ private: tok = tok ? tok->next() : nullptr; ASSERT(db != nullptr); ASSERT(tok && tok->variable() && Token::simpleMatch(tok->variable()->typeStartToken(), "int x ;")); - ASSERT(tok && tok->varId() == 0U); // It's possible to set a varId + ASSERT(tok && tok->varId() == 1U); // It's possible to set a varId } void staticMemberVar() { @@ -4501,6 +4503,117 @@ private: const Variable *var = db ? db->getVariableFromVarId(1) : nullptr; ASSERT(var && var->isPointer() && var->isConst()); } + + void auto2() { + GET_SYMBOL_DB("struct S { int i; };\n" + "int foo() {\n" + " auto a = new S;\n" + " auto * b = new S;\n" + " auto c = new S[10];\n" + " auto * d = new S[10];\n" + " return a->i + b->i + c[0]->i + d[0]->i;\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() == "S" && autotok->type() == nullptr); + + autotok = Token::findsimplematch(autotok->next(), "auto"); + ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S" && autotok->type() && autotok->type()->name() == "S"); + + autotok = Token::findsimplematch(autotok->next(), "auto"); + ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 1 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S" && autotok->type() == nullptr); + + autotok = Token::findsimplematch(autotok->next(), "auto"); + ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S" && autotok->type() && autotok->type()->name() == "S"); + + vartok = Token::findsimplematch(tokenizer.tokens(), "a ="); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S"); + + vartok = Token::findsimplematch(vartok->next(), "b ="); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S"); + + vartok = Token::findsimplematch(vartok->next(), "c ="); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S"); + + vartok = Token::findsimplematch(vartok->next(), "d ="); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S"); + + vartok = Token::findsimplematch(tokenizer.tokens(), "return"); + + vartok = Token::findsimplematch(vartok, "a"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S"); + + vartok = Token::findsimplematch(vartok->next(), "b"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S"); + + vartok = Token::findsimplematch(vartok->next(), "c"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S"); + + vartok = Token::findsimplematch(vartok->next(), "d"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S"); + + vartok = Token::findsimplematch(tokenizer.tokens(), "return"); + + vartok = Token::findsimplematch(vartok, "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"); + + 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 auto3() { + GET_SYMBOL_DB("enum class 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" + "}"); + 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); + + autotok = Token::findsimplematch(autotok->next(), "auto"); + ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "E" && autotok->type() && autotok->type()->name() == "E"); + + autotok = Token::findsimplematch(autotok->next(), "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); + + autotok = Token::findsimplematch(autotok->next(), "auto"); + ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "E" && autotok->type() && autotok->type()->name() == "E"); + + vartok = Token::findsimplematch(tokenizer.tokens(), "a ="); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E"); + + vartok = Token::findsimplematch(vartok->next(), "b ="); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E"); + + vartok = Token::findsimplematch(vartok->next(), "c ="); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E"); + + vartok = Token::findsimplematch(vartok->next(), "d ="); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E"); + + vartok = Token::findsimplematch(tokenizer.tokens(), "return"); + + vartok = Token::findsimplematch(vartok, "a"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E"); + + vartok = Token::findsimplematch(vartok->next(), "b"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E"); + + vartok = Token::findsimplematch(vartok->next(), "c"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E"); + + vartok = Token::findsimplematch(vartok->next(), "d"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E"); + } + }; REGISTER_TEST(TestSymbolDatabase) diff --git a/test/testvarid.cpp b/test/testvarid.cpp index bfc000227..b59ac326a 100644 --- a/test/testvarid.cpp +++ b/test/testvarid.cpp @@ -1344,7 +1344,7 @@ private: "10:\n" "11: void Bar :: f ( )\n" "12: {\n" - "13: foo@2 . x@4 = x@3 ;\n" + "13: foo@2 . x@1 = x@3 ;\n" "14: }\n"; ASSERT_EQUALS(expected, actual); }