| //===- 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 "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<BuiltinType>(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 |
| } |
| |
| static CXType MakeCXType(QualType T, ASTUnit *TU) { |
| CXTypeKind TK = GetTypeKind(T); |
| CXType CT = { TK, { TK == CXType_Invalid ? 0 : T.getAsOpaquePtr(), TU }}; |
| return CT; |
| } |
| |
| static inline QualType GetQualType(CXType CT) { |
| return QualType::getFromOpaquePtr(CT.data[0]); |
| } |
| |
| static inline ASTUnit* GetASTU(CXType CT) { |
| return static_cast<ASTUnit*>(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<TypeDecl>(D)) |
| return MakeCXType(QualType(TD->getTypeForDecl(), 0), AU); |
| if (ObjCInterfaceDecl *ID = dyn_cast<ObjCInterfaceDecl>(D)) |
| return MakeCXType(QualType(ID->getTypeForDecl(), 0), AU); |
| if (ValueDecl *VD = dyn_cast<ValueDecl>(D)) |
| return MakeCXType(VD->getType(), AU); |
| if (ObjCPropertyDecl *PD = dyn_cast<ObjCPropertyDecl>(D)) |
| return MakeCXType(PD->getType(), AU); |
| if (FunctionDecl *FD = dyn_cast<FunctionDecl>(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<PointerType>(TP)->getPointeeType(); |
| break; |
| case Type::BlockPointer: |
| T = cast<BlockPointerType>(TP)->getPointeeType(); |
| break; |
| case Type::LValueReference: |
| case Type::RValueReference: |
| T = cast<ReferenceType>(TP)->getPointeeType(); |
| break; |
| case Type::ObjCObjectPointer: |
| T = cast<ObjCObjectPointerType>(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<TypedefType>(TP)->getDecl(); |
| break; |
| case Type::ObjCObject: |
| D = cast<ObjCObjectType>(TP)->getInterface(); |
| break; |
| case Type::ObjCInterface: |
| D = cast<ObjCInterfaceType>(TP)->getDecl(); |
| break; |
| case Type::Record: |
| case Type::Enum: |
| D = cast<TagType>(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<FunctionType>()) |
| 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<ObjCMethodDecl>(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" |