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:
Thomas Jarosch 2013-01-09 16:53:19 +01:00
parent 8b2adf1391
commit 7dd07d8e77
3 changed files with 53 additions and 44 deletions

View File

@ -296,26 +296,7 @@ const std::string &Token::strAt(int index) const
return tok ? tok->_str : empty_str;
}
static bool strisop(const char str[])
{
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,
static int multiComparePercent(const Token *tok, const char * * haystack_p,
const char * needle,
bool emptyStringFound)
{
@ -325,7 +306,7 @@ static int multiComparePercent(const char * * haystack_p,
if (haystack[1] == 'o' && // "%op%"
haystack[2] == 'p' &&
haystack[3] == '%') {
if (strisop(needle))
if (tok->isOp())
return 1;
*haystack_p = haystack = haystack + 4;
} else if (haystack[1] == 'o' && // "%or%"
@ -355,14 +336,14 @@ static int multiComparePercent(const char * * haystack_p,
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[2] == 'p' && // "%op%|"
haystack[3] == '%' &&
haystack[4] == '|') {
haystack = haystack + 5;
if (strisop(needle))
if (tok->isOp())
return 1;
} else if (haystack[2] == 'r' && // "%or%|"
haystack[3] == '%' &&
@ -402,7 +383,7 @@ int Token::multiCompare(const char *haystack, const char *needle)
needlePointer = needle;
++haystack;
int ret = multiComparePercent(&haystack, needle, emptyStringFound);
int ret = multiComparePercent(tok, &haystack, needle, emptyStringFound);
if (ret < 2)
return ret;
} else if (*haystack == ' ' || *haystack == '\0') {
@ -425,7 +406,7 @@ int Token::multiCompare(const char *haystack, const char *needle)
++haystack;
int ret = multiComparePercent(&haystack, needle, emptyStringFound);
int ret = multiComparePercent(tok, &haystack, needle, emptyStringFound);
if (ret < 2)
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)
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) {
// Empty alternative matches, use the same token on next round
while (*p && *p != ' ')

View File

@ -279,13 +279,14 @@ public:
* string, return value is 0. If needle was not found, return
* value is -1.
*
* @param tok Current token
* @param haystack e.g. "one|two" or "|one|two"
* @param needle e.g. "one", "two" or "invalid"
* @return 1 if needle is found from the haystack
* 0 if needle was empty string
* -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 {
return _linenr;

View File

@ -120,28 +120,54 @@ private:
void multiCompare() {
// Test for found
ASSERT_EQUALS(1, Token::multiCompare("one|two", "one"));
ASSERT_EQUALS(1, Token::multiCompare("one|two", "two"));
ASSERT_EQUALS(1, Token::multiCompare("verybig|two|", "two"));
Token *one = new Token(0);
one->str("one");
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
ASSERT_EQUALS(0, Token::multiCompare("|one|two", "notfound"));
ASSERT_EQUALS(0, Token::multiCompare("one||two", "notfound"));
ASSERT_EQUALS(0, Token::multiCompare("one|two|", "notfound"));
Token *notfound = new Token(0);
notfound->str("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
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("verybig|two", "s")));
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare("one|two", "ne")));
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare("abc|def", "a")));
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("abc|def", "default")));
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(notfound, "one|two", "notfound")));
Token *s = new Token(0);
s->str("s");
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(s, "verybig|two", "s")));
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%
ASSERT_EQUALS(1, Token::multiCompare("one|%op%", "+"));
ASSERT_EQUALS(1, Token::multiCompare("%op%|two", "+"));
ASSERT_EQUALS(-1, Token::multiCompare("one|%op%", "x"));
ASSERT_EQUALS(-1, Token::multiCompare("%op%|two", "x"));
Token *plus = new Token(0);
plus->str("+");
ASSERT_EQUALS(1, Token::multiCompare(plus, "one|%op%", "+"));
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
@ -209,7 +235,8 @@ private:
ASSERT_EQUALS(Token::eBracket, var.tokens()->tokAt(5)->type());
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() {