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     TKCASE(ConstantArray);
     88     default:
     89       return CXType_Unexposed;
     90   }
     91 #undef TKCASE
     92 }
     93 
     94 
     95 CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) {
     96   CXTypeKind TK = GetTypeKind(T);
     97   CXType CT = { TK, { TK == CXType_Invalid ? 0 : T.getAsOpaquePtr(), TU }};
     98   return CT;
     99 }
    100 
    101 using cxtype::MakeCXType;
    102 
    103 static inline QualType GetQualType(CXType CT) {
    104   return QualType::getFromOpaquePtr(CT.data[0]);
    105 }
    106 
    107 static inline CXTranslationUnit GetTU(CXType CT) {
    108   return static_cast<CXTranslationUnit>(CT.data[1]);
    109 }
    110 
    111 extern "C" {
    112 
    113 CXType clang_getCursorType(CXCursor C) {
    114   using namespace cxcursor;
    115 
    116   CXTranslationUnit TU = cxcursor::getCursorTU(C);
    117   ASTContext &Context = static_cast<ASTUnit *>(TU->TUData)->getASTContext();
    118   if (clang_isExpression(C.kind)) {
    119     QualType T = cxcursor::getCursorExpr(C)->getType();
    120     return MakeCXType(T, TU);
    121   }
    122 
    123   if (clang_isDeclaration(C.kind)) {
    124     Decl *D = cxcursor::getCursorDecl(C);
    125 
    126     if (TypeDecl *TD = dyn_cast<TypeDecl>(D))
    127       return MakeCXType(Context.getTypeDeclType(TD), TU);
    128     if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
    129       return MakeCXType(Context.getObjCInterfaceType(ID), TU);
    130     if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
    131       return MakeCXType(VD->getType(), TU);
    132     if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D))
    133       return MakeCXType(PD->getType(), TU);
    134     if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
    135       return MakeCXType(FD->getType(), TU);
    136     return MakeCXType(QualType(), TU);
    137   }
    138 
    139   if (clang_isReference(C.kind)) {
    140     switch (C.kind) {
    141     case CXCursor_ObjCSuperClassRef: {
    142       QualType T
    143         = Context.getObjCInterfaceType(getCursorObjCSuperClassRef(C).first);
    144       return MakeCXType(T, TU);
    145     }
    146 
    147     case CXCursor_ObjCClassRef: {
    148       QualType T = Context.getObjCInterfaceType(getCursorObjCClassRef(C).first);
    149       return MakeCXType(T, TU);
    150     }
    151 
    152     case CXCursor_TypeRef: {
    153       QualType T = Context.getTypeDeclType(getCursorTypeRef(C).first);
    154       return MakeCXType(T, TU);
    155 
    156     }
    157 
    158     case CXCursor_CXXBaseSpecifier:
    159       return cxtype::MakeCXType(getCursorCXXBaseSpecifier(C)->getType(), TU);
    160 
    161     case CXCursor_ObjCProtocolRef:
    162     case CXCursor_TemplateRef:
    163     case CXCursor_NamespaceRef:
    164     case CXCursor_MemberRef:
    165     case CXCursor_OverloadedDeclRef:
    166     default:
    167       break;
    168     }
    169 
    170     return MakeCXType(QualType(), TU);
    171   }
    172 
    173   return MakeCXType(QualType(), TU);
    174 }
    175 
    176 CXType clang_getCanonicalType(CXType CT) {
    177   if (CT.kind == CXType_Invalid)
    178     return CT;
    179 
    180   QualType T = GetQualType(CT);
    181   CXTranslationUnit TU = GetTU(CT);
    182 
    183   if (T.isNull())
    184     return MakeCXType(QualType(), GetTU(CT));
    185 
    186   ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData);
    187   return MakeCXType(AU->getASTContext().getCanonicalType(T), TU);
    188 }
    189 
    190 unsigned clang_isConstQualifiedType(CXType CT) {
    191   QualType T = GetQualType(CT);
    192   return T.isLocalConstQualified();
    193 }
    194 
    195 unsigned clang_isVolatileQualifiedType(CXType CT) {
    196   QualType T = GetQualType(CT);
    197   return T.isLocalVolatileQualified();
    198 }
    199 
    200 unsigned clang_isRestrictQualifiedType(CXType CT) {
    201   QualType T = GetQualType(CT);
    202   return T.isLocalRestrictQualified();
    203 }
    204 
    205 CXType clang_getPointeeType(CXType CT) {
    206   QualType T = GetQualType(CT);
    207   const Type *TP = T.getTypePtrOrNull();
    208 
    209   if (!TP)
    210     return MakeCXType(QualType(), GetTU(CT));
    211 
    212   switch (TP->getTypeClass()) {
    213     case Type::Pointer:
    214       T = cast<PointerType>(TP)->getPointeeType();
    215       break;
    216     case Type::BlockPointer:
    217       T = cast<BlockPointerType>(TP)->getPointeeType();
    218       break;
    219     case Type::LValueReference:
    220     case Type::RValueReference:
    221       T = cast<ReferenceType>(TP)->getPointeeType();
    222       break;
    223     case Type::ObjCObjectPointer:
    224       T = cast<ObjCObjectPointerType>(TP)->getPointeeType();
    225       break;
    226     default:
    227       T = QualType();
    228       break;
    229   }
    230   return MakeCXType(T, GetTU(CT));
    231 }
    232 
    233 CXCursor clang_getTypeDeclaration(CXType CT) {
    234   if (CT.kind == CXType_Invalid)
    235     return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
    236 
    237   QualType T = GetQualType(CT);
    238   const Type *TP = T.getTypePtrOrNull();
    239 
    240   if (!TP)
    241     return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
    242 
    243   Decl *D = 0;
    244 
    245 try_again:
    246   switch (TP->getTypeClass()) {
    247   case Type::Typedef:
    248     D = cast<TypedefType>(TP)->getDecl();
    249     break;
    250   case Type::ObjCObject:
    251     D = cast<ObjCObjectType>(TP)->getInterface();
    252     break;
    253   case Type::ObjCInterface:
    254     D = cast<ObjCInterfaceType>(TP)->getDecl();
    255     break;
    256   case Type::Record:
    257   case Type::Enum:
    258     D = cast<TagType>(TP)->getDecl();
    259     break;
    260   case Type::TemplateSpecialization:
    261     if (const RecordType *Record = TP->getAs<RecordType>())
    262       D = Record->getDecl();
    263     else
    264       D = cast<TemplateSpecializationType>(TP)->getTemplateName()
    265                                                          .getAsTemplateDecl();
    266     break;
    267 
    268   case Type::InjectedClassName:
    269     D = cast<InjectedClassNameType>(TP)->getDecl();
    270     break;
    271 
    272   // FIXME: Template type parameters!
    273 
    274   case Type::Elaborated:
    275     TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull();
    276     goto try_again;
    277 
    278   default:
    279     break;
    280   }
    281 
    282   if (!D)
    283     return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
    284 
    285   return cxcursor::MakeCXCursor(D, GetTU(CT));
    286 }
    287 
    288 CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
    289   const char *s = 0;
    290 #define TKIND(X) case CXType_##X: s = ""  #X  ""; break
    291   switch (K) {
    292     TKIND(Invalid);
    293     TKIND(Unexposed);
    294     TKIND(Void);
    295     TKIND(Bool);
    296     TKIND(Char_U);
    297     TKIND(UChar);
    298     TKIND(Char16);
    299     TKIND(Char32);
    300     TKIND(UShort);
    301     TKIND(UInt);
    302     TKIND(ULong);
    303     TKIND(ULongLong);
    304     TKIND(UInt128);
    305     TKIND(Char_S);
    306     TKIND(SChar);
    307     case CXType_WChar: s = "WChar"; break;
    308     TKIND(Short);
    309     TKIND(Int);
    310     TKIND(Long);
    311     TKIND(LongLong);
    312     TKIND(Int128);
    313     TKIND(Float);
    314     TKIND(Double);
    315     TKIND(LongDouble);
    316     TKIND(NullPtr);
    317     TKIND(Overload);
    318     TKIND(Dependent);
    319     TKIND(ObjCId);
    320     TKIND(ObjCClass);
    321     TKIND(ObjCSel);
    322     TKIND(Complex);
    323     TKIND(Pointer);
    324     TKIND(BlockPointer);
    325     TKIND(LValueReference);
    326     TKIND(RValueReference);
    327     TKIND(Record);
    328     TKIND(Enum);
    329     TKIND(Typedef);
    330     TKIND(ObjCInterface);
    331     TKIND(ObjCObjectPointer);
    332     TKIND(FunctionNoProto);
    333     TKIND(FunctionProto);
    334     TKIND(ConstantArray);
    335   }
    336 #undef TKIND
    337   return cxstring::createCXString(s);
    338 }
    339 
    340 unsigned clang_equalTypes(CXType A, CXType B) {
    341   return A.data[0] == B.data[0] && A.data[1] == B.data[1];;
    342 }
    343 
    344 CXType clang_getResultType(CXType X) {
    345   QualType T = GetQualType(X);
    346   if (!T.getTypePtrOrNull())
    347     return MakeCXType(QualType(), GetTU(X));
    348 
    349   if (const FunctionType *FD = T->getAs<FunctionType>())
    350     return MakeCXType(FD->getResultType(), GetTU(X));
    351 
    352   return MakeCXType(QualType(), GetTU(X));
    353 }
    354 
    355 CXType clang_getCursorResultType(CXCursor C) {
    356   if (clang_isDeclaration(C.kind)) {
    357     Decl *D = cxcursor::getCursorDecl(C);
    358     if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
    359       return MakeCXType(MD->getResultType(), cxcursor::getCursorTU(C));
    360 
    361     return clang_getResultType(clang_getCursorType(C));
    362   }
    363 
    364   return MakeCXType(QualType(), cxcursor::getCursorTU(C));
    365 }
    366 
    367 unsigned clang_isPODType(CXType X) {
    368   QualType T = GetQualType(X);
    369   if (!T.getTypePtrOrNull())
    370     return 0;
    371 
    372   CXTranslationUnit TU = GetTU(X);
    373   ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData);
    374 
    375   return T.isPODType(AU->getASTContext()) ? 1 : 0;
    376 }
    377 
    378 CXType clang_getArrayElementType(CXType CT) {
    379   QualType ET = QualType();
    380   QualType T = GetQualType(CT);
    381   const Type *TP = T.getTypePtrOrNull();
    382 
    383   if (TP) {
    384     switch (TP->getTypeClass()) {
    385     case Type::ConstantArray:
    386       ET = cast<ConstantArrayType> (TP)->getElementType();
    387       break;
    388     default:
    389       break;
    390     }
    391   }
    392   return MakeCXType(ET, GetTU(CT));
    393 }
    394 
    395 long long clang_getArraySize(CXType CT) {
    396   long long result = -1;
    397   QualType T = GetQualType(CT);
    398   const Type *TP = T.getTypePtrOrNull();
    399 
    400   if (TP) {
    401     switch (TP->getTypeClass()) {
    402     case Type::ConstantArray:
    403       result = cast<ConstantArrayType> (TP)->getSize().getSExtValue();
    404       break;
    405     default:
    406       break;
    407     }
    408   }
    409   return result;
    410 }
    411 
    412 CXString clang_getDeclObjCTypeEncoding(CXCursor C) {
    413   if ((C.kind < CXCursor_FirstDecl) || (C.kind > CXCursor_LastDecl))
    414     return cxstring::createCXString("");
    415 
    416   Decl *D = static_cast<Decl*>(C.data[0]);
    417   CXTranslationUnit TU = static_cast<CXTranslationUnit>(C.data[2]);
    418   ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData);
    419   ASTContext &Ctx = AU->getASTContext();
    420   std::string encoding;
    421 
    422   if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))  {
    423     if (Ctx.getObjCEncodingForMethodDecl(OMD, encoding))
    424       return cxstring::createCXString("?");
    425   } else if (ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(D))
    426     Ctx.getObjCEncodingForPropertyDecl(OPD, NULL, encoding);
    427   else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
    428     Ctx.getObjCEncodingForFunctionDecl(FD, encoding);
    429   else {
    430     QualType Ty;
    431     if (TypeDecl *TD = dyn_cast<TypeDecl>(D))
    432       Ty = Ctx.getTypeDeclType(TD);
    433     if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
    434       Ty = VD->getType();
    435     else return cxstring::createCXString("?");
    436     Ctx.getObjCEncodingForType(Ty, encoding);
    437   }
    438 
    439   return cxstring::createCXString(encoding);
    440 }
    441 
    442 } // end: extern "C"
    443