From 09b6568ea26c3f5503f4514737d44ae6586968bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sun, 31 Jul 2016 19:47:34 +0200 Subject: [PATCH] Fixed #7646 (podtypes do not get proper valuetype) --- lib/library.h | 2 + lib/settings.h | 17 ++++ lib/symboldatabase.cpp | 151 ++++++++++++++++++++++-------------- lib/symboldatabase.h | 4 +- lib/tokenize.cpp | 4 +- test/testsymboldatabase.cpp | 23 ++++++ 6 files changed, 141 insertions(+), 60 deletions(-) diff --git a/lib/library.h b/lib/library.h index 1cc07f8fd..02c965365 100644 --- a/lib/library.h +++ b/lib/library.h @@ -44,6 +44,8 @@ namespace tinyxml2 { * @brief Library definitions handling */ class CPPCHECKLIB Library { + friend class TestSymbolDatabase; // For testing only + public: Library(); diff --git a/lib/settings.h b/lib/settings.h index 13532e351..8e4c868c8 100644 --- a/lib/settings.h +++ b/lib/settings.h @@ -293,6 +293,23 @@ public: platformType == Win64; } + const char *platformString() const { + switch (platformType) { + case Unix32: + return "unix32"; + case Unix64: + return "unix64"; + case Win32A: + return "win32A"; + case Win32W: + return "win32W"; + case Win64: + return "win64"; + default: + return "unknown"; + } + } + /** * @brief return true if a file is to be excluded from configuration checking * @return true for the file to be excluded. diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 22bc731b8..19223777a 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -4099,21 +4099,21 @@ unsigned int SymbolDatabase::sizeOfType(const Token *type) const return size; } -static const Token * parsedecl(const Token *type, ValueType * const valuetype, ValueType::Sign defaultSignedness, const Library* lib); -static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, ValueType::Sign defaultSignedness, const Library* lib); +static const Token * parsedecl(const Token *type, ValueType * const valuetype, ValueType::Sign defaultSignedness, const Settings* settings); +static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, ValueType::Sign defaultSignedness, const Settings* settings); -static void setValueType(Token *tok, const Variable &var, bool cpp, ValueType::Sign defaultSignedness, const Library* lib) +static void setValueType(Token *tok, const Variable &var, bool cpp, ValueType::Sign defaultSignedness, const Settings* settings) { if (var.isStlType()) return; ValueType valuetype; valuetype.pointer = var.dimensions().size(); valuetype.typeScope = var.typeScope(); - if (parsedecl(var.typeStartToken(), &valuetype, defaultSignedness, lib)) - setValueType(tok, valuetype, cpp, defaultSignedness, lib); + if (parsedecl(var.typeStartToken(), &valuetype, defaultSignedness, settings)) + setValueType(tok, valuetype, cpp, defaultSignedness, settings); } -static void setValueType(Token *tok, const Enumerator &enumerator, bool cpp, ValueType::Sign defaultSignedness, const Library* lib) +static void setValueType(Token *tok, const Enumerator &enumerator, bool cpp, ValueType::Sign defaultSignedness, const Settings* settings) { ValueType valuetype; valuetype.typeScope = enumerator.scope; @@ -4135,22 +4135,18 @@ static void setValueType(Token *tok, const Enumerator &enumerator, bool cpp, Val else if (type->str() == "long") valuetype.type = type->isLong() ? ValueType::Type::LONGLONG : ValueType::Type::LONG; else if (type->isStandardType()) { - const Library::PodType* podtype = lib->podtype(type->str()); - if (podtype && (podtype->sign == 's' || podtype->sign == 'u')) { - valuetype.type = ValueType::Type::UNKNOWN_INT; - valuetype.sign = (podtype->sign == 'u') ? ValueType::UNSIGNED : ValueType::SIGNED; - } + valuetype.fromLibraryType(type->str(), settings); } - setValueType(tok, valuetype, cpp, defaultSignedness, lib); + setValueType(tok, valuetype, cpp, defaultSignedness, settings); } else { valuetype.sign = ValueType::SIGNED; valuetype.type = ValueType::INT; - setValueType(tok, valuetype, cpp, defaultSignedness, lib); + setValueType(tok, valuetype, cpp, defaultSignedness, settings); } } -static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, ValueType::Sign defaultSignedness, const Library* lib) +static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, ValueType::Sign defaultSignedness, const Settings* settings) { tok->setValueType(new ValueType(valuetype)); Token *parent = const_cast(tok->astParent()); @@ -4164,32 +4160,32 @@ static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, Value if (vt1 && Token::Match(parent, "<<|>>")) { if (!cpp || (vt2 && vt2->isIntegral())) - setValueType(parent, *vt1, cpp, defaultSignedness, lib); + setValueType(parent, *vt1, cpp, defaultSignedness, settings); return; } if (parent->isAssignmentOp()) { if (vt1) - setValueType(parent, *vt1, cpp, defaultSignedness, lib); + setValueType(parent, *vt1, cpp, defaultSignedness, settings); return; } if (parent->str() == "[" && (!cpp || parent->astOperand1() == tok) && valuetype.pointer > 0U) { ValueType vt(valuetype); vt.pointer -= 1U; - setValueType(parent, vt, cpp, defaultSignedness, lib); + setValueType(parent, vt, cpp, defaultSignedness, settings); return; } if (parent->str() == "*" && !parent->astOperand2() && valuetype.pointer > 0U) { ValueType vt(valuetype); vt.pointer -= 1U; - setValueType(parent, vt, cpp, defaultSignedness, lib); + setValueType(parent, vt, cpp, defaultSignedness, settings); return; } if (parent->str() == "&" && !parent->astOperand2()) { ValueType vt(valuetype); vt.pointer += 1U; - setValueType(parent, vt, cpp, defaultSignedness, lib); + setValueType(parent, vt, cpp, defaultSignedness, settings); return; } @@ -4209,7 +4205,7 @@ static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, Value } } if (var) - setValueType(parent, *var, cpp, defaultSignedness, lib); + setValueType(parent, *var, cpp, defaultSignedness, settings); return; } @@ -4224,33 +4220,33 @@ static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, Value if (ternary || parent->isArithmeticalOp() || parent->tokType() == Token::eIncDecOp) { if (vt1->pointer != 0U && vt2 && vt2->pointer == 0U) { - setValueType(parent, *vt1, cpp, defaultSignedness, lib); + setValueType(parent, *vt1, cpp, defaultSignedness, settings); return; } if (vt1->pointer == 0U && vt2 && vt2->pointer != 0U) { - setValueType(parent, *vt2, cpp, defaultSignedness, lib); + setValueType(parent, *vt2, cpp, defaultSignedness, settings); return; } if (vt1->pointer != 0U) { if (ternary || parent->tokType() == Token::eIncDecOp) // result is pointer - setValueType(parent, *vt1, cpp, defaultSignedness, lib); + setValueType(parent, *vt1, cpp, defaultSignedness, settings); else // result is pointer diff - setValueType(parent, ValueType(ValueType::Sign::SIGNED, ValueType::Type::INT, 0U, 0U, "ptrdiff_t"), cpp, defaultSignedness, lib); + setValueType(parent, ValueType(ValueType::Sign::SIGNED, ValueType::Type::INT, 0U, 0U, "ptrdiff_t"), cpp, defaultSignedness, settings); return; } if (vt1->type == ValueType::Type::LONGDOUBLE || (vt2 && vt2->type == ValueType::Type::LONGDOUBLE)) { - setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::LONGDOUBLE, 0U), cpp, defaultSignedness, lib); + setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::LONGDOUBLE, 0U), cpp, defaultSignedness, settings); return; } if (vt1->type == ValueType::Type::DOUBLE || (vt2 && vt2->type == ValueType::Type::DOUBLE)) { - setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::DOUBLE, 0U), cpp, defaultSignedness, lib); + setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::DOUBLE, 0U), cpp, defaultSignedness, settings); return; } if (vt1->type == ValueType::Type::FLOAT || (vt2 && vt2->type == ValueType::Type::FLOAT)) { - setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::FLOAT, 0U), cpp, defaultSignedness, lib); + setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::FLOAT, 0U), cpp, defaultSignedness, settings); return; } } @@ -4284,12 +4280,12 @@ static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, Value vt.originalTypeName.clear(); } - setValueType(parent, vt, cpp, defaultSignedness, lib); + setValueType(parent, vt, cpp, defaultSignedness, settings); return; } } -static const Token * parsedecl(const Token *type, ValueType * const valuetype, ValueType::Sign defaultSignedness, const Library* lib) +static const Token * parsedecl(const Token *type, ValueType * const valuetype, ValueType::Sign defaultSignedness, const Settings* settings) { const unsigned int pointer0 = valuetype->pointer; while (Token::Match(type->previous(), "%name%")) @@ -4333,13 +4329,8 @@ static const Token * parsedecl(const Token *type, ValueType * const valuetype, V return nullptr; else if (type->str() == "*") valuetype->pointer++; - else if (type->isStandardType()) { - const Library::PodType* podtype = lib->podtype(type->str()); - if (podtype && (podtype->sign == 's' || podtype->sign == 'u')) { - valuetype->type = ValueType::Type::UNKNOWN_INT; - valuetype->sign = (podtype->sign == 'u') ? ValueType::UNSIGNED : ValueType::SIGNED; - } - } + else if (type->isStandardType()) + valuetype->fromLibraryType(type->str(), settings); if (!type->originalName().empty()) valuetype->originalTypeName = type->originalName(); type = type->next(); @@ -4386,12 +4377,12 @@ static const Function *getOperatorFunction(const Token * const tok) return nullptr; } -void SymbolDatabase::setValueTypeInTokenList(Token *tokens, bool cpp, char defaultSignedness, const Library* lib) +void SymbolDatabase::setValueTypeInTokenList(Token *tokens, bool cpp, const Settings* settings) { ValueType::Sign defsign; - if (defaultSignedness == 's' || defaultSignedness == 'S') + if (settings->defaultSign == 's' || settings->defaultSign == 'S') defsign = ValueType::SIGNED; - else if (defaultSignedness == 'u' || defaultSignedness == 'U') + else if (settings->defaultSign == 'u' || settings->defaultSign == 'U') defsign = ValueType::UNSIGNED; else defsign = ValueType::UNKNOWN_SIGN; @@ -4406,7 +4397,7 @@ void SymbolDatabase::setValueTypeInTokenList(Token *tokens, bool cpp, char defau 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), cpp, defsign, lib); + ::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, type, 0U), cpp, defsign, settings); } else if (MathLib::isInt(tok->str())) { ValueType::Sign sign = ValueType::Sign::SIGNED; ValueType::Type type = ValueType::Type::INT; @@ -4423,71 +4414,117 @@ void SymbolDatabase::setValueTypeInTokenList(Token *tokens, bool cpp, char defau pos -= 2; } else break; } - ::setValueType(tok, ValueType(sign, type, 0U), cpp, defsign, lib); + ::setValueType(tok, ValueType(sign, type, 0U), cpp, defsign, settings); } } else if (tok->isComparisonOp() || tok->tokType() == Token::eLogicalOp) { if (cpp && tok->isComparisonOp() && (getClassScope(tok->astOperand1()) || getClassScope(tok->astOperand2()))) { const Function *function = getOperatorFunction(tok); if (function) { ValueType vt; - parsedecl(function->retDef, &vt, defsign, lib); - ::setValueType(tok, vt, cpp, defsign, lib); + parsedecl(function->retDef, &vt, defsign, settings); + ::setValueType(tok, vt, cpp, defsign, settings); continue; } } - ::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::BOOL, 0U), cpp, defsign, lib); + ::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::BOOL, 0U), cpp, defsign, settings); } else if (tok->tokType() == Token::eChar) - ::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::CHAR, 0U), cpp, defsign, lib); + ::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::CHAR, 0U), cpp, defsign, settings); 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, cpp, defsign, lib); + ::setValueType(tok, valuetype, cpp, defsign, settings); } else if (tok->str() == "(") { // cast if (!tok->astOperand2() && Token::Match(tok, "( %name%")) { ValueType valuetype; - if (Token::simpleMatch(parsedecl(tok->next(), &valuetype, defsign, lib), ")")) - ::setValueType(tok, valuetype, cpp, defsign, lib); + if (Token::simpleMatch(parsedecl(tok->next(), &valuetype, defsign, settings), ")")) + ::setValueType(tok, valuetype, cpp, defsign, settings); } // 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, lib), ">")) - ::setValueType(tok, valuetype, cpp, defsign, lib); + if (Token::simpleMatch(parsedecl(tok->astOperand1()->tokAt(2), &valuetype, defsign, settings), ">")) + ::setValueType(tok, valuetype, cpp, defsign, settings); } // function else if (tok->previous() && tok->previous()->function() && tok->previous()->function()->retDef) { ValueType valuetype; - if (parsedecl(tok->previous()->function()->retDef, &valuetype, defsign, lib)) - ::setValueType(tok, valuetype, cpp, defsign, lib); + if (parsedecl(tok->previous()->function()->retDef, &valuetype, defsign, settings)) + ::setValueType(tok, valuetype, cpp, defsign, settings); } 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, cpp, defsign, lib); + setValueType(tok, valuetype, cpp, defsign, settings); if (Token::Match(tok, "( %type% %type%| *| *| )")) { ValueType vt; - if (parsedecl(tok->next(), &vt, defsign, lib)) { - setValueType(tok->next(), vt, cpp, defsign, lib); + if (parsedecl(tok->next(), &vt, defsign, settings)) { + setValueType(tok->next(), vt, cpp, defsign, settings); } } } } else if (tok->variable()) { - setValueType(tok, *tok->variable(), cpp, defsign, lib); + setValueType(tok, *tok->variable(), cpp, defsign, settings); } else if (tok->enumerator()) { - setValueType(tok, *tok->enumerator(), cpp, defsign, lib); + setValueType(tok, *tok->enumerator(), cpp, defsign, settings); } } } +bool ValueType::fromLibraryType(const std::string &typestr, const Settings *settings) +{ + const Library::PodType* podtype = settings->library.podtype(typestr); + if (podtype && (podtype->sign == 's' || podtype->sign == 'u')) { + if (podtype->size == 1) + type = ValueType::Type::CHAR; + else if (podtype->size == settings->sizeof_int) + type = ValueType::Type::INT; + else if (podtype->size == settings->sizeof_short) + type = ValueType::Type::SHORT; + else if (podtype->size == settings->sizeof_long) + type = ValueType::Type::LONG; + else if (podtype->size == settings->sizeof_long_long) + type = ValueType::Type::LONGLONG; + else + type = ValueType::Type::UNKNOWN_INT; + sign = (podtype->sign == 'u') ? ValueType::UNSIGNED : ValueType::SIGNED; + return true; + } + + const Library::PlatformType *platformType = settings->library.platform_type(typestr, settings->platformString()); + if (platformType) { + if (platformType->_type == "char") + type = ValueType::Type::CHAR; + else if (platformType->_type == "short") + type = ValueType::Type::SHORT; + else if (platformType->_type == "int") + type = platformType->_long ? ValueType::Type::LONG : ValueType::Type::INT; + else if (platformType->_type == "long") + type = platformType->_long ? ValueType::Type::LONGLONG : ValueType::Type::LONG; + if (platformType->_signed) + sign = ValueType::SIGNED; + else if (platformType->_unsigned) + sign = ValueType::UNSIGNED; + if (platformType->_pointer) + pointer = 1; + if (platformType->_ptr_ptr) + pointer = 2; + if (platformType->_const_ptr) + constness = 1; + return true; + } + + return false; +} + std::string ValueType::str() const { std::string ret; diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 5713c5d8a..d519815d1 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -1071,7 +1071,7 @@ public: void validateVariables() const; /** Set valuetype in provided tokenlist */ - static void setValueTypeInTokenList(Token *tokens, bool cpp, char defaultSignedness, const Library* lib); + static void setValueTypeInTokenList(Token *tokens, bool cpp, const Settings *settings); /** * Calculates sizeof value for given type. @@ -1129,6 +1129,8 @@ public: return (type >= ValueType::Type::BOOL && type <= ValueType::Type::UNKNOWN_INT); } + bool fromLibraryType(const std::string &typestr, const Settings *settings); + std::string str() const; }; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 2a8b81f1e..bedf86531 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1720,7 +1720,7 @@ bool Tokenizer::simplifyTokens1(const std::string &configuration) } } - SymbolDatabase::setValueTypeInTokenList(list.front(), isCPP(), _settings->defaultSign, &_settings->library); + SymbolDatabase::setValueTypeInTokenList(list.front(), isCPP(), _settings); ValueFlow::setValues(&list, _symbolDatabase, _errorLogger, _settings); printDebugOutput(1); @@ -3767,7 +3767,7 @@ bool Tokenizer::simplifyTokenList2() // Create symbol database and then remove const keywords createSymbolDatabase(); - SymbolDatabase::setValueTypeInTokenList(list.front(), isCPP(), _settings->defaultSign, &_settings->library); + SymbolDatabase::setValueTypeInTokenList(list.front(), isCPP(), _settings); ValueFlow::setValues(&list, _symbolDatabase, _errorLogger, _settings); diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index 936ec0cd5..26b9217a9 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -3670,6 +3670,29 @@ private: // Pointer to unknown type ASSERT_EQUALS("*", typeOf("Bar* b;", "b")); + + // Library types + { + // PodType + Settings s; + s.platformType = Settings::Win64; + const Library::PodType u32 = { 4, 'u' }; + s.library.podtypes["u32"] = u32; + ValueType vt; + ASSERT_EQUALS(true, vt.fromLibraryType("u32", &s)); + ASSERT_EQUALS(ValueType::Type::INT, vt.type); + } + { + // PlatformType + Settings s; + s.platformType = Settings::Unix32; + Library::PlatformType s32; + s32._type = "int"; + s.library.platforms[s.platformString()]._platform_types["s32"] = s32; + ValueType vt; + ASSERT_EQUALS(true, vt.fromLibraryType("s32", &s)); + ASSERT_EQUALS(ValueType::Type::INT, vt.type); + } } };