46     if (!msg.callStack.empty()) {
 
   47         ret.
setFileName(msg.callStack.back().getfile(
false));
 
   67         return c > 0 && std::isalnum(c);
 
   76     while (std::getline(istr, line))
 
   77         filedata += line + 
"\n";
 
   78     std::replace(filedata.begin(), filedata.end(), 
'\r', 
'\n');
 
   81     std::istringstream istr2(filedata);
 
   82     while (std::getline(istr2, line)) {
 
   88         if (line.length() > 1 && line[0] == 
'#')
 
   90         if (line.length() >= 2 && line[0] == 
'/' && line[1] == 
'/')
 
  104     tinyxml2::XMLDocument doc;
 
  105     const tinyxml2::XMLError 
error = doc.LoadFile(filename);
 
  106     if (
error != tinyxml2::XML_SUCCESS)
 
  107         return std::string(
"failed to load suppressions XML '") + filename + 
"' (" + tinyxml2::XMLDocument::ErrorIDToName(
error) + 
").";
 
  109     const tinyxml2::XMLElement * 
const rootnode = doc.FirstChildElement();
 
  111         return std::string(
"failed to load suppressions XML '") + filename + 
"' (no root node found).";
 
  113     for (
const tinyxml2::XMLElement * e = rootnode->FirstChildElement(); e; e = e->NextSiblingElement()) {
 
  114         if (std::strcmp(e->Name(), 
"suppress") != 0)
 
  115             return std::string(
"invalid suppression xml file '") + filename + 
"', expected 'suppress' element but got a '" + e->Name() + 
"'.";
 
  118         for (
const tinyxml2::XMLElement * e2 = e->FirstChildElement(); e2; e2 = e2->NextSiblingElement()) {
 
  119             const char *text = e2->GetText() ? e2->GetText() : 
"";
 
  120             if (std::strcmp(e2->Name(), 
"id") == 0)
 
  122             else if (std::strcmp(e2->Name(), 
"fileName") == 0)
 
  124             else if (std::strcmp(e2->Name(), 
"lineNumber") == 0)
 
  126             else if (std::strcmp(e2->Name(), 
"symbolName") == 0)
 
  128             else if (*text && std::strcmp(e2->Name(), 
"hash") == 0)
 
  129                 s.
hash = strToInt<std::size_t>(text);
 
  131                 return std::string(
"unknown element '") + e2->Name() + 
"' in suppressions XML '" + filename + 
"', expected id/fileName/lineNumber/symbolName/hash.";
 
  144     std::vector<Suppression> suppressions;
 
  147     const std::string::size_type start_position = comment.find(
'[');
 
  148     const std::string::size_type end_position = comment.find(
']', start_position);
 
  149     if (end_position == std::string::npos) {
 
  150         if (errorMessage && errorMessage->empty())
 
  151             *errorMessage = 
"Bad multi suppression '" + comment + 
"'. legal format is cppcheck-suppress[errorId, errorId symbolName=arr, ...]";
 
  156     for (std::string::size_type pos = start_position; pos < end_position;) {
 
  157         const std::string::size_type pos1 = pos + 1;
 
  158         pos = comment.find(
',', pos1);
 
  159         const std::string::size_type pos2 = (pos < end_position) ? pos : end_position;
 
  164         std::istringstream iss(comment.substr(pos1, pos2-pos1));
 
  168             if (errorMessage && errorMessage->empty())
 
  169                 *errorMessage = 
"Bad multi suppression '" + comment + 
"'. legal format is cppcheck-suppress[errorId, errorId symbolName=arr, ...]";
 
  170             suppressions.clear();
 
  174         const std::string symbolNameString = 
"symbolName=";
 
  181             if (word.find_first_not_of(
"+-*/%#;") == std::string::npos)
 
  184                 s.
symbolName = word.substr(symbolNameString.size());
 
  186                 if (errorMessage && errorMessage->empty())
 
  187                     *errorMessage = 
"Bad multi suppression '" + comment + 
"'. legal format is cppcheck-suppress[errorId, errorId symbolName=arr, ...]";
 
  188                 suppressions.clear();
 
  193         suppressions.push_back(std::move(s));
 
  201     std::istringstream lineStream;
 
  205     std::string::size_type endpos = std::min(line.find(
'#'), line.find(
"//"));
 
  206     if (endpos != std::string::npos) {
 
  207         while (endpos > 0 && std::isspace(line[endpos-1])) {
 
  210         lineStream.str(line.substr(0, endpos));
 
  212         lineStream.str(line);
 
  215     if (std::getline(lineStream, suppression.
errorId, 
':')) {
 
  216         if (std::getline(lineStream, suppression.
fileName)) {
 
  222             const std::string::size_type pos = suppression.
fileName.rfind(
':');
 
  225             if (pos != std::string::npos &&
 
  226                 suppression.
fileName.find(
'.', pos) == std::string::npos) {
 
  229                     std::istringstream istr1(suppression.
fileName.substr(pos+1));
 
  255             foundSuppression->matched = suppression.
matched;
 
  260     if (suppression.
errorId.empty() && suppression.
hash == 0)
 
  261         return "Failed to add suppression. No id.";
 
  263     for (std::string::size_type pos = 0; pos < suppression.
errorId.length(); ++pos) {
 
  265             return "Failed to add suppression. Invalid id \"" + suppression.
errorId + 
"\"";
 
  267         if (pos == 0 && std::isdigit(suppression.
errorId[pos])) {
 
  268             return "Failed to add suppression. Invalid id \"" + suppression.
errorId + 
"\"";
 
  273         return "Failed to add suppression. Invalid glob pattern '" + suppression.
errorId + 
"'.";
 
  275         return "Failed to add suppression. Invalid glob pattern '" + suppression.
fileName + 
"'.";
 
  284     for (
auto &newSuppression : suppressions) {
 
  299     if (comment.size() < 2)
 
  302     if (comment.find(
';') != std::string::npos)
 
  303         comment.erase(comment.find(
';'));
 
  305     if (comment.find(
"//", 2) != std::string::npos)
 
  306         comment.erase(comment.find(
"//",2));
 
  308     if (comment.compare(comment.size() - 2, 2, 
"*/") == 0)
 
  309         comment.erase(comment.size() - 2, 2);
 
  311     const std::set<std::string> cppchecksuppress{
 
  313         "cppcheck-suppress-begin",
 
  314         "cppcheck-suppress-end",
 
  315         "cppcheck-suppress-file",
 
  316         "cppcheck-suppress-macro" 
  319     std::istringstream iss(comment.substr(2));
 
  322     if (!cppchecksuppress.count(word))
 
  329     const std::string symbolNameString = 
"symbolName=";
 
  335         if (word.find_first_not_of(
"+-*/%#;") == std::string::npos)
 
  338             symbolName = word.substr(symbolNameString.size());
 
  339         else if (errorMessage && errorMessage->empty())
 
  340             *errorMessage = 
"Bad suppression attribute '" + word + 
"'. You can write comments in the comment after a ; or //. Valid suppression attributes; symbolName=sym";
 
  347     if (hash > 0 && hash != errmsg.
hash)
 
  358             if (!thisAndNextLine || lineNumber + 1 != errmsg.
lineNumber)
 
  364     if (!symbolName.empty()) {
 
  365         for (std::string::size_type pos = 0; pos < errmsg.
symbolNames.size();) {
 
  366             const std::string::size_type pos2 = errmsg.
symbolNames.find(
'\n',pos);
 
  368             if (pos2 == std::string::npos) {
 
  395     if (!errorId.empty())
 
  397     if (!fileName.empty())
 
  398         ret += 
" fileName=" + fileName;
 
  399     if (lineNumber != NO_LINE)
 
  400         ret += 
" lineNumber=" + std::to_string(lineNumber);
 
  401     if (!symbolName.empty())
 
  402         ret += 
" symbolName=" + symbolName;
 
  404         ret += 
" hash=" + std::to_string(hash);
 
  406         return ret.substr(1);
 
  412     const bool unmatchedSuppression(errmsg.
errorId == 
"unmatchedSuppression");
 
  413     bool returnValue = 
false;
 
  415         if (!global && !s.isLocal())
 
  417         if (unmatchedSuppression && s.errorId != errmsg.
errorId)
 
  419         if (s.isMatch(errmsg))
 
  428         if (!global && !s.isLocal())
 
  430         if (s.errorId != errmsg.
errorId) 
 
  432         if (s.isMatch(errmsg))
 
  447     out << 
"  <suppressions>" << std::endl;
 
  449         out << 
"    <suppression";
 
  451         if (!suppression.fileName.empty())
 
  454             out << 
" lineNumber=\"" << suppression.lineNumber << 
'"';
 
  455         if (!suppression.symbolName.empty())
 
  457         if (suppression.hash > 0)
 
  458             out << 
" hash=\"" << suppression.hash << 
'\"';
 
  460             out << 
" lineBegin=\"" << suppression.lineBegin << 
'"';
 
  462             out << 
" lineEnd=\"" << suppression.lineEnd << 
'"';
 
  464             out << 
" type=\"file\"";
 
  466             out << 
" type=\"block\"";
 
  468             out << 
" type=\"blockBegin\"";
 
  470             out << 
" type=\"blockEnd\"";
 
  472             out << 
" type=\"macro\"";
 
  473         out << 
" />" << std::endl;
 
  475     out << 
"  </suppressions>" << std::endl;
 
  481     std::list<Suppression> result;
 
  493         if (tmpFile.empty() || !s.isLocal() || s.fileName != tmpFile)
 
  502     std::list<Suppression> result;
 
  526     int currFileIdx = -1;
 
  528         if (currFileIdx != tok->fileIndex() || currLineNr != tok->linenr()) {
 
  529             currLineNr = tok->linenr();
 
  530             currFileIdx = tok->fileIndex();
 
  533                     if (!suppression.checked && (suppression.lineNumber == currLineNr) && (suppression.fileName == tokenizer.
list.
file(tok))) {
 
  534                         suppression.checked = 
true;
 
  537                     if ((!suppression.checked && (suppression.lineBegin <= currLineNr) && (suppression.lineEnd >= currLineNr) && (suppression.fileName == tokenizer.
list.
file(tok)))) {
 
  538                         suppression.checked = 
true;
 
  540                 } 
else if (!suppression.checked && suppression.fileName == tokenizer.
list.
file(tok)) {
 
  541                     suppression.checked = 
true;
 
  554         if (s.errorId == 
"unmatchedSuppression")
 
  558         bool suppressed = 
false;
 
  560             if (s2.errorId == 
"unmatchedSuppression") {
 
  561                 if ((s2.fileName.empty() || s2.fileName == 
"*" || s2.fileName == s.fileName) &&
 
  572         std::list<::ErrorMessage::FileLocation> callStack;
 
  573         if (!s.fileName.empty())
 
  574             callStack.emplace_back(s.fileName, s.lineNumber, 0);
 
This is an interface, which the class responsible of error logging should implement.
 
virtual void reportErr(const ErrorMessage &msg)=0
Information about found errors and warnings is directed here.
 
static std::string toxml(const std::string &str)
Convert XML-sensitive characters into XML entities.
 
static std::string simplifyPath(std::string originalPath)
Simplify path "foo/bar/.." => "foo".
 
static std::vector< Suppression > parseMultiSuppressComment(const std::string &comment, std::string *errorMessage)
Parse multi inline suppression in comment.
 
void dump(std::ostream &out) const
Create an xml dump of suppressions.
 
std::string addSuppressionLine(const std::string &line)
Don't show the given error.
 
void markUnmatchedInlineSuppressionsAsChecked(const Tokenizer &tokenizer)
Marks Inline Suppressions as checked if source line is in the token stream.
 
std::list< Suppression > getUnmatchedGlobalSuppressions(const bool unusedFunctionChecking) const
Returns list of unmatched global (glob pattern) suppressions.
 
const std::list< Suppression > & getSuppressions() const
Returns list of all suppressions.
 
std::string addSuppression(Suppression suppression)
Don't show this error.
 
std::list< Suppression > mSuppressions
List of error which the user doesn't want to see.
 
std::string parseXmlFile(const char *filename)
Don't show errors listed in the file.
 
std::string addSuppressions(std::list< Suppression > suppressions)
Combine list of suppressions into the current suppressions.
 
bool isSuppressed(const ErrorMessage &errmsg, bool global=true)
Returns true if this message should not be shown to the user.
 
bool isSuppressedExplicitly(const ErrorMessage &errmsg, bool global=true)
Returns true if this message is "explicitly" suppressed.
 
static bool reportUnmatchedSuppressions(const std::list< SuppressionList::Suppression > &unmatched, ErrorLogger &errorLogger)
Report unmatched suppressions.
 
std::string parseFile(std::istream &istr)
Don't show errors listed in the file.
 
std::list< Suppression > getUnmatchedLocalSuppressions(const std::string &file, const bool unusedFunctionChecking) const
Returns list of unmatched local (per-file) suppressions.
 
const std::string & file(const Token *tok) const
get filename for given token
 
The token list that the TokenList generates is a linked-list of this class.
 
The main purpose is to tokenize the source code.
 
const Token * tokens() const
 
TokenList list
Token list: stores all tokens.
 
static const std::string emptyString
 
static void replace(std::string &source, const std::unordered_map< std::string, std::string > &substitutionMap)
 
@ information
Checking information.
 
@ error
Programming error.
 
void setFileName(std::string s)
 
const std::string & getFileName() const
 
static SuppressionList::ErrorMessage fromErrorMessage(const ::ErrorMessage &msg, const std::set< std::string > ¯oNames)
 
std::set< std::string > macroNames
 
bool isSuppressed(const ErrorMessage &errmsg) const
 
bool isSameParameters(const Suppression &other) const
 
bool parseComment(std::string comment, std::string *errorMessage)
Parse inline suppression in comment.
 
std::string getText() const
 
bool isMatch(const ErrorMessage &errmsg)
 
static const char ID_CHECKERSREPORT[]
 
static const char ID_UNUSEDFUNCTION[]
 
static bool isAcceptedErrorIdChar(char c)
 
bool matchglob(const std::string &pattern, const std::string &name)
 
bool isValidGlobPattern(const std::string &pattern)
 
bool startsWith(const std::string &str, const char start[], std::size_t startlen)