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;
}
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)
{
if (haystack[0] == '%' && haystack[1] == 'o') {
@ -271,6 +311,10 @@ int Token::multiCompare(const char *haystack, const char *needle)
needlePointer = needle;
++haystack;
int ret = multiComparePercent(&haystack, needle, emptyStringFound);
if (ret < 2)
return ret;
} else if (*haystack == ' ' || *haystack == '\0') {
if (needlePointer == needle)
return 0;
@ -291,36 +335,9 @@ int Token::multiCompare(const char *haystack, const char *needle)
++haystack;
if (haystack[0] == '%' && haystack[1] != '|') {
if (haystack[1] == 'o' && // "%op%"
haystack[2] == 'p' &&
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;
}
int ret = multiComparePercent(&haystack, needle, emptyStringFound);
if (ret < 2)
return ret;
}
}

View File

@ -113,6 +113,9 @@ public:
* - "!!else" No tokens or any token that is not "else".
* - "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
* by separating tokens with a space, e.g.
* ") 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
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->deleteNext();
tok->deleteNext();

View File

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