File indexing completed on 2024-05-12 17:13:19

0001 /*
0002     This file is part of the clazy static checker.
0003 
0004     Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
0005     Author: SĂ©rgio Martins <sergio.martins@kdab.com>
0006 
0007     Copyright (C) 2015 Sergio Martins <smartins@kde.org>
0008 
0009     This library is free software; you can redistribute it and/or
0010     modify it under the terms of the GNU Library General Public
0011     License as published by the Free Software Foundation; either
0012     version 2 of the License, or (at your option) any later version.
0013 
0014     This library is distributed in the hope that it will be useful,
0015     but WITHOUT ANY WARRANTY; without even the implied warranty of
0016     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0017     Library General Public License for more details.
0018 
0019     You should have received a copy of the GNU Library General Public License
0020     along with this library; see the file COPYING.LIB.  If not, write to
0021     the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0022     Boston, MA 02110-1301, USA.
0023 */
0024 
0025 #include "requiredresults.h"
0026 #include "Utils.h"
0027 
0028 #include <clang/AST/DeclCXX.h>
0029 #include <clang/AST/Expr.h>
0030 #include <clang/AST/ExprCXX.h>
0031 
0032 using namespace clang;
0033 
0034 RequiredResults::RequiredResults(const std::string &name, ClazyContext *context)
0035     : CheckBase(name, context)
0036 {
0037 }
0038 
0039 bool RequiredResults::shouldIgnoreMethod(const StringRef &qualifiedName)
0040 {
0041     static const std::vector<StringRef> files = {
0042         "QDir::mkdir",
0043         "QDir::rmdir",
0044         "QDir::mkpath",
0045         "QDBusConnection::send",
0046 
0047         "QRegExp::indexIn",
0048         "QRegExp::exactMatch",
0049         "QQmlProperty::write",
0050         "QQmlProperty::reset",
0051         "QWidget::winId",
0052         "QtWaylandClient::QWaylandEglWindow::contentFBO",
0053         "ProString::updatedHash",
0054 
0055         // kdepim
0056         "KCalCore::Incidence::recurrence",
0057         "KCalCore::RecurrenceRule::Private::buildCache",
0058         "KAlarmCal::KAEvent::updateKCalEvent",
0059         "Akonadi::Server::Collection::clearMimeTypes",
0060         "Akonadi::Server::Collection::addMimeType",
0061         "Akonadi::Server::PimItem::addFlag",
0062         "Akonadi::Server::PimItem::addTag",
0063 
0064         // kf5 libs
0065         "KateVi::Command::execute",
0066         "KArchiveDirectory::copyTo",
0067         "KBookmarkManager::saveAs",
0068         "KBookmarkManager::save",
0069         "KLineEditPrivate::copySqueezedText",
0070         "KJS::UString::Rep::hash",
0071         "KCModuleProxy::realModule",
0072         "KCategorizedView::visualRect",
0073         "KateLineLayout::textLine",
0074         "DOM::HTMLCollectionImpl::firstItem",
0075         "DOM::HTMLCollectionImpl::nextItem",
0076         "DOM::HTMLCollectionImpl::firstItem",
0077         "ImapResourceBase::settings"
0078     };
0079 
0080     return clazy::contains(files, qualifiedName);
0081 }
0082 
0083 void RequiredResults::VisitStmt(clang::Stmt *stm)
0084 {
0085     auto compound = dyn_cast<CompoundStmt>(stm);
0086     if (!compound)
0087         return;
0088 
0089     for (auto child : compound->children()) {
0090         auto callExpr = dyn_cast<CXXMemberCallExpr>(child);
0091         if (!callExpr)
0092             continue;
0093 
0094         CXXMethodDecl *methodDecl = callExpr->getMethodDecl();
0095         if (!methodDecl || !methodDecl->isConst())
0096             continue;
0097 
0098         std::string methodName = methodDecl->getQualifiedNameAsString();
0099         if (shouldIgnoreMethod(StringRef(methodName.c_str()))) // Filter out some false positives
0100             continue;
0101 
0102         QualType qt = methodDecl->getReturnType();
0103         const Type *type = qt.getTypePtrOrNull();
0104         if (!type || type->isVoidType())
0105             continue;
0106 
0107         // Bail-out if any parameter is a non-const-ref or pointer bool bailout = false;
0108         bool bailout = false;
0109         for (auto paramVarDecl : Utils::functionParameters(methodDecl)) {
0110             QualType qt = paramVarDecl->getType();
0111             const Type *type = qt.getTypePtrOrNull();
0112             if (!type || type->isPointerType()) {
0113                 bailout = true;
0114                 break;
0115             }
0116 
0117             // qt.isConstQualified() not working !? TODO: Replace this string parsing when I figure it out
0118             if (type->isReferenceType() && !clazy::contains(qt.getAsString(), "const ")) {
0119                 bailout = true;
0120                 break;
0121             }
0122         }
0123 
0124         if (!bailout) {
0125             std::string error = std::string("Unused result of const member (") + methodName + ')';
0126             emitWarning(clazy::getLocStart(callExpr), error.c_str());
0127         }
0128     }
0129 }