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
26 using namespace clang;
27
GetBuiltinTypeKind(const BuiltinType * BT)28 static 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
GetTypeKind(QualType T)66 static 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
MakeCXType(QualType T,CXTranslationUnit TU)94 CXType 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
100 using cxtype::MakeCXType;
101
GetQualType(CXType CT)102 static inline QualType GetQualType(CXType CT) {
103 return QualType::getFromOpaquePtr(CT.data[0]);
104 }
105
GetTU(CXType CT)106 static inline CXTranslationUnit GetTU(CXType CT) {
107 return static_cast<CXTranslationUnit>(CT.data[1]);
108 }
109
110 extern "C" {
111
clang_getCursorType(CXCursor C)112 CXType 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
clang_getCanonicalType(CXType CT)175 CXType 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
clang_isConstQualifiedType(CXType CT)189 unsigned clang_isConstQualifiedType(CXType CT) {
190 QualType T = GetQualType(CT);
191 return T.isLocalConstQualified();
192 }
193
clang_isVolatileQualifiedType(CXType CT)194 unsigned clang_isVolatileQualifiedType(CXType CT) {
195 QualType T = GetQualType(CT);
196 return T.isLocalVolatileQualified();
197 }
198
clang_isRestrictQualifiedType(CXType CT)199 unsigned clang_isRestrictQualifiedType(CXType CT) {
200 QualType T = GetQualType(CT);
201 return T.isLocalRestrictQualified();
202 }
203
clang_getPointeeType(CXType CT)204 CXType clang_getPointeeType(CXType CT) {
205 QualType T = GetQualType(CT);
206 const Type *TP = T.getTypePtrOrNull();
207
208 if (!TP)
209 return MakeCXType(QualType(), GetTU(CT));
210
211 switch (TP->getTypeClass()) {
212 case Type::Pointer:
213 T = cast<PointerType>(TP)->getPointeeType();
214 break;
215 case Type::BlockPointer:
216 T = cast<BlockPointerType>(TP)->getPointeeType();
217 break;
218 case Type::LValueReference:
219 case Type::RValueReference:
220 T = cast<ReferenceType>(TP)->getPointeeType();
221 break;
222 case Type::ObjCObjectPointer:
223 T = cast<ObjCObjectPointerType>(TP)->getPointeeType();
224 break;
225 default:
226 T = QualType();
227 break;
228 }
229 return MakeCXType(T, GetTU(CT));
230 }
231
clang_getTypeDeclaration(CXType CT)232 CXCursor clang_getTypeDeclaration(CXType CT) {
233 if (CT.kind == CXType_Invalid)
234 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
235
236 QualType T = GetQualType(CT);
237 const Type *TP = T.getTypePtrOrNull();
238
239 if (!TP)
240 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
241
242 Decl *D = 0;
243
244 try_again:
245 switch (TP->getTypeClass()) {
246 case Type::Typedef:
247 D = cast<TypedefType>(TP)->getDecl();
248 break;
249 case Type::ObjCObject:
250 D = cast<ObjCObjectType>(TP)->getInterface();
251 break;
252 case Type::ObjCInterface:
253 D = cast<ObjCInterfaceType>(TP)->getDecl();
254 break;
255 case Type::Record:
256 case Type::Enum:
257 D = cast<TagType>(TP)->getDecl();
258 break;
259 case Type::TemplateSpecialization:
260 if (const RecordType *Record = TP->getAs<RecordType>())
261 D = Record->getDecl();
262 else
263 D = cast<TemplateSpecializationType>(TP)->getTemplateName()
264 .getAsTemplateDecl();
265 break;
266
267 case Type::InjectedClassName:
268 D = cast<InjectedClassNameType>(TP)->getDecl();
269 break;
270
271 // FIXME: Template type parameters!
272
273 case Type::Elaborated:
274 TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull();
275 goto try_again;
276
277 default:
278 break;
279 }
280
281 if (!D)
282 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
283
284 return cxcursor::MakeCXCursor(D, GetTU(CT));
285 }
286
clang_getTypeKindSpelling(enum CXTypeKind K)287 CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
288 const char *s = 0;
289 #define TKIND(X) case CXType_##X: s = "" #X ""; break
290 switch (K) {
291 TKIND(Invalid);
292 TKIND(Unexposed);
293 TKIND(Void);
294 TKIND(Bool);
295 TKIND(Char_U);
296 TKIND(UChar);
297 TKIND(Char16);
298 TKIND(Char32);
299 TKIND(UShort);
300 TKIND(UInt);
301 TKIND(ULong);
302 TKIND(ULongLong);
303 TKIND(UInt128);
304 TKIND(Char_S);
305 TKIND(SChar);
306 case CXType_WChar: s = "WChar"; break;
307 TKIND(Short);
308 TKIND(Int);
309 TKIND(Long);
310 TKIND(LongLong);
311 TKIND(Int128);
312 TKIND(Float);
313 TKIND(Double);
314 TKIND(LongDouble);
315 TKIND(NullPtr);
316 TKIND(Overload);
317 TKIND(Dependent);
318 TKIND(ObjCId);
319 TKIND(ObjCClass);
320 TKIND(ObjCSel);
321 TKIND(Complex);
322 TKIND(Pointer);
323 TKIND(BlockPointer);
324 TKIND(LValueReference);
325 TKIND(RValueReference);
326 TKIND(Record);
327 TKIND(Enum);
328 TKIND(Typedef);
329 TKIND(ObjCInterface);
330 TKIND(ObjCObjectPointer);
331 TKIND(FunctionNoProto);
332 TKIND(FunctionProto);
333 }
334 #undef TKIND
335 return cxstring::createCXString(s);
336 }
337
clang_equalTypes(CXType A,CXType B)338 unsigned clang_equalTypes(CXType A, CXType B) {
339 return A.data[0] == B.data[0] && A.data[1] == B.data[1];;
340 }
341
clang_getResultType(CXType X)342 CXType clang_getResultType(CXType X) {
343 QualType T = GetQualType(X);
344 if (!T.getTypePtrOrNull())
345 return MakeCXType(QualType(), GetTU(X));
346
347 if (const FunctionType *FD = T->getAs<FunctionType>())
348 return MakeCXType(FD->getResultType(), GetTU(X));
349
350 return MakeCXType(QualType(), GetTU(X));
351 }
352
clang_getCursorResultType(CXCursor C)353 CXType clang_getCursorResultType(CXCursor C) {
354 if (clang_isDeclaration(C.kind)) {
355 Decl *D = cxcursor::getCursorDecl(C);
356 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
357 return MakeCXType(MD->getResultType(), cxcursor::getCursorTU(C));
358
359 return clang_getResultType(clang_getCursorType(C));
360 }
361
362 return MakeCXType(QualType(), cxcursor::getCursorTU(C));
363 }
364
clang_isPODType(CXType X)365 unsigned clang_isPODType(CXType X) {
366 QualType T = GetQualType(X);
367 if (!T.getTypePtrOrNull())
368 return 0;
369
370 CXTranslationUnit TU = GetTU(X);
371 ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData);
372
373 return T.isPODType(AU->getASTContext()) ? 1 : 0;
374 }
375
clang_getDeclObjCTypeEncoding(CXCursor C)376 CXString clang_getDeclObjCTypeEncoding(CXCursor C) {
377 if ((C.kind < CXCursor_FirstDecl) || (C.kind > CXCursor_LastDecl))
378 return cxstring::createCXString("");
379
380 Decl *D = static_cast<Decl*>(C.data[0]);
381 CXTranslationUnit TU = static_cast<CXTranslationUnit>(C.data[2]);
382 ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData);
383 ASTContext &Ctx = AU->getASTContext();
384 std::string encoding;
385
386 if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
387 if (Ctx.getObjCEncodingForMethodDecl(OMD, encoding))
388 return cxstring::createCXString("?");
389 } else if (ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(D))
390 Ctx.getObjCEncodingForPropertyDecl(OPD, NULL, encoding);
391 else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
392 Ctx.getObjCEncodingForFunctionDecl(FD, encoding);
393 else {
394 QualType Ty;
395 if (TypeDecl *TD = dyn_cast<TypeDecl>(D))
396 Ty = Ctx.getTypeDeclType(TD);
397 if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
398 Ty = VD->getType();
399 else return cxstring::createCXString("?");
400 Ctx.getObjCEncodingForType(Ty, encoding);
401 }
402
403 return cxstring::createCXString(encoding);
404 }
405
406 } // end: extern "C"
407