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