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 | |
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 | |
19 | using namespace clang; |
20 | using namespace clang::cxcursor; |
21 | |
22 | unsigned 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 | |
30 | enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) { |
31 | AccessSpecifier spec = AS_none; |
32 | |
33 | if (C.kind == CXCursor_CXXAccessSpecifier || clang_isDeclaration(C.kind)) |
34 | spec = getCursorDecl(Cursor: C)->getAccess(); |
35 | else if (C.kind == CXCursor_CXXBaseSpecifier) |
36 | spec = getCursorCXXBaseSpecifier(C)->getAccessSpecifier(); |
37 | else |
38 | return CX_CXXInvalidAccessSpecifier; |
39 | |
40 | switch (spec) { |
41 | case AS_public: return CX_CXXPublic; |
42 | case AS_protected: return CX_CXXProtected; |
43 | case AS_private: return CX_CXXPrivate; |
44 | case AS_none: return CX_CXXInvalidAccessSpecifier; |
45 | } |
46 | |
47 | llvm_unreachable("Invalid AccessSpecifier!"); |
48 | } |
49 | |
50 | enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) { |
51 | using namespace clang::cxcursor; |
52 | |
53 | switch (C.kind) { |
54 | case CXCursor_ClassTemplate: |
55 | case CXCursor_FunctionTemplate: |
56 | if (const TemplateDecl *Template |
57 | = dyn_cast_or_null<TemplateDecl>(Val: getCursorDecl(Cursor: C))) |
58 | return MakeCXCursor(Template->getTemplatedDecl(), getCursorTU(Cursor: C)).kind; |
59 | break; |
60 | |
61 | case CXCursor_ClassTemplatePartialSpecialization: |
62 | if (const ClassTemplateSpecializationDecl *PartialSpec |
63 | = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>( |
64 | Val: getCursorDecl(Cursor: C))) { |
65 | switch (PartialSpec->getTagKind()) { |
66 | case TagTypeKind::Interface: |
67 | case TagTypeKind::Struct: |
68 | return CXCursor_StructDecl; |
69 | case TagTypeKind::Class: |
70 | return CXCursor_ClassDecl; |
71 | case TagTypeKind::Union: |
72 | return CXCursor_UnionDecl; |
73 | case TagTypeKind::Enum: |
74 | return CXCursor_NoDeclFound; |
75 | } |
76 | } |
77 | break; |
78 | |
79 | default: |
80 | break; |
81 | } |
82 | |
83 | return CXCursor_NoDeclFound; |
84 | } |
85 | |
86 | CXCursor clang_getSpecializedCursorTemplate(CXCursor C) { |
87 | if (!clang_isDeclaration(C.kind)) |
88 | return clang_getNullCursor(); |
89 | |
90 | const Decl *D = getCursorDecl(Cursor: C); |
91 | if (!D) |
92 | return clang_getNullCursor(); |
93 | |
94 | Decl *Template = nullptr; |
95 | if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(Val: D)) { |
96 | if (const ClassTemplatePartialSpecializationDecl *PartialSpec |
97 | = dyn_cast<ClassTemplatePartialSpecializationDecl>(Val: CXXRecord)) |
98 | Template = PartialSpec->getSpecializedTemplate(); |
99 | else if (const ClassTemplateSpecializationDecl *ClassSpec |
100 | = dyn_cast<ClassTemplateSpecializationDecl>(Val: CXXRecord)) { |
101 | llvm::PointerUnion<ClassTemplateDecl *, |
102 | ClassTemplatePartialSpecializationDecl *> Result |
103 | = ClassSpec->getSpecializedTemplateOrPartial(); |
104 | if (Result.is<ClassTemplateDecl *>()) |
105 | Template = Result.get<ClassTemplateDecl *>(); |
106 | else |
107 | Template = Result.get<ClassTemplatePartialSpecializationDecl *>(); |
108 | |
109 | } else |
110 | Template = CXXRecord->getInstantiatedFromMemberClass(); |
111 | } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(Val: D)) { |
112 | Template = Function->getPrimaryTemplate(); |
113 | if (!Template) |
114 | Template = Function->getInstantiatedFromMemberFunction(); |
115 | } else if (const VarDecl *Var = dyn_cast<VarDecl>(Val: D)) { |
116 | if (Var->isStaticDataMember()) |
117 | Template = Var->getInstantiatedFromStaticDataMember(); |
118 | } else if (const RedeclarableTemplateDecl *Tmpl |
119 | = dyn_cast<RedeclarableTemplateDecl>(Val: D)) |
120 | Template = Tmpl->getInstantiatedFromMemberTemplate(); |
121 | |
122 | if (!Template) |
123 | return clang_getNullCursor(); |
124 | |
125 | return MakeCXCursor(D: Template, TU: getCursorTU(Cursor: C)); |
126 | } |
127 |