Tokenizer: Add --check-config warning for macro with semicolon in argument
This commit is contained in:
parent
c16d82d729
commit
8ffed6862d
|
@ -3336,6 +3336,8 @@ bool Tokenizer::simplifyTokenList1(const char FileName[])
|
||||||
if (const Token *garbage = findGarbageCode())
|
if (const Token *garbage = findGarbageCode())
|
||||||
syntaxError(garbage);
|
syntaxError(garbage);
|
||||||
|
|
||||||
|
checkConfiguration();
|
||||||
|
|
||||||
// if (x) MACRO() ..
|
// if (x) MACRO() ..
|
||||||
for (const Token *tok = list.front(); tok; tok = tok->next()) {
|
for (const Token *tok = list.front(); tok; tok = tok->next()) {
|
||||||
if (Token::simpleMatch(tok, "if (")) {
|
if (Token::simpleMatch(tok, "if (")) {
|
||||||
|
@ -7638,6 +7640,14 @@ void Tokenizer::unhandled_macro_class_x_y(const Token *tok) const
|
||||||
tok->strAt(3) + "' is not handled. You can use -I or --include to add handling of this code.");
|
tok->strAt(3) + "' is not handled. You can use -I or --include to add handling of this code.");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Tokenizer::macroWithSemicolonError(const Token *tok, const std::string ¯oName) const
|
||||||
|
{
|
||||||
|
reportError(tok,
|
||||||
|
Severity::information,
|
||||||
|
"macroWithSemicolon",
|
||||||
|
"Ensure that '" + macroName + "' is defined either using -I, --include or -D.");
|
||||||
|
}
|
||||||
|
|
||||||
void Tokenizer::cppcheckError(const Token *tok) const
|
void Tokenizer::cppcheckError(const Token *tok) const
|
||||||
{
|
{
|
||||||
printDebugOutput(0);
|
printDebugOutput(0);
|
||||||
|
@ -8004,6 +8014,25 @@ void Tokenizer::simplifyComma()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Tokenizer::checkConfiguration() const
|
||||||
|
{
|
||||||
|
if (!_settings->checkConfiguration)
|
||||||
|
return;
|
||||||
|
for (const Token *tok = tokens(); tok; tok = tok->next()) {
|
||||||
|
if (!Token::Match(tok, "%name% ("))
|
||||||
|
continue;
|
||||||
|
if (Token::Match(tok, "if|for|while|switch"))
|
||||||
|
continue;
|
||||||
|
for (const Token *tok2 = tok->tokAt(2); tok2 && tok2->str() != ")"; tok2 = tok2->next()) {
|
||||||
|
if (tok2->str() == ";") {
|
||||||
|
macroWithSemicolonError(tok, tok->str());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (Token::Match(tok2, "(|{"))
|
||||||
|
tok2 = tok2->link();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Tokenizer::validateC() const
|
void Tokenizer::validateC() const
|
||||||
{
|
{
|
||||||
|
|
|
@ -576,6 +576,10 @@ private:
|
||||||
/** Report that there is an unhandled "class x y {" code */
|
/** Report that there is an unhandled "class x y {" code */
|
||||||
void unhandled_macro_class_x_y(const Token *tok) const;
|
void unhandled_macro_class_x_y(const Token *tok) const;
|
||||||
|
|
||||||
|
/** Check configuration (unknown macros etc) */
|
||||||
|
void checkConfiguration() const;
|
||||||
|
void macroWithSemicolonError(const Token *tok, const std::string ¯oName) const;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Is there C++ code in C file?
|
* Is there C++ code in C file?
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -457,6 +457,9 @@ private:
|
||||||
// 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
|
||||||
TEST_CASE(findGarbageCode);
|
TEST_CASE(findGarbageCode);
|
||||||
|
|
||||||
|
// --check-config
|
||||||
|
TEST_CASE(checkConfiguration);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string tokenizeAndStringify(const char code[], bool simplify = false, bool expand = true, Settings::PlatformType platform = Settings::Native, const char* filename = "test.cpp", bool cpp11 = true) {
|
std::string tokenizeAndStringify(const char code[], bool simplify = false, bool expand = true, Settings::PlatformType platform = Settings::Native, const char* filename = "test.cpp", bool cpp11 = true) {
|
||||||
|
@ -8250,6 +8253,24 @@ private:
|
||||||
// after (expr)
|
// after (expr)
|
||||||
ASSERT_NO_THROW(tokenizeAndStringify("void f() { switch (a) int b; }"));
|
ASSERT_NO_THROW(tokenizeAndStringify("void f() { switch (a) int b; }"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void checkConfig(const char code[]) {
|
||||||
|
errout.str("");
|
||||||
|
|
||||||
|
Settings s;
|
||||||
|
s.checkConfiguration = true;
|
||||||
|
|
||||||
|
// tokenize..
|
||||||
|
Tokenizer tokenizer(&s, this);
|
||||||
|
std::istringstream istr(code);
|
||||||
|
tokenizer.tokenize(istr, "test.cpp");
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkConfiguration() {
|
||||||
|
checkConfig("void f() { DEBUG(x();y()); }");
|
||||||
|
ASSERT_EQUALS("[test.cpp:1]: (information) Ensure that 'DEBUG' is defined either using -I, --include or -D.\n", errout.str());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_TEST(TestTokenizer)
|
REGISTER_TEST(TestTokenizer)
|
||||||
|
|
Loading…
Reference in New Issue