diff options
Diffstat (limited to 'src/checks/level0/unused-non-trivial-variable.cpp')
-rw-r--r-- | src/checks/level0/unused-non-trivial-variable.cpp | 112 |
1 files changed, 84 insertions, 28 deletions
diff --git a/src/checks/level0/unused-non-trivial-variable.cpp b/src/checks/level0/unused-non-trivial-variable.cpp index a05ee2a3..03023ff6 100644 --- a/src/checks/level0/unused-non-trivial-variable.cpp +++ b/src/checks/level0/unused-non-trivial-variable.cpp @@ -21,11 +21,12 @@ #include "unused-non-trivial-variable.h" #include "Utils.h" -#include "checkmanager.h" + #include "StringUtils.h" #include "HierarchyUtils.h" #include "ContextUtils.h" #include "QtUtils.h" +#include "clazy_stl.h" #include <clang/AST/AST.h> #include <clang/Lex/Lexer.h> @@ -38,8 +39,16 @@ using namespace std; UnusedNonTrivialVariable::UnusedNonTrivialVariable(const std::string &name, ClazyContext *context) - : CheckBase(name, context) + : CheckBase(name, context, Option_CanIgnoreIncludes) { + const char *user_blacklist = getenv("CLAZY_UNUSED_NON_TRIVIAL_VARIABLE_BLACKLIST"); + const char *user_whitelist = getenv("CLAZY_UNUSED_NON_TRIVIAL_VARIABLE_WHITELIST"); + + if (user_blacklist) + m_userBlacklist = clazy::splitString(user_blacklist, ','); + + if (user_whitelist) + m_userWhitelist = clazy::splitString(user_whitelist, ','); } void UnusedNonTrivialVariable::VisitStmt(clang::Stmt *stmt) @@ -52,29 +61,79 @@ void UnusedNonTrivialVariable::VisitStmt(clang::Stmt *stmt) handleVarDecl(dyn_cast<VarDecl>(decl)); } +bool UnusedNonTrivialVariable::isUninterestingType(const CXXRecordDecl *record) const +{ + static const vector<StringRef> blacklist = { "QMutexLocker", "QDebugStateSaver", + "QTextBlockFormat", "QWriteLocker", + "QSignalBlocker", "QReadLocker", "PRNGLocker", "QDBusWriteLocker", "QDBusBlockingCallWatcher", + "QBoolBlocker", "QOrderedMutexLocker", "QTextLine", "QScopedScopeLevelCounter" }; + + // Check some obvious candidates first + StringRef typeName = clazy::name(record); + bool any = clazy::any_of(blacklist, [typeName] (StringRef container) { + return container == typeName; + }); + + if (any) + return true; + + static const vector<StringRef> blacklistedTemplates = { "QScopedPointer", "QSetValueOnDestroy", "QScopedValueRollback" }; + StringRef className = clazy::name(record); + for (StringRef templateName : blacklistedTemplates) { + if (clazy::startsWith(className, templateName)) + return true; + } + + // Now check the user's blacklist, set by env-variable + any = clazy::any_of(m_userBlacklist, [typeName] (const std::string &container) { + return container == typeName; + }); + + if (any) + return true; + + return false; +} + bool UnusedNonTrivialVariable::isInterestingType(QualType t) const { // TODO Remove QColor in Qt6 - static const vector<string> nonTrivialTypes = { "QColor", "QVariant", "QFont", "QUrl", "QIcon", - "QImage", "QPixmap", "QPicture", "QBitmap", "QBrush", - "QPen", "QBuffer", "QCache", "QDateTime", "QDir", "QEvent", - "QFileInfo", "QFontInfo", "QFontMetrics", "QJSValue", "QLocale", - "QRegularExpression", "QRegExp", "QUrlQuery", "QStorageInfo", - "QPersistentModelIndex", "QJsonArray", "QJsonDocument", - "QMimeType", "QBitArray", "QCollator", - "QByteArrayList", "QCollatorSortKey", - "QCursor", "QPalette", "QPainterPath", "QRegion", "QFontInfo", "QTextCursor", - "QStaticText", "QFontMetricsF", "QTextFrameFormat", "QTextImageFormat", - "QNetworkCookie", "QNetworkRequest", "QNetworkConfiguration", - "QHostAddress", "QSqlQuery", "QSqlRecord", "QSqlField", - "QLine", "QLineF", "QRect", "QRectF" - }; - - if (QtUtils::isQtContainer(t)) + static const vector<StringRef> nonTrivialTypes = { "QColor", "QVariant", "QFont", "QUrl", "QIcon", + "QImage", "QPixmap", "QPicture", "QBitmap", "QBrush", + "QPen", "QBuffer", "QCache", "QDateTime", "QDir", "QEvent", + "QFileInfo", "QFontInfo", "QFontMetrics", "QJSValue", "QLocale", + "QRegularExpression", "QRegExp", "QUrlQuery", "QStorageInfo", + "QPersistentModelIndex", "QJsonArray", "QJsonDocument", + "QMimeType", "QBitArray", "QCollator", + "QByteArrayList", "QCollatorSortKey", + "QCursor", "QPalette", "QPainterPath", "QRegion", "QFontInfo", "QTextCursor", + "QStaticText", "QFontMetricsF", "QTextFrameFormat", "QTextImageFormat", + "QNetworkCookie", "QNetworkRequest", "QNetworkConfiguration", + "QHostAddress", "QSqlQuery", "QSqlRecord", "QSqlField", + "QLine", "QLineF", "QRect", "QRectF" + }; + + CXXRecordDecl *record = TypeUtils::typeAsRecord(t); + if (!record) + return false; + + if (isOptionSet("no-whitelist")) { + // Will cause too many false-positives, like RAII classes. Use suppressing comments to silence them. + return !isUninterestingType(record); + } + + if (clazy::isQtContainer(record)) + return true; + + StringRef typeName = clazy::name(record); + bool any = clazy::any_of(nonTrivialTypes, [typeName] (StringRef container) { + return container == typeName; + }); + + if (any) return true; - const string typeName = StringUtils::simpleTypeName(t, lo()); - return clazy_std::any_of(nonTrivialTypes, [typeName] (const string &container) { + return clazy::any_of(m_userWhitelist, [typeName] (const std::string &container) { return container == typeName; }); } @@ -84,22 +143,19 @@ void UnusedNonTrivialVariable::handleVarDecl(VarDecl *varDecl) if (!varDecl || !isInterestingType(varDecl->getType())) return; - auto currentFunc = ContextUtils::firstContextOfType<FunctionDecl>(varDecl->getDeclContext()); + auto currentFunc = clazy::firstContextOfType<FunctionDecl>(varDecl->getDeclContext()); Stmt *body = currentFunc ? currentFunc->getBody() : nullptr; if (!body) return; - SourceLocation locStart = varDecl->getLocStart(); + SourceLocation locStart = getLocStart(varDecl); locStart = sm().getExpansionLoc(locStart); - auto declRefs = HierarchyUtils::getStatements<DeclRefExpr>(body, &sm(), locStart); + auto declRefs = clazy::getStatements<DeclRefExpr>(body, &sm(), locStart); auto pred = [varDecl] (DeclRefExpr *declRef) { return declRef->getDecl() == varDecl; }; - if (!clazy_std::any_of(declRefs, pred)) - emitWarning(locStart, "unused " + StringUtils::simpleTypeName(varDecl->getType(), lo())); + if (!clazy::any_of(declRefs, pred)) + emitWarning(locStart, "unused " + clazy::simpleTypeName(varDecl->getType(), lo())); } - - -REGISTER_CHECK("unused-non-trivial-variable", UnusedNonTrivialVariable, CheckLevel0) |