Fixed #3294 (Token::Match multi compare false negative)
This commit is contained in:
parent
580fef6951
commit
5edf153602
|
@ -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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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() {
|
||||||
|
|
Loading…
Reference in New Issue