CXType.cpp revision e22339c44bb28d71a2cc97c840d3da0c4bdb4909
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
26using namespace clang;
27
28static 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
66static 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
96CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) {
97  CXTypeKind TK = CXType_Invalid;
98
99  if (TU && !T.isNull()) {
100    ASTContext &Ctx = static_cast<ASTUnit *>(TU->TUData)->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
118using cxtype::MakeCXType;
119
120static inline QualType GetQualType(CXType CT) {
121  return QualType::getFromOpaquePtr(CT.data[0]);
122}
123
124static inline CXTranslationUnit GetTU(CXType CT) {
125  return static_cast<CXTranslationUnit>(CT.data[1]);
126}
127
128extern "C" {
129
130CXType 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 = static_cast<ASTUnit *>(TU->TUData)->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
203CXType clang_getTypedefDeclUnderlyingType(CXCursor C) {
204  using namespace cxcursor;
205  CXTranslationUnit TU = cxcursor::getCursorTU(C);
206
207  if (clang_isDeclaration(C.kind)) {
208    const Decl *D = cxcursor::getCursorDecl(C);
209
210    if (const TypedefNameDecl *TD = dyn_cast_or_null<TypedefNameDecl>(D)) {
211      QualType T = TD->getUnderlyingType();
212      return MakeCXType(T, TU);
213    }
214
215    return MakeCXType(QualType(), TU);
216  }
217
218  return MakeCXType(QualType(), TU);
219}
220
221CXType clang_getEnumDeclIntegerType(CXCursor C) {
222  using namespace cxcursor;
223  CXTranslationUnit TU = cxcursor::getCursorTU(C);
224
225  if (clang_isDeclaration(C.kind)) {
226    const Decl *D = cxcursor::getCursorDecl(C);
227
228    if (const EnumDecl *TD = dyn_cast_or_null<EnumDecl>(D)) {
229      QualType T = TD->getIntegerType();
230      return MakeCXType(T, TU);
231    }
232
233    return MakeCXType(QualType(), TU);
234  }
235
236  return MakeCXType(QualType(), TU);
237}
238
239long long clang_getEnumConstantDeclValue(CXCursor C) {
240  using namespace cxcursor;
241
242  if (clang_isDeclaration(C.kind)) {
243    const Decl *D = cxcursor::getCursorDecl(C);
244
245    if (const EnumConstantDecl *TD = dyn_cast_or_null<EnumConstantDecl>(D)) {
246      return TD->getInitVal().getSExtValue();
247    }
248
249    return LLONG_MIN;
250  }
251
252  return LLONG_MIN;
253}
254
255unsigned long long clang_getEnumConstantDeclUnsignedValue(CXCursor C) {
256  using namespace cxcursor;
257
258  if (clang_isDeclaration(C.kind)) {
259    const Decl *D = cxcursor::getCursorDecl(C);
260
261    if (const EnumConstantDecl *TD = dyn_cast_or_null<EnumConstantDecl>(D)) {
262      return TD->getInitVal().getZExtValue();
263    }
264
265    return ULLONG_MAX;
266  }
267
268  return ULLONG_MAX;
269}
270
271int clang_getFieldDeclBitWidth(CXCursor C) {
272  using namespace cxcursor;
273
274  if (clang_isDeclaration(C.kind)) {
275    const Decl *D = getCursorDecl(C);
276
277    if (const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(D)) {
278      if (FD->isBitField())
279        return FD->getBitWidthValue(getCursorContext(C));
280    }
281  }
282
283  return -1;
284}
285
286CXType clang_getCanonicalType(CXType CT) {
287  if (CT.kind == CXType_Invalid)
288    return CT;
289
290  QualType T = GetQualType(CT);
291  CXTranslationUnit TU = GetTU(CT);
292
293  if (T.isNull())
294    return MakeCXType(QualType(), GetTU(CT));
295
296  ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData);
297  return MakeCXType(AU->getASTContext().getCanonicalType(T), TU);
298}
299
300unsigned clang_isConstQualifiedType(CXType CT) {
301  QualType T = GetQualType(CT);
302  return T.isLocalConstQualified();
303}
304
305unsigned clang_isVolatileQualifiedType(CXType CT) {
306  QualType T = GetQualType(CT);
307  return T.isLocalVolatileQualified();
308}
309
310unsigned clang_isRestrictQualifiedType(CXType CT) {
311  QualType T = GetQualType(CT);
312  return T.isLocalRestrictQualified();
313}
314
315CXType clang_getPointeeType(CXType CT) {
316  QualType T = GetQualType(CT);
317  const Type *TP = T.getTypePtrOrNull();
318
319  if (!TP)
320    return MakeCXType(QualType(), GetTU(CT));
321
322  switch (TP->getTypeClass()) {
323    case Type::Pointer:
324      T = cast<PointerType>(TP)->getPointeeType();
325      break;
326    case Type::BlockPointer:
327      T = cast<BlockPointerType>(TP)->getPointeeType();
328      break;
329    case Type::LValueReference:
330    case Type::RValueReference:
331      T = cast<ReferenceType>(TP)->getPointeeType();
332      break;
333    case Type::ObjCObjectPointer:
334      T = cast<ObjCObjectPointerType>(TP)->getPointeeType();
335      break;
336    default:
337      T = QualType();
338      break;
339  }
340  return MakeCXType(T, GetTU(CT));
341}
342
343CXCursor clang_getTypeDeclaration(CXType CT) {
344  if (CT.kind == CXType_Invalid)
345    return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
346
347  QualType T = GetQualType(CT);
348  const Type *TP = T.getTypePtrOrNull();
349
350  if (!TP)
351    return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
352
353  Decl *D = 0;
354
355try_again:
356  switch (TP->getTypeClass()) {
357  case Type::Typedef:
358    D = cast<TypedefType>(TP)->getDecl();
359    break;
360  case Type::ObjCObject:
361    D = cast<ObjCObjectType>(TP)->getInterface();
362    break;
363  case Type::ObjCInterface:
364    D = cast<ObjCInterfaceType>(TP)->getDecl();
365    break;
366  case Type::Record:
367  case Type::Enum:
368    D = cast<TagType>(TP)->getDecl();
369    break;
370  case Type::TemplateSpecialization:
371    if (const RecordType *Record = TP->getAs<RecordType>())
372      D = Record->getDecl();
373    else
374      D = cast<TemplateSpecializationType>(TP)->getTemplateName()
375                                                         .getAsTemplateDecl();
376    break;
377
378  case Type::InjectedClassName:
379    D = cast<InjectedClassNameType>(TP)->getDecl();
380    break;
381
382  // FIXME: Template type parameters!
383
384  case Type::Elaborated:
385    TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull();
386    goto try_again;
387
388  default:
389    break;
390  }
391
392  if (!D)
393    return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
394
395  return cxcursor::MakeCXCursor(D, GetTU(CT));
396}
397
398CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
399  const char *s = 0;
400#define TKIND(X) case CXType_##X: s = ""  #X  ""; break
401  switch (K) {
402    TKIND(Invalid);
403    TKIND(Unexposed);
404    TKIND(Void);
405    TKIND(Bool);
406    TKIND(Char_U);
407    TKIND(UChar);
408    TKIND(Char16);
409    TKIND(Char32);
410    TKIND(UShort);
411    TKIND(UInt);
412    TKIND(ULong);
413    TKIND(ULongLong);
414    TKIND(UInt128);
415    TKIND(Char_S);
416    TKIND(SChar);
417    case CXType_WChar: s = "WChar"; break;
418    TKIND(Short);
419    TKIND(Int);
420    TKIND(Long);
421    TKIND(LongLong);
422    TKIND(Int128);
423    TKIND(Float);
424    TKIND(Double);
425    TKIND(LongDouble);
426    TKIND(NullPtr);
427    TKIND(Overload);
428    TKIND(Dependent);
429    TKIND(ObjCId);
430    TKIND(ObjCClass);
431    TKIND(ObjCSel);
432    TKIND(Complex);
433    TKIND(Pointer);
434    TKIND(BlockPointer);
435    TKIND(LValueReference);
436    TKIND(RValueReference);
437    TKIND(Record);
438    TKIND(Enum);
439    TKIND(Typedef);
440    TKIND(ObjCInterface);
441    TKIND(ObjCObjectPointer);
442    TKIND(FunctionNoProto);
443    TKIND(FunctionProto);
444    TKIND(ConstantArray);
445    TKIND(Vector);
446  }
447#undef TKIND
448  return cxstring::createCXString(s);
449}
450
451unsigned clang_equalTypes(CXType A, CXType B) {
452  return A.data[0] == B.data[0] && A.data[1] == B.data[1];;
453}
454
455unsigned clang_isFunctionTypeVariadic(CXType X) {
456  QualType T = GetQualType(X);
457  if (T.isNull())
458    return 0;
459
460  if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>())
461    return (unsigned)FD->isVariadic();
462
463  if (T->getAs<FunctionNoProtoType>())
464    return 1;
465
466  return 0;
467}
468
469CXCallingConv clang_getFunctionTypeCallingConv(CXType X) {
470  QualType T = GetQualType(X);
471  if (T.isNull())
472    return CXCallingConv_Invalid;
473
474  if (const FunctionType *FD = T->getAs<FunctionType>()) {
475#define TCALLINGCONV(X) case CC_##X: return CXCallingConv_##X
476    switch (FD->getCallConv()) {
477      TCALLINGCONV(Default);
478      TCALLINGCONV(C);
479      TCALLINGCONV(X86StdCall);
480      TCALLINGCONV(X86FastCall);
481      TCALLINGCONV(X86ThisCall);
482      TCALLINGCONV(X86Pascal);
483      TCALLINGCONV(AAPCS);
484      TCALLINGCONV(AAPCS_VFP);
485      TCALLINGCONV(PnaclCall);
486      TCALLINGCONV(IntelOclBicc);
487    }
488#undef TCALLINGCONV
489  }
490
491  return CXCallingConv_Invalid;
492}
493
494int clang_getNumArgTypes(CXType X) {
495  QualType T = GetQualType(X);
496  if (T.isNull())
497    return -1;
498
499  if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) {
500    return FD->getNumArgs();
501  }
502
503  if (T->getAs<FunctionNoProtoType>()) {
504    return 0;
505  }
506
507  return -1;
508}
509
510CXType clang_getArgType(CXType X, unsigned i) {
511  QualType T = GetQualType(X);
512  if (T.isNull())
513    return MakeCXType(QualType(), GetTU(X));
514
515  if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) {
516    unsigned numArgs = FD->getNumArgs();
517    if (i >= numArgs)
518      return MakeCXType(QualType(), GetTU(X));
519
520    return MakeCXType(FD->getArgType(i), GetTU(X));
521  }
522
523  return MakeCXType(QualType(), GetTU(X));
524}
525
526CXType clang_getResultType(CXType X) {
527  QualType T = GetQualType(X);
528  if (T.isNull())
529    return MakeCXType(QualType(), GetTU(X));
530
531  if (const FunctionType *FD = T->getAs<FunctionType>())
532    return MakeCXType(FD->getResultType(), GetTU(X));
533
534  return MakeCXType(QualType(), GetTU(X));
535}
536
537CXType clang_getCursorResultType(CXCursor C) {
538  if (clang_isDeclaration(C.kind)) {
539    const Decl *D = cxcursor::getCursorDecl(C);
540    if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
541      return MakeCXType(MD->getResultType(), cxcursor::getCursorTU(C));
542
543    return clang_getResultType(clang_getCursorType(C));
544  }
545
546  return MakeCXType(QualType(), cxcursor::getCursorTU(C));
547}
548
549unsigned clang_isPODType(CXType X) {
550  QualType T = GetQualType(X);
551  if (T.isNull())
552    return 0;
553
554  CXTranslationUnit TU = GetTU(X);
555  ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData);
556
557  return T.isPODType(AU->getASTContext()) ? 1 : 0;
558}
559
560CXType clang_getElementType(CXType CT) {
561  QualType ET = QualType();
562  QualType T = GetQualType(CT);
563  const Type *TP = T.getTypePtrOrNull();
564
565  if (TP) {
566    switch (TP->getTypeClass()) {
567    case Type::ConstantArray:
568      ET = cast<ConstantArrayType> (TP)->getElementType();
569      break;
570    case Type::Vector:
571      ET = cast<VectorType> (TP)->getElementType();
572      break;
573    case Type::Complex:
574      ET = cast<ComplexType> (TP)->getElementType();
575      break;
576    default:
577      break;
578    }
579  }
580  return MakeCXType(ET, GetTU(CT));
581}
582
583long long clang_getNumElements(CXType CT) {
584  long long result = -1;
585  QualType T = GetQualType(CT);
586  const Type *TP = T.getTypePtrOrNull();
587
588  if (TP) {
589    switch (TP->getTypeClass()) {
590    case Type::ConstantArray:
591      result = cast<ConstantArrayType> (TP)->getSize().getSExtValue();
592      break;
593    case Type::Vector:
594      result = cast<VectorType> (TP)->getNumElements();
595      break;
596    default:
597      break;
598    }
599  }
600  return result;
601}
602
603CXType clang_getArrayElementType(CXType CT) {
604  QualType ET = QualType();
605  QualType T = GetQualType(CT);
606  const Type *TP = T.getTypePtrOrNull();
607
608  if (TP) {
609    switch (TP->getTypeClass()) {
610    case Type::ConstantArray:
611      ET = cast<ConstantArrayType> (TP)->getElementType();
612      break;
613    default:
614      break;
615    }
616  }
617  return MakeCXType(ET, GetTU(CT));
618}
619
620long long clang_getArraySize(CXType CT) {
621  long long result = -1;
622  QualType T = GetQualType(CT);
623  const Type *TP = T.getTypePtrOrNull();
624
625  if (TP) {
626    switch (TP->getTypeClass()) {
627    case Type::ConstantArray:
628      result = cast<ConstantArrayType> (TP)->getSize().getSExtValue();
629      break;
630    default:
631      break;
632    }
633  }
634  return result;
635}
636
637CXString clang_getDeclObjCTypeEncoding(CXCursor C) {
638  if (!clang_isDeclaration(C.kind))
639    return cxstring::createCXString("");
640
641  const Decl *D = static_cast<const Decl*>(C.data[0]);
642  ASTUnit *AU = cxcursor::getCursorASTUnit(C);
643  ASTContext &Ctx = AU->getASTContext();
644  std::string encoding;
645
646  if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))  {
647    if (Ctx.getObjCEncodingForMethodDecl(OMD, encoding))
648      return cxstring::createCXString("?");
649  } else if (const ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(D))
650    Ctx.getObjCEncodingForPropertyDecl(OPD, NULL, encoding);
651  else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
652    Ctx.getObjCEncodingForFunctionDecl(FD, encoding);
653  else {
654    QualType Ty;
655    if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
656      Ty = Ctx.getTypeDeclType(TD);
657    if (const ValueDecl *VD = dyn_cast<ValueDecl>(D))
658      Ty = VD->getType();
659    else return cxstring::createCXString("?");
660    Ctx.getObjCEncodingForType(Ty, encoding);
661  }
662
663  return cxstring::createCXString(encoding);
664}
665
666} // end: extern "C"
667