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