@@ -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
132134ErrorMessage::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+
247304static void serializeString (std::string &oss, const std::string & str)
248305{
249306 oss += std::to_string (str.length ());
0 commit comments