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