[clang] 236b6a0 - [clang][extract-api] Emit "functionSignature" in SGF for ObjC methods.

Daniel Grumberg via cfe-commits cfe-commits at lists.llvm.org
Mon Apr 11 11:07:44 PDT 2022


Author: Daniel Grumberg
Date: 2022-04-11T19:05:24+01:00
New Revision: 236b6a0eb41a163510e65664e2160f599287326b

URL: https://github.com/llvm/llvm-project/commit/236b6a0eb41a163510e65664e2160f599287326b
DIFF: https://github.com/llvm/llvm-project/commit/236b6a0eb41a163510e65664e2160f599287326b.diff

LOG: [clang][extract-api] Emit "functionSignature" in SGF for ObjC methods.

- Split GlobalRecord into two distinct types to be able to introduce
has_function_signature type trait.
- Add has_function_signature type trait.
- Serialize function signatures as part of serializeAPIRecord for
records that are known to have a function signature.

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

Added: 
    

Modified: 
    clang/include/clang/ExtractAPI/API.h
    clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
    clang/lib/ExtractAPI/API.cpp
    clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
    clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
    clang/test/ExtractAPI/objc_category.m
    clang/test/ExtractAPI/objc_interface.m

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/ExtractAPI/API.h b/clang/include/clang/ExtractAPI/API.h
index 57b6a2ee5a43c..6a9429704d45e 100644
--- a/clang/include/clang/ExtractAPI/API.h
+++ b/clang/include/clang/ExtractAPI/API.h
@@ -77,7 +77,8 @@ struct APIRecord {
 
   /// Discriminator for LLVM-style RTTI (dyn_cast<> et al.)
   enum RecordKind {
-    RK_Global,
+    RK_GlobalFunction,
+    RK_GlobalVariable,
     RK_EnumConstant,
     RK_Enum,
     RK_StructField,
@@ -112,31 +113,40 @@ struct APIRecord {
   virtual ~APIRecord() = 0;
 };
 
-/// The kind of a global record.
-enum class GVKind : uint8_t {
-  Unknown = 0,
-  Variable = 1,
-  Function = 2,
-};
+/// This holds information associated with global functions.
+struct GlobalFunctionRecord : APIRecord {
+  FunctionSignature Signature;
 
-/// This holds information associated with global variables or functions.
-struct GlobalRecord : APIRecord {
-  GVKind GlobalKind;
+  GlobalFunctionRecord(StringRef Name, StringRef USR, PresumedLoc Loc,
+                       const AvailabilityInfo &Availability,
+                       LinkageInfo Linkage, const DocComment &Comment,
+                       DeclarationFragments Declaration,
+                       DeclarationFragments SubHeading,
+                       FunctionSignature Signature)
+      : APIRecord(RK_GlobalFunction, Name, USR, Loc, Availability, Linkage,
+                  Comment, Declaration, SubHeading),
+        Signature(Signature) {}
 
-  /// The function signature of the record if it is a function.
-  FunctionSignature Signature;
+  static bool classof(const APIRecord *Record) {
+    return Record->getKind() == RK_GlobalFunction;
+  }
 
-  GlobalRecord(StringRef Name, StringRef USR, PresumedLoc Loc,
-               const AvailabilityInfo &Availability, LinkageInfo Linkage,
-               const DocComment &Comment, DeclarationFragments Declaration,
-               DeclarationFragments SubHeading, GVKind Kind,
-               FunctionSignature Signature)
-      : APIRecord(RK_Global, Name, USR, Loc, Availability, Linkage, Comment,
-                  Declaration, SubHeading),
-        GlobalKind(Kind), Signature(Signature) {}
+private:
+  virtual void anchor();
+};
+
+/// This holds information associated with global functions.
+struct GlobalVariableRecord : APIRecord {
+  GlobalVariableRecord(StringRef Name, StringRef USR, PresumedLoc Loc,
+                       const AvailabilityInfo &Availability,
+                       LinkageInfo Linkage, const DocComment &Comment,
+                       DeclarationFragments Declaration,
+                       DeclarationFragments SubHeading)
+      : APIRecord(RK_GlobalVariable, Name, USR, Loc, Availability, Linkage,
+                  Comment, Declaration, SubHeading) {}
 
   static bool classof(const APIRecord *Record) {
-    return Record->getKind() == RK_Global;
+    return Record->getKind() == RK_GlobalVariable;
   }
 
 private:
@@ -446,33 +456,31 @@ struct TypedefRecord : APIRecord {
   virtual void anchor();
 };
 
+/// Check if a record type has a function signature mixin.
+///
+/// This is denoted by the record type having a ``Signature`` field of type
+/// FunctionSignature.
+template <typename RecordTy>
+struct has_function_signature : public std::false_type {};
+template <>
+struct has_function_signature<GlobalFunctionRecord> : public std::true_type {};
+template <>
+struct has_function_signature<ObjCMethodRecord> : public std::true_type {};
+
 /// APISet holds the set of API records collected from given inputs.
 class APISet {
 public:
-  /// Create and add a GlobalRecord of kind \p Kind into the API set.
-  ///
-  /// Note: the caller is responsible for keeping the StringRef \p Name and
-  /// \p USR alive. APISet::copyString provides a way to copy strings into
-  /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
-  /// to generate the USR for \c D and keep it alive in APISet.
-  GlobalRecord *addGlobal(GVKind Kind, StringRef Name, StringRef USR,
-                          PresumedLoc Loc, const AvailabilityInfo &Availability,
-                          LinkageInfo Linkage, const DocComment &Comment,
-                          DeclarationFragments Declaration,
-                          DeclarationFragments SubHeading,
-                          FunctionSignature Signature);
-
   /// Create and add a global variable record into the API set.
   ///
   /// Note: the caller is responsible for keeping the StringRef \p Name and
   /// \p USR alive. APISet::copyString provides a way to copy strings into
   /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
   /// to generate the USR for \c D and keep it alive in APISet.
-  GlobalRecord *addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc,
-                             const AvailabilityInfo &Availability,
-                             LinkageInfo Linkage, const DocComment &Comment,
-                             DeclarationFragments Declaration,
-                             DeclarationFragments SubHeading);
+  GlobalVariableRecord *
+  addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc,
+               const AvailabilityInfo &Availability, LinkageInfo Linkage,
+               const DocComment &Comment, DeclarationFragments Declaration,
+               DeclarationFragments SubHeading);
 
   /// Create and add a function record into the API set.
   ///
@@ -480,12 +488,12 @@ class APISet {
   /// \p USR alive. APISet::copyString provides a way to copy strings into
   /// APISet itself, and APISet::recordUSR(const Decl *D) is a helper method
   /// to generate the USR for \c D and keep it alive in APISet.
-  GlobalRecord *addFunction(StringRef Name, StringRef USR, PresumedLoc Loc,
-                            const AvailabilityInfo &Availability,
-                            LinkageInfo Linkage, const DocComment &Comment,
-                            DeclarationFragments Declaration,
-                            DeclarationFragments SubHeading,
-                            FunctionSignature Signature);
+  GlobalFunctionRecord *
+  addGlobalFunction(StringRef Name, StringRef USR, PresumedLoc Loc,
+                    const AvailabilityInfo &Availability, LinkageInfo Linkage,
+                    const DocComment &Comment, DeclarationFragments Declaration,
+                    DeclarationFragments SubHeading,
+                    FunctionSignature Signature);
 
   /// Create and add an enum constant record into the API set.
   ///
@@ -652,7 +660,12 @@ class APISet {
   /// Get the language used by the APIs.
   Language getLanguage() const { return Lang; }
 
-  const RecordMap<GlobalRecord> &getGlobals() const { return Globals; }
+  const RecordMap<GlobalFunctionRecord> &getGlobalFunctions() const {
+    return GlobalFunctions;
+  }
+  const RecordMap<GlobalVariableRecord> &getGlobalVariables() const {
+    return GlobalVariables;
+  }
   const RecordMap<EnumRecord> &getEnums() const { return Enums; }
   const RecordMap<StructRecord> &getStructs() const { return Structs; }
   const RecordMap<ObjCCategoryRecord> &getObjCCategories() const {
@@ -699,7 +712,8 @@ class APISet {
   const llvm::Triple Target;
   const Language Lang;
 
-  RecordMap<GlobalRecord> Globals;
+  RecordMap<GlobalFunctionRecord> GlobalFunctions;
+  RecordMap<GlobalVariableRecord> GlobalVariables;
   RecordMap<EnumRecord> Enums;
   RecordMap<StructRecord> Structs;
   RecordMap<ObjCCategoryRecord> ObjCCategories;

diff  --git a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
index 93942ff05a0ae..438a9dc327058 100644
--- a/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
+++ b/clang/include/clang/ExtractAPI/Serialization/SymbolGraphSerializer.h
@@ -122,7 +122,8 @@ class SymbolGraphSerializer : public APISerializer {
   ///
   /// \returns \c None if this \p Record should be skipped, or a JSON object
   /// containing common symbol information of \p Record.
-  Optional<Object> serializeAPIRecord(const APIRecord &Record) const;
+  template <typename RecordTy>
+  Optional<Object> serializeAPIRecord(const RecordTy &Record) const;
 
   /// Helper method to serialize second-level member records of \p Record and
   /// the member-of relationships.
@@ -137,8 +138,11 @@ class SymbolGraphSerializer : public APISerializer {
   void serializeRelationship(RelationshipKind Kind, SymbolReference Source,
                              SymbolReference Target);
 
-  /// Serialize a global record.
-  void serializeGlobalRecord(const GlobalRecord &Record);
+  /// Serialize a global function record.
+  void serializeGlobalFunctionRecord(const GlobalFunctionRecord &Record);
+
+  /// Serialize a global variable record.
+  void serializeGlobalVariableRecord(const GlobalVariableRecord &Record);
 
   /// Serialize an enum record.
   void serializeEnumRecord(const EnumRecord &Record);

diff  --git a/clang/lib/ExtractAPI/API.cpp b/clang/lib/ExtractAPI/API.cpp
index 1c33bbf4328cf..10d723d452cac 100644
--- a/clang/lib/ExtractAPI/API.cpp
+++ b/clang/lib/ExtractAPI/API.cpp
@@ -41,34 +41,22 @@ RecordTy *addTopLevelRecord(APISet::RecordMap<RecordTy> &RecordMap,
 
 } // namespace
 
-GlobalRecord *APISet::addGlobal(GVKind Kind, StringRef Name, StringRef USR,
-                                PresumedLoc Loc,
-                                const AvailabilityInfo &Availability,
-                                LinkageInfo Linkage, const DocComment &Comment,
-                                DeclarationFragments Fragments,
-                                DeclarationFragments SubHeading,
-                                FunctionSignature Signature) {
-  return addTopLevelRecord(Globals, Name, USR, Loc, Availability, Linkage,
-                           Comment, Fragments, SubHeading, Kind, Signature);
-}
-
-GlobalRecord *
+GlobalVariableRecord *
 APISet::addGlobalVar(StringRef Name, StringRef USR, PresumedLoc Loc,
                      const AvailabilityInfo &Availability, LinkageInfo Linkage,
                      const DocComment &Comment, DeclarationFragments Fragments,
                      DeclarationFragments SubHeading) {
-  return addGlobal(GVKind::Variable, Name, USR, Loc, Availability, Linkage,
-                   Comment, Fragments, SubHeading, {});
+  return addTopLevelRecord(GlobalVariables, Name, USR, Loc, Availability,
+                           Linkage, Comment, Fragments, SubHeading);
 }
 
-GlobalRecord *
-APISet::addFunction(StringRef Name, StringRef USR, PresumedLoc Loc,
-                    const AvailabilityInfo &Availability, LinkageInfo Linkage,
-                    const DocComment &Comment, DeclarationFragments Fragments,
-                    DeclarationFragments SubHeading,
-                    FunctionSignature Signature) {
-  return addGlobal(GVKind::Function, Name, USR, Loc, Availability, Linkage,
-                   Comment, Fragments, SubHeading, Signature);
+GlobalFunctionRecord *APISet::addGlobalFunction(
+    StringRef Name, StringRef USR, PresumedLoc Loc,
+    const AvailabilityInfo &Availability, LinkageInfo Linkage,
+    const DocComment &Comment, DeclarationFragments Fragments,
+    DeclarationFragments SubHeading, FunctionSignature Signature) {
+  return addTopLevelRecord(GlobalFunctions, Name, USR, Loc, Availability,
+                           Linkage, Comment, Fragments, SubHeading, Signature);
 }
 
 EnumConstantRecord *APISet::addEnumConstant(
@@ -229,7 +217,8 @@ APIRecord::~APIRecord() {}
 
 ObjCContainerRecord::~ObjCContainerRecord() {}
 
-void GlobalRecord::anchor() {}
+void GlobalFunctionRecord::anchor() {}
+void GlobalVariableRecord::anchor() {}
 void EnumConstantRecord::anchor() {}
 void EnumRecord::anchor() {}
 void StructFieldRecord::anchor() {}

diff  --git a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
index 0757881862984..e3700a0d390a2 100644
--- a/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
+++ b/clang/lib/ExtractAPI/ExtractAPIConsumer.cpp
@@ -198,8 +198,8 @@ class ExtractAPIVisitor : public RecursiveASTVisitor<ExtractAPIVisitor> {
         DeclarationFragmentsBuilder::getFunctionSignature(Decl);
 
     // Add the function record to the API set.
-    API.addFunction(Name, USR, Loc, Availability, Linkage, Comment, Declaration,
-                    SubHeading, Signature);
+    API.addGlobalFunction(Name, USR, Loc, Availability, Linkage, Comment,
+                          Declaration, SubHeading, Signature);
     return true;
   }
 

diff  --git a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
index 2a3818e0da520..045d5d68e733b 100644
--- a/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
+++ b/clang/lib/ExtractAPI/Serialization/SymbolGraphSerializer.cpp
@@ -18,6 +18,7 @@
 #include "llvm/Support/JSON.h"
 #include "llvm/Support/Path.h"
 #include "llvm/Support/VersionTuple.h"
+#include <type_traits>
 
 using namespace clang;
 using namespace clang::extractapi;
@@ -285,39 +286,6 @@ Optional<Array> serializeDeclarationFragments(const DeclarationFragments &DF) {
   return Fragments;
 }
 
-/// Serialize the function signature field of a function, as specified by the
-/// Symbol Graph format.
-///
-/// The Symbol Graph function signature property contains two arrays.
-///   - The \c returns array is the declaration fragments of the return type;
-///   - The \c parameters array contains names and declaration fragments of the
-///     parameters.
-///
-/// \returns \c None if \p FS is empty, or an \c Object containing the
-/// formatted function signature.
-Optional<Object> serializeFunctionSignature(const FunctionSignature &FS) {
-  if (FS.empty())
-    return None;
-
-  Object Signature;
-  serializeArray(Signature, "returns",
-                 serializeDeclarationFragments(FS.getReturnType()));
-
-  Array Parameters;
-  for (const auto &P : FS.getParameters()) {
-    Object Parameter;
-    Parameter["name"] = P.Name;
-    serializeArray(Parameter, "declarationFragments",
-                   serializeDeclarationFragments(P.Fragments));
-    Parameters.emplace_back(std::move(Parameter));
-  }
-
-  if (!Parameters.empty())
-    Signature["parameters"] = std::move(Parameters);
-
-  return Signature;
-}
-
 /// Serialize the \c names field of a symbol as specified by the Symbol Graph
 /// format.
 ///
@@ -354,23 +322,14 @@ Object serializeSymbolKind(const APIRecord &Record, Language Lang) {
 
   Object Kind;
   switch (Record.getKind()) {
-  case APIRecord::RK_Global: {
-    auto *GR = dyn_cast<GlobalRecord>(&Record);
-    switch (GR->GlobalKind) {
-    case GVKind::Function:
-      Kind["identifier"] = AddLangPrefix("func");
-      Kind["displayName"] = "Function";
-      break;
-    case GVKind::Variable:
-      Kind["identifier"] = AddLangPrefix("var");
-      Kind["displayName"] = "Global Variable";
-      break;
-    case GVKind::Unknown:
-      // Unknown global kind
-      break;
-    }
+  case APIRecord::RK_GlobalFunction:
+    Kind["identifier"] = AddLangPrefix("func");
+    Kind["displayName"] = "Function";
+    break;
+  case APIRecord::RK_GlobalVariable:
+    Kind["identifier"] = AddLangPrefix("var");
+    Kind["displayName"] = "Global Variable";
     break;
-  }
   case APIRecord::RK_EnumConstant:
     Kind["identifier"] = AddLangPrefix("enum.case");
     Kind["displayName"] = "Enumeration Case";
@@ -430,6 +389,55 @@ Object serializeSymbolKind(const APIRecord &Record, Language Lang) {
   return Kind;
 }
 
+template <typename RecordTy>
+Optional<Object> serializeFunctionSignatureMixinImpl(const RecordTy &Record,
+                                                     std::true_type) {
+  const auto &FS = Record.Signature;
+  if (FS.empty())
+    return None;
+
+  Object Signature;
+  serializeArray(Signature, "returns",
+                 serializeDeclarationFragments(FS.getReturnType()));
+
+  Array Parameters;
+  for (const auto &P : FS.getParameters()) {
+    Object Parameter;
+    Parameter["name"] = P.Name;
+    serializeArray(Parameter, "declarationFragments",
+                   serializeDeclarationFragments(P.Fragments));
+    Parameters.emplace_back(std::move(Parameter));
+  }
+
+  if (!Parameters.empty())
+    Signature["parameters"] = std::move(Parameters);
+
+  return Signature;
+}
+
+template <typename RecordTy>
+Optional<Object> serializeFunctionSignatureMixinImpl(const RecordTy &Record,
+                                                     std::false_type) {
+  return None;
+}
+
+/// Serialize the function signature field, as specified by the
+/// Symbol Graph format.
+///
+/// The Symbol Graph function signature property contains two arrays.
+///   - The \c returns array is the declaration fragments of the return type;
+///   - The \c parameters array contains names and declaration fragments of the
+///     parameters.
+///
+/// \returns \c None if \p FS is empty, or an \c Object containing the
+/// formatted function signature.
+template <typename RecordTy>
+void serializeFunctionSignatureMixin(Object &Paren, const RecordTy &Record) {
+  serializeObject(Paren, "functionSignature",
+                  serializeFunctionSignatureMixinImpl(
+                      Record, has_function_signature<RecordTy>()));
+}
+
 } // namespace
 
 void SymbolGraphSerializer::anchor() {}
@@ -462,8 +470,9 @@ bool SymbolGraphSerializer::shouldSkip(const APIRecord &Record) const {
   return false;
 }
 
+template <typename RecordTy>
 Optional<Object>
-SymbolGraphSerializer::serializeAPIRecord(const APIRecord &Record) const {
+SymbolGraphSerializer::serializeAPIRecord(const RecordTy &Record) const {
   if (shouldSkip(Record))
     return None;
 
@@ -485,6 +494,8 @@ SymbolGraphSerializer::serializeAPIRecord(const APIRecord &Record) const {
   Obj["accessLevel"] = "public";
   serializeArray(Obj, "pathComponents", Array(PathComponents));
 
+  serializeFunctionSignatureMixin(Obj, Record);
+
   return Obj;
 }
 
@@ -526,16 +537,24 @@ void SymbolGraphSerializer::serializeRelationship(RelationshipKind Kind,
   Relationships.emplace_back(std::move(Relationship));
 }
 
-void SymbolGraphSerializer::serializeGlobalRecord(const GlobalRecord &Record) {
+void SymbolGraphSerializer::serializeGlobalFunctionRecord(
+    const GlobalFunctionRecord &Record) {
   auto GlobalPathComponentGuard = makePathComponentGuard(Record.Name);
 
   auto Obj = serializeAPIRecord(Record);
   if (!Obj)
     return;
 
-  if (Record.GlobalKind == GVKind::Function)
-    serializeObject(*Obj, "functionSignature",
-                    serializeFunctionSignature(Record.Signature));
+  Symbols.emplace_back(std::move(*Obj));
+}
+
+void SymbolGraphSerializer::serializeGlobalVariableRecord(
+    const GlobalVariableRecord &Record) {
+  auto GlobalPathComponentGuard = makePathComponentGuard(Record.Name);
+
+  auto Obj = serializeAPIRecord(Record);
+  if (!Obj)
+    return;
 
   Symbols.emplace_back(std::move(*Obj));
 }
@@ -640,9 +659,12 @@ Object SymbolGraphSerializer::serialize() {
   serializeObject(Root, "metadata", serializeMetadata());
   serializeObject(Root, "module", serializeModule());
 
-  // Serialize global records in the API set.
-  for (const auto &Global : API.getGlobals())
-    serializeGlobalRecord(*Global.second);
+  // Serialize global variables in the API set.
+  for (const auto &GlobalVar : API.getGlobalVariables())
+    serializeGlobalVariableRecord(*GlobalVar.second);
+
+  for (const auto &GlobalFunction : API.getGlobalFunctions())
+    serializeGlobalFunctionRecord(*GlobalFunction.second);
 
   // Serialize enum records in the API set.
   for (const auto &Enum : API.getEnums())

diff  --git a/clang/test/ExtractAPI/objc_category.m b/clang/test/ExtractAPI/objc_category.m
index af5a44ff5b424..2a69740203c3a 100644
--- a/clang/test/ExtractAPI/objc_category.m
+++ b/clang/test/ExtractAPI/objc_category.m
@@ -148,6 +148,15 @@ + (void)ClassMethod;
           "spelling": ";"
         }
       ],
+      "functionSignature": {
+        "returns": [
+          {
+            "kind": "typeIdentifier",
+            "preciseIdentifier": "c:v",
+            "spelling": "void"
+          }
+        ]
+      },
       "identifier": {
         "interfaceLanguage": "objective-c",
         "precise": "c:objc(cs)Interface(im)InstanceMethod"
@@ -212,6 +221,15 @@ + (void)ClassMethod;
           "spelling": ";"
         }
       ],
+      "functionSignature": {
+        "returns": [
+          {
+            "kind": "typeIdentifier",
+            "preciseIdentifier": "c:v",
+            "spelling": "void"
+          }
+        ]
+      },
       "identifier": {
         "interfaceLanguage": "objective-c",
         "precise": "c:objc(cs)Interface(cm)ClassMethod"

diff  --git a/clang/test/ExtractAPI/objc_interface.m b/clang/test/ExtractAPI/objc_interface.m
index fc42cfc7c6728..1ac2f81a80603 100644
--- a/clang/test/ExtractAPI/objc_interface.m
+++ b/clang/test/ExtractAPI/objc_interface.m
@@ -182,6 +182,38 @@ - (char)getIvar;
           "spelling": ";"
         }
       ],
+      "functionSignature": {
+        "parameters": [
+          {
+            "declarationFragments": [
+              {
+                "kind": "text",
+                "spelling": "("
+              },
+              {
+                "kind": "typeIdentifier",
+                "preciseIdentifier": "c:i",
+                "spelling": "unsigned int"
+              },
+              {
+                "kind": "text",
+                "spelling": ") "
+              },
+              {
+                "kind": "internalParam",
+                "spelling": "Property"
+              }
+            ],
+            "name": "Property"
+          }
+        ],
+        "returns": [
+          {
+            "kind": "keyword",
+            "spelling": "id"
+          }
+        ]
+      },
       "identifier": {
         "interfaceLanguage": "objective-c",
         "precise": "c:objc(cs)Super(cm)getWithProperty:"
@@ -288,6 +320,61 @@ - (char)getIvar;
           "spelling": ";"
         }
       ],
+      "functionSignature": {
+        "parameters": [
+          {
+            "declarationFragments": [
+              {
+                "kind": "text",
+                "spelling": "("
+              },
+              {
+                "kind": "typeIdentifier",
+                "preciseIdentifier": "c:i",
+                "spelling": "unsigned int"
+              },
+              {
+                "kind": "text",
+                "spelling": ") "
+              },
+              {
+                "kind": "internalParam",
+                "spelling": "Property"
+              }
+            ],
+            "name": "Property"
+          },
+          {
+            "declarationFragments": [
+              {
+                "kind": "text",
+                "spelling": "("
+              },
+              {
+                "kind": "typeIdentifier",
+                "preciseIdentifier": "c:i",
+                "spelling": "unsigned int"
+              },
+              {
+                "kind": "text",
+                "spelling": ") "
+              },
+              {
+                "kind": "internalParam",
+                "spelling": "Thing"
+              }
+            ],
+            "name": "Thing"
+          }
+        ],
+        "returns": [
+          {
+            "kind": "typeIdentifier",
+            "preciseIdentifier": "c:v",
+            "spelling": "void"
+          }
+        ]
+      },
       "identifier": {
         "interfaceLanguage": "objective-c",
         "precise": "c:objc(cs)Super(im)setProperty:andOtherThing:"
@@ -551,6 +638,15 @@ - (char)getIvar;
           "spelling": ";"
         }
       ],
+      "functionSignature": {
+        "returns": [
+          {
+            "kind": "typeIdentifier",
+            "preciseIdentifier": "c:C",
+            "spelling": "char"
+          }
+        ]
+      },
       "identifier": {
         "interfaceLanguage": "objective-c",
         "precise": "c:objc(cs)Derived(im)getIvar"


        


More information about the cfe-commits mailing list