File indexing completed on 2024-04-21 05:38:47

0001 /*
0002     SPDX-FileCopyrightText: 2015 Klarälvdalens Datakonsult AB a KDAB Group company info@kdab.com
0003     SPDX-FileContributor: SĂ©rgio Martins <sergio.martins@kdab.com>
0004 
0005     SPDX-FileCopyrightText: 2015 Sergio Martins <smartins@kde.org>
0006 
0007     SPDX-License-Identifier: LGPL-2.0-or-later
0008 */
0009 
0010 #ifndef FUNCTION_UTILS_H
0011 #define FUNCTION_UTILS_H
0012 
0013 // Contains utility functions regarding functions and methods
0014 
0015 #include "HierarchyUtils.h"
0016 #include "StringUtils.h"
0017 #include "Utils.h"
0018 
0019 #include <clang/AST/Decl.h>
0020 
0021 namespace clazy
0022 {
0023 inline clang::ValueDecl *valueDeclForCallArgument(clang::CallExpr *call, unsigned int argIndex)
0024 {
0025     if (!call || call->getNumArgs() <= argIndex) {
0026         return nullptr;
0027     }
0028 
0029     clang::Expr *firstArg = call->getArg(argIndex);
0030     auto *declRef =
0031         llvm::isa<clang::DeclRefExpr>(firstArg) ? llvm::cast<clang::DeclRefExpr>(firstArg) : clazy::getFirstChildOfType2<clang::DeclRefExpr>(firstArg);
0032     if (!declRef) {
0033         return nullptr;
0034     }
0035 
0036     return declRef->getDecl();
0037 }
0038 
0039 inline bool parametersMatch(const clang::FunctionDecl *f1, const clang::FunctionDecl *f2)
0040 {
0041     if (!f1 || !f2) {
0042         return false;
0043     }
0044 
0045     auto params1 = f1->parameters();
0046     auto params2 = f2->parameters();
0047 
0048     if (params1.size() != params2.size()) {
0049         return false;
0050     }
0051 
0052     for (int i = 0, e = params1.size(); i < e; ++i) {
0053         clang::ParmVarDecl *p1 = params1[i];
0054         clang::ParmVarDecl *p2 = params2[i];
0055 
0056         if (p1->getType() != p2->getType()) {
0057             return false;
0058         }
0059     }
0060 
0061     return true;
0062 }
0063 
0064 /**
0065  * Returns true if a class contains a method with a specific signature.
0066  * (method->getParent() doesn't need to equal record)
0067  */
0068 inline bool classImplementsMethod(const clang::CXXRecordDecl *record, const clang::CXXMethodDecl *method)
0069 {
0070     if (!method->getDeclName().isIdentifier()) {
0071         return false;
0072     }
0073 
0074     llvm::StringRef methodName = clazy::name(method);
0075     for (auto *m : record->methods()) {
0076 #if LLVM_VERSION_MAJOR >= 18
0077         if (!m->isPureVirtual() && clazy::name(m) == methodName && parametersMatch(m, method)) {
0078 #else
0079         if (!m->isPure() && clazy::name(m) == methodName && parametersMatch(m, method)) {
0080 #endif
0081             return true;
0082         }
0083     }
0084 
0085     return false;
0086 }
0087 
0088 }
0089 #endif