Add support for auto variable initialized from function return type.

This commit is contained in:
Robert Reif 2017-04-20 15:22:57 -04:00
parent 95dd16892b
commit 0ff8e49b69
2 changed files with 236 additions and 5 deletions

View File

@ -1303,8 +1303,13 @@ void SymbolDatabase::createSymbolDatabaseSetVariablePointers()
if (!membervar) {
if (type->classScope) {
membervar = type->classScope->getVariable(membertok->str());
if (membervar)
if (membervar) {
membertok->variable(membervar);
if (membertok->varId() == 0 || _variableList[membertok->varId()] == nullptr) {
if (tok->function()->retDef)
fixVarId(varIds, tok->function()->retDef, const_cast<Token *>(membertok), membervar);
}
}
}
}
}
@ -4612,12 +4617,13 @@ void SymbolDatabase::setValueType(Token *tok, const ValueType &valuetype)
if (parent->isAssignmentOp()) {
if (vt1)
setValueType(parent, *vt1);
else if (cpp && Token::Match(parent->tokAt(-3), "%var% ; %var% =") && parent->strAt(-3) == parent->strAt(-1)) {
Token *var1Tok = parent->tokAt(-3);
else if (cpp && ((Token::Match(parent->tokAt(-3), "%var% ; %var% =") && parent->strAt(-3) == parent->strAt(-1)) ||
Token::Match(parent->tokAt(-1), "%var% ="))) {
Token *var1Tok = parent->strAt(-2) == ";" ? parent->tokAt(-3) : parent->tokAt(-1);
Token *autoTok = nullptr;
if (Token::Match(var1Tok->tokAt(-2), "[;{}] auto"))
if (Token::Match(var1Tok->tokAt(-2), ";|{|}|const auto"))
autoTok = var1Tok->previous();
else if (Token::Match(var1Tok->tokAt(-3), "[;{}] auto *"))
else if (Token::Match(var1Tok->tokAt(-3), ";|{|}|const auto *"))
autoTok = var1Tok->tokAt(-2);
if (autoTok) {
ValueType vt(*vt2);

View File

@ -327,6 +327,7 @@ private:
TEST_CASE(auto4);
TEST_CASE(auto5);
TEST_CASE(auto6); // #7963 (segmentation fault)
TEST_CASE(auto7);
}
void array() {
@ -4886,6 +4887,230 @@ private:
ASSERT_EQUALS(true, db != nullptr); // not null
}
void auto7() {
GET_SYMBOL_DB("struct Foo { int a; int b[10]; };\n"
"class Bar {\n"
" Foo foo1;\n"
" Foo foo2[10];\n"
"public:\n"
" const Foo & getFoo1() { return foo1; }\n"
" const Foo * getFoo2() { return foo2; }\n"
"};\n"
"int main() {\n"
" Bar bar;\n"
" auto v1 = bar.getFoo1().a;\n"
" auto v2 = bar.getFoo1().b[0];\n"
" auto v3 = bar.getFoo1().b;\n"
" const auto v4 = bar.getFoo1().b;\n"
" const auto * v5 = bar.getFoo1().b;\n"
" auto v6 = bar.getFoo2()[0].a;\n"
" auto v7 = bar.getFoo2()[0].b[0];\n"
" auto v8 = bar.getFoo2()[0].b;\n"
" const auto v9 = bar.getFoo2()[0].b;\n"
" const auto * v10 = bar.getFoo2()[0].b;\n"
" auto v11 = v1 + v2 + v3[0] + v4[0] + v5[0] + v6 + v7 + v8[0] + v9[0] + v10[0];\n"
" return v11;\n"
"}");
const Token *autotok = Token::findsimplematch(tokenizer.tokens(), "auto v1");
// auto = int, v1 = int
ASSERT(db && autotok && autotok->valueType());
if (db && autotok && autotok->valueType()) {
ASSERT_EQUALS(0, autotok->valueType()->constness);
ASSERT_EQUALS(0, autotok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
}
vartok = Token::findsimplematch(autotok, "v1 =");
ASSERT(db && vartok && vartok->valueType());
if (db && vartok && vartok->valueType()) {
ASSERT_EQUALS(0, vartok->valueType()->constness);
ASSERT_EQUALS(0, vartok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
}
// auto = int, v2 = int
autotok = Token::findsimplematch(autotok, "auto v2");
ASSERT(db && autotok && autotok->valueType());
if (db && autotok && autotok->valueType()) {
ASSERT_EQUALS(0, autotok->valueType()->constness);
ASSERT_EQUALS(0, autotok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
}
vartok = Token::findsimplematch(autotok, "v2 =");
ASSERT(db && vartok && vartok->valueType());
if (db && vartok && vartok->valueType()) {
ASSERT_EQUALS(0, vartok->valueType()->constness);
ASSERT_EQUALS(0, vartok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
}
// auto = const int *, v3 = const int * (const int[10])
autotok = Token::findsimplematch(autotok, "auto v3");
ASSERT(db && autotok && autotok->valueType());
if (db && autotok && autotok->valueType()) {
TODO_ASSERT_EQUALS(1, 0, autotok->valueType()->constness);
ASSERT_EQUALS(1, autotok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
}
vartok = Token::findsimplematch(autotok, "v3 =");
ASSERT(db && vartok && vartok->valueType());
if (db && vartok && vartok->valueType()) {
TODO_ASSERT_EQUALS(1, 0, vartok->valueType()->constness);
ASSERT_EQUALS(1, vartok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
}
// auto = int *, v4 = const int * (const int[10])
autotok = Token::findsimplematch(autotok, "auto v4");
ASSERT(db && autotok && autotok->valueType());
if (db && autotok && autotok->valueType()) {
TODO_ASSERT_EQUALS(0, 1, autotok->valueType()->constness);
ASSERT_EQUALS(1, autotok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
}
vartok = Token::findsimplematch(autotok, "v4 =");
ASSERT(db && vartok && vartok->valueType());
if (db && vartok && vartok->valueType()) {
TODO_ASSERT_EQUALS(1, 0, vartok->valueType()->constness);
ASSERT_EQUALS(1, vartok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
}
// auto = int, v5 = const int * (const int[10])
autotok = Token::findsimplematch(autotok, "auto * v5");
ASSERT(db && autotok && autotok->valueType());
if (db && autotok && autotok->valueType()) {
TODO_ASSERT_EQUALS(0, 1, autotok->valueType()->constness);
ASSERT_EQUALS(0, autotok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
}
vartok = Token::findsimplematch(autotok, "v5 =");
ASSERT(db && vartok && vartok->valueType());
if (db && vartok && vartok->valueType()) {
TODO_ASSERT_EQUALS(1, 0, vartok->valueType()->constness);
ASSERT_EQUALS(1, vartok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
}
// auto = int, v6 = int
autotok = Token::findsimplematch(autotok, "auto v6");
ASSERT(db && autotok && autotok->valueType());
if (db && autotok && autotok->valueType()) {
ASSERT_EQUALS(0, autotok->valueType()->constness);
ASSERT_EQUALS(0, autotok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
}
vartok = Token::findsimplematch(autotok, "v6 =");
ASSERT(db && vartok && vartok->valueType());
if (db && vartok && vartok->valueType()) {
ASSERT_EQUALS(0, vartok->valueType()->constness);
ASSERT_EQUALS(0, vartok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
}
// auto = int, v7 = int
autotok = Token::findsimplematch(autotok, "auto v7");
ASSERT(db && autotok && autotok->valueType());
if (db && autotok && autotok->valueType()) {
ASSERT_EQUALS(0, autotok->valueType()->constness);
ASSERT_EQUALS(0, autotok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
}
vartok = Token::findsimplematch(autotok, "v7 =");
ASSERT(db && vartok && vartok->valueType());
if (db && vartok && vartok->valueType()) {
ASSERT_EQUALS(0, vartok->valueType()->constness);
ASSERT_EQUALS(0, vartok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
}
// auto = const int *, v8 = const int * (const int[10])
autotok = Token::findsimplematch(autotok, "auto v8");
ASSERT(db && autotok && autotok->valueType());
if (db && autotok && autotok->valueType()) {
TODO_ASSERT_EQUALS(1, 0, autotok->valueType()->constness);
ASSERT_EQUALS(1, autotok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
}
vartok = Token::findsimplematch(autotok, "v8 =");
ASSERT(db && vartok && vartok->valueType());
if (db && vartok && vartok->valueType()) {
TODO_ASSERT_EQUALS(1, 0, vartok->valueType()->constness);
ASSERT_EQUALS(1, vartok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
}
// auto = int *, v9 = const int * (const int[10])
autotok = Token::findsimplematch(autotok, "auto v9");
ASSERT(db && autotok && autotok->valueType());
if (db && autotok && autotok->valueType()) {
TODO_ASSERT_EQUALS(0, 1, autotok->valueType()->constness);
ASSERT_EQUALS(1, autotok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
}
vartok = Token::findsimplematch(autotok, "v9 =");
ASSERT(db && vartok && vartok->valueType());
if (db && vartok && vartok->valueType()) {
TODO_ASSERT_EQUALS(1, 0, vartok->valueType()->constness);
ASSERT_EQUALS(1, vartok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
}
// auto = int, v10 = const int * (const int[10])
autotok = Token::findsimplematch(autotok, "auto * v10");
ASSERT(db && autotok && autotok->valueType());
if (db && autotok && autotok->valueType()) {
TODO_ASSERT_EQUALS(0, 1, autotok->valueType()->constness);
ASSERT_EQUALS(0, autotok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
}
vartok = Token::findsimplematch(autotok, "v10 =");
ASSERT(db && vartok && vartok->valueType());
if (db && vartok && vartok->valueType()) {
TODO_ASSERT_EQUALS(1, 0, vartok->valueType()->constness);
ASSERT_EQUALS(1, vartok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
}
// auto = int, v11 = int
autotok = Token::findsimplematch(autotok, "auto v11");
TODO_ASSERT(db && autotok && autotok->valueType());
if (db && autotok && autotok->valueType()) {
ASSERT_EQUALS(0, autotok->valueType()->constness);
ASSERT_EQUALS(0, autotok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, autotok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, autotok->valueType()->type);
}
vartok = autotok->next();
TODO_ASSERT(db && vartok && vartok->valueType());
if (db && vartok && vartok->valueType()) {
ASSERT_EQUALS(0, vartok->valueType()->constness);
ASSERT_EQUALS(0, vartok->valueType()->pointer);
ASSERT_EQUALS(ValueType::SIGNED, vartok->valueType()->sign);
ASSERT_EQUALS(ValueType::INT, vartok->valueType()->type);
}
}
};
REGISTER_TEST(TestSymbolDatabase)