diff --git a/addons/misra.py b/addons/misra.py index bbf7e6c558e..9971c3dae72 100755 --- a/addons/misra.py +++ b/addons/misra.py @@ -45,7 +45,28 @@ def grouped(iterable, n): ['int', 'uint', 'int_least', 'uint_least', 'int_fast', 'uint_fast'], [8, 16, 32, 64])] +STDINT_H_DEFINES_MIN = ['%s%d_MIN' % (n, v) for n, v in itertools.product( + ['INT', 'INT_LEAST', 'INT_FAST',], + [8, 16, 32, 64])] + +STDINT_H_DEFINES_MAX = ['%s%d_MAX' % (n, v) for n, v in itertools.product( + ['INT', 'UINT','INT_LEAST','UINT_LEAST', 'INT_FAST', 'UINT_FAST',], + [8, 16, 32, 64])] +STDINT_H_DEFINES_C = ['%s%d_C' % (n, v) for n, v in itertools.product( + ['INT', 'UINT'], + [8, 16, 32, 64])] + + +INTTYPES_H_DEFINES = ['%s%d' % (n, v) for n, v in itertools.product( + ['PRId', 'PRIi', 'PRIo', 'PRIu', 'PRIx', 'PRIX', 'SCNd', + 'SCNi', 'SCNo', 'SCNu', 'SCNx', 'PRIdLEAST', 'PRIiLEAST', + 'PRIoLEAST', 'PRIuLEAST', 'PRIxLEAST', 'PRIXLEAST', + 'SCNdLEAST', 'SCNiLEAST', 'SCNoLEAST', 'SCNuLEAST', + 'SCNxLEAST', 'PRIdFAST', 'PRIiFAST', 'PRIoFAST', 'PRIuFAST', + 'PRIxFAST', 'PRIXFAST', 'SCNdFAST', 'SCNiFAST', 'SCNoFAST', + 'SCNuFAST', 'SCNxFAST', ], + [8, 16, 32, 64])] typeBits = { 'CHAR': None, 'SHORT': None, @@ -169,7 +190,8 @@ def rawlink(rawtoken): # Identifiers described in Section 7 "Library" of C99 Standard -# Based on ISO/IEC 9899 WF14/N1256 Annex B -- Library summary +# Based on ISO/IEC 9899:1999 (E) Annex B -- Library summary +# (https://www.dii.uchile.cl/~daespino/files/Iso_C_1999_definition.pdf) C99_STDLIB_IDENTIFIERS = { # B.1 Diagnostics 'assert.h': C90_STDLIB_IDENTIFIERS['assert.h'], @@ -220,9 +242,13 @@ def rawlink(rawtoken): 'float.h': C90_STDLIB_IDENTIFIERS['float.h'] + ['FLT_EVAL_METHOD'], # B.7 Format conversion of integer types 'inttypes.h': [ + 'PRIdMAX', 'PRIiMAX', 'PRIoMAX', 'PRIuMAX', 'PRIxMAX', 'PRIXMAX', + 'SCNdMAX', 'SCNiMAX', 'SCNoMAX', 'SCNuMAX', 'SCNxMAX', 'PRIdPTR', + 'PRIiPTR', 'PRIoPTR', 'PRIuPTR', 'PRIxPTR', 'PRIXPTR', 'SCNdPTR', + 'SCNiPTR', 'SCNoPTR', 'SCNuPTR', 'SCNxPTR', 'imaxdiv_t', 'imaxabs', 'imaxdiv', 'strtoimax', 'strtoumax', 'wcstoimax', 'wcstoumax', - ], + ] + INTTYPES_H_DEFINES, # B.8 Alternative spellings 'iso646.h': [ 'and', 'and_eq', 'bitand', 'bitor', 'compl', 'not', 'not_eq', @@ -246,11 +272,12 @@ def rawlink(rawtoken): 'acoshl', 'asinh', 'asinhf', 'asinhl', 'atanh', 'atanhf', 'atanhl', 'cosh', 'coshf', 'coshl', 'sinh', 'sinhf', 'sinhl', 'tanh', 'tanhf', 'tanhl', 'expf', 'expl', 'exp2', 'exp2f', 'exp2l', 'expm1', 'expm1f', - 'expm1l', 'frexpf', 'frexpl', 'ilogb', 'ilogbf', 'ilogbl', 'float', + 'expm1l', 'frexpf', 'frexpl', 'ilogb', 'ilogbf', 'ilogbl', 'ldexpf', 'ldexpl', 'logf', 'logl', 'log10f', 'log10l', 'log1p', 'log1pf', 'log1pl', 'log2', 'log2f', 'log2l', 'logb', 'logbf', 'logbl', 'modff', 'modfl', 'scalbn', 'scalbnf', 'scalbnl', 'scalbln', 'scalblnf', - 'scalblnl', 'hypotl', 'powf', 'powl', 'sqrtf', 'sqrtl', 'erf', 'erff', + 'scalblnl','cbrt', 'cbrtf','cbrtl', 'fabs', 'fabsf', 'fabsl', + 'hypotl', 'hypotf', 'powf', 'powl', 'sqrtf', 'sqrtl', 'erf', 'erff', 'erfl', 'erfc', 'erfcf', 'erfcl', 'lgamma', 'lgammaf', 'lgammal', 'tgamma', 'tgammaf', 'tgammal', 'ceilf', 'ceill', 'floorf', 'floorl', 'nearbyint', 'nearbyintf', 'nearbyintl', 'rint', 'rintf', 'rintl', @@ -261,7 +288,7 @@ def rawlink(rawtoken): 'remquol', 'copysign', 'copysignf', 'copysignl', 'nan', 'nanf', 'nanl', 'nextafter', 'nextafterf', 'nextafterl', 'nexttoward', 'nexttowardf', 'nexttowardl', 'fdim', 'fdimf', 'fdiml', 'fmax', - 'fmaxf', 'fmaxl', 'fmin', 'fminf', 'fminl', 'fmal', 'isgreater', + 'fmaxf', 'fmaxl', 'fmin', 'fminf', 'fminl', 'fmaf','fmal', 'isgreater', 'isgreaterequal', 'isless', 'islessequal', 'islessgreater', 'isunordered', ], @@ -284,11 +311,11 @@ def rawlink(rawtoken): 'UINTMAX_MAX', 'PTRDIFF_MIN', 'PTRDIFF_MAX', 'SIG_ATOMIC_MIN', 'SIG_ATOMIC_MAX', 'SIZE_MAX', 'WCHAR_MIN', 'WCHAR_MAX', 'WINT_MIN', 'WINT_MAX', 'INTN_C', 'UINTN_C', 'INTMAX_C', 'UINTMAX_C', - ] + STDINT_TYPES, + ] + STDINT_TYPES + STDINT_H_DEFINES_MIN + STDINT_H_DEFINES_MAX + STDINT_H_DEFINES_C, # B.18 Input/output 'stdio.h': C90_STDLIB_IDENTIFIERS['stdio.h'] + [ 'mode', 'restrict', 'snprintf', 'vfscanf', 'vscanf', - 'vsnprintf', 'vsscanf', + 'vsnprintf', 'vsscanf','ftell' ], # B.19 General utilities 'stdlib.h': C90_STDLIB_IDENTIFIERS['stdlib.h'] + [ @@ -317,22 +344,148 @@ def rawlink(rawtoken): 'vfwprintf', 'vfwscanf', 'vswprintf', 'vswscanf', 'vwprintf', 'vwscanf', 'wprintf', 'wscanf', 'fgetwc', 'fgetws', 'fputwc', 'fputws', 'fwide', 'getwc', 'getwchar', 'putwc', 'putwchar', 'ungetwc', 'wcstod', - 'wcstof', 'double', 'int', 'long', 'long', 'long', 'wcscpy', 'wcsncpy', - 'wmemcpy', 'wmemmove', 'wcscat', 'wcsncat', 'wcscmp', 'wcscoll', + 'wcstof', 'wcstold', 'wcstol', 'wcstoll', 'wcstoul', 'wcstoull', 'wcscpy', + 'wcsncpy', 'wmemcpy', 'wmemmove', 'wcscat', 'wcsncat', 'wcscmp', 'wcscoll', 'wcsncmp', 'wcsxfrm', 'wmemcmp', 'wcschr', 'wcscspn', 'wcspbrk', 'wcsrchr', 'wcsspn', 'wcsstr', 'wcstok', 'wmemchr', 'wcslen', 'wmemset', 'wcsftime', 'btowc', 'wctob', 'mbsinit', 'mbrlen', 'mbrtowc', 'wcrtomb', 'mbsrtowcs', 'wcsrtombs', ], + # B.24 Wide character classification and mapping utilities + 'wctype.h': ['wint_t', 'wctrans_t', 'wctype_t', 'WEOF', + 'iswalnum', 'iswalpha', 'iswblank', 'iswcntrl', 'iswdigit', + 'iswgraph', 'iswlower', 'iswprint', 'iswpunct', 'iswspace', 'iswupper', + 'iswxdigit', 'iswctype', 'wctype', 'towlower', 'towupper', 'towctrans', + 'wctrans'], } +# Identifiers described in Section 7 "Library" of C11 Standard +# Based on ISO/IEC 9899:201x N1570 (Draft 12.04.2011) Annex B -- Library summary +# (https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) +C11_STDLIB_IDENTIFIERS = { + # B.1 Diagnostics + 'assert.h': C99_STDLIB_IDENTIFIERS['assert.h']+ ['static_assert'], + # B.2 Complex + 'complex.h': C99_STDLIB_IDENTIFIERS['complex.h']+['__STDC_NO_COMPLEX__','CMPLX','CMPLXF','CMPLXL'], + # B.3 Character handling + 'ctype.h': C99_STDLIB_IDENTIFIERS['ctype.h'], + # B.4 Errors + 'errno.h': C99_STDLIB_IDENTIFIERS['errno.h']+['__STDC_WANT_LIB_EXT1__', 'errno_t'], + # B.5 Floating-point environment + 'fenv.h': C99_STDLIB_IDENTIFIERS['fenv.h'], + # B.6 Characteristics of floating types + 'float.h': C99_STDLIB_IDENTIFIERS['float.h']+[ + 'FLT_HAS_SUBNORM','DBL_HAS_SUBNORM','LDBL_HAS_SUBNORM', + 'FLT_DECIMAL_DIG','DBL_DECIMAL_DIG','LDBL_DECIMAL_DIG', + 'FLT_TRUE_MIN','DBL_TRUE_MIN','LDBL_TRUE_MIN'], + # B.7 Format conversion of integer types + 'inttypes.h': C99_STDLIB_IDENTIFIERS["inttypes.h"], + # B.8 Alternative spellings + 'iso646.h': C99_STDLIB_IDENTIFIERS["iso646.h"], + # B.9 Size of integer types + 'limits.h': C99_STDLIB_IDENTIFIERS['limits.h'], + # B.10 Localization + 'locale.h': C99_STDLIB_IDENTIFIERS['locale.h'], + # B.11 Mathematics + 'math.h': C99_STDLIB_IDENTIFIERS['math.h'], + # B.12 Nonlocal jumps + 'setjmp.h': C99_STDLIB_IDENTIFIERS['setjmp.h'], + # B.13 Signal handling + 'signal.h': C99_STDLIB_IDENTIFIERS['signal.h'], + # B.14 Alignment + 'stdalign.h': ['alignas','__alignas_is_defined'], + # B.15 Variable arguments + 'stdarg.h': C99_STDLIB_IDENTIFIERS['stdarg.h'], + # B.16 Atomics + 'stdatomic.h': ['ATOMIC_BOOL_LOCK_FREE', 'ATOMIC_CHAR_LOCK_FREE', + 'ATOMIC_CHAR16_T_LOCK_FREE', 'ATOMIC_CHAR32_T_LOCK_FREE', 'ATOMIC_WCHAR_T_LOCK_FREE', + 'ATOMIC_SHORT_LOCK_FREE', 'ATOMIC_INT_LOCK_FREE', 'ATOMIC_LONG_LOCK_FREE', + 'ATOMIC_LLONG_LOCK_FREE', 'ATOMIC_POINTER_LOCK_FREE', 'ATOMIC_FLAG_INIT', + 'memory_order', 'atomic_flag', 'memory_order_relaxed', 'memory_order_consume', + 'memory_order_acquire', 'memory_order_release', 'memory_order_acq_rel', 'memory_order_seq_cst', + 'atomic_bool', 'atomic_char', 'atomic_schar', 'atomic_uchar', 'atomic_short', 'atomic_ushort', + 'atomic_int', 'atomic_uint', 'atomic_long', 'atomic_ulong', 'atomic_llong', 'atomic_ullong', + 'atomic_char16_t', 'atomic_char32_t', 'atomic_wchar_t', 'atomic_int_least8_t', + 'atomic_uint_least8_t', 'atomic_int_least16_t', 'atomic_uint_least16_t', + 'atomic_int_least32_t', 'atomic_uint_least32_t', 'atomic_int_least64_t', + 'atomic_uint_least64_t', 'atomic_int_fast8_t', 'atomic_uint_fast8_t', + 'atomic_int_fast16_t', 'atomic_uint_fast16_t', 'atomic_int_fast32_t', + 'atomic_uint_fast32_t', 'atomic_int_fast64_t', 'atomic_uint_fast64_t', + 'atomic_intptr_t', 'atomic_uintptr_t', 'atomic_size_t', 'atomic_ptrdiff_t', + 'atomic_intmax_t', 'atomic_uintmax_t', 'ATOMIC_VAR_INIT', 'type kill_dependency', + 'atomic_thread_fence', 'atomic_signal_fence', 'atomic_is_lock_free', + 'atomic_store', 'atomic_store_explicit', 'atomic_load', 'atomic_load_explicit', + 'atomic_exchange', 'atomic_exchange_explicit', 'atomic_compare_exchange_strong', + 'atomic_compare_exchange_strong_explicit', 'atomic_compare_exchange_weak', + 'atomic_compare_exchange_weak_explicit', 'atomic_fetch_key', 'atomic_fetch_key_explicit', + 'atomic_flag_test_and_set', 'atomic_flag_test_and_set_explicit', + 'atomic_flag_clear', 'atomic_flag_clear_explicit', ], + # B.17 Boolean type and values + 'stdbool.h': C99_STDLIB_IDENTIFIERS['stdbool.h'], + # B.18 Common definitions + 'stddef.h': C99_STDLIB_IDENTIFIERS['stddef.h'] + + ['max_align_t','__STDC_WANT_LIB_EXT1__', 'rsize_t'], + # B.19 Integer types + 'stdint.h': C99_STDLIB_IDENTIFIERS['stdint.h']+ + ['__STDC_WANT_LIB_EXT1__', 'RSIZE_MAX'], + # B.20 Input/output + 'stdio.h': C99_STDLIB_IDENTIFIERS['stdio.h'] + + ['__STDC_WANT_LIB_EXT1__', 'L_tmpnam_s', 'TMP_MAX_S', 'errno_t', 'rsize_t', + 'tmpfile_s', 'tmpnam_s', 'fopen_s', 'freopen_s', 'fprintf_s', 'fscanf_s', + 'printf_s','scanf_s','snprintf_s','sprintf_s','sscanf_s','vfprintf_s', + 'vfscanf_s', 'vsprintf_s', 'vsscanf_s', 'gets_s' + ], + # B.21 General utilities + 'stdlib.h': C99_STDLIB_IDENTIFIERS['stdlib.h'] + + ['constraint_handler_t', 'set_constraint_handler_s', 'abort_handler_s', + 'ignore_handler_s', 'getenv_s', 'bsearch_s', 'qsort_s', 'wctomb_s', + 'mbstowcs_s', 'wcstombs_s'], + # B.22 Noretrun + 'stdnoreturn.h': ['noreturn'], + # B.23 String handling + 'string.h': C99_STDLIB_IDENTIFIERS['string.h'] + + ['memcpy_s', 'memmoce_s', 'strcpy_s', 'strncpy_s','strcat_s', + 'strtok_s', 'memset_s', 'strerror_s', 'strerrorlen_s', 'strnlen_s'], + # B.24 Type-generic math + 'tgmath.h': C99_STDLIB_IDENTIFIERS['tgmath.h'], + # B.25 Threads + 'threads.h': ['thread_local', 'ONCE_FLAG_INIT', 'TSS_DTOR_ITERATIONS', + 'cnd_t', 'thrd_t', 'tss_t', 'mtx_t', 'tss_dtor_t', 'thrd_start_t', + 'once_flag', 'mtx_plain', 'mtx_recursive', 'mtx_timed', 'thrd_timedout', + 'thrd_success', 'thrd_busy', 'thrd_error', 'thrd_nomem', 'call_once', + 'cnd_broadcast', 'cnd_destroy','cnd_init', 'cnd_signal', 'cnd_timedwait', + 'cnd_wait','mtx_destroy', 'mtx_init', 'mtx_lock', 'mtx_timedlock', + 'mtx_trylock', 'mtx_unlock', 'thrd_create', 'thrd_current', + 'thrd_detach', 'thrd_equal', 'thrd_exit', 'thrd_join', 'thrd_sleep', + 'thrd_yield', 'tss_create', 'tss_delete', 'tss_get', 'tss_set' ], + # B.26 Date and time + 'time.h': C99_STDLIB_IDENTIFIERS['time.h'] + [ + 'asctime_s', 'ctime_s', 'gmtime_s', 'localtime_s' + ], + # B.27 Unicode utilities + 'uchar.h': ['mbstate_t', 'size_t', 'char16_t', 'char32_t', + 'mbrtoc16', 'c16rtomb', 'mbrtoc32', 'c32rtomb' + ], + # B.28 Extended multibyte/wide character utilities + 'wchar.h': C99_STDLIB_IDENTIFIERS["wchar.h"]+[ + 'fwprintf_s', 'fwscanf_s', 'snwprintf_s', 'swprintf_s', 'swscanf_s', + 'vfwprintf_s', 'vfwscanf_s', 'vsnwprintf_s', 'vswprintf_s', 'vswscanf_s', + 'vwprintf_s', 'vwscanf_s', 'wprintf_s', 'wscanf_s', 'wcscpy_s', 'wcsncpy_s', + 'wmemcpy_s', 'wmemmove_s', 'wcscat_s', 'wcsncat_s', 'wcstok_s', 'wcsnlen_s', + 'wcrtomb_s', 'mbsrtowcs_s', 'wcsrtombs_s', + ], + # B.29 Wide character classification and mapping utilities + 'wctype.h': C99_STDLIB_IDENTIFIERS['wctype.h'], +} def isStdLibId(id_, standard='c99'): id_lists = [] if standard == 'c89': id_lists = C90_STDLIB_IDENTIFIERS.values() - elif standard in ('c99', 'c11'): + elif standard == 'c99': id_lists = C99_STDLIB_IDENTIFIERS.values() + else: + id_lists = C11_STDLIB_IDENTIFIERS.values() for l in id_lists: if id_ in l: return True @@ -349,16 +502,23 @@ def isStdLibId(id_, standard='c99'): } -# Reserved keywords defined in ISO/IEC 9899 WF14/N1256 -- ch. 6.4.1 +# Reserved keywords defined in Section 6.4.1 "Language" of C99 Standard +# Based on ISO/IEC 9899:1999 (E) 6.4.1 Keywords +# Adding the expanding macros from Section 7 too +# (https://www.dii.uchile.cl/~daespino/files/Iso_C_1999_definition.pdf) C99_ADDED_KEYWORDS = { 'inline', 'restrict', '_Bool', '_Complex', '_Imaginary', 'bool', 'complex', 'imaginary' } +# Reserved keywords defined in Section 6.4.1 "Language" of C11 Standard +# Based on ISO/IEC 9899:201x N1570 (Draft 12.04.2011) 6.4.1 Keywords +# Adding the expanding macros from Section 7 too +# (https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1570.pdf) C11_ADDED_KEYWORDS = { '_Alignas', '_Alignof', '_Atomic', '_Generic', '_Noreturn', - '_Statis_assert', '_Thread_local' , - 'alignas', 'alignof', 'noreturn', 'static_assert' + '_Static_assert', '_Thread_local' , + 'alignas', 'alignof', 'noreturn', 'static_assert','thread_local' } def isKeyword(keyword, standard='c99'): @@ -1547,7 +1707,7 @@ def misra_1_4(self, cfg): for token in cfg.tokenlist: if token.str in ('_Atomic', '_Noreturn', '_Generic', '_Thread_local', '_Alignas', '_Alignof'): self.reportError(token, 1, 4) - if token.str.endswith('_s') and isFunctionCall(token.next): + if token.str.endswith('_s') and isFunctionCall(token.next, cfg.standards.c): # See C specification C11 - Annex K, page 578 if token.str in ('tmpfile_s', 'tmpnam_s', 'fopen_s', 'freopen_s', 'fprintf_s', 'fscanf_s', 'printf_s', 'scanf_s', 'snprintf_s', 'sprintf_s', 'sscanf_s', 'vfprintf_s', 'vfscanf_s', 'vprintf_s', 'vscanf_s', @@ -1942,7 +2102,7 @@ def reportErrorIfVariableIsNotConst(variable, stringLiteral): self.reportError(token, 7, 4) # Check use as function parameter - if isFunctionCall(token) and token.astOperand1 and token.astOperand1.function: + if isFunctionCall(token, data.standards.c) and token.astOperand1 and token.astOperand1.function: functionDeclaration = token.astOperand1.function if functionDeclaration.tokenDef: @@ -3269,7 +3429,7 @@ def misra_16_7(self, data): def misra_17_1(self, data): for token in data.tokenlist: - if isFunctionCall(token) and token.astOperand1.str in ( + if isFunctionCall(token, data.standards.c) and token.astOperand1.str in ( 'va_list', 'va_arg', 'va_start', 'va_end', 'va_copy'): self.reportError(token, 17, 1) elif token.str == 'va_list': @@ -3338,7 +3498,7 @@ def misra_17_3(self, cfg): end_token = token.next.link while tok != end_token: if tok.isName and tok.function is None and tok.valueType is None and tok.next.str == "(" and \ - tok.next.valueType is None and not isKeyword(tok.str) and not isStdLibId(tok.str): + tok.next.valueType is None and not isKeyword(tok.str, cfg.standards.c) and not isStdLibId(tok.str, cfg.standards.c): self.reportError(tok, 17, 3) break tok = tok.next @@ -3391,7 +3551,7 @@ def misra_config(self, data): continue if tok.next.str == "(" or tok.str in ["EOF"]: continue - if isKeyword(tok.str) or isStdLibId(tok.str): + if isKeyword(tok.str, data.standards.c) or isStdLibId(tok.str, data.standards.c): continue if tok.astParent is None: continue @@ -3656,7 +3816,7 @@ def misra_20_9(self, cfg): break for s in cond.E.split(' '): if (s[0] >= 'A' and s[0] <= 'Z') or (s[0] >= 'a' and s[0] <= 'z'): - if isKeyword(s): + if isKeyword(s, cfg.standards.c): continue if s in defined: continue @@ -3790,7 +3950,7 @@ def misra_21_2(self, cfg): def misra_21_3(self, data): for token in data.tokenlist: - if isFunctionCall(token) and (token.astOperand1.str in ('malloc', 'calloc', 'realloc', 'free')): + if isFunctionCall(token, data.standards.c) and (token.astOperand1.str in ('malloc', 'calloc', 'realloc', 'free')): self.reportError(token, 21, 3) def misra_21_4(self, data): @@ -3813,12 +3973,12 @@ def misra_21_6(self, data): def misra_21_7(self, data): for token in data.tokenlist: - if isFunctionCall(token) and (token.astOperand1.str in ('atof', 'atoi', 'atol', 'atoll')): + if isFunctionCall(token, data.standards.c) and (token.astOperand1.str in ('atof', 'atoi', 'atol', 'atoll')): self.reportError(token, 21, 7) def misra_21_8(self, data): for token in data.tokenlist: - if isFunctionCall(token) and (token.astOperand1.str in ('abort', 'exit', 'getenv')): + if isFunctionCall(token, data.standards.c) and (token.astOperand1.str in ('abort', 'exit', 'getenv')): self.reportError(token, 21, 8) def misra_21_9(self, data): @@ -3845,7 +4005,7 @@ def misra_21_12(self, data): for token in data.tokenlist: if token.str == 'fexcept_t' and token.isName: self.reportError(token, 21, 12) - if isFunctionCall(token) and (token.astOperand1.str in ( + if isFunctionCall(token, data.standards.c) and (token.astOperand1.str in ( 'feclearexcept', 'fegetexceptflag', 'feraiseexcept', @@ -3857,7 +4017,7 @@ def misra_21_14(self, data): # buffers used in strcpy/strlen/etc function calls string_buffers = [] for token in data.tokenlist: - if token.str[0] == 's' and isFunctionCall(token.next): + if token.str[0] == 's' and isFunctionCall(token.next, data.standards.c): name, args = cppcheckdata.get_function_call_name_args(token) if name is None: continue diff --git a/addons/test/misra_test.py b/addons/test/misra_test.py index 9862318d30b..55a24cb4b27 100644 --- a/addons/test/misra_test.py +++ b/addons/test/misra_test.py @@ -8,7 +8,7 @@ import os from .util import dump_create, dump_remove, convert_json_output - +from addons.misra import C11_STDLIB_IDENTIFIERS, C99_STDLIB_IDENTIFIERS,C90_STDLIB_IDENTIFIERS, isStdLibId, isKeyword TEST_SOURCE_FILES = [os.path.join('addons','test','misra','misra-test.c')] @@ -181,3 +181,64 @@ def test_platform(checker): dump_create(test_file, "--language=c") checker.parseDump(test_file + ".dump") assert checker.is_cpp is False + +def test_std99_identifiers(): + for headerfile in C90_STDLIB_IDENTIFIERS: + for identifier in C90_STDLIB_IDENTIFIERS[headerfile]: + assert identifier in C99_STDLIB_IDENTIFIERS[headerfile], f"{identifier} of C90 not found in C99_STDLIB_IDENTIFIERS" + +def test_stdC11_identifiers(): + for headerfile in C90_STDLIB_IDENTIFIERS: + for identifier in C90_STDLIB_IDENTIFIERS[headerfile]: + assert identifier in C99_STDLIB_IDENTIFIERS[headerfile], f"{identifier} of C90 not found in C11_STDLIB_IDENTIFIERS" + for headerfile in C99_STDLIB_IDENTIFIERS: + for identifier in C99_STDLIB_IDENTIFIERS[headerfile]: + assert identifier in C11_STDLIB_IDENTIFIERS[headerfile], f"{identifier} of C99 not found in C11_STDLIB_IDENTIFIERS" + +def test_isStdLibId(): + # Check that Identifiers from C90 are correctly classified + assert isStdLibId("assert", 'c89') is True + assert isStdLibId("assert", 'c99') is True + assert isStdLibId("assert", 'c11') is True + assert isStdLibId("assert", 'c23') is True + + # Check that Identifiers from C99 are correctly classified + assert isStdLibId("UINT32_C", 'c89') is False + assert isStdLibId("UINT32_C", 'c99') is True + assert isStdLibId("UINT32_C", 'c11') is True + assert isStdLibId("UINT32_C", 'c23') is True + + # Check that Identifiers from C11 are correctly classified + assert isStdLibId("sprintf_s", 'c89') is False + assert isStdLibId("sprintf_s", 'c99') is False + assert isStdLibId("sprintf_s", 'c11') is True + assert isStdLibId("sprintf_s", 'c23') is True + + # Function Defaulting to C99 + assert isStdLibId("assert") is True + assert isStdLibId("UINT32_C") is True + assert isStdLibId("sprintf_s") is False + +def test_isKeyword(): + # Check that Keywords from C90 are correctly classified + assert isKeyword("if", 'c89') is True + assert isKeyword("if", 'c99') is True + assert isKeyword("if", 'c11') is True + assert isKeyword("if", 'c23') is True + + # Check that Keywords from C99 are correctly classified + assert isKeyword("inline", 'c89') is False + assert isKeyword("inline", 'c99') is True + assert isKeyword("inline", 'c11') is True + assert isKeyword("inline", 'c23') is True + + # Check that Keywords from C11 are correctly classified + assert isKeyword("static_assert", 'c89') is False + assert isKeyword("static_assert", 'c99') is False + assert isKeyword("static_assert", 'c11') is True + assert isKeyword("static_assert", 'c23') is True + + # Function Defaulting to C99 + assert isKeyword("if") is True + assert isKeyword("inline") is True + assert isKeyword("static_assert") is False