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 }