Merge pull request #880 from IOBYTE/master
Update symbol database with new auto type and variable information for assignment to auto.
This commit is contained in:
commit
c280bcedb4
|
@ -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();
|
||||
|
@ -1228,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<Token *>(membertok)->varId(membervar->nameToken()->varId());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -4409,18 +4420,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 +4438,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 +4451,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 +4466,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<Token *>(tok->astParent());
|
||||
|
@ -4470,13 +4480,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,13 +4495,24 @@ 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);
|
||||
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, 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)
|
||||
if (var) {
|
||||
const_cast<Variable *>(var)->setFlags(*vt2);
|
||||
if (vt2->typeScope && vt2->typeScope->definedType) {
|
||||
const_cast<Variable *>(var)->type(vt2->typeScope->definedType);
|
||||
if (autoTok->valueType()->pointer == 0)
|
||||
autoTok->type(vt2->typeScope->definedType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
|
@ -4500,25 +4521,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 +4559,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 +4576,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<Variable *>(parent->previous()->variable())->setFlags(vt);
|
||||
} else if (vt2->container) {
|
||||
// TODO: Determine exact type of RHS
|
||||
|
@ -4573,10 +4594,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 +4614,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 +4674,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 +4799,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 *>(_tokenizer)->list.front();
|
||||
|
||||
for (Token *tok = tokens; tok; tok = tok->next())
|
||||
tok->setValueType(nullptr);
|
||||
|
@ -4800,17 +4815,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 +4842,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 +4918,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 +4957,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,11 +4965,14 @@ 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);
|
||||
}
|
||||
}
|
||||
|
||||
// Update auto variables with new type information.
|
||||
createSymbolDatabaseSetVariablePointers();
|
||||
}
|
||||
|
||||
ValueType ValueType::parseDecl(const Token *type, const Settings *settings)
|
||||
|
|
|
@ -1025,6 +1025,42 @@ private:
|
|||
void findFunctionInBase(const std::string & name, size_t args, std::vector<const Function *> & 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::LONGDOUBLE);
|
||||
}
|
||||
|
||||
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<Type> _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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue