File indexing completed on 2024-05-12 05:40:57
0001 /* 0002 SPDX-FileCopyrightText: 2015 Sergio Martins <smartins@kde.org> 0003 SPDX-FileCopyrightText: 2015 Mathias Hasselmann <mathias.hasselmann@kdab.com> 0004 0005 SPDX-License-Identifier: LGPL-2.0-or-later 0006 */ 0007 0008 #include "auto-unexpected-qstringbuilder.h" 0009 #include "FixItUtils.h" 0010 #include "StringUtils.h" 0011 #include "TypeUtils.h" 0012 0013 #include <clang/AST/Decl.h> 0014 #include <clang/AST/DeclBase.h> 0015 #include <clang/AST/DeclCXX.h> 0016 #include <clang/AST/ExprCXX.h> 0017 #include <clang/AST/Stmt.h> 0018 #include <clang/AST/Type.h> 0019 #include <clang/Basic/Diagnostic.h> 0020 #include <clang/Basic/LLVM.h> 0021 #include <clang/Basic/SourceLocation.h> 0022 #include <llvm/ADT/StringRef.h> 0023 #include <llvm/Support/Casting.h> 0024 0025 #include <vector> 0026 0027 class ClazyContext; 0028 0029 using namespace clang; 0030 0031 static bool isQStringBuilder(QualType t) 0032 { 0033 CXXRecordDecl *record = clazy::typeAsRecord(t); 0034 return record && clazy::name(record) == "QStringBuilder"; 0035 } 0036 0037 AutoUnexpectedQStringBuilder::AutoUnexpectedQStringBuilder(const std::string &name, ClazyContext *context) 0038 : CheckBase(name, context, Option_CanIgnoreIncludes) 0039 { 0040 } 0041 0042 void AutoUnexpectedQStringBuilder::VisitDecl(Decl *decl) 0043 { 0044 auto *varDecl = dyn_cast<VarDecl>(decl); 0045 if (!varDecl) { 0046 return; 0047 } 0048 0049 QualType qualtype = varDecl->getType(); 0050 const Type *type = qualtype.getTypePtrOrNull(); 0051 if (!type || !type->isRecordType() || !dyn_cast<AutoType>(type) || !isQStringBuilder(qualtype)) { 0052 return; 0053 } 0054 0055 std::string replacement = "QString " + clazy::name(varDecl).str(); 0056 0057 if (qualtype.isConstQualified()) { 0058 replacement = "const " + replacement; 0059 } 0060 0061 SourceLocation start = varDecl->getBeginLoc(); 0062 SourceLocation end = varDecl->getLocation(); 0063 std::vector<FixItHint> fixits; 0064 fixits.push_back(clazy::createReplacement({start, end}, replacement)); 0065 0066 emitWarning(decl->getBeginLoc(), "auto deduced to be QStringBuilder instead of QString. Possible crash.", fixits); 0067 } 0068 0069 void AutoUnexpectedQStringBuilder::VisitStmt(Stmt *stmt) 0070 { 0071 auto *lambda = dyn_cast<LambdaExpr>(stmt); 0072 if (!lambda) { 0073 return; 0074 } 0075 0076 CXXMethodDecl *method = lambda->getCallOperator(); 0077 if (!method || !isQStringBuilder(method->getReturnType())) { 0078 return; 0079 } 0080 0081 emitWarning(stmt->getBeginLoc(), "lambda return type deduced to be QStringBuilder instead of QString. Possible crash."); 0082 }