diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 8652f96de..c47404fc9 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -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(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); diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 830a43ccc..6d5c82aa5 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -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)