Fixed #7646 (podtypes do not get proper valuetype)

This commit is contained in:
Daniel Marjamäki 2016-07-31 19:47:34 +02:00
parent 8d89eefff9
commit 09b6568ea2
6 changed files with 141 additions and 60 deletions

View File

@ -44,6 +44,8 @@ namespace tinyxml2 {
* @brief Library definitions handling
*/
class CPPCHECKLIB Library {
friend class TestSymbolDatabase; // For testing only
public:
Library();

View File

@ -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.

View File

@ -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<Token *>(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;

View File

@ -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;
};

View File

@ -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);

View File

@ -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);
}
}
};