File indexing completed on 2024-05-12 05:40:58
0001 /* 0002 SPDX-FileCopyrightText: 2017 Sergio Martins <smartins@kde.org> 0003 0004 SPDX-License-Identifier: LGPL-2.0-or-later 0005 */ 0006 0007 #include "overridden-signal.h" 0008 #include "AccessSpecifierManager.h" 0009 #include "ClazyContext.h" 0010 #include "FunctionUtils.h" 0011 #include "QtUtils.h" 0012 #include "StringUtils.h" 0013 0014 #include <clang/AST/DeclCXX.h> 0015 #include <clang/Basic/LLVM.h> 0016 #include <llvm/ADT/StringRef.h> 0017 #include <llvm/Support/Casting.h> 0018 0019 namespace clang 0020 { 0021 class Decl; 0022 } // namespace clang 0023 0024 using namespace clang; 0025 0026 OverriddenSignal::OverriddenSignal(const std::string &name, ClazyContext *context) 0027 : CheckBase(name, context, Option_CanIgnoreIncludes) 0028 { 0029 context->enableAccessSpecifierManager(); 0030 } 0031 0032 void OverriddenSignal::VisitDecl(clang::Decl *decl) 0033 { 0034 AccessSpecifierManager *accessSpecifierManager = m_context->accessSpecifierManager; 0035 auto *method = dyn_cast<CXXMethodDecl>(decl); 0036 if (!accessSpecifierManager || !method) { 0037 return; 0038 } 0039 0040 if (method->isThisDeclarationADefinition() && !method->hasInlineBody()) { 0041 return; 0042 } 0043 0044 CXXRecordDecl *record = method->getParent(); 0045 CXXRecordDecl *baseClass = clazy::getQObjectBaseClass(record); 0046 if (!baseClass) { 0047 return; 0048 } 0049 0050 const bool methodIsSignal = accessSpecifierManager->qtAccessSpecifierType(method) == QtAccessSpecifier_Signal; 0051 const StringRef methodName = clazy::name(method); 0052 0053 std::string warningMsg; 0054 while (baseClass) { 0055 for (auto *baseMethod : baseClass->methods()) { 0056 if (clazy::name(baseMethod) == methodName) { 0057 if (!clazy::parametersMatch(method, baseMethod)) { // overloading is permitted. 0058 continue; 0059 } 0060 0061 const bool baseMethodIsSignal = accessSpecifierManager->qtAccessSpecifierType(baseMethod) == QtAccessSpecifier_Signal; 0062 0063 if (methodIsSignal && baseMethodIsSignal) { 0064 warningMsg = "Overriding signal with signal: " + method->getQualifiedNameAsString(); 0065 } else if (methodIsSignal && !baseMethodIsSignal) { 0066 warningMsg = "Overriding non-signal with signal: " + method->getQualifiedNameAsString(); 0067 } else if (!methodIsSignal && baseMethodIsSignal) { 0068 warningMsg = "Overriding signal with non-signal: " + method->getQualifiedNameAsString(); 0069 } 0070 0071 if (!warningMsg.empty()) { 0072 emitWarning(decl, warningMsg); 0073 return; 0074 } 0075 } 0076 } 0077 0078 baseClass = clazy::getQObjectBaseClass(baseClass); 0079 } 0080 }