diff --git a/cfg/qt.cfg b/cfg/qt.cfg index 69bc205a316..8c2d34073b0 100644 --- a/cfg/qt.cfg +++ b/cfg/qt.cfg @@ -5236,12 +5236,12 @@ QApplication QMutexLocker - QRectF - QSizeF - QPointF QRect + QRectF QSize + QSizeF QPoint + QPointF QRegion diff --git a/cfg/windows.cfg b/cfg/windows.cfg index f690a83a1aa..05c31803fbc 100644 --- a/cfg/windows.cfg +++ b/cfg/windows.cfg @@ -4907,6 +4907,8 @@ HFONT CreateFont( + + false diff --git a/cfg/wxwidgets.cfg b/cfg/wxwidgets.cfg index dd42c600bd1..a5a3b3242b8 100644 --- a/cfg/wxwidgets.cfg +++ b/cfg/wxwidgets.cfg @@ -5,6 +5,8 @@ wxRect wxSize wxPoint + wxPoint2DInt + wxPoint2DDouble wxRealPoint wxVersionInfo wxRegion diff --git a/cli/cmdlineparser.cpp b/cli/cmdlineparser.cpp index 7f275ab00df..59cf67847fa 100644 --- a/cli/cmdlineparser.cpp +++ b/cli/cmdlineparser.cpp @@ -1071,44 +1071,57 @@ CmdLineParser::Result CmdLineParser::parseFromArgs(int argc, const char* const a // Rule file else if (std::strncmp(argv[i], "--rule-file=", 12) == 0) { #ifdef HAVE_RULES - // TODO: improved error handling - unknown elements, wrong root node, etc. + // TODO: improved error handling - wrong root node, etc. + // TODO: consume unused "version" attribute const std::string ruleFile = argv[i] + 12; tinyxml2::XMLDocument doc; const tinyxml2::XMLError err = doc.LoadFile(ruleFile.c_str()); if (err == tinyxml2::XML_SUCCESS) { const tinyxml2::XMLElement *node = doc.FirstChildElement(); - // TODO: this looks like legacy handling - deprecate it + // check if it is a single or multi rule configuration if (node && strcmp(node->Value(), "rules") == 0) node = node->FirstChildElement("rule"); for (; node && strcmp(node->Value(), "rule") == 0; node = node->NextSiblingElement()) { Settings::Rule rule; - const tinyxml2::XMLElement *tokenlist = node->FirstChildElement("tokenlist"); - if (tokenlist) - rule.tokenlist = tokenlist->GetText(); - - const tinyxml2::XMLElement *pattern = node->FirstChildElement("pattern"); - if (pattern) { - rule.pattern = pattern->GetText(); + for (const tinyxml2::XMLElement *subnode = node->FirstChildElement(); subnode; subnode = subnode->NextSiblingElement()) { + const char * const subtext = subnode->GetText(); + if (std::strcmp(subnode->Name(), "tokenlist") == 0) { + rule.tokenlist = empty_if_null(subtext); + } + else if (std::strcmp(subnode->Name(), "pattern") == 0) { + rule.pattern = empty_if_null(subtext); + } + else if (std::strcmp(subnode->Name(), "message") == 0) { + for (const tinyxml2::XMLElement *msgnode = subnode->FirstChildElement(); msgnode; msgnode = msgnode->NextSiblingElement()) { + const char * const msgtext = msgnode->GetText(); + if (std::strcmp(msgnode->Name(), "severity") == 0) { + rule.severity = severityFromString(empty_if_null(msgtext)); + } + else if (std::strcmp(msgnode->Name(), "id") == 0) { + rule.id = empty_if_null(msgtext); + } + else if (std::strcmp(msgnode->Name(), "summary") == 0) { + rule.summary = empty_if_null(msgtext); + } + else { + mLogger.printError("unable to load rule-file '" + ruleFile + "' - unknown element '" + msgnode->Name() + "' encountered in 'message'."); + return Result::Fail; + } + } + } + else { + mLogger.printError("unable to load rule-file '" + ruleFile + "' - unknown element '" + subnode->Name() + "' encountered in 'rule'."); + return Result::Fail; + } } - const tinyxml2::XMLElement *message = node->FirstChildElement("message"); - if (message) { - const tinyxml2::XMLElement *severity = message->FirstChildElement("severity"); - if (severity) - rule.severity = severityFromString(severity->GetText()); - - const tinyxml2::XMLElement *id = message->FirstChildElement("id"); - if (id) - rule.id = id->GetText(); - - const tinyxml2::XMLElement *summary = message->FirstChildElement("summary"); - if (summary) - rule.summary = summary->GetText() ? summary->GetText() : ""; + if (rule.pattern.empty()) { + mLogger.printError("unable to load rule-file '" + ruleFile + "' - a rule is lacking a pattern."); + return Result::Fail; } - if (!rule.pattern.empty()) - mSettings.rules.emplace_back(std::move(rule)); + mSettings.rules.emplace_back(std::move(rule)); } } else { mLogger.printError("unable to load rule-file '" + ruleFile + "' (" + tinyxml2::XMLDocument::ErrorIDToName(err) + ")."); diff --git a/lib/checkother.cpp b/lib/checkother.cpp index 331cb03be27..beff6996668 100644 --- a/lib/checkother.cpp +++ b/lib/checkother.cpp @@ -944,6 +944,9 @@ void CheckOther::checkVariableScope() if (!var || !var->isLocal() || var->isConst()) continue; + if (var->nameToken()->isExpandedMacro()) + continue; + const bool isPtrOrRef = var->isPointer() || var->isReference(); const bool isSimpleType = var->typeStartToken()->isStandardType() || var->typeStartToken()->isEnumType() || (var->typeStartToken()->isC() && var->type() && var->type()->isStructType()); if (!isPtrOrRef && !isSimpleType && !astIsContainer(var->nameToken())) @@ -1824,7 +1827,7 @@ static bool isConstant(const Token* tok) { return tok && (tok->isEnumerator() || Token::Match(tok, "%bool%|%num%|%str%|%char%|nullptr|NULL")); } -static bool isConstStatement(const Token *tok) +static bool isConstStatement(const Token *tok, bool isNestedBracket = false) { if (!tok) return false; @@ -1875,9 +1878,13 @@ static bool isConstStatement(const Token *tok) if (Token::simpleMatch(tok, "?") && Token::simpleMatch(tok->astOperand2(), ":")) // ternary operator return isConstStatement(tok->astOperand1()) && isConstStatement(tok->astOperand2()->astOperand1()) && isConstStatement(tok->astOperand2()->astOperand2()); if (isBracketAccess(tok) && isWithoutSideEffects(tok->astOperand1(), /*checkArrayAccess*/ true, /*checkReference*/ false)) { - if (Token::simpleMatch(tok->astParent(), "[")) - return isConstStatement(tok->astOperand2()) && isConstStatement(tok->astParent()); - return isConstStatement(tok->astOperand2()); + const bool isChained = succeeds(tok->astParent(), tok); + if (Token::simpleMatch(tok->astParent(), "[")) { + if (isChained) + return isConstStatement(tok->astOperand2()) && isConstStatement(tok->astParent()); + return isNestedBracket && isConstStatement(tok->astOperand2()); + } + return isConstStatement(tok->astOperand2(), /*isNestedBracket*/ !isChained); } return false; } diff --git a/lib/checktype.cpp b/lib/checktype.cpp index 0cc91ac8976..df30f929601 100644 --- a/lib/checktype.cpp +++ b/lib/checktype.cpp @@ -299,7 +299,7 @@ void CheckType::signConversionError(const Token *tok, const ValueFlow::Value *ne //--------------------------------------------------------------------------- // Checking for long cast of int result const long x = var1 * var2; //--------------------------------------------------------------------------- -static bool checkTypeCombination(const ValueType& src, const ValueType& tgt, const Settings& settings) +static bool checkTypeCombination(ValueType src, ValueType tgt, const Settings& settings) { static const std::pair typeCombinations[] = { { ValueType::Type::INT, ValueType::Type::LONG }, @@ -310,6 +310,9 @@ static bool checkTypeCombination(const ValueType& src, const ValueType& tgt, con { ValueType::Type::DOUBLE, ValueType::Type::LONGDOUBLE }, }; + src.reference = Reference::None; + tgt.reference = Reference::None; + const std::size_t sizeSrc = ValueFlow::getSizeOf(src, settings); const std::size_t sizeTgt = ValueFlow::getSizeOf(tgt, settings); if (!(sizeSrc > 0 && sizeTgt > 0 && sizeSrc < sizeTgt)) diff --git a/lib/checkunusedvar.cpp b/lib/checkunusedvar.cpp index 7d7ccd7b023..15f989d8a99 100644 --- a/lib/checkunusedvar.cpp +++ b/lib/checkunusedvar.cpp @@ -713,10 +713,12 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const type = Variables::pointer; else if (mTokenizer->isC() || i->typeEndToken()->isStandardType() || + i->isStlType() || isRecordTypeWithoutSideEffects(i->type()) || mSettings->library.detectContainer(i->typeStartToken()) || - i->isStlType()) + mSettings->library.getTypeCheck("unusedvar", i->typeStartToken()->str()) == Library::TypeCheck::check) type = Variables::standard; + if (type == Variables::none || isPartOfClassStructUnion(i->typeStartToken())) continue; const Token* defValTok = i->nameToken()->next(); @@ -1007,7 +1009,7 @@ void CheckUnusedVar::checkFunctionVariableUsage_iterateScopes(const Scope* const // assignment else if ((Token::Match(tok, "%name% [") && Token::simpleMatch(skipBracketsAndMembers(tok->next()), "=")) || - (tok->isUnaryOp("*") && Token::simpleMatch(tok->astParent(), "=") && Token::simpleMatch(tok->astOperand1(), "+"))) { + (tok->isUnaryOp("*") && astIsLHS(tok) && Token::simpleMatch(tok->astParent(), "=") && Token::simpleMatch(tok->astOperand1(), "+"))) { const Token *eq = tok; while (eq && !eq->isAssignmentOp()) eq = eq->astParent(); @@ -1199,8 +1201,9 @@ void CheckUnusedVar::checkFunctionVariableUsage() if (!isAssignment && !isInitialization && !isIncrementOrDecrement) continue; + bool isTrivialInit = false; if (isInitialization && Token::Match(tok, "%var% { }")) // don't warn for trivial initialization - continue; + isTrivialInit = true; if (isIncrementOrDecrement && tok->astParent() && precedes(tok, tok->astOperand1())) continue; @@ -1306,6 +1309,8 @@ void CheckUnusedVar::checkFunctionVariableUsage() reportLibraryCfgError(tok, bailoutTypeName); continue; } + if (isTrivialInit && findExpressionChanged(expr, start, scopeEnd, mSettings)) + continue; // warn if (!expr->variable() || !expr->variable()->isMaybeUnused()) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 9d719cfaafa..2d85f117a17 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -4251,7 +4251,7 @@ static bool setVarIdParseDeclaration(Token** tok, const VariableMap& variableMap bracket = true; } else if (tok2->str() == "::") { singleNameCount = 0; - } else if (tok2->str() != "*" && tok2->str() != "::" && tok2->str() != "...") { + } else if (tok2->str() != "*" && tok2->str() != "...") { break; } tok2 = tok2->next(); @@ -4826,7 +4826,8 @@ void Tokenizer::setVarIdPass1() // function declaration inside executable scope? Function declaration is of form: type name "(" args ")" if (scopeStack.top().isExecutable && Token::Match(tok, "%name% [,)[]")) { bool par = false; - const Token *start, *end; + const Token* start; + Token* end; // search begin of function declaration for (start = tok; Token::Match(start, "%name%|*|&|,|("); start = start->previous()) { @@ -4850,9 +4851,11 @@ void Tokenizer::setVarIdPass1() const bool isNotstartKeyword = start->next() && notstart.find(start->next()->str()) != notstart.end(); // now check if it is a function declaration - if (Token::Match(start, "[;{}] %type% %name%|*") && par && Token::simpleMatch(end, ") ;") && !isNotstartKeyword) + if (Token::Match(start, "[;{}] %type% %name%|*") && par && Token::simpleMatch(end, ") ;") && !isNotstartKeyword) { // function declaration => don't set varid + tok = end; continue; + } } if ((!scopeStack.top().isEnum || !(Token::Match(tok->previous(), "{|,") && Token::Match(tok->next(), ",|=|}"))) && @@ -8583,9 +8586,12 @@ void Tokenizer::findGarbageCode() const bool match1 = Token::Match(tok, "%or%|%oror%|==|!=|+|-|/|!|>=|<=|~|^|++|--|::|sizeof"); bool match2 = Token::Match(tok->next(), "{|if|else|while|do|for|return|switch|break"); if (isCPP()) { - match1 = match1 || Token::Match(tok, "::|throw|decltype|typeof"); + match1 = match1 || Token::Match(tok, "throw|decltype|typeof"); match2 = match2 || Token::Match(tok->next(), "try|catch|namespace"); } + if (match1 && !tok->isIncDecOp()) { + match2 = match2 || Token::Match(tok->next(), "%assign%"); + } if (match1 && match2) syntaxError(tok); } @@ -8635,6 +8641,8 @@ void Tokenizer::findGarbageCode() const syntaxError(tok); if (Token::Match(tok, "==|!=|<=|>= %comp%") && tok->strAt(-1) != "operator") syntaxError(tok, tok->str() + " " + tok->strAt(1)); + if (Token::simpleMatch(tok, ":: ::")) + syntaxError(tok); } // ternary operator without : diff --git a/lib/tokenlist.cpp b/lib/tokenlist.cpp index 5e9017eb487..af8d20e17d8 100644 --- a/lib/tokenlist.cpp +++ b/lib/tokenlist.cpp @@ -1758,7 +1758,10 @@ static Token * createAstAtToken(Token *tok) void TokenList::createAst() const { for (Token *tok = mTokensFrontBack.front; tok; tok = tok ? tok->next() : nullptr) { - tok = createAstAtToken(tok); + Token* const nextTok = createAstAtToken(tok); + if (precedes(nextTok, tok)) + throw InternalError(tok, "Syntax Error: Infinite loop when creating AST.", InternalError::AST); + tok = nextTok; } } diff --git a/lib/utils.h b/lib/utils.h index 481d9e890b3..22b511c90c8 100644 --- a/lib/utils.h +++ b/lib/utils.h @@ -361,4 +361,10 @@ namespace cppcheck } } +template +static inline T* empty_if_null(T* p) +{ + return p ? p : ""; +} + #endif diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 5a3833419b0..aa194ea1727 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -4972,6 +4972,8 @@ static void valueFlowLifetime(TokenList &tokenlist, ErrorLogger *errorLogger, co } // address of else if (tok->isUnaryOp("&")) { + if (Token::simpleMatch(tok->astParent(), "*")) + continue; for (const ValueFlow::LifetimeToken& lt : ValueFlow::getLifetimeTokens(tok->astOperand1())) { if (!settings.certainty.isEnabled(Certainty::inconclusive) && lt.inconclusive) continue; @@ -5334,16 +5336,19 @@ static const Scope* getLoopScope(const Token* tok) // static void valueFlowConditionExpressions(const TokenList &tokenlist, const SymbolDatabase& symboldatabase, ErrorLogger *errorLogger, const Settings &settings) { - if (settings.checkLevel == Settings::CheckLevel::normal) + if (!settings.daca && (settings.checkLevel == Settings::CheckLevel::normal)) return; for (const Scope * scope : symboldatabase.functionScopes) { if (const Token* incompleteTok = findIncompleteVar(scope->bodyStart, scope->bodyEnd)) { if (settings.debugwarnings) bailoutIncompleteVar(tokenlist, errorLogger, incompleteTok, "Skipping function due to incomplete variable " + incompleteTok->str()); - break; + continue; } + if (settings.daca && (settings.checkLevel == Settings::CheckLevel::normal)) + continue; + for (Token* tok = const_cast(scope->bodyStart); tok != scope->bodyEnd; tok = tok->next()) { if (!Token::simpleMatch(tok, "if (")) continue; diff --git a/releasenotes.txt b/releasenotes.txt index 65c9e9ef90a..f68333b7075 100644 --- a/releasenotes.txt +++ b/releasenotes.txt @@ -24,4 +24,6 @@ Other: - Removed deprecated platform type 'Unspecified'. Please use 'unspecified' instead. - Removed deprecated 'Makefile' option 'SRCDIR'. - Added CMake option 'DISALLOW_THREAD_EXECUTOR' to control the inclusion of the executor which performs the analysis within a thread of the main process. -- Removed CMake option 'USE_THREADS' in favor of 'DISALLOW_THREAD_EXECUTOR'. \ No newline at end of file +- Removed CMake option 'USE_THREADS' in favor of 'DISALLOW_THREAD_EXECUTOR'. +- Fixed crash with '--rule-file=' if some data was missing. +- '--rule-file' will now bail out if a rule could not be added or a file contains unexpected data. \ No newline at end of file diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 4ec673ba152..a92ef8ed166 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -115,7 +115,6 @@ if (BUILD_TESTS) else() # TODO: remove missingInclude disabling when it no longer is implied by --enable=information # TODO: add syntax check - # need to suppress unmatchedSuppression in case valueFlowBailout is not reported add_test(NAME cfg-${TEST_NAME} COMMAND $ --library=${LIBRARY} @@ -129,9 +128,7 @@ if (BUILD_TESTS) --disable=missingInclude --inline-suppr --debug-warnings - --suppress=valueFlowBailout - --suppress=purgedConfiguration - --suppress=unmatchedSuppression + --suppress=checkersReport ${CMAKE_CURRENT_SOURCE_DIR}/cfg/${CFG_TEST} ) endif() diff --git a/test/cfg/boost.cpp b/test/cfg/boost.cpp index d2e19fbd2b1..d68d5a7f262 100644 --- a/test/cfg/boost.cpp +++ b/test/cfg/boost.cpp @@ -7,6 +7,8 @@ // No warnings about bad library configuration, unmatched suppressions, etc. exitcode=0 // +// cppcheck-suppress-file valueFlowBailout + #include #include #include diff --git a/test/cfg/bsd.c b/test/cfg/bsd.c index 734a97fe4aa..6652129c553 100644 --- a/test/cfg/bsd.c +++ b/test/cfg/bsd.c @@ -6,6 +6,8 @@ // No warnings about bad library configuration, unmatched suppressions, etc. exitcode=0 // +// cppcheck-suppress-file valueFlowBailout + #include #include #include diff --git a/test/cfg/cppunit.cpp b/test/cfg/cppunit.cpp index 28b7fa7a858..1eaf0b66628 100644 --- a/test/cfg/cppunit.cpp +++ b/test/cfg/cppunit.cpp @@ -6,6 +6,8 @@ // No warnings about bad library configuration, unmatched suppressions, etc. exitcode=0 // +// cppcheck-suppress-file valueFlowBailout + #include void cppunit_assert_equal(int x, double y) diff --git a/test/cfg/gnu.c b/test/cfg/gnu.c index a259215153b..296a3cc0442 100644 --- a/test/cfg/gnu.c +++ b/test/cfg/gnu.c @@ -7,6 +7,8 @@ // No warnings about bad library configuration, unmatched suppressions, etc. exitcode=0 // +// cppcheck-suppress-file valueFlowBailout + #include #include #include @@ -387,6 +389,7 @@ void memleak_xmalloc() void memleak_mmap() { + // cppcheck-suppress valueFlowBailoutIncompleteVar const void * p_mmap = mmap(NULL, 1, PROT_NONE, MAP_ANONYMOUS | MAP_SHARED, -1, 0); printf("%p", p_mmap); // cppcheck-suppress memleak @@ -466,6 +469,7 @@ int nullPointer_epoll_ctl(int epfd, int op, int fd, struct epoll_event *event) // Remove (deregister) the target file descriptor fd from the // epoll instance referred to by epfd. The event is ignored and // can be NULL. + // cppcheck-suppress valueFlowBailoutIncompleteVar return epoll_ctl(epfd, EPOLL_CTL_DEL, fd, NULL); } #endif diff --git a/test/cfg/googletest.cpp b/test/cfg/googletest.cpp index cc4c1415ae6..c13db34967a 100644 --- a/test/cfg/googletest.cpp +++ b/test/cfg/googletest.cpp @@ -7,6 +7,8 @@ // No warnings about bad library configuration, unmatched suppressions, etc. exitcode=0 // +// cppcheck-suppress-file valueFlowBailout + #include #include @@ -50,6 +52,7 @@ TEST(test_cppcheck, cppcheck) // #9964 - avoid compareBoolExpressionWithInt false positive TEST(Test, assert_false_fp) { + // cppcheck-suppress valueFlowBailoutIncompleteVar ASSERT_FALSE(errno < 0); } @@ -73,6 +76,7 @@ TEST(Test, warning_in_assert_macros) // cppcheck-suppress duplicateExpression ASSERT_GE(i, i); + // cppcheck-suppress valueFlowBailoutIncompleteVar unsigned int u = errno; // cppcheck-suppress [unsignedPositive] ASSERT_GE(u, 0); diff --git a/test/cfg/gtk.c b/test/cfg/gtk.c index 66aa875b229..6d8b2258a91 100644 --- a/test/cfg/gtk.c +++ b/test/cfg/gtk.c @@ -302,6 +302,7 @@ void g_new0_test() int b; }; // valid + // cppcheck-suppress valueFlowBailoutIncompleteVar struct a * pNew1 = g_new0(struct a, 5); printf("%p", pNew1); g_free(pNew1); @@ -320,6 +321,7 @@ void g_try_new_test() int b; }; // valid + // cppcheck-suppress valueFlowBailoutIncompleteVar struct a * pNew1 = g_try_new(struct a, 5); printf("%p", pNew1); g_free(pNew1); @@ -337,6 +339,7 @@ void g_try_new0_test() int b; }; // valid + // cppcheck-suppress valueFlowBailoutIncompleteVar struct a * pNew1 = g_try_new0(struct a, 5); printf("%p", pNew1); g_free(pNew1); @@ -354,7 +357,7 @@ void g_renew_test() struct a { int b; }; - // cppcheck-suppress leakReturnValNotUsed + // cppcheck-suppress [leakReturnValNotUsed,valueFlowBailoutIncompleteVar] g_renew(struct a, NULL, 1); struct a * pNew = g_new(struct a, 1); @@ -369,7 +372,7 @@ void g_try_renew_test() struct a { int b; }; - // cppcheck-suppress leakReturnValNotUsed + // cppcheck-suppress [leakReturnValNotUsed,valueFlowBailoutIncompleteVar] g_try_renew(struct a, NULL, 1); struct a * pNew = g_try_new(struct a, 1); diff --git a/test/cfg/libcurl.c b/test/cfg/libcurl.c index 8c494494a03..9e91eefcc5c 100644 --- a/test/cfg/libcurl.c +++ b/test/cfg/libcurl.c @@ -7,6 +7,8 @@ // No warnings about bad library configuration, unmatched suppressions, etc. exitcode=0 // +// cppcheck-suppress-file valueFlowBailout + #include #include diff --git a/test/cfg/opencv2.cpp b/test/cfg/opencv2.cpp index 6667785ef4e..de0f3731b81 100644 --- a/test/cfg/opencv2.cpp +++ b/test/cfg/opencv2.cpp @@ -7,6 +7,8 @@ // No warnings about bad library configuration, unmatched suppressions, etc. exitcode=0 // +// cppcheck-suppress-file valueFlowBailout + #include #include @@ -43,7 +45,7 @@ void memleak() { // cppcheck-suppress cstyleCast const char * pBuf = (char *)cv::fastMalloc(1000); - // cppcheck-suppress uninitdata + // cppcheck-suppress [uninitdata, valueFlowBailoutIncompleteVar] std::cout << pBuf; // cppcheck-suppress memleak } diff --git a/test/cfg/posix.c b/test/cfg/posix.c index c2a78fbdc1b..b4b8c9e4985 100644 --- a/test/cfg/posix.c +++ b/test/cfg/posix.c @@ -7,6 +7,8 @@ // No warnings about bad library configuration, unmatched suppressions, etc. exitcode=0 // +// cppcheck-suppress-file [valueFlowBailout,purgedConfiguration] + #define _BSD_SOURCE #include @@ -1062,6 +1064,7 @@ void * memleak_mmap2() // #8327 void memleak_getline() { // #11043 char *line = NULL; size_t size = 0; + // cppcheck-suppress valueFlowBailoutIncompleteVar getline(&line, &size, stdin); // cppcheck-suppress memleak line = NULL; @@ -1082,6 +1085,7 @@ void memleak_getline_array(FILE* stream) { // #12498 void memleak_getdelim(int delim) { char *line = NULL; size_t size = 0; + // cppcheck-suppress valueFlowBailoutIncompleteVar getdelim(&line, &size, delim, stdin); // cppcheck-suppress memleak line = NULL; @@ -1101,6 +1105,7 @@ void memleak_getdelim_array(FILE* stream, int delim) { void * identicalCondition_mmap(int fd, size_t size) // #9940 { + // cppcheck-suppress valueFlowBailoutIncompleteVar void* buffer = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); if (buffer == MAP_FAILED) { return NULL; @@ -1113,6 +1118,7 @@ int munmap_no_double_free(int tofd, // #11396 size_t len) { int rc; + // cppcheck-suppress valueFlowBailoutIncompleteVar const void* fptr = mmap(NULL,len,PROT_READ|PROT_WRITE,MAP_SHARED,fromfd,(off_t)0); if (fptr == MAP_FAILED) { return -1; @@ -1147,6 +1153,7 @@ void resourceLeak_fdopen(int fd) void resourceLeak_fdopen2(const char* fn) // #2767 { + // cppcheck-suppress valueFlowBailoutIncompleteVar int fi = open(fn, O_RDONLY); FILE* fd = fdopen(fi, "r"); fclose(fd); @@ -1193,14 +1200,14 @@ void resourceLeak_socket(void) void resourceLeak_open1(void) { - // cppcheck-suppress unreadVariable + // cppcheck-suppress [unreadVariable,valueFlowBailoutIncompleteVar] int fd = open("file", O_RDWR | O_CREAT); // cppcheck-suppress resourceLeak } void resourceLeak_open2(void) { - // cppcheck-suppress unreadVariable + // cppcheck-suppress [unreadVariable,valueFlowBailoutIncompleteVar] int fd = open("file", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); // cppcheck-suppress resourceLeak } @@ -1213,6 +1220,7 @@ void noleak(int x, int y, int z) closedir(p2); int s = socket(AF_INET,SOCK_STREAM,0); close(s); + // cppcheck-suppress valueFlowBailoutIncompleteVar int fd1 = open("a", O_RDWR | O_CREAT); close(fd1); int fd2 = open("a", O_RDWR | O_CREAT, S_IRUSR | S_IWUSR); @@ -1357,7 +1365,7 @@ void timet_h(const struct timespec* ptp1) clockid_t clk_id1, clk_id2, clk_id3; // cppcheck-suppress constVariablePointer struct timespec* ptp; - // cppcheck-suppress uninitvar + // cppcheck-suppress [uninitvar,valueFlowBailoutIncompleteVar] clock_settime(CLOCK_REALTIME, ptp); // cppcheck-suppress uninitvar clock_settime(clk_id1, ptp); diff --git a/test/cfg/qt.cpp b/test/cfg/qt.cpp index 5fcb803e372..d4350cea827 100644 --- a/test/cfg/qt.cpp +++ b/test/cfg/qt.cpp @@ -7,6 +7,8 @@ // No warnings about bad library configuration, unmatched suppressions, etc. exitcode=0 // +// cppcheck-suppress-file valueFlowBailout + #include #include #include @@ -23,19 +25,19 @@ #include #include #include -#include -#include -#include -#include #include +#include #include +#include #include +#include +#include #include void unreadVariable_QRegion(const int x, const QRegion::RegionType type, const QPolygon &polygon, const QBitmap &bm, const QRegion ®ion, const Qt::FillRule fillRule) { - // cppcheck-suppress unreadVariable + // cppcheck-suppress unusedVariable QRegion a; // cppcheck-suppress unreadVariable QRegion b{}; @@ -53,7 +55,7 @@ void unreadVariable_QRegion(const int x, const QRegion::RegionType type, const Q void unreadVariable_QPoint(const QPoint &s) { - // cppcheck-suppress unreadVariable + // cppcheck-suppress unusedVariable QPoint a; // cppcheck-suppress unreadVariable QPoint b{}; @@ -67,7 +69,7 @@ void unreadVariable_QPoint(const QPoint &s) void unreadVariable_QPointF(const QPointF &s) { - // cppcheck-suppress unreadVariable + // cppcheck-suppress unusedVariable QPointF a; // cppcheck-suppress unreadVariable QPointF b{}; @@ -81,7 +83,7 @@ void unreadVariable_QPointF(const QPointF &s) void unreadVariable_QSizeF(const QSize &s) { - // cppcheck-suppress unreadVariable + // cppcheck-suppress unusedVariable QSizeF a; // cppcheck-suppress unreadVariable QSizeF b{}; @@ -95,7 +97,7 @@ void unreadVariable_QSizeF(const QSize &s) void unreadVariable_QSize(const QSize &s) { - // cppcheck-suppress unreadVariable + // cppcheck-suppress unusedVariable QSize a; // cppcheck-suppress unreadVariable QSize b{}; @@ -108,7 +110,7 @@ void unreadVariable_QSize(const QSize &s) } void unreadVariable_QRect(const QPoint &topLeft, const QSize &size, const QPoint &bottomRight, const int x) { - // cppcheck-suppress unreadVariable + // cppcheck-suppress unusedVariable QRect a; // cppcheck-suppress unreadVariable QRect b{}; @@ -123,7 +125,7 @@ void unreadVariable_QRect(const QPoint &topLeft, const QSize &size, const QPoint } void unreadVariable_QRectF(const QPointF &topLeft, const QSizeF &size, const QPointF &bottomRight, const QRectF &rect, const qreal x) { - // cppcheck-suppress unreadVariable + // cppcheck-suppress unusedVariable QRectF a; // cppcheck-suppress unreadVariable QRectF b{}; @@ -576,7 +578,7 @@ void validCode(int * pIntPtr, QString & qstrArg, double d) printf(QT_TR_NOOP("Hi")); - // cppcheck-suppress checkLibraryFunction + // cppcheck-suppress valueFlowBailoutIncompleteVar Q_DECLARE_LOGGING_CATEGORY(logging_category_test); QT_FORWARD_DECLARE_CLASS(forwardDeclaredClass); QT_FORWARD_DECLARE_STRUCT(forwardDeclaredStruct); diff --git a/test/cfg/runtests.sh b/test/cfg/runtests.sh index 744d9aa7284..5b4fa1dd6fd 100755 --- a/test/cfg/runtests.sh +++ b/test/cfg/runtests.sh @@ -27,7 +27,7 @@ CFG="$DIR"../../cfg/ # TODO: remove missingInclude disabling when it no longer is implied by --enable=information # Cppcheck options # need to suppress unmatchedSuppression in case valueFlowBailout is not reported -CPPCHECK_OPT='--check-library --platform=unix64 --enable=style,information --inconclusive --force --check-level=exhaustive --error-exitcode=-1 --disable=missingInclude --inline-suppr --template="{file}:{line}:{severity}:{id}:{message}" --debug-warnings --suppress=valueFlowBailout --suppress=purgedConfiguration --suppress=unmatchedSuppression' +CPPCHECK_OPT='--check-library --platform=unix64 --enable=style,information --inconclusive --force --check-level=exhaustive --error-exitcode=-1 --disable=missingInclude --inline-suppr --template="{file}:{line}:{severity}:{id}:{message}" --debug-warnings --suppress=checkersReport' # Compiler settings CXX=g++ diff --git a/test/cfg/std.c b/test/cfg/std.c index 9f2a0d213cf..f795cdc5bda 100644 --- a/test/cfg/std.c +++ b/test/cfg/std.c @@ -7,6 +7,8 @@ // No warnings about bad library configuration, unmatched suppressions, etc. exitcode=0 // +// cppcheck-suppress-file valueFlowBailout + #include #include #include @@ -401,6 +403,7 @@ void nullpointer(int value) fp = 0; // No FP fflush(0); // If stream is a null pointer, all streams are flushed. + // cppcheck-suppress valueFlowBailoutIncompleteVar fp = freopen(0,"abc",stdin); fclose(fp); fp = NULL; @@ -732,6 +735,7 @@ void uninitvar_fgets(void) char *str; int n; + // cppcheck-suppress valueFlowBailoutIncompleteVar fgets(buf,10,stdin); // cppcheck-suppress uninitvar @@ -749,6 +753,7 @@ void uninitvar_fputc(void) int i; FILE *fp; + // cppcheck-suppress valueFlowBailoutIncompleteVar fputc('a', stdout); // cppcheck-suppress uninitvar @@ -763,6 +768,7 @@ void uninitvar_fputs(void) const char *s; FILE *fp; + // cppcheck-suppress valueFlowBailoutIncompleteVar fputs("a", stdout); // cppcheck-suppress uninitvar @@ -3456,6 +3462,7 @@ void invalidFunctionArg_log10(float f, double d, const long double ld) (void)log10f(0.0f); (void)log10f(1.4013e-45f); // note: calculated by nextafterf(0.0f, 1.0f); (void)log10f(f); + // cppcheck-suppress valueFlowBailoutIncompleteVar (void)log10f(FLT_MAX); // cppcheck-suppress invalidFunctionArg @@ -3480,6 +3487,7 @@ void invalidFunctionArg_log(float f, double d, const long double ld) (void)logf(0.0f); (void)logf(1.4013e-45f); // note: calculated by nextafterf(0.0f, 1.0f); (void)logf(f); + // cppcheck-suppress valueFlowBailoutIncompleteVar (void)logf(FLT_MAX); // cppcheck-suppress invalidFunctionArg @@ -3504,6 +3512,7 @@ void invalidFunctionArg_log2(float f, double d, const long double ld) (void)log2f(0.0f); (void)log2f(1.4013e-45f); // note: calculated by nextafterf(0.0f, 1.0f); (void)log2f(f); + // cppcheck-suppress valueFlowBailoutIncompleteVar (void)log2f(FLT_MAX); // cppcheck-suppress invalidFunctionArg @@ -4973,6 +4982,7 @@ void invalidPrintfArgType_printf(void) // #7016 uint8_t n = 7; // TODO cppcheck-suppress invalidPrintfArgType_uint + // cppcheck-suppress valueFlowBailoutIncompleteVar printf("%" PRIi16 "\n", n); } diff --git a/test/cfg/std.cpp b/test/cfg/std.cpp index 0438ea39487..a8a0f018c4e 100644 --- a/test/cfg/std.cpp +++ b/test/cfg/std.cpp @@ -7,6 +7,8 @@ // No warnings about bad library configuration, unmatched suppressions, etc. exitcode=0 // +// cppcheck-suppress-file valueFlowBailout + #include #include #include @@ -662,8 +664,10 @@ void memleak_localtime_s(const std::time_t *restrict time, struct tm *restrict r { const time_t t = time(0); const struct tm* const now = new tm(); - if (localtime_s(now, &t) == 0) + if (localtime_s(now, &t) == 0) { + // cppcheck-suppress valueFlowBailoutIncompleteVar std::cout << now->tm_mday << std::endl; + } // cppcheck-suppress memleak } #endif // __STDC_LIB_EXT1__ @@ -706,6 +710,7 @@ void invalidFunctionArg_std_wstring_substr(const std::wstring &str, std::size_t (void)str.substr(pos,-1); // no warning is expected for (void)str.substr(pos,len); + // cppcheck-suppress valueFlowBailoutIncompleteVar (void)str.substr(pos, std::wstring::npos); } @@ -2469,21 +2474,21 @@ void uninitvar_ldexp(void) void invalidFunctionArg_lgamma(float f, double d, long double ld) { (void)lgamma(d); - // cppcheck-suppress invalidFunctionArg + // TODO cppcheck-suppress invalidFunctionArg (void)lgamma(-0.1); // cppcheck-suppress invalidFunctionArg (void)lgamma(0.0); (void)lgamma(0.1); (void)lgammaf(f); - // cppcheck-suppress invalidFunctionArg + // TODO cppcheck-suppress invalidFunctionArg (void)lgammaf(-0.1f); // cppcheck-suppress invalidFunctionArg (void)lgammaf(0.0f); (void)lgammaf(0.1f); (void)lgammal(ld); - // cppcheck-suppress invalidFunctionArg + // TODO cppcheck-suppress invalidFunctionArg (void)lgammal(-0.1L); // cppcheck-suppress invalidFunctionArg (void)lgammal(0.0L); @@ -2493,21 +2498,21 @@ void invalidFunctionArg_lgamma(float f, double d, long double ld) void invalidFunctionArg_tgamma(float f, double d, long double ld) { (void)tgamma(d); - // cppcheck-suppress invalidFunctionArg + // TODO cppcheck-suppress invalidFunctionArg (void)tgamma(-0.1); // cppcheck-suppress invalidFunctionArg (void)tgamma(0.0); (void)tgamma(0.1); (void)tgammaf(f); - // cppcheck-suppress invalidFunctionArg + // TODO cppcheck-suppress invalidFunctionArg (void)tgammaf(-0.1f); // cppcheck-suppress invalidFunctionArg (void)tgammaf(0.0f); (void)tgammaf(0.1f); (void)tgammal(ld); - // cppcheck-suppress invalidFunctionArg + // TODO cppcheck-suppress invalidFunctionArg (void)tgammal(-0.1L); // cppcheck-suppress invalidFunctionArg (void)tgammal(0.0L); @@ -4256,7 +4261,7 @@ void nullPointer_system(const char *c) void uninitvar_setw(void) { int i; - // cppcheck-suppress uninitvar + // cppcheck-suppress [uninitvar,valueFlowBailoutIncompleteVar] std::cout << std::setw(i); } @@ -4264,6 +4269,7 @@ void uninitvar_setiosflags(void) { std::ios_base::fmtflags mask; // TODO cppcheck-suppress uninitvar + // cppcheck-suppress valueFlowBailoutIncompleteVar std::cout << std::setiosflags(mask); // #6987 - false negative } @@ -4271,13 +4277,14 @@ void uninitvar_resetiosflags(void) { std::ios_base::fmtflags mask; // TODO cppcheck-suppress uninitvar + // cppcheck-suppress valueFlowBailoutIncompleteVar std::cout << std::resetiosflags(mask); // #6987 - false negative } void uninitvar_setfill(void) { char c; - // cppcheck-suppress uninitvar + // cppcheck-suppress [uninitvar,valueFlowBailoutIncompleteVar] std::cout << std::setfill(c); wchar_t wc; @@ -4288,14 +4295,14 @@ void uninitvar_setfill(void) void uninitvar_setprecision(void) { int p; - // cppcheck-suppress uninitvar + // cppcheck-suppress [uninitvar,valueFlowBailoutIncompleteVar] std::cout << std::setprecision(p); } void uninitvar_setbase(void) { int p; - // cppcheck-suppress uninitvar + // cppcheck-suppress [uninitvar,valueFlowBailoutIncompleteVar] std::cout << std::setbase(p); } @@ -4732,6 +4739,7 @@ void stdbind_helper(int a) void stdbind() { + // cppcheck-suppress valueFlowBailoutIncompleteVar using namespace std::placeholders; // TODO cppcheck-suppress ignoredReturnValue #9369 @@ -4963,7 +4971,7 @@ void memleak_std_realloc(void* block, size_t newsize) void unusedAllocatedMemory_std_free() { - //cppcheck-suppress unusedAllocatedMemory + // TODO cppcheck-suppress unusedAllocatedMemory void* p = std::malloc(1); std::free(p); } diff --git a/test/cfg/windows.cpp b/test/cfg/windows.cpp index 179f44d4b3f..5f2e6555ead 100644 --- a/test/cfg/windows.cpp +++ b/test/cfg/windows.cpp @@ -7,6 +7,8 @@ // No warnings about bad library configuration, unmatched suppressions, etc. exitcode=0 // +// cppcheck-suppress-file [valueFlowBailout,purgedConfiguration] + #include #include #include @@ -355,7 +357,7 @@ void validCode() WSACleanup(); wordInit = MAKEWORD(1, 2); - // cppcheck-suppress redundantAssignment + // TODO cppcheck-suppress redundantAssignment dwordInit = MAKELONG(1, 2); // cppcheck-suppress redundantAssignment wordInit = LOWORD(dwordInit); @@ -485,7 +487,7 @@ void mismatchAllocDealloc() void nullPointer() { HANDLE hSemaphore; - // cppcheck-suppress nullPointer + // cppcheck-suppress [nullPointer,valueFlowBailoutIncompleteVar] hSemaphore = OpenSemaphore(SEMAPHORE_ALL_ACCESS, FALSE, NULL); CloseHandle(hSemaphore); @@ -588,7 +590,7 @@ void memleak_HeapAlloc() void memleak_LocalAlloc() { LPTSTR pszBuf; - // cppcheck-suppress [LocalAllocCalled, cstyleCast] + // cppcheck-suppress [LocalAllocCalled, cstyleCast, valueFlowBailoutIncompleteVar] pszBuf = (LPTSTR)LocalAlloc(LPTR, MAX_PATH*sizeof(TCHAR)); (void)LocalSize(pszBuf); (void)LocalFlags(pszBuf); @@ -622,7 +624,7 @@ void resourceLeak_CreateSemaphoreA() void resourceLeak_CreateSemaphoreEx() { HANDLE hSemaphore; - // cppcheck-suppress unreadVariable + // cppcheck-suppress [unreadVariable,valueFlowBailoutIncompleteVar] hSemaphore = CreateSemaphoreEx(NULL, 0, 1, NULL, 0, SEMAPHORE_ALL_ACCESS); // cppcheck-suppress resourceLeak } @@ -630,7 +632,7 @@ void resourceLeak_CreateSemaphoreEx() void resourceLeak_OpenSemaphore() { HANDLE hSemaphore; - // cppcheck-suppress unreadVariable + // cppcheck-suppress [unreadVariable,valueFlowBailoutIncompleteVar] hSemaphore = OpenSemaphore(SEMAPHORE_ALL_ACCESS, TRUE, _T("sem")); // cppcheck-suppress resourceLeak } @@ -646,7 +648,7 @@ void resourceLeak_CreateMutexA() void resourceLeak_CreateMutexEx() { HANDLE hMutex; - // cppcheck-suppress unreadVariable + // cppcheck-suppress [unreadVariable,valueFlowBailoutIncompleteVar] hMutex = CreateMutexEx(NULL, _T("sem"), 0, MUTEX_ALL_ACCESS); // cppcheck-suppress resourceLeak } @@ -688,7 +690,7 @@ void resourceLeak_CreateEventExA() void resourceLeak_OpenEventW() { HANDLE hEvent; - // cppcheck-suppress unreadVariable + // cppcheck-suppress [unreadVariable,valueFlowBailoutIncompleteVar] hEvent = OpenEventW(EVENT_ALL_ACCESS, TRUE, L"testevent"); // cppcheck-suppress resourceLeak } @@ -705,7 +707,7 @@ void ignoredReturnValue(FILE* fp) { // cppcheck-suppress leakReturnValNotUsed CreateSemaphoreW(NULL, 0, 1, NULL); - // cppcheck-suppress leakReturnValNotUsed + // cppcheck-suppress [leakReturnValNotUsed,valueFlowBailoutIncompleteVar] CreateSemaphoreExA(NULL, 0, 1, NULL, 0, SEMAPHORE_ALL_ACCESS); // cppcheck-suppress leakReturnValNotUsed OpenSemaphoreA(SEMAPHORE_ALL_ACCESS, TRUE, "sem"); @@ -770,7 +772,7 @@ void invalidFunctionArg() // cppcheck-suppress invalidFunctionArgBool hSemaphore = CreateSemaphore(NULL, 0, 1, false); CloseHandle(hSemaphore); - // cppcheck-suppress invalidFunctionArg + // cppcheck-suppress [invalidFunctionArg,valueFlowBailoutIncompleteVar] hSemaphore = CreateSemaphoreEx(NULL, 0, 0, NULL, 0, SEMAPHORE_ALL_ACCESS); CloseHandle(hSemaphore); // cppcheck-suppress invalidFunctionArg @@ -789,7 +791,7 @@ void invalidFunctionArg() CloseHandle(hMutex); //Incorrect: 2. parameter to LoadLibraryEx() must be NULL - // cppcheck-suppress invalidFunctionArg + // TODO cppcheck-suppress invalidFunctionArg HINSTANCE hInstLib = LoadLibraryEx(L"My.dll", HANDLE(1), 0); FreeLibrary(hInstLib); @@ -814,7 +816,7 @@ void uninitvar() // cppcheck-suppress uninitvar lstrcat(buf, _T("test")); buf[0] = _T('\0'); - // cppcheck-suppress constVariable + // TODO cppcheck-suppress constVariable TCHAR buf2[2]; // cppcheck-suppress lstrcatCalled // cppcheck-suppress uninitvar diff --git a/test/cfg/wxwidgets.cpp b/test/cfg/wxwidgets.cpp index 85e233cdf9a..9292a7f71b3 100644 --- a/test/cfg/wxwidgets.cpp +++ b/test/cfg/wxwidgets.cpp @@ -7,12 +7,15 @@ // No warnings about bad library configuration, unmatched suppressions, etc. exitcode=0 // +// cppcheck-suppress-file valueFlowBailout + #include #include #include #include #include #include +#include #include #include #include @@ -36,15 +39,41 @@ #include #include -void unreadVariable_wxAcceleratorEntry() +void unreadVariable_wxPoint2DInt(const wxInt32 x, const wxPoint2DInt& pti, const wxPoint &pt) +{ + // cppcheck-suppress unusedVariable + wxPoint2DInt a; + // cppcheck-suppress unreadVariable + wxPoint2DInt b(x, x); + // cppcheck-suppress unreadVariable + wxPoint2DInt c(pti); + // cppcheck-suppress unreadVariable + wxPoint2DInt d(pt); +} + +void unreadVariable_wxPoint2DDouble(const wxDouble x, const wxPoint2DDouble& ptd, const wxPoint2DInt& pti, const wxPoint &pt) { + // cppcheck-suppress unusedVariable + wxPoint2DDouble a; + // cppcheck-suppress unreadVariable + wxPoint2DDouble b(x, x); + // cppcheck-suppress unreadVariable + wxPoint2DDouble c(ptd); // cppcheck-suppress unreadVariable + wxPoint2DDouble d(pti); + // cppcheck-suppress unreadVariable + wxPoint2DDouble e(pt); +} + +void unusedVariable_wxAcceleratorEntry() +{ + // cppcheck-suppress unusedVariable wxAcceleratorEntry a; } void unreadVariable_wxDateSpan(const int x) { - // cppcheck-suppress unreadVariable + // cppcheck-suppress unusedVariable wxDateSpan a; // cppcheck-suppress unreadVariable wxDateSpan b{x}; @@ -58,7 +87,7 @@ void unreadVariable_wxDateSpan(const int x) void unreadVariable_wxTimeSpan(const long x, const wxLongLong y) { - // cppcheck-suppress unreadVariable + // cppcheck-suppress unusedVariable wxTimeSpan a; // cppcheck-suppress unreadVariable wxTimeSpan b{}; @@ -80,7 +109,7 @@ void unreadVariable_wxFileType(const wxFileTypeInfo &info) void unreadVariable_wxPosition(const int x) { - // cppcheck-suppress unreadVariable + // cppcheck-suppress unusedVariable wxPosition a; // cppcheck-suppress unreadVariable wxPosition b{}; @@ -90,7 +119,7 @@ void unreadVariable_wxPosition(const int x) void unreadVariable_wxRegEx(const wxString &expr, const int flags) { - // cppcheck-suppress unreadVariable + // cppcheck-suppress unusedVariable wxRegEx a; // cppcheck-suppress unreadVariable wxRegEx b{expr}; @@ -100,7 +129,7 @@ void unreadVariable_wxRegEx(const wxString &expr, const int flags) void unreadVariable_wxRegion(const wxCoord x, const wxPoint &pt, const wxRect &rect, const wxRegion ®ion, const wxBitmap &bmp) { - // cppcheck-suppress unreadVariable + // cppcheck-suppress unusedVariable wxRegion a; // cppcheck-suppress unreadVariable wxRegion b{}; @@ -118,7 +147,7 @@ void unreadVariable_wxRegion(const wxCoord x, const wxPoint &pt, const wxRect &r void unreadVariable_wxVersionInfo(const wxString &name, const int major, const int minor, const int micro, const wxString &description, const wxString ©right) { - // cppcheck-suppress unreadVariable + // cppcheck-suppress unusedVariable wxVersionInfo a; // cppcheck-suppress unreadVariable wxVersionInfo b(name); @@ -136,7 +165,7 @@ void unreadVariable_wxVersionInfo(const wxString &name, const int major, const i void unreadVariable_wxSize(const wxSize &s) { - // cppcheck-suppress unreadVariable + // cppcheck-suppress unusedVariable wxSize a; // cppcheck-suppress unreadVariable wxSize b{}; @@ -150,7 +179,7 @@ void unreadVariable_wxSize(const wxSize &s) void unreadVariable_wxPoint(const wxRealPoint &rp, const int x, const int y) { - // cppcheck-suppress unreadVariable + // cppcheck-suppress unusedVariable wxPoint a; // cppcheck-suppress unreadVariable wxPoint b{}; @@ -168,7 +197,7 @@ void unreadVariable_wxPoint(const wxRealPoint &rp, const int x, const int y) void unreadVariable_wxRealPoint(const wxPoint &pt, const double x, const double y) { - // cppcheck-suppress unreadVariable + // cppcheck-suppress unusedVariable wxRealPoint a; // cppcheck-suppress unreadVariable wxRealPoint b{}; @@ -186,7 +215,7 @@ void unreadVariable_wxRealPoint(const wxPoint &pt, const double x, const double void unreadVariable_wxRect(const int x, const wxPoint &pt, const wxSize &sz) { - // cppcheck-suppress unreadVariable + // cppcheck-suppress unusedVariable wxRect a; // cppcheck-suppress unreadVariable wxRect b{}; diff --git a/test/cli/fuzz-crash/crash-0f0efd6e66bd115fc0aabbfe6503230b31de5f24 b/test/cli/fuzz-crash/crash-0f0efd6e66bd115fc0aabbfe6503230b31de5f24 new file mode 100644 index 00000000000..a011f109bd7 --- /dev/null +++ b/test/cli/fuzz-crash/crash-0f0efd6e66bd115fc0aabbfe6503230b31de5f24 @@ -0,0 +1 @@ +d f(t*a){a[a[3]]} \ No newline at end of file diff --git a/test/cli/fuzz-crash/crash-43fe82a87d6a7f34f000cbbc90b63ad1a58e3dcd b/test/cli/fuzz-crash/crash-43fe82a87d6a7f34f000cbbc90b63ad1a58e3dcd new file mode 100644 index 00000000000..ac43489b2c0 --- /dev/null +++ b/test/cli/fuzz-crash/crash-43fe82a87d6a7f34f000cbbc90b63ad1a58e3dcd @@ -0,0 +1 @@ +d o(){t&a=*&a} \ No newline at end of file diff --git a/test/cli/fuzz-timeout/timeout-0ee5eed9abd34e9d23640a5b82dd724affd05b79 b/test/cli/fuzz-timeout/timeout-0ee5eed9abd34e9d23640a5b82dd724affd05b79 new file mode 100644 index 00000000000..5f9465da55e --- /dev/null +++ b/test/cli/fuzz-timeout/timeout-0ee5eed9abd34e9d23640a5b82dd724affd05b79 @@ -0,0 +1 @@ +;new t() \ No newline at end of file diff --git a/test/cli/fuzz-timeout/timeout-a0b9848dd6e98677a0a96c5fc50ad571ed5a7092 b/test/cli/fuzz-timeout/timeout-a0b9848dd6e98677a0a96c5fc50ad571ed5a7092 new file mode 100644 index 00000000000..2f29da2e360 --- /dev/null +++ b/test/cli/fuzz-timeout/timeout-a0b9848dd6e98677a0a96c5fc50ad571ed5a7092 @@ -0,0 +1,2 @@ +t i(){int +t,?:0::::} \ No newline at end of file diff --git a/test/fixture.h b/test/fixture.h index 7527f3261bd..af227609363 100644 --- a/test/fixture.h +++ b/test/fixture.h @@ -280,7 +280,7 @@ class TestFixture : public ErrorLogger { }; // TODO: most asserts do not actually assert i.e. do not return -#define TEST_CASE( NAME ) do { if (prepareTest(#NAME)) { setVerbose(false); NAME(); teardownTest(); } } while (false) +#define TEST_CASE( NAME ) do { if (prepareTest(#NAME)) { setVerbose(false); try { NAME(); teardownTest(); } catch (...) { assertNoThrowFail(__FILE__, __LINE__); } } } while (false) #define ASSERT( CONDITION ) if (!assert_(__FILE__, __LINE__, (CONDITION))) return #define ASSERT_LOC( CONDITION, FILE_, LINE_ ) assert_(FILE_, LINE_, (CONDITION)) #define CHECK_EQUALS( EXPECTED, ACTUAL ) assertEquals(__FILE__, __LINE__, (EXPECTED), (ACTUAL)) diff --git a/test/testcmdlineparser.cpp b/test/testcmdlineparser.cpp index 5437ca9f013..60a56efbccc 100644 --- a/test/testcmdlineparser.cpp +++ b/test/testcmdlineparser.cpp @@ -334,11 +334,16 @@ class TestCmdlineParser : public TestFixture { TEST_CASE(ruleNotSupported); #endif #ifdef HAVE_RULES - TEST_CASE(ruleFile); + TEST_CASE(ruleFileMulti); + TEST_CASE(ruleFileSingle); TEST_CASE(ruleFileEmpty); TEST_CASE(ruleFileMissing); TEST_CASE(ruleFileInvalid); TEST_CASE(ruleFileNoRoot); + TEST_CASE(ruleFileEmptyElements1); + TEST_CASE(ruleFileEmptyElements2); + TEST_CASE(ruleFileUnknownElement1); + TEST_CASE(ruleFileUnknownElement2); #else TEST_CASE(ruleFileNotSupported); #endif @@ -2147,19 +2152,67 @@ class TestCmdlineParser : public TestFixture { #endif #ifdef HAVE_RULES - void ruleFile() { + void ruleFileMulti() { REDIRECT; ScopedFile file("rule.xml", "\n" "\n" + "toklist1\n" ".+\n" + "\n" + "error\n" + "ruleId1\n" + "ruleSummary1\n" + "\n" + "\n" + "\n" + "toklist2\n" + ".*\n" + "\n" + "warning\n" + "ruleId2\n" + "ruleSummary2\n" + "\n" "\n" ""); const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(2, settings->rules.size()); + auto it = settings->rules.cbegin(); + ASSERT_EQUALS("toklist1", it->tokenlist); + ASSERT_EQUALS(".+", it->pattern); + ASSERT_EQUALS_ENUM(Severity::error, it->severity); + ASSERT_EQUALS("ruleId1", it->id); + ASSERT_EQUALS("ruleSummary1", it->summary); + ++it; + ASSERT_EQUALS("toklist2", it->tokenlist); + ASSERT_EQUALS(".*", it->pattern); + ASSERT_EQUALS_ENUM(Severity::warning, it->severity); + ASSERT_EQUALS("ruleId2", it->id); + ASSERT_EQUALS("ruleSummary2", it->summary); + } + + void ruleFileSingle() { + REDIRECT; + ScopedFile file("rule.xml", + "\n" + "toklist\n" + ".+\n" + "\n" + "error\n" + "ruleId\n" + "ruleSummary\n" + "\n" + "\n"); + const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); ASSERT_EQUALS(1, settings->rules.size()); auto it = settings->rules.cbegin(); + ASSERT_EQUALS("toklist", it->tokenlist); ASSERT_EQUALS(".+", it->pattern); + ASSERT_EQUALS_ENUM(Severity::error, it->severity); + ASSERT_EQUALS("ruleId", it->id); + ASSERT_EQUALS("ruleSummary", it->summary); } void ruleFileEmpty() { @@ -2189,6 +2242,63 @@ class TestCmdlineParser : public TestFixture { ScopedFile file("rule.xml", ""); const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"}; ASSERT_EQUALS_ENUM(CmdLineParser::Result::Success, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS(0, settings->rules.size()); + } + + void ruleFileEmptyElements1() { + REDIRECT; + ScopedFile file("rule.xml", + "" + "" + "" + "" + "" + ); + const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); // do not crash + ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' - a rule is lacking a pattern.\n", logger->str()); + } + + void ruleFileEmptyElements2() { + REDIRECT; + ScopedFile file("rule.xml", + "" + "" + "" + "" + "" + "" + "" + ); + const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); // do not crash + ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' - a rule is lacking a pattern.\n", logger->str()); + } + + void ruleFileUnknownElement1() { + REDIRECT; + ScopedFile file("rule.xml", + "" + "" + "" + ); + const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' - unknown element 'messages' encountered in 'rule'.\n", logger->str()); + } + + void ruleFileUnknownElement2() { + REDIRECT; + ScopedFile file("rule.xml", + "" + "" + "" + "" + "" + ); + const char * const argv[] = {"cppcheck", "--rule-file=rule.xml", "file.cpp"}; + ASSERT_EQUALS_ENUM(CmdLineParser::Result::Fail, parser->parseFromArgs(3, argv)); + ASSERT_EQUALS("cppcheck: error: unable to load rule-file 'rule.xml' - unknown element 'pattern' encountered in 'message'.\n", logger->str()); } #else void ruleFileNotSupported() { diff --git a/test/testcondition.cpp b/test/testcondition.cpp index 868f8a98caa..5c794bbd39c 100644 --- a/test/testcondition.cpp +++ b/test/testcondition.cpp @@ -123,6 +123,7 @@ class TestCondition : public TestFixture { TEST_CASE(compareOutOfTypeRange); TEST_CASE(knownConditionCast); // #9976 TEST_CASE(knownConditionIncrementLoop); // #9808 + TEST_CASE(knownConditionAfterBailout); // #12526 } #define check(...) check_(__FILE__, __LINE__, __VA_ARGS__) @@ -5957,6 +5958,37 @@ class TestCondition : public TestFixture { "}\n"); ASSERT_EQUALS("", errout_str()); } + + void knownConditionAfterBailout() { // #12526 + check( + "#include \n" + "int func()\n" + "{\n" + " return VALUE_1;" + "}\n" + "\n" + "struct S1 {\n" + " bool b{};\n" + "};\n" + "\n" + "struct S {\n" + " void f(const std::list& l) const\n" + " {\n" + " if (mS.b)\n" + " return;\n" + " for (int i : l)\n" + " {\n" + " (void)i;\n" + " if (mS.b)\n" + " continue;\n" + " }\n" + " }\n" + "\n" + " S1 mS;\n" + "};" + ); + ASSERT_EQUALS("[test.cpp:13] -> [test.cpp:18]: (style) Condition 'mS.b' is always false\n", errout_str()); + } }; REGISTER_TEST(TestCondition) diff --git a/test/testgarbage.cpp b/test/testgarbage.cpp index f52ba217473..acb46bfe609 100644 --- a/test/testgarbage.cpp +++ b/test/testgarbage.cpp @@ -253,6 +253,7 @@ class TestGarbage : public TestFixture { TEST_CASE(garbageCode222); // #10763 TEST_CASE(garbageCode223); // #11639 TEST_CASE(garbageCode224); + TEST_CASE(garbageCode225); TEST_CASE(garbageCodeFuzzerClientMode1); // test cases created with the fuzzer client, mode 1 @@ -1746,6 +1747,10 @@ class TestGarbage : public TestFixture { checkCode("void f(){ auto* b = dynamic_cast 0 && *q < 100) {}\n" "}\n"; valueOfTok(code, "&&"); + + code = "void f() { int& a = *&a; }\n"; // #12511 + valueOfTok(code, "="); } void valueFlowHang() { @@ -8468,6 +8473,22 @@ class TestValueFlow : public TestFixture { ASSERT_EQUALS(false, testValueOfX(code, 5U, 0)); } + void valueFlowBailoutIncompleteVar() { // #12526 + bailout( + "int f1() {\n" + " return VALUE_1;\n" + "}\n" + "\n" + "int f2() {\n" + " return VALUE_2;\n" + "}\n" + ); + ASSERT_EQUALS_WITHOUT_LINENUMBERS( + "[test.cpp:2]: (debug) valueFlowConditionExpressions bailout: Skipping function due to incomplete variable VALUE_1\n" + "[test.cpp:6]: (debug) valueFlowConditionExpressions bailout: Skipping function due to incomplete variable VALUE_2\n", + errout_str()); + } + void performanceIfCount() { /*const*/ Settings s(settings); s.performanceValueFlowMaxIfCount = 1; diff --git a/test/testvarid.cpp b/test/testvarid.cpp index f763a0f1207..a6e5e132042 100644 --- a/test/testvarid.cpp +++ b/test/testvarid.cpp @@ -1507,6 +1507,20 @@ class TestVarID : public TestFixture { "6: }\n"; ASSERT_EQUALS(expected, actual); } + + { + const std::string actual = tokenize("void f(int n) {\n" // #12537 + " int n1;\n" + " void g(int is, int n1);\n" + " n1 = n - 1;\n" + "}\n", "test.cpp"); + const char expected[] = "1: void f ( int n@1 ) {\n" + "2: int n1@2 ;\n" + "3: void g ( int is , int n1 ) ;\n" + "4: n1@2 = n@1 - 1 ;\n" + "5: }\n"; + ASSERT_EQUALS(expected, actual); + } } void varid_sizeof() {