brintos

brintos / llvm-project-archived public Read only

0
0
Text · 5.7 KiB · 605f3ef Raw
180 lines · cpp
1//===- CIndexCXX.cpp - Clang-C Source Indexing Library --------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This file implements the libclang support for C++ cursors.10//11//===----------------------------------------------------------------------===//12 13#include "CIndexer.h"14#include "CXCursor.h"15#include "CXType.h"16#include "clang/AST/DeclCXX.h"17#include "clang/AST/DeclTemplate.h"18 19using namespace clang;20using namespace clang::cxcursor;21 22unsigned clang_isVirtualBase(CXCursor C) {23  if (C.kind != CXCursor_CXXBaseSpecifier)24    return 0;25  26  const CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);27  return B->isVirtual();28}29 30unsigned clang_visitCXXBaseClasses(CXType PT, CXFieldVisitor visitor,31                                   CXClientData client_data) {32  CXCursor PC = clang_getTypeDeclaration(PT);33  if (clang_isInvalid(PC.kind))34    return false;35  const CXXRecordDecl *RD =36      dyn_cast_if_present<CXXRecordDecl>(cxcursor::getCursorDecl(PC));37  if (!RD || RD->isInvalidDecl())38    return false;39  RD = RD->getDefinition();40  if (!RD || RD->isInvalidDecl())41    return false;42 43  for (auto &Base : RD->bases()) {44    // Callback to the client.45    switch (46        visitor(cxcursor::MakeCursorCXXBaseSpecifier(&Base, getCursorTU(PC)),47                client_data)) {48    case CXVisit_Break:49      return true;50    case CXVisit_Continue:51      break;52    }53  }54  return true;55}56 57unsigned clang_visitCXXMethods(CXType PT, CXFieldVisitor visitor,58                               CXClientData client_data) {59  CXCursor PC = clang_getTypeDeclaration(PT);60  if (clang_isInvalid(PC.kind))61    return false;62  const auto *RD =63      dyn_cast_if_present<CXXRecordDecl>(cxcursor::getCursorDecl(PC));64  if (!RD || RD->isInvalidDecl())65    return false;66  RD = RD->getDefinition();67  if (!RD || RD->isInvalidDecl())68    return false;69 70  for (const auto *Method : RD->methods()) {71    // Callback to the client.72    switch (73        visitor(cxcursor::MakeCXCursor(Method, getCursorTU(PC)), client_data)) {74    case CXVisit_Break:75      return true;76    case CXVisit_Continue:77      break;78    }79  }80  return true;81}82 83enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) {84  AccessSpecifier spec = AS_none;85 86  if (C.kind == CXCursor_CXXAccessSpecifier || clang_isDeclaration(C.kind))87    spec = getCursorDecl(C)->getAccess();88  else if (C.kind == CXCursor_CXXBaseSpecifier)89    spec = getCursorCXXBaseSpecifier(C)->getAccessSpecifier();90  else91    return CX_CXXInvalidAccessSpecifier;92  93  switch (spec) {94    case AS_public: return CX_CXXPublic;95    case AS_protected: return CX_CXXProtected;96    case AS_private: return CX_CXXPrivate;97    case AS_none: return CX_CXXInvalidAccessSpecifier;98  }99 100  llvm_unreachable("Invalid AccessSpecifier!");101}102 103enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) {104  using namespace clang::cxcursor;105  106  switch (C.kind) {107  case CXCursor_ClassTemplate: 108  case CXCursor_FunctionTemplate:109    if (const TemplateDecl *Template110                           = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C)))111      return MakeCXCursor(Template->getTemplatedDecl(), getCursorTU(C)).kind;112    break;113      114  case CXCursor_ClassTemplatePartialSpecialization:115    if (const ClassTemplateSpecializationDecl *PartialSpec116          = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(117                                                            getCursorDecl(C))) {118      switch (PartialSpec->getTagKind()) {119      case TagTypeKind::Interface:120      case TagTypeKind::Struct:121        return CXCursor_StructDecl;122      case TagTypeKind::Class:123        return CXCursor_ClassDecl;124      case TagTypeKind::Union:125        return CXCursor_UnionDecl;126      case TagTypeKind::Enum:127        return CXCursor_NoDeclFound;128      }129    }130    break;131      132  default:133    break;134  }135  136  return CXCursor_NoDeclFound;137}138 139CXCursor clang_getSpecializedCursorTemplate(CXCursor C) {140  if (!clang_isDeclaration(C.kind))141    return clang_getNullCursor();142    143  const Decl *D = getCursorDecl(C);144  if (!D)145    return clang_getNullCursor();146 147  Decl *Template = nullptr;148  if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {149    if (const ClassTemplatePartialSpecializationDecl *PartialSpec150          = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord))151      Template = PartialSpec->getSpecializedTemplate();152    else if (const ClassTemplateSpecializationDecl *ClassSpec 153               = dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) {154      llvm::PointerUnion<ClassTemplateDecl *,155                         ClassTemplatePartialSpecializationDecl *> Result156        = ClassSpec->getSpecializedTemplateOrPartial();157      if (isa<ClassTemplateDecl *>(Result))158        Template = cast<ClassTemplateDecl *>(Result);159      else160        Template = cast<ClassTemplatePartialSpecializationDecl *>(Result);161 162    } else 163      Template = CXXRecord->getInstantiatedFromMemberClass();164  } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {165    Template = Function->getPrimaryTemplate();166    if (!Template)167      Template = Function->getInstantiatedFromMemberFunction();168  } else if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {169    if (Var->isStaticDataMember())170      Template = Var->getInstantiatedFromStaticDataMember();171  } else if (const RedeclarableTemplateDecl *Tmpl172                                        = dyn_cast<RedeclarableTemplateDecl>(D))173    Template = Tmpl->getInstantiatedFromMemberTemplate();174  175  if (!Template)176    return clang_getNullCursor();177  178  return MakeCXCursor(Template, getCursorTU(C));179}180