From d181e98d02f4b983d9bcbbc3312188043ab7f085 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Mon, 16 Apr 2018 13:55:12 +0200 Subject: [PATCH] misc.py: Added experimental ellipsisStructArg checker that warns when struct is passed to ellipsis function --- addons/misc.py | 44 ++++++++++++++++++++++++++++++++++++++- addons/test/misc-test.cpp | 14 ++++++++++++- 2 files changed, 56 insertions(+), 2 deletions(-) diff --git a/addons/misc.py b/addons/misc.py index ffabd2375..06cb3aae3 100644 --- a/addons/misc.py +++ b/addons/misc.py @@ -28,6 +28,21 @@ def simpleMatch(token, pattern): token = token.next 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): return tokenString.startswith('"') @@ -64,6 +79,32 @@ def implicitlyVirtual(data): continue 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:]: if arg == '-verify': continue @@ -76,11 +117,12 @@ for arg in sys.argv[1:]: for tok in data.rawTokens: if tok.str.startswith('//'): 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) stringConcatInArrayInit(data.rawTokens) implicitlyVirtual(data) + ellipsisStructArg(data) if VERIFY: for expected in VERIFY_EXPECTED: diff --git a/addons/test/misc-test.cpp b/addons/test/misc-test.cpp index 8029262ae..c2d1b1206 100644 --- a/addons/test/misc-test.cpp +++ b/addons/test/misc-test.cpp @@ -1,6 +1,8 @@ // 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 *b[] = {"a","b" "c"}; // stringConcatInArrayInit const char *c[] = { @@ -17,6 +19,8 @@ const char *c[] = { "b\n" }; + +// Function is implicitly virtual class base { virtual void dostuff(int); }; @@ -24,3 +28,11 @@ class base { class derived : base { 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 +}