aboutsummaryrefslogtreecommitdiffstats
path: root/src/checks/level0/unused-non-trivial-variable.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/checks/level0/unused-non-trivial-variable.cpp')
-rw-r--r--src/checks/level0/unused-non-trivial-variable.cpp112
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)