CIndexCXX.cpp revision a60ed47da13393796d8552b9fdca12abbb3eea42
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
20using namespace clang;
21using namespace clang::cxcursor;
22
23extern "C" {
24
25unsigned 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
33enum 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
49enum 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
81CXCursor 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