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 //===--------------------------------------------------------------------===//
17 #include "CXTranslationUnit.h"
19 #include "clang/AST/Decl.h"
20 #include "clang/AST/DeclObjC.h"
21 #include "clang/AST/DeclTemplate.h"
22 #include "clang/AST/Expr.h"
23 #include "clang/AST/Type.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 = cxtu::getASTUnit(TU)->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);
135 return MakeCXType(QualType(), TU);
137 ASTContext &Context = cxtu::getASTUnit(TU)->getASTContext();
138 if (clang_isExpression(C.kind)) {
139 QualType T = cxcursor::getCursorExpr(C)->getType();
140 return MakeCXType(T, TU);
143 if (clang_isDeclaration(C.kind)) {
144 const Decl *D = cxcursor::getCursorDecl(C);
146 return MakeCXType(QualType(), TU);
148 if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
149 return MakeCXType(Context.getTypeDeclType(TD), TU);
150 if (const ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D))
151 return MakeCXType(Context.getObjCInterfaceType(ID), TU);
152 if (const DeclaratorDecl *DD = dyn_cast<DeclaratorDecl>(D)) {
153 if (TypeSourceInfo *TSInfo = DD->getTypeSourceInfo())
154 return MakeCXType(TSInfo->getType(), TU);
155 return MakeCXType(DD->getType(), TU);
157 if (const ValueDecl *VD = dyn_cast<ValueDecl>(D))
158 return MakeCXType(VD->getType(), TU);
159 if (const ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D))
160 return MakeCXType(PD->getType(), TU);
161 if (const FunctionTemplateDecl *FTD = dyn_cast<FunctionTemplateDecl>(D)) {
162 if (TypeSourceInfo *TSInfo = FTD->getTemplatedDecl()->getTypeSourceInfo())
163 return MakeCXType(TSInfo->getType(), TU);
164 return MakeCXType(FTD->getTemplatedDecl()->getType(), TU);
166 return MakeCXType(QualType(), TU);
169 if (clang_isReference(C.kind)) {
171 case CXCursor_ObjCSuperClassRef: {
173 = Context.getObjCInterfaceType(getCursorObjCSuperClassRef(C).first);
174 return MakeCXType(T, TU);
177 case CXCursor_ObjCClassRef: {
178 QualType T = Context.getObjCInterfaceType(getCursorObjCClassRef(C).first);
179 return MakeCXType(T, TU);
182 case CXCursor_TypeRef: {
183 QualType T = Context.getTypeDeclType(getCursorTypeRef(C).first);
184 return MakeCXType(T, TU);
188 case CXCursor_CXXBaseSpecifier:
189 return cxtype::MakeCXType(getCursorCXXBaseSpecifier(C)->getType(), TU);
191 case CXCursor_MemberRef:
192 return cxtype::MakeCXType(getCursorMemberRef(C).first->getType(), TU);
194 case CXCursor_VariableRef:
195 return cxtype::MakeCXType(getCursorVariableRef(C).first->getType(), TU);
197 case CXCursor_ObjCProtocolRef:
198 case CXCursor_TemplateRef:
199 case CXCursor_NamespaceRef:
200 case CXCursor_OverloadedDeclRef:
205 return MakeCXType(QualType(), TU);
208 return MakeCXType(QualType(), TU);
211 CXString clang_getTypeSpelling(CXType CT) {
212 QualType T = GetQualType(CT);
214 return cxstring::createEmpty();
216 CXTranslationUnit TU = GetTU(CT);
218 llvm::raw_svector_ostream OS(Str);
219 PrintingPolicy PP(cxtu::getASTUnit(TU)->getASTContext().getLangOpts());
223 return cxstring::createDup(OS.str());
226 CXType clang_getTypedefDeclUnderlyingType(CXCursor C) {
227 using namespace cxcursor;
228 CXTranslationUnit TU = cxcursor::getCursorTU(C);
230 if (clang_isDeclaration(C.kind)) {
231 const Decl *D = cxcursor::getCursorDecl(C);
233 if (const TypedefNameDecl *TD = dyn_cast_or_null<TypedefNameDecl>(D)) {
234 QualType T = TD->getUnderlyingType();
235 return MakeCXType(T, TU);
238 return MakeCXType(QualType(), TU);
241 return MakeCXType(QualType(), TU);
244 CXType clang_getEnumDeclIntegerType(CXCursor C) {
245 using namespace cxcursor;
246 CXTranslationUnit TU = cxcursor::getCursorTU(C);
248 if (clang_isDeclaration(C.kind)) {
249 const Decl *D = cxcursor::getCursorDecl(C);
251 if (const EnumDecl *TD = dyn_cast_or_null<EnumDecl>(D)) {
252 QualType T = TD->getIntegerType();
253 return MakeCXType(T, TU);
256 return MakeCXType(QualType(), TU);
259 return MakeCXType(QualType(), TU);
262 long long clang_getEnumConstantDeclValue(CXCursor C) {
263 using namespace cxcursor;
265 if (clang_isDeclaration(C.kind)) {
266 const Decl *D = cxcursor::getCursorDecl(C);
268 if (const EnumConstantDecl *TD = dyn_cast_or_null<EnumConstantDecl>(D)) {
269 return TD->getInitVal().getSExtValue();
278 unsigned long long clang_getEnumConstantDeclUnsignedValue(CXCursor C) {
279 using namespace cxcursor;
281 if (clang_isDeclaration(C.kind)) {
282 const Decl *D = cxcursor::getCursorDecl(C);
284 if (const EnumConstantDecl *TD = dyn_cast_or_null<EnumConstantDecl>(D)) {
285 return TD->getInitVal().getZExtValue();
294 int clang_getFieldDeclBitWidth(CXCursor C) {
295 using namespace cxcursor;
297 if (clang_isDeclaration(C.kind)) {
298 const Decl *D = getCursorDecl(C);
300 if (const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(D)) {
301 if (FD->isBitField())
302 return FD->getBitWidthValue(getCursorContext(C));
309 CXType clang_getCanonicalType(CXType CT) {
310 if (CT.kind == CXType_Invalid)
313 QualType T = GetQualType(CT);
314 CXTranslationUnit TU = GetTU(CT);
317 return MakeCXType(QualType(), GetTU(CT));
319 return MakeCXType(cxtu::getASTUnit(TU)->getASTContext()
320 .getCanonicalType(T),
324 unsigned clang_isConstQualifiedType(CXType CT) {
325 QualType T = GetQualType(CT);
326 return T.isLocalConstQualified();
329 unsigned clang_isVolatileQualifiedType(CXType CT) {
330 QualType T = GetQualType(CT);
331 return T.isLocalVolatileQualified();
334 unsigned clang_isRestrictQualifiedType(CXType CT) {
335 QualType T = GetQualType(CT);
336 return T.isLocalRestrictQualified();
339 CXType clang_getPointeeType(CXType CT) {
340 QualType T = GetQualType(CT);
341 const Type *TP = T.getTypePtrOrNull();
344 return MakeCXType(QualType(), GetTU(CT));
346 switch (TP->getTypeClass()) {
348 T = cast<PointerType>(TP)->getPointeeType();
350 case Type::BlockPointer:
351 T = cast<BlockPointerType>(TP)->getPointeeType();
353 case Type::LValueReference:
354 case Type::RValueReference:
355 T = cast<ReferenceType>(TP)->getPointeeType();
357 case Type::ObjCObjectPointer:
358 T = cast<ObjCObjectPointerType>(TP)->getPointeeType();
364 return MakeCXType(T, GetTU(CT));
367 CXCursor clang_getTypeDeclaration(CXType CT) {
368 if (CT.kind == CXType_Invalid)
369 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
371 QualType T = GetQualType(CT);
372 const Type *TP = T.getTypePtrOrNull();
375 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
380 switch (TP->getTypeClass()) {
382 D = cast<TypedefType>(TP)->getDecl();
384 case Type::ObjCObject:
385 D = cast<ObjCObjectType>(TP)->getInterface();
387 case Type::ObjCInterface:
388 D = cast<ObjCInterfaceType>(TP)->getDecl();
392 D = cast<TagType>(TP)->getDecl();
394 case Type::TemplateSpecialization:
395 if (const RecordType *Record = TP->getAs<RecordType>())
396 D = Record->getDecl();
398 D = cast<TemplateSpecializationType>(TP)->getTemplateName()
399 .getAsTemplateDecl();
402 case Type::InjectedClassName:
403 D = cast<InjectedClassNameType>(TP)->getDecl();
406 // FIXME: Template type parameters!
408 case Type::Elaborated:
409 TP = cast<ElaboratedType>(TP)->getNamedType().getTypePtrOrNull();
417 return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
419 return cxcursor::MakeCXCursor(D, GetTU(CT));
422 CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
424 #define TKIND(X) case CXType_##X: s = "" #X ""; break
441 case CXType_WChar: s = "WChar"; break;
459 TKIND(LValueReference);
460 TKIND(RValueReference);
464 TKIND(ObjCInterface);
465 TKIND(ObjCObjectPointer);
466 TKIND(FunctionNoProto);
467 TKIND(FunctionProto);
468 TKIND(ConstantArray);
472 return cxstring::createRef(s);
475 unsigned clang_equalTypes(CXType A, CXType B) {
476 return A.data[0] == B.data[0] && A.data[1] == B.data[1];;
479 unsigned clang_isFunctionTypeVariadic(CXType X) {
480 QualType T = GetQualType(X);
484 if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>())
485 return (unsigned)FD->isVariadic();
487 if (T->getAs<FunctionNoProtoType>())
493 CXCallingConv clang_getFunctionTypeCallingConv(CXType X) {
494 QualType T = GetQualType(X);
496 return CXCallingConv_Invalid;
498 if (const FunctionType *FD = T->getAs<FunctionType>()) {
499 #define TCALLINGCONV(X) case CC_##X: return CXCallingConv_##X
500 switch (FD->getCallConv()) {
501 TCALLINGCONV(Default);
503 TCALLINGCONV(X86StdCall);
504 TCALLINGCONV(X86FastCall);
505 TCALLINGCONV(X86ThisCall);
506 TCALLINGCONV(X86Pascal);
508 TCALLINGCONV(AAPCS_VFP);
509 TCALLINGCONV(PnaclCall);
510 TCALLINGCONV(IntelOclBicc);
515 return CXCallingConv_Invalid;
518 int clang_getNumArgTypes(CXType X) {
519 QualType T = GetQualType(X);
523 if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) {
524 return FD->getNumArgs();
527 if (T->getAs<FunctionNoProtoType>()) {
534 CXType clang_getArgType(CXType X, unsigned i) {
535 QualType T = GetQualType(X);
537 return MakeCXType(QualType(), GetTU(X));
539 if (const FunctionProtoType *FD = T->getAs<FunctionProtoType>()) {
540 unsigned numArgs = FD->getNumArgs();
542 return MakeCXType(QualType(), GetTU(X));
544 return MakeCXType(FD->getArgType(i), GetTU(X));
547 return MakeCXType(QualType(), GetTU(X));
550 CXType clang_getResultType(CXType X) {
551 QualType T = GetQualType(X);
553 return MakeCXType(QualType(), GetTU(X));
555 if (const FunctionType *FD = T->getAs<FunctionType>())
556 return MakeCXType(FD->getResultType(), GetTU(X));
558 return MakeCXType(QualType(), GetTU(X));
561 CXType clang_getCursorResultType(CXCursor C) {
562 if (clang_isDeclaration(C.kind)) {
563 const Decl *D = cxcursor::getCursorDecl(C);
564 if (const ObjCMethodDecl *MD = dyn_cast_or_null<ObjCMethodDecl>(D))
565 return MakeCXType(MD->getResultType(), cxcursor::getCursorTU(C));
567 return clang_getResultType(clang_getCursorType(C));
570 return MakeCXType(QualType(), cxcursor::getCursorTU(C));
573 unsigned clang_isPODType(CXType X) {
574 QualType T = GetQualType(X);
578 CXTranslationUnit TU = GetTU(X);
580 return T.isPODType(cxtu::getASTUnit(TU)->getASTContext()) ? 1 : 0;
583 CXType clang_getElementType(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();
594 ET = cast<VectorType> (TP)->getElementType();
597 ET = cast<ComplexType> (TP)->getElementType();
603 return MakeCXType(ET, GetTU(CT));
606 long long clang_getNumElements(CXType CT) {
607 long long result = -1;
608 QualType T = GetQualType(CT);
609 const Type *TP = T.getTypePtrOrNull();
612 switch (TP->getTypeClass()) {
613 case Type::ConstantArray:
614 result = cast<ConstantArrayType> (TP)->getSize().getSExtValue();
617 result = cast<VectorType> (TP)->getNumElements();
626 CXType clang_getArrayElementType(CXType CT) {
627 QualType ET = QualType();
628 QualType T = GetQualType(CT);
629 const Type *TP = T.getTypePtrOrNull();
632 switch (TP->getTypeClass()) {
633 case Type::ConstantArray:
634 ET = cast<ConstantArrayType> (TP)->getElementType();
640 return MakeCXType(ET, GetTU(CT));
643 long long clang_getArraySize(CXType CT) {
644 long long result = -1;
645 QualType T = GetQualType(CT);
646 const Type *TP = T.getTypePtrOrNull();
649 switch (TP->getTypeClass()) {
650 case Type::ConstantArray:
651 result = cast<ConstantArrayType> (TP)->getSize().getSExtValue();
660 long long clang_Type_getAlignOf(CXType T) {
661 if (T.kind == CXType_Invalid)
662 return CXTypeLayoutError_Invalid;
663 ASTContext &Ctx = cxtu::getASTUnit(GetTU(T))->getASTContext();
664 QualType QT = GetQualType(T);
665 // [expr.alignof] p1: return size_t value for complete object type, reference
667 // [expr.alignof] p3: if reference type, return size of referenced type
668 if (QT->isReferenceType())
669 QT = QT.getNonReferenceType();
670 if (QT->isIncompleteType())
671 return CXTypeLayoutError_Incomplete;
672 if (QT->isDependentType())
673 return CXTypeLayoutError_Dependent;
674 // Exceptions by GCC extension - see ASTContext.cpp:1313 getTypeInfoImpl
675 // if (QT->isFunctionType()) return 4; // Bug #15511 - should be 1
676 // if (QT->isVoidType()) return 1;
677 return Ctx.getTypeAlignInChars(QT).getQuantity();
680 long long clang_Type_getSizeOf(CXType T) {
681 if (T.kind == CXType_Invalid)
682 return CXTypeLayoutError_Invalid;
683 ASTContext &Ctx = cxtu::getASTUnit(GetTU(T))->getASTContext();
684 QualType QT = GetQualType(T);
685 // [expr.sizeof] p2: if reference type, return size of referenced type
686 if (QT->isReferenceType())
687 QT = QT.getNonReferenceType();
688 // [expr.sizeof] p1: return -1 on: func, incomplete, bitfield, incomplete
690 // Note: We get the cxtype, not the cxcursor, so we can't call
691 // FieldDecl->isBitField()
692 // [expr.sizeof] p3: pointer ok, function not ok.
693 // [gcc extension] lib/AST/ExprConstant.cpp:1372 HandleSizeof : vla == error
694 if (QT->isIncompleteType())
695 return CXTypeLayoutError_Incomplete;
696 if (QT->isDependentType())
697 return CXTypeLayoutError_Dependent;
698 if (!QT->isConstantSizeType())
699 return CXTypeLayoutError_NotConstantSize;
700 // [gcc extension] lib/AST/ExprConstant.cpp:1372
701 // HandleSizeof : {voidtype,functype} == 1
702 // not handled by ASTContext.cpp:1313 getTypeInfoImpl
703 if (QT->isVoidType() || QT->isFunctionType())
705 return Ctx.getTypeSizeInChars(QT).getQuantity();
708 static long long visitRecordForValidation(const RecordDecl *RD) {
709 for (RecordDecl::field_iterator I = RD->field_begin(), E = RD->field_end();
711 QualType FQT = (*I)->getType();
712 if (FQT->isIncompleteType())
713 return CXTypeLayoutError_Incomplete;
714 if (FQT->isDependentType())
715 return CXTypeLayoutError_Dependent;
717 if (const RecordType *ChildType = (*I)->getType()->getAs<RecordType>()) {
718 if (const RecordDecl *Child = ChildType->getDecl()) {
719 long long ret = visitRecordForValidation(Child);
724 // else try next field
729 long long clang_Type_getOffsetOf(CXType PT, const char *S) {
730 // check that PT is not incomplete/dependent
731 CXCursor PC = clang_getTypeDeclaration(PT);
732 if (clang_isInvalid(PC.kind))
733 return CXTypeLayoutError_Invalid;
734 const RecordDecl *RD =
735 dyn_cast_or_null<RecordDecl>(cxcursor::getCursorDecl(PC));
737 return CXTypeLayoutError_Invalid;
738 RD = RD->getDefinition();
740 return CXTypeLayoutError_Incomplete;
741 QualType RT = GetQualType(PT);
742 if (RT->isIncompleteType())
743 return CXTypeLayoutError_Incomplete;
744 if (RT->isDependentType())
745 return CXTypeLayoutError_Dependent;
746 // We recurse into all record fields to detect incomplete and dependent types.
747 long long Error = visitRecordForValidation(RD);
751 return CXTypeLayoutError_InvalidFieldName;
753 ASTContext &Ctx = cxtu::getASTUnit(GetTU(PT))->getASTContext();
754 IdentifierInfo *II = &Ctx.Idents.get(S);
755 DeclarationName FieldName(II);
756 RecordDecl::lookup_const_result Res = RD->lookup(FieldName);
757 // If a field of the parent record is incomplete, lookup will fail.
758 // and we would return InvalidFieldName instead of Incomplete.
759 // But this erroneous results does protects again a hidden assertion failure
760 // in the RecordLayoutBuilder
762 return CXTypeLayoutError_InvalidFieldName;
763 if (const FieldDecl *FD = dyn_cast<FieldDecl>(Res.front()))
764 return Ctx.getFieldOffset(FD);
765 if (const IndirectFieldDecl *IFD = dyn_cast<IndirectFieldDecl>(Res.front()))
766 return Ctx.getFieldOffset(IFD);
767 // we don't want any other Decl Type.
768 return CXTypeLayoutError_InvalidFieldName;
771 unsigned clang_Cursor_isBitField(CXCursor C) {
772 if (!clang_isDeclaration(C.kind))
774 const FieldDecl *FD = dyn_cast_or_null<FieldDecl>(cxcursor::getCursorDecl(C));
777 return FD->isBitField();
780 CXString clang_getDeclObjCTypeEncoding(CXCursor C) {
781 if (!clang_isDeclaration(C.kind))
782 return cxstring::createEmpty();
784 const Decl *D = cxcursor::getCursorDecl(C);
785 ASTContext &Ctx = cxcursor::getCursorContext(C);
786 std::string encoding;
788 if (const ObjCMethodDecl *OMD = dyn_cast<ObjCMethodDecl>(D)) {
789 if (Ctx.getObjCEncodingForMethodDecl(OMD, encoding))
790 return cxstring::createRef("?");
791 } else if (const ObjCPropertyDecl *OPD = dyn_cast<ObjCPropertyDecl>(D))
792 Ctx.getObjCEncodingForPropertyDecl(OPD, NULL, encoding);
793 else if (const FunctionDecl *FD = dyn_cast<FunctionDecl>(D))
794 Ctx.getObjCEncodingForFunctionDecl(FD, encoding);
797 if (const TypeDecl *TD = dyn_cast<TypeDecl>(D))
798 Ty = Ctx.getTypeDeclType(TD);
799 if (const ValueDecl *VD = dyn_cast<ValueDecl>(D))
801 else return cxstring::createRef("?");
802 Ctx.getObjCEncodingForType(Ty, encoding);
805 return cxstring::createDup(encoding);