File indexing completed on 2024-05-12 05:40:56

0001 /*
0002     SPDX-FileCopyrightText: 2017 Sergio Martins <smartins@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "lambda-unique-connection.h"
0008 #include "HierarchyUtils.h"
0009 #include "QtUtils.h"
0010 
0011 #include <clang/AST/Decl.h>
0012 #include <clang/AST/DeclTemplate.h>
0013 #include <clang/AST/Expr.h>
0014 #include <clang/AST/Stmt.h>
0015 #include <clang/Basic/LLVM.h>
0016 #include <llvm/ADT/StringRef.h>
0017 #include <llvm/Support/Casting.h>
0018 
0019 #include <vector>
0020 
0021 class ClazyContext;
0022 namespace clang
0023 {
0024 class CXXMethodDecl;
0025 } // namespace clang
0026 
0027 using namespace clang;
0028 
0029 LambdaUniqueConnection::LambdaUniqueConnection(const std::string &name, ClazyContext *context)
0030     : CheckBase(name, context, Option_CanIgnoreIncludes)
0031 {
0032 }
0033 
0034 void LambdaUniqueConnection::VisitStmt(clang::Stmt *stmt)
0035 {
0036     auto *call = dyn_cast<CallExpr>(stmt);
0037     if (!call) {
0038         return;
0039     }
0040 
0041     // We want this signature:
0042     // connect(const QObject *sender, PointerToMemberFunction signal, const QObject *context, Functor functor, Qt::ConnectionType type)
0043 
0044     FunctionDecl *func = call->getDirectCallee();
0045     if (!func || func->getNumParams() != 5 || !func->isTemplateInstantiation() || !clazy::isConnect(func) || !clazy::connectHasPMFStyle(func)) {
0046         return;
0047     }
0048 
0049     Expr *typeArg = call->getArg(4); // The type
0050 
0051     std::vector<DeclRefExpr *> result;
0052     clazy::getChilds(typeArg, result);
0053 
0054     bool found = false;
0055     for (auto *declRef : result) {
0056         if (auto *enumConstant = dyn_cast<EnumConstantDecl>(declRef->getDecl())) {
0057             if (clazy::name(enumConstant) == "UniqueConnection") {
0058                 found = true;
0059                 break;
0060             }
0061         }
0062     }
0063 
0064     if (!found) {
0065         return;
0066     }
0067 
0068     FunctionTemplateSpecializationInfo *tsi = func->getTemplateSpecializationInfo();
0069     if (!tsi) {
0070         return;
0071     }
0072     FunctionTemplateDecl *temp = tsi->getTemplate();
0073     const TemplateParameterList *tempParams = temp->getTemplateParameters();
0074     if (tempParams->size() != 2) {
0075         return;
0076     }
0077 
0078     CXXMethodDecl *method = clazy::pmfFromConnect(call, 3);
0079     if (method) {
0080         // How else to detect if it's the right overload ? It's all templated stuff with the same
0081         // names for all the template arguments
0082         return;
0083     }
0084 
0085     emitWarning(typeArg, "UniqueConnection is not supported with non-member functions");
0086 }