Report unknown macros for pattern '%name% %num%'
This commit is contained in:
parent
a62ddc6edd
commit
f07a71e3e1
|
@ -4302,7 +4302,7 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
|
||||||
|
|
||||||
createLinks();
|
createLinks();
|
||||||
|
|
||||||
reportUnknownMacrosInNonExecutableScopes();
|
reportUnknownMacros();
|
||||||
|
|
||||||
simplifyHeaders();
|
simplifyHeaders();
|
||||||
|
|
||||||
|
@ -9285,8 +9285,21 @@ static bool isCPPAttribute(const Token * tok)
|
||||||
return Token::simpleMatch(tok, "[ [") && tok->link() && tok->link()->previous() == tok->linkAt(1);
|
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()) {
|
for (const Token *tok = tokens(); tok; tok = tok->next()) {
|
||||||
// Skip executable scopes..
|
// Skip executable scopes..
|
||||||
if (tok->str() == "{") {
|
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), ") {")) {
|
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 *bodyStart = tok->linkAt(1)->linkAt(1)->tokAt(2);
|
||||||
const Token *bodyEnd = tok->link();
|
const Token *bodyEnd = tok->link();
|
||||||
for (const Token *tok2 = bodyStart; tok2 && tok2 != bodyEnd; tok2 = tok2->next()) {
|
for (const Token *tok2 = bodyStart; tok2 && tok2 != bodyEnd; tok2 = tok2->next()) {
|
||||||
|
|
|
@ -635,7 +635,7 @@ private:
|
||||||
void validate() const;
|
void validate() const;
|
||||||
|
|
||||||
/** Detect unknown macros and throw unknownMacro */
|
/** Detect unknown macros and throw unknownMacro */
|
||||||
void reportUnknownMacrosInNonExecutableScopes();
|
void reportUnknownMacros();
|
||||||
|
|
||||||
/** Detect garbage code and call syntaxError() if found. */
|
/** Detect garbage code and call syntaxError() if found. */
|
||||||
void findGarbageCode() const;
|
void findGarbageCode() const;
|
||||||
|
|
|
@ -43,6 +43,40 @@ TokenList::TokenList(const Settings* settings) :
|
||||||
mIsC(false),
|
mIsC(false),
|
||||||
mIsCpp(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()
|
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()));
|
mIsC = mSettings->enforcedLang == Settings::C || (mSettings->enforcedLang == Settings::None && Path::isC(getSourceFilePath()));
|
||||||
mIsCpp = mSettings->enforcedLang == Settings::CPP || (mSettings->enforcedLang == Settings::None && Path::isCPP(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;
|
return mFiles.size() - 1;
|
||||||
}
|
}
|
||||||
|
@ -140,7 +206,7 @@ void TokenList::addtoken(std::string str, const nonneg int lineno, const nonneg
|
||||||
mTokensFrontBack.back->str(str);
|
mTokensFrontBack.back->str(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCPP() && str == "delete")
|
if (isKeyword(str))
|
||||||
mTokensFrontBack.back->isKeyword(true);
|
mTokensFrontBack.back->isKeyword(true);
|
||||||
mTokensFrontBack.back->linenr(lineno);
|
mTokensFrontBack.back->linenr(lineno);
|
||||||
mTokensFrontBack.back->fileIndex(fileno);
|
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();
|
||||||
|
}
|
||||||
|
|
|
@ -188,6 +188,8 @@ public:
|
||||||
|
|
||||||
void clangSetOrigFiles();
|
void clangSetOrigFiles();
|
||||||
|
|
||||||
|
bool isKeyword(const std::string &str) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/** Disable copy constructor, no implementation */
|
/** Disable copy constructor, no implementation */
|
||||||
|
@ -208,8 +210,11 @@ private:
|
||||||
/** settings */
|
/** settings */
|
||||||
const Settings* mSettings;
|
const Settings* mSettings;
|
||||||
|
|
||||||
|
std::set<std::string> mKeywords;
|
||||||
|
|
||||||
/** File is known to be C/C++ code */
|
/** File is known to be C/C++ code */
|
||||||
bool mIsC, mIsCpp;
|
bool mIsC;
|
||||||
|
bool mIsCpp;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
|
@ -467,7 +467,7 @@ private:
|
||||||
|
|
||||||
TEST_CASE(sizeofAddParentheses);
|
TEST_CASE(sizeofAddParentheses);
|
||||||
|
|
||||||
TEST_CASE(reportUnknownMacrosInNonExecutableScopes);
|
TEST_CASE(reportUnknownMacros);
|
||||||
|
|
||||||
// Make sure the Tokenizer::findGarbageCode() does not have false positives
|
// Make sure the Tokenizer::findGarbageCode() does not have false positives
|
||||||
// The TestGarbage ensures that there are true 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;"));
|
ASSERT_EQUALS("sizeof ( a ) > sizeof ( & main ) ;", tokenizeAndStringify("sizeof a > sizeof &main;"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void reportUnknownMacrosInNonExecutableScopes() {
|
void reportUnknownMacros() {
|
||||||
const char code[] = "MY_UNKNOWN_IMP1(IInStream)\n"
|
const char code1[] = "MY_UNKNOWN_IMP1(IInStream)\n"
|
||||||
"STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) { if (ptr); }";
|
"STDMETHOD(Read)(void *data, UInt32 size, UInt32 *processedSize) { if (ptr); }";
|
||||||
ASSERT_THROW(tokenizeAndStringify(code), InternalError);
|
ASSERT_THROW(tokenizeAndStringify(code1), InternalError);
|
||||||
|
|
||||||
|
const char code2[] = "void foo() { dostuff(x 0); }";
|
||||||
|
ASSERT_THROW(tokenizeAndStringify(code2), InternalError);
|
||||||
}
|
}
|
||||||
|
|
||||||
void findGarbageCode() { // Test Tokenizer::findGarbageCode()
|
void findGarbageCode() { // Test Tokenizer::findGarbageCode()
|
||||||
|
|
Loading…
Reference in New Issue