misra; implemented rule 20.8

This commit is contained in:
Daniel Marjamäki 2021-07-22 08:46:28 +02:00
parent 00eb71fd49
commit 74ab8f1a48
10 changed files with 73 additions and 11 deletions

View File

@ -43,7 +43,7 @@ jobs:
- name: Extra test for misra
run: |
C:\tools\cygwin\bin\bash.exe -l -c cd %GITHUB_WORKSPACE%\addons\test
..\..\cppcheck --dump --suppress=uninitvar --inline-suppr misra\misra-test.c --std=c89 --platform=unix64 && python3 ..\misra.py -verify misra\misra-test.c.dump
..\..\cppcheck --dump -DDUMMY --suppress=uninitvar --inline-suppr misra\misra-test.c --std=c89 --platform=unix64 && python3 ..\misra.py -verify misra\misra-test.c.dump
C:\tools\cygwin\bin\bash.exe -l -c cd %GITHUB_WORKSPACE%
.\cppcheck --addon=misra --inline-suppr --enable=information --error-exitcode=1 addons\test\misra\misra-ctu-*-test.c

View File

@ -127,7 +127,7 @@ jobs:
./cppcheck --addon=threadsafety --std=c++03 addons/test/threadsafety
./cppcheck --addon=misra --inline-suppr --enable=information --error-exitcode=1 addons/test/misra/misra-ctu-*-test.c
cd addons/test
../../cppcheck --dump --suppress=uninitvar --inline-suppr misra/misra-test.c --std=c89 --platform=unix64 && python3 ../misra.py -verify misra/misra-test.c.dump
../../cppcheck --dump -DDUMMY --suppress=uninitvar --inline-suppr misra/misra-test.c --std=c89 --platform=unix64 && python3 ../misra.py -verify misra/misra-test.c.dump
- name: Build GUI on ubuntu
if: contains(matrix.os, 'ubuntu')

View File

@ -137,5 +137,5 @@ jobs:
run: |
.\cppcheck.exe --addon=misra --inline-suppr --enable=information --error-exitcode=1 addons\test\misra\misra-ctu-*-test.c
cd addons\test
..\..\cppcheck.exe --dump --suppress=uninitvar --inline-suppr misra\misra-test.c --std=c89 --platform=unix64 && python3 ..\misra.py -verify misra\misra-test.c.dump
..\..\cppcheck.exe --dump -DDUMMY --suppress=uninitvar --inline-suppr misra\misra-test.c --std=c89 --platform=unix64 && python3 ..\misra.py -verify misra\misra-test.c.dump

View File

@ -73,8 +73,8 @@ matrix:
- cd addons/test
# We'll force C89 standard to enable an additional verification for
# rules 5.4 and 5.5 which have standard-dependent options.
- ${CPPCHECK} --dump --suppress=uninitvar --suppress=uninitStructMember --std=c89 misra/misra-test.c
- ${CPPCHECK} --dump --suppress=uninitvar --suppress=uninitStructMember --std=c89 misra/misra-test.h
- ${CPPCHECK} --dump -DDUMMY --suppress=uninitvar --suppress=uninitStructMember --std=c89 misra/misra-test.c
- ${CPPCHECK} --dump -DDUMMY --suppress=uninitvar --suppress=uninitStructMember --std=c89 misra/misra-test.h
- python3 ../misra.py -verify misra/misra-test.c.dump
- ${CPPCHECK} --dump misra/misra-test.cpp
- python3 ../misra.py -verify misra/misra-test.cpp.dump

View File

