parent
ad4e688ff8
commit
dd76504f82
|
@ -33,7 +33,7 @@ Executor::Executor(const std::map<std::string, std::size_t> &files, const Settin
|
|||
|
||||
bool Executor::hasToLog(const ErrorMessage &msg)
|
||||
{
|
||||
if (!mSuppressions.isSuppressed(msg))
|
||||
if (!mSuppressions.isSuppressed(msg, {}))
|
||||
{
|
||||
std::string errmsg = msg.toString(mSettings.verbose);
|
||||
|
||||
|
|
|
@ -394,7 +394,7 @@ void ProcessExecutor::reportInternalChildErr(const std::string &childname, const
|
|||
"cppcheckError",
|
||||
Certainty::normal);
|
||||
|
||||
if (!mSuppressions.isSuppressed(errmsg))
|
||||
if (!mSuppressions.isSuppressed(errmsg, {}))
|
||||
mErrorLogger.reportErr(errmsg);
|
||||
}
|
||||
|
||||
|
|
|
@ -858,6 +858,13 @@ unsigned int CppCheck::checkFile(const std::string& filename, const std::string
|
|||
}
|
||||
hasValidConfig = true;
|
||||
|
||||
// locations macros
|
||||
mLocationMacros.clear();
|
||||
for (const Token* tok = tokenizer.tokens(); tok; tok = tok->next()) {
|
||||
if (!tok->getMacroName().empty())
|
||||
mLocationMacros[Location(files[tok->fileIndex()], tok->linenr())].emplace(tok->getMacroName());
|
||||
}
|
||||
|
||||
// If only errors are printed, print filename after the check
|
||||
if (!mSettings.quiet && (!mCurrentConfig.empty() || checkCount > 1)) {
|
||||
std::string fixedpath = Path::simplifyPath(filename);
|
||||
|
@ -1556,8 +1563,17 @@ void CppCheck::reportErr(const ErrorMessage &msg)
|
|||
if (!mSettings.buildDir.empty())
|
||||
mAnalyzerInformation.reportErr(msg);
|
||||
|
||||
std::set<std::string> macroNames;
|
||||
if (!msg.callStack.empty()) {
|
||||
const std::string &file = msg.callStack.back().getfile(false);
|
||||
int lineNumber = msg.callStack.back().line;
|
||||
const auto it = mLocationMacros.find(Location(file, lineNumber));
|
||||
if (it != mLocationMacros.cend())
|
||||
macroNames = it->second;
|
||||
}
|
||||
|
||||
// TODO: only convert if necessary
|
||||
const auto errorMessage = Suppressions::ErrorMessage::fromErrorMessage(msg);
|
||||
const auto errorMessage = Suppressions::ErrorMessage::fromErrorMessage(msg, macroNames);
|
||||
|
||||
if (mSettings.nomsg.isSuppressed(errorMessage, mUseGlobalSuppressions)) {
|
||||
return;
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#include <functional>
|
||||
#include <list>
|
||||
#include <map>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
@ -223,6 +224,9 @@ private:
|
|||
/** @brief Current preprocessor configuration */
|
||||
std::string mCurrentConfig;
|
||||
|
||||
using Location = std::pair<std::string, int>;
|
||||
std::map<Location, std::set<std::string>> mLocationMacros; // What macros are used on a location?
|
||||
|
||||
unsigned int mExitCode{};
|
||||
|
||||
bool mUseGlobalSuppressions;
|
||||
|
|
|
@ -119,15 +119,16 @@ static bool parseInlineSuppressionCommentToken(const simplecpp::Token *tok, std:
|
|||
const std::string suppressTypeString =
|
||||
comment.substr(pos1 + cppchecksuppress.size() + 1, argumentLength);
|
||||
|
||||
if ("file" == suppressTypeString) {
|
||||
if ("file" == suppressTypeString)
|
||||
errorType = Suppressions::Type::file;
|
||||
} else if ("begin" == suppressTypeString) {
|
||||
else if ("begin" == suppressTypeString)
|
||||
errorType = Suppressions::Type::blockBegin;
|
||||
} else if ("end" == suppressTypeString) {
|
||||
else if ("end" == suppressTypeString)
|
||||
errorType = Suppressions::Type::blockEnd;
|
||||
} else {
|
||||
else if ("macro" == suppressTypeString)
|
||||
errorType = Suppressions::Type::macro;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (comment[pos2] == '[') {
|
||||
|
@ -217,6 +218,15 @@ static void addInlineSuppressions(const simplecpp::TokenList &tokens, const Sett
|
|||
}
|
||||
relativeFilename = Path::simplifyPath(relativeFilename);
|
||||
|
||||
// Macro name
|
||||
std::string macroName;
|
||||
if (tok->str() == "#" && tok->next && tok->next->str() == "define") {
|
||||
const simplecpp::Token *macroNameTok = tok->next->next;
|
||||
if (sameline(tok, macroNameTok) && macroNameTok->name) {
|
||||
macroName = macroNameTok->str();
|
||||
}
|
||||
}
|
||||
|
||||
// Add the suppressions.
|
||||
for (Suppressions::Suppression &suppr : inlineSuppressions) {
|
||||
suppr.fileName = relativeFilename;
|
||||
|
@ -252,7 +262,7 @@ static void addInlineSuppressions(const simplecpp::TokenList &tokens, const Sett
|
|||
// NOLINTNEXTLINE(bugprone-use-after-move) - moved only when thrownError is false
|
||||
bad.emplace_back(suppr.fileName, suppr.lineNumber, "Suppress End: No matching begin");
|
||||
}
|
||||
} else if (Suppressions::Type::unique == suppr.type) {
|
||||
} else if (Suppressions::Type::unique == suppr.type || suppr.type == Suppressions::Type::macro) {
|
||||
// special handling when suppressing { warnings for backwards compatibility
|
||||
const bool thisAndNextLine = tok->previous &&
|
||||
tok->previous->previous &&
|
||||
|
@ -264,6 +274,7 @@ static void addInlineSuppressions(const simplecpp::TokenList &tokens, const Sett
|
|||
|
||||
suppr.thisAndNextLine = thisAndNextLine;
|
||||
suppr.lineNumber = tok->location.line;
|
||||
suppr.macroName = macroName;
|
||||
suppressions.addSuppression(std::move(suppr));
|
||||
} else if (Suppressions::Type::file == suppr.type) {
|
||||
if (onlyComments)
|
||||
|
|
|
@ -35,7 +35,7 @@
|
|||
|
||||
#include <tinyxml2.h>
|
||||
|
||||
Suppressions::ErrorMessage Suppressions::ErrorMessage::fromErrorMessage(const ::ErrorMessage &msg)
|
||||
Suppressions::ErrorMessage Suppressions::ErrorMessage::fromErrorMessage(const ::ErrorMessage &msg, const std::set<std::string> ¯oNames)
|
||||
{
|
||||
Suppressions::ErrorMessage ret;
|
||||
ret.hash = msg.hash;
|
||||
|
@ -48,6 +48,7 @@ Suppressions::ErrorMessage Suppressions::ErrorMessage::fromErrorMessage(const ::
|
|||
}
|
||||
ret.certainty = msg.certainty;
|
||||
ret.symbolNames = msg.symbolNames();
|
||||
ret.macroNames = macroNames;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -308,7 +309,8 @@ bool Suppressions::Suppression::parseComment(std::string comment, std::string *e
|
|||
"cppcheck-suppress",
|
||||
"cppcheck-suppress-begin",
|
||||
"cppcheck-suppress-end",
|
||||
"cppcheck-suppress-file"
|
||||
"cppcheck-suppress-file",
|
||||
"cppcheck-suppress-macro"
|
||||
};
|
||||
|
||||
std::istringstream iss(comment.substr(2));
|
||||
|
@ -343,14 +345,19 @@ bool Suppressions::Suppression::isSuppressed(const Suppressions::ErrorMessage &e
|
|||
return false;
|
||||
if (!errorId.empty() && !matchglob(errorId, errmsg.errorId))
|
||||
return false;
|
||||
if (!fileName.empty() && !matchglob(fileName, errmsg.getFileName()))
|
||||
return false;
|
||||
if ((Suppressions::Type::unique == type) && (lineNumber != NO_LINE) && (lineNumber != errmsg.lineNumber)) {
|
||||
if (!thisAndNextLine || lineNumber + 1 != errmsg.lineNumber)
|
||||
if (type == Suppressions::Type::macro) {
|
||||
if (errmsg.macroNames.count(macroName) == 0)
|
||||
return false;
|
||||
} else {
|
||||
if (!fileName.empty() && !matchglob(fileName, errmsg.getFileName()))
|
||||
return false;
|
||||
if ((Suppressions::Type::unique == type) && (lineNumber != NO_LINE) && (lineNumber != errmsg.lineNumber)) {
|
||||
if (!thisAndNextLine || lineNumber + 1 != errmsg.lineNumber)
|
||||
return false;
|
||||
}
|
||||
if ((Suppressions::Type::block == type) && ((errmsg.lineNumber < lineBegin) || (errmsg.lineNumber > lineEnd)))
|
||||
return false;
|
||||
}
|
||||
if ((Suppressions::Type::block == type) && ((errmsg.lineNumber < lineBegin) || (errmsg.lineNumber > lineEnd)))
|
||||
return false;
|
||||
if (!symbolName.empty()) {
|
||||
for (std::string::size_type pos = 0; pos < errmsg.symbolNames.size();) {
|
||||
const std::string::size_type pos2 = errmsg.symbolNames.find('\n',pos);
|
||||
|
@ -412,11 +419,11 @@ bool Suppressions::isSuppressed(const Suppressions::ErrorMessage &errmsg, bool g
|
|||
return returnValue;
|
||||
}
|
||||
|
||||
bool Suppressions::isSuppressed(const ::ErrorMessage &errmsg)
|
||||
bool Suppressions::isSuppressed(const ::ErrorMessage &errmsg, const std::set<std::string>& macroNames)
|
||||
{
|
||||
if (mSuppressions.empty())
|
||||
return false;
|
||||
return isSuppressed(Suppressions::ErrorMessage::fromErrorMessage(errmsg));
|
||||
return isSuppressed(Suppressions::ErrorMessage::fromErrorMessage(errmsg, macroNames));
|
||||
}
|
||||
|
||||
void Suppressions::dump(std::ostream & out) const
|
||||
|
@ -445,6 +452,8 @@ std::list<Suppressions::Suppression> Suppressions::getUnmatchedLocalSuppressions
|
|||
for (const Suppression &s : mSuppressions) {
|
||||
if (s.matched || ((s.lineNumber != Suppression::NO_LINE) && !s.checked))
|
||||
continue;
|
||||
if (s.type == Suppressions::Type::macro)
|
||||
continue;
|
||||
if (s.hash > 0)
|
||||
continue;
|
||||
if (!unusedFunctionChecking && s.errorId == "unusedFunction")
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include <cstddef>
|
||||
#include <istream>
|
||||
#include <list>
|
||||
#include <set>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
@ -42,7 +43,7 @@ class CPPCHECKLIB Suppressions {
|
|||
public:
|
||||
|
||||
enum class Type {
|
||||
unique, file, block, blockBegin, blockEnd
|
||||
unique, file, block, blockBegin, blockEnd, macro
|
||||
};
|
||||
|
||||
struct CPPCHECKLIB ErrorMessage {
|
||||
|
@ -55,8 +56,9 @@ public:
|
|||
int lineNumber;
|
||||
Certainty certainty;
|
||||
std::string symbolNames;
|
||||
std::set<std::string> macroNames;
|
||||
|
||||
static Suppressions::ErrorMessage fromErrorMessage(const ::ErrorMessage &msg);
|
||||
static Suppressions::ErrorMessage fromErrorMessage(const ::ErrorMessage &msg, const std::set<std::string> ¯oNames);
|
||||
private:
|
||||
std::string mFileName;
|
||||
};
|
||||
|
@ -74,6 +76,8 @@ public:
|
|||
return fileName < other.fileName;
|
||||
if (symbolName != other.symbolName)
|
||||
return symbolName < other.symbolName;
|
||||
if (macroName != other.macroName)
|
||||
return macroName < other.macroName;
|
||||
if (hash != other.hash)
|
||||
return hash < other.hash;
|
||||
if (thisAndNextLine != other.thisAndNextLine)
|
||||
|
@ -90,6 +94,8 @@ public:
|
|||
return false;
|
||||
if (symbolName != other.symbolName)
|
||||
return false;
|
||||
if (macroName != other.macroName)
|
||||
return false;
|
||||
if (hash != other.hash)
|
||||
return false;
|
||||
if (type != other.type)
|
||||
|
@ -135,6 +141,7 @@ public:
|
|||
int lineEnd = NO_LINE;
|
||||
Type type = Type::unique;
|
||||
std::string symbolName;
|
||||
std::string macroName;
|
||||
std::size_t hash{};
|
||||
bool thisAndNextLine{}; // Special case for backwards compatibility: { // cppcheck-suppress something
|
||||
bool matched{};
|
||||
|
@ -200,7 +207,7 @@ public:
|
|||
* @param errmsg error message
|
||||
* @return true if this error is suppressed.
|
||||
*/
|
||||
bool isSuppressed(const ::ErrorMessage &errmsg);
|
||||
bool isSuppressed(const ::ErrorMessage &errmsg, const std::set<std::string>& macroNames);
|
||||
|
||||
/**
|
||||
* @brief Create an xml dump of suppressions
|
||||
|
|
17
lib/token.h
17
lib/token.h
|
@ -106,6 +106,9 @@ struct TokenImpl {
|
|||
// original name like size_t
|
||||
std::string* mOriginalName{};
|
||||
|
||||
// If this token came from a macro replacement list, this is the name of that macro
|
||||
std::string mMacroName;
|
||||
|
||||
// ValueType
|
||||
ValueType* mValueType{};
|
||||
|
||||
|
@ -461,10 +464,7 @@ public:
|
|||
setFlag(fIsStandardType, b);
|
||||
}
|
||||
bool isExpandedMacro() const {
|
||||
return getFlag(fIsExpandedMacro);
|
||||
}
|
||||
void isExpandedMacro(const bool m) {
|
||||
setFlag(fIsExpandedMacro, m);
|
||||
return !mImpl->mMacroName.empty();
|
||||
}
|
||||
bool isCast() const {
|
||||
return getFlag(fIsCast);
|
||||
|
@ -763,6 +763,13 @@ public:
|
|||
setFlag(fIsTemplateArg, value);
|
||||
}
|
||||
|
||||
std::string getMacroName() const {
|
||||
return mImpl->mMacroName;
|
||||
}
|
||||
void setMacroName(std::string name) {
|
||||
mImpl->mMacroName = std::move(name);
|
||||
}
|
||||
|
||||
template<size_t count>
|
||||
static const Token *findsimplematch(const Token * const startTok, const char (&pattern)[count]) {
|
||||
return findsimplematch(startTok, pattern, count-1);
|
||||
|
@ -1305,7 +1312,7 @@ private:
|
|||
fIsPointerCompare = (1ULL << 2),
|
||||
fIsLong = (1ULL << 3),
|
||||
fIsStandardType = (1ULL << 4),
|
||||
fIsExpandedMacro = (1ULL << 5),
|
||||
//fIsExpandedMacro = (1ULL << 5),
|
||||
fIsCast = (1ULL << 6),
|
||||
fIsAttributeConstructor = (1ULL << 7), // __attribute__((constructor)) __attribute__((constructor(priority)))
|
||||
fIsAttributeDestructor = (1ULL << 8), // __attribute__((destructor)) __attribute__((destructor(priority)))
|
||||
|
|
|
@ -806,7 +806,7 @@ namespace {
|
|||
if (pointerType) {
|
||||
tok->insertToken("const");
|
||||
tok->next()->column(tok->column());
|
||||
tok->next()->isExpandedMacro(tok->previous()->isExpandedMacro());
|
||||
tok->next()->setMacroName(tok->previous()->getMacroName());
|
||||
tok->deletePrevious();
|
||||
}
|
||||
}
|
||||
|
@ -7169,7 +7169,7 @@ void Tokenizer::simplifyVarDecl(Token * tokBegin, const Token * const tokEnd, co
|
|||
endDecl = endDecl->next();
|
||||
endDecl->next()->isSplittedVarDeclEq(true);
|
||||
endDecl->insertToken(varName->str());
|
||||
endDecl->next()->isExpandedMacro(varName->isExpandedMacro());
|
||||
endDecl->next()->setMacroName(varName->getMacroName());
|
||||
continue;
|
||||
}
|
||||
//non-VLA case
|
||||
|
|
|
@ -306,6 +306,7 @@ void TokenList::insertTokens(Token *dest, const Token *src, nonneg int n)
|
|||
dest->varId(src->varId());
|
||||
dest->tokType(src->tokType());
|
||||
dest->flags(src->flags());
|
||||
dest->setMacroName(src->getMacroName());
|
||||
src = src->next();
|
||||
--n;
|
||||
}
|
||||
|
@ -363,7 +364,7 @@ void TokenList::createTokens(simplecpp::TokenList&& tokenList)
|
|||
mTokensFrontBack.back->fileIndex(tok->location.fileIndex);
|
||||
mTokensFrontBack.back->linenr(tok->location.line);
|
||||
mTokensFrontBack.back->column(tok->location.col);
|
||||
mTokensFrontBack.back->isExpandedMacro(!tok->macro.empty());
|
||||
mTokensFrontBack.back->setMacroName(tok->macro);
|
||||
|
||||
tok = tok->next;
|
||||
if (tok)
|
||||
|
|
|
@ -530,6 +530,41 @@ Suppressing multiple ids in one comment by using []:
|
|||
|
||||
// cppcheck-suppress [aaaa, bbbb]
|
||||
|
||||
Suppressing warnings `aaaa` on a block of code:
|
||||
|
||||
// cppcheck-suppress-begin aaaa
|
||||
...
|
||||
// cppcheck-suppress-end aaaa
|
||||
|
||||
Suppressing multiple ids on a block of code:
|
||||
|
||||
// cppcheck-suppress-begin [aaaa, bbbb]
|
||||
...
|
||||
// cppcheck-suppress-end [aaaa, bbbb]
|
||||
|
||||
Suppressing warnings `aaaa` for a whole file:
|
||||
|
||||
// cppcheck-suppress-file aaaa
|
||||
|
||||
Suppressing multiple ids for a whole file:
|
||||
|
||||
// cppcheck-suppress-file [aaaa, bbbb]
|
||||
|
||||
Suppressing warnings `aaaa` where macro is used:
|
||||
|
||||
// cppcheck-suppress-macro aaaa
|
||||
#define MACRO ...
|
||||
...
|
||||
x = MACRO; // <- aaaa warnings are suppressed here
|
||||
|
||||
|
||||
Suppressing multiple ids where macro is used:
|
||||
|
||||
// cppcheck-suppress-macro [aaaa, bbbb]
|
||||
#define MACRO ...
|
||||
...
|
||||
x = MACRO; // <- aaaa and bbbb warnings are suppressed here
|
||||
|
||||
### Comment before code or on same line
|
||||
|
||||
The comment can be put before the code or at the same line as the code.
|
||||
|
|
|
@ -551,6 +551,21 @@ Suppressing multiple ids for a whole file:
|
|||
|
||||
// cppcheck-suppress-file [aaaa, bbbb]
|
||||
|
||||
Suppressing warnings `aaaa` where macro is used:
|
||||
|
||||
// cppcheck-suppress-macro aaaa
|
||||
#define MACRO ...
|
||||
...
|
||||
x = MACRO; // <- aaaa warnings are suppressed here
|
||||
|
||||
|
||||
Suppressing multiple ids where macro is used:
|
||||
|
||||
// cppcheck-suppress-macro [aaaa, bbbb]
|
||||
#define MACRO ...
|
||||
...
|
||||
x = MACRO; // <- aaaa and bbbb warnings are suppressed here
|
||||
|
||||
### Comment before code or on same line
|
||||
|
||||
The comment can be put before the code or at the same line as the code.
|
||||
|
|
|
@ -24,3 +24,7 @@ Other:
|
|||
- "--project" can also no longer be used in conjunction with additional source files.
|
||||
- If a addon cannot be found it will bail out immediately instead of continously writing errors and failing the analysis at the end.
|
||||
- Added CMake option "BUILD_MANPAGE" which adds the "man" target which will build the manpage. This requires xsltproc and the docbook XSLs to be installed.
|
||||
- Improved inline suppressions:
|
||||
- You can suppress warnings in a block of code using "-begin" and "-end".
|
||||
- You can suppress warnings in current file using "-file".
|
||||
- You can suppress all warnings where macro is used using "-macro"
|
||||
|
|
|
@ -777,6 +777,19 @@ private:
|
|||
" int a; return a;\n"
|
||||
"}\n",
|
||||
"uninitvar"));
|
||||
|
||||
// cppcheck-suppress-macro
|
||||
(this->*check)("// cppcheck-suppress-macro zerodiv\n"
|
||||
"#define DIV(A,B) A/B\n"
|
||||
"a = DIV(10,0);\n",
|
||||
"");
|
||||
ASSERT_EQUALS("", errout.str());
|
||||
|
||||
(this->*check)("// cppcheck-suppress-macro abc\n"
|
||||
"#define DIV(A,B) A/B\n"
|
||||
"a = DIV(10,1);\n",
|
||||
"");
|
||||
ASSERT_EQUALS("", errout.str()); // <- no unmatched suppression reported for macro suppression
|
||||
}
|
||||
|
||||
void suppressionsSettings() {
|
||||
|
|
Loading…
Reference in New Issue