Warn when there is a unknown macro

This commit is contained in:
Daniel Marjamäki 2018-11-13 16:49:02 +01:00
parent 69e7392ce2
commit e6a5e0f752
4 changed files with 27 additions and 15 deletions

View File

@ -4198,12 +4198,15 @@ void Tokenizer::removeMacrosInGlobalScope()
tok->deleteNext();
}
if ((!tok->previous() || Token::Match(tok->previous(), "[;{}]")) &&
Token::Match(tok, "%type%") && tok->isUpperCaseName()) {
if (Token::Match(tok, "%type%") && tok->isUpperCaseName() &&
(!tok->previous() || Token::Match(tok->previous(), "[;{}]") || (tok->previous()->isName() && endsWith(tok->previous()->str(), ':')))) {
const Token *tok2 = tok->next();
if (tok2 && tok2->str() == "(")
tok2 = tok2->link()->next();
if (Token::Match(tok, "%type% (") && Token::Match(tok2, "%type% (") && isFunctionHead(tok2->next(), "{"))
unknownMacroError(tok);
// remove unknown macros before namespace|class|struct|union
if (Token::Match(tok2, "namespace|class|struct|union")) {
// is there a "{" for?
@ -4218,14 +4221,15 @@ void Tokenizer::removeMacrosInGlobalScope()
}
// replace unknown macros before foo(
if (Token::Match(tok2, "%type% (") && isFunctionHead(tok2->next(), "{")) {
std::string typeName;
for (const Token* tok3 = tok; tok3 != tok2; tok3 = tok3->next())
typeName += tok3->str();
Token::eraseTokens(tok, tok2);
tok->str(typeName);
}
/*
if (Token::Match(tok2, "%type% (") && isFunctionHead(tok2->next(), "{")) {
std::string typeName;
for (const Token* tok3 = tok; tok3 != tok2; tok3 = tok3->next())
typeName += tok3->str();
Token::eraseTokens(tok, tok2);
tok->str(typeName);
}
*/
// remove unknown macros before foo::foo(
if (Token::Match(tok2, "%type% :: %type%")) {
const Token *tok3 = tok2;
@ -7916,6 +7920,12 @@ void Tokenizer::syntaxErrorC(const Token *tok, const std::string &what) const
throw InternalError(tok, "Code '"+what+"' is invalid C code. Use --std or --language to configure the language.", InternalError::SYNTAX);
}
void Tokenizer::unknownMacroError(const Token *tok1) const
{
printDebugOutput(0);
throw InternalError(tok1, "There is an unknown macro here somewhere. Configuration is required. If " + tok1->str() + " is a macro then please configure it.", InternalError::SYNTAX);
}
void Tokenizer::unhandled_macro_class_x_y(const Token *tok) const
{
reportError(tok,

View File

@ -598,6 +598,9 @@ public:
/** Syntax error. C++ code in C file. */
void syntaxErrorC(const Token *tok, const std::string &what) const;
/** Warn about unknown macro(s), configuration is recommended */
void unknownMacroError(const Token *tok1) const;
private:
/** Report that there is an unhandled "class x y {" code */

View File

@ -1448,9 +1448,8 @@ private:
const char code[] = "typedef char (* type1)[10];\n"
"LOCAL(type1) foo() { }";
// this is invalid C so just make sure it doesn't generate an internal error
checkSimplifyTypedef(code);
ASSERT_EQUALS("", errout.str());
// this is invalid C, assert that an "unknown macro" warning is written
ASSERT_THROW(checkSimplifyTypedef(code), InternalError);
}
}

View File

@ -6155,8 +6155,8 @@ private:
ASSERT_EQUALS("; foo :: foo ( ) { }",
tokenizeAndStringify("; AB(foo*) foo::foo() { }"));
// #4834
ASSERT_EQUALS("A(B) foo ( ) { }", tokenizeAndStringify("A(B) foo() {}"));
// #4834 - syntax error
ASSERT_THROW(tokenizeAndStringify("A(B) foo() {}"), InternalError);
// #3855
ASSERT_EQUALS("; class foo { }",