From 727d086dc41acb7b6cea43f1c911b0a3d23bae4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20Marjam=C3=A4ki?= Date: Wed, 22 Nov 2023 12:47:48 +0100 Subject: [PATCH] Fix #12217 (misra 11.4: report conversion in macro) (#5692) --- addons/cppcheckdata.py | 5 ++++- addons/misra.py | 25 +++++++++++++++++++++++++ addons/test/misra/misra-test.c | 5 ++++- lib/tokenize.cpp | 2 +- 4 files changed, 34 insertions(+), 3 deletions(-) diff --git a/addons/cppcheckdata.py b/addons/cppcheckdata.py index 550d2ea71..d8bfcddd1 100755 --- a/addons/cppcheckdata.py +++ b/addons/cppcheckdata.py @@ -254,6 +254,7 @@ class Token: isCast externLang isExpandedMacro Is this token a expanded macro token + macroName Macro name that this token is expanded from isRemovedVoidParameter Has void parameter been removed? isSplittedVarDeclComma Is this a comma changed to semicolon in a split variable declaration ('int a,b;' => 'int a; int b;') isSplittedVarDeclEq Is this a '=' changed to semicolon in a split variable declaration ('int a=5;' => 'int a; a=5;') @@ -313,6 +314,7 @@ class Token: isCast = False isUnsigned = False isSigned = False + macroName = None isExpandedMacro = False isRemovedVoidParameter = False isSplittedVarDeclComma = False @@ -386,7 +388,8 @@ class Token: if element.get('isCast'): self.isCast = True self.externLang = element.get('externLang') - if element.get('isExpandedMacro'): + self.macroName = element.get('macroName') + if self.macroName or element.get('isExpandedMacro'): self.isExpandedMacro = True if element.get('isRemovedVoidParameter'): self.isRemovedVoidParameter = True diff --git a/addons/misra.py b/addons/misra.py index cc26146dd..a93b9b518 100755 --- a/addons/misra.py +++ b/addons/misra.py @@ -2520,6 +2520,20 @@ class MisraChecker: self.reportError(token, 11, 3) def misra_11_4(self, data): + # Get list of macro definitions + macros = {} + for directive in data.directives: + #define X ((peripheral_t *)0x40000U) + res = re.match(r'#define ([A-Za-z0-9_]+).*', directive.str) + if res: + if res.group(1) in macros: + macros[res.group(1)].append(directive) + else: + macros[res.group(1)] = [directive] + + # If macro definition is non-compliant then warn about the macro definition instead of + # the macro usages. To reduce diagnostics for a non-compliant macro. + bad_macros = [] for token in data.tokenlist: if not isCast(token): continue @@ -2530,6 +2544,17 @@ class MisraChecker: if vt2.pointer > 0 and vt1.pointer == 0 and (vt1.isIntegral() or vt1.isEnum()) and vt2.type != 'void': self.reportError(token, 11, 4) elif vt1.pointer > 0 and vt2.pointer == 0 and (vt2.isIntegral() or vt2.isEnum()) and vt1.type != 'void': + if token.macroName is not None and \ + token.macroName == token.astOperand1.macroName and \ + token.astOperand1.isInt and \ + token.link.previous.str == '*' and \ + token.macroName == token.link.previous.macroName and \ + token.macroName in macros and \ + len(macros[token.macroName]) == 1: + if token.macroName not in bad_macros: + bad_macros.append(token.macroName) + self.reportError(macros[token.macroName][0], 11, 4) + continue self.reportError(token, 11, 4) def misra_11_5(self, data): diff --git a/addons/test/misra/misra-test.c b/addons/test/misra/misra-test.c index db73cfd64..60295a837 100644 --- a/addons/test/misra/misra-test.c +++ b/addons/test/misra/misra-test.c @@ -798,12 +798,15 @@ static void misra_11_3(u8* p, struct Fred *fred) { struct Wilma *wilma = (struct Wilma *)fred; // 11.3 } +typedef struct { uint32_t something; } struct_11_4; +#define A_11_4 ((struct_11_4 *)0x40000U) // 11.4 + static void misra_11_4(u8*p) { u64 y = (u64)p; // 11.4 u8 *misra_11_4_A = ( u8 * ) 0x0005;// 11.4 s32 misra_11_4_B; u8 *q = ( u8 * ) misra_11_4_B; // 11.4 - + dummy = A_11_4->something; // no-warning } static void misra_11_5(void *p) { diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 35ee843fa..262554138 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -5946,7 +5946,7 @@ void Tokenizer::dump(std::ostream &out) const if (tok->isExternC()) outs += " externLang=\"C\""; if (tok->isExpandedMacro()) - outs += " isExpandedMacro=\"true\""; + outs += " macroName=\"" + tok->getMacroName() + "\""; if (tok->isTemplateArg()) outs += " isTemplateArg=\"true\""; if (tok->isRemovedVoidParameter())