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);
90 return CXType_Unexposed;
96 CXType cxtype::MakeCXType(QualType T, CXTranslationUnit TU) {
97 CXTypeKind TK = CXType_Invalid;
99 if (TU && !T.isNull()) {
100 ASTContext &Ctx = static_cast<ASTUnit *>(TU->TUData)->getASTContext();
101 if (Ctx.getLangOpts().ObjC1) {
102 QualType UnqualT = T.getUnqualifiedType();
103 if (Ctx.isObjCIdType(UnqualT))
105 else if (Ctx.isObjCClassType(UnqualT))
106 TK = CXType_ObjCClass;
107 else if (Ctx.isObjCSelType(UnqualT))
111 if (TK == CXType_Invalid)
114 CXType CT = { TK, { TK == CXType_Invalid ? 0 : T.getAsOpaquePtr(), TU }};
118 using cxtype::MakeCXType;
120 static inline QualType GetQualType(CXType CT) {
121 return QualType::getFromOpaquePtr(CT.data[0]);
124 static inline CXTranslationUnit GetTU(CXType CT) {
125 return static_cast<CXTranslationUnit>(CT.data[1]);
130 CXType clang_getCursorType(CXCursor C) {
131 using namespace cxcursor;
133 CXTranslationUnit TU = cxcursor::getCursorTU(C);
134 ASTContext &Context = static_cast<ASTUnit *>(TU->TUData)->getASTContext();
135 if (clang_isExpression(C.kind)) {
136 QualType T = cxcursor::getCursorExpr(C)->getType();
137 return MakeCXType(T, TU);
140 if (clang_isDeclaration(C.kind)) {
141 Decl *D = cxcursor::getCursorDecl(C);
143 return MakeCXType(QualType(), TU);
145 if (TypeDecl *TD = dyn_cast<TypeDecl>(D))
146 return MakeCXType(Context.getTypeDeclType(TD), TU);
147 if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
148 return MakeCXType(Context.getObjCInterfaceType(ID), TU);
149 if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
150 return MakeCXType(VD->getType(), TU);
151 if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D))
152 return MakeCXType(PD->getType(), TU);
153 if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
154 return MakeCXType(FD->getType(), TU);
155 return MakeCXType(QualType(), TU);
158 if (clang_isReference(C.kind)) {
160 case CXCursor_ObjCSuperClassRef: {
162 = Context.getObjCInterfaceType(getCursorObjCSuperClassRef(C).first);
163 return MakeCXType(T, TU);
166 case CXCursor_ObjCClassRef: {
167 QualType T = Context.getObjCInterfaceType(getCursorObjCClassRef(C).first);
168 return MakeCXType(T, TU);
171 case CXCursor_TypeRef: {
172 QualType T = Context.getTypeDeclType(getCursorTypeRef(C).first);
173 return MakeCXType(T, TU);
177 case CXCursor_CXXBaseSpecifier:
178 return cxtype::MakeCXType(getCursorCXXBaseSpecifier(C)->getType(), TU);
180 case CXCursor_MemberRef:
181 return cxtype::MakeCXType(getCursorMemberRef(C).first->getType(), TU);
183 case CXCursor_VariableRef:
184 return cxtype::MakeCXType(getCursorVariableRef(C).first->getType(), TU);
186 case CXCursor_ObjCProtocolRef:
187 case CXCursor_TemplateRef:
188 case CXCursor_NamespaceRef:
189 case CXCursor_OverloadedDeclRef:
194 return MakeCXType(QualType(), TU);
197 return MakeCXType(QualType(), TU);
200 CXType clang_getTypedefDeclUnderlyingType(CXCursor C) {
201 using namespace cxcursor;
202 CXTranslationUnit TU = cxcursor::getCursorTU(C);
204 if (clang_isDeclaration(C.kind)) {
205 Decl *D = cxcursor::getCursorDecl(C);
207 if (TypedefNameDecl *TD = dyn_cast_or_null<TypedefNameDecl>(D)) {
208 QualType T = TD->getUnderlyingType();
209 return MakeCXType(T, TU);
212 return MakeCXType(QualType(), TU);
215 return MakeCXType(QualType(), TU);
218 CXType clang_getEnumDeclIntegerType(CXCursor C) {
219 using namespace cxcursor;
220 CXTranslationUnit TU = cxcursor::getCursorTU(C);
222 if (clang_isDeclaration(C.kind)) {
223 Decl *D = cxcursor::getCursorDecl(C);
225 if (EnumDecl *TD = dyn_cast_or_null<EnumDecl>(D)) {
226 QualType T = TD->getIntegerType();
227 return MakeCXType(T, TU);
230 return MakeCXType(QualType(), TU);
233 return MakeCXType(QualType(), TU);
236 long long clang_getEnumConstantDeclValue(CXCursor C) {
237 using namespace cxcursor;
239 if (clang_isDeclaration(C.kind)) {
240 Decl *D = cxcursor::getCursorDecl(C);
242 if (EnumConstantDecl *TD = dyn_cast_or_null<EnumConstantDecl>(D)) {
243 return TD->getInitVal().getSExtValue();
252 unsigned long long clang_getEnumConstantDeclUnsignedValue(CXCursor C) {
253 using namespace cxcursor;
255 if (clang_isDeclaration(C.kind)) {
256 Decl *D = cxcursor::getCursorDecl(C);
258 if (EnumConstantDecl *TD = dyn_cast_or_null<EnumConstantDecl>(D)) {
259 return TD->getInitVal().getZExtValue();
268 CXType clang_getCanonicalType(CXType CT) {
269 if (CT.kind == CXType_Invalid)
272 QualType T = GetQualType(CT);
273 CXTranslationUnit TU = GetTU(CT);
276 return MakeCXType(QualType(), GetTU(CT));
278 ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData);
279 return MakeCXType(AU->getASTContext().getCanonicalType(T), TU);
282 unsigned clang_isConstQualifiedType(CXType CT) {
283 QualType T = GetQualType(CT);
284 return T.isLocalConstQualified();
287 unsigned clang_isVolatileQualifiedType(CXType CT) {
288 QualType T = GetQualType(CT);
289 return T.isLocalVolatileQualified();
292 unsigned clang_isRestrictQualifiedType(CXType CT) {
293 QualType T = GetQualType(CT);
294 return T.isLocalRestrictQualified();
297 CXType clang_getPointeeType(CXType CT) {
298 QualType T = GetQualType(CT);
299 const Type *TP = T.getTypePtrOrNull();
302 return MakeCXType(QualType(), GetTU(CT));
304 switch (TP->getTypeClass()) {
306 T = cast<PointerType>(TP)->getPointeeType();
308 case Type::BlockPointer:
309 T = cast<BlockPointerType>(TP)->getPointeeType();
311 case Type::LValueReference:
312 case Type::RValueReference:
313 T = cast<ReferenceType>(TP)->getPointeeType();
315 case Type::ObjCObjectPointer:
316 T = cast<ObjCObjectPointerType>(TP)->getPointeeType();
322 return MakeCXType(T, GetTU(CT));
325 CXCursor clang_getTypeDeclaration(CXType CT) {
326 if (CT.kind == CXType_Invalid)
327 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
329 QualType T = GetQualType(CT);
330 const Type *TP = T.getTypePtrOrNull();
333 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
338 switch (TP->getTypeClass()) {
340 D = cast<TypedefType>(TP)->getDecl();
342 case Type::ObjCObject:
343 D = cast<ObjCObjectType>(TP)->getInterface();
345 case Type::ObjCInterface:
346 D = cast<ObjCInterfaceType>(TP)->getDecl();
350 D = cast<TagType>(TP)->getDecl();
352 case Type::TemplateSpecialization:
353 if (const RecordType *Record = TP->getAs<RecordType>())
354 D = Record->getDecl();
356 D = cast<TemplateSpecializationType>(TP)->getTemplateName()
357 .getAsTemplateDecl();
360 case Type::InjectedClassName:
361 D = cast<InjectedClassNameType>(TP)->getDecl();
364 // FIXME: Template type parameters!
366 case Type::Elaborated:
367 TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull();
375 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
377 return cxcursor::MakeCXCursor(D, GetTU(CT));
380 CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
382 #define TKIND(X) case CXType_##X: s = "" #X ""; break
399 case CXType_WChar: s = "WChar"; break;
417 TKIND(LValueReference);
418 TKIND(RValueReference);
422 TKIND(ObjCInterface);
423 TKIND(ObjCObjectPointer);
424 TKIND(FunctionNoProto);
425 TKIND(FunctionProto);
426 TKIND(ConstantArray);
430 return cxstring::createCXString(s);
433 unsigned clang_equalTypes(CXType A, CXType B) {
434 return A.data[0] == B.data[0] && A.data[1] == B.data[1];;
437 unsigned clang_isFunctionTypeVariadic(CXType X) {
438 QualType T = GetQualType(X);
442 if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>())
443 return (unsigned)FD->isVariadic();
445 if (T->getAs<FunctionNoProtoType>())
451 CXCallingConv clang_getFunctionTypeCallingConv(CXType X) {
452 QualType T = GetQualType(X);
454 return CXCallingConv_Invalid;
456 if (const FunctionType *FD = T->getAs<FunctionType>()) {
457 #define TCALLINGCONV(X) case CC_##X: return CXCallingConv_##X
458 switch (FD->getCallConv()) {
459 TCALLINGCONV(Default);
461 TCALLINGCONV(X86StdCall);
462 TCALLINGCONV(X86FastCall);
463 TCALLINGCONV(X86ThisCall);
464 TCALLINGCONV(X86Pascal);
466 TCALLINGCONV(AAPCS_VFP);
471 return CXCallingConv_Invalid;
474 int clang_getNumArgTypes(CXType X) {
475 QualType T = GetQualType(X);
479 if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) {
480 return FD->getNumArgs();
483 if (T->getAs<FunctionNoProtoType>()) {
490 CXType clang_getArgType(CXType X, unsigned i) {
491 QualType T = GetQualType(X);
493 return MakeCXType(QualType(), GetTU(X));
495 if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) {
496 unsigned numArgs = FD->getNumArgs();
498 return MakeCXType(QualType(), GetTU(X));
500 return MakeCXType(FD->getArgType(i), GetTU(X));
503 return MakeCXType(QualType(), GetTU(X));
506 CXType clang_getResultType(CXType X) {
507 QualType T = GetQualType(X);
509 return MakeCXType(QualType(), GetTU(X));
511 if (const FunctionType *FD = T->getAs<FunctionType>())
512 return MakeCXType(FD->getResultType(), GetTU(X));
514 return MakeCXType(QualType(), GetTU(X));
517 CXType clang_getCursorResultType(CXCursor C) {
518 if (clang_isDeclaration(C.kind)) {
519 Decl *D = cxcursor::getCursorDecl(C);
520 if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
521 return MakeCXType(MD->getResultType(), cxcursor::getCursorTU(C));
523 return clang_getResultType(clang_getCursorType(C));
526 return MakeCXType(QualType(), cxcursor::getCursorTU(C));
529 unsigned clang_isPODType(CXType X) {
530 QualType T = GetQualType(X);
534 CXTranslationUnit TU = GetTU(X);
535 ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData);
537 return T.isPODType(AU->getASTContext()) ? 1 : 0;
540 CXType clang_getElementType(CXType CT) {
541 QualType ET = QualType();
542 QualType T = GetQualType(CT);
543 const Type *TP = T.getTypePtrOrNull();
546 switch (TP->getTypeClass()) {
547 case Type::ConstantArray:
548 ET = cast<ConstantArrayType> (TP)->getElementType();
551 ET = cast<VectorType> (TP)->getElementType();
554 ET = cast<ComplexType> (TP)->getElementType();
560 return MakeCXType(ET, GetTU(CT));
563 long long clang_getNumElements(CXType CT) {
564 long long result = -1;
565 QualType T = GetQualType(CT);
566 const Type *TP = T.getTypePtrOrNull();
569 switch (TP->getTypeClass()) {
570 case Type::ConstantArray:
571 result = cast<ConstantArrayType> (TP)->getSize().getSExtValue();
574 result = cast<VectorType> (TP)->getNumElements();
583 CXType clang_getArrayElementType(CXType CT) {
584 QualType ET = QualType();
585 QualType T = GetQualType(CT);
586 const Type *TP = T.getTypePtrOrNull();
589 switch (TP->getTypeClass()) {
590 case Type::ConstantArray:
591 ET = cast<ConstantArrayType> (TP)->getElementType();
597 return MakeCXType(ET, GetTU(CT));
600 long long clang_getArraySize(CXType CT) {
601 long long result = -1;
602 QualType T = GetQualType(CT);
603 const Type *TP = T.getTypePtrOrNull();
606 switch (TP->getTypeClass()) {
607 case Type::ConstantArray:
608 result = cast<ConstantArrayType> (TP)->getSize().getSExtValue();
617 CXString clang_getDeclObjCTypeEncoding(CXCursor C) {
618 if ((C.kind < CXCursor_FirstDecl) || (C.kind > CXCursor_LastDecl))
619 return cxstring::createCXString("");
621 Decl *D = static_cast<Decl*>(C.data[0]);
622 CXTranslationUnit TU = static_cast<CXTranslationUnit>(C.data[2]);
623 ASTUnit *AU = static_cast<ASTUnit*>(TU->TUData);
624 ASTContext &Ctx = AU->getASTContext();
625 std::string encoding;
627 if (ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
628 if (Ctx.getObjCEncodingForMethodDecl(OMD, encoding))
629 return cxstring::createCXString("?");
630 } else if (ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(D))
631 Ctx.getObjCEncodingForPropertyDecl(OPD, NULL, encoding);
632 else if (FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
633 Ctx.getObjCEncodingForFunctionDecl(FD, encoding);
636 if (TypeDecl *TD = dyn_cast<TypeDecl>(D))
637 Ty = Ctx.getTypeDeclType(TD);
638 if (ValueDecl *VD = dyn_cast<ValueDecl>(D))
640 else return cxstring::createCXString("?");
641 Ctx.getObjCEncodingForType(Ty, encoding);
644 return cxstring::createCXString(encoding);