blob: 45a5bed27962f7a2cf88898b66c1e2f1bb128fda [file] [log] [blame]
Ted Kremenek8e0ac172010-05-14 21:29:26 +00001//===- 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"
Ted Kremeneked122732010-11-16 01:56:27 +000016#include "CXString.h"
Ted Kremenek95f33552010-08-26 01:42:22 +000017#include "CXType.h"
Ted Kremenek8e0ac172010-05-14 21:29:26 +000018#include "clang/AST/Expr.h"
19#include "clang/AST/Type.h"
20#include "clang/AST/Decl.h"
21#include "clang/AST/DeclObjC.h"
Douglas Gregor3f0fee32010-10-02 21:57:58 +000022#include "clang/AST/DeclTemplate.h"
Ted Kremenek8e0ac172010-05-14 21:29:26 +000023#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);
Ted Kremenek04c3cf32010-06-21 20:15:39 +000083 TKCASE(FunctionNoProto);
84 TKCASE(FunctionProto);
Ted Kremenek8e0ac172010-05-14 21:29:26 +000085 default:
86 return CXType_Unexposed;
87 }
88#undef TKCASE
89}
90
Ted Kremenek95f33552010-08-26 01:42:22 +000091
92CXType cxtype::MakeCXType(QualType T, ASTUnit *TU) {
Ted Kremenek8e0ac172010-05-14 21:29:26 +000093 CXTypeKind TK = GetTypeKind(T);
94 CXType CT = { TK, { TK == CXType_Invalid ? 0 : T.getAsOpaquePtr(), TU }};
95 return CT;
96}
97
Ted Kremenek95f33552010-08-26 01:42:22 +000098using cxtype::MakeCXType;
99
Ted Kremenek8e0ac172010-05-14 21:29:26 +0000100static inline QualType GetQualType(CXType CT) {
101 return QualType::getFromOpaquePtr(CT.data[0]);
102}
103
104static inline ASTUnit* GetASTU(CXType CT) {
105 return static_cast<ASTUnit*>(CT.data[1]);
106}
107
108extern "C" {
109
110CXType clang_getCursorType(CXCursor C) {
Douglas Gregor3f0fee32010-10-02 21:57:58 +0000111 using namespace cxcursor;
112
Ted Kremenek8e0ac172010-05-14 21:29:26 +0000113 ASTUnit *AU = cxcursor::getCursorASTUnit(C);
114
115 if (clang_isExpression(C.kind)) {
116 QualType T = cxcursor::getCursorExpr(C)->getType();
117 return MakeCXType(T, AU);
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), AU);
125 if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
126 return MakeCXType(QualType(ID->getTypeForDecl(), 0), AU);
127 if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
128 return MakeCXType(VD->getType(), AU);
Ted Kremenek0d32a682010-06-21 19:41:40 +0000129 if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D))
130 return MakeCXType(PD->getType(), AU);
Ted Kremenek04c3cf32010-06-21 20:15:39 +0000131 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
132 return MakeCXType(FD->getType(), AU);
Ted Kremenek8e0ac172010-05-14 21:29:26 +0000133 return MakeCXType(QualType(), AU);
134 }
Douglas Gregor3f0fee32010-10-02 21:57:58 +0000135
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 AU);
143
144 case CXCursor_ObjCClassRef:
145 return MakeCXType(
146 QualType(getCursorObjCClassRef(C).first->getTypeForDecl(),
147 0),
148 AU);
149
150 case CXCursor_TypeRef:
151 return MakeCXType(QualType(getCursorTypeRef(C).first->getTypeForDecl(),
152 0),
153 AU);
154
155 case CXCursor_CXXBaseSpecifier:
156 return cxtype::MakeCXType(getCursorCXXBaseSpecifier(C)->getType(), AU);
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(), AU);
168 }
Ted Kremenek8e0ac172010-05-14 21:29:26 +0000169
170 return MakeCXType(QualType(), AU);
171}
172
173CXType clang_getCanonicalType(CXType CT) {
174 if (CT.kind == CXType_Invalid)
175 return CT;
176
177 QualType T = GetQualType(CT);
178
179 if (T.isNull())
180 return MakeCXType(QualType(), GetASTU(CT));
181
182 ASTUnit *AU = GetASTU(CT);
183 return MakeCXType(AU->getASTContext().getCanonicalType(T), AU);
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(), GetASTU(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, GetASTU(CT));
212}
213
214CXCursor clang_getTypeDeclaration(CXType CT) {
Ted Kremenekb3da5392010-05-29 20:01:52 +0000215 if (CT.kind == CXType_Invalid)
216 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
217
Ted Kremenek8e0ac172010-05-14 21:29:26 +0000218 QualType T = GetQualType(CT);
219 Type *TP = T.getTypePtr();
Ted Kremenekb3da5392010-05-29 20:01:52 +0000220
221 if (!TP)
222 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
223
Ted Kremenek8e0ac172010-05-14 21:29:26 +0000224 Decl *D = 0;
225
Douglas Gregor3f0fee32010-10-02 21:57:58 +0000226try_again:
Ted Kremenek8e0ac172010-05-14 21:29:26 +0000227 switch (TP->getTypeClass()) {
Douglas Gregor3f0fee32010-10-02 21:57:58 +0000228 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;
Ted Kremenek8e0ac172010-05-14 21:29:26 +0000261 }
262
263 if (!D)
264 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
265
266 return cxcursor::MakeCXCursor(D, GetASTU(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);
Ted Kremenek04c3cf32010-06-21 20:15:39 +0000313 TKIND(FunctionNoProto);
314 TKIND(FunctionProto);
Ted Kremenek8e0ac172010-05-14 21:29:26 +0000315 }
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
Ted Kremenek04c3cf32010-06-21 20:15:39 +0000324CXType clang_getResultType(CXType X) {
325 QualType T = GetQualType(X);
326 if (!T.getTypePtr())
327 return MakeCXType(QualType(), GetASTU(X));
328
329 if (const FunctionType *FD = T->getAs<FunctionType>())
330 return MakeCXType(FD->getResultType(), GetASTU(X));
331
332 return MakeCXType(QualType(), GetASTU(X));
333}
334
Ted Kremenek9a140842010-06-21 20:48:56 +0000335CXType 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::getCursorASTUnit(C));
340
341 return clang_getResultType(clang_getCursorType(C));
342 }
343
344 return MakeCXType(QualType(), cxcursor::getCursorASTUnit(C));
345}
346
Ted Kremenek3ce9e7d2010-07-30 00:14:11 +0000347unsigned clang_isPODType(CXType X) {
348 QualType T = GetQualType(X);
349 if (!T.getTypePtr())
350 return 0;
351 return T->isPODType() ? 1 : 0;
352}
353
Ted Kremenek8e0ac172010-05-14 21:29:26 +0000354} // end: extern "C"