From f099c6a1109cc1840e35eb32c90cc4921f1133b6 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Tue, 21 Mar 2017 21:55:22 -0400 Subject: [PATCH 1/3] Refactor symbol database value type support by making setValueTypeInTokenList and setValueType member functions of SymbolDatabase. Class variables are no longer passed around as parameters but accessed directly which simplifies the code. There should be no functional change. --- lib/symboldatabase.cpp | 140 +++++++++++++++++++++-------------------- lib/symboldatabase.h | 77 +++++++++++++---------- lib/tokenize.cpp | 4 +- 3 files changed, 116 insertions(+), 105 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index bf78eaa33..308176f70 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -37,6 +37,15 @@ SymbolDatabase::SymbolDatabase(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger) : _tokenizer(tokenizer), _settings(settings), _errorLogger(errorLogger) { + cpp = isCPP(); + + if (_settings->defaultSign == 's' || _settings->defaultSign == 'S') + defaultSignedness = ValueType::SIGNED; + else if (_settings->defaultSign == 'u' || _settings->defaultSign == 'U') + defaultSignedness = ValueType::UNSIGNED; + else + defaultSignedness = ValueType::UNKNOWN_SIGN; + createSymbolDatabaseFindAllScopes(); createSymbolDatabaseClassInfo(); createSymbolDatabaseVariableInfo(); @@ -4409,18 +4418,17 @@ unsigned int SymbolDatabase::sizeOfType(const Token *type) const } 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 Settings* settings) +void SymbolDatabase::setValueType(Token *tok, const Variable &var) { ValueType valuetype; valuetype.pointer = var.dimensions().size(); valuetype.typeScope = var.typeScope(); - if (parsedecl(var.typeStartToken(), &valuetype, defaultSignedness, settings)) - setValueType(tok, valuetype, cpp, defaultSignedness, settings); + if (parsedecl(var.typeStartToken(), &valuetype, defaultSignedness, _settings)) + setValueType(tok, valuetype); } -static void setValueType(Token *tok, const Enumerator &enumerator, bool cpp, ValueType::Sign defaultSignedness, const Settings* settings) +void SymbolDatabase::setValueType(Token *tok, const Enumerator &enumerator) { ValueType valuetype; valuetype.typeScope = enumerator.scope; @@ -4428,7 +4436,7 @@ static void setValueType(Token *tok, const Enumerator &enumerator, bool cpp, Val if (type) { valuetype.type = ValueType::typeFromString(type->str(), type->isLong()); if (valuetype.type == ValueType::Type::UNKNOWN_TYPE && type->isStandardType()) - valuetype.fromLibraryType(type->str(), settings); + valuetype.fromLibraryType(type->str(), _settings); if (valuetype.isIntegral()) { if (type->isSigned()) @@ -4441,11 +4449,11 @@ static void setValueType(Token *tok, const Enumerator &enumerator, bool cpp, Val valuetype.sign = ValueType::Sign::SIGNED; } - setValueType(tok, valuetype, cpp, defaultSignedness, settings); + setValueType(tok, valuetype); } else { valuetype.sign = ValueType::SIGNED; valuetype.type = ValueType::INT; - setValueType(tok, valuetype, cpp, defaultSignedness, settings); + setValueType(tok, valuetype); } } @@ -4456,7 +4464,7 @@ static void setAutoTokenProperties(Token * const autoTok) autoTok->isStandardType(true); } -static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, ValueType::Sign defaultSignedness, const Settings* settings) +void SymbolDatabase::setValueType(Token *tok, const ValueType &valuetype) { tok->setValueType(new ValueType(valuetype)); Token *parent = const_cast(tok->astParent()); @@ -4470,13 +4478,13 @@ 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, settings); + setValueType(parent, *vt1); return; } if (parent->isAssignmentOp()) { if (vt1) - setValueType(parent, *vt1, cpp, defaultSignedness, settings); + setValueType(parent, *vt1); else if (cpp && Token::Match(parent->tokAt(-3), "%var% ; %var% =") && parent->strAt(-3) == parent->strAt(-1)) { Token *var1Tok = parent->tokAt(-3); Token *autoTok = nullptr; @@ -4485,10 +4493,10 @@ static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, Value else if (Token::Match(var1Tok->tokAt(-3), "[;{}] auto *")) autoTok = var1Tok->tokAt(-2); if (autoTok) { - setValueType(autoTok, *vt2, cpp, defaultSignedness, settings); + setValueType(autoTok, *vt2); setAutoTokenProperties(autoTok); - setValueType(var1Tok, *vt2, cpp, defaultSignedness, settings); - setValueType(parent->previous(), *vt2, cpp, defaultSignedness, settings); + setValueType(var1Tok, *vt2); + setValueType(parent->previous(), *vt2); const Variable *var = parent->previous()->variable(); if (var) const_cast(var)->setFlags(*vt2); @@ -4500,25 +4508,25 @@ static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, Value if (parent->str() == "[" && (!cpp || parent->astOperand1() == tok) && valuetype.pointer > 0U) { ValueType vt(valuetype); vt.pointer -= 1U; - setValueType(parent, vt, cpp, defaultSignedness, settings); + setValueType(parent, vt); return; } if (Token::Match(parent->previous(), "%name% (") && parent->astOperand1() == tok && valuetype.pointer > 0U) { ValueType vt(valuetype); vt.pointer -= 1U; - setValueType(parent, vt, cpp, defaultSignedness, settings); + setValueType(parent, vt); return; } if (parent->str() == "*" && !parent->astOperand2() && valuetype.pointer > 0U) { ValueType vt(valuetype); vt.pointer -= 1U; - setValueType(parent, vt, cpp, defaultSignedness, settings); + setValueType(parent, vt); return; } if (parent->str() == "&" && !parent->astOperand2()) { ValueType vt(valuetype); vt.pointer += 1U; - setValueType(parent, vt, cpp, defaultSignedness, settings); + setValueType(parent, vt); return; } @@ -4538,7 +4546,7 @@ static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, Value } } if (var) - setValueType(parent, *var, cpp, defaultSignedness, settings); + setValueType(parent, *var); return; } @@ -4555,9 +4563,9 @@ static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, Value vt.pointer--; if (isconst) vt.constness |= 1; - setValueType(autoToken, vt, cpp, defaultSignedness, settings); + setValueType(autoToken, vt); setAutoTokenProperties(autoToken); - setValueType(parent->previous(), vt, cpp, defaultSignedness, settings); + setValueType(parent->previous(), vt); const_cast(parent->previous()->variable())->setFlags(vt); } else if (vt2->container) { // TODO: Determine exact type of RHS @@ -4573,10 +4581,10 @@ static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, Value // TODO: Get type better if (Token::Match(typeStart, "std :: %type% < %type% *| *| >")) { ValueType vt; - if (parsedecl(typeStart->tokAt(4), &vt, defaultSignedness, settings)) { - setValueType(autoToken, vt, cpp, defaultSignedness, settings); + if (parsedecl(typeStart->tokAt(4), &vt, defaultSignedness, _settings)) { + setValueType(autoToken, vt); setAutoTokenProperties(autoToken); - setValueType(parent->previous(), vt, cpp, defaultSignedness, settings); + setValueType(parent->previous(), vt); } } } @@ -4593,33 +4601,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, settings); + setValueType(parent, *vt1); return; } if (vt1->pointer == 0U && vt2 && vt2->pointer != 0U) { - setValueType(parent, *vt2, cpp, defaultSignedness, settings); + setValueType(parent, *vt2); return; } if (vt1->pointer != 0U) { if (ternary || parent->tokType() == Token::eIncDecOp) // result is pointer - setValueType(parent, *vt1, cpp, defaultSignedness, settings); + setValueType(parent, *vt1); else // result is pointer diff - setValueType(parent, ValueType(ValueType::Sign::SIGNED, ValueType::Type::INT, 0U, 0U, "ptrdiff_t"), cpp, defaultSignedness, settings); + setValueType(parent, ValueType(ValueType::Sign::SIGNED, ValueType::Type::INT, 0U, 0U, "ptrdiff_t")); 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, settings); + setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::LONGDOUBLE, 0U)); 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, settings); + setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::DOUBLE, 0U)); 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, settings); + setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::FLOAT, 0U)); return; } } @@ -4653,7 +4661,7 @@ static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, Value vt.originalTypeName.clear(); } - setValueType(parent, vt, cpp, defaultSignedness, settings); + setValueType(parent, vt); return; } } @@ -4778,15 +4786,9 @@ static const Function *getOperatorFunction(const Token * const tok) return nullptr; } -void SymbolDatabase::setValueTypeInTokenList(Token *tokens, bool cpp, const Settings* settings) +void SymbolDatabase::setValueTypeInTokenList() { - ValueType::Sign defsign; - if (settings->defaultSign == 's' || settings->defaultSign == 'S') - defsign = ValueType::SIGNED; - else if (settings->defaultSign == 'u' || settings->defaultSign == 'U') - defsign = ValueType::UNSIGNED; - else - defsign = ValueType::UNKNOWN_SIGN; + Token * tokens = const_cast(_tokenizer)->list.front(); for (Token *tok = tokens; tok; tok = tok->next()) tok->setValueType(nullptr); @@ -4800,17 +4802,17 @@ void SymbolDatabase::setValueTypeInTokenList(Token *tokens, bool cpp, const Sett type = ValueType::Type::FLOAT; else if (suffix == 'L' || suffix == 'l') type = ValueType::Type::LONGDOUBLE; - ::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, type, 0U), cpp, defsign, settings); + setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, type, 0U)); } else if (MathLib::isInt(tok->str())) { bool unsignedSuffix = (tok->str().find_last_of("uU") != std::string::npos); ValueType::Sign sign = unsignedSuffix ? ValueType::Sign::UNSIGNED : ValueType::Sign::SIGNED; ValueType::Type type; const MathLib::bigint value = MathLib::toLongNumber(tok->str()); - if (settings->platformType == cppcheck::Platform::Unspecified) + if (_settings->platformType == cppcheck::Platform::Unspecified) type = ValueType::Type::INT; - else if (settings->isIntValue(unsignedSuffix ? (value >> 1) : value)) + else if (_settings->isIntValue(unsignedSuffix ? (value >> 1) : value)) type = ValueType::Type::INT; - else if (settings->isLongValue(unsignedSuffix ? (value >> 1) : value)) + else if (_settings->isLongValue(unsignedSuffix ? (value >> 1) : value)) type = ValueType::Type::LONG; else type = ValueType::Type::LONGLONG; @@ -4827,67 +4829,67 @@ void SymbolDatabase::setValueTypeInTokenList(Token *tokens, bool cpp, const Sett pos -= 2; } else break; } - ::setValueType(tok, ValueType(sign, type, 0U), cpp, defsign, settings); + setValueType(tok, ValueType(sign, type, 0U)); } } 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, settings); - ::setValueType(tok, vt, cpp, defsign, settings); + parsedecl(function->retDef, &vt, defaultSignedness, _settings); + setValueType(tok, vt); continue; } } - ::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::BOOL, 0U), cpp, defsign, settings); + setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::BOOL, 0U)); } else if (tok->tokType() == Token::eChar) - ::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::CHAR, 0U), cpp, defsign, settings); + setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::CHAR, 0U)); 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, settings); + setValueType(tok, valuetype); } else if (tok->str() == "(") { // cast if (!tok->astOperand2() && Token::Match(tok, "( %name%")) { ValueType valuetype; - if (Token::simpleMatch(parsedecl(tok->next(), &valuetype, defsign, settings), ")")) - ::setValueType(tok, valuetype, cpp, defsign, settings); + if (Token::simpleMatch(parsedecl(tok->next(), &valuetype, defaultSignedness, _settings), ")")) + setValueType(tok, valuetype); } // 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, settings), ">")) - ::setValueType(tok, valuetype, cpp, defsign, settings); + if (Token::simpleMatch(parsedecl(tok->astOperand1()->tokAt(2), &valuetype, defaultSignedness, _settings), ">")) + setValueType(tok, valuetype); } // function else if (tok->previous() && tok->previous()->function() && tok->previous()->function()->retDef) { ValueType valuetype; - if (parsedecl(tok->previous()->function()->retDef, &valuetype, defsign, settings)) - ::setValueType(tok, valuetype, cpp, defsign, settings); + if (parsedecl(tok->previous()->function()->retDef, &valuetype, defaultSignedness, _settings)) + setValueType(tok, valuetype); } 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, settings); + setValueType(tok, valuetype); if (Token::Match(tok, "( %type% %type%| *| *| )")) { ValueType vt; - if (parsedecl(tok->next(), &vt, defsign, settings)) { - setValueType(tok->next(), vt, cpp, defsign, settings); + if (parsedecl(tok->next(), &vt, defaultSignedness, _settings)) { + setValueType(tok->next(), vt); } } } // library function else if (tok->previous()) { - const std::string& typestr(settings->library.returnValueType(tok->previous())); + const std::string& typestr(_settings->library.returnValueType(tok->previous())); if (typestr.empty() || typestr == "iterator") { if (Token::simpleMatch(tok->astOperand1(), ".") && tok->astOperand1()->astOperand1() && @@ -4903,25 +4905,25 @@ void SymbolDatabase::setValueTypeInTokenList(Token *tokens, bool cpp, const Sett ValueType vt; vt.type = ValueType::Type::ITERATOR; vt.container = cont; - setValueType(tok, vt, cpp, defsign, settings); + setValueType(tok, vt); } } } continue; } - TokenList tokenList(settings); + TokenList tokenList(_settings); std::istringstream istr(typestr+";"); if (tokenList.createTokens(istr)) { ValueType vt; - if (parsedecl(tokenList.front(), &vt, defsign, settings)) { - setValueType(tok, vt, cpp, defsign, settings); + if (parsedecl(tokenList.front(), &vt, defaultSignedness, _settings)) { + setValueType(tok, vt); } } } } else if (tok->variable()) { - setValueType(tok, *tok->variable(), cpp, defsign, settings); + setValueType(tok, *tok->variable()); } else if (tok->enumerator()) { - setValueType(tok, *tok->enumerator(), cpp, defsign, settings); + setValueType(tok, *tok->enumerator()); } else if (cpp && tok->str() == "new") { const Token *typeTok = tok->next(); if (Token::Match(typeTok, "( std| ::| nothrow )")) @@ -4942,7 +4944,7 @@ void SymbolDatabase::setValueTypeInTokenList(Token *tokens, bool cpp, const Sett } else { vt.type = ValueType::typeFromString(typestr, typeTok->isLong()); if (vt.type == ValueType::Type::UNKNOWN_TYPE) - vt.fromLibraryType(typestr, settings); + vt.fromLibraryType(typestr, _settings); if (vt.type == ValueType::Type::UNKNOWN_TYPE) return; if (typeTok->isUnsigned()) @@ -4950,9 +4952,9 @@ void SymbolDatabase::setValueTypeInTokenList(Token *tokens, bool cpp, const Sett else if (typeTok->isSigned()) vt.sign = ValueType::Sign::SIGNED; if (vt.sign == ValueType::Sign::UNKNOWN_SIGN && vt.isIntegral()) - vt.sign = (vt.type == ValueType::Type::CHAR) ? defsign : ValueType::Sign::SIGNED; + vt.sign = (vt.type == ValueType::Type::CHAR) ? defaultSignedness : ValueType::Sign::SIGNED; } - setValueType(tok, vt, cpp, defsign, settings); + setValueType(tok, vt); } } } diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index 8dbc1dd72..c4771752e 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -1025,6 +1025,42 @@ private: void findFunctionInBase(const std::string & name, size_t args, std::vector & matches) const; }; + +/** Value type */ +class CPPCHECKLIB ValueType { +public: + enum Sign { UNKNOWN_SIGN, SIGNED, UNSIGNED } sign; + enum Type { UNKNOWN_TYPE, NONSTD, RECORD, CONTAINER, ITERATOR, VOID, BOOL, CHAR, SHORT, INT, LONG, LONGLONG, UNKNOWN_INT, FLOAT, DOUBLE, LONGDOUBLE } type; + unsigned int pointer; // 0=>not pointer, 1=>*, 2=>**, 3=>***, etc + unsigned int constness; // bit 0=data, bit 1=*, bit 2=** + const Scope *typeScope; + const Library::Container *container; + std::string originalTypeName; + + ValueType() : sign(UNKNOWN_SIGN), type(UNKNOWN_TYPE), pointer(0U), constness(0U), typeScope(nullptr), container(nullptr) {} + ValueType(const ValueType &vt) : sign(vt.sign), type(vt.type), pointer(vt.pointer), constness(vt.constness), typeScope(vt.typeScope), container(vt.container), originalTypeName(vt.originalTypeName) {} + ValueType(enum Sign s, enum Type t, unsigned int p) : sign(s), type(t), pointer(p), constness(0U), typeScope(nullptr), container(nullptr) {} + ValueType(enum Sign s, enum Type t, unsigned int p, unsigned int c) : sign(s), type(t), pointer(p), constness(c), typeScope(nullptr), container(nullptr) {} + ValueType(enum Sign s, enum Type t, unsigned int p, unsigned int c, const std::string &otn) : sign(s), type(t), pointer(p), constness(c), typeScope(nullptr), container(nullptr), originalTypeName(otn) {} + + static ValueType parseDecl(const Token *type, const Settings *settings); + + static Type typeFromString(const std::string &typestr, bool longType); + + bool isIntegral() const { + return (type >= ValueType::Type::BOOL && type <= ValueType::Type::UNKNOWN_INT); + } + + bool isFloat() const { + return (type == ValueType::Type::FLOAT || type == ValueType::Type::DOUBLE); + } + + bool fromLibraryType(const std::string &typestr, const Settings *settings); + + std::string str() const; +}; + + class CPPCHECKLIB SymbolDatabase { public: SymbolDatabase(const Tokenizer *tokenizer, const Settings *settings, ErrorLogger *errorLogger); @@ -1100,7 +1136,7 @@ public: void validateVariables() const; /** Set valuetype in provided tokenlist */ - static void setValueTypeInTokenList(Token *tokens, bool cpp, const Settings *settings); + void setValueTypeInTokenList(); /** * Calculates sizeof value for given type. @@ -1144,6 +1180,10 @@ private: const Enumerator * findEnumerator(const Token * tok) const; + void setValueType(Token *tok, const ValueType &valuetype); + void setValueType(Token *tok, const Variable &var); + void setValueType(Token *tok, const Enumerator &enumerators); + const Tokenizer *_tokenizer; const Settings *_settings; ErrorLogger *_errorLogger; @@ -1153,40 +1193,9 @@ private: /** list for missing types */ std::list _blankTypes; -}; -/** Value type */ -class CPPCHECKLIB ValueType { -public: - enum Sign {UNKNOWN_SIGN, SIGNED, UNSIGNED} sign; - enum Type {UNKNOWN_TYPE, NONSTD, RECORD, CONTAINER, ITERATOR, VOID, BOOL, CHAR, SHORT, INT, LONG, LONGLONG, UNKNOWN_INT, FLOAT, DOUBLE, LONGDOUBLE} type; - unsigned int pointer; // 0=>not pointer, 1=>*, 2=>**, 3=>***, etc - unsigned int constness; // bit 0=data, bit 1=*, bit 2=** - const Scope *typeScope; - const Library::Container *container; - std::string originalTypeName; - - ValueType() : sign(UNKNOWN_SIGN), type(UNKNOWN_TYPE), pointer(0U), constness(0U), typeScope(nullptr), container(nullptr) {} - ValueType(const ValueType &vt) : sign(vt.sign), type(vt.type), pointer(vt.pointer), constness(vt.constness), typeScope(vt.typeScope), container(vt.container), originalTypeName(vt.originalTypeName) {} - ValueType(enum Sign s, enum Type t, unsigned int p) : sign(s), type(t), pointer(p), constness(0U), typeScope(nullptr), container(nullptr) {} - ValueType(enum Sign s, enum Type t, unsigned int p, unsigned int c) : sign(s), type(t), pointer(p), constness(c), typeScope(nullptr), container(nullptr) {} - ValueType(enum Sign s, enum Type t, unsigned int p, unsigned int c, const std::string &otn) : sign(s), type(t), pointer(p), constness(c), typeScope(nullptr), container(nullptr), originalTypeName(otn) {} - - static ValueType parseDecl(const Token *type, const Settings *settings); - - static Type typeFromString(const std::string &typestr, bool longType); - - bool isIntegral() const { - return (type >= ValueType::Type::BOOL && type <= ValueType::Type::UNKNOWN_INT); - } - - bool isFloat() const { - return (type == ValueType::Type::FLOAT || type == ValueType::Type::DOUBLE); - } - - bool fromLibraryType(const std::string &typestr, const Settings *settings); - - std::string str() const; + bool cpp; + ValueType::Sign defaultSignedness; }; diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 8358c9da9..62bd6781c 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -1737,7 +1737,7 @@ bool Tokenizer::simplifyTokens1(const std::string &configuration) } } - SymbolDatabase::setValueTypeInTokenList(list.front(), isCPP(), _settings); + _symbolDatabase->setValueTypeInTokenList(); ValueFlow::setValues(&list, _symbolDatabase, _errorLogger, _settings); printDebugOutput(1); @@ -3791,7 +3791,7 @@ bool Tokenizer::simplifyTokenList2() // Create symbol database and then remove const keywords createSymbolDatabase(); - SymbolDatabase::setValueTypeInTokenList(list.front(), isCPP(), _settings); + _symbolDatabase->setValueTypeInTokenList(); ValueFlow::setValues(&list, _symbolDatabase, _errorLogger, _settings); From fda1f02dabb2a443fb6b614f0f1095a2d4730e54 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Wed, 22 Mar 2017 19:11:40 -0400 Subject: [PATCH 2/3] long double is a floating point type. --- lib/symboldatabase.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/symboldatabase.h b/lib/symboldatabase.h index c4771752e..da471c3ab 100644 --- a/lib/symboldatabase.h +++ b/lib/symboldatabase.h @@ -1052,7 +1052,7 @@ public: } bool isFloat() const { - return (type == ValueType::Type::FLOAT || type == ValueType::Type::DOUBLE); + return (type >= ValueType::Type::FLOAT && type <= ValueType::Type::LONGDOUBLE); } bool fromLibraryType(const std::string &typestr, const Settings *settings); From 662bc6f846e4e5535b1f5b1756db8639e1d367f0 Mon Sep 17 00:00:00 2001 From: Robert Reif Date: Wed, 22 Mar 2017 22:09:40 -0400 Subject: [PATCH 3/3] Add variable or type information to auto and auto variable tokens. Changing the auto variable type requires rerunning the variable pointer pass to correct the symbol database for the new type. --- lib/symboldatabase.cpp | 22 ++++++- test/testsymboldatabase.cpp | 119 +++++++++++++++++++++++++++++++++++- test/testvarid.cpp | 2 +- 3 files changed, 136 insertions(+), 7 deletions(-) diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index 308176f70..b763c0fb9 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -1237,8 +1237,10 @@ void SymbolDatabase::createSymbolDatabaseSetVariablePointers() const Variable *var = tok->variable(); if (var && var->typeScope()) { const Variable *membervar = var->typeScope()->getVariable(membertok->str()); - if (membervar) + if (membervar) { membertok->variable(membervar); + const_cast(membertok)->varId(membervar->nameToken()->varId()); + } } } } @@ -4493,13 +4495,24 @@ void SymbolDatabase::setValueType(Token *tok, const ValueType &valuetype) else if (Token::Match(var1Tok->tokAt(-3), "[;{}] auto *")) autoTok = var1Tok->tokAt(-2); if (autoTok) { - setValueType(autoTok, *vt2); + ValueType vt(*vt2); + if (autoTok->strAt(1) == "*" && vt.pointer) + vt.pointer--; + if (autoTok->strAt(-1) == "const") + vt.constness |= 1; + setValueType(autoTok, vt); setAutoTokenProperties(autoTok); setValueType(var1Tok, *vt2); setValueType(parent->previous(), *vt2); const Variable *var = parent->previous()->variable(); - if (var) + if (var) { const_cast(var)->setFlags(*vt2); + if (vt2->typeScope && vt2->typeScope->definedType) { + const_cast(var)->type(vt2->typeScope->definedType); + if (autoTok->valueType()->pointer == 0) + autoTok->type(vt2->typeScope->definedType); + } + } } } return; @@ -4957,6 +4970,9 @@ void SymbolDatabase::setValueTypeInTokenList() setValueType(tok, vt); } } + + // Update auto variables with new type information. + createSymbolDatabaseSetVariablePointers(); } ValueType ValueType::parseDecl(const Token *type, const Settings *settings) diff --git a/test/testsymboldatabase.cpp b/test/testsymboldatabase.cpp index eba49feb3..47c6c624d 100644 --- a/test/testsymboldatabase.cpp +++ b/test/testsymboldatabase.cpp @@ -320,6 +320,8 @@ private: TEST_CASE(noReturnType); TEST_CASE(auto1); + TEST_CASE(auto2); + TEST_CASE(auto3); } void array() { @@ -812,7 +814,7 @@ private: tok = tok ? tok->next() : nullptr; ASSERT(db != nullptr); ASSERT(tok && tok->variable() && Token::simpleMatch(tok->variable()->typeStartToken(), "int x ;")); - ASSERT(tok && tok->varId() == 0U); // It's possible to set a varId + ASSERT(tok && tok->varId() == 1U); // It's possible to set a varId } void arrayMemberVar2() { @@ -828,7 +830,7 @@ private: tok = tok ? tok->next() : nullptr; ASSERT(db != nullptr); ASSERT(tok && tok->variable() && Token::simpleMatch(tok->variable()->typeStartToken(), "int x ;")); - ASSERT(tok && tok->varId() == 0U); // It's possible to set a varId + ASSERT(tok && tok->varId() == 1U); // It's possible to set a varId } void arrayMemberVar3() { @@ -844,7 +846,7 @@ private: tok = tok ? tok->next() : nullptr; ASSERT(db != nullptr); ASSERT(tok && tok->variable() && Token::simpleMatch(tok->variable()->typeStartToken(), "int x ;")); - ASSERT(tok && tok->varId() == 0U); // It's possible to set a varId + ASSERT(tok && tok->varId() == 1U); // It's possible to set a varId } void staticMemberVar() { @@ -4501,6 +4503,117 @@ private: const Variable *var = db ? db->getVariableFromVarId(1) : nullptr; ASSERT(var && var->isPointer() && var->isConst()); } + + void auto2() { + GET_SYMBOL_DB("struct S { int i; };\n" + "int foo() {\n" + " auto a = new S;\n" + " auto * b = new S;\n" + " auto c = new S[10];\n" + " auto * d = new S[10];\n" + " return a->i + b->i + c[0]->i + d[0]->i;\n" + "}"); + const Token *autotok = Token::findsimplematch(tokenizer.tokens(), "auto"); + ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 1 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S" && autotok->type() == nullptr); + + autotok = Token::findsimplematch(autotok->next(), "auto"); + ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S" && autotok->type() && autotok->type()->name() == "S"); + + autotok = Token::findsimplematch(autotok->next(), "auto"); + ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 1 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S" && autotok->type() == nullptr); + + autotok = Token::findsimplematch(autotok->next(), "auto"); + ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "S" && autotok->type() && autotok->type()->name() == "S"); + + vartok = Token::findsimplematch(tokenizer.tokens(), "a ="); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S"); + + vartok = Token::findsimplematch(vartok->next(), "b ="); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S"); + + vartok = Token::findsimplematch(vartok->next(), "c ="); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S"); + + vartok = Token::findsimplematch(vartok->next(), "d ="); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S"); + + vartok = Token::findsimplematch(tokenizer.tokens(), "return"); + + vartok = Token::findsimplematch(vartok, "a"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S"); + + vartok = Token::findsimplematch(vartok->next(), "b"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S"); + + vartok = Token::findsimplematch(vartok->next(), "c"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S"); + + vartok = Token::findsimplematch(vartok->next(), "d"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "S"); + + vartok = Token::findsimplematch(tokenizer.tokens(), "return"); + + vartok = Token::findsimplematch(vartok, "i"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int"); + + vartok = Token::findsimplematch(vartok->next(), "i"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int"); + + vartok = Token::findsimplematch(vartok->next(), "i"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int"); + + vartok = Token::findsimplematch(vartok->next(), "i"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->typeStartToken()->str() == "int"); + } + + void auto3() { + GET_SYMBOL_DB("enum class E : unsigned short { A, B, C };\n" + "int foo() {\n" + " auto a = new E;\n" + " auto * b = new E;\n" + " auto c = new E[10];\n" + " auto * d = new E[10];\n" + " return a + b + c + d;\n" + "}"); + const Token *autotok = Token::findsimplematch(tokenizer.tokens(), "auto"); + ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 1 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "E" && autotok->type() == nullptr); + + autotok = Token::findsimplematch(autotok->next(), "auto"); + ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "E" && autotok->type() && autotok->type()->name() == "E"); + + autotok = Token::findsimplematch(autotok->next(), "auto"); + ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 1 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "E" && autotok->type() == nullptr); + + autotok = Token::findsimplematch(autotok->next(), "auto"); + ASSERT(db && autotok && autotok->valueType() && autotok->valueType()->pointer == 0 && autotok->valueType()->typeScope && autotok->valueType()->typeScope->definedType && autotok->valueType()->typeScope->definedType->name() == "E" && autotok->type() && autotok->type()->name() == "E"); + + vartok = Token::findsimplematch(tokenizer.tokens(), "a ="); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E"); + + vartok = Token::findsimplematch(vartok->next(), "b ="); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E"); + + vartok = Token::findsimplematch(vartok->next(), "c ="); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E"); + + vartok = Token::findsimplematch(vartok->next(), "d ="); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E"); + + vartok = Token::findsimplematch(tokenizer.tokens(), "return"); + + vartok = Token::findsimplematch(vartok, "a"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E"); + + vartok = Token::findsimplematch(vartok->next(), "b"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E"); + + vartok = Token::findsimplematch(vartok->next(), "c"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E"); + + vartok = Token::findsimplematch(vartok->next(), "d"); + ASSERT(db && vartok && vartok->variable() && vartok->variable()->isPointer() && vartok->variable()->type() && vartok->variable()->type()->name() == "E"); + } + }; REGISTER_TEST(TestSymbolDatabase) diff --git a/test/testvarid.cpp b/test/testvarid.cpp index bfc000227..b59ac326a 100644 --- a/test/testvarid.cpp +++ b/test/testvarid.cpp @@ -1344,7 +1344,7 @@ private: "10:\n" "11: void Bar :: f ( )\n" "12: {\n" - "13: foo@2 . x@4 = x@3 ;\n" + "13: foo@2 . x@1 = x@3 ;\n" "14: }\n"; ASSERT_EQUALS(expected, actual); }