Skip to content

[clang][ExtractAPI] Correctly generate declaration fragments for non-type template parameters #91958

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

Merged
merged 1 commit into from
May 17, 2024

Conversation

daniel-grumberg
Copy link
Contributor

Previously we only generated declaration fragments for template type parameters/arguments, this adds supports for most other possible template parameters/arguments.

rdar://127732598

…type template parameters.

Previously we only generated declaration fragments for template type
paramters/arguments, this adds supports for most other possible template
parameters/arguments.

rdar://127732598
@llvmbot llvmbot added the clang Clang issues not falling into any other category label May 13, 2024
@llvmbot
Copy link
Member

llvmbot commented May 13, 2024

@llvm/pr-subscribers-clang

Author: Daniel Grumberg (daniel-grumberg)

Changes

Previously we only generated declaration fragments for template type parameters/arguments, this adds supports for most other possible template parameters/arguments.

rdar://127732598


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

15 Files Affected:

  • (modified) clang/lib/ExtractAPI/DeclarationFragments.cpp (+189-37)
  • (modified) clang/test/ExtractAPI/class_template.cpp (+1-1)
  • (modified) clang/test/ExtractAPI/class_template_param_inheritance.cpp (+1-1)
  • (modified) clang/test/ExtractAPI/class_template_partial_spec.cpp (+2-2)
  • (modified) clang/test/ExtractAPI/class_template_spec.cpp (+2-2)
  • (modified) clang/test/ExtractAPI/concept.cpp (+1-1)
  • (modified) clang/test/ExtractAPI/field_template.cpp (+1-1)
  • (modified) clang/test/ExtractAPI/global_func_template.cpp (+2-2)
  • (modified) clang/test/ExtractAPI/global_func_template_spec.cpp (+2-2)
  • (modified) clang/test/ExtractAPI/global_var_template.cpp (+1-1)
  • (modified) clang/test/ExtractAPI/global_var_template_partial_spec.cpp (+2-2)
  • (modified) clang/test/ExtractAPI/global_var_template_spec.cpp (+2-2)
  • (modified) clang/test/ExtractAPI/method_template.cpp (+1-1)
  • (modified) clang/test/ExtractAPI/method_template_spec.cpp (+2-2)
  • (added) clang/test/ExtractAPI/non_type_template.cpp (+313)
diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp
index 9bf7950888dbb..98b9343924a83 100644
--- a/clang/lib/ExtractAPI/DeclarationFragments.cpp
+++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp
@@ -12,13 +12,19 @@
 //===----------------------------------------------------------------------===//
 
 #include "clang/ExtractAPI/DeclarationFragments.h"
+#include "clang/AST/ASTFwd.h"
 #include "clang/AST/Decl.h"
 #include "clang/AST/DeclCXX.h"
+#include "clang/AST/TemplateBase.h"
+#include "clang/AST/TemplateName.h"
 #include "clang/AST/Type.h"
 #include "clang/AST/TypeLoc.h"
 #include "clang/ExtractAPI/TypedefUnderlyingTypeResolver.h"
 #include "clang/Index/USRGeneration.h"
 #include "llvm/ADT/StringSwitch.h"
+#include "llvm/Support/ErrorHandling.h"
+#include "llvm/Support/raw_ostream.h"
+#include <optional>
 
 using namespace clang::extractapi;
 using namespace llvm;
@@ -386,6 +392,25 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForType(
         getFragmentsForType(AT->getElementType(), Context, After));
   }
 
+  if (const TemplateSpecializationType *TemplSpecTy =
+          dyn_cast<TemplateSpecializationType>(T)) {
+    const auto TemplName = TemplSpecTy->getTemplateName();
+    std::string Str;
+    raw_string_ostream Stream(Str);
+    TemplName.print(Stream, Context.getPrintingPolicy(),
+                    TemplateName::Qualified::AsWritten);
+    SmallString<64> USR("");
+    if (const auto *TemplDecl = TemplName.getAsTemplateDecl())
+      index::generateUSRForDecl(TemplDecl, USR);
+
+    return Fragments
+        .append(Str, DeclarationFragments::FragmentKind::TypeIdentifier, USR)
+        .append("<", DeclarationFragments::FragmentKind::Text)
+        .append(getFragmentsForTemplateArguments(
+            TemplSpecTy->template_arguments(), Context, std::nullopt))
+        .append(">", DeclarationFragments::FragmentKind::Text);
+  }
+
   // Everything we care about has been handled now, reduce to the canonical
   // unqualified base type.
   QualType Base = T->getCanonicalTypeUnqualified();
