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