From ab7e6b66fdd768f566e76972755de3578f1d0f4a Mon Sep 17 00:00:00 2001 From: Daniel Grumberg Date: Fri, 24 May 2024 16:32:25 +0100 Subject: [PATCH] [clang][ExtractAPI] Ensure TemplateArgumentLocations are only accessed if available (#93205) --- clang/lib/ExtractAPI/DeclarationFragments.cpp | 32 +++++++++----- clang/test/ExtractAPI/non_type_template.cpp | 44 +++++++++++++++++++ 2 files changed, 65 insertions(+), 11 deletions(-) diff --git a/clang/lib/ExtractAPI/DeclarationFragments.cpp b/clang/lib/ExtractAPI/DeclarationFragments.cpp index 904b9315f26e..8c7c0f8a1472 100644 --- a/clang/lib/ExtractAPI/DeclarationFragments.cpp +++ b/clang/lib/ExtractAPI/DeclarationFragments.cpp @@ -1084,12 +1084,22 @@ DeclarationFragmentsBuilder::getFragmentsForTemplateArguments( if (StringRef(ArgumentFragment.begin()->Spelling) .starts_with("type-parameter")) { - std::string ProperArgName = TemplateArgumentLocs.value()[i] - .getTypeSourceInfo() - ->getType() - .getAsString(); - ArgumentFragment.begin()->Spelling.swap(ProperArgName); + if (TemplateArgumentLocs.has_value() && + TemplateArgumentLocs->size() > i) { + std::string ProperArgName = TemplateArgumentLocs.value()[i] + .getTypeSourceInfo() + ->getType() + .getAsString(); + ArgumentFragment.begin()->Spelling.swap(ProperArgName); + } else { + auto &Spelling = ArgumentFragment.begin()->Spelling; + Spelling.clear(); + raw_string_ostream OutStream(Spelling); + CTA.print(Context.getPrintingPolicy(), OutStream, false); + OutStream.flush(); + } } + Fragments.append(std::move(ArgumentFragment)); break; } @@ -1212,9 +1222,9 @@ DeclarationFragmentsBuilder::getFragmentsForClassTemplateSpecialization( cast(Decl))) .pop_back() // there is an extra semicolon now .append("<", DeclarationFragments::FragmentKind::Text) - .append( - getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(), - Decl->getASTContext(), std::nullopt)) + .append(getFragmentsForTemplateArguments( + Decl->getTemplateArgs().asArray(), Decl->getASTContext(), + Decl->getTemplateArgsAsWritten()->arguments())) .append(">", DeclarationFragments::FragmentKind::Text) .appendSemicolon(); } @@ -1255,9 +1265,9 @@ DeclarationFragmentsBuilder::getFragmentsForVarTemplateSpecialization( .append(DeclarationFragmentsBuilder::getFragmentsForVarTemplate(Decl)) .pop_back() // there is an extra semicolon now .append("<", DeclarationFragments::FragmentKind::Text) - .append( - getFragmentsForTemplateArguments(Decl->getTemplateArgs().asArray(), - Decl->getASTContext(), std::nullopt)) + .append(getFragmentsForTemplateArguments( + Decl->getTemplateArgs().asArray(), Decl->getASTContext(), + Decl->getTemplateArgsAsWritten()->arguments())) .append(">", DeclarationFragments::FragmentKind::Text) .appendSemicolon(); } diff --git a/clang/test/ExtractAPI/non_type_template.cpp b/clang/test/ExtractAPI/non_type_template.cpp index 4e65eb790ca1..85f38e39c82b 100644 --- a/clang/test/ExtractAPI/non_type_template.cpp +++ b/clang/test/ExtractAPI/non_type_template.cpp @@ -310,4 +310,48 @@ NestedTemplateTemplateParamPack var; // VAR-NEXT: } // VAR-NEXT: ] +template +class TypeContainer { + public: + // RUN: FileCheck %s --input-file %t/output.symbols.json --check-prefix TYPE + typedef Foo Type; +// TYPE-LABEL: "!testLabel": "c:non_type_template.cpp@ST>1#T@TypeContainer@T@Type", +// TYPE: "declarationFragments": [ +// TYPE-NEXT: { +// TYPE-NEXT: "kind": "keyword", +// TYPE-NEXT: "spelling": "typedef" +// TYPE-NEXT: }, +// TYPE-NEXT: { +// TYPE-NEXT: "kind": "text", +// TYPE-NEXT: "spelling": " " +// TYPE-NEXT: }, +// TYPE-NEXT: { +// TYPE-NEXT: "kind": "typeIdentifier", +// TYPE-NEXT: "preciseIdentifier": "c:@ST>2#T#NI@Foo", +// TYPE-NEXT: "spelling": "Foo" +// TYPE-NEXT: }, +// TYPE-NEXT: { +// TYPE-NEXT: "kind": "text", +// TYPE-NEXT: "spelling": "<" +// TYPE-NEXT: }, +// TYPE-NEXT: { +// TYPE-NEXT: "kind": "typeIdentifier", +// TYPE-NEXT: "preciseIdentifier": "c:t0.0", +// TYPE-NEXT: "spelling": "T" +// TYPE-NEXT: }, +// TYPE-NEXT: { +// TYPE-NEXT: "kind": "text", +// TYPE-NEXT: "spelling": "> " +// TYPE-NEXT: }, +// TYPE-NEXT: { +// TYPE-NEXT: "kind": "identifier", +// TYPE-NEXT: "spelling": "Type" +// TYPE-NEXT: }, +// TYPE-NEXT: { +// TYPE-NEXT: "kind": "text", +// TYPE-NEXT: "spelling": ";" +// TYPE-NEXT: } +// TYPE-NEXT: ] +}; + // expected-no-diagnostics