Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[clang][ExtractAPI] Add support for blocks in declaration fragments #73369

Merged

Conversation

daniel-grumberg
Copy link
Contributor

Ensure that block types get represented correctly in declaration fragments, as block parameter names are important for documentation clients we need a separate system from getFragmentsForType in order to have access to full ParmVarDecls for the parameters.

rdar://118257401

Ensure that block types get represented correctly in declaration
fragments, as block parameter names are important for documentation
clients we need a separate system from getFragmentsForType in order to
have access to full ParmVarDecls for the parameters.

rdar://118257401
@llvmbot llvmbot added the clang Clang issues not falling into any other category label Nov 24, 2023
@llvmbot
Copy link
Collaborator

llvmbot commented Nov 24, 2023

@llvm/pr-subscribers-clang

Author: Daniel Grumberg (daniel-grumberg)

Changes

Ensure that block types get represented correctly in declaration fragments, as block parameter names are important for documentation clients we need a separate system from getFragmentsForType in order to have access to full ParmVarDecls for the parameters.

rdar://118257401


Patch is 36.77 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/73369.diff

7 Files Affected:

  • (modified) clang/include/clang/ExtractAPI/DeclarationFragments.h (+6)
  • (modified) clang/lib/ExtractAPI/DeclarationFragments.cpp (+148-28)
  • (added) clang/test/ExtractAPI/objc_block.m (+965)
  • (modified) clang/test/ExtractAPI/objc_category.m (+4)
  • (modified) clang/test/ExtractAPI/objc_id_protocol.m (+8)
  • (modified) clang/test/ExtractAPI/objc_interface.m (+4)
  • (modified) clang/test/ExtractAPI/objc_property.m (+24)
diff --git a/clang/include/clang/ExtractAPI/DeclarationFragments.h b/clang/include/clang/ExtractAPI/DeclarationFragments.h
index 316d83df13e9359..d719196b9a43ecb 100644
--- a/clang/include/clang/ExtractAPI/DeclarationFragments.h
+++ b/clang/include/clang/ExtractAPI/DeclarationFragments.h
@@ -24,6 +24,7 @@
 #include "clang/AST/DeclObjC.h"
 #include "clang/AST/DeclTemplate.h"
 #include "clang/AST/ExprCXX.h"
+#include "clang/AST/TypeLoc.h"
 #include "clang/Basic/Specifiers.h"
 #include "clang/Lex/MacroInfo.h"
 #include "llvm/ADT/SmallVector.h"
@@ -410,6 +411,11 @@ class DeclarationFragmentsBuilder {
   /// Build DeclarationFragments for a parameter variable declaration
   /// ParmVarDecl.
   static DeclarationFragments getFragmentsForParam(const ParmVarDecl *);
+
+  static DeclarationFragments
+  getFragmentsForBlock(const NamedDecl *BlockDecl, FunctionTypeLoc &Block,
+                       FunctionProtoTypeLoc &BlockProto,
+                       DeclarationFragments &After);
 };
 
 template <typename FunctionT>
diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp
index 02fa6cd6119ecac..eb6eea0aaf54655 100644
--- a/clang/lib/ExtractAPI/DeclarationFragments.cpp
+++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp
@@ -15,6 +15,8 @@
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
 #include "clang/AST/QualTypeNames.h"
+#include "clang/AST/Type.h"
+#include "clang/AST/TypeLoc.h"
 #include "clang/Basic/OperatorKinds.h"
 #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
 #include "clang/Index/USRGeneration.h"
@@ -24,6 +26,40 @@
 using namespace clang::extractapi;
 using namespace llvm;
 