@@ -650,7 +675,6 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForBlock(
 DeclarationFragments
 DeclarationFragmentsBuilder::getFragmentsForFunction(const FunctionDecl *Func) {
   DeclarationFragments Fragments;
-  // FIXME: Handle template specialization
   switch (Func->getStorageClass()) {
   case SC_None:
   case SC_PrivateExtern:
@@ -952,27 +976,84 @@ DeclarationFragmentsBuilder::getFragmentsForTemplateParameters(
       Fragments.append(",", DeclarationFragments::FragmentKind::Text)
           .appendSpace();
 
-    const auto *TemplateParam =
-        dyn_cast<TemplateTypeParmDecl>(ParameterArray[i]);
-    if (!TemplateParam)
-      continue;
-    if (TemplateParam->hasTypeConstraint())
-      Fragments.append(TemplateParam->getTypeConstraint()
-                           ->getNamedConcept()
-                           ->getName()
-                           .str(),
-                       DeclarationFragments::FragmentKind::TypeIdentifier);
-    else if (TemplateParam->wasDeclaredWithTypename())
-      Fragments.append("typename", DeclarationFragments::FragmentKind::Keyword);
-    else
-      Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);
-
-    if (TemplateParam->isParameterPack())
-      Fragments.append("...", DeclarationFragments::FragmentKind::Text);
-
-    Fragments.appendSpace().append(
-        TemplateParam->getName(),
-        DeclarationFragments::FragmentKind::GenericParameter);
+    if (const auto *TemplateParam =
+            dyn_cast<TemplateTypeParmDecl>(ParameterArray[i])) {
+      if (TemplateParam->hasTypeConstraint())
+        Fragments.append(TemplateParam->getTypeConstraint()
+                             ->getNamedConcept()
+                             ->getName()
+                             .str(),
+                         DeclarationFragments::FragmentKind::TypeIdentifier);
+      else if (TemplateParam->wasDeclaredWithTypename())
+        Fragments.append("typename",
+                         DeclarationFragments::FragmentKind::Keyword);
+      else
+        Fragments.append("class", DeclarationFragments::FragmentKind::Keyword);
+
+      if (TemplateParam->isParameterPack())
+        Fragments.append("...", DeclarationFragments::FragmentKind::Text);
+
+      if (!TemplateParam->getName().empty())
+        Fragments.appendSpace().append(
+            TemplateParam->getName(),
+            DeclarationFragments::FragmentKind::GenericParameter);
+
+      if (TemplateParam->hasDefaultArgument()) {
+        DeclarationFragments After;
+        Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)
+            .append(getFragmentsForType(TemplateParam->getDefaultArgument(),
+                                        TemplateParam->getASTContext(), After));
+        Fragments.append(std::move(After));
+      }
+    } else if (const auto *NTP =
+                   dyn_cast<NonTypeTemplateParmDecl>(ParameterArray[i])) {
+      DeclarationFragments After;
+      const auto TyFragments =
+          getFragmentsForType(NTP->getType(), NTP->getASTContext(), After);
+      Fragments.append(std::move(TyFragments)).append(std::move(After));
+
+      if (NTP->isParameterPack())
+        Fragments.append("...", DeclarationFragments::FragmentKind::Text);
+
+      if (!NTP->getName().empty())
+        Fragments.appendSpace().append(
+            NTP->getName(),
+            DeclarationFragments::FragmentKind::GenericParameter);
+
+      if (NTP->hasDefaultArgument()) {
+        SmallString<8> ExprStr;
+        raw_svector_ostream Output(ExprStr);
+        NTP->getDefaultArgument()->printPretty(
+            Output, nullptr, NTP->getASTContext().getPrintingPolicy());
+        Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)
+            .append(ExprStr, DeclarationFragments::FragmentKind::Text);
+      }
+    } else if (const auto *TTP =
+                   dyn_cast<TemplateTemplateParmDecl>(ParameterArray[i])) {
+      Fragments.append("template", DeclarationFragments::FragmentKind::Keyword)
+          .appendSpace()
+          .append("<", DeclarationFragments::FragmentKind::Text)
+          .append(getFragmentsForTemplateParameters(
+              TTP->getTemplateParameters()->asArray()))
+          .append(">", DeclarationFragments::FragmentKind::Text)
+          .appendSpace()
+          .append(TTP->wasDeclaredWithTypename() ? "typename" : "class",
+                  DeclarationFragments::FragmentKind::Keyword);
+
+      if (TTP->isParameterPack())
+        Fragments.append("...", DeclarationFragments::FragmentKind::Text);
+
+      if (!TTP->getName().empty())
+        Fragments.appendSpace().append(
+            TTP->getName(),
+            DeclarationFragments::FragmentKind::GenericParameter);
+      if (TTP->hasDefaultArgument()) {
+        const auto Default = TTP->getDefaultArgument();
+        Fragments.append(" = ", DeclarationFragments::FragmentKind::Text)
+            .append(getFragmentsForTemplateArguments(
+                {Default.getArgument()}, TTP->getASTContext(), {Default}));
+      }
+    }
   }
   return Fragments;
 }
