Properly implement %op% for Token::multiCompare
Use tok->isOp() instead of doing it "manually". This fixes false positives for the C++ template case since the brackets in "template < something >" are not comparison operators. Profiling showed using tok->isOp() is actually faster than before (-O2).
This commit is contained in:
parent
8b2adf1391
commit
7dd07d8e77
|
@ -296,26 +296,7 @@ const std::string &Token::strAt(int index) const
|
||||||
return tok ? tok->_str : empty_str;
|
return tok ? tok->_str : empty_str;
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool strisop(const char str[])
|
static int multiComparePercent(const Token *tok, const char * * haystack_p,
|
||||||
{
|
|
||||||
if (str[1] == 0) {
|
|
||||||
if (std::strchr("+-*/%&|^~!<>", *str))
|
|
||||||
return true;
|
|
||||||
} else if (str[2] == 0) {
|
|
||||||
if ((str[0] == '&' && str[1] == '&') ||
|
|
||||||
(str[0] == '|' && str[1] == '|') ||
|
|
||||||
(str[0] == '=' && str[1] == '=') ||
|
|
||||||
(str[0] == '!' && str[1] == '=') ||
|
|
||||||
(str[0] == '>' && str[1] == '=') ||
|
|
||||||
(str[0] == '<' && str[1] == '=') ||
|
|
||||||
(str[0] == '>' && str[1] == '>') ||
|
|
||||||
(str[0] == '<' && str[1] == '<'))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int multiComparePercent(const char * * haystack_p,
|
|
||||||
const char * needle,
|
const char * needle,
|
||||||
bool emptyStringFound)
|
bool emptyStringFound)
|
||||||
{
|
{
|
||||||
|
@ -325,7 +306,7 @@ static int multiComparePercent(const char * * haystack_p,
|
||||||
if (haystack[1] == 'o' && // "%op%"
|
if (haystack[1] == 'o' && // "%op%"
|
||||||
haystack[2] == 'p' &&
|
haystack[2] == 'p' &&
|
||||||
haystack[3] == '%') {
|
haystack[3] == '%') {
|
||||||
if (strisop(needle))
|
if (tok->isOp())
|
||||||
return 1;
|
return 1;
|
||||||
*haystack_p = haystack = haystack + 4;
|
*haystack_p = haystack = haystack + 4;
|
||||||
} else if (haystack[1] == 'o' && // "%or%"
|
} else if (haystack[1] == 'o' && // "%or%"
|
||||||
|
@ -355,14 +336,14 @@ static int multiComparePercent(const char * * haystack_p,
|
||||||
return 0xFFFF;
|
return 0xFFFF;
|
||||||
}
|
}
|
||||||
|
|
||||||
int Token::multiCompare(const char *haystack, const char *needle)
|
int Token::multiCompare(const Token *tok, const char *haystack, const char *needle)
|
||||||
{
|
{
|
||||||
if (haystack[0] == '%' && haystack[1] == 'o') {
|
if (haystack[0] == '%' && haystack[1] == 'o') {
|
||||||
if (haystack[2] == 'p' && // "%op%|"
|
if (haystack[2] == 'p' && // "%op%|"
|
||||||
haystack[3] == '%' &&
|
haystack[3] == '%' &&
|
||||||
haystack[4] == '|') {
|
haystack[4] == '|') {
|
||||||
haystack = haystack + 5;
|
haystack = haystack + 5;
|
||||||
if (strisop(needle))
|
if (tok->isOp())
|
||||||
return 1;
|
return 1;
|
||||||
} else if (haystack[2] == 'r' && // "%or%|"
|
} else if (haystack[2] == 'r' && // "%or%|"
|
||||||
haystack[3] == '%' &&
|
haystack[3] == '%' &&
|
||||||
|
@ -402,7 +383,7 @@ int Token::multiCompare(const char *haystack, const char *needle)
|
||||||
needlePointer = needle;
|
needlePointer = needle;
|
||||||
++haystack;
|
++haystack;
|
||||||
|
|
||||||
int ret = multiComparePercent(&haystack, needle, emptyStringFound);
|
int ret = multiComparePercent(tok, &haystack, needle, emptyStringFound);
|
||||||
if (ret < 2)
|
if (ret < 2)
|
||||||
return ret;
|
return ret;
|
||||||
} else if (*haystack == ' ' || *haystack == '\0') {
|
} else if (*haystack == ' ' || *haystack == '\0') {
|
||||||
|
@ -425,7 +406,7 @@ int Token::multiCompare(const char *haystack, const char *needle)
|
||||||
|
|
||||||
++haystack;
|
++haystack;
|
||||||
|
|
||||||
int ret = multiComparePercent(&haystack, needle, emptyStringFound);
|
int ret = multiComparePercent(tok, &haystack, needle, emptyStringFound);
|
||||||
if (ret < 2)
|
if (ret < 2)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -711,7 +692,7 @@ bool Token::Match(const Token *tok, const char pattern[], unsigned int varid)
|
||||||
|
|
||||||
// Parse multi options, such as void|int|char (accept token which is one of these 3)
|
// Parse multi options, such as void|int|char (accept token which is one of these 3)
|
||||||
else if (chrInFirstWord(p, '|') && (p[0] != '|' || firstWordLen(p) > 2)) {
|
else if (chrInFirstWord(p, '|') && (p[0] != '|' || firstWordLen(p) > 2)) {
|
||||||
int res = multiCompare(p, tok->_str.c_str());
|
int res = multiCompare(tok, p, tok->_str.c_str());
|
||||||
if (res == 0) {
|
if (res == 0) {
|
||||||
// Empty alternative matches, use the same token on next round
|
// Empty alternative matches, use the same token on next round
|
||||||
while (*p && *p != ' ')
|
while (*p && *p != ' ')
|
||||||
|
|
|
@ -279,13 +279,14 @@ public:
|
||||||
* string, return value is 0. If needle was not found, return
|
* string, return value is 0. If needle was not found, return
|
||||||
* value is -1.
|
* value is -1.
|
||||||
*
|
*
|
||||||
|
* @param tok Current token
|
||||||
* @param haystack e.g. "one|two" or "|one|two"
|
* @param haystack e.g. "one|two" or "|one|two"
|
||||||
* @param needle e.g. "one", "two" or "invalid"
|
* @param needle e.g. "one", "two" or "invalid"
|
||||||
* @return 1 if needle is found from the haystack
|
* @return 1 if needle is found from the haystack
|
||||||
* 0 if needle was empty string
|
* 0 if needle was empty string
|
||||||
* -1 if needle was not found
|
* -1 if needle was not found
|
||||||
*/
|
*/
|
||||||
static int multiCompare(const char *haystack, const char *needle);
|
static int multiCompare(const Token *tok, const char *haystack, const char *needle);
|
||||||
|
|
||||||
unsigned int linenr() const {
|
unsigned int linenr() const {
|
||||||
return _linenr;
|
return _linenr;
|
||||||
|
|
|
@ -120,28 +120,54 @@ private:
|
||||||
|
|
||||||
void multiCompare() {
|
void multiCompare() {
|
||||||
// Test for found
|
// Test for found
|
||||||
ASSERT_EQUALS(1, Token::multiCompare("one|two", "one"));
|
Token *one = new Token(0);
|
||||||
ASSERT_EQUALS(1, Token::multiCompare("one|two", "two"));
|
one->str("one");
|
||||||
ASSERT_EQUALS(1, Token::multiCompare("verybig|two|", "two"));
|
ASSERT_EQUALS(1, Token::multiCompare(one, "one|two", "one"));
|
||||||
|
|
||||||
|
Token *two = new Token(0);
|
||||||
|
two->str("two");
|
||||||
|
ASSERT_EQUALS(1, Token::multiCompare(two, "one|two", "two"));
|
||||||
|
ASSERT_EQUALS(1, Token::multiCompare(two, "verybig|two|", "two"));
|
||||||
|
|
||||||
// Test for empty string found
|
// Test for empty string found
|
||||||
ASSERT_EQUALS(0, Token::multiCompare("|one|two", "notfound"));
|
Token *notfound = new Token(0);
|
||||||
ASSERT_EQUALS(0, Token::multiCompare("one||two", "notfound"));
|
notfound->str("notfound");
|
||||||
ASSERT_EQUALS(0, Token::multiCompare("one|two|", "notfound"));
|
ASSERT_EQUALS(0, Token::multiCompare(notfound, "|one|two", "notfound"));
|
||||||
|
ASSERT_EQUALS(0, Token::multiCompare(notfound, "one||two", "notfound"));
|
||||||
|
ASSERT_EQUALS(0, Token::multiCompare(notfound, "one|two|", "notfound"));
|
||||||
|
|
||||||
// Test for not found
|
// Test for not found
|
||||||
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare("one|two", "notfound")));
|
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(notfound, "one|two", "notfound")));
|
||||||
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare("verybig|two", "s")));
|
|
||||||
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare("one|two", "ne")));
|
Token *s = new Token(0);
|
||||||
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare("abc|def", "a")));
|
s->str("s");
|
||||||
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare("abc|def", "abcd")));
|
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(s, "verybig|two", "s")));
|
||||||
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare("abc|def", "default")));
|
|
||||||
|
Token *ne = new Token(0);
|
||||||
|
ne->str("ne");
|
||||||
|
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(ne, "one|two", "ne")));
|
||||||
|
|
||||||
|
Token *a = new Token(0);
|
||||||
|
a->str("a");
|
||||||
|
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(a, "abc|def", "a")));
|
||||||
|
|
||||||
|
Token *abcd = new Token(0);
|
||||||
|
abcd->str("abcd");
|
||||||
|
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(abcd, "abc|def", "abcd")));
|
||||||
|
|
||||||
|
Token *def = new Token(0);
|
||||||
|
def->str("default");
|
||||||
|
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(def, "abc|def", "default")));
|
||||||
|
|
||||||
// %op%
|
// %op%
|
||||||
ASSERT_EQUALS(1, Token::multiCompare("one|%op%", "+"));
|
Token *plus = new Token(0);
|
||||||
ASSERT_EQUALS(1, Token::multiCompare("%op%|two", "+"));
|
plus->str("+");
|
||||||
ASSERT_EQUALS(-1, Token::multiCompare("one|%op%", "x"));
|
ASSERT_EQUALS(1, Token::multiCompare(plus, "one|%op%", "+"));
|
||||||
ASSERT_EQUALS(-1, Token::multiCompare("%op%|two", "x"));
|
ASSERT_EQUALS(1, Token::multiCompare(plus, "%op%|two", "+"));
|
||||||
|
Token *x = new Token(0);
|
||||||
|
x->str("x");
|
||||||
|
ASSERT_EQUALS(-1, Token::multiCompare(x, "one|%op%", "x"));
|
||||||
|
ASSERT_EQUALS(-1, Token::multiCompare(x, "%op%|two", "x"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void multiCompare2() { // #3294
|
void multiCompare2() { // #3294
|
||||||
|
@ -209,7 +235,8 @@ private:
|
||||||
ASSERT_EQUALS(Token::eBracket, var.tokens()->tokAt(5)->type());
|
ASSERT_EQUALS(Token::eBracket, var.tokens()->tokAt(5)->type());
|
||||||
|
|
||||||
ASSERT_EQUALS(false, Token::Match(var.tokens(), "std :: queue %op%"));
|
ASSERT_EQUALS(false, Token::Match(var.tokens(), "std :: queue %op%"));
|
||||||
TODO_ASSERT_EQUALS(false, true, Token::Match(var.tokens(), "std :: queue x|%op%"));
|
ASSERT_EQUALS(false, Token::Match(var.tokens(), "std :: queue x|%op%"));
|
||||||
|
ASSERT_EQUALS(false, Token::Match(var.tokens(), "std :: queue %op%|x"));
|
||||||
}
|
}
|
||||||
|
|
||||||
void getStrLength() {
|
void getStrLength() {
|
||||||
|
|
Loading…
Reference in New Issue