Fixed #7260 (ValueType: in C++ the result of 'sint >> unknowntype' has unknown type)
This commit is contained in:
parent
88a525aca7
commit
a014920280
|
@ -3607,18 +3607,18 @@ bool SymbolDatabase::isReservedName(const std::string& iName) const
|
||||||
}
|
}
|
||||||
|
|
||||||
static const Token * parsedecl(const Token *type, ValueType * const valuetype, ValueType::Sign defaultSignedness);
|
static const Token * parsedecl(const Token *type, ValueType * const valuetype, ValueType::Sign defaultSignedness);
|
||||||
static void setValueType(Token *tok, const ValueType &valuetype, ValueType::Sign defaultSignedness);
|
static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, ValueType::Sign defaultSignedness);
|
||||||
|
|
||||||
static void setValueType(Token *tok, const Variable &var, ValueType::Sign defaultSignedness)
|
static void setValueType(Token *tok, const Variable &var, bool cpp, ValueType::Sign defaultSignedness)
|
||||||
{
|
{
|
||||||
ValueType valuetype;
|
ValueType valuetype;
|
||||||
valuetype.pointer = var.dimensions().size();
|
valuetype.pointer = var.dimensions().size();
|
||||||
valuetype.typeScope = var.typeScope();
|
valuetype.typeScope = var.typeScope();
|
||||||
if (parsedecl(var.typeStartToken(), &valuetype, defaultSignedness))
|
if (parsedecl(var.typeStartToken(), &valuetype, defaultSignedness))
|
||||||
setValueType(tok, valuetype, defaultSignedness);
|
setValueType(tok, valuetype, cpp, defaultSignedness);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setValueType(Token *tok, const ValueType &valuetype, ValueType::Sign defaultSignedness)
|
static void setValueType(Token *tok, const ValueType &valuetype, bool cpp, ValueType::Sign defaultSignedness)
|
||||||
{
|
{
|
||||||
tok->setValueType(new ValueType(valuetype));
|
tok->setValueType(new ValueType(valuetype));
|
||||||
Token *parent = const_cast<Token *>(tok->astParent());
|
Token *parent = const_cast<Token *>(tok->astParent());
|
||||||
|
@ -3628,7 +3628,8 @@ static void setValueType(Token *tok, const ValueType &valuetype, ValueType::Sign
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (Token::Match(parent, "<<|>>")) {
|
if (Token::Match(parent, "<<|>>")) {
|
||||||
setValueType(parent,valuetype, defaultSignedness);
|
if (!cpp || (parent->astOperand2() && parent->astOperand2()->valueType() && parent->astOperand2()->valueType()->isIntegral()))
|
||||||
|
setValueType(parent, *parent->astOperand1()->valueType(), cpp, defaultSignedness);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3636,20 +3637,20 @@ static void setValueType(Token *tok, const ValueType &valuetype, ValueType::Sign
|
||||||
ValueType vt(valuetype);
|
ValueType vt(valuetype);
|
||||||
vt.pointer -= 1U;
|
vt.pointer -= 1U;
|
||||||
vt.constness >>= 1;
|
vt.constness >>= 1;
|
||||||
setValueType(parent, vt, defaultSignedness);
|
setValueType(parent, vt, cpp, defaultSignedness);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (parent->str() == "*" && !parent->astOperand2() && valuetype.pointer > 0U) {
|
if (parent->str() == "*" && !parent->astOperand2() && valuetype.pointer > 0U) {
|
||||||
ValueType vt(valuetype);
|
ValueType vt(valuetype);
|
||||||
vt.pointer -= 1U;
|
vt.pointer -= 1U;
|
||||||
vt.constness >>= 1;
|
vt.constness >>= 1;
|
||||||
setValueType(parent, vt, defaultSignedness);
|
setValueType(parent, vt, cpp, defaultSignedness);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (parent->str() == "&" && !parent->astOperand2()) {
|
if (parent->str() == "&" && !parent->astOperand2()) {
|
||||||
ValueType vt(valuetype);
|
ValueType vt(valuetype);
|
||||||
vt.pointer += 1U;
|
vt.pointer += 1U;
|
||||||
setValueType(parent, vt, defaultSignedness);
|
setValueType(parent, vt, cpp, defaultSignedness);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3663,7 +3664,7 @@ static void setValueType(Token *tok, const ValueType &valuetype, ValueType::Sign
|
||||||
for (std::list<Variable>::const_iterator it = typeScope->varlist.begin(); it != typeScope->varlist.end(); ++it) {
|
for (std::list<Variable>::const_iterator it = typeScope->varlist.begin(); it != typeScope->varlist.end(); ++it) {
|
||||||
const Variable &var = *it;
|
const Variable &var = *it;
|
||||||
if (var.nameToken()->str() == name) {
|
if (var.nameToken()->str() == name) {
|
||||||
setValueType(parent, var, defaultSignedness);
|
setValueType(parent, var, cpp, defaultSignedness);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3675,30 +3676,30 @@ static void setValueType(Token *tok, const ValueType &valuetype, ValueType::Sign
|
||||||
const ValueType *vt2 = parent->astOperand2() ? parent->astOperand2()->valueType() : nullptr;
|
const ValueType *vt2 = parent->astOperand2() ? parent->astOperand2()->valueType() : nullptr;
|
||||||
if (parent->isArithmeticalOp() && vt2) {
|
if (parent->isArithmeticalOp() && vt2) {
|
||||||
if (vt1->pointer != 0U && vt2->pointer == 0U) {
|
if (vt1->pointer != 0U && vt2->pointer == 0U) {
|
||||||
setValueType(parent, *vt1, defaultSignedness);
|
setValueType(parent, *vt1, cpp, defaultSignedness);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vt1->pointer == 0U && vt2->pointer != 0U) {
|
if (vt1->pointer == 0U && vt2->pointer != 0U) {
|
||||||
setValueType(parent, *vt2, defaultSignedness);
|
setValueType(parent, *vt2, cpp, defaultSignedness);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vt1->pointer != 0U) { // result is pointer diff
|
if (vt1->pointer != 0U) { // result is pointer diff
|
||||||
setValueType(parent, ValueType(ValueType::Sign::UNSIGNED, ValueType::Type::INT, 0U, 0U, "ptrdiff_t"), defaultSignedness);
|
setValueType(parent, ValueType(ValueType::Sign::UNSIGNED, ValueType::Type::INT, 0U, 0U, "ptrdiff_t"), cpp, defaultSignedness);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (vt1->type == ValueType::Type::LONGDOUBLE || vt2->type == ValueType::Type::LONGDOUBLE) {
|
if (vt1->type == ValueType::Type::LONGDOUBLE || vt2->type == ValueType::Type::LONGDOUBLE) {
|
||||||
setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::LONGDOUBLE, 0U), defaultSignedness);
|
setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::LONGDOUBLE, 0U), cpp, defaultSignedness);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (vt1->type == ValueType::Type::DOUBLE || vt2->type == ValueType::Type::DOUBLE) {
|
if (vt1->type == ValueType::Type::DOUBLE || vt2->type == ValueType::Type::DOUBLE) {
|
||||||
setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::DOUBLE, 0U), defaultSignedness);
|
setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::DOUBLE, 0U), cpp, defaultSignedness);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (vt1->type == ValueType::Type::FLOAT || vt2->type == ValueType::Type::FLOAT) {
|
if (vt1->type == ValueType::Type::FLOAT || vt2->type == ValueType::Type::FLOAT) {
|
||||||
setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::FLOAT, 0U), defaultSignedness);
|
setValueType(parent, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::FLOAT, 0U), cpp, defaultSignedness);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3733,7 +3734,7 @@ static void setValueType(Token *tok, const ValueType &valuetype, ValueType::Sign
|
||||||
vt.originalTypeName.clear();
|
vt.originalTypeName.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
setValueType(parent, vt, defaultSignedness);
|
setValueType(parent, vt, cpp, defaultSignedness);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3788,7 +3789,7 @@ static const Token * parsedecl(const Token *type, ValueType * const valuetype, V
|
||||||
return (type && valuetype->type != ValueType::Type::UNKNOWN_TYPE) ? type : nullptr;
|
return (type && valuetype->type != ValueType::Type::UNKNOWN_TYPE) ? type : nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SymbolDatabase::setValueTypeInTokenList(Token *tokens, char defaultSignedness)
|
void SymbolDatabase::setValueTypeInTokenList(Token *tokens, bool cpp, char defaultSignedness)
|
||||||
{
|
{
|
||||||
ValueType::Sign defsign;
|
ValueType::Sign defsign;
|
||||||
if (defaultSignedness == 's' || defaultSignedness == 'S')
|
if (defaultSignedness == 's' || defaultSignedness == 'S')
|
||||||
|
@ -3808,7 +3809,7 @@ void SymbolDatabase::setValueTypeInTokenList(Token *tokens, char defaultSignedne
|
||||||
const char suffix = tok->str()[tok->str().size() - 1U];
|
const char suffix = tok->str()[tok->str().size() - 1U];
|
||||||
if (suffix == 'f' || suffix == 'F')
|
if (suffix == 'f' || suffix == 'F')
|
||||||
type = ValueType::Type::FLOAT;
|
type = ValueType::Type::FLOAT;
|
||||||
::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, type, 0U), defsign);
|
::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, type, 0U), cpp, defsign);
|
||||||
} else if (MathLib::isInt(tok->str())) {
|
} else if (MathLib::isInt(tok->str())) {
|
||||||
ValueType::Sign sign = ValueType::Sign::SIGNED;
|
ValueType::Sign sign = ValueType::Sign::SIGNED;
|
||||||
ValueType::Type type = ValueType::Type::INT;
|
ValueType::Type type = ValueType::Type::INT;
|
||||||
|
@ -3821,49 +3822,49 @@ void SymbolDatabase::setValueTypeInTokenList(Token *tokens, char defaultSignedne
|
||||||
if (suffix == 'l' || suffix == 'L')
|
if (suffix == 'l' || suffix == 'L')
|
||||||
type = (type == ValueType::Type::INT) ? ValueType::Type::LONG : ValueType::Type::LONGLONG;
|
type = (type == ValueType::Type::INT) ? ValueType::Type::LONG : ValueType::Type::LONGLONG;
|
||||||
}
|
}
|
||||||
::setValueType(tok, ValueType(sign, type, 0U), defsign);
|
::setValueType(tok, ValueType(sign, type, 0U), cpp, defsign);
|
||||||
}
|
}
|
||||||
} else if (tok->isComparisonOp())
|
} else if (tok->isComparisonOp())
|
||||||
::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::BOOL, 0U), defsign);
|
::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::BOOL, 0U), cpp, defsign);
|
||||||
else if (tok->tokType() == Token::eChar)
|
else if (tok->tokType() == Token::eChar)
|
||||||
::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::CHAR, 0U), defsign);
|
::setValueType(tok, ValueType(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::CHAR, 0U), cpp, defsign);
|
||||||
else if (tok->tokType() == Token::eString) {
|
else if (tok->tokType() == Token::eString) {
|
||||||
ValueType valuetype(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::CHAR, 1U, 1U);
|
ValueType valuetype(ValueType::Sign::UNKNOWN_SIGN, ValueType::Type::CHAR, 1U, 1U);
|
||||||
if (tok->isLong()) {
|
if (tok->isLong()) {
|
||||||
valuetype.originalTypeName = "wchar_t";
|
valuetype.originalTypeName = "wchar_t";
|
||||||
valuetype.type = ValueType::Type::SHORT;
|
valuetype.type = ValueType::Type::SHORT;
|
||||||
}
|
}
|
||||||
::setValueType(tok, valuetype, defsign);
|
::setValueType(tok, valuetype, cpp, defsign);
|
||||||
} else if (tok->str() == "(") {
|
} else if (tok->str() == "(") {
|
||||||
// cast
|
// cast
|
||||||
if (!tok->astOperand2() && Token::Match(tok, "( %name%")) {
|
if (!tok->astOperand2() && Token::Match(tok, "( %name%")) {
|
||||||
ValueType valuetype;
|
ValueType valuetype;
|
||||||
if (Token::simpleMatch(parsedecl(tok->next(), &valuetype, defsign), ")"))
|
if (Token::simpleMatch(parsedecl(tok->next(), &valuetype, defsign), ")"))
|
||||||
::setValueType(tok, valuetype, defsign);
|
::setValueType(tok, valuetype, cpp, defsign);
|
||||||
}
|
}
|
||||||
|
|
||||||
// C++ cast
|
// C++ cast
|
||||||
if (tok->astOperand2() && Token::Match(tok->astOperand1(), "static_cast|const_cast|dynamic_cast|reinterpret_cast < %name%") && tok->astOperand1()->linkAt(1)) {
|
if (tok->astOperand2() && Token::Match(tok->astOperand1(), "static_cast|const_cast|dynamic_cast|reinterpret_cast < %name%") && tok->astOperand1()->linkAt(1)) {
|
||||||
ValueType valuetype;
|
ValueType valuetype;
|
||||||
if (Token::simpleMatch(parsedecl(tok->astOperand1()->tokAt(2), &valuetype, defsign), ">"))
|
if (Token::simpleMatch(parsedecl(tok->astOperand1()->tokAt(2), &valuetype, defsign), ">"))
|
||||||
::setValueType(tok, valuetype, defsign);
|
::setValueType(tok, valuetype, cpp, defsign);
|
||||||
}
|
}
|
||||||
|
|
||||||
// function
|
// function
|
||||||
else if (tok->previous() && tok->previous()->function() && tok->previous()->function()->retDef) {
|
else if (tok->previous() && tok->previous()->function() && tok->previous()->function()->retDef) {
|
||||||
ValueType valuetype;
|
ValueType valuetype;
|
||||||
if (Token::simpleMatch(parsedecl(tok->previous()->function()->retDef, &valuetype, defsign), "("))
|
if (Token::simpleMatch(parsedecl(tok->previous()->function()->retDef, &valuetype, defsign), "("))
|
||||||
::setValueType(tok, valuetype, defsign);
|
::setValueType(tok, valuetype, cpp, defsign);
|
||||||
}
|
}
|
||||||
|
|
||||||
else if (Token::simpleMatch(tok->previous(), "sizeof (")) {
|
else if (Token::simpleMatch(tok->previous(), "sizeof (")) {
|
||||||
// TODO: use specified size_t type
|
// TODO: use specified size_t type
|
||||||
ValueType valuetype(ValueType::Sign::UNSIGNED, ValueType::Type::LONG, 0U);
|
ValueType valuetype(ValueType::Sign::UNSIGNED, ValueType::Type::LONG, 0U);
|
||||||
valuetype.originalTypeName = "size_t";
|
valuetype.originalTypeName = "size_t";
|
||||||
setValueType(tok, valuetype, defsign);
|
setValueType(tok, valuetype, cpp, defsign);
|
||||||
}
|
}
|
||||||
} else if (tok->variable()) {
|
} else if (tok->variable()) {
|
||||||
setValueType(tok, *tok->variable(), defsign);
|
setValueType(tok, *tok->variable(), cpp, defsign);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1027,7 +1027,7 @@ public:
|
||||||
void validate() const;
|
void validate() const;
|
||||||
|
|
||||||
/** Set valuetype in provided tokenlist */
|
/** Set valuetype in provided tokenlist */
|
||||||
static void setValueTypeInTokenList(Token *tokens, char defaultSignedness);
|
static void setValueTypeInTokenList(Token *tokens, bool cpp, char defaultSignedness);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class Scope;
|
friend class Scope;
|
||||||
|
|
|
@ -1735,7 +1735,7 @@ bool Tokenizer::simplifyTokens1(const std::string &configuration,
|
||||||
list.createAst();
|
list.createAst();
|
||||||
list.validateAst();
|
list.validateAst();
|
||||||
|
|
||||||
SymbolDatabase::setValueTypeInTokenList(list.front(), _settings->defaultSign);
|
SymbolDatabase::setValueTypeInTokenList(list.front(), isCPP(), _settings->defaultSign);
|
||||||
ValueFlow::setValues(&list, _symbolDatabase, _errorLogger, _settings);
|
ValueFlow::setValues(&list, _symbolDatabase, _errorLogger, _settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3077,12 +3077,12 @@ private:
|
||||||
"}");
|
"}");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string typeOf(const char code[], const char str[]) {
|
std::string typeOf(const char code[], const char str[], const char filename[] = "test.cpp") {
|
||||||
Settings s;
|
Settings s;
|
||||||
s.platform(Settings::Unspecified);
|
s.platform(Settings::Unspecified);
|
||||||
Tokenizer tokenizer(&s, this);
|
Tokenizer tokenizer(&s, this);
|
||||||
std::istringstream istr(code);
|
std::istringstream istr(code);
|
||||||
tokenizer.tokenize(istr, "test.cpp");
|
tokenizer.tokenize(istr, filename);
|
||||||
const Token * const tok = Token::findsimplematch(tokenizer.tokens(),str);
|
const Token * const tok = Token::findsimplematch(tokenizer.tokens(),str);
|
||||||
return tok->valueType() ? tok->valueType()->str() : std::string();
|
return tok->valueType() ? tok->valueType()->str() : std::string();
|
||||||
}
|
}
|
||||||
|
@ -3153,6 +3153,10 @@ private:
|
||||||
// shift => result has same type as lhs
|
// shift => result has same type as lhs
|
||||||
ASSERT_EQUALS("int", typeOf("int x; a = x << 1U;", "<<"));
|
ASSERT_EQUALS("int", typeOf("int x; a = x << 1U;", "<<"));
|
||||||
ASSERT_EQUALS("int", typeOf("int x; a = x >> 1U;", ">>"));
|
ASSERT_EQUALS("int", typeOf("int x; a = x >> 1U;", ">>"));
|
||||||
|
ASSERT_EQUALS("", typeOf("a = 12 >> x;", ">>", "test.cpp")); // >> might be overloaded
|
||||||
|
ASSERT_EQUALS("signed int", typeOf("a = 12 >> x;", ">>", "test.c"));
|
||||||
|
ASSERT_EQUALS("", typeOf("a = 12 << x;", "<<", "test.cpp")); // << might be overloaded
|
||||||
|
ASSERT_EQUALS("signed int", typeOf("a = 12 << x;", "<<", "test.c"));
|
||||||
|
|
||||||
// array..
|
// array..
|
||||||
ASSERT_EQUALS("void * *", typeOf("void * x[10]; a = x + 0;", "+"));
|
ASSERT_EQUALS("void * *", typeOf("void * x[10]; a = x + 0;", "+"));
|
||||||
|
|
Loading…
Reference in New Issue