diff --git a/addons/cppcheckdata.py b/addons/cppcheckdata.py index c9704e5c2..095e38776 100755 --- a/addons/cppcheckdata.py +++ b/addons/cppcheckdata.py @@ -33,11 +33,12 @@ class Directive: str = None file = None linenr = None + col = 0 def __init__(self, element): self.str = element.get('str') self.file = element.get('file') - self.linenr = element.get('linenr') + self.linenr = int(element.get('linenr')) class ValueType: @@ -129,6 +130,7 @@ class Token: astOperand2 ast operand2 file file name linenr line number + col column To iterate through all tokens use such code: @code @@ -184,6 +186,7 @@ class Token: file = None linenr = None + col = None def __init__(self, element): self.Id = element.get('id') @@ -222,7 +225,8 @@ class Token: self.isLogicalOp = True self.linkId = element.get('link') self.link = None - self.varId = element.get('varId') + if element.get('varId'): + self.varId = int(element.get('varId')) self.variableId = element.get('variable') self.variable = None self.functionId = element.get('function') @@ -242,7 +246,8 @@ class Token: self.astOperand2Id = element.get('astOperand2') self.astOperand2 = None self.file = element.get('file') - self.linenr = element.get('linenr') + self.linenr = int(element.get('linenr')) + self.col = int(element.get('col')) def setId(self, IdMap): self.scope = IdMap[self.scopeId] @@ -792,41 +797,9 @@ def ArgumentParser(): return parser -def reportError(template, callstack=(), severity='', message='', errorId='', suppressions=None, outputFunc=None): - """ - Format an error message according to the template. - - :param template: format string, or 'gcc', 'vs' or 'edit'. - :param callstack: e.g. [['file1.cpp',10],['file2.h','20'], ... ] - :param severity: e.g. 'error', 'warning' ... - :param errorId: message ID. - :param message: message text. - """ - # expand predefined templates - if template == 'gcc': - template = '{file}:{line}: {severity}: {message}' - elif template == 'vs': - template = '{file}({line}): {severity}: {message}' - elif template == 'edit': - template = '{file} +{line}: {severity}: {message}' - # compute 'callstack}, {file} and {line} replacements - stack = ' -> '.join('[' + f + ':' + str(l) + ']' for (f, l) in callstack) - file = callstack[-1][0] - line = str(callstack[-1][1]) - - if suppressions is not None and any(suppression.isMatch(file, line, message, errorId) for suppression in suppressions): - return None - - outputLine = template.format(callstack=stack, file=file, line=line, - severity=severity, message=message, id=errorId) - if outputFunc is not None: - outputFunc(outputLine) - # format message - return outputLine - -def reportErrorCli(token, severity, message, addon, errorId): +def reportErrorCli(location, severity, message, addon, errorId): if '--cli' in sys.argv: errout = sys.stdout else: errout = sys.errout - errout.write('[%s:%i]: (%s) %s [%s-%s]\n' % (token.file, int(token.linenr), severity, message, addon, errorId)) + errout.write('[%s:%i:%i] (%s) %s [%s-%s]\n' % (location.file, location.linenr, location.col, severity, message, addon, errorId)) diff --git a/addons/misra.py b/addons/misra.py index 600770109..40f73e01e 100755 --- a/addons/misra.py +++ b/addons/misra.py @@ -2003,30 +2003,20 @@ class MisraChecker: self.suppressionStats[ruleNum].append(location) return else: - id = 'misra-c2012-' + str(num1) + '.' + str(num2) + errorId = 'c2012-' + str(num1) + '.' + str(num2) severity = 'style' if ruleNum in self.ruleTexts: - errmsg = self.ruleTexts[ruleNum].text + ' [' + id + ']' + errmsg = self.ruleTexts[ruleNum].text severity = self.ruleTexts[ruleNum].cppcheck_severity elif len(self.ruleTexts) == 0: - errmsg = 'misra violation (use --rule-texts= to get proper output) [' + id + ']' + errmsg = 'misra violation (use --rule-texts= to get proper output)' else: return - formattedMsg = cppcheckdata.reportError(args.template, - callstack=[(location.file, location.linenr)], - severity=severity, - message = errmsg, - errorId = id, - suppressions = self.dumpfileSuppressions) - if formattedMsg: - if CLI: - print(formattedMsg) - else: - sys.stderr.write(formattedMsg) - sys.stderr.write('\n') - if not severity in self.violations: - self.violations[severity] = [] - self.violations[severity].append(id) + cppcheckdata.reportErrorCli(location, severity, errmsg, 'misra', errorId) + + if not severity in self.violations: + self.violations[severity] = [] + self.violations[severity].append(errorId) def loadRuleTexts(self, filename): num1 = 0 diff --git a/lib/cppcheck.cpp b/lib/cppcheck.cpp index 69f82e937..3f6a8cac4 100644 --- a/lib/cppcheck.cpp +++ b/lib/cppcheck.cpp @@ -278,6 +278,7 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string fdump << " location.fileIndex << "\" " << "linenr=\"" << tok->location.line << "\" " + << "col=\"" << tok->location.col << "\" " << "str=\"" << ErrorLogger::toxml(tok->str()) << "\"" << "/>" << std::endl; } @@ -577,31 +578,36 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string // [test.cpp:123]: (style) some problem [abc-someProblem] const std::string line = results.substr(pos1, pos2-pos1); - // Line must start with [filename:line]: ( + // Line must start with [filename:line:column]: ( const std::string::size_type loc1 = 1; - const std::string::size_type loc2 = line.find(':'); - const std::string::size_type loc3 = line.find("]: ("); - if (loc2 == std::string::npos || loc3 == std::string::npos) + const std::string::size_type loc4 = line.find("]"); + if (loc4 + 5 >= line.size() || line.compare(loc4, 3, "] (", 0, 3) != 0) continue; - if (!(loc1 < loc2 && loc2 < loc3)) + const std::string::size_type loc3 = line.rfind(':', loc4); + if (loc3 == std::string::npos) + continue; + const std::string::size_type loc2 = line.rfind(':', loc3 - 1); + if (loc2 == std::string::npos) continue; // Then there must be a (severity) - const std::string::size_type sev1 = loc3 + 4; + const std::string::size_type sev1 = loc4 + 3; const std::string::size_type sev2 = line.find(")", sev1); if (sev2 == std::string::npos) continue; // line must end with [addon-x] const std::string::size_type id1 = line.rfind("[" + addonInfo.script + "-"); - if (id1 == std::string::npos || id1 < loc3) + if (id1 == std::string::npos || id1 < sev2) continue; ErrorLogger::ErrorMessage errmsg; const std::string filename = line.substr(loc1, loc2-loc1); const int lineNumber = std::atoi(line.c_str() + loc2 + 1); + const int column = std::atoi(line.c_str() + loc3 + 1); errmsg._callStack.emplace_back(ErrorLogger::ErrorMessage::FileLocation(filename, lineNumber)); + errmsg._callStack.back().col = column; errmsg._id = line.substr(id1+1, line.size()-id1-2); std::string text = line.substr(sev2 + 2, id1 - sev2 - 2); diff --git a/lib/token.cpp b/lib/token.cpp index cb4200f70..a13d00926 100644 --- a/lib/token.cpp +++ b/lib/token.cpp @@ -1360,7 +1360,8 @@ void Token::printAst(bool verbose, bool xml, std::ostream &out) const printed.insert(tok); if (xml) { - out << "scope() << "\" fileIndex=\"" << tok->fileIndex() << "\" linenr=\"" << tok->linenr() << "\">" << std::endl; + out << "scope() << "\" fileIndex=\"" << tok->fileIndex() << "\" linenr=\"" << tok->linenr() + << "\" col=\"" << tok->col() << "\">" << std::endl; astStringXml(tok, 2U, out); out << "" << std::endl; } else if (verbose) diff --git a/lib/tokenize.cpp b/lib/tokenize.cpp index 766bc6864..3955b4c67 100644 --- a/lib/tokenize.cpp +++ b/lib/tokenize.cpp @@ -4696,7 +4696,7 @@ void Tokenizer::dump(std::ostream &out) const // tokens.. out << " " << std::endl; for (const Token *tok = list.front(); tok; tok = tok->next()) { - out << " linenr() << '\"'; + out << " linenr() << "\" col=\"" << tok->col() << "\""; out << " str=\"" << ErrorLogger::toxml(tok->str()) << '\"'; out << " scope=\"" << tok->scope() << '\"'; if (tok->isName()) {