@@ -993,23 +1074,85 @@ DeclarationFragmentsBuilder::getFragmentsForTemplateArguments(
       Fragments.append(",", DeclarationFragments::FragmentKind::Text)
           .appendSpace();
 
-    std::string Type = TemplateArguments[i].getAsType().getAsString();
-    DeclarationFragments After;
-    DeclarationFragments ArgumentFragment =
-        getFragmentsForType(TemplateArguments[i].getAsType(), Context, After);
-
-    if (StringRef(ArgumentFragment.begin()->Spelling)
-            .starts_with("type-parameter")) {
-      std::string ProperArgName = TemplateArgumentLocs.value()[i]
-                                      .getTypeSourceInfo()
-                                      ->getType()
-                                      .getAsString();
-      ArgumentFragment.begin()->Spelling.swap(ProperArgName);
+    const auto &CTA = TemplateArguments[i];
+    switch (CTA.getKind()) {
+    case TemplateArgument::Type: {
+      DeclarationFragments After;
+      DeclarationFragments ArgumentFragment =
+          getFragmentsForType(CTA.getAsType(), Context, After);
+
+      if (StringRef(ArgumentFragment.begin()->Spelling)
+              .starts_with("type-parameter")) {
+        std::string ProperArgName = TemplateArgumentLocs.value()[i]
+                                        .getTypeSourceInfo()
+                                        ->getType()
+                                        .getAsString();
+        ArgumentFragment.begin()->Spelling.swap(ProperArgName);
+      }
+      Fragments.append(std::move(ArgumentFragment));
+      break;
     }
-    Fragments.append(std::move(ArgumentFragment));
+    case TemplateArgument::Declaration: {
+      const auto *VD = CTA.getAsDecl();
+      SmallString<128> USR;
+      index::generateUSRForDecl(VD, USR);
+      Fragments.append(VD->getNameAsString(),
+                       DeclarationFragments::FragmentKind::Identifier, USR);
+      break;
+    }
+    case TemplateArgument::NullPtr:
+      Fragments.append("nullptr", DeclarationFragments::FragmentKind::Keyword);
+      break;
 
-    if (TemplateArguments[i].isPackExpansion())
-      Fragments.append("...", DeclarationFragments::FragmentKind::Text);
+    case TemplateArgument::Integral: {
+      SmallString<4> Str;
+      CTA.getAsIntegral().toString(Str);
+      Fragments.append(Str, DeclarationFragments::FragmentKind::Text);
+      break;
+    }
+
+    case TemplateArgument::StructuralValue: {
+      const auto SVTy = CTA.getStructuralValueType();
+      Fragments.append(CTA.getAsStructuralValue().getAsString(Context, SVTy),
+                       DeclarationFragments::FragmentKind::Text);
+      break;
+    }
+
+    case TemplateArgument::TemplateExpansion:
+    case TemplateArgument::Template: {
+      std::string Str;
+      raw_string_ostream Stream(Str);
+      CTA.getAsTemplate().print(Stream, Context.getPrintingPolicy());
+      SmallString<64> USR("");
+      if (const auto *TemplDecl =
+              CTA.getAsTemplateOrTemplatePattern().getAsTemplateDecl())
+        index::generateUSRForDecl(TemplDecl, USR);
+      Fragments.append(Str, DeclarationFragments::FragmentKind::TypeIdentifier,
+                       USR);
+      if (CTA.getKind() == TemplateArgument::TemplateExpansion)
+        Fragments.append("...", DeclarationFragments::FragmentKind::Text);
+      break;
+    }
+
+    case TemplateArgument::Pack:
+      Fragments.append("<", DeclarationFragments::FragmentKind::Text)
+          .append(getFragmentsForTemplateArguments(CTA.pack_elements(), Context,
+                                                   {}))
+          .append(">", DeclarationFragments::FragmentKind::Text);
+      break;
+
+    case TemplateArgument::Expression: {
+      SmallString<8> ExprStr;
+      raw_svector_ostream Output(ExprStr);
+      CTA.getAsExpr()->printPretty(Output, nullptr,
+                                   Context.getPrintingPolicy());
+      Fragments.append(ExprStr, DeclarationFragments::FragmentKind::Text);
+      break;
+    }
+
+    case TemplateArgument::Null:
+      break;
+    }
   }
   return Fragments;
 }
