Home | History | Annotate | Download | only in libclang
      1 //===- CXTypes.cpp - Implements 'CXTypes' aspect of libclang ------------===//
      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 'CXTypes' API hooks in the Clang-C library.
     11 //
     12 //===--------------------------------------------------------------------===//
     13 
     14 #include "CIndexer.h"
     15 #include "CXTranslationUnit.h"
     16 #include "CXCursor.h"
     17 #include "CXString.h"
     18 #include "CXType.h"
     19 #include "clang/AST/Expr.h"
     20 #include "clang/AST/Type.h"
     21 #include "clang/AST/Decl.h"
     22 #include "clang/AST/DeclObjC.h"
     23 #include "clang/AST/DeclTemplate.h"
     24 #include "clang/Frontend/ASTUnit.h"
     25 
     26 using namespace clang;
     27 
     28 static CXTypeKind GetBuiltinTypeKind(const BuiltinType *BT) {
     29 #define BTCASE(K) case BuiltinType::K: return CXType_##K
     30   switch (BT->getKind()) {
     31     BTCASE(Void);
     32     BTCASE(Bool);
     33     BTCASE(Char_U);
     34     BTCASE(UChar);
     35     BTCASE(Char16);
     36     BTCASE(Char32);
     37     BTCASE(UShort);
     38     BTCASE(UInt);
     39     BTCASE(ULong);
     40     BTCASE(ULongLong);
     41     BTCASE(UInt128);
     42     BTCASE(Char_S);
     43     BTCASE(SChar);
     44     case BuiltinType::WChar_S: return CXType_WChar;
     45     case BuiltinType::WChar_U: return CXType_WChar;
     46     BTCASE(Short);
     47     BTCASE(Int);
     48     BTCASE(Long);
     49     BTCASE(LongLong);
     50     BTCASE(Int128);
     51     BTCASE(Float);
     52     BTCASE(Double);
     53     BTCASE(LongDouble);
     54     BTCASE(NullPtr);
     55     BTCASE(Overload);
     56     BTCASE(Dependent);
     57     BTCASE(ObjCId);
     58     BTCASE(ObjCClass);
     59     BTCASE(ObjCSel);
     60   default:
     61     return CXType_Unexposed;
     62   }
     63 #undef BTCASE
     64 }
     65 
     66 static CXTypeKind GetTypeKind(QualType T) {
     67   const Type *TP = T.getTypePtrOrNull();
     68   if (!TP)
     69     return CXType_Invalid;
     70 
     71 #define TKCASE(K) case Type::K: return CXType_##K
     72   switch (TP->getTypeClass()) {
     73     case Type::Builtin:
     74       return GetBuiltinTypeKind(cast<BuiltinType>(TP));
     75     TKCASE(Complex);
     76     TKCASE(Pointer);
     77     TKCASE(BlockPointer);
     78     TKCASE(LValueReference);
     79     TKCASE(RValueReference);
     80     TKCASE(Record);
     81     TKCASE(Enum);
     82     TKCASE(Typedef);
     83     TKCASE(ObjCInterface);
     84     TKCASE(ObjCObjectPointer);
     85     TKCASE(FunctionNoProto);
     86     TKCASE(FunctionProto);
     87     default:
     88       return CXType_Unexposed;
     89   }
     90 #undef TKCASE
     91 }
     92 
     93 
     94 CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) {
     95   CXTypeKind TK = GetTypeKind(T);
     96   CXType CT = { TK, { TK == CXType_Invalid ? 0 : T.getAsOpaquePtr(), TU }};
     97   return CT;
     98 }
     99 
    100 using cxtype::MakeCXType;
    101 
    102 static inline QualType GetQualType(CXType CT) {
    103   return QualType::getFromOpaquePtr(CT.data[0]);
    104 }
    105 
    106 static inline CXTranslationUnit GetTU(CXType CT) {
    107   return static_cast<CXTranslationUnit>(CT.data[1]);
    108 }
    109 
    110 extern "C" {
    111 
    112 CXType clang_getCursorType(CXCursor C) {
    113   using namespace cxcursor;
    114 
    115   CXTranslationUnit TU = cxcursor::getCursorTU(C);
    116   ASTContext &Context = static_cast<ASTUnit *>(TU->TUData)->getASTContext();
    117   if (clang_isExpression(C.kind)) {
    118     QualType T = cxcursor::getCursorExpr(C)->getType();
    119     return MakeCXType(T, TU);
    120   }
    121 
    122   if (clang_isDeclaration(C.kind)) {
    123     Decl *D = cxcursor::getCursorDecl(C);
    124 
    125     if (TypeDecl *TD = dyn_cast<TypeDecl>(D))
    126       return MakeCXType(Context.getTypeDeclType(TD), TU);
    127     if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
    128       return MakeCXType(Context.getObjCInterfaceType(ID), TU);
    129     if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
    130       return MakeCXType(VD->getType(), TU);
    131     if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D))
    132       return MakeCXType(PD->getType(), TU);
    133     if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
    134       return MakeCXType(FD->getType(), TU);
    135     return MakeCXType(QualType(), TU);
    136   }
    137 
    138   if (clang_isReference(C.kind)) {
    139     switch (C.kind) {
    140     case CXCursor_ObjCSuperClassRef: {
    141       QualType T
    142         = Context.getObjCInterfaceType(getCursorObjCSuperClassRef(C).first);
    143       return MakeCXType(T, TU);
    144     }
    145 
    146     case CXCursor_ObjCClassRef: {
    147       QualType T = Context.getObjCInterfaceType(getCursorObjCClassRef(C).first);
    148       return MakeCXType(T, TU);
    149     }
    150 
    151     case CXCursor_TypeRef: {
    152       QualType T = Context.getTypeDeclType(getCursorTypeRef(C).first);
    153       return MakeCXType(T, TU);
    154 
    155     }
    156 
    157     case CXCursor_CXXBaseSpecifier:
    158       return cxtype::MakeCXType(getCursorCXXBaseSpecifier(C)->getType(), TU);
    159 
    160     case CXCursor_ObjCProtocolRef:
    161     case CXCursor_TemplateRef:
    162     case CXCursor_NamespaceRef:
    163     case CXCursor_MemberRef:
    164     case CXCursor_OverloadedDeclRef:
    165     default:
    166       break;
    167     }
    168 
    169     return MakeCXType(QualType(), TU);
    170   }
    171 
    172   return MakeCXType(QualType(), TU);
    173 }
    174 
    175 CXType clang_getCanonicalType(CXType CT) {
    176   if (CT.kind == CXType_Invalid)
    177     return CT;
    178 
    179   QualType T = GetQualType(CT);
    180   CXTranslationUnit TU = GetTU(CT);
    181 
    182   if (T.isNull())
    183     return MakeCXType(QualType(), GetTU(CT));
    184 
    185   ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData);
    186   return MakeCXType(AU->getASTContext().getCanonicalType(T), TU);
    187 }
    188 
    189 unsigned clang_isConstQualifiedType(CXType CT) {
    190   QualType T = GetQualType(CT);
    191   return T.isLocalConstQualified();
    192 }
    193 
    194 unsigned clang_isVolatileQualifiedType(CXType CT) {
    195   QualType T = GetQualType(CT);
    196   return T.isLocalVolatileQualified();
    197 }
    198 
    199 unsigned clang_isRestrictQualifiedType(CXType CT) {
    200   QualType T = GetQualType(CT);
    201   return T.isLocalRestrictQualified();
    202 }
    203 
    204 CXType clang_getPointeeType(CXType CT) {
    205   QualType T = GetQualType(CT);
    206   const Type *TP = T.getTypePtrOrNull();
    207 
    208   if (!TP)
    209     return MakeCXType(QualType(), GetTU(CT));
    210 
    211   switch (TP->getTypeClass()) {
    212     case Type::Pointer:
    213       T = cast<PointerType>(TP)->getPointeeType();
    214       break;
    215     case Type::BlockPointer:
    216       T = cast<BlockPointerType>(TP)->getPointeeType();
    217       break;
    218     case Type::LValueReference:
    219     case Type::RValueReference:
    220       T = cast<ReferenceType>(TP)->getPointeeType();
    221       break;
    222     case Type::ObjCObjectPointer:
    223       T = cast<ObjCObjectPointerType>(TP)->getPointeeType();
    224       break;
    225     default:
    226       T = QualType();
    227       break;
    228   }
    229   return MakeCXType(T, GetTU(CT));
    230 }
    231 
    232 CXCursor clang_getTypeDeclaration(CXType CT) {
    233   if (CT.kind == CXType_Invalid)
    234     return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
    235 
    236   QualType T = GetQualType(CT);
    237   const Type *TP = T.getTypePtrOrNull();
    238 
    239   if (!TP)
    240     return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
    241 
    242   Decl *D = 0;
    243 
    244 try_again:
    245   switch (TP->getTypeClass()) {
    246   case Type::Typedef:
    247     D = cast<TypedefType>(TP)->getDecl();
    248     break;
    249   case Type::ObjCObject:
    250     D = cast<ObjCObjectType>(TP)->getInterface();
    251     break;
    252   case Type::ObjCInterface:
    253     D = cast<ObjCInterfaceType>(TP)->getDecl();
    254     break;
    255   case Type::Record:
    256   case Type::Enum:
    257     D = cast<TagType>(TP)->getDecl();
    258     break;
    259   case Type::TemplateSpecialization:
    260     if (const RecordType *Record = TP->getAs<RecordType>())
    261       D = Record->getDecl();
    262     else
    263       D = cast<TemplateSpecializationType>(TP)->getTemplateName()
    264                                                          .getAsTemplateDecl();
    265     break;
    266 
    267   case Type::InjectedClassName:
    268     D = cast<InjectedClassNameType>(TP)->getDecl();
    269     break;
    270 
    271   // FIXME: Template type parameters!
    272 
    273   case Type::Elaborated:
    274     TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull();
    275     goto try_again;
    276 
    277   default:
    278     break;
    279   }
    280 
    281   if (!D)
    282     return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
    283 
    284   return cxcursor::MakeCXCursor(D, GetTU(CT));
    285 }
    286 
    287 CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
    288   const char *s = 0;
    289 #define TKIND(X) case CXType_##X: s = ""  #X  ""; break
    290   switch (K) {
    291     TKIND(Invalid);
    292     TKIND(Unexposed);
    293     TKIND(Void);
    294     TKIND(Bool);
    295     TKIND(Char_U);
    296     TKIND(UChar);
    297     TKIND(Char16);
    298     TKIND(Char32);
    299     TKIND(UShort);
    300     TKIND(UInt);
    301     TKIND(ULong);
    302     TKIND(ULongLong);
    303     TKIND(UInt128);
    304     TKIND(Char_S);
    305     TKIND(SChar);
    306     case CXType_WChar: s = "WChar"; break;
    307     TKIND(Short);
    308     TKIND(Int);
    309     TKIND(Long);
    310     TKIND(LongLong);
    311     TKIND(Int128);
    312     TKIND(Float);
    313     TKIND(Double);
    314     TKIND(LongDouble);
    315     TKIND(NullPtr);
    316     TKIND(Overload);
    317     TKIND(Dependent);
    318     TKIND(ObjCId);
    319     TKIND(ObjCClass);
    320     TKIND(ObjCSel);
    321     TKIND(Complex);
    322     TKIND(Pointer);
    323     TKIND(BlockPointer);
    324     TKIND(LValueReference);
    325     TKIND(RValueReference);
    326     TKIND(Record);
    327     TKIND(Enum);
    328     TKIND(Typedef);
    329     TKIND(ObjCInterface);
    330     TKIND(ObjCObjectPointer);
    331     TKIND(FunctionNoProto);
    332     TKIND(FunctionProto);
    333   }
    334 #undef TKIND
    335   return cxstring::createCXString(s);
    336 }
    337 
    338 unsigned clang_equalTypes(CXType A, CXType B) {
    339   return A.data[0] == B.data[0] && A.data[1] == B.data[1];;
    340 }
    341 
    342 CXType clang_getResultType(CXType X) {
    343   QualType T = GetQualType(X);
    344   if (!T.getTypePtrOrNull())
    345     return MakeCXType(QualType(), GetTU(X));
    346 
    347   if (const FunctionType *FD = T->getAs<FunctionType>())
    348     return MakeCXType(FD->getResultType(), GetTU(X));
    349 
    350   return MakeCXType(QualType(), GetTU(X));
    351 }
    352 
    353 CXType clang_getCursorResultType(CXCursor C) {
    354   if (clang_isDeclaration(C.kind)) {
    355     Decl *D = cxcursor::getCursorDecl(C);
    356     if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
    357       return MakeCXType(MD->getResultType(), cxcursor::getCursorTU(C));
    358 
    359     return clang_getResultType(clang_getCursorType(C));
    360   }
    361 
    362   return MakeCXType(QualType(), cxcursor::getCursorTU(C));
    363 }
    364 
    365 unsigned clang_isPODType(CXType X) {
    366   QualType T = GetQualType(X);
    367   if (!T.getTypePtrOrNull())
    368     return 0;
    369 
    370   CXTranslationUnit TU = GetTU(X);
    371   ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData);
    372 
    373   return T.isPODType(AU->getASTContext()) ? 1 : 0;
    374 }
    375 
    376 CXString clang_getDeclObjCTypeEncoding(CXCursor C) {
    377   if ((C.kind < CXCursor_FirstDecl) || (C.kind > CXCursor_LastDecl))
    378     return cxstring::createCXString("");
    379 
    380   Decl *D = static_cast<Decl*>(C.data[0]);
    381   CXTranslationUnit TU = static_cast<CXTranslationUnit>(C.data[2]);
    382   ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData);
    383   ASTContext &Ctx = AU->getASTContext();
    384   std::string encoding;
    385 
    386   if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))  {
    387     if (Ctx.getObjCEncodingForMethodDecl(OMD, encoding))
    388       return cxstring::createCXString("?");
    389   } else if (ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(D))
    390     Ctx.getObjCEncodingForPropertyDecl(OPD, NULL, encoding);
    391   else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
    392     Ctx.getObjCEncodingForFunctionDecl(FD, encoding);
    393   else {
    394     QualType Ty;
    395     if (TypeDecl *TD = dyn_cast<TypeDecl>(D))
    396       Ty = Ctx.getTypeDeclType(TD);
    397     if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
    398       Ty = VD->getType();
    399     else return cxstring::createCXString("?");
    400     Ctx.getObjCEncodingForType(Ty, encoding);
    401   }
    402 
    403   return cxstring::createCXString(encoding);
    404 }
    405 
    406 } // end: extern "C"
    407