• 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   if (C.kind != CXCursor_CXXBaseSpecifier)
35     return CX_CXXInvalidAccessSpecifier;
36 
37   CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
38   switch (B->getAccessSpecifier()) {
39     case AS_public: return CX_CXXPublic;
40     case AS_protected: return CX_CXXProtected;
41     case AS_private: return CX_CXXPrivate;
42     case AS_none: return CX_CXXInvalidAccessSpecifier;
43   }
44 
45   // FIXME: Clang currently thinks this is reachable.
46   return CX_CXXInvalidAccessSpecifier;
47 }
48 
clang_getTemplateCursorKind(CXCursor C)49 enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) {
50   using namespace clang::cxcursor;
51 
52   switch (C.kind) {
53   case CXCursor_ClassTemplate:
54   case CXCursor_FunctionTemplate:
55     if (TemplateDecl *Template
56                            = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C)))
57       return MakeCXCursor(Template->getTemplatedDecl(),
58                           static_cast<CXTranslationUnit>(C.data[2])).kind;
59     break;
60 
61   case CXCursor_ClassTemplatePartialSpecialization:
62     if (ClassTemplateSpecializationDecl *PartialSpec
63           = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
64                                                             getCursorDecl(C))) {
65       switch (PartialSpec->getTagKind()) {
66       case TTK_Class: return CXCursor_ClassDecl;
67       case TTK_Struct: return CXCursor_StructDecl;
68       case TTK_Union: return CXCursor_UnionDecl;
69       case TTK_Enum: return CXCursor_NoDeclFound;
70       }
71     }
72     break;
73 
74   default:
75     break;
76   }
77 
78   return CXCursor_NoDeclFound;
79 }
80 
clang_getSpecializedCursorTemplate(CXCursor C)81 CXCursor clang_getSpecializedCursorTemplate(CXCursor C) {
82   if (!clang_isDeclaration(C.kind))
83     return clang_getNullCursor();
84 
85   Decl *D = getCursorDecl(C);
86   if (!D)
87     return clang_getNullCursor();
88 
89   Decl *Template = 0;
90   if (CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
91     if (ClassTemplatePartialSpecializationDecl *PartialSpec
92           = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord))
93       Template = PartialSpec->getSpecializedTemplate();
94     else if (ClassTemplateSpecializationDecl *ClassSpec
95                = dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) {
96       llvm::PointerUnion<ClassTemplateDecl *,
97                          ClassTemplatePartialSpecializationDecl *> Result
98         = ClassSpec->getSpecializedTemplateOrPartial();
99       if (Result.is<ClassTemplateDecl *>())
100         Template = Result.get<ClassTemplateDecl *>();
101       else
102         Template = Result.get<ClassTemplatePartialSpecializationDecl *>();
103 
104     } else
105       Template = CXXRecord->getInstantiatedFromMemberClass();
106   } else if (FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
107     Template = Function->getPrimaryTemplate();
108     if (!Template)
109       Template = Function->getInstantiatedFromMemberFunction();
110   } else if (VarDecl *Var = dyn_cast<VarDecl>(D)) {
111     if (Var->isStaticDataMember())
112       Template = Var->getInstantiatedFromStaticDataMember();
113   } else if (RedeclarableTemplateDecl *Tmpl
114                                         = dyn_cast<RedeclarableTemplateDecl>(D))
115     Template = Tmpl->getInstantiatedFromMemberTemplate();
116 
117   if (!Template)
118     return clang_getNullCursor();
119 
120   return MakeCXCursor(Template, static_cast<CXTranslationUnit>(C.data[2]));
121 }
122 
123 } // end extern "C"
124