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; 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 != ' ')

View File

@ -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;

View File

@ -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() {