File indexing completed on 2024-04-14 05:32:08

0001 /*
0002     SPDX-FileCopyrightText: 2016 Sergio Martins <smartins@kde.org>
0003 
0004     SPDX-License-Identifier: LGPL-2.0-or-later
0005 */
0006 
0007 #include "TemplateUtils.h"
0008 #include "StringUtils.h"
0009 
0010 #include <clang/AST/Decl.h>
0011 #include <clang/AST/DeclCXX.h>
0012 #include <clang/AST/DeclTemplate.h>
0013 #include <clang/AST/TemplateBase.h>
0014 #include <clang/AST/Type.h>
0015 #include <clang/Basic/LLVM.h>
0016 #include <llvm/Support/Casting.h>
0017 
0018 namespace clang
0019 {
0020 class LangOptions;
0021 } // namespace clang
0022 
0023 using namespace clang;
0024 
0025 static std::vector<QualType> typesFromTemplateArguments(const TemplateArgumentList *templateArgs)
0026 {
0027     std::vector<QualType> result;
0028     const int numArgs = templateArgs->size();
0029     result.reserve(numArgs);
0030     for (int i = 0; i < numArgs; ++i) {
0031         const TemplateArgument &arg = templateArgs->get(i);
0032         if (arg.getKind() == TemplateArgument::Type) {
0033             result.push_back(arg.getAsType());
0034         }
0035     }
0036 
0037     return result;
0038 }
0039 
0040 std::vector<QualType> clazy::getTemplateArgumentsTypes(CXXMethodDecl *method)
0041 {
0042     if (!method) {
0043         return {};
0044     }
0045 
0046     FunctionTemplateSpecializationInfo *specializationInfo = method->getTemplateSpecializationInfo();
0047     if (!specializationInfo || !specializationInfo->TemplateArguments) {
0048         return {};
0049     }
0050 
0051     return typesFromTemplateArguments(specializationInfo->TemplateArguments);
0052 }
0053 
0054 std::vector<clang::QualType> clazy::getTemplateArgumentsTypes(CXXRecordDecl *record)
0055 {
0056     if (!record) {
0057         return {};
0058     }
0059 
0060     auto *templateDecl = dyn_cast<ClassTemplateSpecializationDecl>(record);
0061     if (!templateDecl) {
0062         return {};
0063     }
0064 
0065     return typesFromTemplateArguments(&(templateDecl->getTemplateInstantiationArgs()));
0066 }
0067 
0068 ClassTemplateSpecializationDecl *clazy::templateDecl(Decl *decl)
0069 {
0070     if (isa<ClassTemplateSpecializationDecl>(decl)) {
0071         return dyn_cast<ClassTemplateSpecializationDecl>(decl);
0072     }
0073 
0074     auto *varDecl = dyn_cast<VarDecl>(decl);
0075     if (!varDecl) {
0076         return nullptr;
0077     }
0078     QualType qt = varDecl->getType();
0079     const Type *t = qt.getTypePtrOrNull();
0080     if (!t) {
0081         return nullptr;
0082     }
0083     CXXRecordDecl *classDecl = t->getAsCXXRecordDecl();
0084     if (!classDecl) {
0085         return nullptr;
0086     }
0087     return dyn_cast<ClassTemplateSpecializationDecl>(classDecl);
0088 }
0089 
0090 std::string clazy::getTemplateArgumentTypeStr(ClassTemplateSpecializationDecl *specialization, unsigned int index, const LangOptions &lo, bool recordOnly)
0091 {
0092     if (!specialization) {
0093         return {};
0094     }
0095 
0096     const auto &args = specialization->getTemplateArgs();
0097     if (args.size() <= index) {
0098         return {};
0099     }
0100 
0101     QualType qt = args[index].getAsType();
0102     if (recordOnly) {
0103         const Type *t = qt.getTypePtrOrNull();
0104         if (!t || !t->getAsCXXRecordDecl()) {
0105             return {};
0106         }
0107     }
0108 
0109     return clazy::simpleTypeName(args[index].getAsType(), lo);
0110 }
0111 
0112 clang::QualType clazy::getTemplateArgumentType(ClassTemplateSpecializationDecl *specialization, unsigned int index)
0113 {
0114     if (!specialization) {
0115         return {};
0116     }
0117 
0118     const auto &args = specialization->getTemplateArgs();
0119     if (args.size() <= index) {
0120         return {};
0121     }
0122 
0123     return args[index].getAsType();
0124 }