https://github.com/ojhunt created 
https://github.com/llvm/llvm-project/pull/213166

This assertion was due to template instantiation not recording the 
instantiation as incomplete when parameter deduction fails.

>From 469b688f32dac03a81d51e3195375db37be28177 Mon Sep 17 00:00:00 2001
From: Oliver Hunt <[email protected]>
Date: Thu, 30 Jul 2026 13:39:26 -0700
Subject: [PATCH] [clang] Assertion failure on template parameter deduction
 failure

This assertion was due to template instantiation not recording the
instantiation as incomplete when parameter deduction fails.
---
 clang/lib/Sema/SemaTemplateInstantiate.cpp    | 24 +++++++++++++
 ...tion-after-parameter-deduction-failure.cpp | 35 +++++++++++++++++++
 2 files changed, 59 insertions(+)
 create mode 100644 
clang/test/SemaTemplate/instantiation-after-parameter-deduction-failure.cpp

diff --git a/clang/lib/Sema/SemaTemplateInstantiate.cpp 
b/clang/lib/Sema/SemaTemplateInstantiate.cpp
index 2cf2a4f85f830..b3d48218f5efe 100644
--- a/clang/lib/Sema/SemaTemplateInstantiate.cpp
+++ b/clang/lib/Sema/SemaTemplateInstantiate.cpp
@@ -1992,6 +1992,30 @@ Decl *TemplateInstantiator::TransformDecl(SourceLocation 
Loc, Decl *D) {
         *SemaRef.CurrentInstantiationScope->findInstantiationOf(D));
   }
 
+  // ***REVIEWER***: Essentially cloned from the above TemplateTemplateParmDecl
+  // logic. This seems like the actual root cause fix, but prior "correct 
seeming"
+  // changes i've made against template code was gratuitously wrong.
+  // Biggest question: is it correct to use !getInstantiationOfIfExists as the
+  // test for failure?
+  // Errrr, ***REVIEWER*** again: I thought this was specific to errors, but I
+  // managed to come up with a couple of valid code tests that trip this
+  // assertion.
+  if (BailOutOnIncomplete && isa<ParmVarDecl>(D) &&
+      SemaRef.CurrentInstantiationScope &&
+      !SemaRef.CurrentInstantiationScope->getInstantiationOfIfExists(D)) {
+    assert(!SemaRef.CodeSynthesisContexts.empty() &&
+           SemaRef.CodeSynthesisContexts.back().Kind ==
+               Sema::CodeSynthesisContext::DeducedTemplateArgumentSubstitution 
&&
+           "***REVIEWER***: it seemed like this is only mean to happen during "
+           "substitution, but i based that on adding a __builtin_trap() and "
+           "then looking at a few of the resulting crashing tests and they "
+           "were all in this mode. Is that expected/correct? the assertion "
+           "doesn't fire on any of the template tests"
+           "");
+    IsIncomplete = true;
+    return nullptr;
+  }
+
   return SemaRef.FindInstantiatedDecl(Loc, cast<NamedDecl>(D), TemplateArgs);
 }
 
diff --git 
a/clang/test/SemaTemplate/instantiation-after-parameter-deduction-failure.cpp 
b/clang/test/SemaTemplate/instantiation-after-parameter-deduction-failure.cpp
new file mode 100644
index 0000000000000..c5839f7ff3c6d
--- /dev/null
+++ 
b/clang/test/SemaTemplate/instantiation-after-parameter-deduction-failure.cpp
@@ -0,0 +1,35 @@
+// RUN: %clang_cc1 -std=c++23 -fsyntax-only -verify %s
+
+namespace ambiguous_overload {
+template <class> struct S {
+  template <class T> S(T);
+};
+struct S1 {};
+struct S2 {
+  operator S1();
+};
+
+template <typename T> auto foo(T, S<decltype(0)>); // #declaration
+template <typename T> auto foo(T arg, decltype(arg)) {
+  foo(arg, S2{});
+  // expected-error@-1 {{function 'foo<ambiguous_overload::S1>' with deduced 
return type cannot be used before it is defined}}
+  // expected-note@#declaration {{'foo<ambiguous_overload::S1>' declared here}}
+  // expected-note@#instantiation {{in instantiation of function template 
specialization 'ambiguous_overload::foo<ambiguous_overload::S1>' requested 
here}}
+}
+
+void bar(S1 d) {
+  foo(d, S1{}); // #instantiation
+}
+}
+
+namespace explicit_specialization {
+  template <typename T> void foo(T, int);
+  template <typename T> void foo(T arg, decltype(arg));
+  template <> void foo(int, int) {}
+}
+
+namespace address_of {
+  template <typename T> void foo(T, int);
+  template <typename T> void foo(T arg, decltype(arg));
+  void (*p)(int, int) = foo;
+}

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to