CXType.cpp revision fbcfeeabed6aa60ba664be302f2b03bed3d1b24d
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    default:
88      return CXType_Unexposed;
89  }
90#undef TKCASE
91}
92
93
94CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) {
95  CXTypeKind TK = GetTypeKind(T);
96  CXType CT = { TK, { TK == CXType_Invalid ? 0 : T.getAsOpaquePtr(), TU }};
97  return CT;
98}
99
100using cxtype::MakeCXType;
101
102static inline QualType GetQualType(CXType CT) {
103  return QualType::getFromOpaquePtr(CT.data[0]);
104}
105
106static inline CXTranslationUnit GetTU(CXType CT) {
107  return static_cast<CXTranslationUnit>(CT.data[1]);
108}
109
110extern "C" {
111
112CXType clang_getCursorType(CXCursor C) {
113  using namespace cxcursor;
114
115  CXTranslationUnit TU = cxcursor::getCursorTU(C);
116  ASTContext &Context = static_cast<ASTUnit *>(TU->TUData)->getASTContext();
117  if (clang_isExpression(C.kind)) {
118    QualType T = cxcursor::getCursorExpr(C)->getType();
119    return MakeCXType(T, TU);
120  }
121
122  if (clang_isDeclaration(C.kind)) {
123    Decl *D = cxcursor::getCursorDecl(C);
124
125    if (TypeDecl *TD = dyn_cast<TypeDecl>(D))
126      return MakeCXType(Context.getTypeDeclType(TD), TU);
127    if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
128      return MakeCXType(Context.getObjCInterfaceType(ID), TU);
129    if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
130      return MakeCXType(VD->getType(), TU);
131    if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D))
132      return MakeCXType(PD->getType(), TU);
133    if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
134      return MakeCXType(FD->getType(), TU);
135    return MakeCXType(QualType(), TU);
136  }
137
138  if (clang_isReference(C.kind)) {
139    switch (C.kind) {
140    case CXCursor_ObjCSuperClassRef: {
141      QualType T
142        = Context.getObjCInterfaceType(getCursorObjCSuperClassRef(C).first);
143      return MakeCXType(T, TU);
144    }
145
146    case CXCursor_ObjCClassRef: {
147      QualType T = Context.getObjCInterfaceType(getCursorObjCClassRef(C).first);
148      return MakeCXType(T, TU);
149    }
150
151    case CXCursor_TypeRef: {
152      QualType T = Context.getTypeDeclType(getCursorTypeRef(C).first);
153      return MakeCXType(T, TU);
154
155    }
156
157    case CXCursor_CXXBaseSpecifier:
158      return cxtype::MakeCXType(getCursorCXXBaseSpecifier(C)->getType(), TU);
159
160    case CXCursor_ObjCProtocolRef:
161    case CXCursor_TemplateRef:
162    case CXCursor_NamespaceRef:
163    case CXCursor_MemberRef:
164    case CXCursor_OverloadedDeclRef:
165    default:
166      break;
167    }
168
169    return MakeCXType(QualType(), TU);
170  }
171
172  return MakeCXType(QualType(), TU);
173}
174
175CXType clang_getCanonicalType(CXType CT) {
176  if (CT.kind == CXType_Invalid)
177    return CT;
178
179  QualType T = GetQualType(CT);
180  CXTranslationUnit TU = GetTU(CT);
181
182  if (T.isNull())
183    return MakeCXType(QualType(), GetTU(CT));
184
185  ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData);
186  return MakeCXType(AU->getASTContext().getCanonicalType(T), TU);
187}
188
189CXType clang_getPointeeType(CXType CT) {
190  QualType T = GetQualType(CT);
191  const Type *TP = T.getTypePtrOrNull();
192
193  if (!TP)
194    return MakeCXType(QualType(), GetTU(CT));
195
196  switch (TP->getTypeClass()) {
197    case Type::Pointer:
198      T = cast<PointerType>(TP)->getPointeeType();
199      break;
200    case Type::BlockPointer:
201      T = cast<BlockPointerType>(TP)->getPointeeType();
202      break;
203    case Type::LValueReference:
204    case Type::RValueReference:
205      T = cast<ReferenceType>(TP)->getPointeeType();
206      break;
207    case Type::ObjCObjectPointer:
208      T = cast<ObjCObjectPointerType>(TP)->getPointeeType();
209      break;
210    default:
211      T = QualType();
212      break;
213  }
214  return MakeCXType(T, GetTU(CT));
215}
216
217CXCursor clang_getTypeDeclaration(CXType CT) {
218  if (CT.kind == CXType_Invalid)
219    return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
220
221  QualType T = GetQualType(CT);
222  const Type *TP = T.getTypePtrOrNull();
223
224  if (!TP)
225    return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
226
227  Decl *D = 0;
228
229try_again:
230  switch (TP->getTypeClass()) {
231  case Type::Typedef:
232    D = cast<TypedefType>(TP)->getDecl();
233    break;
234  case Type::ObjCObject:
235    D = cast<ObjCObjectType>(TP)->getInterface();
236    break;
237  case Type::ObjCInterface:
238    D = cast<ObjCInterfaceType>(TP)->getDecl();
239    break;
240  case Type::Record:
241  case Type::Enum:
242    D = cast<TagType>(TP)->getDecl();
243    break;
244  case Type::TemplateSpecialization:
245    if (const RecordType *Record = TP->getAs<RecordType>())
246      D = Record->getDecl();
247    else
248      D = cast<TemplateSpecializationType>(TP)->getTemplateName()
249                                                         .getAsTemplateDecl();
250    break;
251
252  case Type::InjectedClassName:
253    D = cast<InjectedClassNameType>(TP)->getDecl();
254    break;
255
256  // FIXME: Template type parameters!
257
258  case Type::Elaborated:
259    TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull();
260    goto try_again;
261
262  default:
263    break;
264  }
265
266  if (!D)
267    return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
268
269  return cxcursor::MakeCXCursor(D, GetTU(CT));
270}
271
272CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
273  const char *s = 0;
274#define TKIND(X) case CXType_##X: s = ""  #X  ""; break
275  switch (K) {
276    TKIND(Invalid);
277    TKIND(Unexposed);
278    TKIND(Void);
279    TKIND(Bool);
280    TKIND(Char_U);
281    TKIND(UChar);
282    TKIND(Char16);
283    TKIND(Char32);
284    TKIND(UShort);
285    TKIND(UInt);
286    TKIND(ULong);
287    TKIND(ULongLong);
288    TKIND(UInt128);
289    TKIND(Char_S);
290    TKIND(SChar);
291    case CXType_WChar: s = "WChar"; break;
292    TKIND(Short);
293    TKIND(Int);
294    TKIND(Long);
295    TKIND(LongLong);
296    TKIND(Int128);
297    TKIND(Float);
298    TKIND(Double);
299    TKIND(LongDouble);
300    TKIND(NullPtr);
301    TKIND(Overload);
302    TKIND(Dependent);
303    TKIND(ObjCId);
304    TKIND(ObjCClass);
305    TKIND(ObjCSel);
306    TKIND(Complex);
307    TKIND(Pointer);
308    TKIND(BlockPointer);
309    TKIND(LValueReference);
310    TKIND(RValueReference);
311    TKIND(Record);
312    TKIND(Enum);
313    TKIND(Typedef);
314    TKIND(ObjCInterface);
315    TKIND(ObjCObjectPointer);
316    TKIND(FunctionNoProto);
317    TKIND(FunctionProto);
318  }
319#undef TKIND
320  return cxstring::createCXString(s);
321}
322
323unsigned clang_equalTypes(CXType A, CXType B) {
324  return A.data[0] == B.data[0] && A.data[1] == B.data[1];;
325}
326
327CXType clang_getResultType(CXType X) {
328  QualType T = GetQualType(X);
329  if (!T.getTypePtrOrNull())
330    return MakeCXType(QualType(), GetTU(X));
331
332  if (const FunctionType *FD = T->getAs<FunctionType>())
333    return MakeCXType(FD->getResultType(), GetTU(X));
334
335  return MakeCXType(QualType(), GetTU(X));
336}
337
338CXType clang_getCursorResultType(CXCursor C) {
339  if (clang_isDeclaration(C.kind)) {
340    Decl *D = cxcursor::getCursorDecl(C);
341    if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
342      return MakeCXType(MD->getResultType(), cxcursor::getCursorTU(C));
343
344    return clang_getResultType(clang_getCursorType(C));
345  }
346
347  return MakeCXType(QualType(), cxcursor::getCursorTU(C));
348}
349
350unsigned clang_isPODType(CXType X) {
351  QualType T = GetQualType(X);
352  if (!T.getTypePtrOrNull())
353    return 0;
354  return T->isPODType() ? 1 : 0;
355}
356
357CXString clang_getDeclObjCTypeEncoding(CXCursor C) {
358  if ((C.kind < CXCursor_FirstDecl) || (C.kind > CXCursor_LastDecl))
359    return cxstring::createCXString("");
360
361  Decl *D = static_cast<Decl*>(C.data[0]);
362  CXTranslationUnit TU = static_cast<CXTranslationUnit>(C.data[2]);
363  ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData);
364  ASTContext &Ctx = AU->getASTContext();
365  std::string encoding;
366
367  if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))
368    Ctx.getObjCEncodingForMethodDecl(OMD, encoding);
369  else if (ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(D))
370    Ctx.getObjCEncodingForPropertyDecl(OPD, NULL, encoding);
371  else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
372    Ctx.getObjCEncodingForFunctionDecl(FD, encoding);
373  else {
374    QualType Ty;
375    if (TypeDecl *TD = dyn_cast<TypeDecl>(D))
376      Ty = Ctx.getTypeDeclType(TD);
377    if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
378      Ty = VD->getType();
379    else return cxstring::createCXString("?");
380    Ctx.getObjCEncodingForType(Ty, encoding);
381  }
382
383  return cxstring::createCXString(encoding);
384}
385
386} // end: extern "C"
387