Home | History | Annotate | Line # | Download | only in libclang
      1 //===- CIndexCXX.cpp - Clang-C Source Indexing Library --------------------===//
      2 //
      3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
      4 // See https://llvm.org/LICENSE.txt for license information.
      5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
      6 //
      7 //===----------------------------------------------------------------------===//
      8 //
      9 // This file implements the libclang support for C++ cursors.
     10 //
     11 //===----------------------------------------------------------------------===//
     12 
     13 #include "CIndexer.h"
     14 #include "CXCursor.h"
     15 #include "CXType.h"
     16 #include "clang/AST/DeclCXX.h"
     17 #include "clang/AST/DeclTemplate.h"
     18 
     19 using namespace clang;
     20 using namespace clang::cxcursor;
     21 
     22 unsigned clang_isVirtualBase(CXCursor C) {
     23   if (C.kind != CXCursor_CXXBaseSpecifier)
     24     return 0;
     25 
     26   const CXXBaseSpecifier *B = getCursorCXXBaseSpecifier(C);
     27   return B->isVirtual();
     28 }
     29 
     30 enum CX_CXXAccessSpecifier clang_getCXXAccessSpecifier(CXCursor C) {
     31   AccessSpecifier spec = AS_none;
     32 
     33   if (C.kind == CXCursor_CXXAccessSpecifier || clang_isDeclaration(C.kind))
     34     spec = getCursorDecl(C)->getAccess();
     35   else if (C.kind == CXCursor_CXXBaseSpecifier)
     36     spec = getCursorCXXBaseSpecifier(C)->getAccessSpecifier();
     37   else
     38     return CX_CXXInvalidAccessSpecifier;
     39 
     40   switch (spec) {
     41     case AS_public: return CX_CXXPublic;
     42     case AS_protected: return CX_CXXProtected;
     43     case AS_private: return CX_CXXPrivate;
     44     case AS_none: return CX_CXXInvalidAccessSpecifier;
     45   }
     46 
     47   llvm_unreachable("Invalid AccessSpecifier!");
     48 }
     49 
     50 enum 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 (const TemplateDecl *Template
     57                            = dyn_cast_or_null<TemplateDecl>(getCursorDecl(C)))
     58       return MakeCXCursor(Template->getTemplatedDecl(), getCursorTU(C)).kind;
     59     break;
     60 
     61   case CXCursor_ClassTemplatePartialSpecialization:
     62     if (const ClassTemplateSpecializationDecl *PartialSpec
     63           = dyn_cast_or_null<ClassTemplatePartialSpecializationDecl>(
     64                                                             getCursorDecl(C))) {
     65       switch (PartialSpec->getTagKind()) {
     66       case TTK_Interface:
     67       case TTK_Struct: return CXCursor_StructDecl;
     68       case TTK_Class: return CXCursor_ClassDecl;
     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 
     82 CXCursor clang_getSpecializedCursorTemplate(CXCursor C) {
     83   if (!clang_isDeclaration(C.kind))
     84     return clang_getNullCursor();
     85 
     86   const Decl *D = getCursorDecl(C);
     87   if (!D)
     88     return clang_getNullCursor();
     89 
     90   Decl *Template = nullptr;
     91   if (const CXXRecordDecl *CXXRecord = dyn_cast<CXXRecordDecl>(D)) {
     92     if (const ClassTemplatePartialSpecializationDecl *PartialSpec
     93           = dyn_cast<ClassTemplatePartialSpecializationDecl>(CXXRecord))
     94       Template = PartialSpec->getSpecializedTemplate();
     95     else if (const 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 (const FunctionDecl *Function = dyn_cast<FunctionDecl>(D)) {
    108     Template = Function->getPrimaryTemplate();
    109     if (!Template)
    110       Template = Function->getInstantiatedFromMemberFunction();
    111   } else if (const VarDecl *Var = dyn_cast<VarDecl>(D)) {
    112     if (Var->isStaticDataMember())
    113       Template = Var->getInstantiatedFromStaticDataMember();
    114   } else if (const RedeclarableTemplateDecl *Tmpl
    115                                         = dyn_cast<RedeclarableTemplateDecl>(D))
    116     Template = Tmpl->getInstantiatedFromMemberTemplate();
    117 
    118   if (!Template)
    119     return clang_getNullCursor();
    120 
    121   return MakeCXCursor(Template, getCursorTU(C));
    122 }
    123