michaelwu updated this revision to Diff 156692.
michaelwu added a comment.

`clang_Type_getNumObjCTypeArgs` and `clang_Type_getNumObjCProtocolRefs` now 
return unsigned.

I've bumped `CINDEX_VERSION_MINOR` in https://reviews.llvm.org/D49635 , which 
is the last in this patch series.


https://reviews.llvm.org/D49063

Files:
  include/clang-c/Index.h
  test/Index/objc-typeargs-protocols.m
  test/Index/print-type.m
  tools/c-index-test/c-index-test.c
  tools/libclang/CXType.cpp
  tools/libclang/libclang.exports

Index: tools/libclang/libclang.exports
===================================================================
--- tools/libclang/libclang.exports
+++ tools/libclang/libclang.exports
@@ -98,6 +98,11 @@
 clang_Type_visitFields
 clang_Type_getNamedType
 clang_Type_isTransparentTagTypedef
+clang_Type_getObjCObjectBaseType
+clang_Type_getNumObjCProtocolRefs
+clang_Type_getObjCProtocolDecl
+clang_Type_getNumObjCTypeArgs
+clang_Type_getObjCTypeArg
 clang_VerbatimBlockLineComment_getText
 clang_VerbatimLineComment_getText
 clang_HTMLTagComment_getAsString
Index: tools/libclang/CXType.cpp
===================================================================
--- tools/libclang/CXType.cpp
+++ tools/libclang/CXType.cpp
@@ -98,6 +98,7 @@
     TKCASE(Enum);
     TKCASE(Typedef);
     TKCASE(ObjCInterface);
+    TKCASE(ObjCObject);
     TKCASE(ObjCObjectPointer);
     TKCASE(FunctionNoProto);
     TKCASE(FunctionProto);
@@ -575,6 +576,7 @@
     TKIND(Enum);
     TKIND(Typedef);
     TKIND(ObjCInterface);
+    TKIND(ObjCObject);
     TKIND(ObjCObjectPointer);
     TKIND(FunctionNoProto);
     TKIND(FunctionProto);
@@ -1098,6 +1100,74 @@
   return MakeCXType(QT.getValueOr(QualType()), GetTU(CT));
 }
 
+CXType clang_Type_getObjCObjectBaseType(CXType CT) {
+  QualType T = GetQualType(CT);
+  if (T.isNull())
+    return MakeCXType(QualType(), GetTU(CT));
+
+  const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(T);
+  if (!OT)
+    return MakeCXType(QualType(), GetTU(CT));
+
+  return MakeCXType(OT->getBaseType(), GetTU(CT));
+}
+
+unsigned clang_Type_getNumObjCProtocolRefs(CXType CT) {
+  QualType T = GetQualType(CT);
+  if (T.isNull())
+    return 0;
+
+  const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(T);
+  if (!OT)
+    return 0;
+
+  return OT->getNumProtocols();
+}
+
+CXCursor clang_Type_getObjCProtocolDecl(CXType CT, unsigned i) {
+  QualType T = GetQualType(CT);
+  if (T.isNull())
+    return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
+
+  const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(T);
+  if (!OT)
+    return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
+
+  const ObjCProtocolDecl *PD = OT->getProtocol(i);
+  if (!PD)
+    return cxcursor::MakeCXCursorInvalid(CXCursor_NoDeclFound);
+
+  return cxcursor::MakeCXCursor(PD, GetTU(CT));
+}
+
+unsigned clang_Type_getNumObjCTypeArgs(CXType CT) {
+  QualType T = GetQualType(CT);
+  if (T.isNull())
+    return 0;
+
+  const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(T);
+  if (!OT)
+    return 0;
+
+  return OT->getTypeArgs().size();
+}
+
+CXType clang_Type_getObjCTypeArg(CXType CT, unsigned i) {
+  QualType T = GetQualType(CT);
+  if (T.isNull())
+    return MakeCXType(QualType(), GetTU(CT));
+
+  const ObjCObjectType *OT = dyn_cast<ObjCObjectType>(T);
+  if (!OT)
+    return MakeCXType(QualType(), GetTU(CT));
+
+  const ArrayRef<QualType> TA = OT->getTypeArgs();
+  if ((size_t)i >= TA.size())
+    return MakeCXType(QualType(), GetTU(CT));
+
+  return MakeCXType(TA[i], GetTU(CT));
+}
+
 unsigned clang_Type_visitFields(CXType PT,
                                 CXFieldVisitor visitor,
                                 CXClientData client_data){
Index: tools/c-index-test/c-index-test.c
===================================================================
--- tools/c-index-test/c-index-test.c
+++ tools/c-index-test/c-index-test.c
@@ -1500,6 +1500,7 @@
                                          CXClientData d) {
   if (!clang_isInvalid(clang_getCursorKind(cursor))) {
     CXType T = clang_getCursorType(cursor);
+    CXType PT = clang_getPointeeType(T);
     enum CXRefQualifierKind RQ = clang_Type_getCXXRefQualifier(T);
     PrintCursor(cursor, NULL);
     PrintTypeAndTypeKind(T, " [type=%s] [typekind=%s]");
@@ -1545,11 +1546,45 @@
         printf("]");
       }
     }
