CIndexCXX.cpp revision 6666ed4ed2e2bc13da5ac5d0a4947019137d45be
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  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
53enum 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
86CXCursor 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