@@ -1019,10 +1162,12 @@ DeclarationFragments DeclarationFragmentsBuilder::getFragmentsForConcept(
   DeclarationFragments Fragments;
   return Fragments
       .append("template", DeclarationFragments::FragmentKind::Keyword)
+      .appendSpace()
       .append("<", DeclarationFragments::FragmentKind::Text)
       .append(getFragmentsForTemplateParameters(
           Concept->getTemplateParameters()->asArray()))
       .append("> ", DeclarationFragments::FragmentKind::Text)
+      .appendSpace()
       .append("concept", DeclarationFragments::FragmentKind::Keyword)
       .appendSpace()
       .append(Concept->getName().str(),
@@ -1035,6 +1180,7 @@ DeclarationFragmentsBuilder::getFragmentsForRedeclarableTemplate(
     const RedeclarableTemplateDecl *RedeclarableTemplate) {
   DeclarationFragments Fragments;
   Fragments.append("template", DeclarationFragments::FragmentKind::Keyword)
+      .appendSpace()
       .append("<", DeclarationFragments::FragmentKind::Text)
       .append(getFragmentsForTemplateParameters(
           RedeclarableTemplate->getTemplateParameters()->asArray()))
@@ -1057,6 +1203,7 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization(
   DeclarationFragments Fragments;
   return Fragments
       .append("template", DeclarationFragments::FragmentKind::Keyword)
+      .appendSpace()
       .append("<", DeclarationFragments::FragmentKind::Text)
       .append(">", DeclarationFragments::FragmentKind::Text)
       .appendSpace()
@@ -1077,6 +1224,7 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplatePartialSpecialization(
   DeclarationFragments Fragments;
   return Fragments
       .append("template", DeclarationFragments::FragmentKind::Keyword)
+      .appendSpace()
       .append("<", DeclarationFragments::FragmentKind::Text)
       .append(getFragmentsForTemplateParameters(
           Decl->getTemplateParameters()->asArray()))
@@ -1099,6 +1247,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization(
   DeclarationFragments Fragments;
   return Fragments
       .append("template", DeclarationFragments::FragmentKind::Keyword)
+      .appendSpace()
       .append("<", DeclarationFragments::FragmentKind::Text)
       .append(">", DeclarationFragments::FragmentKind::Text)
       .appendSpace()
@@ -1118,6 +1267,7 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplatePartialSpecialization(
   DeclarationFragments Fragments;
   return Fragments
       .append("template", DeclarationFragments::FragmentKind::Keyword)
+      .appendSpace()
       .append("<", DeclarationFragments::FragmentKind::Text)
       // Partial specs may have new params.
       .append(getFragmentsForTemplateParameters(
@@ -1140,6 +1290,7 @@ DeclarationFragmentsBuilder::getFragmentsForFunctionTemplate(
   DeclarationFragments Fragments;
   return Fragments
       .append("template", DeclarationFragments::FragmentKind::Keyword)
+      .appendSpace()
       .append("<", DeclarationFragments::FragmentKind::Text)
       // Partial specs may have new params.
       .append(getFragmentsForTemplateParameters(
@@ -1156,6 +1307,7 @@ DeclarationFragmentsBuilder::getFragmentsForFunctionTemplateSpecialization(
   DeclarationFragments Fragments;
   return Fragments
       .append("template", DeclarationFragments::FragmentKind::Keyword)
+      .appendSpace()
       .append("<>", DeclarationFragments::FragmentKind::Text)
       .appendSpace()
       .append(DeclarationFragmentsBuilder::getFragmentsForFunction(Decl));
diff --git a/clang/test/ExtractAPI/class_template.cpp b/clang/test/ExtractAPI/class_template.cpp
index 4f2670d7b6997..203d47394dd60 100644
--- a/clang/test/ExtractAPI/class_template.cpp
+++ b/clang/test/ExtractAPI/class_template.cpp
@@ -51,7 +51,7 @@ template<typename T> class Foo {};
         },
         {
           "kind": "text",
-          "spelling": "<"
+          "spelling": " <"
         },
         {
           "kind": "keyword",
diff --git a/clang/test/ExtractAPI/class_template_param_inheritance.cpp b/clang/test/ExtractAPI/class_template_param_inheritance.cpp
index 3d7b09f93ed6d..53b331e0b460b 100644
--- a/clang/test/ExtractAPI/class_template_param_inheritance.cpp
+++ b/clang/test/ExtractAPI/class_template_param_inheritance.cpp
@@ -58,7 +58,7 @@ template<typename T> class Foo : public T {};
         },
         {
           "kind": "text",
-          "spelling": "<"
+          "spelling": " <"
         },
         {
           "kind": "keyword",
diff --git a/clang/test/ExtractAPI/class_template_partial_spec.cpp b/clang/test/ExtractAPI/class_template_partial_spec.cpp
index c8d9cc78d41c5..7d244f49c7359 100644
--- a/clang/test/ExtractAPI/class_template_partial_spec.cpp
+++ b/clang/test/ExtractAPI/class_template_partial_spec.cpp
@@ -53,7 +53,7 @@ template<typename Z> class Foo<Z, int> {};
         },
         {
           "kind": "text",
-          "spelling": "<"
+          "spelling": " <"
         },
         {
           "kind": "keyword",
@@ -161,7 +161,7 @@ template<typename Z> class Foo<Z, int> {};
         },
         {
           "kind": "text",
-          "spelling": "<"
+          "spelling": " <"
         },
         {
           "kind": "keyword",
diff --git a/clang/test/ExtractAPI/class_template_spec.cpp b/clang/test/ExtractAPI/class_template_spec.cpp
index 06a95314dc4aa..9dbd887510c70 100644
--- a/clang/test/ExtractAPI/class_template_spec.cpp
+++ b/clang/test/ExtractAPI/class_template_spec.cpp
@@ -53,7 +53,7 @@ template<> class Foo<int> {};
         },
         {
           "kind": "text",
-          "spelling": "<"
+          "spelling": " <"
         },
         {
           "kind": "keyword",
@@ -140,7 +140,7 @@ template<> class Foo<int> {};
         },
         {
           "kind": "text",
-          "spelling": "<> "
+          "spelling": " <> "
         },
         {
           "kind": "keyword",
diff --git a/clang/test/ExtractAPI/concept.cpp b/clang/test/ExtractAPI/concept.cpp
index 443eac2971f0e..4396a39a63ef6 100644
--- a/clang/test/ExtractAPI/concept.cpp
+++ b/clang/test/ExtractAPI/concept.cpp
@@ -51,7 +51,7 @@ template<typename T> concept Foo = true;
         },
         {
           "kind": "text",
-          "spelling": "<"
+          "spelling": " <"
         },
         {
           "kind": "keyword",
diff --git a/clang/test/ExtractAPI/field_template.cpp b/clang/test/ExtractAPI/field_template.cpp
index 2058ed008cfe4..973a9de5c9986 100644
--- a/clang/test/ExtractAPI/field_template.cpp
+++ b/clang/test/ExtractAPI/field_template.cpp
@@ -114,7 +114,7 @@ class Foo {
         },
         {
           "kind": "text",
-          "spelling": "<"
+          "spelling": " <"
         },
         {
           "kind": "keyword",
diff --git a/clang/test/ExtractAPI/global_func_template.cpp b/clang/test/ExtractAPI/global_func_template.cpp
index f43a618ec0c36..044757c316d58 100644
--- a/clang/test/ExtractAPI/global_func_template.cpp
+++ b/clang/test/ExtractAPI/global_func_template.cpp
@@ -52,7 +52,7 @@ template<typename T> T Fizz(int Buzz);
         },
         {
           "kind": "text",
-          "spelling": "<"
+          "spelling": " <"
         },
         {
           "kind": "keyword",
@@ -186,7 +186,7 @@ template<typename T> T Fizz(int Buzz);
         },
         {
           "kind": "text",
-          "spelling": "<"
+          "spelling": " <"
         },
         {
           "kind": "keyword",
diff --git a/clang/test/ExtractAPI/global_func_template_spec.cpp b/clang/test/ExtractAPI/global_func_template_spec.cpp
index fe046e9c3b9da..b88063aacfedc 100644
--- a/clang/test/ExtractAPI/global_func_template_spec.cpp
+++ b/clang/test/ExtractAPI/global_func_template_spec.cpp
@@ -52,7 +52,7 @@ template<> void Foo<int>(int Bar);
         },
         {
           "kind": "text",
-          "spelling": "<"
+          "spelling": " <"
         },
         {
           "kind": "keyword",
@@ -186,7 +186,7 @@ template<> void Foo<int>(int Bar);
         },
         {
           "kind": "text",
-          "spelling": "<> "
+          "spelling": " <> "
         },
         {
           "kind": "typeIdentifier",
diff --git a/clang/test/ExtractAPI/global_var_template.cpp b/clang/test/ExtractAPI/global_var_template.cpp
index 94f3713cd3d31..5c9194141332b 100644
--- a/clang/test/ExtractAPI/global_var_template.cpp
+++ b/clang/test/ExtractAPI/global_var_template.cpp
@@ -50,7 +50,7 @@ template<typename T> T Foo = T(3.14);
         },
         {
           "kind": "text",
-          "spelling": "<"
+          "spelling": " <"
         },
         {
           "kind": "keyword",
diff --git a/clang/test/ExtractAPI/global_var_template_partial_spec.cpp b/clang/test/ExtractAPI/global_var_template_partial_spec.cpp
index 91084f258878e..ffb1557fd7580 100644
--- a/clang/test/ExtractAPI/global_var_template_partial_spec.cpp
+++ b/clang/test/ExtractAPI/global_var_template_partial_spec.cpp
@@ -52,7 +52,7 @@ template<typename Z> int Foo<int, Z> = 0;
         },
         {
           "kind": "text",
-          "spelling": "<"
+          "spelling": " <"
         },
         {
           "kind": "keyword",
@@ -161,7 +161,7 @@ template<typename Z> int Foo<...
[truncated]

Copy link
Contributor

@QuietMisdreavus QuietMisdreavus left a comment

Choose a reason for hiding this comment

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

Looks good, thanks!

@daniel-grumberg daniel-grumberg merged commit 7a67479 into llvm:main May 17, 2024
6 checks passed
daniel-grumberg added a commit to daniel-grumberg/llvm-project that referenced this pull request May 24, 2024
…type template parameters (llvm#91958)

Previously we only generated declaration fragments for template type
parameters/arguments, this adds supports for most other possible
template parameters/arguments.

rdar://127732598
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.

3 participants