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
19using namespace clang;
20using namespace clang::cxcursor;
21
22unsigned 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
30enum 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
50enum 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(D: Template->getTemplatedDecl(), TU: 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
86CXCursor 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