misra; implemented rule 20.8
This commit is contained in:
parent
00eb71fd49
commit
74ab8f1a48
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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')
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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, ¯oUsage);
|
simplecpp::preprocess(tokens2, tokens1, files, mTokenLists, dui, &outputList, ¯oUsage, &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 ¯oUsage: mMacroUsage) {
|
for (const simplecpp::MacroUsage ¯oUsage: 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[] = {
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
Loading…
Reference in New Issue