File indexing completed on 2024-05-12 05:40:57

0001 /*
0002     SPDX-FileCopyrightText: 2016 Sergio Martins <smartins@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "qstring-insensitive-allocation.h"
0008 #include "StringUtils.h"
0009 #include "Utils.h"
0010 #include "clazy_stl.h"
0011 
0012 #include <clang/AST/Expr.h>
0013 #include <clang/AST/Stmt.h>
0014 #include <clang/Basic/LLVM.h>
0015 #include <llvm/Support/Casting.h>
0016 
0017 #include <vector>
0018 
0019 using namespace clang;
0020 
0021 QStringInsensitiveAllocation::QStringInsensitiveAllocation(const std::string &name, ClazyContext *context)
0022     : CheckBase(name, context, Option_CanIgnoreIncludes)
0023 {
0024 }
0025 
0026 static bool isInterestingCall1(CallExpr *call)
0027 {
0028     FunctionDecl *func = call->getDirectCallee();
0029     if (!func) {
0030         return false;
0031     }
0032 
0033     static const std::vector<std::string> methods{"QString::toUpper", "QString::toLower"};
0034     return clazy::contains(methods, clazy::qualifiedMethodName(func));
0035 }
0036 
0037 static bool isInterestingCall2(CallExpr *call)
0038 {
0039     FunctionDecl *func = call->getDirectCallee();
0040     if (!func) {
0041         return false;
0042     }
0043 
0044     static const std::vector<std::string> methods{"QString::endsWith", "QString::startsWith", "QString::contains", "QString::compare"};
0045     return clazy::contains(methods, clazy::qualifiedMethodName(func));
0046 }
0047 
0048 void QStringInsensitiveAllocation::VisitStmt(clang::Stmt *stmt)
0049 {
0050     std::vector<CallExpr *> calls = Utils::callListForChain(dyn_cast<CallExpr>(stmt));
0051     if (calls.size() < 2) {
0052         return;
0053     }
0054 
0055     CallExpr *call1 = calls[calls.size() - 1];
0056     CallExpr *call2 = calls[calls.size() - 2];
0057 
0058     if (!isInterestingCall1(call1) || !isInterestingCall2(call2)) {
0059         return;
0060     }
0061 
0062     emitWarning(stmt->getBeginLoc(), "unneeded allocation");
0063 }