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 - name: Extra test for misra
run: | run: |
C:\tools\cygwin\bin\bash.exe -l -c cd %GITHUB_WORKSPACE%\addons\test 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% 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 .\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=threadsafety --std=c++03 addons/test/threadsafety
./cppcheck --addon=misra --inline-suppr --enable=information --error-exitcode=1 addons/test/misra/misra-ctu-*-test.c ./cppcheck --addon=misra --inline-suppr --enable=information --error-exitcode=1 addons/test/misra/misra-ctu-*-test.c
cd addons/test 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 - name: Build GUI on ubuntu
if: contains(matrix.os, 'ubuntu') if: contains(matrix.os, 'ubuntu')

View File

@ -137,5 +137,5 @@ jobs:
run: | run: |
.\cppcheck.exe --addon=misra --inline-suppr --enable=information --error-exitcode=1 addons\test\misra\misra-ctu-*-test.c .\cppcheck.exe --addon=misra --inline-suppr --enable=information --error-exitcode=1 addons\test\misra\misra-ctu-*-test.c
cd addons\test 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 - cd addons/test
# We'll force C89 standard to enable an additional verification for # We'll force C89 standard to enable an additional verification for
# rules 5.4 and 5.5 which have standard-dependent options. # 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 -DDUMMY --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.h
- python3 ../misra.py -verify misra/misra-test.c.dump - python3 ../misra.py -verify misra/misra-test.c.dump
- ${CPPCHECK} --dump misra/misra-test.cpp - ${CPPCHECK} --dump misra/misra-test.cpp
- python3 ../misra.py -verify misra/misra-test.cpp.dump - 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: class ValueType:
""" """
@ -759,6 +782,7 @@ class Configuration:
name Name of the configuration, "" for default name Name of the configuration, "" for default
directives List of Directive items directives List of Directive items
macro_usage List of used macros macro_usage List of used macros
preprocessor_if_conditions List of preprocessor if conditions that was evaluated during preprocessing
tokenlist List of Token items tokenlist List of Token items
scopes List of Scope items scopes List of Scope items
functions List of Function items functions List of Function items
@ -770,6 +794,7 @@ class Configuration:
name = '' name = ''
directives = [] directives = []
macro_usage = [] macro_usage = []
preprocessor_if_conditions = []
tokenlist = [] tokenlist = []
scopes = [] scopes = []
functions = [] functions = []
@ -782,6 +807,7 @@ class Configuration:
self.name = name self.name = name
self.directives = [] self.directives = []
self.macro_usage = [] self.macro_usage = []
self.preprocessor_if_conditions = []
self.tokenlist = [] self.tokenlist = []
self.scopes = [] self.scopes = []
self.functions = [] self.functions = []
@ -1045,6 +1071,10 @@ class CppcheckData:
elif node.tag == 'macro' and event == 'start': elif node.tag == 'macro' and event == 'start':
cfg.macro_usage.append(MacroUsage(node)) 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 # Parse tokens
elif node.tag == 'tokenlist' and event == 'start': elif node.tag == 'tokenlist' and event == 'start':
continue continue

View File

@ -3209,6 +3209,12 @@ class MisraChecker:
self.reportError(directive, 20, 7) self.reportError(directive, 20, 7)
break 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): def misra_20_10(self, data):
for directive in data.directives: for directive in data.directives:
d = Define(directive) d = Define(directive)
@ -3884,7 +3890,8 @@ class MisraChecker:
self.executeCheck(2003, self.misra_20_3, cfg) self.executeCheck(2003, self.misra_20_3, cfg)
self.executeCheck(2004, self.misra_20_4, cfg) self.executeCheck(2004, self.misra_20_4, cfg)
self.executeCheck(2005, self.misra_20_5, 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(2010, self.misra_20_10, cfg)
self.executeCheck(2013, self.misra_20_13, cfg) self.executeCheck(2013, self.misra_20_13, cfg)
self.executeCheck(2014, self.misra_20_14, cfg) self.executeCheck(2014, self.misra_20_14, cfg)

View File

@ -1,6 +1,6 @@
// To test: // To test:
// ~/cppcheck/cppcheck --dump misra/misra-test.h --std=c89 // ~/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 "path\file.h" // 20.2
#include "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 #define MUL(a ,b ) ( a * b ) // 20.7
#if __LINE__ // 20.8
#endif
#define M_20_10(a) (#a) // 20.10 #define M_20_10(a) (#a) // 20.10
#else1 // 20.13 #else1 // 20.13

View File

@ -20,7 +20,7 @@ def find_cppcheck_binary():
def dump_create(fpath, *argv): def dump_create(fpath, *argv):
cppcheck_binary = find_cppcheck_binary() 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 = subprocess.Popen(cmd)
p.communicate() p.communicate()
if p.returncode != 0: if p.returncode != 0:

View File

@ -738,9 +738,11 @@ simplecpp::TokenList Preprocessor::preprocess(const simplecpp::TokenList &tokens
simplecpp::OutputList outputList; simplecpp::OutputList outputList;
std::list<simplecpp::MacroUsage> macroUsage; std::list<simplecpp::MacroUsage> macroUsage;
std::list<simplecpp::IfCond> ifCond;
simplecpp::TokenList tokens2(files); 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; mMacroUsage = macroUsage;
mIfCond = ifCond;
handleErrors(outputList, throwError); handleErrors(outputList, throwError);
@ -800,6 +802,9 @@ std::string Preprocessor::getcode(const std::string &filedata, const std::string
std::string ret; std::string ret;
try { try {
ret = getcode(tokens1, cfg, files, filedata.find("#file") != std::string::npos); 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 &) { } catch (const simplecpp::Output &) {
ret.clear(); ret.clear();
} }
@ -961,7 +966,7 @@ void Preprocessor::dump(std::ostream &out) const
if (!mMacroUsage.empty()) { if (!mMacroUsage.empty()) {
out << " <macro-usage>" << std::endl; out << " <macro-usage>" << std::endl;
for (const simplecpp::MacroUsage &macroUsage: mMacroUsage) { for (const simplecpp::MacroUsage &macroUsage: mMacroUsage) {
out << " <macro " out << " <macro"
<< " name=\"" << macroUsage.macroName << "\"" << " name=\"" << macroUsage.macroName << "\""
<< " file=\"" << macroUsage.macroLocation.file() << "\"" << " file=\"" << macroUsage.macroLocation.file() << "\""
<< " line=\"" << macroUsage.macroLocation.line << "\"" << " line=\"" << macroUsage.macroLocation.line << "\""
@ -969,10 +974,25 @@ void Preprocessor::dump(std::ostream &out) const
<< " usefile=\"" << macroUsage.useLocation.file() << "\"" << " usefile=\"" << macroUsage.useLocation.file() << "\""
<< " useline=\"" << macroUsage.useLocation.line << "\"" << " useline=\"" << macroUsage.useLocation.line << "\""
<< " usecolumn=\"" << macroUsage.useLocation.col << "\"" << " 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; 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[] = { static const std::uint32_t crc32Table[] = {

View File

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