diff --git a/lib/checkbool.cpp b/lib/checkbool.cpp index 0cb3be50e..0cf94af8a 100644 --- a/lib/checkbool.cpp +++ b/lib/checkbool.cpp @@ -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() { diff --git a/lib/checkcondition.cpp b/lib/checkcondition.cpp index b9d0c8290..82e509847 100644 --- a/lib/checkcondition.cpp +++ b/lib/checkcondition.cpp @@ -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)); diff --git a/lib/checkfunctions.cpp b/lib/checkfunctions.cpp index 2a367bd0a..5c71be024 100644 --- a/lib/checkfunctions.cpp +++ b/lib/checkfunctions.cpp @@ -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); diff --git a/lib/checkio.cpp b/lib/checkio.cpp index 8e1d76360..fce1566d7 100644 --- a/lib/checkio.cpp +++ b/lib/checkio.cpp @@ -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")) { diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 45bf575a0..6bd324d50 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -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); } } diff --git a/lib/symboldatabase.cpp b/lib/symboldatabase.cpp index a8528d820..a1e335cf9 100644 --- a/lib/symboldatabase.cpp +++ b/lib/symboldatabase.cpp @@ -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 c_keywords = make_container< std::set >() << - "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; diff --git a/lib/token.cpp b/lib/token.cpp index f65044a57..f56e03f81 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -113,10 +113,20 @@ void Token::update_property_info() update_property_isStandardType(); } -namespace { - const std::set stdTypes = make_container >() << - "bool" << "char" << "char16_t" << "char32_t" << "double" << "float" << "int" << "long" << "short" << "size_t" << "void" << "wchar_t"; -} +static const std::set stdTypes = + make_container >() << "bool" + << "_Bool" + << "char" + << "char16_t" + << "char32_t" + << "double" + << "float" + << "int" + << "long" + << "short" + << "size_t" + << "void" + << "wchar_t"; void Token::update_property_isStandardType() { diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index bc7c18345..aac52f73f 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -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; diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index 6873c1129..af19714fa 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -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) { diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index f1d8a7aa4..d0ed48c08 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -1981,7 +1981,7 @@ static void valueFlowAfterAssign(TokenList *tokenlist, SymbolDatabase* symboldat std::list 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::iterator it; for (it = values.begin(); it != values.end(); ++it) { if (it->isIntValue()) diff --git a/test/cfg/std.cpp b/test/cfg/std.cpp index 6eb7bb8e2..3f29a78f1 100644 --- a/test/cfg/std.cpp +++ b/test/cfg/std.cpp @@ -3223,7 +3223,8 @@ void stdalgorithm(const std::list &ints1, const std::list &ints2) } -void getline() { +void getline() +{ // #837 std::ifstream in("test1.txt"); diff --git a/test/testtokenize.cpp b/test/testtokenize.cpp index fd5117267..c732708dd 100644 --- a/test/testtokenize.cpp +++ b/test/testtokenize.cpp @@ -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;")); }