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 }