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.

This commit is contained in:
Robert Reif 2017-03-22 22:09:40 -04:00
parent fda1f02dab
commit 662bc6f846
3 changed files with 136 additions and 7 deletions

View File

@ -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<Token *>(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<Variable *>(var)->setFlags(*vt2);
if (vt2->typeScope && vt2->typeScope->definedType) {
const_cast<Variable *>(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)

View File

@ -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)

View File

@ -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);
}