diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index dda3e9b1e0b..26f3bb780f1 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -7017,6 +7017,10 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, const setAutoTokenProperties(autoTok); if (vt2->pointer > vt.pointer) vt.pointer++; + if (Token::simpleMatch(autoTok->next(), "&")) + vt.reference = Reference::LValue; + if (Token::simpleMatch(autoTok->next(), "&&")) + vt.reference = Reference::RValue; setValueType(var1Tok, vt); if (var1Tok != parent->previous()) setValueType(parent->previous(), vt); @@ -7291,15 +7295,42 @@ void SymbolDatabase::setValueType(Token* tok, const ValueType& valuetype, const } // c++17 auto type deduction of braced init list - if (parent->isCpp() && mSettings.standards.cpp >= Standards::CPP17 && vt2 && Token::Match(parent->tokAt(-2), "auto %var% {")) { - Token *autoTok = parent->tokAt(-2); - setValueType(autoTok, *vt2); - setAutoTokenProperties(autoTok); - if (parent->previous()->variable()) - const_cast(parent->previous()->variable())->setValueType(*vt2); - else - debugMessage(parent->previous(), "debug", "Missing variable class for variable with varid"); - return; + if (parent->isCpp() && mSettings.standards.cpp >= Standards::CPP17 && vt2) { + Token *autoTok = nullptr; + if (Token::Match(parent->tokAt(-2), "auto %var% {")) + autoTok = parent->tokAt(-2); + else if (Token::Match(parent->tokAt(-3), "auto &|&&|* %var% {")) + autoTok = parent->tokAt(-3); + if (autoTok) { + setValueType(autoTok, *vt2); + setAutoTokenProperties(autoTok); + + Token *varTok = parent->astOperand1(); + auto *varVt = new ValueType(*vt2); + for (Token *qualTok = autoTok->next(); qualTok != varTok; qualTok = qualTok->next()) { + if (Token::simpleMatch(qualTok, "&")) { + varVt->reference = Reference::LValue; + continue; + } + if (Token::simpleMatch(qualTok, "&&")) { + varVt->reference = Reference::RValue; + continue; + } + if (Token::simpleMatch(qualTok, "*")) { + varVt->pointer++; + continue; + } + break; + } + + varTok->setValueType(varVt); + + if (parent->previous()->variable()) + const_cast(parent->previous()->variable())->setValueType(*varVt); + else + debugMessage(parent->previous(), "debug", "Missing variable class for variable with varid"); + return; + } } if (!vt1) diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index e981c8ea546..3ed8a6d08ec 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -220,6 +220,7 @@ class TestSymbolDatabase : public TestFixture { TEST_CASE(VariableValueType4); // smart pointer type TEST_CASE(VariableValueType5); // smart pointer type TEST_CASE(VariableValueType6); // smart pointer type + TEST_CASE(VariableValueType7); TEST_CASE(VariableValueTypeReferences); TEST_CASE(VariableValueTypeTemplate); @@ -1315,6 +1316,36 @@ class TestSymbolDatabase : public TestFixture { ASSERT(check->valueType()->smartPointerTypeToken); } + void VariableValueType7() { + GET_SYMBOL_DB("void f() {\n" + " auto x0 = 0;\n" + " auto &x1 = x0;\n" + " auto &x2 {x0};\n" + " auto &&x3 = 0;\n" + " auto &&x4 {0};\n" + "}\n"); + + const Token* x1 = Token::findsimplematch(tokenizer.tokens(), "x1"); + const Token* x2 = Token::findsimplematch(tokenizer.tokens(), "x2"); + const Token* x3 = Token::findsimplematch(tokenizer.tokens(), "x3"); + const Token* x4 = Token::findsimplematch(tokenizer.tokens(), "x4"); + + ASSERT(x1); + ASSERT(x2); + ASSERT(x3); + ASSERT(x4); + + ASSERT_EQUALS_ENUM(ValueType::INT, x1->valueType()->type); + ASSERT_EQUALS_ENUM(ValueType::INT, x2->valueType()->type); + ASSERT_EQUALS_ENUM(ValueType::INT, x3->valueType()->type); + ASSERT_EQUALS_ENUM(ValueType::INT, x4->valueType()->type); + + ASSERT_EQUALS_ENUM(Reference::LValue, x1->valueType()->reference); + ASSERT_EQUALS_ENUM(Reference::LValue, x2->valueType()->reference); + ASSERT_EQUALS_ENUM(Reference::RValue, x3->valueType()->reference); + ASSERT_EQUALS_ENUM(Reference::RValue, x4->valueType()->reference); + } + void VariableValueTypeReferences() { { GET_SYMBOL_DB("void foo(int x) {}\n");