File indexing completed on 2024-05-12 05:40:59
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 "range-loop-reference.h" 0011 #include "ClazyContext.h" 0012 #include "FixItUtils.h" 0013 #include "PreProcessorVisitor.h" 0014 #include "QtUtils.h" 0015 #include "StringUtils.h" 0016 #include "TypeUtils.h" 0017 0018 #include <clang/AST/Expr.h> 0019 #include <clang/AST/Stmt.h> 0020 #include <clang/AST/StmtCXX.h> 0021 #include <clang/AST/Type.h> 0022 #include <llvm/Support/Casting.h> 0023 0024 class ClazyContext; 0025 0026 using namespace clang; 0027 0028 RangeLoopReference::RangeLoopReference(const std::string &name, ClazyContext *context) 0029 : CheckBase(name, context, Option_CanIgnoreIncludes) 0030 { 0031 context->enablePreprocessorVisitor(); 0032 } 0033 0034 void RangeLoopReference::VisitStmt(clang::Stmt *stmt) 0035 { 0036 if (auto *rangeLoop = dyn_cast<CXXForRangeStmt>(stmt)) { 0037 processForRangeLoop(rangeLoop); 0038 } 0039 } 0040 0041 void RangeLoopReference::processForRangeLoop(CXXForRangeStmt *rangeLoop) 0042 { 0043 Expr *containerExpr = rangeLoop->getRangeInit(); 0044 if (!containerExpr) { 0045 return; 0046 } 0047 0048 QualType qt = containerExpr->getType(); 0049 const Type *t = qt.getTypePtrOrNull(); 0050 if (!t || !t->isRecordType()) { 0051 return; 0052 } 0053 0054 clazy::QualTypeClassification classif; 0055 auto *varDecl = rangeLoop->getLoopVariable(); 0056 bool success = varDecl && clazy::classifyQualType(m_context, varDecl->getType(), varDecl, /*by-ref*/ classif, rangeLoop); 0057 if (!success) { 0058 return; 0059 } 0060 0061 if (classif.passNonTriviallyCopyableByConstRef) { 0062 std::string msg; 0063 const std::string paramStr = clazy::simpleTypeName(varDecl->getType(), lo()); 0064 msg = "Missing reference in range-for with non trivial type (" + paramStr + ')'; 0065 0066 std::vector<FixItHint> fixits; 0067 const bool isConst = varDecl->getType().isConstQualified(); 0068 0069 if (!isConst) { 0070 SourceLocation start = varDecl->getBeginLoc(); 0071 fixits.push_back(clazy::createInsertion(start, "const ")); 0072 } 0073 0074 SourceLocation end = varDecl->getLocation(); 0075 fixits.push_back(clazy::createInsertion(end, "&")); 0076 0077 // We ignore classif.passSmallTrivialByValue because it doesn't matter, the compiler is able 0078 // to optimize it, generating the same assembly, regardless of pass by value. 0079 emitWarning(varDecl->getBeginLoc(), msg, fixits); 0080 } 0081 }