xref: /openbsd-src/gnu/llvm/clang/tools/libclang/CIndexCXX.cpp (revision e5dd70708596ae51455a0ffa086a00c5b29f8583)
1*e5dd7070Spatrick //===- CIndexCXX.cpp - Clang-C Source Indexing Library --------------------===//
2*e5dd7070Spatrick //
3*e5dd7070Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*e5dd7070Spatrick // See https://llvm.org/LICENSE.txt for license information.
5*e5dd7070Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*e5dd7070Spatrick //
7*e5dd7070Spatrick //===----------------------------------------------------------------------===//
8*e5dd7070Spatrick //
9*e5dd7070Spatrick // This file implements the libclang support for C++ cursors.
10*e5dd7070Spatrick //
11*e5dd7070Spatrick //===----------------------------------------------------------------------===//
12*e5dd7070Spatrick 
13*e5dd7070Spatrick #include "CIndexer.h"
14*e5dd7070Spatrick #include "CXCursor.h"
15*e5dd7070Spatrick #include "CXType.h"
16*e5dd7070Spatrick #include "clang/AST/DeclCXX.h"
17*e5dd7070Spatrick #include "clang/AST/DeclTemplate.h"
18*e5dd7070Spatrick 
19*e5dd7070Spatrick using namespace clang;
20*e5dd7070Spatrick using namespace clang::cxcursor;
21*e5dd7070Spatrick 
clang_isVirtualBase(CXCursor C)22*e5dd7070Spatrick unsigned clang_isVirtualBase(CXCursor C) {
23*e5dd7070Spatrick   if (C.kind != CXCursor_CXXBaseSpecifier)
24*e5dd7070Spatrick     return 0;
25*e5dd7070Spatrick 
26*e5dd7070Spatrick   const CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
27*e5dd7070Spatrick   return B->isVirtual();
28*e5dd7070Spatrick }
29*e5dd7070Spatrick 
clang_getCXXAccessSpecifier(CXCursor C)30*e5dd7070Spatrick enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) {
31*e5dd7070Spatrick   AccessSpecifier spec = AS_none;
32*e5dd7070Spatrick 
33*e5dd7070Spatrick   if (C.kind == CXCursor_CXXAccessSpecifier || clang_isDeclaration(C.kind))
34*e5dd7070Spatrick     spec = getCursorDecl(C)->getAccess();
35*e5dd7070Spatrick   else if (C.kind == CXCursor_CXXBaseSpecifier)
36*e5dd7070Spatrick     spec = getCursorCXXBaseSpecifier(C)->getAccessSpecifier();
37*e5dd7070Spatrick   else
38*e5dd7070Spatrick     return CX_CXXInvalidAccessSpecifier;
39*e5dd7070Spatrick 
40*e5dd7070Spatrick   switch (spec) {
41*e5dd7070Spatrick     case AS_public: return CX_CXXPublic;
42*e5dd7070Spatrick     case AS_protected: return CX_CXXProtected;
43*e5dd7070Spatrick     case AS_private: return CX_CXXPrivate;
44*e5dd7070Spatrick     case AS_none: return CX_CXXInvalidAccessSpecifier;
45*e5dd7070Spatrick   }
46*e5dd7070Spatrick 
47*e5dd7070Spatrick   llvm_unreachable("Invalid AccessSpecifier!");
48*e5dd7070Spatrick }
49*e5dd7070Spatrick 
clang_getTemplateCursorKind(CXCursor C)50*e5dd7070Spatrick enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) {
51*e5dd7070Spatrick   using namespace clang::cxcursor;
52*e5dd7070Spatrick 
53*e5dd7070Spatrick   switch (C.kind) {
54*e5dd7070Spatrick   case CXCursor_ClassTemplate:
55*e5dd7070Spatrick   case CXCursor_FunctionTemplate:
56*e5dd7070Spatrick     if (const TemplateDecl *Template
57*e5dd7070Spatrick                            = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C)))
58*e5dd7070Spatrick       return MakeCXCursor(Template->getTemplatedDecl(), getCursorTU(C)).kind;
59*e5dd7070Spatrick     break;
60*e5dd7070Spatrick 
61*e5dd7070Spatrick   case CXCursor_ClassTemplatePartialSpecialization:
62*e5dd7070Spatrick     if (const ClassTemplateSpecializationDecl *PartialSpec
63*e5dd7070Spatrick           = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
64*e5dd7070Spatrick                                                             getCursorDecl(C))) {
65*e5dd7070Spatrick       switch (PartialSpec->getTagKind()) {
66*e5dd7070Spatrick       case TTK_Interface:
67*e5dd7070Spatrick       case TTK_Struct: return CXCursor_StructDecl;
68*e5dd7070Spatrick       case TTK_Class: return CXCursor_ClassDecl;
69*e5dd7070Spatrick       case TTK_Union: return CXCursor_UnionDecl;
70*e5dd7070Spatrick       case TTK_Enum: return CXCursor_NoDeclFound;
71*e5dd7070Spatrick       }
72*e5dd7070Spatrick     }
73*e5dd7070Spatrick     break;
74*e5dd7070Spatrick 
75*e5dd7070Spatrick   default:
76*e5dd7070Spatrick     break;
77*e5dd7070Spatrick   }
78*e5dd7070Spatrick 
79*e5dd7070Spatrick   return CXCursor_NoDeclFound;
80*e5dd7070Spatrick }
81*e5dd7070Spatrick 
clang_getSpecializedCursorTemplate(CXCursor C)82*e5dd7070Spatrick CXCursor clang_getSpecializedCursorTemplate(CXCursor C) {
83*e5dd7070Spatrick   if (!clang_isDeclaration(C.kind))
84*e5dd7070Spatrick     return clang_getNullCursor();
85*e5dd7070Spatrick 
86*e5dd7070Spatrick   const Decl *D = getCursorDecl(C);
87*e5dd7070Spatrick   if (!D)
88*e5dd7070Spatrick     return clang_getNullCursor();
89*e5dd7070Spatrick 
90*e5dd7070Spatrick   Decl *Template = nullptr;
91*e5dd7070Spatrick   if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
92*e5dd7070Spatrick     if (const ClassTemplatePartialSpecializationDecl *PartialSpec
93*e5dd7070Spatrick           = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord))
94*e5dd7070Spatrick       Template = PartialSpec->getSpecializedTemplate();
95*e5dd7070Spatrick     else if (const ClassTemplateSpecializationDecl *ClassSpec
96*e5dd7070Spatrick                = dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) {
97*e5dd7070Spatrick       llvm::PointerUnion<ClassTemplateDecl *,
98*e5dd7070Spatrick                          ClassTemplatePartialSpecializationDecl *> Result
99*e5dd7070Spatrick         = ClassSpec->getSpecializedTemplateOrPartial();
100*e5dd7070Spatrick       if (Result.is<ClassTemplateDecl *>())
101*e5dd7070Spatrick         Template = Result.get<ClassTemplateDecl *>();
102*e5dd7070Spatrick       else
103*e5dd7070Spatrick         Template = Result.get<ClassTemplatePartialSpecializationDecl *>();
104*e5dd7070Spatrick 
105*e5dd7070Spatrick     } else
106*e5dd7070Spatrick       Template = CXXRecord->getInstantiatedFromMemberClass();
107*e5dd7070Spatrick   } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
108*e5dd7070Spatrick     Template = Function->getPrimaryTemplate();
109*e5dd7070Spatrick     if (!Template)
110*e5dd7070Spatrick       Template = Function->getInstantiatedFromMemberFunction();
111*e5dd7070Spatrick   } else if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
112*e5dd7070Spatrick     if (Var->isStaticDataMember())
113*e5dd7070Spatrick       Template = Var->getInstantiatedFromStaticDataMember();
114*e5dd7070Spatrick   } else if (const RedeclarableTemplateDecl *Tmpl
115*e5dd7070Spatrick                                         = dyn_cast<RedeclarableTemplateDecl>(D))
116*e5dd7070Spatrick     Template = Tmpl->getInstantiatedFromMemberTemplate();
117*e5dd7070Spatrick 
118*e5dd7070Spatrick   if (!Template)
119*e5dd7070Spatrick     return clang_getNullCursor();
120*e5dd7070Spatrick 
121*e5dd7070Spatrick   return MakeCXCursor(Template, getCursorTU(C));
122*e5dd7070Spatrick }
123