[cfe-commits] r103809 - in /cfe/trunk: include/clang-c/Index.h test/Index/print-typekind.c tools/c-index-test/c-index-test.c tools/libclang/CMakeLists.txt tools/libclang/CXTypes.cpp tools/libclang/libclang.darwin.exports tools/libclang/libclang.exports

Ted Kremenek kremenek at apple.com
Fri May 14 14:29:26 PDT 2010


Author: kremenek
Date: Fri May 14 16:29:26 2010
New Revision: 103809

URL: http://llvm.org/viewvc/llvm-project?rev=103809&view=rev
Log:
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.

Added:
    cfe/trunk/test/Index/print-typekind.c
    cfe/trunk/tools/libclang/CXTypes.cpp
Modified:
    cfe/trunk/include/clang-c/Index.h
    cfe/trunk/tools/c-index-test/c-index-test.c
    cfe/trunk/tools/libclang/CMakeLists.txt
    cfe/trunk/tools/libclang/libclang.darwin.exports
    cfe/trunk/tools/libclang/libclang.exports

Modified: cfe/trunk/include/clang-c/Index.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang-c/Index.h?rev=103809&r1=103808&r2=103809&view=diff
==============================================================================
--- cfe/trunk/include/clang-c/Index.h (original)
+++ cfe/trunk/include/clang-c/Index.h Fri May 14 16:29:26 2010
@@ -1024,6 +1024,124 @@
  */
 
 /**
+ * \defgroup CINDEX_TYPES Type information for CXCursors
+ *
+ * @{
+ */
+
+/**
+ * \brief Describes the kind of type
+ */
+enum CXTypeKind {
+  /**
+   * \brief Reprents an invalid type (e.g., where no type is available).
+   */
+  CXType_Invalid = 0,
+
+  /**
+   * \brief A type whose specific kind is not exposed via this
+   * interface.
+   */
+  CXType_Unexposed = 1,
+
+  /* Builtin types */
+  CXType_Void = 2,
+  CXType_Bool = 3,
+  CXType_Char_U = 4,
+  CXType_UChar = 5,
+  CXType_Char16 = 6,
+  CXType_Char32 = 7,
+  CXType_UShort = 8,
+  CXType_UInt = 9,
+  CXType_ULong = 10,
+  CXType_ULongLong = 11,
+  CXType_UInt128 = 12,
+  CXType_Char_S = 13,
+  CXType_SChar = 14,
+  CXType_WChar = 15,
+  CXType_Short = 16,
+  CXType_Int = 17,
+  CXType_Long = 18,
+  CXType_LongLong = 19,
+  CXType_Int128 = 20,
+  CXType_Float = 21,
+  CXType_Double = 22,
+  CXType_LongDouble = 23,
+  CXType_NullPtr = 24,
+  CXType_Overload = 25,
+  CXType_Dependent = 26,
+  CXType_ObjCId = 27,
+  CXType_ObjCClass = 28,
+  CXType_ObjCSel = 29,
+  CXType_FirstBuiltin = CXType_Void,
+  CXType_LastBuiltin  = CXType_ObjCSel,
+
+  CXType_Complex = 100,
+  CXType_Pointer = 101,
+  CXType_BlockPointer = 102,
+  CXType_LValueReference = 103,
+  CXType_RValueReference = 104,
+  CXType_Record = 105,
+  CXType_Enum = 106,
+  CXType_Typedef = 107,
+  CXType_ObjCInterface = 108,
+  CXType_ObjCObjectPointer = 109
+};
+
+/**
+ * \brief The type of an element in the abstract syntax tree.
+ *
+ */
+typedef struct {
+  enum CXTypeKind kind;
+  void *data[2];
+} CXType;
+
+/**
+ * \brief Retrieve the type of a CXCursor (if any).
+ */
+CINDEX_LINKAGE CXType clang_getCursorType(CXCursor C);
+
+/**
+ * \determine Determine whether two CXTypes represent the same type.
+ *
+ * \returns non-zero if the CXTypes represent the same type and 
+            zero otherwise.
+ */
+CINDEX_LINKAGE unsigned clang_equalTypes(CXType A, CXType B);
+
+/**
+ * \brief Return the canonical type for a CXType.
+ *
+ * Clang's type system explicitly models typedefs and all the ways
+ * a specific type can be represented.  The canonical type is the underlying
+ * type with all the "sugar" removed.  For example, if 'T' is a typedef
+ * for 'int', the canonical type for 'T' would be 'int'.
+ */
+CINDEX_LINKAGE CXType clang_getCanonicalType(CXType T);
+
+/**
+ * \brief For pointer types, returns the type of the pointee.
+ *
+ */
+CINDEX_LINKAGE CXType clang_getPointeeType(CXType T);
+
+/**
+ * \brief Return the cursor for the declaration of the given type.
+ */
+CINDEX_LINKAGE CXCursor clang_getTypeDeclaration(CXType T);
+
+
+/**
+ * \brief Retrieve the spelling of a given CXTypeKind.
+ */
+CINDEX_LINKAGE CXString clang_getTypeKindSpelling(enum CXTypeKind K);
+
+/**
+ * @}
+ */
+
+/**
  * \defgroup CINDEX_CURSOR_TRAVERSAL Traversing the AST with cursors
  *
  * These routines provide the ability to traverse the abstract syntax tree

Added: cfe/trunk/test/Index/print-typekind.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Index/print-typekind.c?rev=103809&view=auto
==============================================================================
--- cfe/trunk/test/Index/print-typekind.c (added)
+++ cfe/trunk/test/Index/print-typekind.c Fri May 14 16:29:26 2010
@@ -0,0 +1,20 @@
+typedef int FooType;
+int *p;
+int *f(int *p, char *x, FooType z) {
+  FooType w = z;
+  return p + z;
+}
+
+// RUN: c-index-test -test-print-typekind %s | FileCheck %s
+// CHECK: TypedefDecl=FooType:1:13 (Definition) typekind=Typedef [canonical=Int]
+// CHECK: VarDecl=p:2:6 typekind=Pointer
+// CHECK: FunctionDecl=f:3:6 (Definition) typekind=Unexposed [canonical=Unexposed]
+// CHECK: ParmDecl=p:3:13 (Definition) typekind=Pointer
+// CHECK: ParmDecl=x:3:22 (Definition) typekind=Pointer
+// CHECK: ParmDecl=z:3:33 (Definition) typekind=Typedef [canonical=Int]
+// CHECK: VarDecl=w:4:11 (Definition) typekind=Typedef [canonical=Int]
+// CHECK: DeclRefExpr=z:3:33 typekind=Typedef [canonical=Int]
+// CHECK: UnexposedExpr= typekind=Pointer
+// CHECK: DeclRefExpr=p:3:13 typekind=Pointer
+// CHECK: DeclRefExpr=z:3:33 typekind=Typedef [canonical=Int]
+

Modified: cfe/trunk/tools/c-index-test/c-index-test.c
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/c-index-test/c-index-test.c?rev=103809&r1=103808&r2=103809&view=diff
==============================================================================
--- cfe/trunk/tools/c-index-test/c-index-test.c (original)
+++ cfe/trunk/tools/c-index-test/c-index-test.c Fri May 14 16:29:26 2010
@@ -447,6 +447,31 @@
 }
 
 /******************************************************************************/
