CIndexCXX.cpp 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  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-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file implements the libclang support for C++ cursors.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "CIndexer.h"
  13. #include "CXCursor.h"
  14. #include "CXType.h"
  15. #include "clang/AST/DeclCXX.h"
  16. #include "clang/AST/DeclTemplate.h"
  17. using namespace clang;
  18. using namespace clang::cxcursor;
  19. unsigned clang_isVirtualBase(CXCursor C) {
  20. if (C.kind != CXCursor_CXXBaseSpecifier)
  21. return 0;
  22. const CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
  23. return B->isVirtual();
  24. }
  25. enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) {
  26. AccessSpecifier spec = AS_none;
  27. if (C.kind == CXCursor_CXXAccessSpecifier || clang_isDeclaration(C.kind))
  28. spec = getCursorDecl(C)->getAccess();
  29. else if (C.kind == CXCursor_CXXBaseSpecifier)
  30. spec = getCursorCXXBaseSpecifier(C)->getAccessSpecifier();
  31. else
  32. return CX_CXXInvalidAccessSpecifier;
  33. switch (spec) {
  34. case AS_public: return CX_CXXPublic;
  35. case AS_protected: return CX_CXXProtected;
  36. case AS_private: return CX_CXXPrivate;
  37. case AS_none: return CX_CXXInvalidAccessSpecifier;
  38. }
  39. llvm_unreachable("Invalid AccessSpecifier!");
  40. }
  41. enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) {
  42. using namespace clang::cxcursor;
  43. switch (C.kind) {
  44. case CXCursor_ClassTemplate:
  45. case CXCursor_FunctionTemplate:
  46. if (const TemplateDecl *Template
  47. = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C)))
  48. return MakeCXCursor(Template->getTemplatedDecl(), getCursorTU(C)).kind;
  49. break;
  50. case CXCursor_ClassTemplatePartialSpecialization:
  51. if (const ClassTemplateSpecializationDecl *PartialSpec
  52. = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
  53. getCursorDecl(C))) {
  54. switch (PartialSpec->getTagKind()) {
  55. case TTK_Interface:
  56. case TTK_Struct: return CXCursor_StructDecl;
  57. case TTK_Class: return CXCursor_ClassDecl;
  58. case TTK_Union: return CXCursor_UnionDecl;
  59. case TTK_Enum: return CXCursor_NoDeclFound;
  60. }
  61. }
  62. break;
  63. default:
  64. break;
  65. }
  66. return CXCursor_NoDeclFound;
  67. }
  68. CXCursor clang_getSpecializedCursorTemplate(CXCursor C) {
  69. if (!clang_isDeclaration(C.kind))
  70. return clang_getNullCursor();
  71. const Decl *D = getCursorDecl(C);
  72. if (!D)
  73. return clang_getNullCursor();
  74. Decl *Template = nullptr;
  75. if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
  76. if (const ClassTemplatePartialSpecializationDecl *PartialSpec
  77. = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord))
  78. Template = PartialSpec->getSpecializedTemplate();
  79. else if (const ClassTemplateSpecializationDecl *ClassSpec
  80. = dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) {
  81. llvm::PointerUnion<ClassTemplateDecl *,
  82. ClassTemplatePartialSpecializationDecl *> Result
  83. = ClassSpec->getSpecializedTemplateOrPartial();
  84. if (Result.is<ClassTemplateDecl *>())
  85. Template = Result.get<ClassTemplateDecl *>();
  86. else
  87. Template = Result.get<ClassTemplatePartialSpecializationDecl *>();
  88. } else
  89. Template = CXXRecord->getInstantiatedFromMemberClass();
  90. } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
  91. Template = Function->getPrimaryTemplate();
  92. if (!Template)
  93. Template = Function->getInstantiatedFromMemberFunction();
  94. } else if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
  95. if (Var->isStaticDataMember())
  96. Template = Var->getInstantiatedFromStaticDataMember();
  97. } else if (const RedeclarableTemplateDecl *Tmpl
  98. = dyn_cast<RedeclarableTemplateDecl>(D))
  99. Template = Tmpl->getInstantiatedFromMemberTemplate();
  100. if (!Template)
  101. return clang_getNullCursor();
  102. return MakeCXCursor(Template, getCursorTU(C));
  103. }