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

0001 /*
0002     SPDX-FileCopyrightText: 2017 Sergio Martins <smartins@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "virtual-signal.h"
0008 #include "AccessSpecifierManager.h"
0009 #include "ClazyContext.h"
0010 #include "QtUtils.h"
0011 
0012 #include <clang/AST/DeclCXX.h>
0013 #include <clang/Basic/LLVM.h>
0014 #include <llvm/Support/Casting.h>
0015 
0016 namespace clang
0017 {
0018 class Decl;
0019 } // namespace clang
0020 
0021 using namespace clang;
0022 
0023 VirtualSignal::VirtualSignal(const std::string &name, ClazyContext *context)
0024     : CheckBase(name, context)
0025 {
0026     context->enableAccessSpecifierManager();
0027 }
0028 
0029 void VirtualSignal::VisitDecl(Decl *stmt)
0030 {
0031     auto *method = dyn_cast<CXXMethodDecl>(stmt);
0032     if (!method || !method->isVirtual()) {
0033         return;
0034     }
0035 
0036     AccessSpecifierManager *accessSpecifierManager = m_context->accessSpecifierManager;
0037     if (!accessSpecifierManager) {
0038         return;
0039     }
0040 
0041     QtAccessSpecifierType qst = accessSpecifierManager->qtAccessSpecifierType(method);
0042     if (qst == QtAccessSpecifier_Signal) {
0043         for (const auto *m : method->overridden_methods()) {
0044             if (const auto *baseClass = m->getParent()) {
0045                 if (!clazy::isQObject(baseClass)) {
0046                     // It's possible that the signal is overriding a method from a non-QObject base class
0047                     // if the derived class inherits both QObject and some other interface.
0048                     return;
0049                 }
0050             }
0051         }
0052 
0053         emitWarning(method, "signal is virtual");
0054     }
0055 }