Skip to content

Commit 7dd07d8

Browse files
committed
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).
1 parent 8b2adf1 commit 7dd07d8

File tree

3 files changed

+53
-44
lines changed

3 files changed

+53
-44
lines changed

lib/token.cpp

Lines changed: 7 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -296,26 +296,7 @@ const std::string &Token::strAt(int index) const
296296
return tok ? tok->_str : empty_str;
297297
}
298298

299-
static bool strisop(const char str[])
300-
{
301-
if (str[1] == 0) {
302-
if (std::strchr("+-*/%&|^~!<>", *str))
303-
return true;
304-
} else if (str[2] == 0) {
305-
if ((str[0] == '&' && str[1] == '&') ||
306-
(str[0] == '|' && str[1] == '|') ||
307-
(str[0] == '=' && str[1] == '=') ||
308-
(str[0] == '!' && str[1] == '=') ||
309-
(str[0] == '>' && str[1] == '=') ||
310-
(str[0] == '<' && str[1] == '=') ||
311-
(str[0] == '>' && str[1] == '>') ||
312-
(str[0] == '<' && str[1] == '<'))
313-
return true;
314-
}
315-
return false;
316-
}
317-
318-
static int multiComparePercent(const char * * haystack_p,
299+
static int multiComparePercent(const Token *tok, const char * * haystack_p,
319300
const char * needle,
320301
bool emptyStringFound)
321302
{
@@ -325,7 +306,7 @@ static int multiComparePercent(const char * * haystack_p,
325306
if (haystack[1] == 'o' && // "%op%"
326307
haystack[2] == 'p' &&
327308
haystack[3] == '%') {
328-
if (strisop(needle))
309+
if (tok->isOp())
329310
return 1;
330311
*haystack_p = haystack = haystack + 4;
331312
} else if (haystack[1] == 'o' && // "%or%"
@@ -355,14 +336,14 @@ static int multiComparePercent(const char * * haystack_p,
355336
return 0xFFFF;
356337
}
357338

358-
int Token::multiCompare(const char *haystack, const char *needle)
339+
int Token::multiCompare(const Token *tok, const char *haystack, const char *needle)
359340
{
360341
if (haystack[0] == '%' && haystack[1] == 'o') {
361342
if (haystack[2] == 'p' && // "%op%|"
362343
haystack[3] == '%' &&
363344
haystack[4] == '|') {
364345
haystack = haystack + 5;
365-
if (strisop(needle))
346+
if (tok->isOp())
366347
return 1;
367348
} else if (haystack[2] == 'r' && // "%or%|"
368349
haystack[3] == '%' &&
@@ -402,7 +383,7 @@ int Token::multiCompare(const char *haystack, const char *needle)
402383
needlePointer = needle;
403384
++haystack;
404385

405-
int ret = multiComparePercent(&haystack, needle, emptyStringFound);
386+
int ret = multiComparePercent(tok, &haystack, needle, emptyStringFound);
406387
if (ret < 2)
407388
return ret;
408389
} else if (*haystack == ' ' || *haystack == '\0') {
@@ -425,7 +406,7 @@ int Token::multiCompare(const char *haystack, const char *needle)
425406

426407
++haystack;
427408

428-
int ret = multiComparePercent(&haystack, needle, emptyStringFound);
409+
int ret = multiComparePercent(tok, &haystack, needle, emptyStringFound);
429410
if (ret < 2)
430411
return ret;
431412
}
@@ -711,7 +692,7 @@ bool Token::Match(const Token *tok, const char pattern[], unsigned int varid)
711692

712693
// Parse multi options, such as void|int|char (accept token which is one of these 3)
713694
else if (chrInFirstWord(p, '|') && (p[0] != '|' || firstWordLen(p) > 2)) {
714-
int res = multiCompare(p, tok->_str.c_str());
695+
int res = multiCompare(tok, p, tok->_str.c_str());
715696
if (res == 0) {
716697
// Empty alternative matches, use the same token on next round
717698
while (*p && *p != ' ')

lib/token.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -279,13 +279,14 @@ class CPPCHECKLIB Token {
279279
* string, return value is 0. If needle was not found, return
280280
* value is -1.
281281
*
282+
* @param tok Current token
282283
* @param haystack e.g. "one|two" or "|one|two"
283284
* @param needle e.g. "one", "two" or "invalid"
284285
* @return 1 if needle is found from the haystack
285286
* 0 if needle was empty string
286287
* -1 if needle was not found
287288
*/
288-
static int multiCompare(const char *haystack, const char *needle);
289+
static int multiCompare(const Token *tok, const char *haystack, const char *needle);
289290

290291
unsigned int linenr() const {
291292
return _linenr;

test/testtoken.cpp

Lines changed: 44 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -120,28 +120,54 @@ class TestToken : public TestFixture {
120120

121121
void multiCompare() {
122122
// Test for found
123-
ASSERT_EQUALS(1, Token::multiCompare("one|two", "one"));
124-
ASSERT_EQUALS(1, Token::multiCompare("one|two", "two"));
125-
ASSERT_EQUALS(1, Token::multiCompare("verybig|two|", "two"));
123+
Token *one = new Token(0);
124+
one->str("one");
125+
ASSERT_EQUALS(1, Token::multiCompare(one, "one|two", "one"));
126+
127+
Token *two = new Token(0);
128+
two->str("two");
129+
ASSERT_EQUALS(1, Token::multiCompare(two, "one|two", "two"));
130+
ASSERT_EQUALS(1, Token::multiCompare(two, "verybig|two|", "two"));
126131

127132
// Test for empty string found
128-
ASSERT_EQUALS(0, Token::multiCompare("|one|two", "notfound"));
129-
ASSERT_EQUALS(0, Token::multiCompare("one||two", "notfound"));
130-
ASSERT_EQUALS(0, Token::multiCompare("one|two|", "notfound"));
133+
Token *notfound = new Token(0);
134+
notfound->str("notfound");
135+
ASSERT_EQUALS(0, Token::multiCompare(notfound, "|one|two", "notfound"));
136+
ASSERT_EQUALS(0, Token::multiCompare(notfound, "one||two", "notfound"));
137+
ASSERT_EQUALS(0, Token::multiCompare(notfound, "one|two|", "notfound"));
131138

132139
// Test for not found
133-
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare("one|two", "notfound")));
134-
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare("verybig|two", "s")));
135-
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare("one|two", "ne")));
136-
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare("abc|def", "a")));
137-
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare("abc|def", "abcd")));
138-
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare("abc|def", "default")));
140+
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(notfound, "one|two", "notfound")));
141+
142+
Token *s = new Token(0);
143+
s->str("s");
144+
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(s, "verybig|two", "s")));
145+
146+
Token *ne = new Token(0);
147+
ne->str("ne");
148+
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(ne, "one|two", "ne")));
149+
150+
Token *a = new Token(0);
151+
a->str("a");
152+
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(a, "abc|def", "a")));
153+
154+
Token *abcd = new Token(0);
155+
abcd->str("abcd");
156+
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(abcd, "abc|def", "abcd")));
157+
158+
Token *def = new Token(0);
159+
def->str("default");
160+
ASSERT_EQUALS(static_cast<unsigned int>(-1), static_cast<unsigned int>(Token::multiCompare(def, "abc|def", "default")));
139161

