Tokenizer: Throw unknownMacro in non-executable scope

This commit is contained in:
Daniel Marjamäki 2020-02-19 21:11:54 +01:00
parent bdf715b3e5
commit 6f6f9dd5bc
4 changed files with 39 additions and 4 deletions

View File

@ -4302,6 +4302,8 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
createLinks();
reportUnknownMacrosInNonExecutableScopes();
simplifyHeaders();
// Remove __asm..
@ -9283,6 +9285,29 @@ static bool isCPPAttribute(const Token * tok)
return Token::simpleMatch(tok, "[ [") && tok->link() && tok->link()->previous() == tok->linkAt(1);
}
void Tokenizer::reportUnknownMacrosInNonExecutableScopes()
{
for (const Token *tok = tokens(); tok; tok = tok->next()) {
// Skip executable scopes..
if (tok->str() == "{") {
const Token *prev = tok->previous();
while (prev && prev->isName())
prev = prev->previous();
if (prev && prev->str() == ")")
tok = tok->link();
}
if (Token::Match(tok, "%name% (") && tok->isUpperCaseName() && Token::simpleMatch(tok->linkAt(1), ") (") && Token::simpleMatch(tok->linkAt(1)->linkAt(1), ") {")) {
const Token *bodyStart = tok->linkAt(1)->linkAt(1)->tokAt(2);
const Token *bodyEnd = tok->link();
for (const Token *tok2 = bodyStart; tok2 && tok2 != bodyEnd; tok2 = tok2->next()) {
if (Token::Match(tok2, "if|switch|for|while|return"))
unknownMacroError(tok);
}
}
}
}
void Tokenizer::findGarbageCode() const
{
const bool isCPP11 = isCPP() && mSettings->standards.cpp >= Standards::CPP11;

View File

@ -634,6 +634,9 @@ private:
*/
void validate() const;
/** Detect unknown macros and throw unknownMacro */
void reportUnknownMacrosInNonExecutableScopes();
/** Detect garbage code and call syntaxError() if found. */
void findGarbageCode() const;

View File

@ -2537,10 +2537,9 @@ private:
void symboldatabase5() {
// ticket #2178 - segmentation fault
check("int CL_INLINE_DECL(integer_decode_float) (int x) {\n"
" return (sign ? cl_I() : 0);\n"
"}");
ASSERT_EQUALS("", errout.str());
ASSERT_THROW(check("int CL_INLINE_DECL(integer_decode_float) (int x) {\n"
" return (sign ? cl_I() : 0);\n"
"}"), InternalError);
}
void symboldatabase6() {

View File

@ -466,6 +466,8 @@ private:
TEST_CASE(sizeofAddParentheses);
TEST_CASE(reportUnknownMacrosInNonExecutableScopes);
// Make sure the Tokenizer::findGarbageCode() does not have false positives
// The TestGarbage ensures that there are true positives
TEST_CASE(findGarbageCode);
@ -7959,6 +7961,12 @@ private:
ASSERT_EQUALS("sizeof ( a ) > sizeof ( & main ) ;", tokenizeAndStringify("sizeof a > sizeof &main;"));
}
void reportUnknownMacrosInNonExecutableScopes() {
const char code[] = "MY_UNKNOWN_IMP1(IInStream)\n"
"STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) { if (ptr); }";
ASSERT_THROW(tokenizeAndStringify(code), InternalError);
}
void findGarbageCode() { // Test Tokenizer::findGarbageCode()
// before if|for|while|switch
ASSERT_NO_THROW(tokenizeAndStringify("void f() { do switch (a) {} while (1); }"))