]> granicus.if.org Git - clang/commitdiff
[libclang 1/8] Add support for ObjCObjectType
authorMichael Wu <mwu.code@gmail.com>
Fri, 3 Aug 2018 03:03:20 +0000 (03:03 +0000)
committerMichael Wu <mwu.code@gmail.com>
Fri, 3 Aug 2018 03:03:20 +0000 (03:03 +0000)
Summary: This patch adds support to the clang-c API for identifying ObjCObjects in CXTypes, enumerating type args and protocols on ObjCObjectTypes, and retrieving the base type of ObjCObjectTypes. Currently only ObjCInterfaceTypes are exposed, which do not have type args or protocols.

Reviewers: yvvan, jbcoe

Reviewed By: yvvan

Subscribers: cfe-commits

Differential Revision: https://reviews.llvm.org/D49063

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338804 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang-c/Index.h
test/Index/objc-typeargs-protocols.m [new file with mode: 0644]
test/Index/print-type.m
tools/c-index-test/c-index-test.c
tools/libclang/CXType.cpp
tools/libclang/libclang.exports

index 5178048bf727b87fa6cc1442379cdcaddcad4c5a..170c658f57e9f868c82894d810996af35ac2857c 100644 (file)
@@ -3265,7 +3265,9 @@ enum CXTypeKind {
   CXType_OCLSampler = 157,
   CXType_OCLEvent = 158,
   CXType_OCLQueue = 159,
-  CXType_OCLReserveID = 160
+  CXType_OCLReserveID = 160,
+
+  CXType_ObjCObject = 161
 };
 
 /**
@@ -3626,6 +3628,43 @@ CINDEX_LINKAGE int clang_getNumArgTypes(CXType T);
  */
 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.
  */
diff --git a/test/Index/objc-typeargs-protocols.m b/test/Index/objc-typeargs-protocols.m
new file mode 100644 (file)
index 0000000..780f7b2
--- /dev/null
@@ -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 392399a573f1caa6efcd855413ac726e83b4997a..64a161aa45121df73b812bb7b325ceb6c8d2e16a 100644 (file)
@@ -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 70ab11866edd544649b74ee01264fea954e6d4af..17be449d91267bd9ada2e6383759eaac81178d49 100644 (file)
@@ -1500,6 +1500,7 @@ static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p,
                                          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 @@ static enum CXChildVisitResult PrintType(CXCursor cursor, CXCursor p,
         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 7c0f307944a14835add4d319dddb26e5d3fe720a..81fd87ae3fa7d2fb2992ec2b99d11404c22056e0 100644 (file)
@@ -98,6 +98,7 @@ static CXTypeKind GetTypeKind(QualType T) {
     TKCASE(Enum);
     TKCASE(Typedef);
     TKCASE(ObjCInterface);
+    TKCASE(ObjCObject);
     TKCASE(ObjCObjectPointer);
     TKCASE(FunctionNoProto);
     TKCASE(FunctionProto);
@@ -575,6 +576,7 @@ CXString clang_getTypeKindSpelling(enum CXTypeKind K) {
     TKIND(Enum);
     TKIND(Typedef);
     TKIND(ObjCInterface);
+    TKIND(ObjCObject);
     TKIND(ObjCObjectPointer);
     TKIND(FunctionNoProto);
     TKIND(FunctionProto);
@@ -1098,6 +1100,74 @@ CXType clang_Type_getTemplateArgumentAsType(CXType CT, unsigned index) {
   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 95a42712c4afea6fe8d2f08d4fd398368f7aad56..08353d7524ac920fb935f49c6463ee4081954d38 100644 (file)
@@ -98,6 +98,11 @@ clang_Type_getCXXRefQualifier
 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