diff --git a/addons/cppcheckdata.py b/addons/cppcheckdata.py index e71d444a0b6..80f97c720de 100755 --- a/addons/cppcheckdata.py +++ b/addons/cppcheckdata.py @@ -946,29 +946,60 @@ class Suppression: fileName The name of the file to suppress warnings for, can include wildcards lineNumber The number of the line to suppress warnings from, can be 0 to represent any line symbolName The name of the symbol to match warnings for, can include wildcards + lineBegin The first line to suppress warnings from + lineEnd The last line to suppress warnings from + suppressionType The type of suppression which is applied (unique = None (default), file, block, blockBegin, blockEnd, macro) """ errorId = None fileName = None lineNumber = None symbolName = None + lineBegin = None + lineEnd = None + suppressionType = None def __init__(self, element): self.errorId = element.get('errorId') self.fileName = element.get('fileName') self.lineNumber = element.get('lineNumber') self.symbolName = element.get('symbolName') + self.lineBegin = element.get('lineBegin') + self.lineEnd = element.get('lineEnd') + self.suppressionType = element.get('type') def __repr__(self): - attrs = ['errorId' , "fileName", "lineNumber", "symbolName"] + attrs = ["errorId", "fileName", "lineNumber", "symbolName", "lineBegin", "lineEnd","suppressionType"] return "{}({})".format( "Suppression", ", ".join(("{}={}".format(a, repr(getattr(self, a))) for a in attrs)) ) def isMatch(self, file, line, message, errorId): + # Line Suppression if ((self.fileName is None or fnmatch(file, self.fileName)) - and (self.lineNumber is None or int(line) == int(self.lineNumber)) + and (self.suppressionType == None) # Verify use of default suppression type (None = unique) + and (self.lineNumber != None and int(line) == int(self.lineNumber)) + and (self.symbolName is None or fnmatch(message, '*'+self.symbolName+'*')) + and fnmatch(errorId, self.errorId)): + return True + # File Suppression + if ((self.fileName is None or fnmatch(file, self.fileName)) + and (self.suppressionType != None and self.suppressionType == "file") # Verify use of file (global) suppression type + and (self.symbolName is None or fnmatch(message, '*'+self.symbolName+'*')) + and fnmatch(errorId, self.errorId)): + return True + # Block Suppression Mode + if ((self.fileName is None or fnmatch(file, self.fileName)) + and (self.suppressionType != None and self.suppressionType == "block") # Type for Block suppression + and (self.lineBegin != None and int(line) > int(self.lineBegin)) # Code Match is between the Block suppression + and (self.lineEnd != None and int(line) < int(self.lineEnd)) # Code Match is between the Block suppression + and (self.symbolName is None or fnmatch(message, '*'+self.symbolName+'*')) + and fnmatch(errorId, self.errorId)): + return True + # Other Suppression (Globaly set via suppression file or cli command) + if ((self.fileName is None or fnmatch(file, self.fileName)) + and (self.suppressionType is None) and (self.symbolName is None or fnmatch(message, '*'+self.symbolName+'*')) and fnmatch(errorId, self.errorId)): return True diff --git a/addons/test/misra/misra-suppressions1-test.c b/addons/test/misra/misra-suppressions1-test.c index ce47fe88e95..403d71f73ea 100644 --- a/addons/test/misra/misra-suppressions1-test.c +++ b/addons/test/misra/misra-suppressions1-test.c @@ -4,6 +4,7 @@ // This needs to stay at line number 7 to make the test pass // If it is changed update suppressions.txt with the new line number +// cppcheck-suppress-file misra-c2012-5.2 #include //21.6 extern int misra_5_2_var_hides_var______31x;//8.4 @@ -13,6 +14,8 @@ static void misra_5_2_function_hides_var_31y(void) {}//5.2 static void foo(void) { int i; + // cppcheck-suppress-begin misra-c2012-16.4 + // cppcheck-suppress misra-c2012-16.6 switch(misra_5_2_func1()) //16.4 16.6 { case 1: @@ -30,4 +33,5 @@ static void foo(void) } while(misra_5_2_func2()); //17.3 } } + // cppcheck-suppress-end misra-c2012-16.4 } diff --git a/addons/test/misra/misra-suppressions2-test.c b/addons/test/misra/misra-suppressions2-test.c index e32e2ab9781..79d3f68191e 100644 --- a/addons/test/misra/misra-suppressions2-test.c +++ b/addons/test/misra/misra-suppressions2-test.c @@ -2,6 +2,7 @@ // ../../cppcheck --suppressions-list=suppressions.txt --dump misra-suppressions*-test.c && python ../misra.py misra-suppressions*-test.c.dump // There should be no violations reported +// cppcheck-suppress-file misra-c2012-5.2 union misra_5_2_field_hides_field__63x { //19.2 int misra_5_2_field_hides_field__31x; int misra_5_2_field_hides_field__31y;//5.2 diff --git a/addons/test/misra/suppressions.txt b/addons/test/misra/suppressions.txt index 97b070025bd..139e088552e 100644 --- a/addons/test/misra/suppressions.txt +++ b/addons/test/misra/suppressions.txt @@ -1,9 +1,6 @@ misra-c2012-21.6:*/misra-suppressions1-test.c:7 misra-c2012-17.3 -misra-c2012-5.2 misra-c2012-8.4:*/misra-suppressions1-test.c -misra-c2012-16.4:*/misra-suppressions1-test.c -misra-c2012-16.6:*/misra-suppressions1-test.c misra-c2012-4.1:*/misra-suppressions2-test.c misra-c2012-8.4:*/misra-suppressions2-test.c misra-c2012-19.2:*/misra-suppressions2-test.c diff --git a/addons/test/misra_test.py b/addons/test/misra_test.py index 3ae6380b8ad..546b075a709 100644 --- a/addons/test/misra_test.py +++ b/addons/test/misra_test.py @@ -122,7 +122,7 @@ def test_rules_suppression(checker, capsys): for src in test_sources: re_suppressed= r"\[%s\:[0-9]+\]" % src dump_remove(src) - dump_create(src, "--suppressions-list=addons/test/misra/suppressions.txt") + dump_create(src, "--suppressions-list=addons/test/misra/suppressions.txt","--inline-suppr") checker.parseDump(src + ".dump") captured = capsys.readouterr().err found = re.search(re_suppressed, captured) diff --git a/lib/suppressions.cpp b/lib/suppressions.cpp index 80e922490ea..69bbe95229f 100644 --- a/lib/suppressions.cpp +++ b/lib/suppressions.cpp @@ -455,6 +455,20 @@ void SuppressionList::dump(std::ostream & out) const out << " symbolName=\"" << ErrorLogger::toxml(suppression.symbolName) << '\"'; if (suppression.hash > 0) out << " hash=\"" << suppression.hash << '\"'; + if (suppression.lineBegin != Suppression::NO_LINE) + out << " lineBegin=\"" << suppression.lineBegin << '"'; + if (suppression.lineEnd != Suppression::NO_LINE) + out << " lineEnd=\"" << suppression.lineEnd << '"'; + if (suppression.type == SuppressionList::Type::file) + out << " type=\"file\""; + else if (suppression.type == SuppressionList::Type::block) + out << " type=\"block\""; + else if (suppression.type == SuppressionList::Type::blockBegin) + out << " type=\"blockBegin\""; + else if (suppression.type == SuppressionList::Type::blockEnd) + out << " type=\"blockEnd\""; + else if (suppression.type == SuppressionList::Type::macro) + out << " type=\"macro\""; out << " />" << std::endl; } out << " " << std::endl;