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 }