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   const 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 || clang_isDeclaration(C.kind))
     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 
     53 enum 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 (const TemplateDecl *Template
     60                            = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C)))
     61       return MakeCXCursor(Template->getTemplatedDecl(), getCursorTU(C)).kind;
     62     break;
     63 
     64   case CXCursor_ClassTemplatePartialSpecialization:
     65     if (const ClassTemplateSpecializationDecl *PartialSpec
     66           = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
     67                                                             getCursorDecl(C))) {
     68       switch (PartialSpec->getTagKind()) {
     69       case TTK_Interface:
     70       case TTK_Struct: return CXCursor_StructDecl;
     71       case TTK_Class: return CXCursor_ClassDecl;
     72       case TTK_Union: return CXCursor_UnionDecl;
     73       case TTK_Enum: return CXCursor_NoDeclFound;
     74       }
     75     }
     76     break;
     77 
     78   default:
     79     break;
     80   }
     81 
     82   return CXCursor_NoDeclFound;
     83 }
     84 
     85 CXCursor clang_getSpecializedCursorTemplate(CXCursor C) {
     86   if (!clang_isDeclaration(C.kind))
     87     return clang_getNullCursor();
     88 
     89   const Decl *D = getCursorDecl(C);
     90   if (!D)
     91     return clang_getNullCursor();
     92 
     93   Decl *Template = nullptr;
     94   if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
     95     if (const ClassTemplatePartialSpecializationDecl *PartialSpec
     96           = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord))
     97       Template = PartialSpec->getSpecializedTemplate();
     98     else if (const ClassTemplateSpecializationDecl *ClassSpec
     99                = dyn_cast<ClassTemplateSpecializationDecl>(CXXRecord)) {
    100       llvm::PointerUnion<ClassTemplateDecl *,
    101                          ClassTemplatePartialSpecializationDecl *> Result
    102         = ClassSpec->getSpecializedTemplateOrPartial();
    103       if (Result.is<ClassTemplateDecl *>())
    104         Template = Result.get<ClassTemplateDecl *>();
    105       else
    106         Template = Result.get<ClassTemplatePartialSpecializationDecl *>();
    107 
    108     } else
    109       Template = CXXRecord->getInstantiatedFromMemberClass();
    110   } else if (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
    111     Template = Function->getPrimaryTemplate();
    112     if (!Template)
    113       Template = Function->getInstantiatedFromMemberFunction();
    114   } else if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
    115     if (Var->isStaticDataMember())
    116       Template = Var->getInstantiatedFromStaticDataMember();
    117   } else if (const RedeclarableTemplateDecl *Tmpl
    118                                         = dyn_cast<RedeclarableTemplateDecl>(D))
    119     Template = Tmpl->getInstantiatedFromMemberTemplate();
    120 
    121   if (!Template)
    122     return clang_getNullCursor();
    123 
    124   return MakeCXCursor(Template, getCursorTU(C));
    125 }
    126 
    127 } // end extern "C"
    128