]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/libclang/CXType.cpp
Vendor import of clang trunk r132879:
[FreeBSD/FreeBSD.git] / tools / libclang / CXType.cpp
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
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
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
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
102 static inline QualType GetQualType(CXType CT) {
103   return QualType::getFromOpaquePtr(CT.data[0]);
104 }
105
106 static inline CXTranslationUnit GetTU(CXType CT) {
107   return static_cast<CXTranslationUnit>(CT.data[1]);
108 }
109
110 extern "C" {
111
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
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
189 unsigned clang_isConstQualifiedType(CXType CT) {
190   QualType T = GetQualType(CT);
191   return T.isLocalConstQualified();
192 }
193
194 unsigned clang_isVolatileQualifiedType(CXType CT) {
195   QualType T = GetQualType(CT);
196   return T.isLocalVolatileQualified();
197 }
198
199 unsigned clang_isRestrictQualifiedType(CXType CT) {
200   QualType T = GetQualType(CT);
201   return T.isLocalRestrictQualified();
202 }
203
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
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
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
338 unsigned clang_equalTypes(CXType A, CXType B) {
339   return A.data[0] == B.data[0] && A.data[1] == B.data[1];;
340 }
341
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
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
365 unsigned clang_isPODType(CXType X) {
366   QualType T = GetQualType(X);
367   if (!T.getTypePtrOrNull())
368     return 0;
369   return T->isPODType() ? 1 : 0;
370 }
371
372 CXString clang_getDeclObjCTypeEncoding(CXCursor C) {
373   if ((C.kind < CXCursor_FirstDecl) || (C.kind > CXCursor_LastDecl))
374     return cxstring::createCXString("");
375
376   Decl *D = static_cast<Decl*>(C.data[0]);
377   CXTranslationUnit TU = static_cast<CXTranslationUnit>(C.data[2]);
378   ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData);
379   ASTContext &Ctx = AU->getASTContext();
380   std::string encoding;
381
382   if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D))  {
383     if (Ctx.getObjCEncodingForMethodDecl(OMD, encoding))
384       return cxstring::createCXString("?");
385   } else if (ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(D)) 
386     Ctx.getObjCEncodingForPropertyDecl(OPD, NULL, encoding);
387   else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
388     Ctx.getObjCEncodingForFunctionDecl(FD, encoding);
389   else {
390     QualType Ty;
391     if (TypeDecl *TD = dyn_cast<TypeDecl>(D))
392       Ty = Ctx.getTypeDeclType(TD);
393     if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
394       Ty = VD->getType();
395     else return cxstring::createCXString("?");
396     Ctx.getObjCEncodingForType(Ty, encoding);
397   }
398
399   return cxstring::createCXString(encoding);
400 }
401
402 } // end: extern "C"