[clang] 0b295bc - [clang] Treat pack-index-specifiers as non-deduced contexts (#232883)

via cfe-commits cfe-commits at lists.llvm.org
Sun Oct 18 05:02:47 PDT 2026


Author: Nikolai Fedotenko
Date: 2026-10-18T12:02:41Z
New Revision: 0b295bc9b916d1facbf95802bb2f822d3ab70aac

URL: https://github.com/llvm/llvm-project/commit/0b295bc9b916d1facbf95802bb2f822d3ab70aac
DIFF: https://github.com/llvm/llvm-project/commit/0b295bc9b916d1facbf95802bb2f822d3ab70aac.diff

LOG: [clang] Treat pack-index-specifiers as non-deduced contexts (#232883)

Per C++26 [temp.deduct.type]p5.2, a pack-index-specifier is a
non-deduced context. Deduction against an unresolved PackIndexingType
used to fail with a bare IncompletePack result that carried no
parameter/argument info, so matching an explicit instantiation, explicit
specialization, or address-of against such a function template was
rejected, and emitting the resulting diagnostic crashed in
DiagnoseBadDeduction (assertion "no parameter found for incomplete
deduction result" in +asserts builds, null dereference otherwise).

A pack-index-specifier whose pack and index are fully substituted
canonicalizes to its selected type, so the PackIndexing case in
DeduceTemplateArgumentsByTypeMatch only ever sees unresolved ones;
returning Success there (deducing nothing) is all that is needed.

Fixes #232220

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.md
    clang/lib/Sema/SemaTemplateDeduction.cpp
    clang/test/SemaCXX/cxx2c-pack-indexing.cpp

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 7d3f0eb702553d..7705b0e61bf4bf 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -1024,6 +1024,12 @@ features cannot lower the translation-unit ABI level;
 - Fixed an issue where Clang would allow invoking consteval functions outside
   of a manifestly constant evaluated context. (#GH183415, #GH169139)
 
+- A pack-index-specifier (`T...[N]`) is now treated as a non-deduced context,
+  per C++26 [temp.deduct.type]. This fixes a crash when matching an explicit
+  instantiation, explicit specialization, or call against a function template
+  whose parameter type uses pack indexing, and makes such valid matches
+  succeed instead of being rejected. (#GH232220)
+
 #### Bug Fixes to AST Handling
 
 - Fixed a non-deterministic ordering of unused local typedefs that made

diff  --git a/clang/lib/Sema/SemaTemplateDeduction.cpp b/clang/lib/Sema/SemaTemplateDeduction.cpp
index 90724e1d01cb20..b9cda516c7a486 100644
--- a/clang/lib/Sema/SemaTemplateDeduction.cpp
+++ b/clang/lib/Sema/SemaTemplateDeduction.cpp
@@ -2556,16 +2556,15 @@ static TemplateDeductionResult DeduceTemplateArgumentsByTypeMatch(
       // No template argument deduction for these types
       return TemplateDeductionResult::Success;
 
-    case Type::PackIndexing: {
-      const PackIndexingType *PIT = P->getAs<PackIndexingType>();
-      if (PIT->hasSelectedType()) {
-        return DeduceTemplateArgumentsByTypeMatch(
-            S, TemplateParams, PIT->getSelectedType(), A, Info, Deduced, TDF,
-            degradeCallPartialOrderingKind(POK),
-            /*DeducedFromArrayBound=*/false, HasDeducedAnyParam);
-      }
-      return TemplateDeductionResult::IncompletePack;
-    }
+    case Type::PackIndexing:
+      // C++26 [temp.deduct.type]p5.2:
+      //   The non-deduced contexts are:
+      //   [...]
+      //   - A pack-index-specifier or a pack-index-expression.
+      assert(!P->getAs<PackIndexingType>()->hasSelectedType() &&
+             "a pack-index-specifier with a selected type canonicalizes to "
+             "the selected type and should not dispatch here");
+      return TemplateDeductionResult::Success;
     }
 
   llvm_unreachable("Invalid Type Class!");

diff  --git a/clang/test/SemaCXX/cxx2c-pack-indexing.cpp b/clang/test/SemaCXX/cxx2c-pack-indexing.cpp
index bbd708d3b63f52..910160dbf683d9 100644
--- a/clang/test/SemaCXX/cxx2c-pack-indexing.cpp
+++ b/clang/test/SemaCXX/cxx2c-pack-indexing.cpp
@@ -378,3 +378,29 @@ int test(){
 
 }
 }
+
+namespace GH232220 {
+template <class... T> void f(T...[1]); // #GH232220-f
+template <class... T> void g(T...[1]) {}
+
+// T...[1] is a non-deduced context ([temp.deduct.type]p5.2); matching a
+// specialization against the template used to fail and then crash while
+// emitting the resulting diagnostic.
+template void g<int, short>(short);
+
+template <class... T> void h(T...[1]);
+template <> void h<int, short>(short) {}
+
+void test() {
+  f<int, short>(short{});
+  void (*p)(short) = f<int, short>;
+  g<int, long>(42L);
+
+  f(0);
+  // expected-error at -1 {{no matching function for call to 'f'}}
+  // expected-note@#GH232220-f {{candidate template ignored: substitution failure [with T = <>]: invalid index 1 for pack 'T' of size 0}}
+  f<int>(0);
+  // expected-error at -1 {{no matching function for call to 'f'}}
+  // expected-note@#GH232220-f {{candidate template ignored: substitution failure [with T = <int>]: invalid index 1 for pack 'T' of size 1}}
+}
+} // namespace GH232220


        


More information about the cfe-commits mailing list