@ -94,6 +94,29 @@ class MacroUsage:
)
class PreprocessorIfCondition:
"""
Information about #if/#elif conditions
"""
file = None
linenr = None
column = None
E = None
result = None
def __init__(self, element):
_load_location(self, element)
self.E = element.get('E')
self.result = int(element.get('result'))
def __repr__(self):
attrs = ["file", "linenr", "column", "E", "result"]
return "{}({})".format(
"PreprocessorIfCondition",
", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs))
)
class ValueType:
"""
@ -759,6 +782,7 @@ class Configuration:
name Name of the configuration, "" for default
directives List of Directive items
macro_usage List of used macros
preprocessor_if_conditions List of preprocessor if conditions that was evaluated during preprocessing
tokenlist List of Token items
scopes List of Scope items
functions List of Function items
@ -770,6 +794,7 @@ class Configuration:
name = ''
directives = []
macro_usage = []
preprocessor_if_conditions = []
tokenlist = []
scopes = []
functions = []
@ -782,6 +807,7 @@ class Configuration:
self.name = name
self.directives = []
self.macro_usage = []
self.preprocessor_if_conditions = []
self.tokenlist = []
self.scopes = []
self.functions = []
@ -1045,6 +1071,10 @@ class CppcheckData:
elif node.tag == 'macro' and event == 'start':
cfg.macro_usage.append(MacroUsage(node))
# Preprocessor #if/#elif condition
elif node.tag == "if-cond" and event == 'start':
cfg.preprocessor_if_conditions.append(PreprocessorIfCondition(node))
# Parse tokens
elif node.tag == 'tokenlist' and event == 'start':
continue

View File

@ -3209,6 +3209,12 @@ class MisraChecker:
self.reportError(directive, 20, 7)
break
def misra_20_8(self, cfg):
for cond in cfg.preprocessor_if_conditions:
#print(cond)
if cond.result and cond.result not in (0,1):
self.reportError(cond, 20, 8)
def misra_20_10(self, data):
for directive in data.directives:
d = Define(directive)
@ -3884,7 +3890,8 @@ class MisraChecker:
self.executeCheck(2003, self.misra_20_3, cfg)
self.executeCheck(2004, self.misra_20_4, cfg)
self.executeCheck(2005, self.misra_20_5, cfg)
self.executeCheck(2006, self.misra_20_7, cfg)
self.executeCheck(2007, self.misra_20_7, cfg)
self.executeCheck(2008, self.misra_20_8, cfg)
self.executeCheck(2010, self.misra_20_10, cfg)
self.executeCheck(2013, self.misra_20_13, cfg)
self.executeCheck(2014, self.misra_20_14, cfg)

View File

@ -1,6 +1,6 @@
// To test:
// ~/cppcheck/cppcheck --dump misra/misra-test.h --std=c89
// ~/cppcheck/cppcheck --dump --suppress=uninitvar --inline-suppr misra/misra-test.c --std=c89 --platform=unix64 && python3 ../misra.py -verify misra/misra-test.c.dump
// ~/cppcheck/cppcheck --dump -DDUMMY --suppress=uninitvar --inline-suppr misra/misra-test.c --std=c89 --platform=unix64 && python3 ../misra.py -verify misra/misra-test.c.dump
#include "path\file.h" // 20.2
#include "file//.h" // 20.2
@ -1558,6 +1558,9 @@ struct { int a; } struct_20_7_s;
#define MUL(a ,b ) ( a * b ) // 20.7
#if __LINE__ // 20.8
#endif
#define M_20_10(a) (#a) // 20.10
#else1 // 20.13

View File

@ -20,7 +20,7 @@ def find_cppcheck_binary():
def dump_create(fpath, *argv):
cppcheck_binary = find_cppcheck_binary()
cmd = [cppcheck_binary, "--dump", "--quiet", fpath] + list(argv)
cmd = [cppcheck_binary, "--dump", "-DDUMMY", "--quiet", fpath] + list(argv)
p = subprocess.Popen(cmd)
p.communicate()
if p.returncode != 0:

View File

@ -738,9 +738,11 @@ simplecpp::TokenList Preprocessor::preprocess(const simplecpp::TokenList &tokens
simplecpp::OutputList outputList;
std::list<simplecpp::MacroUsage> macroUsage;
std::list<simplecpp::IfCond> ifCond;
simplecpp::TokenList tokens2(files);
simplecpp::preprocess(tokens2, tokens1, files, mTokenLists, dui, &outputList, &macroUsage);
simplecpp::preprocess(tokens2, tokens1, files, mTokenLists, dui, &outputList, &macroUsage, &ifCond);
mMacroUsage = macroUsage;
mIfCond = ifCond;
handleErrors(outputList, throwError);
@ -800,6 +802,9 @@ std::string Preprocessor::getcode(const std::string &filedata, const std::string
std::string ret;
try {
ret = getcode(tokens1, cfg, files, filedata.find("#file") != std::string::npos);
// Since "files" is a local variable the tracking info must be cleared..
mMacroUsage.clear();
mIfCond.clear();
} catch (const simplecpp::Output &) {
ret.clear();
}
@ -961,7 +966,7 @@ void Preprocessor::dump(std::ostream &out) const
if (!mMacroUsage.empty()) {
out << " <macro-usage>" << std::endl;
for (const simplecpp::MacroUsage &macroUsage: mMacroUsage) {
out << " <macro "
out << " <macro"
<< " name=\"" << macroUsage.macroName << "\""
<< " file=\"" << macroUsage.macroLocation.file() << "\""
<< " line=\"" << macroUsage.macroLocation.line << "\""
@ -969,10 +974,25 @@ void Preprocessor::dump(std::ostream &out) const
<< " usefile=\"" << macroUsage.useLocation.file() << "\""
<< " useline=\"" << macroUsage.useLocation.line << "\""
<< " usecolumn=\"" << macroUsage.useLocation.col << "\""
<< " known-value=\"" << (macroUsage.macroValueKnown ? 1 : 0) << "\"/>" << std::endl;
<< " is-known-value=\"" << (macroUsage.macroValueKnown ? "true" : "false") << "\""
<< "/>" << std::endl;
}
out << " </macro-usage>" << std::endl;
}
if (!mIfCond.empty()) {
out << " <simplecpp-if-cond>" << std::endl;
for (const simplecpp::IfCond &ifCond: mIfCond) {
out << " <if-cond"
<< " file=\"" << ErrorLogger::toxml(ifCond.location.file()) << "\""
<< " line=\"" << ifCond.location.line << "\""
<< " column=\"" << ifCond.location.col << "\""
<< " E=\"" << ErrorLogger::toxml(ifCond.E) << "\""
<< " result=\"" << ifCond.result << "\""
<< "/>" << std::endl;
}
out << " </simplecpp-if-cond>" << std::endl;
}
}
static const std::uint32_t crc32Table[] = {

View File

@ -223,7 +223,9 @@ private:
/** filename for cpp/c file - useful when reporting errors */
std::string mFile0;
/** simplecpp tracking info */
std::list<simplecpp::MacroUsage> mMacroUsage;
std::list<simplecpp::IfCond> mIfCond;
};
/// @}