1 //===- CIndexCXX.cpp - Clang-C Source Indexing Library --------------------===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the libclang support for C++ cursors.
11 //===----------------------------------------------------------------------===//
16 #include "clang/AST/DeclCXX.h"
17 #include "clang/AST/DeclTemplate.h"
19 using namespace clang
;
20 using namespace clang::cxcursor
;
22 unsigned clang_isVirtualBase(CXCursor C
) {
23 if (C
.kind
!= CXCursor_CXXBaseSpecifier
)
26 const CXXBaseSpecifier
*B
= getCursorCXXBaseSpecifier(C
);
27 return B
->isVirtual();
30 enum CX_CXXAccessSpecifier
clang_getCXXAccessSpecifier(CXCursor C
) {
31 AccessSpecifier spec
= AS_none
;
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();
38 return CX_CXXInvalidAccessSpecifier
;
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
;
47 llvm_unreachable("Invalid AccessSpecifier!");
50 enum CXCursorKind
clang_getTemplateCursorKind(CXCursor C
) {
51 using namespace clang::cxcursor
;
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
;
61 case CXCursor_ClassTemplatePartialSpecialization
:
62 if (const ClassTemplateSpecializationDecl
*PartialSpec
63 = dyn_cast_or_null
<ClassTemplatePartialSpecializationDecl
>(
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
;
83 return CXCursor_NoDeclFound
;
86 CXCursor
clang_getSpecializedCursorTemplate(CXCursor C
) {
87 if (!clang_isDeclaration(C
.kind
))
88 return clang_getNullCursor();
90 const Decl
*D
= getCursorDecl(C
);
92 return clang_getNullCursor();
94 Decl
*Template
= nullptr;
95 if (const CXXRecordDecl
*CXXRecord
= dyn_cast
<CXXRecordDecl
>(D
)) {
96 if (const ClassTemplatePartialSpecializationDecl
*PartialSpec
97 = dyn_cast
<ClassTemplatePartialSpecializationDecl
>(CXXRecord
))
98 Template
= PartialSpec
->getSpecializedTemplate();
99 else if (const ClassTemplateSpecializationDecl
*ClassSpec
100 = dyn_cast
<ClassTemplateSpecializationDecl
>(CXXRecord
)) {
101 llvm::PointerUnion
<ClassTemplateDecl
*,
102 ClassTemplatePartialSpecializationDecl
*> Result
103 = ClassSpec
->getSpecializedTemplateOrPartial();
104 if (Result
.is
<ClassTemplateDecl
*>())
105 Template
= Result
.get
<ClassTemplateDecl
*>();
107 Template
= Result
.get
<ClassTemplatePartialSpecializationDecl
*>();
110 Template
= CXXRecord
->getInstantiatedFromMemberClass();
111 } else if (const FunctionDecl
*Function
= dyn_cast
<FunctionDecl
>(D
)) {
112 Template
= Function
->getPrimaryTemplate();
114 Template
= Function
->getInstantiatedFromMemberFunction();
115 } else if (const VarDecl
*Var
= dyn_cast
<VarDecl
>(D
)) {
116 if (Var
->isStaticDataMember())
117 Template
= Var
->getInstantiatedFromStaticDataMember();
118 } else if (const RedeclarableTemplateDecl
*Tmpl
119 = dyn_cast
<RedeclarableTemplateDecl
>(D
))
120 Template
= Tmpl
->getInstantiatedFromMemberTemplate();
123 return clang_getNullCursor();
125 return MakeCXCursor(Template
, getCursorTU(C
));