Fixed #3294 (Token::Match multi compare false negative)

This commit is contained in:
Daniel Marjamäki 2011-11-05 19:24:21 +01:00
parent 580fef6951
commit 5edf153602
4 changed files with 55 additions and 33 deletions

View File

@ -225,6 +225,46 @@ static bool strisop(const char str[])
return false; return false;
} }
static int multiComparePercent(const char * * haystack_p,
const char * needle,
bool emptyStringFound)
{
const char *haystack = *haystack_p;
if (haystack[0] == '%' && haystack[1] != '|') {
if (haystack[1] == 'o' && // "%op%"
haystack[2] == 'p' &&
haystack[3] == '%') {
if (strisop(needle))
return 1;
*haystack_p = haystack = haystack + 4;
} else if (haystack[1] == 'o' && // "%or%"
haystack[2] == 'r' &&
haystack[3] == '%') {
if (*needle == '|')
return 1;
*haystack_p = haystack = haystack + 4;
} else if (haystack[1] == 'o' && // "%oror%"
haystack[2] == 'r' &&
haystack[3] == 'o' &&
haystack[4] == 'r' &&
haystack[5] == '%') {
if (needle[0] == '|' && needle[1] == '|')
return 1;
*haystack_p = haystack = haystack + 6;
}
if (*haystack == '|')
*haystack_p = haystack = haystack + 1;
else if (*haystack == ' ' || *haystack == '\0')
return emptyStringFound ? 0 : -1;
else
return -1;
}
return 0xFFFF;
}
int Token::multiCompare(const char *haystack, const char *needle) int Token::multiCompare(const char *haystack, const char *needle)
{ {
if (haystack[0] == '%' && haystack[1] == 'o') { if (haystack[0] == '%' && haystack[1] == 'o') {
@ -271,6 +311,10 @@ int Token::multiCompare(const char *haystack, const char *needle)
needlePointer = needle; needlePointer = needle;
++haystack; ++haystack;
int ret = multiComparePercent(&haystack, needle, emptyStringFound);
if (ret < 2)
return ret;
} else if (*haystack == ' ' || *haystack == '\0') { } else if (*haystack == ' ' || *haystack == '\0') {
if (needlePointer == needle) if (needlePointer == needle)
return 0; return 0;
@ -291,36 +335,9 @@ int Token::multiCompare(const char *haystack, const char *needle)
++haystack; ++haystack;
if (haystack[0] == '%' && haystack[1] != '|') { int ret = multiComparePercent(&haystack, needle, emptyStringFound);
if (haystack[1] == 'o' && // "%op%" if (ret < 2)
haystack[2] == 'p' && return ret;
haystack[3] == '%') {
if (strisop(needle))
return 1;
haystack = haystack + 4;
} else if (haystack[1] == 'o' && // "%or%"
haystack[2] == 'r' &&
haystack[3] == '%') {
if (*needle == '|')
return 1;
haystack = haystack + 4;
} else if (haystack[1] == 'o' && // "%oror%"
haystack[2] == 'r' &&
haystack[3] == 'o' &&
haystack[4] == 'r' &&
haystack[5] == '%') {
if (needle[0] == '|' && needle[1] == '|')
return 1;
haystack = haystack + 6;
}
if (*haystack == '|')
haystack++;
else if (*haystack == ' ' || *haystack == '\0')
return emptyStringFound ? 0 : -1;
else
return -1;
}
} }
} }

View File

@ -113,6 +113,9 @@ public:
* - "!!else" No tokens or any token that is not "else". * - "!!else" No tokens or any token that is not "else".
* - "someRandomText" If token contains "someRandomText". * - "someRandomText" If token contains "someRandomText".
* *
* multi-compare patterns such as "int|void|char" can contain %or%, %oror% and %op%
* but it is not recommended to put such an %cmd% as the first pattern.
*
* The patterns can be also combined to compare to multiple tokens at once * The patterns can be also combined to compare to multiple tokens at once
* by separating tokens with a space, e.g. * by separating tokens with a space, e.g.
* ") const|void {" will return true if first token is ')' next token is either * ") const|void {" will return true if first token is ')' next token is either

View File

@ -1869,7 +1869,10 @@ bool Tokenizer::tokenize(std::istream &code,
// token concatenation // token concatenation
for (Token *tok = _tokens; tok; tok = tok->next()) { for (Token *tok = _tokens; tok; tok = tok->next()) {
if (Token::Match(tok, "%var%|%num% ## %var%|%num%")) { // TODO: pattern should be "%var%|%num% ## %var%|%num%"
if (Token::Match(tok, "%any% ## %any%") &&
(tok->isName() || tok->isNumber()) &&
(tok->tokAt(2)->isName() || tok->tokAt(2)->isNumber())) {
tok->str(tok->str() + tok->strAt(2)); tok->str(tok->str() + tok->strAt(2));
tok->deleteNext(); tok->deleteNext();
tok->deleteNext(); tok->deleteNext();

View File

@ -107,8 +107,7 @@ private:
void multiCompare2() { // #3294 void multiCompare2() { // #3294
// Original pattern that failed: [[,(=<>+-*|&^] %num% [+-*/] %num% ]|,|)|;|=|%op% // Original pattern that failed: [[,(=<>+-*|&^] %num% [+-*/] %num% ]|,|)|;|=|%op%
givenACodeSampleToTokenize toks("a == 1"); givenACodeSampleToTokenize toks("a == 1");
// FIXME: Result should be true ASSERT_EQUALS(true, Token::Match(toks.tokens(), "a =|%op%"));
ASSERT_EQUALS(false, Token::Match(toks.tokens(), "a =|%op%"));
} }
void getStrLength() { void getStrLength() {