From 95f33555a6d51b6537a9ed3968c3d1c2e4991b51 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Thu, 26 Aug 2010 01:42:22 +0000 Subject: Add libclang API hook "clang_getIBOutletCollectionType" to query the collection type for iboutletcollection attributes. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@112139 91177308-0d34-0410-b5e6-96231b3b80d8 --- tools/libclang/CXType.cpp | 297 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 297 insertions(+) create mode 100644 tools/libclang/CXType.cpp (limited to 'tools/libclang/CXType.cpp') diff --git a/tools/libclang/CXType.cpp b/tools/libclang/CXType.cpp new file mode 100644 index 0000000000..aa173cae32 --- /dev/null +++ b/tools/libclang/CXType.cpp @@ -0,0 +1,297 @@ +//===- 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" -- cgit v1.2.3-18-g5258