Commit f583f039 authored by Paul's avatar Paul
Browse files

Try to use lazy matching

parent 25e722d8
import cppcheck, itertools import cppcheck, itertools
from cppcheckdata import simpleMatch, match from cppcheckdata import simpleMatch, match #patterns, bind_split
def skipTokenMatches(tokens, skip=None): def skipTokenMatches(tokens, skip=None):
...@@ -37,7 +37,6 @@ def getVariableDecl(var): ...@@ -37,7 +37,6 @@ def getVariableDecl(var):
end = end.next end = end.next
return var.typeStartToken.forward(end) return var.typeStartToken.forward(end)
def isFunctionCall(token): def isFunctionCall(token):
if not token: if not token:
return False return False
...@@ -49,6 +48,84 @@ def isFunctionCall(token): ...@@ -49,6 +48,84 @@ def isFunctionCall(token):
return False return False
return True return True
# def isplit(source, sep=' '):
# sepsize = len(sep)
# start = 0
# while True:
# idx = source.find(sep, start)
# if idx == -1:
# yield source[start:]
# return
# yield source[start:idx]
# start = idx + sepsize
# def match_atom(token, p):
# if not token:
# return None
# if not p:
# return None
# if token.str == p:
# return token
# if p in ['!', '|', '||', '%', '!=', '*']:
# return None
# if p in patterns:
# return patterns[p](token)
# if '|' in p:
# for x in isplit(p, '|'):
# t = match_atom(token, x)
# if t:
# return t
# elif p.startswith('!!'):
# t = match_atom(token, p[2:])
# if not t:
# return token
# elif p.startswith('**'):
# a = p[2:]
# t = token
# while t:
# if match_atom(t, a):
# return t
# if t.link and t.str in ['(', '[', '<', '{']:
# t = t.link
# t = t.next
# return None
# class MatchResult:
# def __init__(self, matches, bindings=None, keys=None):
# self.__dict__.update(bindings or {})
# self._matches = matches
# self._keys = keys or []
# def __bool__(self):
# return self._matches
# def __nonzero__(self):
# return self._matches
# def __getattr__(self, k):
# if not self._matches:
# return None
# if k in self._keys:
# return None
# else:
# raise AttributeError
# def match(token, pattern):
# if not pattern:
# return MatchResult(False)
# end = None
# bindings = {}
# words = (bind_split(word) for word in isplit(pattern))
# for p, b in words:
# t = match_atom(token, p)
# if b:
# bindings[b] = token
# if not t:
# return MatchResult(False)
# end = t
# token = t.next
# bindings['end'] = end
# return MatchResult(True, bindings=bindings)
@cppcheck.checker @cppcheck.checker
def AvoidBranchingStatementAsLastInLoop(cfg, data): def AvoidBranchingStatementAsLastInLoop(cfg, data):
...@@ -81,8 +158,8 @@ def AvoidBranchingStatementAsLastInLoop(cfg, data): ...@@ -81,8 +158,8 @@ def AvoidBranchingStatementAsLastInLoop(cfg, data):
@cppcheck.checker @cppcheck.checker
def ConditionalAssert(cfg, data): def ConditionalAssert(cfg, data):
for token in cfg.tokenlist: for token in cfg.tokenlist:
if token.str != 'if': # if token.str != 'if':
continue # continue
if not match(token, "if (*) { assert (*) ; }"): if not match(token, "if (*) { assert (*) ; }"):
continue continue
cppcheck.reportError(token, "style", cppcheck.reportError(token, "style",
...@@ -92,8 +169,8 @@ def ConditionalAssert(cfg, data): ...@@ -92,8 +169,8 @@ def ConditionalAssert(cfg, data):
@cppcheck.checker @cppcheck.checker
def EmptyCatchStatement(cfg, data): def EmptyCatchStatement(cfg, data):
for token in cfg.tokenlist: for token in cfg.tokenlist:
if token.str != 'catch': # if token.str != 'catch':
continue # continue
if not match(token, "catch (*) { }"): if not match(token, "catch (*) { }"):
continue continue
cppcheck.reportError(token, "style", "An empty catch statement.") cppcheck.reportError(token, "style", "An empty catch statement.")
...@@ -102,8 +179,8 @@ def EmptyCatchStatement(cfg, data): ...@@ -102,8 +179,8 @@ def EmptyCatchStatement(cfg, data):
@cppcheck.checker @cppcheck.checker
def EmptyDoWhileStatement(cfg, data): def EmptyDoWhileStatement(cfg, data):
for token in cfg.tokenlist: for token in cfg.tokenlist:
if token.str != 'do': # if token.str != 'do':
continue # continue
if not simpleMatch(token, "do { } while ("): if not simpleMatch(token, "do { } while ("):
continue continue
cppcheck.reportError(token, "style", "Empty do-while.") cppcheck.reportError(token, "style", "Empty do-while.")
...@@ -112,8 +189,8 @@ def EmptyDoWhileStatement(cfg, data): ...@@ -112,8 +189,8 @@ def EmptyDoWhileStatement(cfg, data):
@cppcheck.checker @cppcheck.checker
def EmptyElseBlock(cfg, data): def EmptyElseBlock(cfg, data):
for token in cfg.tokenlist: for token in cfg.tokenlist:
if token.str != 'else': # if token.str != 'else':
continue # continue
if not simpleMatch(token, "else { }"): if not simpleMatch(token, "else { }"):
continue continue
cppcheck.reportError(token, "style", cppcheck.reportError(token, "style",
...@@ -123,8 +200,8 @@ def EmptyElseBlock(cfg, data): ...@@ -123,8 +200,8 @@ def EmptyElseBlock(cfg, data):
@cppcheck.checker @cppcheck.checker
def EmptyForStatement(cfg, data): def EmptyForStatement(cfg, data):
for token in cfg.tokenlist: for token in cfg.tokenlist:
if token.str != 'for': # if token.str != 'for':
continue # continue
if not match(token, "for (*) { }"): if not match(token, "for (*) { }"):
continue continue
cppcheck.reportError(token, "style", "Empty for statement.") cppcheck.reportError(token, "style", "Empty for statement.")
...@@ -133,8 +210,8 @@ def EmptyForStatement(cfg, data): ...@@ -133,8 +210,8 @@ def EmptyForStatement(cfg, data):
@cppcheck.checker @cppcheck.checker
def EmptyIfStatement(cfg, data): def EmptyIfStatement(cfg, data):
for token in cfg.tokenlist: for token in cfg.tokenlist:
if token.str != 'if': # if token.str != 'if':
continue # continue
if not match(token, "if (*) { }"): if not match(token, "if (*) { }"):
continue continue
cppcheck.reportError(token, "style", "Empty if statement.") cppcheck.reportError(token, "style", "Empty if statement.")
...@@ -143,8 +220,8 @@ def EmptyIfStatement(cfg, data): ...@@ -143,8 +220,8 @@ def EmptyIfStatement(cfg, data):
@cppcheck.checker @cppcheck.checker
def EmptySwitchStatement(cfg, data): def EmptySwitchStatement(cfg, data):
for token in cfg.tokenlist: for token in cfg.tokenlist:
if token.str != 'switch': # if token.str != 'switch':
continue # continue
if not match(token, "switch (*) { }"): if not match(token, "switch (*) { }"):
continue continue
cppcheck.reportError(token, "style", "Empty switch statement.") cppcheck.reportError(token, "style", "Empty switch statement.")
...@@ -153,8 +230,8 @@ def EmptySwitchStatement(cfg, data): ...@@ -153,8 +230,8 @@ def EmptySwitchStatement(cfg, data):
@cppcheck.checker @cppcheck.checker
def EmptyWhileStatement(cfg, data): def EmptyWhileStatement(cfg, data):
for token in cfg.tokenlist: for token in cfg.tokenlist:
if token.str != 'while': # if token.str != 'while':
continue # continue
if not match(token, "while (*) { }"): if not match(token, "while (*) { }"):
continue continue
cppcheck.reportError(token, "style", "Empty while statement.") cppcheck.reportError(token, "style", "Empty while statement.")
...@@ -163,8 +240,8 @@ def EmptyWhileStatement(cfg, data): ...@@ -163,8 +240,8 @@ def EmptyWhileStatement(cfg, data):
@cppcheck.checker @cppcheck.checker
def ForLoopShouldBeWhileLoop(cfg, data): def ForLoopShouldBeWhileLoop(cfg, data):
for token in cfg.tokenlist: for token in cfg.tokenlist:
if token.str != 'for': # if token.str != 'for':
continue # continue
if not match(token, "for ( ; !!;"): if not match(token, "for ( ; !!;"):
continue continue
# Skip empty for loops # Skip empty for loops
...@@ -201,8 +278,8 @@ def GotoStatement(cfg, data): ...@@ -201,8 +278,8 @@ def GotoStatement(cfg, data):
@cppcheck.checker @cppcheck.checker
def LambdaAttribute(cfg, data): def LambdaAttribute(cfg, data):
for token in cfg.tokenlist: for token in cfg.tokenlist:
if token.str != ']': # if token.str != ']':
continue # continue
if not match(token, "] __device__|__host__ {|("): if not match(token, "] __device__|__host__ {|("):
continue continue
cppcheck.reportError( cppcheck.reportError(
...@@ -228,8 +305,8 @@ def MultipleUnaryOperator(cfg, data): ...@@ -228,8 +305,8 @@ def MultipleUnaryOperator(cfg, data):
@cppcheck.checker @cppcheck.checker
def MutableVariable(cfg, data): def MutableVariable(cfg, data):
for token in cfg.tokenlist: for token in cfg.tokenlist:
if token.str != 'mutable': # if token.str != 'mutable':
continue # continue
if not match(token, "mutable %var%"): if not match(token, "mutable %var%"):
continue continue
cppcheck.reportError(token, "style", cppcheck.reportError(token, "style",
...@@ -271,8 +348,8 @@ def RedundantCast(cfg, data): ...@@ -271,8 +348,8 @@ def RedundantCast(cfg, data):
@cppcheck.checker @cppcheck.checker
def RedundantConditionalOperator(cfg, data): def RedundantConditionalOperator(cfg, data):
for token in cfg.tokenlist: for token in cfg.tokenlist:
if token.str != '?': # if token.str != '?':
continue # continue
if not match(token, "? true|false : true|false"): if not match(token, "? true|false : true|false"):
continue continue
cppcheck.reportError(token, "style", cppcheck.reportError(token, "style",
...@@ -282,8 +359,8 @@ def RedundantConditionalOperator(cfg, data): ...@@ -282,8 +359,8 @@ def RedundantConditionalOperator(cfg, data):
@cppcheck.checker @cppcheck.checker
def RedundantIfStatement(cfg, data): def RedundantIfStatement(cfg, data):
for token in cfg.tokenlist: for token in cfg.tokenlist:
if token.str != 'if': # if token.str != 'if':
continue # continue
if not match( if not match(
token, token,
"if (*) { return true|false ; } else { return true|false ; }"): "if (*) { return true|false ; } else { return true|false ; }"):
...@@ -329,8 +406,8 @@ def RedundantLocalVariable(cfg, data): ...@@ -329,8 +406,8 @@ def RedundantLocalVariable(cfg, data):
@cppcheck.checker @cppcheck.checker
def UnnecessaryEmptyCondition(cfg, data): def UnnecessaryEmptyCondition(cfg, data):
for token in cfg.tokenlist: for token in cfg.tokenlist:
if token.str != 'if': # if token.str != 'if':
continue # continue
m = match(token, "if (*)@if_cond { for (*)@for_cond {*} }") m = match(token, "if (*)@if_cond { for (*)@for_cond {*} }")
if not m: if not m:
continue continue
...@@ -362,12 +439,7 @@ def UseDeviceLaunch(cfg, data): ...@@ -362,12 +439,7 @@ def UseDeviceLaunch(cfg, data):
@cppcheck.checker @cppcheck.checker
def UseManagePointer(cfg, data): def UseManagePointer(cfg, data):
functions = { functions = {"fclose", "free", "hipFree", "hipHostFree", "hipFreeArray", "hipMemFree", "hipStreamDestroy", "hipEventDestroy", "hipArrayDestroy", "hipCtxDestroy", "hipDestroyTextureObject", "hipDestroySurfaceObject", "miirDestroyHandle"}
"fclose", "free", "hipFree", "hipHostFree", "hipFreeArray",
"hipMemFree", "hipStreamDestroy", "hipEventDestroy", "hipArrayDestroy",
"hipCtxDestroy", "hipDestroyTextureObject", "hipDestroySurfaceObject",
"miirDestroyHandle"
}
for token in cfg.tokenlist: for token in cfg.tokenlist:
if not isFunctionCall(token): if not isFunctionCall(token):
continue continue
...@@ -380,8 +452,8 @@ def UseManagePointer(cfg, data): ...@@ -380,8 +452,8 @@ def UseManagePointer(cfg, data):
@cppcheck.checker @cppcheck.checker
def UseSmartPointer(cfg, data): def UseSmartPointer(cfg, data):
for token in cfg.tokenlist: for token in cfg.tokenlist:
if token.str != 'new': # if token.str != 'new':
continue # continue
if not match(token, "new %name%"): if not match(token, "new %name%"):
continue continue
cppcheck.reportError(token, "style", cppcheck.reportError(token, "style",
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment