1585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek//===- CIndexCXX.cpp - Clang-C Source Indexing Library --------------------===//
2585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek//
3585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek//                     The LLVM Compiler Infrastructure
4585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek//
5585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek// This file is distributed under the University of Illinois Open Source
6585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek// License. See LICENSE.TXT for details.
7585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek//
8585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek//===----------------------------------------------------------------------===//
9585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek//
10585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek// This file implements the libclang support for C++ cursors.
11585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek//
12585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek//===----------------------------------------------------------------------===//
13585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek
14585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek#include "CIndexer.h"
15585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek#include "CXCursor.h"
16585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek#include "CXType.h"
17585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek#include "clang/AST/DeclCXX.h"
1849f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor#include "clang/AST/DeclTemplate.h"
19585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek
20585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenekusing namespace clang;
21e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregorusing namespace clang::cxcursor;
22585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek
23585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenekextern "C" {
24585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek
25585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenekunsigned clang_isVirtualBase(CXCursor C) {
26585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek  if (C.kind != CXCursor_CXXBaseSpecifier)
27585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek    return 0;
28585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek
2967812b2f94f4b5e7d2596db1705ffa1149ddc45aDmitri Gribenko  const CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
30585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek  return B->isVirtual();
31585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek}
32585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek
33585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenekenum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) {
342dfdb948bef51a601e763191e4becfe59880d382Argyrios Kyrtzidis  AccessSpecifier spec = AS_none;
352dfdb948bef51a601e763191e4becfe59880d382Argyrios Kyrtzidis
3604b6748ee90649069ee79464317ae6cd6aca317dArgyrios Kyrtzidis  if (C.kind == CXCursor_CXXAccessSpecifier || clang_isDeclaration(C.kind))
372dfdb948bef51a601e763191e4becfe59880d382Argyrios Kyrtzidis    spec = getCursorDecl(C)->getAccess();
382dfdb948bef51a601e763191e4becfe59880d382Argyrios Kyrtzidis  else if (C.kind == CXCursor_CXXBaseSpecifier)
392dfdb948bef51a601e763191e4becfe59880d382Argyrios Kyrtzidis    spec = getCursorCXXBaseSpecifier(C)->getAccessSpecifier();
402dfdb948bef51a601e763191e4becfe59880d382Argyrios Kyrtzidis  else
41585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek    return CX_CXXInvalidAccessSpecifier;
42585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek
432dfdb948bef51a601e763191e4becfe59880d382Argyrios Kyrtzidis  switch (spec) {
44585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek    case AS_public: return CX_CXXPublic;
45585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek    case AS_protected: return CX_CXXProtected;
46585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek    case AS_private: return CX_CXXPrivate;
47585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek    case AS_none: return CX_CXXInvalidAccessSpecifier;
48585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek  }
497530c034c0c71a64c5a9173206d9742ae847af8bDavid Blaikie
507530c034c0c71a64c5a9173206d9742ae847af8bDavid Blaikie  llvm_unreachable("Invalid AccessSpecifier!");
51585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek}
52585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek
5349f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregorenum CXCursorKind clang_getTemplateCursorKind(CXCursor C) {
5449f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor  using namespace clang::cxcursor;
5549f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor
5649f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor  switch (C.kind) {
5749f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor  case CXCursor_ClassTemplate:
5849f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor  case CXCursor_FunctionTemplate:
59e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko    if (const TemplateDecl *Template
6049f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor                           = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C)))
6146f92523918fd4ac4df5489265c7f85c1b28baeaDmitri Gribenko      return MakeCXCursor(Template->getTemplatedDecl(), getCursorTU(C)).kind;
6249f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor    break;
6349f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor
6449f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor  case CXCursor_ClassTemplatePartialSpecialization:
65e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko    if (const ClassTemplateSpecializationDecl *PartialSpec
6617d35c36fbae764fcd68fa8b31624078a033aabcJoao Matos          = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
6717d35c36fbae764fcd68fa8b31624078a033aabcJoao Matos                                                            getCursorDecl(C))) {
6817d35c36fbae764fcd68fa8b31624078a033aabcJoao Matos      switch (PartialSpec->getTagKind()) {
6917d35c36fbae764fcd68fa8b31624078a033aabcJoao Matos      case TTK_Interface:
7017d35c36fbae764fcd68fa8b31624078a033aabcJoao Matos      case TTK_Struct: return CXCursor_StructDecl;
7117d35c36fbae764fcd68fa8b31624078a033aabcJoao Matos      case TTK_Class: return CXCursor_ClassDecl;
7217d35c36fbae764fcd68fa8b31624078a033aabcJoao Matos      case TTK_Union: return CXCursor_UnionDecl;
7317d35c36fbae764fcd68fa8b31624078a033aabcJoao Matos      case TTK_Enum: return CXCursor_NoDeclFound;
7417d35c36fbae764fcd68fa8b31624078a033aabcJoao Matos      }
7549f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor    }
7649f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor    break;
7749f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor
7849f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor  default:
7949f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor    break;
8049f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor  }
8149f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor
8249f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor  return CXCursor_NoDeclFound;
8349f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor}
8449f6f5489483beaffc7ce48dfc000af4e65b9216Douglas Gregor
85e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas GregorCXCursor clang_getSpecializedCursorTemplate(CXCursor C) {
86e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor  if (!clang_isDeclaration(C.kind))
87e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor    return clang_getNullCursor();
88e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor
89e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko  const Decl *D = getCursorDecl(C);
90e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor  if (!D)
91e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor    return clang_getNullCursor();
92e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor
93e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor  Decl *Template = 0;
94e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko  if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
95e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko    if (const ClassTemplatePartialSpecializationDecl *PartialSpec
96e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor          = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord))
97e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor      Template = PartialSpec->getSpecializedTemplate();
98e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko    else if (const ClassTemplateSpecializationDecl *ClassSpec
99e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor               = dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) {
100e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor      llvm::PointerUnion<ClassTemplateDecl *,
101e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor                         ClassTemplatePartialSpecializationDecl *> Result
102e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor        = ClassSpec->getSpecializedTemplateOrPartial();
103e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor      if (Result.is<ClassTemplateDecl *>())
104e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor        Template = Result.get<ClassTemplateDecl *>();
105e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor      else
106e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor        Template = Result.get<ClassTemplatePartialSpecializationDecl *>();
107e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor
108e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor    } else
109e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor      Template = CXXRecord->getInstantiatedFromMemberClass();
110e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko  } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
111e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor    Template = Function->getPrimaryTemplate();
112e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor    if (!Template)
113e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor      Template = Function->getInstantiatedFromMemberFunction();
114e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko  } else if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
115e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor    if (Var->isStaticDataMember())
116e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor      Template = Var->getInstantiatedFromStaticDataMember();
117e22339c44bb28d71a2cc97c840d3da0c4bdb4909Dmitri Gribenko  } else if (const RedeclarableTemplateDecl *Tmpl
118e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor                                        = dyn_cast<RedeclarableTemplateDecl>(D))
119e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor    Template = Tmpl->getInstantiatedFromMemberTemplate();
120e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor
121e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor  if (!Template)
122e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor    return clang_getNullCursor();
123e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor
12446f92523918fd4ac4df5489265c7f85c1b28baeaDmitri Gribenko  return MakeCXCursor(Template, getCursorTU(C));
125e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor}
126e0329acf5c9437e2086a2fb2bf7a95ae2ac96505Douglas Gregor
127585b318a7333b5dd1d900881db7b6610e2701fe8Ted Kremenek} // end extern "C"
128