Add CXType and an initial set of supporting functions to libclang. This exposes details of
Clang's representation of the C type system to clients. It is nowhere near complete, and will
be expanded on demand.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@103809 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/tools/libclang/CMakeLists.txt b/tools/libclang/CMakeLists.txt
index d3de94a..62c9738 100644
--- a/tools/libclang/CMakeLists.txt
+++ b/tools/libclang/CMakeLists.txt
@@ -26,6 +26,7 @@
CIndexUSRs.cpp
CIndexer.cpp
CXCursor.cpp
+ CXTypes.cpp
../../include/clang-c/Index.h
)
set_target_properties(libclang PROPERTIES OUTPUT_NAME clang)
diff --git a/tools/libclang/CXTypes.cpp b/tools/libclang/CXTypes.cpp
new file mode 100644
index 0000000..28dc12a
--- /dev/null
+++ b/tools/libclang/CXTypes.cpp
@@ -0,0 +1,246 @@
+//===- 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);
+ 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);
+
+ 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) {
+ QualType T = GetQualType(CT);
+ Type *TP = T.getTypePtr();
+ Decl *D = 0;
+
+ switch (TP->getTypeClass()) {
+ case Type::Typedef:
+ D = cast<TypedefType>(TP)->getDecl();
+ 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);
+ }
+#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];;
+}
+
+} // end: extern "C"
diff --git a/tools/libclang/libclang.darwin.exports b/tools/libclang/libclang.darwin.exports
index b361168..2ea3677 100644
--- a/tools/libclang/libclang.darwin.exports
+++ b/tools/libclang/libclang.darwin.exports
@@ -21,7 +21,9 @@
_clang_enableStackTraces
_clang_equalCursors
_clang_equalLocations
+_clang_equalTypes
_clang_formatDiagnostic
+_clang_getCanonicalType
_clang_getCString
_clang_getClangVersion
_clang_getCompletionChunkCompletionString
@@ -37,6 +39,7 @@
_clang_getCursorLocation
_clang_getCursorReferenced
_clang_getCursorSpelling
+_clang_getCursorType
_clang_getCursorUSR
_clang_getDefinitionSpellingAndExtent
_clang_getDiagnostic
@@ -58,6 +61,7 @@
_clang_getNullRange
_clang_getNumCompletionChunks
_clang_getNumDiagnostics
+_clang_getPointeeType
_clang_getRange
_clang_getRangeEnd
_clang_getRangeStart
@@ -67,6 +71,8 @@
_clang_getTokenSpelling
_clang_getTranslationUnitCursor
_clang_getTranslationUnitSpelling
+_clang_getTypeDeclaration
+_clang_getTypeKindSpelling
_clang_isCursorDefinition
_clang_isDeclaration
_clang_isExpression
diff --git a/tools/libclang/libclang.exports b/tools/libclang/libclang.exports
index 991bb06..321a4cc 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -21,7 +21,9 @@
clang_enableStackTraces
clang_equalCursors
clang_equalLocations
+clang_equalTypes
clang_formatDiagnostic
+clang_getCanonicalType
clang_getCString
clang_getClangVersion
clang_getCompletionChunkCompletionString
@@ -37,6 +39,7 @@
clang_getCursorLocation
clang_getCursorReferenced
clang_getCursorSpelling
+clang_getCursorType
clang_getCursorUSR
clang_getDefinitionSpellingAndExtent
clang_getDiagnostic
@@ -58,6 +61,7 @@
clang_getNullRange
clang_getNumCompletionChunks
clang_getNumDiagnostics
+clang_getPointeeType
clang_getRange
clang_getRangeEnd
clang_getRangeStart
@@ -67,6 +71,8 @@
clang_getTokenSpelling
clang_getTranslationUnitCursor
clang_getTranslationUnitSpelling
+clang_getTypeDeclaration
+clang_getTypeKindSpelling
clang_isCursorDefinition
clang_isDeclaration
clang_isExpression