Fixed #3425 (False positive: Null pointer dereference (pointer is checked in macro))
This commit is contained in:
parent
772b8cc37d
commit
2bb5de4c89
|
@ -615,7 +615,7 @@ void CheckNullPointer::nullPointerStructByDeRefAndChec()
|
|||
|
||||
// Check if pointer is null.
|
||||
// TODO: false negatives for "if (!p || .."
|
||||
else if (Token::Match(tok2, "if ( !| %varid% )|&&", varid1)) {
|
||||
else if (!tok2->isExpandedMacro() && Token::Match(tok2, "if ( !| %varid% )|&&", varid1)) {
|
||||
// Is this variable a pointer?
|
||||
if (var->isPointer())
|
||||
nullPointerError(tok1, varname, tok2->linenr(), inconclusive);
|
||||
|
@ -637,7 +637,7 @@ void CheckNullPointer::nullPointerByDeRefAndChec()
|
|||
// - logical operators
|
||||
// - while
|
||||
const Token* const tok = i->classDef;
|
||||
if (i->type == Scope::eIf && tok && Token::Match(tok->previous(), "; if ( !| %var% )|%oror%|&&")) {
|
||||
if (i->type == Scope::eIf && tok && !tok->isExpandedMacro() && Token::Match(tok->previous(), "; if ( !| %var% )|%oror%|&&")) {
|
||||
const Token * vartok = tok->tokAt(2);
|
||||
if (vartok->str() == "!")
|
||||
vartok = vartok->next();
|
||||
|
@ -758,7 +758,7 @@ void CheckNullPointer::nullPointerByCheckAndDeRef()
|
|||
// Check if pointer is NULL and then dereference it..
|
||||
|
||||
for (const Token *tok = _tokenizer->tokens(); tok; tok = tok->next()) {
|
||||
if (Token::simpleMatch(tok, "if (")) {
|
||||
if (Token::simpleMatch(tok, "if (") && !tok->isExpandedMacro()) {
|
||||
// TODO: investigate false negatives:
|
||||
// - handle "while"?
|
||||
// - if there are logical operators
|
||||
|
|
|
@ -2741,7 +2741,7 @@ std::string Preprocessor::expandMacros(const std::string &code, std::string file
|
|||
macrocode.append(1,' ');
|
||||
|
||||
// insert expanded macro code
|
||||
line.insert(pos1, macrocode);
|
||||
line.insert(pos1, "$" + macrocode);
|
||||
|
||||
// position = start position.
|
||||
pos = pos1;
|
||||
|
|
|
@ -42,6 +42,7 @@ Token::Token(Token **t) :
|
|||
_isLong(false),
|
||||
_isUnused(false),
|
||||
_isStandardType(false),
|
||||
_isExpandedMacro(false),
|
||||
_varId(0),
|
||||
_fileIndex(0),
|
||||
_linenr(0),
|
||||
|
@ -148,6 +149,7 @@ void Token::deleteThis()
|
|||
_isLong = _next->_isLong;
|
||||
_isUnused = _next->_isUnused;
|
||||
_isStandardType = _next->_isStandardType;
|
||||
_isExpandedMacro = _next->_isExpandedMacro;
|
||||
_varId = _next->_varId;
|
||||
_fileIndex = _next->_fileIndex;
|
||||
_linenr = _next->_linenr;
|
||||
|
|
|
@ -231,6 +231,13 @@ public:
|
|||
}
|
||||
bool isStandardType() const;
|
||||
|
||||
bool isExpandedMacro() const {
|
||||
return _isExpandedMacro;
|
||||
}
|
||||
void setExpandedMacro(bool m) {
|
||||
_isExpandedMacro = m;
|
||||
}
|
||||
|
||||
static const Token *findsimplematch(const Token *tok, const char pattern[]);
|
||||
static const Token *findsimplematch(const Token *tok, const char pattern[], const Token *end);
|
||||
static const Token *findmatch(const Token *tok, const char pattern[], unsigned int varId = 0);
|
||||
|
@ -448,6 +455,7 @@ private:
|
|||
bool _isLong;
|
||||
bool _isUnused;
|
||||
bool _isStandardType;
|
||||
bool _isExpandedMacro;
|
||||
unsigned int _varId;
|
||||
unsigned int _fileIndex;
|
||||
unsigned int _linenr;
|
||||
|
|
|
@ -245,6 +245,7 @@ Token *Tokenizer::copyTokens(Token *dest, const Token *first, const Token *last)
|
|||
tok2->isPointerCompare(tok->isPointerCompare());
|
||||
tok2->isLong(tok->isLong());
|
||||
tok2->isUnused(tok->isUnused());
|
||||
tok2->setExpandedMacro(tok->isExpandedMacro());
|
||||
tok2->varId(tok->varId());
|
||||
|
||||
// Check for links and fix them up
|
||||
|
@ -287,8 +288,19 @@ void Tokenizer::createTokens(std::istream &code)
|
|||
// FileIndex. What file in the _files vector is read now?
|
||||
unsigned int FileIndex = 0;
|
||||
|
||||
bool expandedMacro = false;
|
||||
|
||||
// Read one byte at a time from code and create tokens
|
||||
for (char ch = (char)code.get(); code.good(); ch = (char)code.get()) {
|
||||
if (ch == '$') {
|
||||
while (code.peek() == '$')
|
||||
code.get();
|
||||
ch = ' ';
|
||||
expandedMacro = true;
|
||||
} else if (ch == '\n') {
|
||||
expandedMacro = false;
|
||||
}
|
||||
|
||||
// char/string..
|
||||
// multiline strings are not handled. The preprocessor should handle that for us.
|
||||
if (ch == '\'' || ch == '\"') {
|
||||
|
@ -340,9 +352,13 @@ void Tokenizer::createTokens(std::istream &code)
|
|||
} else {
|
||||
// Add previous token
|
||||
addtoken(CurrentToken.c_str(), lineno, FileIndex);
|
||||
if (!CurrentToken.empty())
|
||||
_tokensBack->setExpandedMacro(expandedMacro);
|
||||
|
||||
// Add content of the string
|
||||
addtoken(line.c_str(), lineno, FileIndex);
|
||||
if (!line.empty())
|
||||
_tokensBack->setExpandedMacro(expandedMacro);
|
||||
}
|
||||
|
||||
CurrentToken.clear();
|
||||
|
@ -368,22 +384,27 @@ void Tokenizer::createTokens(std::istream &code)
|
|||
} else if (ch=='&' && code.peek() == '&') {
|
||||
if (!CurrentToken.empty()) {
|
||||
addtoken(CurrentToken.c_str(), lineno, FileIndex, true);
|
||||
if (!CurrentToken.empty())
|
||||
_tokensBack->setExpandedMacro(expandedMacro);
|
||||
CurrentToken.clear();
|
||||
}
|
||||
|
||||
// &&
|
||||
ch = (char)code.get();
|
||||
addtoken("&&", lineno, FileIndex, true);
|
||||
_tokensBack->setExpandedMacro(expandedMacro);
|
||||
continue;
|
||||
} else if (ch==':' && CurrentToken.empty() && code.peek() == ' ') {
|
||||
// :
|
||||
addtoken(":", lineno, FileIndex, true);
|
||||
_tokensBack->setExpandedMacro(expandedMacro);
|
||||
CurrentToken.clear();
|
||||
continue;
|
||||
} else if (ch==':' && CurrentToken.empty() && code.peek() == ':') {
|
||||
// ::
|
||||
ch = (char)code.get();
|
||||
addtoken("::", lineno, FileIndex, true);
|
||||
_tokensBack->setExpandedMacro(expandedMacro);
|
||||
CurrentToken.clear();
|
||||
continue;
|
||||
} else {
|
||||
|
@ -406,6 +427,8 @@ void Tokenizer::createTokens(std::istream &code)
|
|||
}
|
||||
|
||||
addtoken(CurrentToken.c_str(), lineno, FileIndex, true);
|
||||
if (!CurrentToken.empty())
|
||||
_tokensBack->setExpandedMacro(expandedMacro);
|
||||
|
||||
CurrentToken.clear();
|
||||
|
||||
|
@ -421,6 +444,7 @@ void Tokenizer::createTokens(std::istream &code)
|
|||
if ((ch == '+' || ch == '-' || ch == '>') && (code.peek() == ch))
|
||||
CurrentToken += (char)code.get();
|
||||
addtoken(CurrentToken.c_str(), lineno, FileIndex);
|
||||
_tokensBack->setExpandedMacro(expandedMacro);
|
||||
CurrentToken.clear();
|
||||
continue;
|
||||
}
|
||||
|
@ -429,6 +453,8 @@ void Tokenizer::createTokens(std::istream &code)
|
|||
CurrentToken += ch;
|
||||
}
|
||||
addtoken(CurrentToken.c_str(), lineno, FileIndex, true);
|
||||
if (!CurrentToken.empty())
|
||||
_tokensBack->setExpandedMacro(expandedMacro);
|
||||
_tokens->assignProgressValues();
|
||||
}
|
||||
|
||||
|
|
|
@ -454,6 +454,13 @@ private:
|
|||
check(code, true);
|
||||
ASSERT_EQUALS("[test.cpp:2]: (error) Possible null pointer dereference: fred - otherwise it is redundant to check if fred is null at line 3\n", errout.str());
|
||||
}
|
||||
|
||||
// false positives when there are macros
|
||||
check("void f(struct FRED *fred) {\n"
|
||||
" fred->x = 0;\n"
|
||||
" $if(!fred){}\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
// Dereferencing a pointer and then checking if it is null
|
||||
|
@ -709,6 +716,13 @@ private:
|
|||
" if (!abc) { }\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// false positives when there are macros
|
||||
check("void f(int *p) {\n"
|
||||
" *p = 0;\n"
|
||||
" $if(!p){}\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
void nullpointer5() {
|
||||
|
@ -1441,6 +1455,13 @@ private:
|
|||
" int sz = sizeof fred->x;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
// check in macro
|
||||
check("void f(int *x) {\n"
|
||||
" $if (!x) {}\n"
|
||||
" *x = 0;\n"
|
||||
"}");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
// Test CheckNullPointer::nullConstantDereference
|
||||
|
|
|
@ -1520,7 +1520,7 @@ private:
|
|||
// Compare results..
|
||||
ASSERT_EQUALS(1, static_cast<unsigned int>(actual.size()));
|
||||
#ifdef __GNUC__
|
||||
ASSERT_EQUALS("\n\nint a = 4; int b = 5;\n", actual[""]);
|
||||
ASSERT_EQUALS("\n\n$int a = 4; int b = 5;\n", actual[""]);
|
||||
#else
|
||||
ASSERT_EQUALS("\nint b = 5;\nint a = 4;\\\n", actual[""]);
|
||||
#endif
|
||||
|
@ -1544,7 +1544,7 @@ private:
|
|||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS(1, static_cast<unsigned int>(actual.size()));
|
||||
ASSERT_EQUALS("\n\nint main(){\nint a = 4;\n}\n", actual[""]);
|
||||
ASSERT_EQUALS("\n\nint main(){\n$int a = 4;\n}\n", actual[""]);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
|
@ -1589,32 +1589,32 @@ private:
|
|||
{
|
||||
const char filedata[] = "#define AAA(aa) f(aa)\n"
|
||||
"AAA(5);\n";
|
||||
ASSERT_EQUALS("\nf(5);\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n$f(5);\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
{
|
||||
const char filedata[] = "#define AAA(aa) f(aa)\n"
|
||||
"AAA (5);\n";
|
||||
ASSERT_EQUALS("\nf(5);\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n$f(5);\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
}
|
||||
|
||||
void macro_simple2() {
|
||||
const char filedata[] = "#define min(x,y) x<y?x:y\n"
|
||||
"min(a(),b());\n";
|
||||
ASSERT_EQUALS("\na()<b()?a():b();\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n$a()<b()?a():b();\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void macro_simple3() {
|
||||
const char filedata[] = "#define A 4\n"
|
||||
"A AA\n";
|
||||
ASSERT_EQUALS("\n4 AA\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n$4 AA\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void macro_simple4() {
|
||||
const char filedata[] = "#define TEMP_1 if( temp > 0 ) return 1;\n"
|
||||
"TEMP_1\n";
|
||||
ASSERT_EQUALS("\nif( temp > 0 ) return 1;\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n$if( temp > 0 ) return 1;\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void macro_simple5() {
|
||||
|
@ -1625,69 +1625,69 @@ private:
|
|||
" int temp = 0;\n"
|
||||
" ABC\n"
|
||||
"}\n";
|
||||
ASSERT_EQUALS("\n\nvoid foo()\n{\n int temp = 0;\n if( temp > 0 ) return 1;\n}\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n\nvoid foo()\n{\n int temp = 0;\n $if( temp > 0 ) return 1;\n}\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void macro_simple6() {
|
||||
const char filedata[] = "#define ABC (a+b+c)\n"
|
||||
"ABC\n";
|
||||
ASSERT_EQUALS("\n(a+b+c)\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n$(a+b+c)\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void macro_simple7() {
|
||||
const char filedata[] = "#define ABC(str) str\n"
|
||||
"ABC(\"(\")\n";
|
||||
ASSERT_EQUALS("\n\"(\"\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n$\"(\"\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void macro_simple8() {
|
||||
const char filedata[] = "#define ABC 123\n"
|
||||
"#define ABCD 1234\n"
|
||||
"ABC ABCD\n";
|
||||
ASSERT_EQUALS("\n\n123 1234\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n\n$123 $1234\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void macro_simple9() {
|
||||
const char filedata[] = "#define ABC(a) f(a)\n"
|
||||
"ABC( \"\\\"\" );\n"
|
||||
"ABC( \"g\" );\n";
|
||||
ASSERT_EQUALS("\nf(\"\\\"\");\nf(\"g\");\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n$f(\"\\\"\");\n$f(\"g\");\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void macro_simple10() {
|
||||
const char filedata[] = "#define ABC(t) t x\n"
|
||||
"ABC(unsigned long);\n";
|
||||
ASSERT_EQUALS("\nunsigned long x;\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n$unsigned long x;\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void macro_simple11() {
|
||||
const char filedata[] = "#define ABC(x) delete x\n"
|
||||
"ABC(a);\n";
|
||||
ASSERT_EQUALS("\ndelete a;\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n$delete a;\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void macro_simple12() {
|
||||
const char filedata[] = "#define AB ab.AB\n"
|
||||
"AB.CD\n";
|
||||
ASSERT_EQUALS("\nab.AB.CD\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n$ab.AB.CD\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void macro_simple13() {
|
||||
const char filedata[] = "#define TRACE(x)\n"
|
||||
"TRACE(;if(a))\n";
|
||||
ASSERT_EQUALS("\n\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n$\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void macro_simple14() {
|
||||
const char filedata[] = "#define A \" a \"\n"
|
||||
"printf(A);\n";
|
||||
ASSERT_EQUALS("\nprintf(\" a \");\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\nprintf($\" a \");\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void macro_simple15() {
|
||||
const char filedata[] = "#define FOO\"foo\"\n"
|
||||
"FOO\n";
|
||||
ASSERT_EQUALS("\n\"foo\"\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n$\"foo\"\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void macroInMacro1() {
|
||||
|
@ -1695,28 +1695,28 @@ private:
|
|||
const char filedata[] = "#define A(m) long n = m; n++;\n"
|
||||
"#define B(n) A(n)\n"
|
||||
"B(0)\n";
|
||||
ASSERT_EQUALS("\n\nlong n=0;n++;\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n\n$$long n=0;n++;\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
{
|
||||
const char filedata[] = "#define A B\n"
|
||||
"#define B 3\n"
|
||||
"A\n";
|
||||
ASSERT_EQUALS("\n\n3\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n\n$$3\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
{
|
||||
const char filedata[] = "#define DBG(fmt, args...) printf(fmt, ## args)\n"
|
||||
"#define D(fmt, args...) DBG(fmt, ## args)\n"
|
||||
"DBG(\"hello\");\n";
|
||||
ASSERT_EQUALS("\n\nprintf(\"hello\");\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n\n$printf(\"hello\");\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
{
|
||||
const char filedata[] = "#define DBG(fmt, args...) printf(fmt, ## args)\n"
|
||||
"#define D(fmt, args...) DBG(fmt, ## args)\n"
|
||||
"DBG(\"hello: %d\",3);\n";
|
||||
ASSERT_EQUALS("\n\nprintf(\"hello: %d\",3);\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n\n$printf(\"hello: %d\",3);\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1727,14 +1727,14 @@ private:
|
|||
"ABC(2,3);\n"
|
||||
"ABC(4,5,6);\n";
|
||||
|
||||
ASSERT_EQUALS("\n\n\n1+0*0;\n2+03*0;\n4+05*06;\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n\n\n$1+$0*0;\n$2+$03*0;\n$4+$05*06;\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
{
|
||||
const char filedata[] = "#define A 4\n"
|
||||
"#define B(a) a,A\n"
|
||||
"B(2);\n";
|
||||
ASSERT_EQUALS("\n\n2, 4;\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n\n$2, 4;\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1748,13 +1748,13 @@ private:
|
|||
const char filedata[] = "#define A(x) (x*2)\n"
|
||||
"#define B A(\n"
|
||||
"foo B(i));\n";
|
||||
ASSERT_EQUALS("\n\nfoo ((i)*2);\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n\nfoo $$((i)*2);\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
{
|
||||
const char filedata[] = "#define foo foo\n"
|
||||
"foo\n";
|
||||
ASSERT_EQUALS("\nfoo\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n$foo\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1763,7 +1763,7 @@ private:
|
|||
"#define A(name) void foo##name() { do { B(1, 2); }\n"
|
||||
"A(0)\n"
|
||||
"A(1)\n";
|
||||
ASSERT_EQUALS("\n\nvoid foo0(){do{}while(0);}\nvoid foo1(){do{}while(0);}\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n\n$void foo0(){do{$}while(0);}\n$void foo1(){do{$}while(0);}\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1771,7 +1771,7 @@ private:
|
|||
"#define B(x) (\n"
|
||||
"#define A() B(xx)\n"
|
||||
"B(1) A() ) )\n";
|
||||
ASSERT_EQUALS("\n\n( ( ) )\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n\n$( $$( ) )\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1779,14 +1779,14 @@ private:
|
|||
"#define PTR1 (\n"
|
||||
"#define PTR2 PTR1 PTR1\n"
|
||||
"int PTR2 PTR2 foo )))) = 0;\n";
|
||||
ASSERT_EQUALS("\n\nint ( ( ( ( foo )))) = 0;\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n\nint $$( $( $$( $( foo )))) = 0;\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
{
|
||||
const char filedata[] =
|
||||
"#define PTR1 (\n"
|
||||
"PTR1 PTR1\n";
|
||||
ASSERT_EQUALS("\n( (\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n$( $(\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1794,7 +1794,7 @@ private:
|
|||
const char filedata[] = "#define A(x) a##x\n"
|
||||
"#define B 0\n"
|
||||
"A(B)\n";
|
||||
ASSERT_EQUALS("\n\naB\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n\n$aB\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void macro_mismatch() {
|
||||
|
@ -1809,7 +1809,7 @@ private:
|
|||
"\n"
|
||||
")\n"
|
||||
"int a;\n";
|
||||
ASSERT_EQUALS("\n"
|
||||
ASSERT_EQUALS("\n$"
|
||||
"\n"
|
||||
"\n"
|
||||
"\n"
|
||||
|
@ -1820,7 +1820,7 @@ private:
|
|||
void macro_nopar() {
|
||||
const char filedata[] = "#define AAA( ) { NULL }\n"
|
||||
"AAA()\n";
|
||||
ASSERT_EQUALS("\n{ NULL }\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n${ NULL }\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void macro_switchCase() {
|
||||
|
@ -1832,14 +1832,14 @@ private:
|
|||
" break; "
|
||||
"}\n"
|
||||
"A( 5 );\n";
|
||||
ASSERT_EQUALS("\nswitch(a){case 2:break;};\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n$switch(a){case 2:break;};\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
{
|
||||
// Make sure "2 BB" doesn't become "2BB"
|
||||
const char filedata[] = "#define A() AA : 2 BB\n"
|
||||
"A();\n";
|
||||
ASSERT_EQUALS("\nAA : 2 BB;\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n$AA : 2 BB;\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1847,7 +1847,7 @@ private:
|
|||
"#define B() A\n"
|
||||
"#define C( a ) B() break;\n"
|
||||
"{C( 2 );\n";
|
||||
ASSERT_EQUALS("\n\n\n{} break;;\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n\n\n{$$$} break;;\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1856,7 +1856,7 @@ private:
|
|||
"#define B() A\n"
|
||||
"#define C( a ) B() _break;\n"
|
||||
"{C( 2 );\n";
|
||||
ASSERT_EQUALS("\n\n\n{} _break;;\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n\n\n{$$$} _break;;\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
|
||||
|
@ -1865,7 +1865,7 @@ private:
|
|||
"#define B() A\n"
|
||||
"#define C( a ) B() 5;\n"
|
||||
"{C( 2 );\n";
|
||||
ASSERT_EQUALS("\n\n\n{} 5;;\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n\n\n{$$$} 5;;\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1911,7 +1911,7 @@ private:
|
|||
"AAA\n";
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS("\n\n\nchar b=0;\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n\n\n$char b=0;\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
{
|
||||
|
@ -1932,37 +1932,37 @@ private:
|
|||
"AAA\n";
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS("\n\n\n789\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n\n\n$789\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void preprocessor_doublesharp() {
|
||||
// simple testcase without ##
|
||||
const char filedata1[] = "#define TEST(var,val) var = val\n"
|
||||
"TEST(foo,20);\n";
|
||||
ASSERT_EQUALS("\nfoo=20;\n", OurPreprocessor::expandMacros(filedata1));
|
||||
ASSERT_EQUALS("\n$foo=20;\n", OurPreprocessor::expandMacros(filedata1));
|
||||
|
||||
// simple testcase with ##
|
||||
const char filedata2[] = "#define TEST(var,val) var##_##val = val\n"
|
||||
"TEST(foo,20);\n";
|
||||
ASSERT_EQUALS("\nfoo_20=20;\n", OurPreprocessor::expandMacros(filedata2));
|
||||
ASSERT_EQUALS("\n$foo_20=20;\n", OurPreprocessor::expandMacros(filedata2));
|
||||
|
||||
// concat macroname
|
||||
const char filedata3[] = "#define ABCD 123\n"
|
||||
"#define A(B) A##B\n"
|
||||
"A(BCD)\n";
|
||||
ASSERT_EQUALS("\n\n123\n", OurPreprocessor::expandMacros(filedata3));
|
||||
ASSERT_EQUALS("\n\n$$123\n", OurPreprocessor::expandMacros(filedata3));
|
||||
|
||||
// Ticket #1802 - inner ## must be expanded before outer macro
|
||||
const char filedata4[] = "#define A(B) A##B\n"
|
||||
"#define a(B) A(B)\n"
|
||||
"a(A(B))\n";
|
||||
ASSERT_EQUALS("\n\nAAB\n", OurPreprocessor::expandMacros(filedata4));
|
||||
ASSERT_EQUALS("\n\n$$AAB\n", OurPreprocessor::expandMacros(filedata4));
|
||||
|
||||
// Ticket #1802 - inner ## must be expanded before outer macro
|
||||
const char filedata5[] = "#define AB(A,B) A##B\n"
|
||||
"#define ab(A,B) AB(A,B)\n"
|
||||
"ab(a,AB(b,c))\n";
|
||||
ASSERT_EQUALS("\n\nabc\n", OurPreprocessor::expandMacros(filedata5));
|
||||
ASSERT_EQUALS("\n\n$$abc\n", OurPreprocessor::expandMacros(filedata5));
|
||||
|
||||
// Ticket #1802
|
||||
const char filedata6[] = "#define AB_(A,B) A ## B\n"
|
||||
|
@ -1970,7 +1970,7 @@ private:
|
|||
"#define ab(suf) AB(X, AB_(_, suf))\n"
|
||||
"#define X x\n"
|
||||
"ab(y)\n";
|
||||
ASSERT_EQUALS("\n\n\n\nx_y\n", OurPreprocessor::expandMacros(filedata6));
|
||||
ASSERT_EQUALS("\n\n\n\n$$$x_y\n", OurPreprocessor::expandMacros(filedata6));
|
||||
}
|
||||
|
||||
|
||||
|
@ -2004,7 +2004,7 @@ private:
|
|||
// Preprocess..
|
||||
std::string actual = OurPreprocessor::expandMacros(filedata);
|
||||
|
||||
ASSERT_EQUALS("\nprintf(\"[0x%lx-0x%lx)\",pstart,pend);\n", actual);
|
||||
ASSERT_EQUALS("\n$printf(\"[0x%lx-0x%lx)\",pstart,pend);\n", actual);
|
||||
}
|
||||
|
||||
void va_args_2() {
|
||||
|
@ -2014,19 +2014,19 @@ private:
|
|||
// Preprocess..
|
||||
std::string actual = OurPreprocessor::expandMacros(filedata);
|
||||
|
||||
ASSERT_EQUALS("\nprintf(\"hello\");\n", actual);
|
||||
ASSERT_EQUALS("\n$printf(\"hello\");\n", actual);
|
||||
}
|
||||
|
||||
void va_args_3() {
|
||||
const char filedata[] = "#define FRED(...) { fred(__VA_ARGS__); }\n"
|
||||
"FRED(123)\n";
|
||||
ASSERT_EQUALS("\n{ fred(123); }\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n${ fred(123); }\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void va_args_4() {
|
||||
const char filedata[] = "#define FRED(name, ...) name (__VA_ARGS__)\n"
|
||||
"FRED(abc, 123)\n";
|
||||
ASSERT_EQUALS("\nabc(123)\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n$abc(123)\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
|
||||
|
@ -2048,7 +2048,7 @@ private:
|
|||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS(1, static_cast<unsigned int>(actual.size()));
|
||||
ASSERT_EQUALS("\nint main()\n{\nif( 'ABCD' == 0 );\nreturn 0;\n}\n", actual[""]);
|
||||
ASSERT_EQUALS("\nint main()\n{\nif( $'ABCD' == 0 );\nreturn 0;\n}\n", actual[""]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -2059,7 +2059,7 @@ private:
|
|||
// expand macros..
|
||||
std::string actual = OurPreprocessor::expandMacros(filedata);
|
||||
|
||||
ASSERT_EQUALS("\n\"abc\"\n", actual);
|
||||
ASSERT_EQUALS("\n$\"abc\"\n", actual);
|
||||
}
|
||||
|
||||
void stringify2() {
|
||||
|
@ -2069,7 +2069,7 @@ private:
|
|||
// expand macros..
|
||||
std::string actual = OurPreprocessor::expandMacros(filedata);
|
||||
|
||||
ASSERT_EQUALS("\ng(\"abc\");\n", actual);
|
||||
ASSERT_EQUALS("\n$g(\"abc\");\n", actual);
|
||||
}
|
||||
|
||||
void stringify3() {
|
||||
|
@ -2079,7 +2079,7 @@ private:
|
|||
// expand macros..
|
||||
std::string actual = OurPreprocessor::expandMacros(filedata);
|
||||
|
||||
ASSERT_EQUALS("\ng(\"abc\");\n", actual);
|
||||
ASSERT_EQUALS("\n$g(\"abc\");\n", actual);
|
||||
}
|
||||
|
||||
void stringify4() {
|
||||
|
@ -2091,13 +2091,13 @@ private:
|
|||
// expand macros..
|
||||
std::string actual = OurPreprocessor::expandMacros(filedata);
|
||||
|
||||
ASSERT_EQUALS("\n1 \n\n\"abc\" 2\n", actual);
|
||||
ASSERT_EQUALS("\n1 $\n\n\"abc\" 2\n", actual);
|
||||
}
|
||||
|
||||
void stringify5() {
|
||||
const char filedata[] = "#define A(x) a(#x,x)\n"
|
||||
"A(foo(\"\\\"\"))\n";
|
||||
ASSERT_EQUALS("\na(\"foo(\\\"\\\\\\\"\\\")\",foo(\"\\\"\"))\n", OurPreprocessor::expandMacros(filedata));
|
||||
ASSERT_EQUALS("\n$a(\"foo(\\\"\\\\\\\"\\\")\",foo(\"\\\"\"))\n", OurPreprocessor::expandMacros(filedata));
|
||||
}
|
||||
|
||||
void pragma() {
|
||||
|
@ -2259,7 +2259,7 @@ private:
|
|||
errout.str("");
|
||||
const std::string actual(OurPreprocessor::expandMacros(filedata, this));
|
||||
|
||||
ASSERT_EQUALS("\n\nint a = 1;\n", actual);
|
||||
ASSERT_EQUALS("\n\nint a = $1;\n", actual);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
|
@ -2324,7 +2324,7 @@ private:
|
|||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS(1, static_cast<unsigned int>(actual.size()));
|
||||
ASSERT_EQUALS("\nvoid f() {\ng( );\n}\n", actual[""]);
|
||||
ASSERT_EQUALS("\nvoid f() {\n$g( );\n}\n", actual[""]);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
|
@ -2345,8 +2345,8 @@ private:
|
|||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS(2, static_cast<unsigned int>(actual.size()));
|
||||
ASSERT_EQUALS("\n\n\n\n\n20\n", actual[""]);
|
||||
ASSERT_EQUALS("\n\n\n\n\n10\n", actual["A"]);
|
||||
ASSERT_EQUALS("\n\n\n\n\n$20\n", actual[""]);
|
||||
ASSERT_EQUALS("\n\n\n\n\n$10\n", actual["A"]);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
|
@ -2366,7 +2366,7 @@ private:
|
|||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS(1, static_cast<unsigned int>(actual.size()));
|
||||
ASSERT_EQUALS("\n\nvoid f() { }\n", actual[""]);
|
||||
ASSERT_EQUALS("\n\nvoid f() ${ }\n", actual[""]);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
|
@ -2410,7 +2410,7 @@ private:
|
|||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS(1, static_cast<unsigned int>(actual.size()));
|
||||
ASSERT_EQUALS("\nvoid f()\n{\nprintf(\"\\n\");\n}\n", actual[""]);
|
||||
ASSERT_EQUALS("\nvoid f()\n{\n$printf(\"\\n\");\n}\n", actual[""]);
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
}
|
||||
|
||||
|
@ -2536,7 +2536,7 @@ private:
|
|||
preprocessor.preprocess(istr, actual, "file.c");
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS("\n\n1\n\n", actual[""]);
|
||||
ASSERT_EQUALS("\n\n$1\n\n", actual[""]);
|
||||
ASSERT_EQUALS(1, (int)actual.size());
|
||||
}
|
||||
|
||||
|
@ -2554,7 +2554,7 @@ private:
|
|||
preprocessor.preprocess(istr, actual, "file.c");
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS("\n\n1\n\n", actual[""]);
|
||||
ASSERT_EQUALS("\n\n$1\n\n", actual[""]);
|
||||
ASSERT_EQUALS(1, (int)actual.size());
|
||||
}
|
||||
|
||||
|
@ -2572,7 +2572,7 @@ private:
|
|||
preprocessor.preprocess(istr, actual, "file.c");
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS("\n\n1\n\n", actual[""]);
|
||||
ASSERT_EQUALS("\n\n$1\n\n", actual[""]);
|
||||
ASSERT_EQUALS(1, (int)actual.size());
|
||||
}
|
||||
|
||||
|
@ -2591,7 +2591,7 @@ private:
|
|||
preprocessor.preprocess(istr, actual, "file.c");
|
||||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS("\n\n\n\n1\n", actual[""]);
|
||||
ASSERT_EQUALS("\n\n\n\n$1\n", actual[""]);
|
||||
ASSERT_EQUALS(1, (int)actual.size());
|
||||
}
|
||||
}
|
||||
|
@ -2625,8 +2625,8 @@ private:
|
|||
"B me;\n";
|
||||
|
||||
// Preprocess => actual result..
|
||||
ASSERT_EQUALS("\n\n\n\n\n\nint me;\n", Preprocessor::getcode(filedata, "", "a.cpp", NULL, NULL));
|
||||
ASSERT_EQUALS("\n\n\n\n\n\nchar me;\n", Preprocessor::getcode(filedata, "A", "a.cpp", NULL, NULL));
|
||||
ASSERT_EQUALS("\n\n\n\n\n\n$int me;\n", Preprocessor::getcode(filedata, "", "a.cpp", NULL, NULL));
|
||||
ASSERT_EQUALS("\n\n\n\n\n\n$char me;\n", Preprocessor::getcode(filedata, "A", "a.cpp", NULL, NULL));
|
||||
}
|
||||
|
||||
void redundant_config() {
|
||||
|
@ -3248,7 +3248,7 @@ private:
|
|||
|
||||
// Compare results..
|
||||
ASSERT_EQUALS(1U, actual.size());
|
||||
TODO_ASSERT_EQUALS("\n;\n","\nXDefined;\n", actual[""]);
|
||||
TODO_ASSERT_EQUALS("\n;\n","\n$XDefined;\n", actual[""]);
|
||||
}
|
||||
|
||||
void undef8() {
|
||||
|
|
|
@ -53,6 +53,7 @@ private:
|
|||
TEST_CASE(tokenize19); // #3006 (segmentation fault)
|
||||
TEST_CASE(tokenize20); // replace C99 _Bool => bool
|
||||
TEST_CASE(tokenize21); // tokenize 0x0E-7
|
||||
TEST_CASE(tokenize22); // special marker $ from preprocessor
|
||||
|
||||
// don't freak out when the syntax is wrong
|
||||
TEST_CASE(wrong_syntax);
|
||||
|
@ -606,6 +607,10 @@ private:
|
|||
ASSERT_EQUALS("14 - 7", tokenizeAndStringify("0x0E-7"));
|
||||
}
|
||||
|
||||
void tokenize22() { // tokenize special marker $ from preprocessor
|
||||
ASSERT_EQUALS("a b", tokenizeAndStringify("a$b"));
|
||||
}
|
||||
|
||||
void wrong_syntax() {
|
||||
{
|
||||
errout.str("");
|
||||
|
|
Loading…
Reference in New Issue