Fixed #10196 ("Unhandled char constant 'x'" with non-standard escape character)

This commit is contained in:
Daniel Marjamäki 2021-05-08 11:20:29 +02:00
parent 0a84ad874c
commit abb4200316
5 changed files with 42 additions and 12 deletions

View File

@ -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 loc(tokenizer.list.getSourceFilePath(), 0, 0);
ErrorMessage::FileLocation loc2(filename, 0, 0); ErrorMessage::FileLocation loc2(filename, 0, 0);
locationList.push_back(loc2); locationList.push_back(loc2);
locationList.push_back(loc); if (filename != tokenizer.list.getSourceFilePath())
locationList.push_back(loc);
} }
ErrorMessage errmsg(locationList, ErrorMessage errmsg(locationList,
tokenizer.list.getSourceFilePath(), tokenizer.list.getSourceFilePath(),

View File

@ -505,13 +505,8 @@ MathLib::bigint MathLib::toLongNumber(const std::string & str)
return static_cast<bigint>(doubleval); return static_cast<bigint>(doubleval);
} }
if (isCharLiteral(str)) { if (isCharLiteral(str))
try { return simplecpp::characterLiteralToLL(str);
return simplecpp::characterLiteralToLL(str);
} catch (const std::exception& e) {
throw InternalError(nullptr, "Internal Error. MathLib::toLongNumber: characterLiteralToLL(" + str + ") => " + e.what());
}
}
try { try {
const biguint ret = std::stoull(str, nullptr, 10); const biguint ret = std::stoull(str, nullptr, 10);

View File

@ -2766,6 +2766,19 @@ bool Tokenizer::simplifyTokens1(const std::string &configuration)
ValueFlow::setValues(&list, mSymbolDatabase, mErrorLogger, mSettings); 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(); mSymbolDatabase->setArrayDimensionsUsingValueFlow();
printDebugOutput(1); printDebugOutput(1);
@ -9528,6 +9541,21 @@ void Tokenizer::cppcheckError(const Token *tok) const
printDebugOutput(0); printDebugOutput(0);
throw InternalError(tok, "Analysis failed. If the code is valid then please report this failure.", InternalError::INTERNAL); 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 * Helper function to check whether number is equal to integer constant X
* or floating point pattern X.0 * or floating point pattern X.0

View File

@ -652,6 +652,8 @@ public:
/** Warn about unknown macro(s), configuration is recommended */ /** Warn about unknown macro(s), configuration is recommended */
NORETURN void unknownMacroError(const Token *tok1) const; NORETURN void unknownMacroError(const Token *tok1) const;
void unhandledCharLiteral(const Token *tok, const std::string& msg) const;
private: private:
/** Report that there is an unhandled "class x y {" code */ /** Report that there is an unhandled "class x y {" code */

View File

@ -913,10 +913,14 @@ size_t ValueFlow::getSizeOf(const ValueType &vt, const Settings *settings)
static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, bool cpp) static Token * valueFlowSetConstantValue(Token *tok, const Settings *settings, bool cpp)
{ {
if ((tok->isNumber() && MathLib::isInt(tok->str())) || (tok->tokType() == Token::eChar)) { if ((tok->isNumber() && MathLib::isInt(tok->str())) || (tok->tokType() == Token::eChar)) {
ValueFlow::Value value(MathLib::toLongNumber(tok->str())); try {
if (!tok->isTemplateArg()) ValueFlow::Value value(MathLib::toLongNumber(tok->str()));
value.setKnown(); if (!tok->isTemplateArg())
setTokenValue(tok, value, settings); value.setKnown();
setTokenValue(tok, value, settings);
} catch (const std::exception &e) {
// Bad character literal
}
} else if (tok->isNumber() && MathLib::isFloat(tok->str())) { } else if (tok->isNumber() && MathLib::isFloat(tok->str())) {
ValueFlow::Value value; ValueFlow::Value value;
value.valueType = ValueFlow::Value::ValueType::FLOAT; value.valueType = ValueFlow::Value::ValueType::FLOAT;