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(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>(getCursorDecl(C))) |
58 | return MakeCXCursor(Template->getTemplatedDecl(), getCursorTU(C)).kind; |
59 | break; |
60 | |
61 | case CXCursor_ClassTemplatePartialSpecialization: |
62 | if (const ClassTemplateSpecializationDecl *PartialSpec |
63 | = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>( |
64 | getCursorDecl(C))) { |
65 | switch (PartialSpec->getTagKind()) { |
66 | case TTK_Interface: |
67 | case TTK_Struct: return CXCursor_StructDecl; |
68 | case TTK_Class: return CXCursor_ClassDecl; |
69 | case TTK_Union: return CXCursor_UnionDecl; |
70 | case TTK_Enum: return CXCursor_NoDeclFound; |
71 | } |
72 | } |
73 | break; |
74 | |
75 | default: |
76 | break; |
77 | } |
78 | |
79 | return CXCursor_NoDeclFound; |
80 | } |
81 | |
82 | CXCursor clang_getSpecializedCursorTemplate(CXCursor C) { |
83 | if (!clang_isDeclaration(C.kind)) |
84 | return clang_getNullCursor(); |
85 | |
86 | const Decl *D = getCursorDecl(C); |
87 | if (!D) |
88 | return clang_getNullCursor(); |
89 | |
90 | Decl *Template = nullptr; |
91 | if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) { |
92 | if (const ClassTemplatePartialSpecializationDecl *PartialSpec |
93 | = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord)) |
94 | Template = PartialSpec->getSpecializedTemplate(); |
95 | else if (const ClassTemplateSpecializationDecl *ClassSpec |
96 | = dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) { |
97 | llvm::PointerUnion<ClassTemplateDecl *, |
98 | ClassTemplatePartialSpecializationDecl *> Result |
99 | = ClassSpec->getSpecializedTemplateOrPartial(); |
100 | if (Result.is<ClassTemplateDecl *>()) |
101 | Template = Result.get<ClassTemplateDecl *>(); |
102 | else |
103 | Template = Result.get<ClassTemplatePartialSpecializationDecl *>(); |
104 | |
105 | } else |
106 | Template = CXXRecord->getInstantiatedFromMemberClass(); |
107 | } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) { |
108 | Template = Function->getPrimaryTemplate(); |
109 | if (!Template) |
110 | Template = Function->getInstantiatedFromMemberFunction(); |
111 | } else if (const VarDecl *Var = dyn_cast<VarDecl>(D)) { |
112 | if (Var->isStaticDataMember()) |
113 | Template = Var->getInstantiatedFromStaticDataMember(); |
114 | } else if (const RedeclarableTemplateDecl *Tmpl |
115 | = dyn_cast<RedeclarableTemplateDecl>(D)) |
116 | Template = Tmpl->getInstantiatedFromMemberTemplate(); |
117 | |
118 | if (!Template) |
119 | return clang_getNullCursor(); |
120 | |
121 | return MakeCXCursor(Template, getCursorTU(C)); |
122 | } |
123 |