File indexing completed on 2024-04-28 05:38:35
0001 /* 0002 SPDX-FileCopyrightText: 2015 Klarälvdalens Datakonsult AB a KDAB Group company info@kdab.com 0003 SPDX-FileContributor: Sérgio Martins <sergio.martins@kdab.com> 0004 0005 SPDX-FileCopyrightText: 2015 Sergio Martins <smartins@kde.org> 0006 0007 SPDX-License-Identifier: LGPL-2.0-or-later 0008 */ 0009 0010 #include "requiredresults.h" 0011 #include "Utils.h" 0012 0013 #include <clang/AST/DeclCXX.h> 0014 #include <clang/AST/Expr.h> 0015 #include <clang/AST/ExprCXX.h> 0016 0017 using namespace clang; 0018 0019 RequiredResults::RequiredResults(const std::string &name, ClazyContext *context) 0020 : CheckBase(name, context) 0021 { 0022 } 0023 0024 bool RequiredResults::shouldIgnoreMethod(const StringRef &qualifiedName) 0025 { 0026 static const std::vector<StringRef> files = { 0027 "QDir::mkdir", 0028 "QDir::rmdir", 0029 "QDir::mkpath", 0030 "QDBusConnection::send", 0031 0032 "QRegExp::indexIn", 0033 "QRegExp::exactMatch", 0034 "QQmlProperty::write", 0035 "QQmlProperty::reset", 0036 "QWidget::winId", 0037 "QtWaylandClient::QWaylandEglWindow::contentFBO", 0038 "ProString::updatedHash", 0039 0040 // kdepim 0041 "KCalCore::Incidence::recurrence", 0042 "KCalCore::RecurrenceRule::Private::buildCache", 0043 "KAlarmCal::KAEvent::updateKCalEvent", 0044 "Akonadi::Server::Collection::clearMimeTypes", 0045 "Akonadi::Server::Collection::addMimeType", 0046 "Akonadi::Server::PimItem::addFlag", 0047 "Akonadi::Server::PimItem::addTag", 0048 0049 // kf5 libs 0050 "KateVi::Command::execute", 0051 "KArchiveDirectory::copyTo", 0052 "KBookmarkManager::saveAs", 0053 "KBookmarkManager::save", 0054 "KLineEditPrivate::copySqueezedText", 0055 "KJS::UString::Rep::hash", 0056 "KCModuleProxy::realModule", 0057 "KCategorizedView::visualRect", 0058 "KateLineLayout::textLine", 0059 "DOM::HTMLCollectionImpl::firstItem", 0060 "DOM::HTMLCollectionImpl::nextItem", 0061 "DOM::HTMLCollectionImpl::firstItem", 0062 "ImapResourceBase::settings", 0063 }; 0064 0065 return clazy::contains(files, qualifiedName); 0066 } 0067 0068 void RequiredResults::VisitStmt(clang::Stmt *stm) 0069 { 0070 auto compound = dyn_cast<CompoundStmt>(stm); 0071 if (!compound) 0072 return; 0073 0074 for (auto child : compound->children()) { 0075 auto callExpr = dyn_cast<CXXMemberCallExpr>(child); 0076 if (!callExpr) 0077 continue; 0078 0079 CXXMethodDecl *methodDecl = callExpr->getMethodDecl(); 0080 if (!methodDecl || !methodDecl->isConst()) 0081 continue; 0082 0083 std::string methodName = methodDecl->getQualifiedNameAsString(); 0084 if (shouldIgnoreMethod(methodName)) // Filter out some false positives 0085 continue; 0086 0087 QualType qt = methodDecl->getReturnType(); 0088 const Type *type = qt.getTypePtrOrNull(); 0089 if (!type || type->isVoidType()) 0090 continue; 0091 0092 // Bail-out if any parameter is a non-const-ref or pointer bool bailout = false; 0093 bool bailout = false; 0094 for (auto paramVarDecl : Utils::functionParameters(methodDecl)) { 0095 QualType qt = paramVarDecl->getType(); 0096 const Type *type = qt.getTypePtrOrNull(); 0097 if (!type || type->isPointerType()) { 0098 bailout = true; 0099 break; 0100 } 0101 0102 // qt.isConstQualified() not working !? TODO: Replace this string parsing when I figure it out 0103 if (type->isReferenceType() && !clazy::contains(qt.getAsString(), "const ")) { 0104 bailout = true; 0105 break; 0106 } 0107 } 0108 0109 if (!bailout) { 0110 std::string error = std::string("Unused result of const member (") + methodName + ')'; 0111 emitWarning(callExpr->getBeginLoc(), error); 0112 } 0113 } 0114 }