+/* 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 @@
     "       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 @@
   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);

Modified: cfe/trunk/tools/libclang/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CMakeLists.txt?rev=103809&r1=103808&r2=103809&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/CMakeLists.txt (original)
+++ cfe/trunk/tools/libclang/CMakeLists.txt Fri May 14 16:29:26 2010
@@ -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)

Added: cfe/trunk/tools/libclang/CXTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/CXTypes.cpp?rev=103809&view=auto
==============================================================================
--- cfe/trunk/tools/libclang/CXTypes.cpp (added)
+++ cfe/trunk/tools/libclang/CXTypes.cpp Fri May 14 16:29:26 2010
@@ -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"

Modified: cfe/trunk/tools/libclang/libclang.darwin.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.darwin.exports?rev=103809&r1=103808&r2=103809&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/libclang.darwin.exports (original)
+++ cfe/trunk/tools/libclang/libclang.darwin.exports Fri May 14 16:29:26 2010
@@ -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

Modified: cfe/trunk/tools/libclang/libclang.exports
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/tools/libclang/libclang.exports?rev=103809&r1=103808&r2=103809&view=diff
==============================================================================
--- cfe/trunk/tools/libclang/libclang.exports (original)
+++ cfe/trunk/tools/libclang/libclang.exports Fri May 14 16:29:26 2010
@@ -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





More information about the cfe-commits mailing list