Report unknown macros for pattern '%name% %num%'

This commit is contained in:
Daniel Marjamäki 2020-02-22 11:57:09 +01:00
parent a62ddc6edd
commit f07a71e3e1
5 changed files with 105 additions and 10 deletions

View File

@ -4302,7 +4302,7 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
createLinks();
reportUnknownMacrosInNonExecutableScopes();
reportUnknownMacros();
simplifyHeaders();
@ -9285,8 +9285,21 @@ static bool isCPPAttribute(const Token * tok)
return Token::simpleMatch(tok, "[ [") && tok->link() && tok->link()->previous() == tok->linkAt(1);
}
void Tokenizer::reportUnknownMacrosInNonExecutableScopes()
void Tokenizer::reportUnknownMacros()
{
// Report unknown macros used in expressions "%name% %num%"
for (const Token *tok = tokens(); tok; tok = tok->next()) {
if (Token::Match(tok, "%name% %num%")) {
// A keyword is not an unknown macro
if (list.isKeyword(tok->str()))
continue;
if (Token::Match(tok->previous(), "%op%|("))
unknownMacroError(tok);
}
}
// Report unknown macros in non-executable scopes..
for (const Token *tok = tokens(); tok; tok = tok->next()) {
// Skip executable scopes..
if (tok->str() == "{") {
@ -9298,6 +9311,10 @@ void Tokenizer::reportUnknownMacrosInNonExecutableScopes()
}
if (Token::Match(tok, "%name% (") && tok->isUpperCaseName() && Token::simpleMatch(tok->linkAt(1), ") (") && Token::simpleMatch(tok->linkAt(1)->linkAt(1), ") {")) {
// A keyword is not an unknown macro
if (list.isKeyword(tok->str()))
continue;
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()) {

View File

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

View File

@ -43,6 +43,40 @@ TokenList::TokenList(const Settings* settings) :
mIsC(false),
mIsCpp(false)
{
mKeywords.insert("auto");
mKeywords.insert("break");
mKeywords.insert("case");
mKeywords.insert("char");
mKeywords.insert("const");
mKeywords.insert("continue");
mKeywords.insert("default");
mKeywords.insert("do");
mKeywords.insert("double");
mKeywords.insert("else");
mKeywords.insert("enum");
mKeywords.insert("extern");
mKeywords.insert("float");
mKeywords.insert("for");
mKeywords.insert("goto");
mKeywords.insert("if");
mKeywords.insert("inline");
mKeywords.insert("int");
mKeywords.insert("long");
mKeywords.insert("register");
mKeywords.insert("restrict");
mKeywords.insert("return");
mKeywords.insert("short");
mKeywords.insert("signed");
mKeywords.insert("sizeof");
mKeywords.insert("static");
mKeywords.insert("struct");
mKeywords.insert("switch");
mKeywords.insert("typedef");
mKeywords.insert("union");
mKeywords.insert("unsigned");
mKeywords.insert("void");
mKeywords.insert("volatile");
mKeywords.insert("while");
}
TokenList::~TokenList()
@ -90,6 +124,38 @@ int TokenList::appendFileIfNew(const std::string &fileName)
mIsC = mSettings->enforcedLang == Settings::C || (mSettings->enforcedLang == Settings::None && Path::isC(getSourceFilePath()));
mIsCpp = mSettings->enforcedLang == Settings::CPP || (mSettings->enforcedLang == Settings::None && Path::isCPP(getSourceFilePath()));
}
if (mIsCpp) {
mKeywords.insert("catch");
mKeywords.insert("delete");
mKeywords.insert("class");
mKeywords.insert("const_cast");
mKeywords.insert("delete");
mKeywords.insert("dynamic_cast");
mKeywords.insert("explicit");
mKeywords.insert("export");
mKeywords.insert("false");
mKeywords.insert("friend");
mKeywords.insert("mutable");
mKeywords.insert("namespace");
mKeywords.insert("new");
mKeywords.insert("operator");
mKeywords.insert("private");
mKeywords.insert("protected");
mKeywords.insert("public");
mKeywords.insert("reinterpret_cast");
mKeywords.insert("static_cast");
mKeywords.insert("template");
mKeywords.insert("this");
mKeywords.insert("throw");
mKeywords.insert("true");
mKeywords.insert("try");
mKeywords.insert("typeid");
mKeywords.insert("typename");
mKeywords.insert("using");
mKeywords.insert("virtual");
mKeywords.insert("wchar_t");
}
}
return mFiles.size() - 1;
}
@ -140,7 +206,7 @@ void TokenList::addtoken(std::string str, const nonneg int lineno, const nonneg
mTokensFrontBack.back->str(str);
}
if (isCPP() && str == "delete")
if (isKeyword(str))
mTokensFrontBack.back->isKeyword(true);
mTokensFrontBack.back->linenr(lineno);
mTokensFrontBack.back->fileIndex(fileno);
@ -1690,3 +1756,7 @@ void TokenList::simplifyStdType()
}
}
bool TokenList::isKeyword(const std::string &str) const
{
return mKeywords.find(str) != mKeywords.end();
}

View File

@ -188,6 +188,8 @@ public:
void clangSetOrigFiles();
bool isKeyword(const std::string &str) const;
private:
/** Disable copy constructor, no implementation */
@ -208,8 +210,11 @@ private:
/** settings */
const Settings* mSettings;
std::set<std::string> mKeywords;
/** File is known to be C/C++ code */
bool mIsC, mIsCpp;
bool mIsC;
bool mIsCpp;
};
/// @}

View File

@ -467,7 +467,7 @@ private:
TEST_CASE(sizeofAddParentheses);
TEST_CASE(reportUnknownMacrosInNonExecutableScopes);
TEST_CASE(reportUnknownMacros);
// Make sure the Tokenizer::findGarbageCode() does not have false positives
// The TestGarbage ensures that there are true positives
@ -7972,10 +7972,13 @@ 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 reportUnknownMacros() {
const char code1[] = "MY_UNKNOWN_IMP1(IInStream)\n"
"STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) { if (ptr); }";
ASSERT_THROW(tokenizeAndStringify(code1), InternalError);
const char code2[] = "void foo() { dostuff(x 0); }";
ASSERT_THROW(tokenizeAndStringify(code2), InternalError);
}
void findGarbageCode() { // Test Tokenizer::findGarbageCode()