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()) {
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
;
79 return CXCursor_NoDeclFound
;
82 CXCursor
clang_getSpecializedCursorTemplate(CXCursor C
) {
83 if (!clang_isDeclaration(C
.kind
))
84 return clang_getNullCursor();
86 const Decl
*D
= getCursorDecl(C
);
88 return clang_getNullCursor();
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
*>();
103 Template
= Result
.get
<ClassTemplatePartialSpecializationDecl
*>();
106 Template
= CXXRecord
->getInstantiatedFromMemberClass();
107 } else if (const FunctionDecl
*Function
= dyn_cast
<FunctionDecl
>(D
)) {
108 Template
= Function
->getPrimaryTemplate();
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();
119 return clang_getNullCursor();
121 return MakeCXCursor(Template
, getCursorTU(C
));