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   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 
     49 enum 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 
     81 CXCursor 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