+    /* Print ObjC base types, type arguments, and protocol list if available. */
+    {
+      CXType BT = clang_Type_getObjCObjectBaseType(PT);
+      if (BT.kind != CXType_Invalid) {
+        PrintTypeAndTypeKind(BT, " [basetype=%s] [basekind=%s]");
+      }
+    }
+    {
+      unsigned NumTypeArgs = clang_Type_getNumObjCTypeArgs(PT);
+      if (NumTypeArgs > 0) {
+        unsigned i;
+        printf(" [typeargs=");
+        for (i = 0; i < NumTypeArgs; ++i) {
+          CXType TA = clang_Type_getObjCTypeArg(PT, i);
+          if (TA.kind != CXType_Invalid) {
+            PrintTypeAndTypeKind(TA, " [%s] [%s]");
+          }
+        }
+        printf("]");
+      }
+    }
+    {
+      unsigned NumProtocols = clang_Type_getNumObjCProtocolRefs(PT);
+      if (NumProtocols > 0) {
+        unsigned i;
+        printf(" [protocols=");
+        for (i = 0; i < NumProtocols; ++i) {
+          CXCursor P = clang_Type_getObjCProtocolDecl(PT, i);
+          if (!clang_isInvalid(clang_getCursorKind(P))) {
+            PrintCursor(P, NULL);
+          }
+        }
+        printf("]");
+      }
+    }
     /* Print if this is a non-POD type. */
     printf(" [isPOD=%d]", clang_isPODType(T));
     /* Print the pointee type. */
     {
-      CXType PT = clang_getPointeeType(T);
       if (PT.kind != CXType_Invalid) {
         PrintTypeAndTypeKind(PT, " [pointeetype=%s] [pointeekind=%s]");
       }
Index: test/Index/print-type.m
===================================================================
--- test/Index/print-type.m
+++ test/Index/print-type.m
@@ -15,5 +15,5 @@
 // CHECK: ObjCInstanceMethodDecl=methodIn:andOut::5:10 (variadic) [Bycopy,] [type=] [typekind=Invalid] [resulttype=id] [resulttypekind=ObjCId] [args= [int] [Int] [short *] [Pointer]] [isPOD=0]
 // CHECK: ParmDecl=i:5:27 (Definition) [In,] [type=int] [typekind=Int] [isPOD=1]
 // CHECK: ParmDecl=j:5:49 (Definition) [Out,] [type=short *] [typekind=Pointer] [isPOD=1] [pointeetype=short] [pointeekind=Short]
-// CHECK: ParmDecl=p:6:36 (Definition) [type=__kindof Foo *] [typekind=ObjCObjectPointer] [canonicaltype=__kindof Foo *] [canonicaltypekind=ObjCObjectPointer] [isPOD=1] [pointeetype=Foo] [pointeekind=ObjCInterface]
+// CHECK: ParmDecl=p:6:36 (Definition) [type=__kindof Foo *] [typekind=ObjCObjectPointer] [canonicaltype=__kindof Foo *] [canonicaltypekind=ObjCObjectPointer] [basetype=Foo] [basekind=ObjCInterface] [isPOD=1] [pointeetype=Foo] [pointeekind=ObjCInterface]
 // CHECK: ObjCPropertyDecl=classProp:7:23 [class,] [type=int] [typekind=Int] [isPOD=1]
Index: test/Index/objc-typeargs-protocols.m
===================================================================
--- /dev/null
+++ test/Index/objc-typeargs-protocols.m
@@ -0,0 +1,28 @@
+
+@interface TestA
+@end
+
+@interface TestB
+@end
+
+@protocol Bar
+@end
+
+@interface Base
+@end
+
+@interface Foo<FirstType, SecondType> : Base
+@end
+
+Foo *a;
+Foo<TestA *, TestB *> *b;
+Foo<Bar> *c;
+Foo<TestA *, TestB *><Bar> *d;
+id<Bar> e;
+
+// RUN: c-index-test -test-print-type %s | FileCheck %s
+// CHECK: VarDecl=a:17:6 [type=Foo *] [typekind=ObjCObjectPointer] [basetype=Foo] [basekind=ObjCInterface] [isPOD=1] [pointeetype=Foo] [pointeekind=ObjCInterface]
+// CHECK: VarDecl=b:18:24 [type=Foo<TestA *,TestB *> *] [typekind=ObjCObjectPointer] [basetype=Foo] [basekind=ObjCInterface] [typeargs= [TestA *] [ObjCObjectPointer] [TestB *] [ObjCObjectPointer]] [isPOD=1] [pointeetype=Foo<TestA *,TestB *>] [pointeekind=ObjCObject]
+// CHECK: VarDecl=c:19:11 [type=Foo<Bar> *] [typekind=ObjCObjectPointer] [basetype=Foo] [basekind=ObjCInterface] [protocols=ObjCProtocolDecl=Bar:8:11 (Definition)] [isPOD=1] [pointeetype=Foo<Bar>] [pointeekind=ObjCObject]
+// CHECK: VarDecl=d:20:29 [type=Foo<TestA *,TestB *><Bar> *] [typekind=ObjCObjectPointer] [basetype=Foo] [basekind=ObjCInterface] [typeargs= [TestA *] [ObjCObjectPointer] [TestB *] [ObjCObjectPointer]] [protocols=ObjCProtocolDecl=Bar:8:11 (Definition)] [isPOD=1] [pointeetype=Foo<TestA *,TestB *><Bar>] [pointeekind=ObjCObject]
+// CHECK: VarDecl=e:21:9 [type=id<Bar>] [typekind=ObjCObjectPointer] [basetype=id] [basekind=ObjCId] [protocols=ObjCProtocolDecl=Bar:8:11 (Definition)] [isPOD=1] [pointeetype=id<Bar>] [pointeekind=ObjCObject]
Index: include/clang-c/Index.h
===================================================================
--- include/clang-c/Index.h
+++ include/clang-c/Index.h
@@ -3266,7 +3266,9 @@
   CXType_OCLSampler = 157,
   CXType_OCLEvent = 158,
   CXType_OCLQueue = 159,
-  CXType_OCLReserveID = 160
+  CXType_OCLReserveID = 160,
+
+  CXType_ObjCObject = 161
 };
 
 /**
@@ -3627,6 +3629,43 @@
  */
 CINDEX_LINKAGE CXType clang_getArgType(CXType T, unsigned i);
 