140162
// %op%
141-
ASSERT_EQUALS(1, Token::multiCompare("one|%op%", "+"));
142-
ASSERT_EQUALS(1, Token::multiCompare("%op%|two", "+"));
143-
ASSERT_EQUALS(-1, Token::multiCompare("one|%op%", "x"));
144-
ASSERT_EQUALS(-1, Token::multiCompare("%op%|two", "x"));
163+
Token *plus = new Token(0);
164+
plus->str("+");
165+
ASSERT_EQUALS(1, Token::multiCompare(plus, "one|%op%", "+"));
166+
ASSERT_EQUALS(1, Token::multiCompare(plus, "%op%|two", "+"));
167+
Token *x = new Token(0);
168+
x->str("x");
169+
ASSERT_EQUALS(-1, Token::multiCompare(x, "one|%op%", "x"));
170+
ASSERT_EQUALS(-1, Token::multiCompare(x, "%op%|two", "x"));
145171
}
146172

147173
void multiCompare2() { // #3294
@@ -209,7 +235,8 @@ class TestToken : public TestFixture {
209235
ASSERT_EQUALS(Token::eBracket, var.tokens()->tokAt(5)->type());
210236

211237
ASSERT_EQUALS(false, Token::Match(var.tokens(), "std :: queue %op%"));
212-
TODO_ASSERT_EQUALS(false, true, Token::Match(var.tokens(), "std :: queue x|%op%"));
238+
ASSERT_EQUALS(false, Token::Match(var.tokens(), "std :: queue x|%op%"));
239+
ASSERT_EQUALS(false, Token::Match(var.tokens(), "std :: queue %op%|x"));
213240
}
214241

215242
void getStrLength() {

0 commit comments

Comments
 (0)