Skip to content

Commit 1937ce7

Browse files
author
Daniel Marjamäki
committed
Fix #14959 (Warning hash for token-based warnings)
1 parent b702ead commit 1937ce7

2 files changed

Lines changed: 61 additions & 2 deletions

File tree

lib/errorlogger.cpp

Lines changed: 59 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,8 @@ ErrorMessage::ErrorMessage(const std::list<const Token*>& callstack, const Token
106106
file0 = list->getFiles()[0];
107107

108108
setmsg(msg);
109+
110+
calculateWarningHash(callstack);
109111
}
110112

111113

@@ -126,7 +128,7 @@ ErrorMessage::ErrorMessage(const std::list<const Token*>& callstack, const Token
126128

127129
setmsg(msg);
128130

129-
// hash = calculateWarningHash(list, hashWarning.str());
131+
calculateWarningHash(callstack);
130132
}
131133

132134
ErrorMessage::ErrorMessage(ErrorPath errorPath, const TokenList *tokenList, Severity severity, const char id[], const std::string &msg, const CWE &cwe, Certainty certainty)
@@ -159,7 +161,11 @@ ErrorMessage::ErrorMessage(ErrorPath errorPath, const TokenList *tokenList, Seve
159161

160162
setmsg(msg);
161163

162-
// hash = calculateWarningHash(tokenList, hashWarning.str());
164+
std::list<const Token*> callstack;
165+
for (const ErrorPathItem& e: errorPath) {
166+
callstack.push_back(e.first);
167+
}
168+
calculateWarningHash(callstack);
163169
}
164170

165171
// TODO: improve errorhandling?
@@ -244,6 +250,57 @@ void ErrorMessage::setmsg(const std::string &msg)
244250
}
245251
}
246252

253+
void ErrorMessage::calculateWarningHash(const std::list<const Token*>& callstack)
254+
{
255+
if (callstack.empty())
256+
return;
257+
// Calculate a hash for this warning message
258+
std::string hashString;
259+
for (const Token* tok: callstack) {
260+
if (!tok)
261+
continue;
262+
if (tok->scope()->isExecutable()) {
263+
// Executable scope => include all tokens in the function => if the
264+
// function is changed the hash is changed
265+
for (const Token* t = tok; t; t = t->previous()) {
266+
if (!t->scope()->isExecutable())
267+
break;
268+
hashString += " " + t->str();
269+
}
270+
for (const Token* t = tok->next(); t; t = t->next()) {
271+
if (!t->scope()->isExecutable())
272+
break;
273+
hashString += " " + t->str();
274+
}
275+
} else {
276+
// Non executable scope => include tokens in current statement => if the current statement is changed the hash is changed
277+
for (const Token* t = tok; t; t = t->previous()) {
278+
if (t->str() == ";")
279+
break;
280+
if (t->scope() != tok->scope()) // stop on {} unless its an initializer
281+
break;
282+
hashString += " " + t->str();
283+
}
284+
for (const Token* t = tok->next(); t; t = t->next()) {
285+
hashString += " " + t->str();
286+
if (t->str() == ";")
287+
break;
288+
if (t->scope() != tok->scope()) // stop on {} unless its an initializer
289+
break;
290+
}
291+
}
292+
}
293+
294+
hashString = id + '\n' + mShortMessage + '\n' + hashString;
295+
296+
// hash algorithm: sdbm
297+
// any hash algorithm can be used but it has to be the same hash on different platforms and compilers
298+
hash = 0;
299+
for (auto c: hashString) {
300+
hash = c + (hash << 6) + (hash << 16) - hash;
301+
}
302+
}
303+
247304
static void serializeString(std::string &oss, const std::string & str)
248305
{
249306
oss += std::to_string(str.length());

lib/errorlogger.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -209,6 +209,8 @@ class CPPCHECKLIB ErrorMessage {
209209
private:
210210
static std::string fixInvalidChars(const std::string& raw);
211211

212+
void calculateWarningHash(const std::list<const Token*>& callstack);
213+
212214
/** Short message */
213215
std::string mShortMessage;
214216

0 commit comments

Comments
 (0)