https://github.com/cor3ntin updated 
https://github.com/llvm/llvm-project/pull/139057

>From 24e912a3ded13660ff094d488b8529d63ff0d821 Mon Sep 17 00:00:00 2001
From: Corentin Jabot <corentinja...@gmail.com>
Date: Thu, 8 May 2025 11:43:06 +0200
Subject: [PATCH] [Clang] Fix handling of pack indexing types in constraints of
 redeclaration

When checking the constraints of a potential redeclaration we inject the
template parameter as template argument to compare them.

This would make clang:
  - try to expand these injected parameters
  - inject a SubstTemplateTypeParmPackType

Why expanding the pack indexing is wasteful, it's recoverable, as it was only
partially expanded.

However, creating SubstTemplateTypeParmPackType nodes was problematic as,
before we can establish that declarations are identical, these nodes won't
canonicalize to the same types (at these point they have unrelated associated 
decl).

To avoid these issues, we track whether a set of template arguments are
injected template parameters. And if they are skip some 
substitutions/instantiation.

Cleanup pack indexing profiling as a drive-by.

Fixes #138255
---
 clang/docs/ReleaseNotes.rst                   |  1 +
 clang/include/clang/AST/ASTContext.h          |  3 +-
 clang/include/clang/AST/Type.h                | 13 +---
 clang/include/clang/Sema/Template.h           | 52 ++++++++++++----
 clang/lib/AST/ASTContext.cpp                  | 43 ++++++-------
 clang/lib/AST/Type.cpp                        | 16 +++--
 clang/lib/Sema/SemaTemplateInstantiate.cpp    | 47 ++++++++++-----
 clang/lib/Sema/SemaTemplateVariadic.cpp       |  7 +++
 clang/lib/Sema/TreeTransform.h                |  2 +-
 .../SemaTemplate/concepts-out-of-line-def.cpp | 60 ++++++++++++++++++-
 10 files changed, 175 insertions(+), 69 deletions(-)

diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index c52e285bde627..938d9578bae61 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -667,6 +667,7 @@ Bug Fixes to C++ Support
   whose type depends on itself. (#GH51347), (#GH55872)
 - Improved parser recovery of invalid requirement expressions. In turn, this
   fixes crashes from follow-on processing of the invalid requirement. 
(#GH138820)
+- Fixed the handling of pack indexing types in the constraints of a member 
function redeclaration. (#GH138255)
 
 Bug Fixes to AST Handling
 ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/AST/ASTContext.h 
b/clang/include/clang/AST/ASTContext.h
index e107db458742e..1fdc488a76507 100644
--- a/clang/include/clang/AST/ASTContext.h
+++ b/clang/include/clang/AST/ASTContext.h
@@ -221,7 +221,8 @@ class ASTContext : public RefCountedBase<ASTContext> {
   mutable llvm::ContextualFoldingSet<DependentDecltypeType, ASTContext &>
       DependentDecltypeTypes;
 
-  mutable llvm::FoldingSet<PackIndexingType> DependentPackIndexingTypes;
+  mutable llvm::ContextualFoldingSet<PackIndexingType, ASTContext &>
+      DependentPackIndexingTypes;
 
   mutable llvm::FoldingSet<TemplateTypeParmType> TemplateTypeParmTypes;
   mutable llvm::FoldingSet<ObjCTypeParamType> ObjCTypeParamTypes;
diff --git a/clang/include/clang/AST/Type.h b/clang/include/clang/AST/Type.h
index 773796a55eaa1..ba723e7e5b5b1 100644
--- a/clang/include/clang/AST/Type.h
+++ b/clang/include/clang/AST/Type.h
@@ -5976,7 +5976,6 @@ class PackIndexingType final
       private llvm::TrailingObjects<PackIndexingType, QualType> {
   friend TrailingObjects;
 
-  const ASTContext &Context;
   QualType Pattern;
   Expr *IndexExpr;
 
@@ -5987,9 +5986,8 @@ class PackIndexingType final
 
 protected:
   friend class ASTContext; // ASTContext creates these.
-  PackIndexingType(const ASTContext &Context, QualType Canonical,
-                   QualType Pattern, Expr *IndexExpr, bool FullySubstituted,
-                   ArrayRef<QualType> Expansions = {});
+  PackIndexingType(QualType Canonical, QualType Pattern, Expr *IndexExpr,
+                   bool FullySubstituted, ArrayRef<QualType> Expansions = {});
 
 public:
   Expr *getIndexExpr() const { return IndexExpr; }
@@ -6024,12 +6022,7 @@ class PackIndexingType final
     return T->getTypeClass() == PackIndexing;
   }
 
-  void Profile(llvm::FoldingSetNodeID &ID) {
-    if (hasSelectedType())
-      getSelectedType().Profile(ID);
-    else
-      Profile(ID, Context, getPattern(), getIndexExpr(), isFullySubstituted());
-  }
+  void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context);
   static void Profile(llvm::FoldingSetNodeID &ID, const ASTContext &Context,
                       QualType Pattern, Expr *E, bool FullySubstituted);
 
diff --git a/clang/include/clang/Sema/Template.h 
b/clang/include/clang/Sema/Template.h
index f9a10cfafb1f7..4fb3b5df6eed0 100644
--- a/clang/include/clang/Sema/Template.h
+++ b/clang/include/clang/Sema/Template.h
@@ -24,6 +24,7 @@
 #include "llvm/ADT/SmallVector.h"
 #include <cassert>
 #include <optional>
+#include <tuple>
 #include <utility>
 
 namespace clang {
@@ -76,9 +77,17 @@ enum class TemplateSubstitutionKind : char {
   class MultiLevelTemplateArgumentList {
     /// The template argument list at a certain template depth
 
+    enum ListProperties {
+      /// A 'Final' substitution.
+      IsFinal = 0x1,
+      /// Track if the arguments are injected template parameters.
+      /// Injected template parameters should not be expanded.
+      ArgumentsAreInjectedTemplateParams = 0x02,
+    };
+
     using ArgList = ArrayRef<TemplateArgument>;
     struct ArgumentListLevel {
-      llvm::PointerIntPair<Decl *, 1, bool> AssociatedDeclAndFinal;
+      llvm::PointerIntPair<Decl *, 3, unsigned> AssociatedDeclAndProperties;
       ArgList Args;
     };
     using ContainerType = SmallVector<ArgumentListLevel, 4>;
@@ -161,11 +170,19 @@ enum class TemplateSubstitutionKind : char {
     /// A template-like entity which owns the whole pattern being substituted.
     /// This will usually own a set of template parameters, or in some
     /// cases might even be a template parameter itself.
-    std::pair<Decl *, bool> getAssociatedDecl(unsigned Depth) const {
+    std::tuple<Decl *, bool, bool> getAssociatedDecl(unsigned Depth) const {
+      assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
+      auto AD = TemplateArgumentLists[getNumLevels() - Depth - 1]
+                    .AssociatedDeclAndProperties;
+      return {AD.getPointer(), AD.getInt() & IsFinal,
+              AD.getInt() & ArgumentsAreInjectedTemplateParams};
+    }
+
+    bool ArgumentsAreInjectedParameters(unsigned Depth) const {
       assert(NumRetainedOuterLevels <= Depth && Depth < getNumLevels());
       auto AD = TemplateArgumentLists[getNumLevels() - Depth - 1]
-                    .AssociatedDeclAndFinal;
-      return {AD.getPointer(), AD.getInt()};
+                    .AssociatedDeclAndProperties;
+      return AD.getInt() & ArgumentsAreInjectedTemplateParams;
     }
 
     /// Determine whether there is a non-NULL template argument at the
@@ -205,16 +222,15 @@ enum class TemplateSubstitutionKind : char {
 
     /// Add a new outmost level to the multi-level template argument
     /// list.
-    /// A 'Final' substitution means that Subst* nodes won't be built
-    /// for the replacements.
-    void addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args,
-                                   bool Final) {
+    void
+    addOuterTemplateArguments(Decl *AssociatedDecl, ArgList Args, bool Final,
+                              bool ArgumentsAreInjectedTemplateParams = false) 
{
       assert(!NumRetainedOuterLevels &&
              "substituted args outside retained args?");
       assert(getKind() == TemplateSubstitutionKind::Specialization);
       TemplateArgumentLists.push_back(
           {{AssociatedDecl ? AssociatedDecl->getCanonicalDecl() : nullptr,
-            Final},
+            getProperties(Final, ArgumentsAreInjectedTemplateParams)},
            Args});
     }
 
@@ -239,15 +255,17 @@ enum class TemplateSubstitutionKind : char {
              "Replacing in an empty list?");
 
       if (!TemplateArgumentLists.empty()) {
-        assert((TemplateArgumentLists[0].AssociatedDeclAndFinal.getPointer() ||
-                TemplateArgumentLists[0].AssociatedDeclAndFinal.getPointer() ==
+        assert((TemplateArgumentLists[0]
+                    .AssociatedDeclAndProperties.getPointer() ||
+                TemplateArgumentLists[0]
+                        .AssociatedDeclAndProperties.getPointer() ==
                     AssociatedDecl) &&
                "Trying to change incorrect declaration?");
         TemplateArgumentLists[0].Args = Args;
       } else {
         --NumRetainedOuterLevels;
         TemplateArgumentLists.push_back(
-            {{AssociatedDecl, /*Final=*/false}, Args});
+            {{AssociatedDecl, /*Properties=*/0}, Args});
       }
     }
 
@@ -292,6 +310,16 @@ enum class TemplateSubstitutionKind : char {
         llvm::errs() << "\n";
       }
     }
+
+    static unsigned getProperties(bool IsFinal, bool IsInjected) {
+      unsigned Props = 0;
+      if (IsFinal)
+        Props |= MultiLevelTemplateArgumentList::IsFinal;
+      if (IsInjected)
+        Props |=
+            MultiLevelTemplateArgumentList::ArgumentsAreInjectedTemplateParams;
+      return Props;
+    }
   };
 
   /// The context in which partial ordering of function templates occurs.
diff --git a/clang/lib/AST/ASTContext.cpp b/clang/lib/AST/ASTContext.cpp
index 1ed16748dff1a..6ebef70b2d44a 100644
--- a/clang/lib/AST/ASTContext.cpp
+++ b/clang/lib/AST/ASTContext.cpp
@@ -940,7 +940,7 @@ ASTContext::ASTContext(LangOptions &LOpts, SourceManager 
&SM,
       DependentSizedMatrixTypes(this_()),
       FunctionProtoTypes(this_(), FunctionProtoTypesLog2InitSize),
       DependentTypeOfExprTypes(this_()), DependentDecltypeTypes(this_()),
-      TemplateSpecializationTypes(this_()),
+      DependentPackIndexingTypes(this_()), 
TemplateSpecializationTypes(this_()),
       DependentTemplateSpecializationTypes(this_()),
       DependentBitIntTypes(this_()), SubstTemplateTemplateParmPacks(this_()),
       DeducedTemplates(this_()), ArrayParameterTypes(this_()),
@@ -6433,34 +6433,29 @@ QualType ASTContext::getPackIndexingType(QualType 
Pattern, Expr *IndexExpr,
                                          ArrayRef<QualType> Expansions,
                                          UnsignedOrNone Index) const {
   QualType Canonical;
-  if (FullySubstituted && Index) {
+  if (FullySubstituted && Index)
     Canonical = getCanonicalType(Expansions[*Index]);
-  } else {
-    llvm::FoldingSetNodeID ID;
-    PackIndexingType::Profile(ID, *this, Pattern.getCanonicalType(), IndexExpr,
-                              FullySubstituted);
-    void *InsertPos = nullptr;
-    PackIndexingType *Canon =
-        DependentPackIndexingTypes.FindNodeOrInsertPos(ID, InsertPos);
-    if (!Canon) {
-      void *Mem = Allocate(
-          PackIndexingType::totalSizeToAlloc<QualType>(Expansions.size()),
-          TypeAlignment);
-      Canon = new (Mem)
-          PackIndexingType(*this, QualType(), Pattern.getCanonicalType(),
-                           IndexExpr, FullySubstituted, Expansions);
-      DependentPackIndexingTypes.InsertNode(Canon, InsertPos);
-    }
-    Canonical = QualType(Canon, 0);
-  }
+  else if (!Pattern.isCanonical())
+    Canonical = getPackIndexingType(Pattern.getCanonicalType(), IndexExpr,
+                                    FullySubstituted, Expansions, Index);
+
+  llvm::FoldingSetNodeID ID;
+  PackIndexingType::Profile(ID, *this, Pattern, IndexExpr, FullySubstituted);
+  void *InsertPos = nullptr;
+  PackIndexingType *Canon =
+      DependentPackIndexingTypes.FindNodeOrInsertPos(ID, InsertPos);
+  if (Canon)
+    return QualType(Canon, 0);
 
   void *Mem =
       Allocate(PackIndexingType::totalSizeToAlloc<QualType>(Expansions.size()),
                TypeAlignment);
-  auto *T = new (Mem) PackIndexingType(*this, Canonical, Pattern, IndexExpr,
-                                       FullySubstituted, Expansions);
-  Types.push_back(T);
-  return QualType(T, 0);
+
+  Canon = new (Mem) PackIndexingType(Canonical, Pattern, IndexExpr,
+                                     FullySubstituted, Expansions);
+  DependentPackIndexingTypes.InsertNode(Canon, InsertPos);
+  Types.push_back(Canon);
+  return QualType(Canon, 0);
 }
 
 /// getUnaryTransformationType - We don't unique these, since the memory
diff --git a/clang/lib/AST/Type.cpp b/clang/lib/AST/Type.cpp
index 31e4bcd7535ea..bb4fe24cf94d1 100644
--- a/clang/lib/AST/Type.cpp
+++ b/clang/lib/AST/Type.cpp
@@ -4126,14 +4126,14 @@ void 
DependentDecltypeType::Profile(llvm::FoldingSetNodeID &ID,
   E->Profile(ID, Context, true);
 }
 
-PackIndexingType::PackIndexingType(const ASTContext &Context,
-                                   QualType Canonical, QualType Pattern,
+PackIndexingType::PackIndexingType(QualType Canonical, QualType Pattern,
                                    Expr *IndexExpr, bool FullySubstituted,
                                    ArrayRef<QualType> Expansions)
     : Type(PackIndexing, Canonical,
            computeDependence(Pattern, IndexExpr, Expansions)),
-      Context(Context), Pattern(Pattern), IndexExpr(IndexExpr),
-      Size(Expansions.size()), FullySubstituted(FullySubstituted) {
+      Pattern(Pattern), IndexExpr(IndexExpr), Size(Expansions.size()),
+      FullySubstituted(FullySubstituted) {
+
   llvm::uninitialized_copy(Expansions, getTrailingObjects<QualType>());
 }
 
@@ -4174,6 +4174,14 @@ PackIndexingType::computeDependence(QualType Pattern, 
Expr *IndexExpr,
   return TD;
 }
 
+void PackIndexingType::Profile(llvm::FoldingSetNodeID &ID,
+                               const ASTContext &Context) {
+  if (hasSelectedType() && isFullySubstituted())
+    getSelectedType().Profile(ID);
+  else
+    Profile(ID, Context, getPattern(), getIndexExpr(), isFullySubstituted());
+}
+
 void PackIndexingType::Profile(llvm::FoldingSetNodeID &ID,
                                const ASTContext &Context, QualType Pattern,
                                Expr *E, bool FullySubstituted) {
diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp 
b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index fb490bcac6e91..da7ebf8e30873 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -338,7 +338,7 @@ Response HandleFunctionTemplateDecl(Sema &SemaRef,
         const_cast<FunctionTemplateDecl *>(FTD),
         const_cast<FunctionTemplateDecl *>(FTD)->getInjectedTemplateArgs(
             SemaRef.Context),
-        /*Final=*/false);
+        /*Final=*/false, /*InjectedTemplateParams=*/true);
 
     NestedNameSpecifier *NNS = FTD->getTemplatedDecl()->getQualifier();
 
@@ -363,18 +363,20 @@ Response HandleFunctionTemplateDecl(Sema &SemaRef,
           // This meets the contract in
           // TreeTransform::TryExpandParameterPacks that the template arguments
           // for unexpanded parameters should be of a Pack kind.
+          bool Injected = false;
           if (TSTy->isCurrentInstantiation()) {
             auto *RD = TSTy->getCanonicalTypeInternal()->getAsCXXRecordDecl();
-            if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate())
+            if (ClassTemplateDecl *CTD = RD->getDescribedClassTemplate()) {
               Arguments = CTD->getInjectedTemplateArgs(SemaRef.Context);
-            else if (auto *Specialization =
-                         dyn_cast<ClassTemplateSpecializationDecl>(RD))
+              Injected = true;
+            } else if (auto *Specialization =
+                           dyn_cast<ClassTemplateSpecializationDecl>(RD))
               Arguments =
                   Specialization->getTemplateInstantiationArgs().asArray();
           }
           Result.addOuterTemplateArguments(
               TSTy->getTemplateName().getAsTemplateDecl(), Arguments,
-              /*Final=*/false);
+              /*Final=*/false, /*InjectedTemplateParams=*/Injected);
         }
       }
 
@@ -399,7 +401,7 @@ Response HandleRecordDecl(Sema &SemaRef, const 
CXXRecordDecl *Rec,
       Result.addOuterTemplateArguments(
           const_cast<CXXRecordDecl *>(Rec),
           ClassTemplate->getInjectedTemplateArgs(SemaRef.Context),
-          /*Final=*/false);
+          /*Final=*/false, /*InjectedTemplateParams=*/true);
   }
 
   if (const MemberSpecializationInfo *MSInfo =
@@ -1476,8 +1478,8 @@ namespace {
       }
     }
 
-    TemplateArgument
-    getTemplateArgumentPackPatternForRewrite(const TemplateArgument &TA) {
+    TemplateArgument getTemplateArgumentorUnsubstitutedExpansionPattern(
+        const TemplateArgument &TA) {
       if (TA.getKind() != TemplateArgument::Pack)
         return TA;
       if (SemaRef.ArgPackSubstIndex)
@@ -1902,7 +1904,9 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation 
Loc, Decl *D) {
 
       TemplateArgument Arg = TemplateArgs(TTP->getDepth(), TTP->getPosition());
 
-      if (TTP->isParameterPack()) {
+      if (TemplateArgs.ArgumentsAreInjectedParameters(TTP->getDepth())) {
+        Arg = getTemplateArgumentorUnsubstitutedExpansionPattern(Arg);
+      } else if (TTP->isParameterPack()) {
         assert(Arg.getKind() == TemplateArgument::Pack &&
                "Missing argument pack");
         Arg = getPackSubstitutedTemplateArgument(getSema(), Arg);
@@ -2054,20 +2058,23 @@ TemplateName 
TemplateInstantiator::TransformTemplateName(
       if (TemplateArgs.isRewrite()) {
         // We're rewriting the template parameter as a reference to another
         // template parameter.
-        Arg = getTemplateArgumentPackPatternForRewrite(Arg);
+        Arg = getTemplateArgumentorUnsubstitutedExpansionPattern(Arg);
         assert(Arg.getKind() == TemplateArgument::Template &&
                "unexpected nontype template argument kind in template 
rewrite");
         return Arg.getAsTemplate();
       }
 
-      auto [AssociatedDecl, Final] =
+      auto [AssociatedDecl, Final, ArgumentsAreInjectedTemplateParams] =
           TemplateArgs.getAssociatedDecl(TTP->getDepth());
       UnsignedOrNone PackIndex = std::nullopt;
       if (TTP->isParameterPack()) {
         assert(Arg.getKind() == TemplateArgument::Pack &&
                "Missing argument pack");
 
-        if (!getSema().ArgPackSubstIndex) {
+        if (ArgumentsAreInjectedTemplateParams)
+          Arg = getTemplateArgumentorUnsubstitutedExpansionPattern(Arg);
+
+        else if (!getSema().ArgPackSubstIndex) {
           // We have the template argument pack to substitute, but we're not
           // actually expanding the enclosing pack expansion yet. So, just
           // keep the entire argument pack.
@@ -2131,7 +2138,7 @@ 
TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
   if (TemplateArgs.isRewrite()) {
     // We're rewriting the template parameter as a reference to another
     // template parameter.
-    Arg = getTemplateArgumentPackPatternForRewrite(Arg);
+    Arg = getTemplateArgumentorUnsubstitutedExpansionPattern(Arg);
     assert(Arg.getKind() == TemplateArgument::Expression &&
            "unexpected nontype template argument kind in template rewrite");
     // FIXME: This can lead to the same subexpression appearing multiple times
@@ -2139,7 +2146,7 @@ 
TemplateInstantiator::TransformTemplateParmRefExpr(DeclRefExpr *E,
     return Arg.getAsExpr();
   }
 
-  auto [AssociatedDecl, Final] =
+  auto [AssociatedDecl, Final, ArgumentsAreInjectedTemplateParams] =
       TemplateArgs.getAssociatedDecl(NTTP->getDepth());
   UnsignedOrNone PackIndex = std::nullopt;
   if (NTTP->isParameterPack()) {
@@ -2584,7 +2591,7 @@ 
TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
     if (TemplateArgs.isRewrite()) {
       // We're rewriting the template parameter as a reference to another
       // template parameter.
-      Arg = getTemplateArgumentPackPatternForRewrite(Arg);
+      Arg = getTemplateArgumentorUnsubstitutedExpansionPattern(Arg);
       assert(Arg.getKind() == TemplateArgument::Type &&
              "unexpected nontype template argument kind in template rewrite");
       QualType NewT = Arg.getAsType();
@@ -2592,7 +2599,7 @@ 
TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
       return NewT;
     }
 
-    auto [AssociatedDecl, Final] =
+    auto [AssociatedDecl, Final, ArgumentsAreInjectedTemplateParams] =
         TemplateArgs.getAssociatedDecl(T->getDepth());
     UnsignedOrNone PackIndex = std::nullopt;
     if (T->isParameterPack()) {
@@ -2600,6 +2607,14 @@ 
TemplateInstantiator::TransformTemplateTypeParmType(TypeLocBuilder &TLB,
              "Missing argument pack");
 
       if (!getSema().ArgPackSubstIndex) {
+
+        if (ArgumentsAreInjectedTemplateParams) {
+          TemplateTypeParmTypeLoc NewTL =
+              TLB.push<TemplateTypeParmTypeLoc>(TL.getType());
+          NewTL.setNameLoc(TL.getNameLoc());
+          return TL.getType();
+        }
+
         // We have the template argument pack, but we're not expanding the
         // enclosing pack expansion yet. Just save the template argument
         // pack for later substitution.
diff --git a/clang/lib/Sema/SemaTemplateVariadic.cpp 
b/clang/lib/Sema/SemaTemplateVariadic.cpp
index 5f0e968ff18c4..ff2f6f94d1b54 100644
--- a/clang/lib/Sema/SemaTemplateVariadic.cpp
+++ b/clang/lib/Sema/SemaTemplateVariadic.cpp
@@ -823,6 +823,13 @@ bool Sema::CheckParameterPacksForExpansion(
         continue;
       }
 
+      // Template arguments that are injected template parameters
+      // Cannot be expanded, even if they constitute a pack expansion.
+      if (TemplateArgs.ArgumentsAreInjectedParameters(Depth)) {
+        ShouldExpand = false;
+        continue;
+      }
+
       // Determine the size of the argument pack.
       ArrayRef<TemplateArgument> Pack =
           TemplateArgs(Depth, Index).getPackAsArray();
diff --git a/clang/lib/Sema/TreeTransform.h b/clang/lib/Sema/TreeTransform.h
index 8b4b79c6ec039..317e8351f1d50 100644
--- a/clang/lib/Sema/TreeTransform.h
+++ b/clang/lib/Sema/TreeTransform.h
@@ -6884,7 +6884,7 @@ 
TreeTransform<Derived>::TransformPackIndexingType(TypeLocBuilder &TLB,
     assert(!Unexpanded.empty() && "Pack expansion without parameter packs?");
     // Determine whether the set of unexpanded parameter packs can and should
     // be expanded.
-    bool ShouldExpand = true;
+    bool ShouldExpand = false;
     bool RetainExpansion = false;
     UnsignedOrNone NumExpansions = std::nullopt;
     if (getDerived().TryExpandParameterPacks(TL.getEllipsisLoc(), 
SourceRange(),
diff --git a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp 
b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
index 5af4ec75cae90..191b40310e8be 100644
--- a/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
+++ b/clang/test/SemaTemplate/concepts-out-of-line-def.cpp
@@ -1,4 +1,6 @@
-// RUN: %clang_cc1 -std=c++20 -verify %s
+// RUN: %clang_cc1 -std=c++20 -Wno-c++26-extensions -verify %s
+// RUN: %clang_cc1 -std=c++2c -Wno-c++26-extensions -verify %s
+
 
 static constexpr int PRIMARY = 0;
 static constexpr int SPECIALIZATION_CONCEPT = 1;
@@ -779,3 +781,59 @@ template <typename T>
 consteval void S::mfn() requires (bool(&fn)) {}
 
 }
+
+
+namespace GH138255 {
+
+  template <typename... T>
+  concept C = true;
+
+  struct Func {
+      template<typename... Ts>
+      requires C<Ts...[0]>
+      static auto buggy() -> void;
+
+      template<typename... Ts>
+      requires C<Ts...[0]>
+      friend auto fr() -> void;
+
+      template<typename... Ts>
+      requires C<Ts...[0]>
+      friend auto fr2() -> void{}; // expected-note{{previous definition is 
here}}
+  };
+
+  template<typename... Ts>
+  requires C<Ts...[0]>
+  auto Func::buggy() -> void {}
+
+  template<typename... Ts>
+  requires C<Ts...[0]>
+  auto fr() -> void {}
+
+  template<typename... Ts>
+  requires C<Ts...[0]>
+  auto fr2() -> void {} // expected-error{{redefinition of 'fr2'}}
+
+
+  template <typename... Ts>
+  requires C<Ts...[0]>
+  struct Class;
+
+  template <typename... Ts>
+  requires C<Ts...[0]>
+  struct Class;
+
+
+  template <typename...>
+  struct TplClass {
+      template<typename... Ts>
+      requires C<Ts...[0]>
+      static auto buggy() -> void;
+  };
+
+  template<>
+  template<typename... Ts>
+  requires C<Ts...[0]>
+  auto TplClass<int>::buggy() -> void {}
+
+  }

_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to