From 5b0434419349b218eb765766c56cf21ead493a42 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 28 Jan 2026 11:06:32 -0500 Subject: [PATCH 1/2] [Clang] Fix parsing of pack-index-specifier with template-id pattern --- clang/lib/Parse/ParseDeclCXX.cpp | 47 +++++++++++++++++++++++++------- clang/lib/Parse/ParseExprCXX.cpp | 31 +++++++++++++++++++++ 2 files changed, 68 insertions(+), 10 deletions(-) diff --git a/clang/lib/Parse/ParseDeclCXX.cpp b/clang/lib/Parse/ParseDeclCXX.cpp index da7b07ee26d3f..ec5b4204230cf 100644 --- a/clang/lib/Parse/ParseDeclCXX.cpp +++ b/clang/lib/Parse/ParseDeclCXX.cpp @@ -1147,8 +1147,9 @@ void Parser::AnnotateExistingDecltypeSpecifier(const DeclSpec &DS, } SourceLocation Parser::ParsePackIndexingType(DeclSpec &DS) { - assert(Tok.isOneOf(tok::annot_pack_indexing_type, tok::identifier) && - "Expected an identifier"); + assert(Tok.isOneOf(tok::annot_pack_indexing_type, tok::identifier, + tok::annot_template_id) && + "Expected an identifier or template-id"); TypeResult Type; SourceLocation StartLoc; @@ -1180,15 +1181,41 @@ SourceLocation Parser::ParsePackIndexingType(DeclSpec &DS) { return Tok.getEndLoc(); } - ParsedType Ty = Actions.getTypeName(*Tok.getIdentifierInfo(), - Tok.getLocation(), getCurScope()); - if (!Ty) { - DS.SetTypeSpecError(); - return Tok.getEndLoc(); - } - Type = Ty; + if (Tok.is(tok::annot_template_id)) { + TemplateIdAnnotation *TemplateId = takeTemplateIdAnnotation(Tok); + StartLoc = TemplateId->TemplateNameLoc; - StartLoc = ConsumeToken(); + ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(), + TemplateId->NumArgs); + CXXScopeSpec SS; + TypeResult Ty = + TemplateId->isInvalid() + ? TypeError() + : Actions.ActOnTemplateIdType( + getCurScope(), ElaboratedTypeKeyword::None, + /*ElaboratedKeywordLoc=*/SourceLocation(), SS, + TemplateId->TemplateKWLoc, TemplateId->Template, + TemplateId->Name, TemplateId->TemplateNameLoc, + TemplateId->LAngleLoc, TemplateArgsPtr, TemplateId->RAngleLoc, + /*IsCtorOrDtorName=*/false, /*IsClassName=*/false, + ImplicitTypenameContext::No); + + if (Ty.isInvalid()) { + DS.SetTypeSpecError(); + return TemplateId->RAngleLoc; + } + Type = Ty; + ConsumeAnnotationToken(); + } else { + ParsedType Ty = Actions.getTypeName(*Tok.getIdentifierInfo(), + Tok.getLocation(), getCurScope()); + if (!Ty) { + DS.SetTypeSpecError(); + return Tok.getEndLoc(); + } + Type = Ty; + StartLoc = ConsumeToken(); + } EllipsisLoc = ConsumeToken(); BalancedDelimiterTracker T(*this, tok::l_square); T.consumeOpen(); diff --git a/clang/lib/Parse/ParseExprCXX.cpp b/clang/lib/Parse/ParseExprCXX.cpp index 842b52375eb14..618cc05a6e8d9 100644 --- a/clang/lib/Parse/ParseExprCXX.cpp +++ b/clang/lib/Parse/ParseExprCXX.cpp @@ -324,6 +324,37 @@ bool Parser::ParseOptionalCXXScopeSpecifier( continue; } + // Handle template-id pack-index-specifier + if (Tok.is(tok::annot_template_id) && NextToken().is(tok::ellipsis) && + GetLookAheadToken(2).is(tok::l_square) && + !GetLookAheadToken(3).is(tok::r_square)) { + SourceLocation Start = Tok.getLocation(); + DeclSpec DS(AttrFactory); + SourceLocation CCLoc; + SourceLocation EndLoc = ParsePackIndexingType(DS); + if (DS.getTypeSpecType() == DeclSpec::TST_error) + return false; + + QualType Pattern = Sema::GetTypeFromParser(DS.getRepAsType()); + QualType Type = + Actions.ActOnPackIndexingType(Pattern, DS.getPackIndexingExpr(), + DS.getBeginLoc(), DS.getEllipsisLoc()); + + if (Type.isNull()) + return false; + + if (!TryConsumeToken(tok::coloncolon, CCLoc)) { + AnnotateExistingIndexedTypeNamePack(ParsedType::make(Type), Start, + EndLoc); + return false; + } + if (Actions.ActOnCXXNestedNameSpecifierIndexedPack(SS, DS, CCLoc, + std::move(Type))) + SS.SetInvalid(SourceRange(Start, CCLoc)); + HasScopeSpecifier = true; + continue; + } + if (Tok.is(tok::annot_template_id) && NextToken().is(tok::coloncolon)) { // We have // From c5443af8b0c02dddc95fdba4dd7583bee15eb343 Mon Sep 17 00:00:00 2001 From: Krystian Stasiowski Date: Wed, 28 Jan 2026 13:04:14 -0500 Subject: [PATCH 2/2] [FOLD] add tests --- clang/test/Parser/cxx2c-pack-indexing.cpp | 27 +++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/clang/test/Parser/cxx2c-pack-indexing.cpp b/clang/test/Parser/cxx2c-pack-indexing.cpp index 79069a86ea706..07d2e90f4c304 100644 --- a/clang/test/Parser/cxx2c-pack-indexing.cpp +++ b/clang/test/Parser/cxx2c-pack-indexing.cpp @@ -83,3 +83,30 @@ void foo() { } } + +namespace TemplateIdPackIndexing { + +template +struct Inner { + using type = T; + static constexpr int value = 42; +}; + +template typename... TT> +struct Test { + using type = TT...[0]::type; + static constexpr auto value = TT...[0]::value; +}; + +static_assert(Test::value == 42); + +template typename... TT> +struct Test2 { + template + using type = typename TT...[0]::template rebind; +}; + +template typename... TT, typename U> +auto test_unannotated() -> typename TT...[0]::type; + +}