misc.py: Added experimental ellipsisStructArg checker that warns when struct is passed to ellipsis function

This commit is contained in:
Daniel Marjamäki 2018-04-16 13:55:12 +02:00
parent 194b4096c2
commit d181e98d02
2 changed files with 56 additions and 2 deletions

View File

@ -28,6 +28,21 @@ def simpleMatch(token, pattern):
token = token.next token = token.next
return True return True
# Get function arguments
def getArgumentsRecursive(tok, arguments):
if tok is None:
return
if tok.str == ',':
getArgumentsRecursive(tok.astOperand1, arguments)
getArgumentsRecursive(tok.astOperand2, arguments)
else:
arguments.append(tok);
def getArguments(ftok):
arguments = []
getArgumentsRecursive(ftok.astOperand2, arguments)
return arguments
def isStringLiteral(tokenString): def isStringLiteral(tokenString):
return tokenString.startswith('"') return tokenString.startswith('"')
@ -64,6 +79,32 @@ def implicitlyVirtual(data):
continue continue
reportError(function.tokenDef, 'style', 'Function \'' + function.name + '\' overrides base class function but is not marked with \'virtual\' keyword.', 'implicitlyVirtual') reportError(function.tokenDef, 'style', 'Function \'' + function.name + '\' overrides base class function but is not marked with \'virtual\' keyword.', 'implicitlyVirtual')
def ellipsisStructArg(data):
for cfg in data.configurations:
for tok in cfg.tokenlist:
if tok.str != '(':
continue
if tok.astOperand1 is None or tok.astOperand2 is None:
continue
if tok.astOperand1.function is None:
continue
for argnr, argvar in tok.astOperand1.function.argument.items():
if argnr < 1:
continue
if not simpleMatch(argvar.typeStartToken, '. . .'):
continue
callArgs = getArguments(tok)
for i in range(argnr-1, len(callArgs)):
valueType = callArgs[i].valueType
if not valueType:
continue
if valueType.pointer > 0:
continue
if valueType.type != 'record':
continue
reportError(tok, 'style', 'Passing record to ellipsis function \'' + tok.astOperand1.function.name + '\'.', 'ellipsisStructArg')
break
for arg in sys.argv[1:]: for arg in sys.argv[1:]:
if arg == '-verify': if arg == '-verify':
continue continue
@ -76,11 +117,12 @@ for arg in sys.argv[1:]:
for tok in data.rawTokens: for tok in data.rawTokens:
if tok.str.startswith('//'): if tok.str.startswith('//'):
for word in tok.str[2:].split(' '): for word in tok.str[2:].split(' '):
if word == 'stringConcatInArrayInit' or word == 'implicitlyVirtual': if word in ['stringConcatInArrayInit', 'implicitlyVirtual', 'ellipsisStructArg']:
VERIFY_EXPECTED.append(str(tok.linenr) + ':' + word) VERIFY_EXPECTED.append(str(tok.linenr) + ':' + word)
stringConcatInArrayInit(data.rawTokens) stringConcatInArrayInit(data.rawTokens)
implicitlyVirtual(data) implicitlyVirtual(data)
ellipsisStructArg(data)
if VERIFY: if VERIFY:
for expected in VERIFY_EXPECTED: for expected in VERIFY_EXPECTED:

View File

@ -1,6 +1,8 @@
// To test: // To test:
// ~/cppcheck/cppcheck --dump misc-test.c && python ../misc.py -verify misc-test.c.dump // ~/cppcheck/cppcheck --dump misc-test.cpp && python ../misc.py -verify misc-test.cpp.dump
// Warn about string concatenation in array initializers..
const char *a[] = {"a" "b"}; const char *a[] = {"a" "b"};
const char *b[] = {"a","b" "c"}; // stringConcatInArrayInit const char *b[] = {"a","b" "c"}; // stringConcatInArrayInit
const char *c[] = { const char *c[] = {
@ -17,6 +19,8 @@ const char *c[] = {
"b\n" "b\n"
}; };
// Function is implicitly virtual
class base { class base {
virtual void dostuff(int); virtual void dostuff(int);
}; };
@ -24,3 +28,11 @@ class base {
class derived : base { class derived : base {
void dostuff(int); // implicitlyVirtual void dostuff(int); // implicitlyVirtual
}; };
// Pass struct to ellipsis function
struct {int x;int y;} s;
void ellipsis(int x, ...);
void foo(void) {
ellipsis(321, s); // ellipsisStructArg
}