Home | History | Annotate | Download | only in libclang
      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 
     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 
     33 enum 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   // FIXME: Clang currently thinks this is reachable.
     51   return CX_CXXInvalidAccessSpecifier;
     52 }
     53 
     54 enum CXCursorKind clang_getTemplateCursorKind(CXCursor C) {
     55   using namespace clang::cxcursor;
     56 
     57   switch (C.kind) {
     58   case CXCursor_ClassTemplate:
     59   case CXCursor_FunctionTemplate:
     60     if (TemplateDecl *Template
     61                            = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C)))
     62       return MakeCXCursor(Template->getTemplatedDecl(),
     63                           static_cast<CXTranslationUnit>(C.data[2])).kind;
     64     break;
     65 
     66   case CXCursor_ClassTemplatePartialSpecialization:
     67     if (ClassTemplateSpecializationDecl *PartialSpec
     68           = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
     69                                                             getCursorDecl(C))) {
     70       switch (PartialSpec->getTagKind()) {
     71       case TTK_Class: return CXCursor_ClassDecl;
     72       case TTK_Struct: return CXCursor_StructDecl;
     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 
     86 CXCursor 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