From a014920280166666164ae11ebb06690f5a2544b1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Thu, 7 Jan 2016 10:46:19 +0100 Subject: [PATCH] Fixed #7260 (ValueType: in C++ the result of 'sint >> unknowntype' has unknown type) --- lib/symboldatabase.cpp | 55 +++++++++++++++++++------------------ lib/symboldatabase.h | 2 +- lib/tokenize.cpp | 2 +- test/testsymboldatabase.cpp | 8 ++++-- 4 files changed, 36 insertions(+), 31 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 2bbdc8e05..a714e891a 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -3607,18 +3607,18 @@ bool SymbolDatabase::isReservedName(const std::string& iName) const } static const Token * parsedecl(const Token *type, ValueType * const valuetype, ValueType::Sign defaultSignedness); -static void setValueType(Token *tok, const ValueType &valuetype, ValueType::Sign defaultSignedness); +static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, ValueType::Sign defaultSignedness); -static void setValueType(Token *tok, const Variable &var, ValueType::Sign defaultSignedness) +static void setValueType(Token *tok, const Variable &var, bool cpp, ValueType::Sign defaultSignedness) { ValueType valuetype; valuetype.pointer = var.dimensions().size(); valuetype.typeScope = var.typeScope(); if (parsedecl(var.typeStartToken(), &valuetype, defaultSignedness)) - setValueType(tok, valuetype, defaultSignedness); + setValueType(tok, valuetype, cpp, defaultSignedness); } -static void setValueType(Token *tok, const ValueType &valuetype, ValueType::Sign defaultSignedness) +static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, ValueType::Sign defaultSignedness) { tok->setValueType(new ValueType(valuetype)); Token *parent = const_cast(tok->astParent()); @@ -3628,7 +3628,8 @@ static void setValueType(Token *tok, const ValueType &valuetype, ValueType::Sign return; if (Token::Match(parent, "<<|>>")) { - setValueType(parent,valuetype, defaultSignedness); + if (!cpp || (parent->astOperand2() && parent->astOperand2()->valueType() && parent->astOperand2()->valueType()->isIntegral())) + setValueType(parent, *parent->astOperand1()->valueType(), cpp, defaultSignedness); return; } @@ -3636,20 +3637,20 @@ static void setValueType(Token *tok, const ValueType &valuetype, ValueType::Sign ValueType vt(valuetype); vt.pointer -= 1U; vt.constness >>= 1; - setValueType(parent, vt, defaultSignedness); + setValueType(parent, vt, cpp, defaultSignedness); return; } if (parent->str() == "*" && !parent->astOperand2() && valuetype.pointer > 0U) { ValueType vt(valuetype); vt.pointer -= 1U; vt.constness >>= 1; - setValueType(parent, vt, defaultSignedness); + setValueType(parent, vt, cpp, defaultSignedness); return; } if (parent->str() == "&" && !parent->astOperand2()) { ValueType vt(valuetype); vt.pointer += 1U; - setValueType(parent, vt, defaultSignedness); + setValueType(parent, vt, cpp, defaultSignedness); return; } @@ -3663,7 +3664,7 @@ static void setValueType(Token *tok, const ValueType &valuetype, ValueType::Sign for (std::list::const_iterator it = typeScope->varlist.begin(); it != typeScope->varlist.end(); ++it) { const Variable &var = *it; if (var.nameToken()->str() == name) { - setValueType(parent, var, defaultSignedness); + setValueType(parent, var, cpp, defaultSignedness); return; } } @@ -3675,30 +3676,30 @@ static void setValueType(Token *tok, const ValueType &valuetype, ValueType::Sign const ValueType *vt2 = parent->astOperand2() ? parent->astOperand2()->valueType() : nullptr; if (parent->isArithmeticalOp() && vt2) { if (vt1->pointer != 0U && vt2->pointer == 0U) { - setValueType(parent, *vt1, defaultSignedness); + setValueType(parent, *vt1, cpp, defaultSignedness); return; } if (vt1->pointer == 0U && vt2->pointer != 0U) { - setValueType(parent, *vt2, defaultSignedness); + setValueType(parent, *vt2, cpp, defaultSignedness); return; } if (vt1->pointer != 0U) { // result is pointer diff - setValueType(parent, ValueType(ValueType::Sign::UNSIGNED, ValueType::Type::INT, 0U, 0U, "ptrdiff_t"), defaultSignedness); + setValueType(parent, ValueType(ValueType::Sign::UNSIGNED, ValueType::Type::INT, 0U, 0U, "ptrdiff_t"), cpp, defaultSignedness); return; } if (vt1->type == ValueType::Type::LONGDOUBLE || vt2->type == ValueType::Type::LONGDOUBLE) { - setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::LONGDOUBLE, 0U), defaultSignedness); + setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::LONGDOUBLE, 0U), cpp, defaultSignedness); return; } if (vt1->type == ValueType::Type::DOUBLE || vt2->type == ValueType::Type::DOUBLE) { - setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::DOUBLE, 0U), defaultSignedness); + setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::DOUBLE, 0U), cpp, defaultSignedness); return; } if (vt1->type == ValueType::Type::FLOAT || vt2->type == ValueType::Type::FLOAT) { - setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::FLOAT, 0U), defaultSignedness); + setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::FLOAT, 0U), cpp, defaultSignedness); return; } } @@ -3733,7 +3734,7 @@ static void setValueType(Token *tok, const ValueType &valuetype, ValueType::Sign vt.originalTypeName.clear(); } - setValueType(parent, vt, defaultSignedness); + setValueType(parent, vt, cpp, defaultSignedness); return; } } @@ -3788,7 +3789,7 @@ static const Token * parsedecl(const Token *type, ValueType * const valuetype, V return (type && valuetype->type != ValueType::Type::UNKNOWN_TYPE) ? type : nullptr; } -void SymbolDatabase::setValueTypeInTokenList(Token *tokens, char defaultSignedness) +void SymbolDatabase::setValueTypeInTokenList(Token *tokens, bool cpp, char defaultSignedness) { ValueType::Sign defsign; if (defaultSignedness == 's' || defaultSignedness == 'S') @@ -3808,7 +3809,7 @@ void SymbolDatabase::setValueTypeInTokenList(Token *tokens, char defaultSignedne const char suffix = tok->str()[tok->str().size() - 1U]; if (suffix == 'f' || suffix == 'F') type = ValueType::Type::FLOAT; - ::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, type, 0U), defsign); + ::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, type, 0U), cpp, defsign); } else if (MathLib::isInt(tok->str())) { ValueType::Sign sign = ValueType::Sign::SIGNED; ValueType::Type type = ValueType::Type::INT; @@ -3821,49 +3822,49 @@ void SymbolDatabase::setValueTypeInTokenList(Token *tokens, char defaultSignedne if (suffix == 'l' || suffix == 'L') type = (type == ValueType::Type::INT) ? ValueType::Type::LONG : ValueType::Type::LONGLONG; } - ::setValueType(tok, ValueType(sign, type, 0U), defsign); + ::setValueType(tok, ValueType(sign, type, 0U), cpp, defsign); } } else if (tok->isComparisonOp()) - ::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::BOOL, 0U), defsign); + ::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::BOOL, 0U), cpp, defsign); else if (tok->tokType() == Token::eChar) - ::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::CHAR, 0U), defsign); + ::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::CHAR, 0U), cpp, defsign); else if (tok->tokType() == Token::eString) { ValueType valuetype(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::CHAR, 1U, 1U); if (tok->isLong()) { valuetype.originalTypeName = "wchar_t"; valuetype.type = ValueType::Type::SHORT; } - ::setValueType(tok, valuetype, defsign); + ::setValueType(tok, valuetype, cpp, defsign); } else if (tok->str() == "(") { // cast if (!tok->astOperand2() && Token::Match(tok, "( %name%")) { ValueType valuetype; if (Token::simpleMatch(parsedecl(tok->next(), &valuetype, defsign), ")")) - ::setValueType(tok, valuetype, defsign); + ::setValueType(tok, valuetype, cpp, defsign); } // C++ cast if (tok->astOperand2() && Token::Match(tok->astOperand1(), "static_cast|const_cast|dynamic_cast|reinterpret_cast < %name%") && tok->astOperand1()->linkAt(1)) { ValueType valuetype; if (Token::simpleMatch(parsedecl(tok->astOperand1()->tokAt(2), &valuetype, defsign), ">")) - ::setValueType(tok, valuetype, defsign); + ::setValueType(tok, valuetype, cpp, defsign); } // function else if (tok->previous() && tok->previous()->function() && tok->previous()->function()->retDef) { ValueType valuetype; if (Token::simpleMatch(parsedecl(tok->previous()->function()->retDef, &valuetype, defsign), "(")) - ::setValueType(tok, valuetype, defsign); + ::setValueType(tok, valuetype, cpp, defsign); } else if (Token::simpleMatch(tok->previous(), "sizeof (")) { // TODO: use specified size_t type ValueType valuetype(ValueType::Sign::UNSIGNED, ValueType::Type::LONG, 0U); valuetype.originalTypeName = "size_t"; - setValueType(tok, valuetype, defsign); + setValueType(tok, valuetype, cpp, defsign); } } else if (tok->variable()) { - setValueType(tok, *tok->variable(), defsign); + setValueType(tok, *tok->variable(), cpp, defsign); } } } diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index df56da5ca..6bb228a76 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -1027,7 +1027,7 @@ public: void validate() const; /** Set valuetype in provided tokenlist */ - static void setValueTypeInTokenList(Token *tokens, char defaultSignedness); + static void setValueTypeInTokenList(Token *tokens, bool cpp, char defaultSignedness); private: friend class Scope; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 53a43f43f..f43803bec 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1735,7 +1735,7 @@ bool Tokenizer::simplifyTokens1(const std::string &configuration, list.createAst(); list.validateAst(); - SymbolDatabase::setValueTypeInTokenList(list.front(), _settings->defaultSign); + SymbolDatabase::setValueTypeInTokenList(list.front(), isCPP(), _settings->defaultSign); ValueFlow::setValues(&list, _symbolDatabase, _errorLogger, _settings); } diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index c1ae75e9c..644917fce 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -3077,12 +3077,12 @@ private: "}"); } - std::string typeOf(const char code[], const char str[]) { + std::string typeOf(const char code[], const char str[], const char filename[] = "test.cpp") { Settings s; s.platform(Settings::Unspecified); Tokenizer tokenizer(&s, this); std::istringstream istr(code); - tokenizer.tokenize(istr, "test.cpp"); + tokenizer.tokenize(istr, filename); const Token * const tok = Token::findsimplematch(tokenizer.tokens(),str); return tok->valueType() ? tok->valueType()->str() : std::string(); } @@ -3153,6 +3153,10 @@ private: // shift => result has same type as lhs ASSERT_EQUALS("int", typeOf("int x; a = x << 1U;", "<<")); ASSERT_EQUALS("int", typeOf("int x; a = x >> 1U;", ">>")); + ASSERT_EQUALS("", typeOf("a = 12 >> x;", ">>", "test.cpp")); // >> might be overloaded + ASSERT_EQUALS("signed int", typeOf("a = 12 >> x;", ">>", "test.c")); + ASSERT_EQUALS("", typeOf("a = 12 << x;", "<<", "test.cpp")); // << might be overloaded + ASSERT_EQUALS("signed int", typeOf("a = 12 << x;", "<<", "test.c")); // array.. ASSERT_EQUALS("void * *", typeOf("void * x[10]; a = x + 0;", "+"));