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 }