From abb42003164e4f610ecfdc50f193d43bf44b8dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Sat, 8 May 2021 11:20:29 +0200 Subject: [PATCH] Fixed #10196 ("Unhandled char constant 'x'" with non-standard escape character) --- lib/cppcheck.cpp | 3 ++- lib/mathlib.cpp | 9 ++------- lib/tokenize.cpp | 28 ++++++++++++++++++++++++++++ lib/tokenize.h | 2 ++ lib/valueflow.cpp | 12 ++++++++---- 5 files changed, 42 insertions(+), 12 deletions(-) diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index a96acf1cb..c87098b6d 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -835,7 +835,8 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string ErrorMessage::FileLocation loc(tokenizer.list.getSourceFilePath(), 0, 0); ErrorMessage::FileLocation loc2(filename, 0, 0); locationList.push_back(loc2); - locationList.push_back(loc); + if (filename != tokenizer.list.getSourceFilePath()) + locationList.push_back(loc); } ErrorMessage errmsg(locationList, tokenizer.list.getSourceFilePath(), diff --git a/lib/mathlib.cpp b/lib/mathlib.cpp index 7d70e1e1f..6f98e4473 100644 --- a/lib/mathlib.cpp +++ b/lib/mathlib.cpp @@ -505,13 +505,8 @@ MathLib::bigint MathLib::toLongNumber(const std::string & str) return static_cast(doubleval); } - if (isCharLiteral(str)) { - try { - return simplecpp::characterLiteralToLL(str); - } catch (const std::exception& e) { - throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: characterLiteralToLL(" + str + ") => " + e.what()); - } - } + if (isCharLiteral(str)) + return simplecpp::characterLiteralToLL(str); try { const biguint ret = std::stoull(str, nullptr, 10); diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 393cc2276..9887388b6 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -2766,6 +2766,19 @@ bool Tokenizer::simplifyTokens1(const std::string &configuration) ValueFlow::setValues(&list, mSymbolDatabase, mErrorLogger, mSettings); } + // Warn about unhandled character literals + if (mSettings->severity.isEnabled(Severity::information)) { + for (const Token *tok = tokens(); tok; tok = tok->next()) { + if (tok->tokType() == Token::eChar && tok->values().empty()) { + try { + simplecpp::characterLiteralToLL(tok->str()); + } catch (const std::exception &e) { + unhandledCharLiteral(tok, e.what()); + } + } + } + } + mSymbolDatabase->setArrayDimensionsUsingValueFlow(); printDebugOutput(1); @@ -9528,6 +9541,21 @@ void Tokenizer::cppcheckError(const Token *tok) const printDebugOutput(0); throw InternalError(tok, "Analysis failed. If the code is valid then please report this failure.", InternalError::INTERNAL); } + +void Tokenizer::unhandledCharLiteral(const Token *tok, const std::string& msg) const +{ + std::string s = tok ? (" " + tok->str()) : ""; + for (int i = 0; i < s.size(); ++i) { + if ((unsigned char)s[i] >= 0x80) + s.clear(); + } + + reportError(tok, + Severity::information, + "cppcheckUnhandledChar", + "Character literal" + s + " is not handled. " + msg); +} + /** * Helper function to check whether number is equal to integer constant X * or floating point pattern X.0 diff --git a/lib/tokenize.h b/lib/tokenize.h index c17f4b829..1780a7f97 100644 --- a/lib/tokenize.h +++ b/lib/tokenize.h @@ -652,6 +652,8 @@ public: /** Warn about unknown macro(s), configuration is recommended */ NORETURN void unknownMacroError(const Token *tok1) const; + void unhandledCharLiteral(const Token *tok, const std::string& msg) const; + private: /** Report that there is an unhandled "class x y {" code */ diff --git a/lib/valueflow.cpp b/lib/valueflow.cpp index 9cc79b487..2f389e095 100644 --- a/lib/valueflow.cpp +++ b/lib/valueflow.cpp @@ -913,10 +913,14 @@ size_t ValueFlow::getSizeOf(const ValueType &vt, const Settings *settings) static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, bool cpp) { if ((tok->isNumber() && MathLib::isInt(tok->str())) || (tok->tokType() == Token::eChar)) { - ValueFlow::Value value(MathLib::toLongNumber(tok->str())); - if (!tok->isTemplateArg()) - value.setKnown(); - setTokenValue(tok, value, settings); + try { + ValueFlow::Value value(MathLib::toLongNumber(tok->str())); + if (!tok->isTemplateArg()) + value.setKnown(); + setTokenValue(tok, value, settings); + } catch (const std::exception &e) { + // Bad character literal + } } else if (tok->isNumber() && MathLib::isFloat(tok->str())) { ValueFlow::Value value; value.valueType = ValueFlow::Value::ValueType::FLOAT;