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