Don't simplify _Bool in TokenList

This commit is contained in:
Daniel Marjamäki 2017-03-04 11:13:28 +01:00
parent a8424bcb54
commit ecc59859e1
12 changed files with 53 additions and 52 deletions

View File

@ -34,7 +34,15 @@ static const CWE CWE571(571U); // Expression is Always True
static const CWE CWE587(587U); // Assignment of a Fixed Address to a Pointer
static const CWE CWE704(704U); // Incorrect Type Conversion or Cast
//---------------------------------------------------------------------------
static bool isBool(const Variable* var)
{
return (var && Token::Match(var->typeEndToken(), "bool|_Bool"));
}
static bool isNonBoolStdType(const Variable* var)
{
return (var && var->typeEndToken()->isStandardType() && !Token::Match(var->typeEndToken(), "bool|_Bool"));
}
//---------------------------------------------------------------------------
void CheckBool::checkIncrementBoolean()
{
@ -48,7 +56,7 @@ void CheckBool::checkIncrementBoolean()
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "%var% ++")) {
const Variable *var = tok->variable();
if (var && var->typeEndToken()->str() == "bool")
if (isBool(var))
incrementBooleanError(tok);
}
}
@ -88,13 +96,13 @@ void CheckBool::checkBitwiseOnBoolean()
for (const Token* tok = scope->classStart->next(); tok != scope->classEnd; tok = tok->next()) {
if (Token::Match(tok, "(|.|return|&&|%oror%|throw|, %var% [&|]")) {
const Variable *var = tok->next()->variable();
if (var && var->typeEndToken()->str() == "bool") {
if (isBool(var)) {
bitwiseOnBooleanError(tok->next(), var->name(), tok->strAt(2) == "&" ? "&&" : "||");
tok = tok->tokAt(2);
}
} else if (Token::Match(tok, "[&|] %var% )|.|return|&&|%oror%|throw|,") && (!tok->previous() || !tok->previous()->isExtendedOp() || tok->strAt(-1) == ")" || tok->strAt(-1) == "]")) {
const Variable *var = tok->next()->variable();
if (var && var->typeEndToken()->str() == "bool") {
if (isBool(var)) {
bitwiseOnBooleanError(tok->next(), var->name(), tok->str() == "&" ? "&&" : "||");
tok = tok->tokAt(2);
}
@ -115,14 +123,6 @@ void CheckBool::bitwiseOnBooleanError(const Token *tok, const std::string &varna
// if (!x==3) <- Probably meant to be "x!=3"
//---------------------------------------------------------------------------
static bool isBool(const Variable* var)
{
return (var && var->typeEndToken()->str() == "bool");
}
static bool isNonBoolStdType(const Variable* var)
{
return (var && var->typeEndToken()->isStandardType() && var->typeEndToken()->str() != "bool");
}
void CheckBool::checkComparisonOfBoolWithInt()
{
if (!_settings->isEnabled("warning") || !_tokenizer->isCPP())
@ -167,7 +167,7 @@ static bool tokenIsFunctionReturningBool(const Token* tok)
{
const Function* func = tok->function();
if (func && Token::Match(tok, "%name% (")) {
if (func->tokenDef && func->tokenDef->strAt(-1) == "bool") {
if (func->tokenDef && Token::Match(func->tokenDef->previous(), "bool|_Bool")) {
return true;
}
}
@ -288,7 +288,6 @@ void CheckBool::comparisonOfBoolWithBoolError(const Token *tok, const std::strin
" operator could cause unexpected results.", CWE398, false);
}
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
void CheckBool::checkAssignBoolToPointer()
{

View File

@ -241,7 +241,7 @@ static bool inBooleanFunction(const Token *tok)
const Token *ret = func->retDef;
while (Token::Match(ret, "static|const"))
ret = ret->next();
return ret && (ret->str() == "bool");
return Token::Match(ret, "bool|_Bool");
}
}
return false;
@ -257,7 +257,7 @@ void CheckCondition::checkBadBitmaskCheck()
const Token* parent = tok->astParent();
const bool isBoolean = Token::Match(parent, "&&|%oror%") ||
(parent->str() == "?" && parent->astOperand1() == tok) ||
(parent->str() == "=" && parent->astOperand2() == tok && parent->astOperand1() && parent->astOperand1()->variable() && parent->astOperand1()->variable()->typeStartToken()->str() == "bool") ||
(parent->str() == "=" && parent->astOperand2() == tok && parent->astOperand1() && parent->astOperand1()->variable() && Token::Match(parent->astOperand1()->variable()->typeStartToken(), "bool|_Bool")) ||
(parent->str() == "(" && Token::Match(parent->astOperand1(), "if|while")) ||
(parent->str() == "return" && parent->astOperand1() == tok && inBooleanFunction(tok));

View File

@ -105,7 +105,7 @@ void CheckFunctions::invalidFunctionUsage()
while (Token::Match(var, ".|::"))
var = var->astOperand2();
if (Token::Match(top, "%comp%|%oror%|&&|!|true|false") ||
(var && var->variable() && Token::simpleMatch(var->variable()->typeStartToken(), "bool"))) {
(var && var->variable() && Token::Match(var->variable()->typeStartToken(), "bool|_Bool"))) {
if (_settings->library.isboolargbad(functionToken, argnr))
invalidFunctionArgBoolError(top, functionToken->str(), argnr);

View File

@ -1197,7 +1197,7 @@ void CheckIO::checkFormatString(const Token * const tok,
if (argInfo.isArrayOrPointer() && !argInfo.element) {
// use %p on pointers and arrays
invalidPrintfArgTypeError_uint(tok, numFormat, specifier, &argInfo);
} else if (!argInfo.typeToken->isUnsigned() && argInfo.typeToken->str() != "bool") {
} else if (!argInfo.typeToken->isUnsigned() && !Token::Match(argInfo.typeToken, "bool|_Bool")) {
if (!(!argInfo.isArrayOrPointer() && argInfo.element))
invalidPrintfArgTypeError_uint(tok, numFormat, specifier, &argInfo);
} else if (!Token::Match(argInfo.typeToken, "bool|char|short|long|int")) {

View File

@ -2384,7 +2384,7 @@ void CheckOther::checkIncompleteArrayFill()
if ((size != 1 && size != 100 && size != 0) || var->isPointer()) {
if (printWarning)
incompleteArrayFillError(tok, var->name(), tok->str(), false);
} else if (var->typeStartToken()->str() == "bool" && printPortability) // sizeof(bool) is not 1 on all platforms
} else if (Token::Match(var->typeStartToken(), "bool|_Bool") && printPortability) // sizeof(bool) is not 1 on all platforms
incompleteArrayFillError(tok, var->name(), tok->str(), true);
}
}

View File

@ -3953,7 +3953,7 @@ const Function* Scope::findFunction(const Token *tok, bool requireConst) const
// check for a match with a boolean literal
else if (!funcarg->isArrayOrPointer() && Token::Match(arguments[j], "%bool% ,|)")) {
if (funcarg->typeStartToken()->str() == "bool")
if (Token::Match(funcarg->typeStartToken(), "bool|_Bool"))
same++;
else if (Token::Match(funcarg->typeStartToken(), "wchar_t|char|short|int|long"))
fallback1++;
@ -4341,7 +4341,7 @@ Function * SymbolDatabase::findFunctionInScope(const Token *func, const Scope *n
namespace {
const std::set<std::string> c_keywords = make_container< std::set<std::string> >() <<
"auto" << "break" << "case" << "char" << "const" << "continue" << "default" << "do" <<
"_Bool" << "auto" << "break" << "case" << "char" << "const" << "continue" << "default" << "do" <<
"double" << "else" << "enum" << "extern" << "float" << "for" << "goto" << "if" << "inline" <<
"int" << "long" << "register" << "restrict" << "return" << "short" << "signed" << "sizeof" <<
"static" << "struct" << "switch" << "typedef" << "union" << "unsigned" << "void" << "volatile" <<
@ -4403,23 +4403,19 @@ static void setValueType(Token *tok, const Enumerator &enumerator, bool cpp, Val
valuetype.typeScope = enumerator.scope;
const Token * type = enumerator.scope->enumType;
if (type) {
if (type->isSigned())
valuetype.sign = ValueType::Sign::SIGNED;
else if (type->isUnsigned())
valuetype.sign = ValueType::Sign::UNSIGNED;
else
valuetype.sign = defaultSignedness;
if (type->str() == "char")
valuetype.type = ValueType::Type::CHAR;
else if (type->str() == "short")
valuetype.type = ValueType::Type::SHORT;
else if (type->str() == "int")
valuetype.type = ValueType::Type::INT;
else if (type->str() == "long")
valuetype.type = type->isLong() ? ValueType::Type::LONGLONG : ValueType::Type::LONG;
else if (type->isStandardType()) {
valuetype.type = ValueType::typeFromString(type->str(), type->isLong());
if (valuetype.type == ValueType::Type::UNKNOWN_TYPE && type->isStandardType())
valuetype.fromLibraryType(type->str(), settings);
if (valuetype.isIntegral()) {
if (type->isSigned())
valuetype.sign = ValueType::Sign::SIGNED;
else if (type->isUnsigned())
valuetype.sign = ValueType::Sign::UNSIGNED;
else if (valuetype.type == ValueType::Type::CHAR)
valuetype.sign = defaultSignedness;
else
valuetype.sign = ValueType::Sign::SIGNED;
}
setValueType(tok, valuetype, cpp, defaultSignedness, settings);
@ -4636,7 +4632,8 @@ static const Token * parsedecl(const Token *type, ValueType * const valuetype, V
valuetype->sign = ValueType::Sign::UNSIGNED;
else
valuetype->sign = defaultSignedness;
if (ValueType::Type t = ValueType::typeFromString(enum_type->str(), enum_type->isLong()))
ValueType::Type t = ValueType::typeFromString(enum_type->str(), enum_type->isLong());
if (t != ValueType::Type::UNKNOWN_TYPE)
valuetype->type = t;
else if (enum_type->isStandardType())
valuetype->fromLibraryType(enum_type->str(), settings);
@ -4878,7 +4875,7 @@ ValueType::Type ValueType::typeFromString(const std::string &typestr, bool longT
{
if (typestr == "void")
return ValueType::Type::VOID;
if (typestr == "bool")
if (typestr == "bool" || typestr == "_Bool")
return ValueType::Type::BOOL;
if (typestr== "char")
return ValueType::Type::CHAR;

View File

@ -113,10 +113,20 @@ void Token::update_property_info()
update_property_isStandardType();
}
namespace {
const std::set<std::string> stdTypes = make_container<std::set<std::string> >() <<
"bool" << "char" << "char16_t" << "char32_t" << "double" << "float" << "int" << "long" << "short" << "size_t" << "void" << "wchar_t";
}
static const std::set<std::string> stdTypes =
make_container<std::set<std::string> >() << "bool"
<< "_Bool"
<< "char"
<< "char16_t"
<< "char32_t"
<< "double"
<< "float"
<< "int"
<< "long"
<< "short"
<< "size_t"
<< "void"
<< "wchar_t";
void Token::update_property_isStandardType()
{

View File

@ -1781,6 +1781,7 @@ void Tokenizer::fillTypeSizes()
_typeSize["char"] = 1;
_typeSize["char16_t"] = 2;
_typeSize["char32_t"] = 4;
_typeSize["_Bool"] = _settings->sizeof_bool;
_typeSize["bool"] = _settings->sizeof_bool;
_typeSize["short"] = _settings->sizeof_short;
_typeSize["int"] = _settings->sizeof_int;

View File

@ -136,8 +136,6 @@ void TokenList::addtoken(std::string str, const unsigned int lineno, const unsig
(str[2] >= '8')) // includes A-F and a-f
suffix = "U";
str = MathLib::value(str).str() + suffix;
} else if (str.compare(0, 5, "_Bool") == 0) {
str = "bool";
}
if (_back) {

View File

@ -1981,7 +1981,7 @@ static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldat
std::list<ValueFlow::Value> values = tok->astOperand2()->values;
const bool constValue = tok->astOperand2()->isNumber();
if (tokenlist->isCPP() && Token::simpleMatch(var->typeStartToken(), "bool")) {
if (tokenlist->isCPP() && Token::Match(var->typeStartToken(), "bool|_Bool")) {
std::list<ValueFlow::Value>::iterator it;
for (it = values.begin(); it != values.end(); ++it) {
if (it->isIntValue())

View File

@ -3223,7 +3223,8 @@ void stdalgorithm(const std::list<int> &ints1, const std::list<int> &ints2)
}
void getline() {
void getline()
{
// #837
std::ifstream in("test1.txt");

View File

@ -55,7 +55,6 @@ private:
TEST_CASE(tokenize17); // #2759
TEST_CASE(tokenize18); // tokenize "(X&&Y)" into "( X && Y )" instead of "( X & & Y )"
TEST_CASE(tokenize19); // #3006 (segmentation fault)
TEST_CASE(tokenize20); // replace C99 _Bool => bool
TEST_CASE(tokenize21); // tokenize 0x0E-7
TEST_CASE(tokenize22); // special marker $ from preprocessor
TEST_CASE(tokenize25); // #4239 (segmentation fault)
@ -713,10 +712,6 @@ private:
"};"));
}
void tokenize20() { // replace C99 _Bool => bool
ASSERT_EQUALS("bool a ; a = true ;", tokenizeAndStringify("_Bool a = true;"));
}
void tokenize21() { // tokenize 0x0E-7
ASSERT_EQUALS("14 - 7 ;", tokenizeAndStringify("0x0E-7;"));
}