//===- CXTypes.cpp - Implements 'CXTypes' aspect of libclang ------------===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===--------------------------------------------------------------------===// // // This file implements the 'CXTypes' API hooks in the Clang-C library. // //===--------------------------------------------------------------------===// #include "CIndexer.h" #include "CXCursor.h" #include "CXType.h" #include "clang/AST/Expr.h" #include "clang/AST/Type.h" #include "clang/AST/Decl.h" #include "clang/AST/DeclObjC.h" #include "clang/Frontend/ASTUnit.h" using namespace clang; static CXTypeKind GetBuiltinTypeKind(const BuiltinType *BT) { #define BTCASE(K) case BuiltinType::K: return CXType_##K switch (BT->getKind()) { BTCASE(Void); BTCASE(Bool); BTCASE(Char_U); BTCASE(UChar); BTCASE(Char16); BTCASE(Char32); BTCASE(UShort); BTCASE(UInt); BTCASE(ULong); BTCASE(ULongLong); BTCASE(UInt128); BTCASE(Char_S); BTCASE(SChar); BTCASE(WChar); BTCASE(Short); BTCASE(Int); BTCASE(Long); BTCASE(LongLong); BTCASE(Int128); BTCASE(Float); BTCASE(Double); BTCASE(LongDouble); BTCASE(NullPtr); BTCASE(Overload); BTCASE(Dependent); BTCASE(ObjCId); BTCASE(ObjCClass); BTCASE(ObjCSel); default: return CXType_Unexposed; } #undef BTCASE } static CXTypeKind GetTypeKind(QualType T) { Type *TP = T.getTypePtr(); if (!TP) return CXType_Invalid; #define TKCASE(K) case Type::K: return CXType_##K switch (TP->getTypeClass()) { case Type::Builtin: return GetBuiltinTypeKind(cast(TP)); TKCASE(Complex); TKCASE(Pointer); TKCASE(BlockPointer); TKCASE(LValueReference); TKCASE(RValueReference); TKCASE(Record); TKCASE(Enum); TKCASE(Typedef); TKCASE(ObjCInterface); TKCASE(ObjCObjectPointer); TKCASE(FunctionNoProto); TKCASE(FunctionProto); default: return CXType_Unexposed; } #undef TKCASE } CXType cxtype::MakeCXType(QualType T, ASTUnit *TU) { CXTypeKind TK = GetTypeKind(T); CXType CT = { TK, { TK == CXType_Invalid ? 0 : T.getAsOpaquePtr(), TU }}; return CT; } using cxtype::MakeCXType; static inline QualType GetQualType(CXType CT) { return QualType::getFromOpaquePtr(CT.data[0]); } static inline ASTUnit* GetASTU(CXType CT) { return static_cast(CT.data[1]); } extern "C" { CXType clang_getCursorType(CXCursor C) { ASTUnit *AU = cxcursor::getCursorASTUnit(C); if (clang_isExpression(C.kind)) { QualType T = cxcursor::getCursorExpr(C)->getType(); return MakeCXType(T, AU); } if (clang_isDeclaration(C.kind)) { Decl *D = cxcursor::getCursorDecl(C); if (TypeDecl *TD = dyn_cast(D)) return MakeCXType(QualType(TD->getTypeForDecl(), 0), AU); if (ObjCInterfaceDecl *ID = dyn_cast(D)) return MakeCXType(QualType(ID->getTypeForDecl(), 0), AU); if (ValueDecl *VD = dyn_cast(D)) return MakeCXType(VD->getType(), AU); if (ObjCPropertyDecl *PD = dyn_cast(D)) return MakeCXType(PD->getType(), AU); if (FunctionDecl *FD = dyn_cast(D)) return MakeCXType(FD->getType(), AU); return MakeCXType(QualType(), AU); } return MakeCXType(QualType(), AU); } CXType clang_getCanonicalType(CXType CT) { if (CT.kind == CXType_Invalid) return CT; QualType T = GetQualType(CT); if (T.isNull()) return MakeCXType(QualType(), GetASTU(CT)); ASTUnit *AU = GetASTU(CT); return MakeCXType(AU->getASTContext().getCanonicalType(T), AU); } CXType clang_getPointeeType(CXType CT) { QualType T = GetQualType(CT); Type *TP = T.getTypePtr(); if (!TP) return MakeCXType(QualType(), GetASTU(CT)); switch (TP->getTypeClass()) { case Type::Pointer: T = cast(TP)->getPointeeType(); break; case Type::BlockPointer: T = cast(TP)->getPointeeType(); break; case Type::LValueReference: case Type::RValueReference: T = cast(TP)->getPointeeType(); break; case Type::ObjCObjectPointer: T = cast(TP)->getPointeeType(); break; default: T = QualType(); break; } return MakeCXType(T, GetASTU(CT)); } CXCursor clang_getTypeDeclaration(CXType CT) { if (CT.kind == CXType_Invalid) return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); QualType T = GetQualType(CT); Type *TP = T.getTypePtr(); if (!TP) return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); Decl *D = 0; switch (TP->getTypeClass()) { case Type::Typedef: D = cast(TP)->getDecl(); break; case Type::ObjCObject: D = cast(TP)->getInterface(); break; case Type::ObjCInterface: D = cast(TP)->getDecl(); break; case Type::Record: case Type::Enum: D = cast(TP)->getDecl(); break; default: break; } if (!D) return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound); return cxcursor::MakeCXCursor(D, GetASTU(CT)); } CXString clang_getTypeKindSpelling(enum CXTypeKind K) { const char *s = 0; #define TKIND(X) case CXType_##X: s = "" #X ""; break switch (K) { TKIND(Invalid); TKIND(Unexposed); TKIND(Void); TKIND(Bool); TKIND(Char_U); TKIND(UChar); TKIND(Char16); TKIND(Char32); TKIND(UShort); TKIND(UInt); TKIND(ULong); TKIND(ULongLong); TKIND(UInt128); TKIND(Char_S); TKIND(SChar); TKIND(WChar); TKIND(Short); TKIND(Int); TKIND(Long); TKIND(LongLong); TKIND(Int128); TKIND(Float); TKIND(Double); TKIND(LongDouble); TKIND(NullPtr); TKIND(Overload); TKIND(Dependent); TKIND(ObjCId); TKIND(ObjCClass); TKIND(ObjCSel); TKIND(Complex); TKIND(Pointer); TKIND(BlockPointer); TKIND(LValueReference); TKIND(RValueReference); TKIND(Record); TKIND(Enum); TKIND(Typedef); TKIND(ObjCInterface); TKIND(ObjCObjectPointer); TKIND(FunctionNoProto); TKIND(FunctionProto); } #undef TKIND return cxstring::createCXString(s); } unsigned clang_equalTypes(CXType A, CXType B) { return A.data[0] == B.data[0] && A.data[1] == B.data[1];; } CXType clang_getResultType(CXType X) { QualType T = GetQualType(X); if (!T.getTypePtr()) return MakeCXType(QualType(), GetASTU(X)); if (const FunctionType *FD = T->getAs()) return MakeCXType(FD->getResultType(), GetASTU(X)); return MakeCXType(QualType(), GetASTU(X)); } CXType clang_getCursorResultType(CXCursor C) { if (clang_isDeclaration(C.kind)) { Decl *D = cxcursor::getCursorDecl(C); if (const ObjCMethodDecl *MD = dyn_cast(D)) return MakeCXType(MD->getResultType(), cxcursor::getCursorASTUnit(C)); return clang_getResultType(clang_getCursorType(C)); } return MakeCXType(QualType(), cxcursor::getCursorASTUnit(C)); } unsigned clang_isPODType(CXType X) { QualType T = GetQualType(X); if (!T.getTypePtr()) return 0; return T->isPODType() ? 1 : 0; } } // end: extern "C"