+/**
+ * Retrieves the base type of the ObjCObjectType.
+ *
+ * If the type is not an ObjC object, an invalid type is returned.
+ */
+CINDEX_LINKAGE CXType clang_Type_getObjCObjectBaseType(CXType T);
+
+/**
+ * Retrieve the number of protocol references associated with an ObjC object/id.
+ *
+ * If the type is not an ObjC object, 0 is returned.
+ */
+CINDEX_LINKAGE unsigned clang_Type_getNumObjCProtocolRefs(CXType T);
+
+/**
+ * Retrieve the decl for a protocol reference for an ObjC object/id.
+ *
+ * If the type is not an ObjC object or there are not enough protocol
+ * references, an invalid cursor is returned.
+ */
+CINDEX_LINKAGE CXCursor clang_Type_getObjCProtocolDecl(CXType T, unsigned i);
+
+/**
+ * Retreive the number of type arguments associated with an ObjC object.
+ *
+ * If the type is not an ObjC object, 0 is returned.
+ */
+CINDEX_LINKAGE unsigned clang_Type_getNumObjCTypeArgs(CXType T);
+
+/**
+ * Retrieve a type argument associated with an ObjC object.
+ *
+ * If the type is not an ObjC or the index is not valid,
+ * an invalid type is returned.
+ */
+CINDEX_LINKAGE CXType clang_Type_getObjCTypeArg(CXType T, unsigned i);
+
 /**
  * Return 1 if the CXType is a variadic function type, and 0 otherwise.
  */
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to