Support cppcheck-suppression in C style comments

This commit is contained in:
Greg Hewgill 2011-02-20 11:36:03 +13:00
parent 7e5d8e42d4
commit 98ab34b2b5
2 changed files with 166 additions and 111 deletions

View File

@ -338,20 +338,32 @@ std::string Preprocessor::removeComments(const std::string &str, const std::stri
continue; continue;
} }
// We have finished a line that didn't contain any comment // First skip over any whitespace that may be present
// (the '\n' is swallowed when a // comment is detected) if (std::isspace(ch))
if ((ch == '\n' || str.compare(i,2,"//")==0) && !suppressionIDs.empty())
{ {
// Add the suppressions. if (ch == ' ' && previous == ' ')
for (size_t j(0); j < suppressionIDs.size(); ++j)
{ {
const std::string errmsg(settings->nomsg.addSuppression(suppressionIDs[j], filename, lineno)); // Skip double white space
if (!errmsg.empty()) }
else
{
code << char(ch);
previous = ch;
}
// if there has been <backspace><newline> sequences, add extra newlines..
if (ch == '\n')
{
++lineno;
if (newlines > 0)
{ {
writeError(filename, lineno, _errorLogger, "cppcheckError", errmsg); code << std::string(newlines, '\n');
newlines = 0;
previous = '\n';
} }
} }
suppressionIDs.clear();
continue;
} }
// Remove comments.. // Remove comments..
@ -382,6 +394,7 @@ std::string Preprocessor::removeComments(const std::string &str, const std::stri
} }
else if (str.compare(i, 2, "/*", 0, 2) == 0) else if (str.compare(i, 2, "/*", 0, 2) == 0)
{ {
size_t commentStart = i + 2;
unsigned char chPrev = 0; unsigned char chPrev = 0;
++i; ++i;
while (i < str.length() && (chPrev != '*' || ch != '/')) while (i < str.length() && (chPrev != '*' || ch != '/'))
@ -395,126 +408,139 @@ std::string Preprocessor::removeComments(const std::string &str, const std::stri
++lineno; ++lineno;
} }
} }
}
// String or char constants.. if (settings && settings->_inlineSuppressions)
else if (ch == '\"' || ch == '\'')
{
code << char(ch);
char chNext;
do
{ {
++i; std::string comment(str, commentStart, i - commentStart);
chNext = str[i]; std::istringstream iss(comment);
if (chNext == '\\') std::string word;
iss >> word;
if (word == "cppcheck-suppress")
{
iss >> word;
if (iss)
suppressionIDs.push_back(word);
}
}
}
else
{
// Not whitespace and not a comment. Must be code here!
// Add any pending inline suppressions that have accumulated.
if (!suppressionIDs.empty())
{
if (settings != NULL)
{
// Add the suppressions.
for (size_t j(0); j < suppressionIDs.size(); ++j)
{
const std::string errmsg(settings->nomsg.addSuppression(suppressionIDs[j], filename, lineno));
if (!errmsg.empty())
{
writeError(filename, lineno, _errorLogger, "cppcheckError", errmsg);
}
}
}
suppressionIDs.clear();
}
// String or char constants..
if (ch == '\"' || ch == '\'')
{
code << char(ch);
char chNext;
do
{ {
++i; ++i;
char chSeq = str[i]; chNext = str[i];
if (chSeq == '\n') if (chNext == '\\')
++newlines; {
++i;
char chSeq = str[i];
if (chSeq == '\n')
++newlines;
else
{
code << chNext;
code << chSeq;
previous = static_cast<unsigned char>(chSeq);
}
}
else else
{ {
code << chNext; code << chNext;
code << chSeq; previous = static_cast<unsigned char>(chNext);
previous = static_cast<unsigned char>(chSeq);
} }
} }
while (i < str.length() && chNext != ch && chNext != '\n');
}
// Rawstring..
else if (str.compare(i,2,"R\"")==0)
{
std::string delim;
for (std::string::size_type i2 = i+2; i2 < str.length(); ++i2)
{
if (i2 > 16 ||
std::isspace(str[i2]) ||
std::iscntrl(str[i2]) ||
str[i2] == ')' ||
str[i2] == '\\')
{
delim = " ";
break;
}
else if (str[i2] == '(')
break;
delim += str[i2];
}
const std::string::size_type endpos = str.find(")" + delim + "\"", i);
if (delim != " " && endpos != std::string::npos)
{
unsigned int rawstringnewlines = 0;
code << '\"';
for (std::string::size_type p = i + 3 + delim.size(); p < endpos; ++p)
{
if (str[p] == '\n')
{
rawstringnewlines++;
code << "\\n";
}
else if (std::iscntrl((unsigned char)str[p]) ||
std::isspace((unsigned char)str[p]))
{
code << " ";
}
else if (str[p] == '\\')
{
code << "\\";
}
else if (str[p] == '\"' || str[p] == '\'')
{
code << "\\" << (char)str[p];
}
else
{
code << (char)str[p];
}
}
code << "\"";
if (rawstringnewlines > 0)
code << std::string(rawstringnewlines, '\n');
i = endpos + delim.size() + 2;
}
else else
{ {
code << chNext; code << "R";
previous = static_cast<unsigned char>(chNext); previous = 'R';
} }
} }
while (i < str.length() && chNext != ch && chNext != '\n');
}
// Rawstring..
else if (str.compare(i,2,"R\"")==0)
{
std::string delim;
for (std::string::size_type i2 = i+2; i2 < str.length(); ++i2)
{
if (i2 > 16 ||
std::isspace(str[i2]) ||
std::iscntrl(str[i2]) ||
str[i2] == ')' ||
str[i2] == '\\')
{
delim = " ";
break;
}
else if (str[i2] == '(')
break;
delim += str[i2];
}
const std::string::size_type endpos = str.find(")" + delim + "\"", i);
if (delim != " " && endpos != std::string::npos)
{
unsigned int rawstringnewlines = 0;
code << '\"';
for (std::string::size_type p = i + 3 + delim.size(); p < endpos; ++p)
{
if (str[p] == '\n')
{
rawstringnewlines++;
code << "\\n";
}
else if (std::iscntrl((unsigned char)str[p]) ||
std::isspace((unsigned char)str[p]))
{
code << " ";
}
else if (str[p] == '\\')
{
code << "\\";
}
else if (str[p] == '\"' || str[p] == '\'')
{
code << "\\" << (char)str[p];
}
else
{
code << (char)str[p];
}
}
code << "\"";
if (rawstringnewlines > 0)
code << std::string(rawstringnewlines, '\n');
i = endpos + delim.size() + 2;
}
else
{
code << "R";
previous = 'R';
}
}
// Just some code..
else
{
if (ch == ' ' && previous == ' ')
{
// Skip double white space
}
else else
{ {
code << char(ch); code << char(ch);
previous = ch; previous = ch;
} }
// if there has been <backspace><newline> sequences, add extra newlines..
if (ch == '\n')
{
++lineno;
if (newlines > 0)
{
code << std::string(newlines, '\n');
newlines = 0;
previous = '\n';
}
}
} }
} }

View File

@ -172,6 +172,35 @@ private:
""); "");
ASSERT_EQUALS("", errout.str()); ASSERT_EQUALS("", errout.str());
// suppress uninitvar inline
(this->*check)("void f() {\n"
" int a;\n"
" // cppcheck-suppress uninitvar\n"
"\n"
" a++;\n"
"}\n",
"");
ASSERT_EQUALS("", errout.str());
// suppress uninitvar inline
(this->*check)("void f() {\n"
" int a;\n"
" /* cppcheck-suppress uninitvar */\n"
" a++;\n"
"}\n",
"");
ASSERT_EQUALS("", errout.str());
// suppress uninitvar inline
(this->*check)("void f() {\n"
" int a;\n"
" /* cppcheck-suppress uninitvar */\n"
"\n"
" a++;\n"
"}\n",
"");
ASSERT_EQUALS("", errout.str());
// suppress uninitvar inline, without error present // suppress uninitvar inline, without error present
(this->*check)("void f() {\n" (this->*check)("void f() {\n"
" int a;\n" " int a;\n"