1 //===- CXTypes.cpp - Implements 'CXTypes' aspect of libclang ------------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===--------------------------------------------------------------------===//
10 // This file implements the 'CXTypes' API hooks in the Clang-C library.
12 //===--------------------------------------------------------------------===//
15 #include "CXTranslationUnit.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"
26 using namespace clang;
28 static CXTypeKind GetBuiltinTypeKind(const BuiltinType *BT) {
29 #define BTCASE(K) case BuiltinType::K: return CXType_##K
30 switch (BT->getKind()) {
44 case BuiltinType::WChar_S: return CXType_WChar;
45 case BuiltinType::WChar_U: return CXType_WChar;
61 return CXType_Unexposed;
66 static CXTypeKind GetTypeKind(QualType T) {
67 const Type *TP = T.getTypePtrOrNull();
69 return CXType_Invalid;
71 #define TKCASE(K) case Type::K: return CXType_##K
72 switch (TP->getTypeClass()) {
74 return GetBuiltinTypeKind(cast<BuiltinType>(TP));
78 TKCASE(LValueReference);
79 TKCASE(RValueReference);
83 TKCASE(ObjCInterface);
84 TKCASE(ObjCObjectPointer);
85 TKCASE(FunctionNoProto);
86 TKCASE(FunctionProto);
87 TKCASE(ConstantArray);
89 return CXType_Unexposed;
95 CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) {
96 CXTypeKind TK = GetTypeKind(T);
97 CXType CT = { TK, { TK == CXType_Invalid ? 0 : T.getAsOpaquePtr(), TU }};
101 using cxtype::MakeCXType;
103 static inline QualType GetQualType(CXType CT) {
104 return QualType::getFromOpaquePtr(CT.data[0]);
107 static inline CXTranslationUnit GetTU(CXType CT) {
108 return static_cast<CXTranslationUnit>(CT.data[1]);
113 CXType clang_getCursorType(CXCursor C) {
114 using namespace cxcursor;
116 CXTranslationUnit TU = cxcursor::getCursorTU(C);
117 ASTContext &Context = static_cast<ASTUnit *>(TU->TUData)->getASTContext();
118 if (clang_isExpression(C.kind)) {
119 QualType T = cxcursor::getCursorExpr(C)->getType();
120 return MakeCXType(T, TU);
123 if (clang_isDeclaration(C.kind)) {
124 Decl *D = cxcursor::getCursorDecl(C);
126 if (TypeDecl *TD = dyn_cast<TypeDecl>(D))
127 return MakeCXType(Context.getTypeDeclType(TD), TU);
128 if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
129 return MakeCXType(Context.getObjCInterfaceType(ID), TU);
130 if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
131 return MakeCXType(VD->getType(), TU);
132 if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D))
133 return MakeCXType(PD->getType(), TU);
134 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
135 return MakeCXType(FD->getType(), TU);
136 return MakeCXType(QualType(), TU);
139 if (clang_isReference(C.kind)) {
141 case CXCursor_ObjCSuperClassRef: {
143 = Context.getObjCInterfaceType(getCursorObjCSuperClassRef(C).first);
144 return MakeCXType(T, TU);
147 case CXCursor_ObjCClassRef: {
148 QualType T = Context.getObjCInterfaceType(getCursorObjCClassRef(C).first);
149 return MakeCXType(T, TU);
152 case CXCursor_TypeRef: {
153 QualType T = Context.getTypeDeclType(getCursorTypeRef(C).first);
154 return MakeCXType(T, TU);
158 case CXCursor_CXXBaseSpecifier:
159 return cxtype::MakeCXType(getCursorCXXBaseSpecifier(C)->getType(), TU);
161 case CXCursor_ObjCProtocolRef:
162 case CXCursor_TemplateRef:
163 case CXCursor_NamespaceRef:
164 case CXCursor_MemberRef:
165 case CXCursor_OverloadedDeclRef:
170 return MakeCXType(QualType(), TU);
173 return MakeCXType(QualType(), TU);
176 CXType clang_getCanonicalType(CXType CT) {
177 if (CT.kind == CXType_Invalid)
180 QualType T = GetQualType(CT);
181 CXTranslationUnit TU = GetTU(CT);
184 return MakeCXType(QualType(), GetTU(CT));
186 ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData);
187 return MakeCXType(AU->getASTContext().getCanonicalType(T), TU);
190 unsigned clang_isConstQualifiedType(CXType CT) {
191 QualType T = GetQualType(CT);
192 return T.isLocalConstQualified();
195 unsigned clang_isVolatileQualifiedType(CXType CT) {
196 QualType T = GetQualType(CT);
197 return T.isLocalVolatileQualified();
200 unsigned clang_isRestrictQualifiedType(CXType CT) {
201 QualType T = GetQualType(CT);
202 return T.isLocalRestrictQualified();
205 CXType clang_getPointeeType(CXType CT) {
206 QualType T = GetQualType(CT);
207 const Type *TP = T.getTypePtrOrNull();
210 return MakeCXType(QualType(), GetTU(CT));
212 switch (TP->getTypeClass()) {
214 T = cast<PointerType>(TP)->getPointeeType();
216 case Type::BlockPointer:
217 T = cast<BlockPointerType>(TP)->getPointeeType();
219 case Type::LValueReference:
220 case Type::RValueReference:
221 T = cast<ReferenceType>(TP)->getPointeeType();
223 case Type::ObjCObjectPointer:
224 T = cast<ObjCObjectPointerType>(TP)->getPointeeType();
230 return MakeCXType(T, GetTU(CT));
233 CXCursor clang_getTypeDeclaration(CXType CT) {
234 if (CT.kind == CXType_Invalid)
235 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
237 QualType T = GetQualType(CT);
238 const Type *TP = T.getTypePtrOrNull();
241 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
246 switch (TP->getTypeClass()) {
248 D = cast<TypedefType>(TP)->getDecl();
250 case Type::ObjCObject:
251 D = cast<ObjCObjectType>(TP)->getInterface();
253 case Type::ObjCInterface:
254 D = cast<ObjCInterfaceType>(TP)->getDecl();
258 D = cast<TagType>(TP)->getDecl();
260 case Type::TemplateSpecialization:
261 if (const RecordType *Record = TP->getAs<RecordType>())
262 D = Record->getDecl();
264 D = cast<TemplateSpecializationType>(TP)->getTemplateName()
265 .getAsTemplateDecl();
268 case Type::InjectedClassName:
269 D = cast<InjectedClassNameType>(TP)->getDecl();
272 // FIXME: Template type parameters!
274 case Type::Elaborated:
275 TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull();
283 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
285 return cxcursor::MakeCXCursor(D, GetTU(CT));
288 CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
290 #define TKIND(X) case CXType_##X: s = "" #X ""; break
307 case CXType_WChar: s = "WChar"; break;
325 TKIND(LValueReference);
326 TKIND(RValueReference);
330 TKIND(ObjCInterface);
331 TKIND(ObjCObjectPointer);
332 TKIND(FunctionNoProto);
333 TKIND(FunctionProto);
334 TKIND(ConstantArray);
337 return cxstring::createCXString(s);
340 unsigned clang_equalTypes(CXType A, CXType B) {
341 return A.data[0] == B.data[0] && A.data[1] == B.data[1];;
344 CXType clang_getResultType(CXType X) {
345 QualType T = GetQualType(X);
346 if (!T.getTypePtrOrNull())
347 return MakeCXType(QualType(), GetTU(X));
349 if (const FunctionType *FD = T->getAs<FunctionType>())
350 return MakeCXType(FD->getResultType(), GetTU(X));
352 return MakeCXType(QualType(), GetTU(X));
355 CXType clang_getCursorResultType(CXCursor C) {
356 if (clang_isDeclaration(C.kind)) {
357 Decl *D = cxcursor::getCursorDecl(C);
358 if (const ObjCMethodDecl *MD = dyn_cast<ObjCMethodDecl>(D))
359 return MakeCXType(MD->getResultType(), cxcursor::getCursorTU(C));
361 return clang_getResultType(clang_getCursorType(C));
364 return MakeCXType(QualType(), cxcursor::getCursorTU(C));
367 unsigned clang_isPODType(CXType X) {
368 QualType T = GetQualType(X);
369 if (!T.getTypePtrOrNull())
372 CXTranslationUnit TU = GetTU(X);
373 ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData);
375 return T.isPODType(AU->getASTContext()) ? 1 : 0;
378 CXType clang_getArrayElementType(CXType CT) {
379 QualType ET = QualType();
380 QualType T = GetQualType(CT);
381 const Type *TP = T.getTypePtrOrNull();
384 switch (TP->getTypeClass()) {
385 case Type::ConstantArray:
386 ET = cast<ConstantArrayType> (TP)->getElementType();
392 return MakeCXType(ET, GetTU(CT));
395 long long clang_getArraySize(CXType CT) {
396 long long result = -1;
397 QualType T = GetQualType(CT);
398 const Type *TP = T.getTypePtrOrNull();
401 switch (TP->getTypeClass()) {
402 case Type::ConstantArray:
403 result = cast<ConstantArrayType> (TP)->getSize().getSExtValue();
412 CXString clang_getDeclObjCTypeEncoding(CXCursor C) {
413 if ((C.kind < CXCursor_FirstDecl) || (C.kind > CXCursor_LastDecl))
414 return cxstring::createCXString("");
416 Decl *D = static_cast<Decl*>(C.data[0]);
417 CXTranslationUnit TU = static_cast<CXTranslationUnit>(C.data[2]);
418 ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData);
419 ASTContext &Ctx = AU->getASTContext();
420 std::string encoding;
422 if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
423 if (Ctx.getObjCEncodingForMethodDecl(OMD, encoding))
424 return cxstring::createCXString("?");
425 } else if (ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(D))
426 Ctx.getObjCEncodingForPropertyDecl(OPD, NULL, encoding);
427 else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
428 Ctx.getObjCEncodingForFunctionDecl(FD, encoding);
431 if (TypeDecl *TD = dyn_cast<TypeDecl>(D))
432 Ty = Ctx.getTypeDeclType(TD);
433 if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
435 else return cxstring::createCXString("?");
436 Ctx.getObjCEncodingForType(Ty, encoding);
439 return cxstring::createCXString(encoding);