+namespace {
+
+void findTypeLocForBlockDecl(const clang::TypeSourceInfo *TSInfo,
+                             clang::FunctionTypeLoc &Block,
+                             clang::FunctionProtoTypeLoc &BlockProto) {
+  if (!TSInfo)
+    return;
+
+  clang::TypeLoc TL = TSInfo->getTypeLoc().getUnqualifiedLoc();
+  while (true) {
+    // Look through qualified types
+    if (auto QualifiedTL = TL.getAs<clang::QualifiedTypeLoc>()) {
+      TL = QualifiedTL.getUnqualifiedLoc();
+      continue;
+    }
+
+    if (auto AttrTL = TL.getAs<clang::AttributedTypeLoc>()) {
+      TL = AttrTL.getModifiedLoc();
+      continue;
+    }
+
+    // Try to get the function prototype behind the block pointer type,
+    // then we're done.
+    if (auto BlockPtr = TL.getAs<clang::BlockPointerTypeLoc>()) {
+      TL = BlockPtr.getPointeeLoc().IgnoreParens();
+      Block = TL.getAs<clang::FunctionTypeLoc>();
+      BlockProto = TL.getAs<clang::FunctionProtoTypeLoc>();
+    }
+    break;
+  }
+}
+
+} // namespace
+
 DeclarationFragments &DeclarationFragments::appendSpace() {
   if (!Fragments.empty()) {
     Fragment &Last = Fragments.back();
@@ -218,7 +254,7 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
 
   // Declaration fragments of a pointer type is the declaration fragments of
   // the pointee type followed by a `*`,
-  if (T->isPointerType())
+  if (T->isPointerType() && !T->isFunctionPointerType())
     return Fragments
         .append(getFragmentsForType(T->getPointeeType(), Context, After))
         .append(" *", DeclarationFragments::FragmentKind::Text);
@@ -449,10 +485,6 @@ DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
         .append(VarDecl::getStorageClassSpecifierString(SC),
                 DeclarationFragments::FragmentKind::Keyword)
         .appendSpace();
-  QualType T =
-      Var->getTypeSourceInfo()
-          ? Var->getTypeSourceInfo()->getType()
-          : Var->getASTContext().getUnqualifiedObjCPointerType(Var->getType());
 
   // Capture potential fragments that needs to be placed after the variable name
   // ```
@@ -460,8 +492,23 @@ DeclarationFragmentsBuilder::getFragmentsForVar(const VarDecl *Var) {
   // char (*ptr_to_array)[6];
   // ```
   DeclarationFragments After;
-  return Fragments.append(getFragmentsForType(T, Var->getASTContext(), After))
-      .appendSpace()
+  FunctionTypeLoc BlockLoc;
+  FunctionProtoTypeLoc BlockProtoLoc;
+  findTypeLocForBlockDecl(Var->getTypeSourceInfo(), BlockLoc, BlockProtoLoc);
+
+  if (!BlockLoc) {
+    QualType T = Var->getTypeSourceInfo()
+                     ? Var->getTypeSourceInfo()->getType()
+                     : Var->getASTContext().getUnqualifiedObjCPointerType(
+                           Var->getType());
+
+    Fragments.append(getFragmentsForType(T, Var->getASTContext(), After))
+        .appendSpace();
+  } else {
+    Fragments.append(getFragmentsForBlock(Var, BlockLoc, BlockProtoLoc, After));
+  }
+
+  return Fragments
       .append(Var->getName(), DeclarationFragments::FragmentKind::Identifier)
       .append(std::move(After))
       .append(";", DeclarationFragments::FragmentKind::Text);
@@ -504,13 +551,23 @@ DeclarationFragments
 DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) {
   DeclarationFragments Fragments, After;
 
-  QualType T = Param->getTypeSourceInfo()
-                   ? Param->getTypeSourceInfo()->getType()
-                   : Param->getASTContext().getUnqualifiedObjCPointerType(
-                         Param->getType());
+  auto *TSInfo = Param->getTypeSourceInfo();
+
+  QualType T = TSInfo ? TSInfo->getType()
+                      : Param->getASTContext().getUnqualifiedObjCPointerType(
+                            Param->getType());
+
+  FunctionTypeLoc BlockLoc;
+  FunctionProtoTypeLoc BlockProtoLoc;
+  findTypeLocForBlockDecl(TSInfo, BlockLoc, BlockProtoLoc);
+
+  DeclarationFragments TypeFragments;
+  if (BlockLoc)
+    TypeFragments.append(
+        getFragmentsForBlock(Param, BlockLoc, BlockProtoLoc, After));
+  else
+    TypeFragments.append(getFragmentsForType(T, Param->getASTContext(), After));
 
-  DeclarationFragments TypeFragments =
-      getFragmentsForType(T, Param->getASTContext(), After);
   if (TypeFragments.begin()->Spelling.substr(0, 14).compare("type-parameter") ==
       0) {
     std::string ProperArgName = getNameForTemplateArgument(
@@ -522,17 +579,60 @@ DeclarationFragmentsBuilder::getFragmentsForParam(const ParmVarDecl *Param) {
     TypeFragments.begin()->Spelling.swap(ProperArgName);
   }
 
-  if (Param->isObjCMethodParameter())
+  if (Param->isObjCMethodParameter()) {
     Fragments.append("(", DeclarationFragments::FragmentKind::Text)
         .append(std::move(TypeFragments))
-        .append(") ", DeclarationFragments::FragmentKind::Text);
-  else
-    Fragments.append(std::move(TypeFragments)).appendSpace();
+        .append(std::move(After))
+        .append(") ", DeclarationFragments::FragmentKind::Text)
+        .append(Param->getName(),
+                DeclarationFragments::FragmentKind::InternalParam);
+  } else {
+    Fragments.append(std::move(TypeFragments));
+    if (!T->isBlockPointerType())
+      Fragments.appendSpace();
+    Fragments
+        .append(Param->getName(),
+                DeclarationFragments::FragmentKind::InternalParam)
+        .append(std::move(After));
+  }
+  return Fragments;
+}
 
-  return Fragments
-      .append(Param->getName(),
-              DeclarationFragments::FragmentKind::InternalParam)
-      .append(std::move(After));
+DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForBlock(
+    const NamedDecl *BlockDecl, FunctionTypeLoc &Block,
+    FunctionProtoTypeLoc &BlockProto, DeclarationFragments &After) {
+  DeclarationFragments Fragments;
+
+  DeclarationFragments RetTyAfter;
+  auto ReturnValueFragment = getFragmentsForType(
+      Block.getTypePtr()->getReturnType(), BlockDecl->getASTContext(), After);
+
+  Fragments.append(std::move(ReturnValueFragment))
+      .append(std::move(RetTyAfter))
+      .appendSpace()
+      .append("(^", DeclarationFragments::FragmentKind::Text);
+
+  After.append(")", DeclarationFragments::FragmentKind::Text);
+  unsigned NumParams = Block.getNumParams();
+
+  if (!BlockProto || NumParams == 0) {
+    if (BlockProto && BlockProto.getTypePtr()->isVariadic())
+      After.append("(...)", DeclarationFragments::FragmentKind::Text);
+    else
+      After.append("()", DeclarationFragments::FragmentKind::Text);
+  } else {
+    After.append("(", DeclarationFragments::FragmentKind::Text);
+    for (unsigned I = 0; I != NumParams; ++I) {
+      if (I)
+        After.append(", ", DeclarationFragments::FragmentKind::Text);
+      After.append(getFragmentsForParam(Block.getParam(I)));
+      if (I == NumParams - 1 && BlockProto.getTypePtr()->isVariadic())
+        After.append(", ...", DeclarationFragments::FragmentKind::Text);
+    }
+    After.append(")", DeclarationFragments::FragmentKind::Text);
+  }
+
+  return Fragments;
 }
 
 DeclarationFragments
@@ -595,11 +695,18 @@ DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
   Fragments.append(std::move(After));
 
   Fragments.append("(", DeclarationFragments::FragmentKind::Text);
-  for (unsigned i = 0, end = Func->getNumParams(); i != end; ++i) {
+  unsigned NumParams = Func->getNumParams();
+  for (unsigned i = 0; i != NumParams; ++i) {
     if (i)
       Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
     Fragments.append(getFragmentsForParam(Func->getParamDecl(i)));
   }
+
+  if (Func->isVariadic()) {
+    if (NumParams > 0)
+      Fragments.append(", ", DeclarationFragments::FragmentKind::Text);
+    Fragments.append("...", DeclarationFragments::FragmentKind::Text);
+  }
   Fragments.append(")", DeclarationFragments::FragmentKind::Text);
 
   Fragments.append(DeclarationFragments::getExceptionSpecificationString(
@@ -1248,14 +1355,27 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProperty(
     Fragments.append(")", DeclarationFragments::FragmentKind::Text);
   }
 
-  // Build the property type and name, and return the completed fragments.
-  return Fragments.appendSpace()
-      .append(getFragmentsForType(Property->getType(),
-                                  Property->getASTContext(), After))
-      .appendSpace()
+  Fragments.appendSpace();
+
+  FunctionTypeLoc BlockLoc;
+  FunctionProtoTypeLoc BlockProtoLoc;
+  findTypeLocForBlockDecl(Property->getTypeSourceInfo(), BlockLoc,
+                          BlockProtoLoc);
+
+  auto PropType = Property->getType();
+  if (!BlockLoc)
+    Fragments
+        .append(getFragmentsForType(PropType, Property->getASTContext(), After))
+        .appendSpace();
+  else
+    Fragments.append(
+        getFragmentsForBlock(Property, BlockLoc, BlockProtoLoc, After));
+
+  return Fragments
       .append(Property->getName(),
               DeclarationFragments::FragmentKind::Identifier)
-      .append(std::move(After));
+      .append(std::move(After))
+      .append(";", DeclarationFragments::FragmentKind::Text);
 }
 
 DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForObjCProtocol(
diff --git a/clang/test/ExtractAPI/objc_block.m b/clang/test/ExtractAPI/objc_block.m
new file mode 100644
index 000000000000000..a7a4f5696333c18
--- /dev/null
+++ b/clang/test/ExtractAPI/objc_block.m
@@ -0,0 +1,965 @@
+// RUN: rm -rf %t
+// RUN: split-file %s %t
+// RUN: sed -e "s@INPUT_DIR@%{/t:regex_replacement}@g" \
+// RUN: %t/reference.output.json.in >> %t/reference.output.json
+// RUN: %clang_cc1 -extract-api -fblocks -triple arm64-apple-macosx \
+// RUN: -x objective-c-header %t/input.h -o %t/output.json -verify
+
+// Generator version is not consistent across test runs, normalize it.
+// RUN: sed -e "s@\"generator\": \".*\"@\"generator\": \"?\"@g" \
+// RUN: %t/output.json >> %t/output-normalized.json
+// RUN: diff %t/reference.output.json %t/output-normalized.json
+
+//--- input.h
+@interface Foo
+-(void)methodBlockNoParam:(void (^)())block;
+-(void)methodBlockWithParam:(int (^)(int foo))block;
+-(void)methodBlockWithMultipleParam:(int (^)(int foo, unsigned baz))block;
+-(void)methodBlockVariadic:(int (^)(int foo, ...))block;
+@end
+
+void func(int (^arg)(int foo));
+
+int (^global)(int foo);
+
+///expected-no-diagnostics
+
+//--- reference.output.json.in
+{
+  "metadata": {
+    "formatVersion": {
+      "major": 0,
+      "minor": 5,
+      "patch": 3
+    },
+    "generator": "?"
+  },
+  "module": {
+    "name": "",
+    "platform": {
+      "architecture": "arm64",
+      "operatingSystem": {
+        "minimumVersion": {
+          "major": 11,
+          "minor": 0,
+          "patch": 0
+        },
+        "name": "macosx"
+      },
+      "vendor": "apple"
+    }
+  },
+  "relationships": [
+    {
+      "kind": "memberOf",
+      "source": "c:objc(cs)Foo(im)methodBlockNoParam:",
+      "target": "c:objc(cs)Foo",
+      "targetFallback": "Foo"
+    },
+    {
+      "kind": "memberOf",
+      "source": "c:objc(cs)Foo(im)methodBlockWithParam:",
+      "target": "c:objc(cs)Foo",
+      "targetFallback": "Foo"
+    },
+    {
+      "kind": "memberOf",
+      "source": "c:objc(cs)Foo(im)methodBlockWithMultipleParam:",
+      "target": "c:objc(cs)Foo",
+      "targetFallback": "Foo"
+    },
+    {
+      "kind": "memberOf",
+      "source": "c:objc(cs)Foo(im)methodBlockVariadic:",
+      "target": "c:objc(cs)Foo",
+      "targetFallback": "Foo"
+    }
+  ],
+  "symbols": [
+    {
+      "accessLevel": "public",
+      "declarationFragments": [
+        {
+          "kind": "typeIdentifier",
+          "preciseIdentifier": "c:I",
+          "spelling": "int"
+        },
+        {
+          "kind": "text",
+          "spelling": " (^"
+        },
+        {
+          "kind": "identifier",
+          "spelling": "global"
+        },
+        {
+          "kind": "text",
+          "spelling": ")("
+        },
+        {
+          "kind": "typeIdentifier",
+          "preciseIdentifier": "c:I",
+          "spelling": "int"
+        },
+        {
+          "kind": "text",
+          "spelling": " "
+        },
+        {
+          "kind": "internalParam",
+          "spelling": "foo"
+        },
+        {
+          "kind": "text",
+          "spelling": ");"
+        }
+      ],
+      "identifier": {
+        "interfaceLanguage": "objective-c",
+        "precise": "c:@global"
+      },
+      "kind": {
+        "displayName": "Global Variable",
+        "identifier": "objective-c.var"
+      },
+      "location": {
+        "position": {
+          "character": 6,
+          "line": 9
+        },
+        "uri": "file://INPUT_DIR/input.h"
+      },
+      "names": {
+        "navigator": [
+          {
+            "kind": "identifier",
+            "spelling": "global"
+          }
+        ],
+        "subHeading": [
+          {
+            "kind": "identifier",
+            "spelling": "global"
+          }
+        ],
+        "title": "global"
+      },
+      "pathComponents": [
+        "global"
+      ]
+    },
+    {
+      "accessLevel": "public",
+      "declarationFragments": [
+        {
+          "kind": "typeIdentifier",
+          "preciseIdentifier": "c:v",
+          "spelling": "void"
+        },
+        {
+          "kind": "text",
+          "spelling": " "
+        },
+        {
+          "kind": "identifier",
+          "spelling": "func"
+        },
+        {
+          "kind": "text",
+          "spelling": "("
+        },
+        {
+          "kind": "typeIdentifier",
+          "preciseIdentifier": "c:I",
+          "spelling": "int"
+        },
+        {
+          "kind": "text",
+          "spelling": " (^"
+        },
+        {
+          "kind": "internalParam",
+          "spelling": "arg"
+        },
+        {
+          "kind": "text",
+          "spelling": ")("
+        },
+        {
+          "kind": "typeIdentifier",
+          "preciseIdentifier": "c:I",
+          "spelling": "int"
+        },
+        {
+          "kind": "text",
+          "spelling": " "
+        },
+        {
+          "kind": "internalParam",
+          "spelling": "foo"
+        },
+        {
+          "kind": "text",
+          "spelling": "));"
+        }
+      ],
+      "functionSignature": {
+        "parameters": [
+          {
+            "declarationFragments": [
+              {
+                "kind": "typeIdentifier",
+                "preciseIdentifier": "c:I",
+                "spelling": "int"
+              },
+              {
+                "kind": "text",
+                "spelling": " (^"
+              },
+              {
+                "kind": "internalParam",
+                "spelling": "arg"
+              },
+              {
+                "kind": "text",
+                "spelling": ")("
+              },
+              {
+                "kind": "typeIdentifier",
+                "preciseIdentifier": "c:I",
+                "spelling": "int"
+              },
+              {
+                "kind": "text",
+                "spelling": " "
+              },
+              {
+                "kind": "internalParam",
+                "spelling": "foo"
+              },
+              {
+                "kind": "text",
+                "spelling": ")"
+              }
+            ],
+            "name": "arg"
+          }
+        ],
+        "returns": [
+          {
+            "kind": "typeIdentifier",
+            "preciseIdentifier": "c:v",
+            "spelling": "void"
+          }
+        ]
+      },
+      "identifier": {
+        "interfaceLanguage": "objective-c",
+        "precise": "c:@F@func"
+      },
+      "kind": {
+        "displayName": "Function",
+        "identifier": "objective-c.func"
+      },
+      "location": {
+        "position": {
+          "character": 5,
+          "line": 7
+        },
+        "uri": "file://INPUT_DIR/input.h"
+      },
+      "names": {
+        "navigator": [
+          {
+            "kind": "identifier",
+            "spelling": "func"
+          }
+        ],
+        "subHeading": [
+          {
+            "kind": "identifier",
+            "spelling": "func"
+          }
+        ],
+        "title": "func"
+      },
+      "pathComponents": [
+        "func"
+      ]
+    },
+    {
+      "accessLevel": "public",
+      "declarationFragments": [
+        {
+          "kind": "keyword",
+          "spelling": "@interface"
+        },
+        {
+          "kind": "text",
+          "spelling": " "
+        },
+        {
+          "kind": "identifier",
+          "spelling": "Foo"
+        }
+      ],
+      "identifier": {
+        "interfaceLanguage": "objective-c",
+        "precise": "c:objc(cs)Foo"
+      },
+      "kind": {
+        "displayName": "Class",
+        "identifier": "objective-c.class"
+      },
+      "location": {
+        "position": {
+          "character": 11,
+          "line": 0
+        },
+        "uri": "file://INPUT_DIR/input.h"
+      },
+      "names": {
+        "navigator": [
+          {
+            "kind": "identifier",
+            "spelling": "Foo"
+          }
+        ],
+        "subHeading": [
+          {
+            "kind": "identifier",
+            "spelling": "Foo"
+          }
+        ],
+        "title": "Foo"
+      },
+      "pathComponents": [
+        "Foo"
+      ]
+    },
+    {
+      "accessLevel": "public",
+      "declarationFragments": [
+        {
+          "kind": "text",
+          "spelling": "- ("
+        },
+        {
+          "kind": "typeIdentifier",
+          "preciseIdentifier": "c:v",
+          "spelling": "void"
+        },
+        {
+          "kind": "text",
+          "spelling": ") "
+        },
+        {
+          "kind": "identifier",
+          "spelling": "methodBlockNoParam:"
+        },
+        {
+          "kind": "text",
+          "spelling": "("
+        },
+        {
+          "kind": "typeIdentifier",
+          "preciseIdentifier": "c:v",
+          "spelling": "void"
+        },
+        {
+          "kind": "text",
+          "spelling": " (^"
+        },
+        {
+          "kind": "text",
+          "spelling": ")()) "
+        },
+        {
+          "kind": "internalParam",
+          "spelling": "block"
+        },
+        {
+          "kind": "text",
+          "spelling": ";"
+        }
+      ],
+      "functionSignature": {
+        "parameters": [
+          {
+            "declarationFragments": [
+              {
+                "kind": "text",
+                "spelling": "("
+              },
+              {
+                "kind": "typeIdentifier",
+                "preciseIdentifier": "c:v",
+                "spelling": "void...
[truncated]

Copy link
Contributor

@evelez7 evelez7 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@daniel-grumberg daniel-grumberg merged commit 6b89fab into llvm:main Nov 28, 2023
4 checks passed
@daniel-grumberg daniel-grumberg deleted the param-param-decl-fragments branch November 28, 2023 12:55
daniel-grumberg added a commit to apple/llvm-project that referenced this pull request Dec 1, 2023
…lvm#73369)

Ensure that block types get represented correctly in declaration
fragments, as block parameter names are important for documentation
clients we need a separate system from getFragmentsForType in order to
have access to full ParmVarDecls for the parameters.

rdar://118257401
daniel-grumberg added a commit to daniel-grumberg/llvm-project that referenced this pull request Dec 1, 2023
…lvm#73369)

Ensure that block types get represented correctly in declaration
fragments, as block parameter names are important for documentation
clients we need a separate system from getFragmentsForType in order to
have access to full ParmVarDecls for the parameters.

rdar://118257401
daniel-grumberg added a commit to apple/llvm-project that referenced this pull request Dec 4, 2023
…lvm#73369)

Ensure that block types get represented correctly in declaration
fragments, as block parameter names are important for documentation
clients we need a separate system from getFragmentsForType in order to
have access to full ParmVarDecls for the parameters.

rdar://118257401
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants