File indexing completed on 2024-05-12 05:41:01

0001 /*
0002     SPDX-FileCopyrightText: 2016 Sergio Martins <smartins@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "container-inside-loop.h"
0008 #include "ClazyContext.h"
0009 #include "LoopUtils.h"
0010 #include "StmtBodyRange.h"
0011 #include "StringUtils.h"
0012 #include "Utils.h"
0013 #include "clazy_stl.h"
0014 
0015 #include <clang/AST/Decl.h>
0016 #include <clang/AST/ExprCXX.h>
0017 #include <clang/AST/ParentMap.h>
0018 #include <clang/AST/Stmt.h>
0019 #include <clang/Basic/LLVM.h>
0020 #include <llvm/Support/Casting.h>
0021 
0022 namespace clang
0023 {
0024 class CXXConstructorDecl;
0025 } // namespace clang
0026 
0027 using namespace clang;
0028 
0029 ContainerInsideLoop::ContainerInsideLoop(const std::string &name, ClazyContext *context)
0030     : CheckBase(name, context, Option_CanIgnoreIncludes)
0031 {
0032 }
0033 
0034 void ContainerInsideLoop::VisitStmt(clang::Stmt *stmt)
0035 {
0036     auto *ctorExpr = dyn_cast<CXXConstructExpr>(stmt);
0037     if (!ctorExpr) {
0038         return;
0039     }
0040 
0041     CXXConstructorDecl *ctor = ctorExpr->getConstructor();
0042     if (!ctor || !clazy::equalsAny(clazy::classNameFor(ctor), {"QVector", "std::vector", "QList"})) {
0043         return;
0044     }
0045 
0046     auto *declStm = dyn_cast_or_null<DeclStmt>(m_context->parentMap->getParent(stmt));
0047     if (!declStm || !declStm->isSingleDecl()) {
0048         return;
0049     }
0050 
0051     Stmt *loopStmt = clazy::isInLoop(m_context->parentMap, stmt);
0052     if (!loopStmt) {
0053         return;
0054     }
0055 
0056     auto *varDecl = dyn_cast<VarDecl>(declStm->getSingleDecl());
0057     if (!varDecl || Utils::isInitializedExternally(varDecl)) {
0058         return;
0059     }
0060 
0061     if (Utils::isPassedToFunction(StmtBodyRange(loopStmt), varDecl, true)) {
0062         return;
0063     }
0064 
0065     emitWarning(stmt->getBeginLoc(), "container inside loop causes unneeded allocations");
0066 }