• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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   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)
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 (TemplateDecl *Template
60                            = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C)))
61       return MakeCXCursor(Template->getTemplatedDecl(),
62                           static_cast<CXTranslationUnit>(C.data[2])).kind;
63     break;
64 
65   case CXCursor_ClassTemplatePartialSpecialization:
66     if (ClassTemplateSpecializationDecl *PartialSpec
67           = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
68                                                             getCursorDecl(C))) {
69       switch (PartialSpec->getTagKind()) {
70       case TTK_Interface:
71       case TTK_Struct: return CXCursor_StructDecl;
72       case TTK_Class: return CXCursor_ClassDecl;
73       case TTK_Union: return CXCursor_UnionDecl;
74       case TTK_Enum: return CXCursor_NoDeclFound;
75       }
76     }
77     break;
78 
79   default:
80     break;
81   }
82 
83   return CXCursor_NoDeclFound;
84 }
85 
clang_getSpecializedCursorTemplate(CXCursor C)86 CXCursor clang_getSpecializedCursorTemplate(CXCursor C) {
87   if (!clang_isDeclaration(C.kind))
88     return clang_getNullCursor();
89 
90   Decl *D = getCursorDecl(C);
91   if (!D)
92     return clang_getNullCursor();
93 
94   Decl *Template = 0;
95   if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
96     if (ClassTemplatePartialSpecializationDecl *PartialSpec
97           = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord))
98       Template = PartialSpec->getSpecializedTemplate();
99     else if (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 *>();
106       else
107         Template = Result.get<ClassTemplatePartialSpecializationDecl *>();
108 
109     } else
110       Template = CXXRecord->getInstantiatedFromMemberClass();
111   } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
112     Template = Function->getPrimaryTemplate();
113     if (!Template)
114       Template = Function->getInstantiatedFromMemberFunction();
115   } else if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
116     if (Var->isStaticDataMember())
117       Template = Var->getInstantiatedFromStaticDataMember();
118   } else if (RedeclarableTemplateDecl *Tmpl
119                                         = dyn_cast<RedeclarableTemplateDecl>(D))
120     Template = Tmpl->getInstantiatedFromMemberTemplate();
121 
122   if (!Template)
123     return clang_getNullCursor();
124 
125   return MakeCXCursor(Template, static_cast<CXTranslationUnit>(C.data[2]));
126 }
127 
128 } // end extern "C"
129