Merge pull request #711 from Dmitry-Me/moreInterlockedCases

Detect more non-interlocked accesses
This commit is contained in:
PKEuS 2015-12-02 14:13:53 +01:00
commit 423b254772
2 changed files with 89 additions and 0 deletions

View File

@ -2418,6 +2418,24 @@ void CheckOther::checkInterlockedDecrement()
(Token::Match(checkStartTok, "%name% %comp% 0 )") && checkStartTok->str() == interlockedVarTok->str())) { (Token::Match(checkStartTok, "%name% %comp% 0 )") && checkStartTok->str() == interlockedVarTok->str())) {
raceAfterInterlockedDecrementError(checkStartTok); raceAfterInterlockedDecrementError(checkStartTok);
} }
} else if (Token::Match(tok, "if ( ::| InterlockedDecrement ( & %name%")) {
const Token* condEnd = tok->next()->link();
const Token* funcTok = tok->tokAt(2);
const Token* firstAccessTok = funcTok->str() == "::" ? funcTok->tokAt(4) : funcTok->tokAt(3);
if (condEnd && condEnd->next() && condEnd->next()->link()) {
const Token* ifEndTok = condEnd->next()->link();
if (Token::Match(ifEndTok, "} return %name%")) {
const Token* secondAccessTok = ifEndTok->tokAt(2);
if (secondAccessTok->str() == firstAccessTok->str()) {
raceAfterInterlockedDecrementError(secondAccessTok);
}
} else if (Token::Match(ifEndTok, "} else { return %name%")) {
const Token* secondAccessTok = ifEndTok->tokAt(4);
if (secondAccessTok->str() == firstAccessTok->str()) {
raceAfterInterlockedDecrementError( secondAccessTok );
}
}
}
} }
} }
} }

View File

@ -5971,6 +5971,77 @@ private:
" destroy;\n" " destroy;\n"
"}\n"); "}\n");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
checkInterlockedDecrement(
"int f() {\n"
" int counter = 0;\n"
" if (InterlockedDecrement(&counter) == 0) {\n"
" destroy();\n"
" return 0;\n"
" } else {\n"
" return counter;\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout.str());
checkInterlockedDecrement(
"int f() {\n"
" int counter = 0;\n"
" if (::InterlockedDecrement(&counter) == 0) {\n"
" destroy();\n"
" return 0;\n"
" } else {\n"
" return counter;\n"
" }\n"
"}\n");
ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout.str());
checkInterlockedDecrement(
"int f() {\n"
" int counter = 0;\n"
" if (InterlockedDecrement(&counter) == 0) {\n"
" destroy();\n"
" return 0;\n"
" }\n"
" return counter;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout.str());
checkInterlockedDecrement(
"int f() {\n"
" int counter = 0;\n"
" if (::InterlockedDecrement(&counter) == 0) {\n"
" destroy();\n"
" return 0;\n"
" }\n"
" return counter;\n"
"}\n");
ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout.str());
checkInterlockedDecrement(
"int f() {\n"
" int counter = 0;\n"
" if (InterlockedDecrement(&counter) == 0) {\n"
" destroy();\n"
" return 0;\n"
" } else\n"
" return counter;\n"
" \n"
"}\n");
ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout.str());
checkInterlockedDecrement(
"int f() {\n"
" int counter = 0;\n"
" if (::InterlockedDecrement(&counter) == 0) {\n"
" destroy();\n"
" return 0;\n"
" } else\n"
" return counter;\n"
" \n"
"}\n");
ASSERT_EQUALS("[test.cpp:7]: (error) Race condition: non-interlocked access after InterlockedDecrement(). Use InterlockedDecrement() return value instead.\n", errout.str());
} }
void testUnusedLabel() { void testUnusedLabel() {