CXType.cpp revision 5f0bfc522266f3319c4a6262b016a552de058c7f
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    default:
89      return CXType_Unexposed;
90  }
91#undef TKCASE
92}
93
94
95CXType 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
101using cxtype::MakeCXType;
102
103static inline QualType GetQualType(CXType CT) {
104  return QualType::getFromOpaquePtr(CT.data[0]);
105}
106
107static inline CXTranslationUnit GetTU(CXType CT) {
108  return static_cast<CXTranslationUnit>(CT.data[1]);
109}
110
111extern "C" {
112
113CXType 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
176CXType 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
190unsigned clang_isConstQualifiedType(CXType CT) {
191  QualType T = GetQualType(CT);
192  return T.isLocalConstQualified();
193}
194
195unsigned clang_isVolatileQualifiedType(CXType CT) {
196  QualType T = GetQualType(CT);
197  return T.isLocalVolatileQualified();
198}
199
200unsigned clang_isRestrictQualifiedType(CXType CT) {
201  QualType T = GetQualType(CT);
202  return T.isLocalRestrictQualified();
203}
204
205CXType 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
233CXCursor 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
245try_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
288CXString 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
340unsigned clang_equalTypes(CXType A, CXType B) {
341  return A.data[0] == B.data[0] && A.data[1] == B.data[1];;
342}
343
344CXType 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
355CXType 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
367unsigned 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
378CXType 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
395long 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
412CXString 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