From dc1faa71ed76373760ff32b8a3195770deb8605f Mon Sep 17 00:00:00 2001 From: Georgy Komarov Date: Fri, 24 Jul 2020 07:15:40 +0300 Subject: [PATCH] misra.py: Fix false negatives in string concatenation for rule 20.7 This will fix Trac#9633 --- addons/misra.py | 40 ++++++++++++++++++++++++++++++++++ addons/test/misra/misra-test.c | 4 ++++ 2 files changed, 44 insertions(+) diff --git a/addons/misra.py b/addons/misra.py index 361a15e63..be471efea 100755 --- a/addons/misra.py +++ b/addons/misra.py @@ -2302,10 +2302,50 @@ class MisraChecker: self.reportError(directive, 20, 5) def misra_20_7(self, data): + def find_string_concat(exp, arg, directive_args): + # Handle concatenation of string literals, e.g.: + # #define MACRO(A, B) (A " " B) + # Addon should not report errors for both macro arguments. + arg_pos = exp.find(arg, 0) + need_check = False + skip_next = False + state_in_string = False + pos_search = arg_pos + 1 + directive_args = [a.strip() for a in directive_args if a != arg] + arg = arg.strip() + while pos_search < len(exp): + if exp[pos_search] == '"': + if state_in_string: + state_in_string = False + else: + state_in_string = True + pos_search += 1 + elif exp[pos_search] in directive_args: + skip_next = True # Skip check for the next argument + break + elif exp[pos_search] == arg: + pos_search += 1 + elif exp[pos_search] == ' ': + pos_search += 1 + elif state_in_string: + pos_search += 1 + else: + need_check = True + break + return need_check, skip_next + for directive in data.directives: d = Define(directive) exp = '(' + d.expansionList + ')' + skip_next = False for arg in d.args: + if skip_next: + _, skip_next = find_string_concat(exp, arg, d.args) + continue + need_check, skip_next = find_string_concat(exp, arg, d.args) + if not need_check: + continue + pos = 0 while pos < len(exp): pos = exp.find(arg, pos) diff --git a/addons/test/misra/misra-test.c b/addons/test/misra/misra-test.c index 1e73d37d5..74b6ac1b3 100644 --- a/addons/test/misra/misra-test.c +++ b/addons/test/misra/misra-test.c @@ -1031,6 +1031,10 @@ union misra_19_2 { }; // 19.2 #define M_20_7_7(x) a = # x // 20.10 #define M_20_7_8(x, fn) a = fn ( # x ) // 20.7 20.10 #define M_20_7_9(x, fn) a = (fn) ( # x ) // 20.10 +#define M_20_7_10(A, B) (A " " B) +#define M_20_7_11(A, B, C) (A " " B " " C) +#define M_20_7_12(A, B, C) (A " " B + C) // 20.7 +#define M_20_7_13(A, B, C) (A + B " " C) // 20.7 // Compliant: M is a structure member name, not an expression struct { int a; } struct_20_7_s;