diff --git a/addons/misra-test.c b/addons/misra-test.c index f90a28846..d9fe12334 100644 --- a/addons/misra-test.c +++ b/addons/misra-test.c @@ -1,58 +1,26 @@ /* ~/cppcheck/cppcheck --dump misra-test.c python misra.py misra-test.c.dump - -Expected output: -[misra-test.c:5] (style) misra: 11 Identifier is longer than 31 characters -[misra-test.c:9] (style) misra: 14 The type char shall always be declared as unsigned char or signed char -[misra-test.c:3] (style) misra: 15 Make sure the floating point implementation comply with a defined floating point standard -[misra-test.c:17] (style) misra: 33 The right hand of a && or || shall not have side effects -[misra-test.c:21] (style) misra: 34 The operands of a && or || shall be primary expressions -[misra-test.c:3] (style) misra: 41 The implementation of integer division in the chosen compiler should be determined, documented and taken into account. -[misra-test.c:25] (style) misra: 56 The goto statement shall not be used -[misra-test.c:29] (style) misra: 57 The continue statement shall not be used */ -void misra11() { +void misra_5_1() { int a123456789012345678901234567890; // no-warning - int a1234567890123456789012345678901; // 11 + int a1234567890123456789012345678901; // 51 } -void misra14() { - char c; // 14 +void misra_7_1() { + int x = 066; // 71 } -void misra19() { - int x = 066; // 19 +void misra_13_5() { + if (x && (y++ < 123)){} // 135 } -void misra28() { - register int x = 3; // 28 +void misra_14_4() { + if (x+4){} // 144 } -enum misra32 { A=1, B, C=10 }; // 32 -enum misra32_ok1 { A, B, C }; -enum misra32_ok2 { A=1, B, C }; - -void misra33() { - if (x && (y++ < 123)){} // 33 +void misra_15_1() { + goto a1; // 151 } -void misra34() { - if (x+3 && y){} // 34 -} - -void misra56() { - goto a1; // 56 -} - -void misra57() { - continue; // 57 -} - -void misra58() { - while (1) { - if(x) - break; // 58 - } -} diff --git a/addons/misra.py b/addons/misra.py index 9b2f2839e..57f89af4b 100644 --- a/addons/misra.py +++ b/addons/misra.py @@ -1,8 +1,6 @@ #/usr/bin/python # -# MISRA checkers -# -# The goal is that this addon will check conformance against latest MISRA C standard. +# MISRA C 2012 checkers # # Example usage of this addon (scan a sourcefile main.cpp) # cppcheck --dump main.cpp @@ -29,746 +27,186 @@ def hasSideEffects(expr): # Todo: Check function calls return hasSideEffects(expr.astOperand1) or hasSideEffects(expr.astOperand2) -def isPrimaryExpression(expr): - return expr and (expr.isName or expr.isNumber or (expr.str in ['!', '==', '!=', '<', '<=', '>', '>=', '&&', '||'])) +def isBoolExpression(expr): + return expr and expr.str in ['!', '==', '!=', '<', '<=', '>', '>=', '&&', '||'] -# 1 -# STATUS: Use compiler -def misra1(data): - return +# 1.1 Done. Use compiler. +# 1.2 Done. gcc +# 1.3 Done. Use Cppcheck, compiler, .. +# 2.1 Done. Use Cppcheck, clang, etc. +# 2.2 Done. Use Cppcheck +# 2.3 TODO +# 2.4 TODO +# 2.5 Done. clang +# 2.6 Done. Cppcheck +# 2.7 Done. clang, gcc +# 3.1 TODO +# 3.2 TODO +# 4.1 TODO +# 4.2 Done. clang, gcc +# 5.1 Done. +# 5.2 Done. +# 5.3 Done. -Wshadow +# 5.4 Done. clang -Weverything +# 5.5 TODO +# 5.6 TODO +# 5.7 TODO +# 5.8 Done. +# 5.9 Done. -Wshadow +# 6.1 TODO +# 6.2 TODO +# 7.1 Done. +# 7.2 TODO +# 7.3 TODO +# 7.4 Done. Cppcheck, gcc, clang +# 8.1 Done. gcc, clang +# 8.2 TODO +# 8.3 Done. Cppcheck +# 8.4 Done. Clang +# 8.5 TODO +# 8.6 TODO +# 8.7 TODO +# 8.8 TODO +# 8.9 TODO +# 8.10 TODO +# 8.11 TODO +# 8.12 TODO +# 8.13 TODO +# 8.14 TODO +# 9.1 Done. Cppcheck. +# 9.2 TODO +# 9.3 TODO +# 9.4 TODO +# 9.5 TODO +# 10.1 TODO +# 10.2 TODO +# 10.3 Done. Cppcheck. +# 10.4 TODO +# 10.5 TODO +# 10.6 TODO +# 10.7 TODO +# 10.8 TODO +# 11.1 TODO +# 11.2 TODO +# 11.3 TODO +# 11.4 TODO +# 11.5 TODO +# 11.6 TODO +# 11.7 TODO +# 11.8 TODO +# 11.9 TODO +# 12.1 TODO +# 12.2 Done. Cppcheck. +# 12.3 TODO +# 12.4 TODO +# 13.1 TODO +# 13.2 TODO +# 13.3 TODO +# 13.4 TODO +# 13.5 Done +# 13.6 Done. Cppcheck. +# 14.1 TODO +# 14.2 TODO +# 14.3 TODO +# 14.4 Done. +# 15.1 Done. +# 15.2 TODO +# 15.3 TODO +# 15.4 TODO +# 15.5 TODO +# 15.6 TODO +# 15.7 TODO +# 16.1 TODO +# 16.2 TODO +# 16.3 TODO +# 16.4 TODO +# 16.5 TODO +# 16.6 TODO +# 16.7 TODO +# 17.1 TODO +# 17.2 TODO +# 17.3 Done. Compiler. +# 17.4 Done. Compiler. +# 17.5 Done. Cppcheck. +# 17.6 TODO +# 17.7 TODO +# 17.8 TODO +# 18.1 TODO +# 18.2 TODO. Cppcheck. +# 18.3 TODO. Cppcheck. +# 18.4 TODO +# 18.5 TODO +# 18.6 TODO +# 18.7 TODO +# 18.8 TODO +# 19.1 TODO +# 19.2 TODO +# 20.1 TODO +# 20.2 TODO +# 20.3 TODO +# 20.4 TODO +# 20.5 TODO +# 20.6 TODO +# 20.7 TODO +# 20.8 TODO +# 20.9 TODO +# 20.10 TODO +# 20.11 TODO +# 20.12 TODO +# 20.13 TODO +# 20.14 TODO +# 21.1 TODO +# 21.2 TODO +# 21.3 TODO +# 21.4 TODO +# 21.5 TODO +# 21.6 TODO +# 21.7 TODO +# 21.8 TODO +# 21.9 TODO +# 21.10 TODO +# 21.11 TODO +# 21.12 TODO +# 22.1 TODO +# 22.2 TODO +# 22.3 TODO +# 22.4 TODO +# 22.5 TODO +# 22.6 TODO -# 2 -# STATUS: ? -def misra2(data): - return -# 3 -# STATUS: Done -def misra3check(token): - prev = token.previous - if not prev or prev.str != '{': - return True - prev = prev.previous - if not prev or prev.str != ')': - return True - prev = prev.link - if not prev or prev.str != '(': - return True - prev = prev.link - if not prev or not prev.isName or (prev in ['for','if','switch','while']): - return True - after = token.next - if not after or after.str != '(': - return True - after = after.link - if not after or after.str != ')': - return True - after = after.next - if not after or after.str != ';': - return True - after = after.next - if not after or after.str != '}': - return True - return False -def misra3(data): - for token in data.tokenlist: - if token.str != 'asm': - continue - if misra3check(token): - reportError(token, 3) - -# 4 -# STATUS: Done. Checked by Cppcheck -def misra4(data): - return - -# 5 -# STATUS: TODO -def misra5(data): - return - -# 6 -# STATUS: TODO -def misra6(data): - return - -# 7 -# STATUS: TODO - requires some info from preprocessor -def misra7(data): - return - -# 8 -# STATUS: TODO -def misra8(data): - return - -# 9 -# STATUS: TODO -def misra9(data): - return - -# 10 -# STATUS: TODO (Parse comments?) -def misra10(data): - return - -# Identifiers -# ----------- - -# 11 -# STATUS: Done. -def misra11(data): +def misra_5_1(data): for token in data.tokenlist: if token.isName and len(token.str) > 31: - reportError(token, 11) + reportError(token, 51) -# 12 -# STATUS: Done. Use compiler (-Wshadow etc) -def misra12(data): - return - -# 13 -# STATUS: TODO originalName is missing right now -def misra13(data): - for token in data.tokenlist: - if not token in ['char','short','int','long','float','double']: - continue - #if token.originalName != '': - -# 14 -# STATUS: Done -def misra14(data): - for token in data.tokenlist: - if token.str != 'char': - continue - if token.isUnsigned or token.isSigned: - continue - reportError(token, 14) - -# 15 -# STATUS: Done -def misra15(data): - reportError(data.tokenlist[0], 15) - -# 16 -# STATUS: TODO : ValueType information is needed -def misra16(data): - return - -# 17 -# STATUS: Done (Cppcheck duplicateTypedef) -def misra17(data): - return - -# 18 -# STATUS: TODO -def misra18(data): - return - -# 19 -# STATUS: Done -def misra19(rawTokens): +def misra_7_1(rawTokens): for tok in rawTokens: - if re.match(r'0[0-7]+', tok.str): - reportError(tok, 19) + if re.match(r'^0[0-7]+$', tok.str): + reportError(tok, 71) -# 20 -# STATUS: Use compiler -def misra20(data): - return - -# 21 -# STATUS: Done. Use compiler (-Wshadow etc). Cppcheck has some checking also. -def misra21(data): - return - -# 22 -# STATUS: TODO -def misra22(data): - return - -# 23 -# STATUS: TODO -def misra23(data): - return - -# 24 -# STATUS: Probably done. Use compiler. -def misra24(data): - return - -# 25 -# STATUS: TODO -def misra25(data): - return - -# 26 -# STATUS: Done. Use compiler. -def misra26(data): - return - -# 27 -# STATUS: TODO -def misra27(data): - return - -# 28 -# STATUS: Done -def misra28(rawTokens): - for token in rawTokens: - if token.str == 'register': - reportError(token, 28) - -# 29 -# STATUS: TODO -def misra29(data): - return - -# 30 -# STATUS: Done. Cppcheck uninitVar etc.. -def misra30(data): - return - -# 31 -# STATUS: TODO -def misra31(data): - return - -# 32 -# STATUS: Done -def misra32(data): - for token in data.tokenlist: - if token.str != 'enum': - continue - - # Goto start '{' - tok = token.next - if tok and tok.isName: - tok = tok.next - if not tok or tok.str != '{': - continue - - # Parse enum body and remember which members are assigned - eqList = [] - eq = False - tok = tok.next - while tok and tok.str != '}': - if tok.str == '=': - eq = True - elif tok.str == ',': - eqList.append(eq) - eq = False - elif tok.link and (tok.str in ['(','[','{','<']): - tok = tok.link - tok = tok.next - eqList.append(eq) - - # is there error? - if len(eqList) <= 1: - continue - err = False - if eqList[0] and eqList[1]: - err = (False in eqList[1:]) - else: - err = (True in eqList[1:]) - if err: - reportError(token, 32) - - -# 33 -# STATUS: Done -def misra33(data): +def misra_13_5(data): for token in data.tokenlist: if token.isLogicalOp and hasSideEffects(token.astOperand2): - reportError(token, 33) + reportError(token, 135) -# 34 -# STATUS: Done -def misra34(data): +def misra_14_4(data): for token in data.tokenlist: - if not token.isLogicalOp: + if token.str != '(': continue - if not isPrimaryExpression(token.astOperand1) or not isPrimaryExpression(token.astOperand2): - reportError(token, 34) + if not token.astOperand1 or not (token.astOperand1.str in ['if', 'while']): + continue + if not isBoolExpression(token.astOperand2): + reportError(token, 144) -# 35 -# STATUS: TODO (The ValueType is not available yet) -def misra35(data): - return - -# 36 -# STATUS: Done. Cppcheck bitwise op checkers. -def misra36(data): - return - -# 37 -# STATUS: TODO The ValueType information is not available yet -def misra37(data): - return - -# 38 -# STATUS: Done. Cppcheck, compilers. -def misra38(data): - return - -# 39 -# STATUS: TODO (ValueType information is needed) -def misra39(data): - return - -# 40 -# STATUS: Done. Cppcheck -def misra40(data): - return - -# 41 -# STATUS: Done -def misra41(data): - reportError(data.tokenlist[0], 41) - -# 42 -# STATUS: TODO -def misra42(data): - return - -# 43 -# STATUS: Done. Cppcheck, Compiler -def misra43(data): - return - -# 44 -# STATUS: TODO -def misra44(data): - return - -# 45 -# STATUS: TODO -def misra45(data): - return - -# 46 -# STATUS: TODO (should be implemented in Cppcheck) -def misra46(data): - return - -# 47 -# STATUS: TODO -def misra47(data): - return - -# 48 -# STATUS: TODO -def misra48(data): - return - -# 49 -# STATUS: TODO -def misra49(data): - return - -# 50 -# STATUS: Done. Compiler -def misra50(data): - return - -# 51 -# STATUS: TODO (ValueType information is needed) -def misra51(data): - return - -# 52 -# STATUS: Done. Cppcheck (condition is always true, unreachable return, etc) -def misra52(data): - return - -# 53 -# STATUS: Done. Cppcheck (useless code, unchecked result) -def misra53(data): - return - -# 54 -# STATUS: TODO -def misra54(data): - return - -# 55 -# STATUS: TODO -def misra55(data): - return - -# 56 -# STATUS: Done. -def misra56(data): +def misra_15_1(data): for token in data.tokenlist: if token.str == "goto": - reportError(token, 56) + reportError(token, 151) -# 57 -# STATUS: Done. -def misra57(data): - for token in data.tokenlist: - if token.str == "continue": - reportError(token, 57) - -# 58 -# STATUS: TODO -def misra58(data): - for token in data.tokenlist: - if token.str != "break": - continue - s = token.scope - while s and s.type == 'If': - s = s.nestedIn - if s and s.type in ['While', 'For']: - reportError(token, 58) - -# 59 -# STATUS: TODO -def misra59(data): - return - -# 60 -# STATUS: TODO -def misra60(data): - return - -# 61 -# STATUS: TODO -def misra61(data): - return - -# 62 -# STATUS: Done. Compiler. -def misra62(data): - return - -# 63 -# STATUS: TODO -def misra63(data): - return - -# 64 -# STATUS: TODO -def misra64(data): - return - -# 65 -# STATUS: TODO -def misra65(data): - return - -# 66 -# STATUS: TODO -def misra66(data): - return - -# 67 -# STATUS: TODO -def misra67(data): - return - -# 68 -# STATUS: TODO -def misra68(data): - return - -# 69 -# STATUS: TODO -def misra69(data): - return - -# 70 -# STATUS: TODO -def misra70(data): - return - -# 71 -# STATUS: Done. Compilers warn about mismatches. -def misra71(data): - return - -# 72 -# STATUS: TODO -def misra72(data): - return - -# 73 -# STATUS: TODO -def misra73(data): - return - -# 74 -# STATUS: Done. Cppcheck builtin checker -def misra74(data): - return - -# 75 -# STATUS: Done. Should be checked by compilers. -def misra75(data): - return - -# 76 -# STATUS: TODO -def misra76(data): - return - -# 77 -# STATUS: TODO -def misra77(data): - return - -# 78 -# STATUS: TODO -def misra78(data): - return - -# 79 -# STATUS: Done. Compilers -def misra79(data): - return - -# 80 -# STATUS: Done. Compilers -def misra80(data): - return - -# 81 -# STATUS: TODO -def misra81(data): - return - -# 82 -# STATUS: TODO -def misra82(data): - return - -# 83 -# STATUS: TODO -def misra83(data): - return - -# 84 -# STATUS: TODO -def misra84(data): - return - -# 85 -# STATUS: TODO -def misra85(data): - return - -# 86 -# STATUS: TODO -def misra86(data): - return - -# 87 -# STATUS: TODO -def misra87(data): - return - -# 88 -# STATUS: TODO -def misra88(data): - return - -# 89 -# STATUS: TODO -def misra89(data): - return - -# 90 -# STATUS: TODO -def misra90(data): - return - -# 91 -# STATUS: TODO -def misra91(data): - return - -# 92 -# STATUS: TODO -def misra92(data): - return - -# 93 -# STATUS: TODO -def misra93(data): - return - -# 94 -# STATUS: TODO -def misra94(data): - return - -# 95 -# STATUS: TODO -def misra95(data): - return - -# 96 -# STATUS: TODO -def misra96(data): - return - -# 97 -# STATUS: TODO -def misra97(data): - return - -# 98 -# STATUS: TODO -def misra98(data): - return - -# 99 -# STATUS: TODO -def misra99(data): - return - -# 100 -# STATUS: TODO -def misra100(data): - return - -# 101 -# STATUS: TODO -def misra101(data): - return - -# 102 -# STATUS: TODO -def misra102(data): - return - -# 103 -# STATUS: TODO -def misra103(data): - return - -# 104 -# STATUS: TODO -def misra104(data): - return - -# 105 -# STATUS: TODO -def misra105(data): - return - -# 106 -# STATUS: TODO -def misra106(data): - return - -# 107 -# STATUS: Cppcheck has this checking -def misra107(data): - return - -# 108 -# STATUS: TODO -def misra108(data): - return - -# 109 -# STATUS: TODO -def misra109(data): - return - -# 110 -# STATUS: TODO -def misra110(data): - return - -# 111 -# STATUS: TODO -def misra111(data): - return - -# 112 -# STATUS: TODO -def misra112(data): - return - -# 113 -# STATUS: TODO -def misra113(data): - return - -# 114 -# STATUS: TODO -def misra114(data): - return - -# 115 -# STATUS: TODO -def misra115(data): - return - -# 116 -# STATUS: TODO -def misra116(data): - return - -# 117 -# STATUS: Cppcheck (--library) -def misra117(data): - return - -# 118 -# STATUS: TODO -def misra118(data): - return - -# 119 -# STATUS: TODO -def misra119(data): - return - -# 120 -# STATUS: TODO -def misra120(data): - return - -# 121 -# STATUS: TODO -def misra121(data): - return - -# 122 -# STATUS: TODO -def misra122(data): - return - -# 123 -# STATUS: TODO -def misra123(data): - return - -# 124 -# STATUS: TODO -def misra124(data): - return - -# 125 -# STATUS: TODO -def misra125(data): - return - -# 126 -# STATUS: TODO -def misra126(data): - return - -# 127 -# STATUS: TODO -def misra127(data): - return for arg in sys.argv[1:]: @@ -781,134 +219,10 @@ for arg in sys.argv[1:]: cfgNumber = cfgNumber + 1 if len(data.configurations) > 1: print('Checking ' + arg + ', config "' + cfg.name + '"...') - misra1(cfg) - misra2(cfg) - misra3(cfg) - misra4(cfg) - misra5(cfg) - misra6(cfg) - misra7(cfg) - misra8(cfg) - misra9(cfg) - misra10(cfg) - misra11(cfg) - misra12(cfg) - misra13(cfg) - misra14(cfg) - misra15(cfg) - misra16(cfg) - misra17(cfg) - misra18(cfg) - if cfgNumber == 1: - misra19(data.rawTokens) - misra20(cfg) - misra21(cfg) - misra22(cfg) - misra23(cfg) - misra24(cfg) - misra25(cfg) - misra26(cfg) - misra27(cfg) - if cfgNumber == 1: - misra28(data.rawTokens) - misra29(cfg) - misra30(cfg) - misra31(cfg) - misra32(cfg) - misra33(cfg) - misra34(cfg) - misra35(cfg) - misra36(cfg) - misra37(cfg) - misra38(cfg) - misra39(cfg) - misra40(cfg) - misra41(cfg) - misra42(cfg) - misra43(cfg) - misra44(cfg) - misra45(cfg) - misra46(cfg) - misra47(cfg) - misra48(cfg) - misra49(cfg) - misra50(cfg) - misra51(cfg) - misra52(cfg) - misra53(cfg) - misra54(cfg) - misra55(cfg) - misra56(cfg) - misra57(cfg) - misra58(cfg) - misra59(cfg) - misra60(cfg) - misra61(cfg) - misra62(cfg) - misra63(cfg) - misra64(cfg) - misra65(cfg) - misra66(cfg) - misra67(cfg) - misra68(cfg) - misra69(cfg) - misra70(cfg) - misra71(cfg) - misra72(cfg) - misra73(cfg) - misra74(cfg) - misra75(cfg) - misra76(cfg) - misra77(cfg) - misra78(cfg) - misra79(cfg) - misra80(cfg) - misra81(cfg) - misra82(cfg) - misra83(cfg) - misra84(cfg) - misra85(cfg) - misra86(cfg) - misra87(cfg) - misra88(cfg) - misra89(cfg) - misra90(cfg) - misra91(cfg) - misra92(cfg) - misra93(cfg) - misra94(cfg) - misra95(cfg) - misra96(cfg) - misra97(cfg) - misra98(cfg) - misra99(cfg) - misra100(cfg) - misra101(cfg) - misra102(cfg) - misra103(cfg) - misra104(cfg) - misra105(cfg) - misra106(cfg) - misra107(cfg) - misra108(cfg) - misra109(cfg) - misra110(cfg) - misra111(cfg) - misra112(cfg) - misra113(cfg) - misra114(cfg) - misra115(cfg) - misra116(cfg) - misra117(cfg) - misra118(cfg) - misra119(cfg) - misra120(cfg) - misra121(cfg) - misra122(cfg) - misra123(cfg) - misra124(cfg) - misra125(cfg) - misra126(cfg) - misra127(cfg) - + misra_5_1(cfg) + if cfgNumber == 1: + misra_7_1(data.rawTokens) + misra_13_5(cfg) + misra_14_4(cfg) + misra_15_1(cfg)