aboutsummaryrefslogtreecommitdiff
path: root/tools
diff options
context:
space:
mode:
Diffstat (limited to 'tools')
-rw-r--r--tools/c-index-test/c-index-test.c29
-rw-r--r--tools/libclang/CMakeLists.txt1
-rw-r--r--tools/libclang/CXTypes.cpp246
-rw-r--r--tools/libclang/libclang.darwin.exports6
-rw-r--r--tools/libclang/libclang.exports6
5 files changed, 288 insertions, 0 deletions
diff --git a/tools/c-index-test/c-index-test.c b/tools/c-index-test/c-index-test.c
index 494181675c..12fede209e 100644
--- a/tools/c-index-test/c-index-test.c
+++ b/tools/c-index-test/c-index-test.c
@@ -447,6 +447,31 @@ static enum CXChildVisitResult PrintLinkage(CXCursor cursor, CXCursor p,
}
/******************************************************************************/
+/* Typekind testing. */
+/******************************************************************************/
+
+static enum CXChildVisitResult PrintTypeKind(CXCursor cursor, CXCursor p,
+ CXClientData d) {
+
+ if (!clang_isInvalid(clang_getCursorKind(cursor))) {
+ CXType T = clang_getCursorType(cursor);
+ CXType CT = clang_getCanonicalType(T);
+ CXString S = clang_getTypeKindSpelling(T.kind);
+ PrintCursor(cursor);
+ printf(" typekind=%s", clang_getCString(S));
+ if (!clang_equalTypes(T, CT)) {
+ CXString CS = clang_getTypeKindSpelling(CT.kind);
+ printf(" [canonical=%s]", clang_getCString(CS));
+ clang_disposeString(CS);
+ }
+ clang_disposeString(S);
+ printf("\n");
+ }
+ return CXChildVisit_Recurse;
+}
+
+
+/******************************************************************************/
/* Loading ASTs/source. */
/******************************************************************************/
@@ -1179,6 +1204,7 @@ static void print_usage(void) {
" c-index-test -test-inclusion-stack-source {<args>}*\n"
" c-index-test -test-inclusion-stack-tu <AST file>\n"
" c-index-test -test-print-linkage-source {<args>}*\n"
+ " c-index-test -test-print-typekind {<args>}*\n"
" c-index-test -print-usr [<CursorKind> {<args>}]*\n"
" c-index-test -print-usr-file <file>\n\n"
" <symbol filter> values:\n%s",
@@ -1223,6 +1249,9 @@ int main(int argc, const char **argv) {
else if (argc > 2 && strcmp(argv[1], "-test-print-linkage-source") == 0)
return perform_test_load_source(argc - 2, argv + 2, "all", PrintLinkage,
NULL);
+ else if (argc > 2 && strcmp(argv[1], "-test-print-typekind") == 0)
+ return perform_test_load_source(argc - 2, argv + 2, "all",
+ PrintTypeKind, 0);
else if (argc > 1 && strcmp(argv[1], "-print-usr") == 0) {
if (argc > 2)
return print_usrs(argv + 2, argv + argc);
diff --git a/tools/libclang/CMakeLists.txt b/tools/libclang/CMakeLists.txt
index d3de94a7a5..62c973852d 100644
--- a/tools/libclang/CMakeLists.txt
+++ b/tools/libclang/CMakeLists.txt
@@ -26,6 +26,7 @@ add_clang_library(libclang
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 0000000000..28dc12a344
--- /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 b361168053..2ea3677add 100644
--- a/tools/libclang/libclang.darwin.exports
+++ b/tools/libclang/libclang.darwin.exports
@@ -21,7 +21,9 @@ _clang_disposeTranslationUnit
_clang_enableStackTraces
_clang_equalCursors
_clang_equalLocations
+_clang_equalTypes
_clang_formatDiagnostic
+_clang_getCanonicalType
_clang_getCString
_clang_getClangVersion
_clang_getCompletionChunkCompletionString
@@ -37,6 +39,7 @@ _clang_getCursorLinkage
_clang_getCursorLocation
_clang_getCursorReferenced
_clang_getCursorSpelling
+_clang_getCursorType
_clang_getCursorUSR
_clang_getDefinitionSpellingAndExtent
_clang_getDiagnostic
@@ -58,6 +61,7 @@ _clang_getNullLocation
_clang_getNullRange
_clang_getNumCompletionChunks
_clang_getNumDiagnostics
+_clang_getPointeeType
_clang_getRange
_clang_getRangeEnd
_clang_getRangeStart
@@ -67,6 +71,8 @@ _clang_getTokenLocation
_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 991bb067f7..321a4ccab4 100644
--- a/tools/libclang/libclang.exports
+++ b/tools/libclang/libclang.exports
@@ -21,7 +21,9 @@ clang_disposeTranslationUnit
clang_enableStackTraces
clang_equalCursors
clang_equalLocations
+clang_equalTypes
clang_formatDiagnostic
+clang_getCanonicalType
clang_getCString
clang_getClangVersion
clang_getCompletionChunkCompletionString
@@ -37,6 +39,7 @@ clang_getCursorLinkage
clang_getCursorLocation
clang_getCursorReferenced
clang_getCursorSpelling
+clang_getCursorType
clang_getCursorUSR
clang_getDefinitionSpellingAndExtent
clang_getDiagnostic
@@ -58,6 +61,7 @@ clang_getNullLocation
clang_getNullRange
clang_getNumCompletionChunks
clang_getNumDiagnostics
+clang_getPointeeType
clang_getRange
clang_getRangeEnd
clang_getRangeStart
@@ -67,6 +71,8 @@ clang_getTokenLocation
clang_getTokenSpelling
clang_getTranslationUnitCursor
clang_getTranslationUnitSpelling
+clang_getTypeDeclaration
+clang_getTypeKindSpelling
clang_isCursorDefinition
clang_isDeclaration
clang_isExpression