https://github.com/daniel-grumberg created https://github.com/llvm/llvm-project/pull/91958
Previously we only generated declaration fragments for template type parameters/arguments, this adds supports for most other possible template parameters/arguments. rdar://127732598 >From d86e4256da57451a08d580b8eecd5525bd1642c6 Mon Sep 17 00:00:00 2001 From: Daniel Grumberg <dgrumb...@apple.com> Date: Wed, 8 May 2024 12:22:47 +0100 Subject: [PATCH] [clang][ExtractAPI] Correctly generate declaration fragments for non-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 --- clang/lib/ExtractAPI/DeclarationFragments.cpp | 226 ++++++++++--- clang/test/ExtractAPI/class_template.cpp | 2 +- .../class_template_param_inheritance.cpp | 2 +- .../class_template_partial_spec.cpp | 4 +- clang/test/ExtractAPI/class_template_spec.cpp | 4 +- clang/test/ExtractAPI/concept.cpp | 2 +- clang/test/ExtractAPI/field_template.cpp | 2 +- .../test/ExtractAPI/global_func_template.cpp | 4 +- .../ExtractAPI/global_func_template_spec.cpp | 4 +- clang/test/ExtractAPI/global_var_template.cpp | 2 +- .../global_var_template_partial_spec.cpp | 4 +- .../ExtractAPI/global_var_template_spec.cpp | 4 +- clang/test/ExtractAPI/method_template.cpp | 2 +- .../test/ExtractAPI/method_template_spec.cpp | 4 +- clang/test/ExtractAPI/non_type_template.cpp | 313 ++++++++++++++++++ 15 files changed, 522 insertions(+), 57 deletions(-) create mode 100644 clang/test/ExtractAPI/non_type_template.cpp 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<int, Z> = 0; }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", diff --git a/clang/test/ExtractAPI/global_var_template_spec.cpp b/clang/test/ExtractAPI/global_var_template_spec.cpp index ff4d8d17aecbe..e465da97db1f2 100644 --- a/clang/test/ExtractAPI/global_var_template_spec.cpp +++ b/clang/test/ExtractAPI/global_var_template_spec.cpp @@ -52,7 +52,7 @@ template<> int Foo<int>; }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", @@ -140,7 +140,7 @@ template<> int Foo<int>; }, { "kind": "text", - "spelling": "<> " + "spelling": " <> " }, { "kind": "typeIdentifier", diff --git a/clang/test/ExtractAPI/method_template.cpp b/clang/test/ExtractAPI/method_template.cpp index 714f9cac26c20..bf91a208c5488 100644 --- a/clang/test/ExtractAPI/method_template.cpp +++ b/clang/test/ExtractAPI/method_template.cpp @@ -114,7 +114,7 @@ class Foo { }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", diff --git a/clang/test/ExtractAPI/method_template_spec.cpp b/clang/test/ExtractAPI/method_template_spec.cpp index 8eaffdefd827a..978dbe1b6c1d6 100644 --- a/clang/test/ExtractAPI/method_template_spec.cpp +++ b/clang/test/ExtractAPI/method_template_spec.cpp @@ -122,7 +122,7 @@ class Foo { }, { "kind": "text", - "spelling": "<" + "spelling": " <" }, { "kind": "keyword", @@ -257,7 +257,7 @@ class Foo { }, { "kind": "text", - "spelling": "<> " + "spelling": " <> " }, { "kind": "typeIdentifier", diff --git a/clang/test/ExtractAPI/non_type_template.cpp b/clang/test/ExtractAPI/non_type_template.cpp new file mode 100644 index 0000000000000..4e65eb790ca11 --- /dev/null +++ b/clang/test/ExtractAPI/non_type_template.cpp @@ -0,0 +1,313 @@ +// RUN: rm -rf %t +// RUN: %clang_cc1 -extract-api --pretty-sgf --emit-sgf-symbol-labels-for-testing \ +// RUN: -triple arm64-apple-macosx -std=c++17 -x c++-header %s -o %t/output.symbols.json -verify + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix FOO +template <typename T, int N = 4> class Foo { }; +// FOO-LABEL: "!testLabel": "c:@ST>2#T#NI@Foo" +// FOO: "declarationFragments": [ +// FOO-NEXT: { +// FOO-NEXT: "kind": "keyword", +// FOO-NEXT: "spelling": "template" +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "text", +// FOO-NEXT: "spelling": " <" +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "keyword", +// FOO-NEXT: "spelling": "typename" +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "text", +// FOO-NEXT: "spelling": " " +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "genericParameter", +// FOO-NEXT: "spelling": "T" +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "text", +// FOO-NEXT: "spelling": ", " +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "typeIdentifier", +// FOO-NEXT: "preciseIdentifier": "c:I", +// FOO-NEXT: "spelling": "int" +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "text", +// FOO-NEXT: "spelling": " " +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "genericParameter", +// FOO-NEXT: "spelling": "N" +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "text", +// FOO-NEXT: "spelling": " = 4> " +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "keyword", +// FOO-NEXT: "spelling": "class" +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "text", +// FOO-NEXT: "spelling": " " +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "identifier", +// FOO-NEXT: "spelling": "Foo" +// FOO-NEXT: }, +// FOO-NEXT: { +// FOO-NEXT: "kind": "text", +// FOO-NEXT: "spelling": ";" +// FOO-NEXT: } +// FOO-NEXT: ] + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix FOO-SPEC +template <typename T> class Foo <T, 4> { }; +// FOO-SPEC-LABEL: "!testLabel": "c:@SP>1#T@Foo>#t0.0#VI4" +// FOO-SPEC: "declarationFragments": [ +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "keyword", +// FOO-SPEC-NEXT: "spelling": "template" +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "text", +// FOO-SPEC-NEXT: "spelling": " <" +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "keyword", +// FOO-SPEC-NEXT: "spelling": "typename" +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "text", +// FOO-SPEC-NEXT: "spelling": " " +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "genericParameter", +// FOO-SPEC-NEXT: "spelling": "T" +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "text", +// FOO-SPEC-NEXT: "spelling": "> " +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "keyword", +// FOO-SPEC-NEXT: "spelling": "class" +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "text", +// FOO-SPEC-NEXT: "spelling": " " +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "identifier", +// FOO-SPEC-NEXT: "spelling": "Foo" +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "text", +// FOO-SPEC-NEXT: "spelling": "<" +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "typeIdentifier", +// FOO-SPEC-NEXT: "preciseIdentifier": "c:t0.0", +// FOO-SPEC-NEXT: "spelling": "T" +// FOO-SPEC-NEXT: }, +// FOO-SPEC-NEXT: { +// FOO-SPEC-NEXT: "kind": "text", +// FOO-SPEC-NEXT: "spelling": ", 4>;" +// FOO-SPEC-NEXT: } +// FOO-SPEC-NEXT: ] + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix NEST +template <template <template <typename> typename> class... Bs> class NestedTemplateTemplateParamPack{ }; +// NEST-LABEL: "!testLabel": "c:@ST>1#pt>1#t>1#T@NestedTemplateTemplateParamPack" +// NEST: "declarationFragments": [ +// NEST-NEXT: { +// NEST-NEXT: "kind": "keyword", +// NEST-NEXT: "spelling": "template" +// NEST-NEXT: }, +// NEST-NEXT: { +// NEST-NEXT: "kind": "text", +// NEST-NEXT: "spelling": " <" +// NEST-NEXT: }, +// NEST-NEXT: { +// NEST-NEXT: "kind": "keyword", +// NEST-NEXT: "spelling": "template" +// NEST-NEXT: }, +// NEST-NEXT: { +// NEST-NEXT: "kind": "text", +// NEST-NEXT: "spelling": " <" +// NEST-NEXT: }, +// NEST-NEXT: { +// NEST-NEXT: "kind": "keyword", +// NEST-NEXT: "spelling": "template" +// NEST-NEXT: }, +// NEST-NEXT: { +// NEST-NEXT: "kind": "text", +// NEST-NEXT: "spelling": " <" +// NEST-NEXT: }, +// NEST-NEXT: { +// NEST-NEXT: "kind": "keyword", +// NEST-NEXT: "spelling": "typename" +// NEST-NEXT: }, +// NEST-NEXT: { +// NEST-NEXT: "kind": "text", +// NEST-NEXT: "spelling": "> " +// NEST-NEXT: }, +// NEST-NEXT: { +// NEST-NEXT: "kind": "keyword", +// NEST-NEXT: "spelling": "typename" +// NEST-NEXT: }, +// NEST-NEXT: { +// NEST-NEXT: "kind": "text", +// NEST-NEXT: "spelling": "> " +// NEST-NEXT: }, +// NEST-NEXT: { +// NEST-NEXT: "kind": "keyword", +// NEST-NEXT: "spelling": "class" +// NEST-NEXT: }, +// NEST-NEXT: { +// NEST-NEXT: "kind": "text", +// NEST-NEXT: "spelling": "... " +// NEST-NEXT: }, +// NEST-NEXT: { +// NEST-NEXT: "kind": "genericParameter", +// NEST-NEXT: "spelling": "Bs" +// NEST-NEXT: }, +// NEST-NEXT: { +// NEST-NEXT: "kind": "text", +// NEST-NEXT: "spelling": "> " +// NEST-NEXT: }, +// NEST-NEXT: { +// NEST-NEXT: "kind": "keyword", +// NEST-NEXT: "spelling": "class" +// NEST-NEXT: }, +// NEST-NEXT: { +// NEST-NEXT: "kind": "text", +// NEST-NEXT: "spelling": " " +// NEST-NEXT: }, +// NEST-NEXT: { +// NEST-NEXT: "kind": "identifier", +// NEST-NEXT: "spelling": "NestedTemplateTemplateParamPack" +// NEST-NEXT: }, +// NEST-NEXT: { +// NEST-NEXT: "kind": "text", +// NEST-NEXT: "spelling": ";" +// NEST-NEXT: } +// NEST-NEXT: ] + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix BAR +template <template <typename> typename T = Foo> struct Bar { }; +// BAR-LABEL: "!testLabel": "c:@ST>1#t>1#T@Bar" +// BAR: "declarationFragments": [ +// BAR-NEXT: { +// BAR-NEXT: "kind": "keyword", +// BAR-NEXT: "spelling": "template" +// BAR-NEXT: }, +// BAR-NEXT: { +// BAR-NEXT: "kind": "text", +// BAR-NEXT: "spelling": " <" +// BAR-NEXT: }, +// BAR-NEXT: { +// BAR-NEXT: "kind": "keyword", +// BAR-NEXT: "spelling": "template" +// BAR-NEXT: }, +// BAR-NEXT: { +// BAR-NEXT: "kind": "text", +// BAR-NEXT: "spelling": " <" +// BAR-NEXT: }, +// BAR-NEXT: { +// BAR-NEXT: "kind": "keyword", +// BAR-NEXT: "spelling": "typename" +// BAR-NEXT: }, +// BAR-NEXT: { +// BAR-NEXT: "kind": "text", +// BAR-NEXT: "spelling": "> " +// BAR-NEXT: }, +// BAR-NEXT: { +// BAR-NEXT: "kind": "keyword", +// BAR-NEXT: "spelling": "typename" +// BAR-NEXT: }, +// BAR-NEXT: { +// BAR-NEXT: "kind": "text", +// BAR-NEXT: "spelling": " " +// BAR-NEXT: }, +// BAR-NEXT: { +// BAR-NEXT: "kind": "genericParameter", +// BAR-NEXT: "spelling": "T" +// BAR-NEXT: }, +// BAR-NEXT: { +// BAR-NEXT: "kind": "text", +// BAR-NEXT: "spelling": " = " +// BAR-NEXT: }, +// BAR-NEXT: { +// BAR-NEXT: "kind": "typeIdentifier", +// BAR-NEXT: "preciseIdentifier": "c:@ST>2#T#NI@Foo", +// BAR-NEXT: "spelling": "Foo" +// BAR-NEXT: }, +// BAR-NEXT: { +// BAR-NEXT: "kind": "text", +// BAR-NEXT: "spelling": "> " +// BAR-NEXT: }, +// BAR-NEXT: { +// BAR-NEXT: "kind": "keyword", +// BAR-NEXT: "spelling": "struct" +// BAR-NEXT: }, +// BAR-NEXT: { +// BAR-NEXT: "kind": "text", +// BAR-NEXT: "spelling": " " +// BAR-NEXT: }, +// BAR-NEXT: { +// BAR-NEXT: "kind": "identifier", +// BAR-NEXT: "spelling": "Bar" +// BAR-NEXT: }, +// BAR-NEXT: { +// BAR-NEXT: "kind": "text", +// BAR-NEXT: "spelling": ";" +// BAR-NEXT: } +// BAR-NEXT: ] + +// RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix VAR +NestedTemplateTemplateParamPack<Bar, Bar> var; +// VAR-LABEL: "!testLabel": "c:@var" +// VAR: "declarationFragments": [ +// VAR-NEXT: { +// VAR-NEXT: "kind": "typeIdentifier", +// VAR-NEXT: "preciseIdentifier": "c:@ST>1#pt>1#t>1#T@NestedTemplateTemplateParamPack", +// VAR-NEXT: "spelling": "NestedTemplateTemplateParamPack" +// VAR-NEXT: }, +// VAR-NEXT: { +// VAR-NEXT: "kind": "text", +// VAR-NEXT: "spelling": "<" +// VAR-NEXT: }, +// VAR-NEXT: { +// VAR-NEXT: "kind": "typeIdentifier", +// VAR-NEXT: "preciseIdentifier": "c:@ST>1#t>1#T@Bar", +// VAR-NEXT: "spelling": "Bar" +// VAR-NEXT: }, +// VAR-NEXT: { +// VAR-NEXT: "kind": "text", +// VAR-NEXT: "spelling": ", " +// VAR-NEXT: }, +// VAR-NEXT: { +// VAR-NEXT: "kind": "typeIdentifier", +// VAR-NEXT: "preciseIdentifier": "c:@ST>1#t>1#T@Bar", +// VAR-NEXT: "spelling": "Bar" +// VAR-NEXT: }, +// VAR-NEXT: { +// VAR-NEXT: "kind": "text", +// VAR-NEXT: "spelling": "> " +// VAR-NEXT: }, +// VAR-NEXT: { +// VAR-NEXT: "kind": "identifier", +// VAR-NEXT: "spelling": "var" +// VAR-NEXT: }, +// VAR-NEXT: { +// VAR-NEXT: "kind": "text", +// VAR-NEXT: "spelling": ";" +// VAR-NEXT: } +// VAR-NEXT: ] + +// expected-no-diagnostics _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits