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