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 "CXCursor.h"
     16 #include "CXString.h"
     17 #include "CXTranslationUnit.h"
     18 #include "CXType.h"
     19 #include "clang/AST/Decl.h"
     20 #include "clang/AST/DeclObjC.h"
     21 #include "clang/AST/DeclTemplate.h"
     22 #include "clang/AST/Expr.h"
     23 #include "clang/AST/Type.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     TKCASE(Vector);
     89     default:
     90       return CXType_Unexposed;
     91   }
     92 #undef TKCASE
     93 }
     94 
     95 
     96 CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) {
     97   CXTypeKind TK = CXType_Invalid;
     98 
     99   if (TU && !T.isNull()) {
    100     ASTContext &Ctx = cxtu::getASTUnit(TU)->getASTContext();
    101     if (Ctx.getLangOpts().ObjC1) {
    102       QualType UnqualT = T.getUnqualifiedType();
    103       if (Ctx.isObjCIdType(UnqualT))
    104         TK = CXType_ObjCId;
    105       else if (Ctx.isObjCClassType(UnqualT))
    106         TK = CXType_ObjCClass;
    107       else if (Ctx.isObjCSelType(UnqualT))
    108         TK = CXType_ObjCSel;
    109     }
    110   }
    111   if (TK == CXType_Invalid)
    112     TK = GetTypeKind(T);
    113 
    114   CXType CT = { TK, { TK == CXType_Invalid ? 0 : T.getAsOpaquePtr(), TU }};
    115   return CT;
    116 }
    117 
    118 using cxtype::MakeCXType;
    119 
    120 static inline QualType GetQualType(CXType CT) {
    121   return QualType::getFromOpaquePtr(CT.data[0]);
    122 }
    123 
    124 static inline CXTranslationUnit GetTU(CXType CT) {
    125   return static_cast<CXTranslationUnit>(CT.data[1]);
    126 }
    127 
    128 extern "C" {
    129 
    130 CXType clang_getCursorType(CXCursor C) {
    131   using namespace cxcursor;
    132 
    133   CXTranslationUnit TU = cxcursor::getCursorTU(C);
    134   if (!TU)
    135     return MakeCXType(QualType(), TU);
    136 
    137   ASTContext &Context = cxtu::getASTUnit(TU)->getASTContext();
    138   if (clang_isExpression(C.kind)) {
    139     QualType T = cxcursor::getCursorExpr(C)->getType();
    140     return MakeCXType(T, TU);
    141   }
    142 
    143   if (clang_isDeclaration(C.kind)) {
    144     const Decl *D = cxcursor::getCursorDecl(C);
    145     if (!D)
    146       return MakeCXType(QualType(), TU);
    147 
    148     if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
    149       return MakeCXType(Context.getTypeDeclType(TD), TU);
    150     if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
    151       return MakeCXType(Context.getObjCInterfaceType(ID), TU);
    152     if (const ValueDecl *VD = dyn_cast<ValueDecl>(D))
    153       return MakeCXType(VD->getType(), TU);
    154     if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D))
    155       return MakeCXType(PD->getType(), TU);
    156     if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
    157       return MakeCXType(FD->getType(), TU);
    158     return MakeCXType(QualType(), TU);
    159   }
    160 
    161   if (clang_isReference(C.kind)) {
    162     switch (C.kind) {
    163     case CXCursor_ObjCSuperClassRef: {
    164       QualType T
    165         = Context.getObjCInterfaceType(getCursorObjCSuperClassRef(C).first);
    166       return MakeCXType(T, TU);
    167     }
    168 
    169     case CXCursor_ObjCClassRef: {
    170       QualType T = Context.getObjCInterfaceType(getCursorObjCClassRef(C).first);
    171       return MakeCXType(T, TU);
    172     }
    173 
    174     case CXCursor_TypeRef: {
    175       QualType T = Context.getTypeDeclType(getCursorTypeRef(C).first);
    176       return MakeCXType(T, TU);
    177 
    178     }
    179 
    180     case CXCursor_CXXBaseSpecifier:
    181       return cxtype::MakeCXType(getCursorCXXBaseSpecifier(C)->getType(), TU);
    182 
    183     case CXCursor_MemberRef:
    184       return cxtype::MakeCXType(getCursorMemberRef(C).first->getType(), TU);
    185 
    186     case CXCursor_VariableRef:
    187       return cxtype::MakeCXType(getCursorVariableRef(C).first->getType(), TU);
    188 
    189     case CXCursor_ObjCProtocolRef:
    190     case CXCursor_TemplateRef:
    191     case CXCursor_NamespaceRef:
    192     case CXCursor_OverloadedDeclRef:
    193     default:
    194       break;
    195     }
    196 
    197     return MakeCXType(QualType(), TU);
    198   }
    199 
    200   return MakeCXType(QualType(), TU);
    201 }
    202 
    203 CXString clang_getTypeSpelling(CXType CT) {
    204   QualType T = GetQualType(CT);
    205   if (T.isNull())
    206     return cxstring::createEmpty();
    207 
    208   CXTranslationUnit TU = GetTU(CT);
    209   SmallString<64> Str;
    210   llvm::raw_svector_ostream OS(Str);
    211   PrintingPolicy PP(cxtu::getASTUnit(TU)->getASTContext().getLangOpts());
    212 
    213   T.print(OS, PP);
    214 
    215   return cxstring::createDup(OS.str());
    216 }
    217 
    218 CXType clang_getTypedefDeclUnderlyingType(CXCursor C) {
    219   using namespace cxcursor;
    220   CXTranslationUnit TU = cxcursor::getCursorTU(C);
    221 
    222   if (clang_isDeclaration(C.kind)) {
    223     const Decl *D = cxcursor::getCursorDecl(C);
    224 
    225     if (const TypedefNameDecl *TD = dyn_cast_or_null<TypedefNameDecl>(D)) {
    226       QualType T = TD->getUnderlyingType();
    227       return MakeCXType(T, TU);
    228     }
    229 
    230     return MakeCXType(QualType(), TU);
    231   }
    232 
    233   return MakeCXType(QualType(), TU);
    234 }
    235 
    236 CXType clang_getEnumDeclIntegerType(CXCursor C) {
    237   using namespace cxcursor;
    238   CXTranslationUnit TU = cxcursor::getCursorTU(C);
    239 
    240   if (clang_isDeclaration(C.kind)) {
    241     const Decl *D = cxcursor::getCursorDecl(C);
    242 
    243     if (const EnumDecl *TD = dyn_cast_or_null<EnumDecl>(D)) {
    244       QualType T = TD->getIntegerType();
    245       return MakeCXType(T, TU);
    246     }
    247 
    248     return MakeCXType(QualType(), TU);
    249   }
    250 
    251   return MakeCXType(QualType(), TU);
    252 }
    253 
    254 long long clang_getEnumConstantDeclValue(CXCursor C) {
    255   using namespace cxcursor;
    256 
    257   if (clang_isDeclaration(C.kind)) {
    258     const Decl *D = cxcursor::getCursorDecl(C);
    259 
    260     if (const EnumConstantDecl *TD = dyn_cast_or_null<EnumConstantDecl>(D)) {
    261       return TD->getInitVal().getSExtValue();
    262     }
    263 
    264     return LLONG_MIN;
    265   }
    266 
    267   return LLONG_MIN;
    268 }
    269 
    270 unsigned long long clang_getEnumConstantDeclUnsignedValue(CXCursor C) {
    271   using namespace cxcursor;
    272 
    273   if (clang_isDeclaration(C.kind)) {
    274     const Decl *D = cxcursor::getCursorDecl(C);
    275 
    276     if (const EnumConstantDecl *TD = dyn_cast_or_null<EnumConstantDecl>(D)) {
    277       return TD->getInitVal().getZExtValue();
    278     }
    279 
    280     return ULLONG_MAX;
    281   }
    282 
    283   return ULLONG_MAX;
    284 }
    285 
    286 int clang_getFieldDeclBitWidth(CXCursor C) {
    287   using namespace cxcursor;
    288 
    289   if (clang_isDeclaration(C.kind)) {
    290     const Decl *D = getCursorDecl(C);
    291 
    292     if (const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(D)) {
    293       if (FD->isBitField())
    294         return FD->getBitWidthValue(getCursorContext(C));
    295     }
    296   }
    297 
    298   return -1;
    299 }
    300 
    301 CXType clang_getCanonicalType(CXType CT) {
    302   if (CT.kind == CXType_Invalid)
    303     return CT;
    304 
    305   QualType T = GetQualType(CT);
    306   CXTranslationUnit TU = GetTU(CT);
    307 
    308   if (T.isNull())
    309     return MakeCXType(QualType(), GetTU(CT));
    310 
    311   return MakeCXType(cxtu::getASTUnit(TU)->getASTContext()
    312                         .getCanonicalType(T),
    313                     TU);
    314 }
    315 
    316 unsigned clang_isConstQualifiedType(CXType CT) {
    317   QualType T = GetQualType(CT);
    318   return T.isLocalConstQualified();
    319 }
    320 
    321 unsigned clang_isVolatileQualifiedType(CXType CT) {
    322   QualType T = GetQualType(CT);
    323   return T.isLocalVolatileQualified();
    324 }
    325 
    326 unsigned clang_isRestrictQualifiedType(CXType CT) {
    327   QualType T = GetQualType(CT);
    328   return T.isLocalRestrictQualified();
    329 }
    330 
    331 CXType clang_getPointeeType(CXType CT) {
    332   QualType T = GetQualType(CT);
    333   const Type *TP = T.getTypePtrOrNull();
    334 
    335   if (!TP)
    336     return MakeCXType(QualType(), GetTU(CT));
    337 
    338   switch (TP->getTypeClass()) {
    339     case Type::Pointer:
    340       T = cast<PointerType>(TP)->getPointeeType();
    341       break;
    342     case Type::BlockPointer:
    343       T = cast<BlockPointerType>(TP)->getPointeeType();
    344       break;
    345     case Type::LValueReference:
    346     case Type::RValueReference:
    347       T = cast<ReferenceType>(TP)->getPointeeType();
    348       break;
    349     case Type::ObjCObjectPointer:
    350       T = cast<ObjCObjectPointerType>(TP)->getPointeeType();
    351       break;
    352     default:
    353       T = QualType();
    354       break;
    355   }
    356   return MakeCXType(T, GetTU(CT));
    357 }
    358 
    359 CXCursor clang_getTypeDeclaration(CXType CT) {
    360   if (CT.kind == CXType_Invalid)
    361     return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
    362 
    363   QualType T = GetQualType(CT);
    364   const Type *TP = T.getTypePtrOrNull();
    365 
    366   if (!TP)
    367     return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
    368 
    369   Decl *D = 0;
    370 
    371 try_again:
    372   switch (TP->getTypeClass()) {
    373   case Type::Typedef:
    374     D = cast<TypedefType>(TP)->getDecl();
    375     break;
    376   case Type::ObjCObject:
    377     D = cast<ObjCObjectType>(TP)->getInterface();
    378     break;
    379   case Type::ObjCInterface:
    380     D = cast<ObjCInterfaceType>(TP)->getDecl();
    381     break;
    382   case Type::Record:
    383   case Type::Enum:
    384     D = cast<TagType>(TP)->getDecl();
    385     break;
    386   case Type::TemplateSpecialization:
    387     if (const RecordType *Record = TP->getAs<RecordType>())
    388       D = Record->getDecl();
    389     else
    390       D = cast<TemplateSpecializationType>(TP)->getTemplateName()
    391                                                          .getAsTemplateDecl();
    392     break;
    393 
    394   case Type::InjectedClassName:
    395     D = cast<InjectedClassNameType>(TP)->getDecl();
    396     break;
    397 
    398   // FIXME: Template type parameters!
    399 
    400   case Type::Elaborated:
    401     TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull();
    402     goto try_again;
    403 
    404   default:
    405     break;
    406   }
    407 
    408   if (!D)
    409     return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
    410 
    411   return cxcursor::MakeCXCursor(D, GetTU(CT));
    412 }
    413 
    414 CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
    415   const char *s = 0;
    416 #define TKIND(X) case CXType_##X: s = ""  #X  ""; break
    417   switch (K) {
    418     TKIND(Invalid);
    419     TKIND(Unexposed);
    420     TKIND(Void);
    421     TKIND(Bool);
    422     TKIND(Char_U);
    423     TKIND(UChar);
    424     TKIND(Char16);
    425     TKIND(Char32);
    426     TKIND(UShort);
    427     TKIND(UInt);
    428     TKIND(ULong);
    429     TKIND(ULongLong);
    430     TKIND(UInt128);
    431     TKIND(Char_S);
    432     TKIND(SChar);
    433     case CXType_WChar: s = "WChar"; break;
    434     TKIND(Short);
    435     TKIND(Int);
    436     TKIND(Long);
    437     TKIND(LongLong);
    438     TKIND(Int128);
    439     TKIND(Float);
    440     TKIND(Double);
    441     TKIND(LongDouble);
    442     TKIND(NullPtr);
    443     TKIND(Overload);
    444     TKIND(Dependent);
    445     TKIND(ObjCId);
    446     TKIND(ObjCClass);
    447     TKIND(ObjCSel);
    448     TKIND(Complex);
    449     TKIND(Pointer);
    450     TKIND(BlockPointer);
    451     TKIND(LValueReference);
    452     TKIND(RValueReference);
    453     TKIND(Record);
    454     TKIND(Enum);
    455     TKIND(Typedef);
    456     TKIND(ObjCInterface);
    457     TKIND(ObjCObjectPointer);
    458     TKIND(FunctionNoProto);
    459     TKIND(FunctionProto);
    460     TKIND(ConstantArray);
    461     TKIND(Vector);
    462   }
    463 #undef TKIND
    464   return cxstring::createRef(s);
    465 }
    466 
    467 unsigned clang_equalTypes(CXType A, CXType B) {
    468   return A.data[0] == B.data[0] && A.data[1] == B.data[1];;
    469 }
    470 
    471 unsigned clang_isFunctionTypeVariadic(CXType X) {
    472   QualType T = GetQualType(X);
    473   if (T.isNull())
    474     return 0;
    475 
    476   if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>())
    477     return (unsigned)FD->isVariadic();
    478 
    479   if (T->getAs<FunctionNoProtoType>())
    480     return 1;
    481 
    482   return 0;
    483 }
    484 
    485 CXCallingConv clang_getFunctionTypeCallingConv(CXType X) {
    486   QualType T = GetQualType(X);
    487   if (T.isNull())
    488     return CXCallingConv_Invalid;
    489 
    490   if (const FunctionType *FD = T->getAs<FunctionType>()) {
    491 #define TCALLINGCONV(X) case CC_##X: return CXCallingConv_##X
    492     switch (FD->getCallConv()) {
    493       TCALLINGCONV(Default);
    494       TCALLINGCONV(C);
    495       TCALLINGCONV(X86StdCall);
    496       TCALLINGCONV(X86FastCall);
    497       TCALLINGCONV(X86ThisCall);
    498       TCALLINGCONV(X86Pascal);
    499       TCALLINGCONV(AAPCS);
    500       TCALLINGCONV(AAPCS_VFP);
    501       TCALLINGCONV(PnaclCall);
    502       TCALLINGCONV(IntelOclBicc);
    503     }
    504 #undef TCALLINGCONV
    505   }
    506 
    507   return CXCallingConv_Invalid;
    508 }
    509 
    510 int clang_getNumArgTypes(CXType X) {
    511   QualType T = GetQualType(X);
    512   if (T.isNull())
    513     return -1;
    514 
    515   if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) {
    516     return FD->getNumArgs();
    517   }
    518 
    519   if (T->getAs<FunctionNoProtoType>()) {
    520     return 0;
    521   }
    522 
    523   return -1;
    524 }
    525 
    526 CXType clang_getArgType(CXType X, unsigned i) {
    527   QualType T = GetQualType(X);
    528   if (T.isNull())
    529     return MakeCXType(QualType(), GetTU(X));
    530 
    531   if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) {
    532     unsigned numArgs = FD->getNumArgs();
    533     if (i >= numArgs)
    534       return MakeCXType(QualType(), GetTU(X));
    535 
    536     return MakeCXType(FD->getArgType(i), GetTU(X));
    537   }
    538 
    539   return MakeCXType(QualType(), GetTU(X));
    540 }
    541 
    542 CXType clang_getResultType(CXType X) {
    543   QualType T = GetQualType(X);
    544   if (T.isNull())
    545     return MakeCXType(QualType(), GetTU(X));
    546 
    547   if (const FunctionType *FD = T->getAs<FunctionType>())
    548     return MakeCXType(FD->getResultType(), GetTU(X));
    549 
    550   return MakeCXType(QualType(), GetTU(X));
    551 }
    552 
    553 CXType clang_getCursorResultType(CXCursor C) {
    554   if (clang_isDeclaration(C.kind)) {
    555     const Decl *D = cxcursor::getCursorDecl(C);
    556     if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
    557       return MakeCXType(MD->getResultType(), cxcursor::getCursorTU(C));
    558 
    559     return clang_getResultType(clang_getCursorType(C));
    560   }
    561 
    562   return MakeCXType(QualType(), cxcursor::getCursorTU(C));
    563 }
    564 
    565 unsigned clang_isPODType(CXType X) {
    566   QualType T = GetQualType(X);
    567   if (T.isNull())
    568     return 0;
    569 
    570   CXTranslationUnit TU = GetTU(X);
    571 
    572   return T.isPODType(cxtu::getASTUnit(TU)->getASTContext()) ? 1 : 0;
    573 }
    574 
    575 CXType clang_getElementType(CXType CT) {
    576   QualType ET = QualType();
    577   QualType T = GetQualType(CT);
    578   const Type *TP = T.getTypePtrOrNull();
    579 
    580   if (TP) {
    581     switch (TP->getTypeClass()) {
    582     case Type::ConstantArray:
    583       ET = cast<ConstantArrayType> (TP)->getElementType();
    584       break;
    585     case Type::Vector:
    586       ET = cast<VectorType> (TP)->getElementType();
    587       break;
    588     case Type::Complex:
    589       ET = cast<ComplexType> (TP)->getElementType();
    590       break;
    591     default:
    592       break;
    593     }
    594   }
    595   return MakeCXType(ET, GetTU(CT));
    596 }
    597 
    598 long long clang_getNumElements(CXType CT) {
    599   long long result = -1;
    600   QualType T = GetQualType(CT);
    601   const Type *TP = T.getTypePtrOrNull();
    602 
    603   if (TP) {
    604     switch (TP->getTypeClass()) {
    605     case Type::ConstantArray:
    606       result = cast<ConstantArrayType> (TP)->getSize().getSExtValue();
    607       break;
    608     case Type::Vector:
    609       result = cast<VectorType> (TP)->getNumElements();
    610       break;
    611     default:
    612       break;
    613     }
    614   }
    615   return result;
    616 }
    617 
    618 CXType clang_getArrayElementType(CXType CT) {
    619   QualType ET = QualType();
    620   QualType T = GetQualType(CT);
    621   const Type *TP = T.getTypePtrOrNull();
    622 
    623   if (TP) {
    624     switch (TP->getTypeClass()) {
    625     case Type::ConstantArray:
    626       ET = cast<ConstantArrayType> (TP)->getElementType();
    627       break;
    628     default:
    629       break;
    630     }
    631   }
    632   return MakeCXType(ET, GetTU(CT));
    633 }
    634 
    635 long long clang_getArraySize(CXType CT) {
    636   long long result = -1;
    637   QualType T = GetQualType(CT);
    638   const Type *TP = T.getTypePtrOrNull();
    639 
    640   if (TP) {
    641     switch (TP->getTypeClass()) {
    642     case Type::ConstantArray:
    643       result = cast<ConstantArrayType> (TP)->getSize().getSExtValue();
    644       break;
    645     default:
    646       break;
    647     }
    648   }
    649   return result;
    650 }
    651 
    652 CXString clang_getDeclObjCTypeEncoding(CXCursor C) {
    653   if (!clang_isDeclaration(C.kind))
    654     return cxstring::createEmpty();
    655 
    656   const Decl *D = cxcursor::getCursorDecl(C);
    657   ASTContext &Ctx = cxcursor::getCursorContext(C);
    658   std::string encoding;
    659 
    660   if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))  {
    661     if (Ctx.getObjCEncodingForMethodDecl(OMD, encoding))
    662       return cxstring::createRef("?");
    663   } else if (const ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(D))
    664     Ctx.getObjCEncodingForPropertyDecl(OPD, NULL, encoding);
    665   else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
    666     Ctx.getObjCEncodingForFunctionDecl(FD, encoding);
    667   else {
    668     QualType Ty;
    669     if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
    670       Ty = Ctx.getTypeDeclType(TD);
    671     if (const ValueDecl *VD = dyn_cast<ValueDecl>(D))
    672       Ty = VD->getType();
    673     else return cxstring::createRef("?");
    674     Ctx.getObjCEncodingForType(Ty, encoding);
    675   }
    676 
    677   return cxstring::createDup(encoding);
    678 }
    679 
    680 } // end: extern "C"
    681