[clang] [WIP] [Clang] Check TemplateAlias is valid before generate DeductionGuide (PR #208148)
Fan Mo via cfe-commits
cfe-commits at lists.llvm.org
Thu Jul 16 23:08:00 PDT 2026
https://github.com/w007878 updated https://github.com/llvm/llvm-project/pull/208148
>From c5bf40cb6076c5a20bad7eb7997844236b360545 Mon Sep 17 00:00:00 2001
From: Fan Mo <w007878 at hotmail.com>
Date: Sat, 13 Jun 2026 20:33:20 -0500
Subject: [PATCH 1/8] fix: use getDeclName in static assert failed boolean
condition printer
---
clang/lib/Sema/SemaTemplate.cpp | 2 +-
clang/test/SemaCXX/static-assert.cpp | 14 ++++++++++++++
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 8c94a1ad39208..41664f36dd6a3 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3647,7 +3647,7 @@ class FailedBooleanConditionPrinterHelper : public PrinterHelper {
DR->getQualifier().print(OS, Policy, true);
// Then print the decl itself.
const ValueDecl *VD = DR->getDecl();
- OS << VD->getName();
+ OS << VD->getDeclName();
if (const auto *IV = dyn_cast<VarTemplateSpecializationDecl>(VD)) {
// This is a template variable, print the expanded template arguments.
printTemplateArgumentList(
diff --git a/clang/test/SemaCXX/static-assert.cpp b/clang/test/SemaCXX/static-assert.cpp
index 354016db36432..f9c6378ecc396 100644
--- a/clang/test/SemaCXX/static-assert.cpp
+++ b/clang/test/SemaCXX/static-assert.cpp
@@ -364,3 +364,17 @@ namespace Diagnostics {
static_assert(1 << 3 != 8, ""); // expected-error {{failed}} \
// expected-note {{evaluates to '8 != 8'}}
}
+
+namespace GH203701 {
+ struct S {
+ constexpr S(auto) {}
+ constexpr operator int() const { return 0; }
+ constexpr static f() const { return 0; }
+ };
+
+ constexpr auto a = [](this S) { return 1; };
+
+ static_assert((&decltype(a)::operator())(1) == 42); // expected-error {{static assertion failed}}
+ static_assert((&S::operator int) == nullptr, ""); // expected-error {{static assertion failed}}
+ static_assert((S::f() == 1)); // expected-error {{static assertion failed}}
+}
>From 66e68710b4a2e4e220d45a54f18a891a52abe595 Mon Sep 17 00:00:00 2001
From: Fan Mo <w007878 at hotmail.com>
Date: Sat, 13 Jun 2026 21:42:16 -0500
Subject: [PATCH 2/8] fix test
---
clang/test/SemaCXX/static-assert.cpp | 6 ++----
1 file changed, 2 insertions(+), 4 deletions(-)
diff --git a/clang/test/SemaCXX/static-assert.cpp b/clang/test/SemaCXX/static-assert.cpp
index f9c6378ecc396..21a11ee7a5c45 100644
--- a/clang/test/SemaCXX/static-assert.cpp
+++ b/clang/test/SemaCXX/static-assert.cpp
@@ -369,12 +369,10 @@ namespace GH203701 {
struct S {
constexpr S(auto) {}
constexpr operator int() const { return 0; }
- constexpr static f() const { return 0; }
};
constexpr auto a = [](this S) { return 1; };
- static_assert((&decltype(a)::operator())(1) == 42); // expected-error {{static assertion failed}}
- static_assert((&S::operator int) == nullptr, ""); // expected-error {{static assertion failed}}
- static_assert((S::f() == 1)); // expected-error {{static assertion failed}}
+ static_assert((&decltype(a)::operator())(1) == 42, ""); // expected-error-re {{static assertion failed due to requirement '(&const GH203701::(lambda at {.*})::operator())(1) == 42'}}
+ static_assert((&S::operator int) == nullptr, ""); // expected-error {{static assertion failed due to requirement '(&GH203701::S::operator int) == nullptr'}}
}
>From 3088167d0348e6d13496edbac829eda93138beba Mon Sep 17 00:00:00 2001
From: Fan Mo <w007878 at hotmail.com>
Date: Sat, 13 Jun 2026 23:13:42 -0500
Subject: [PATCH 3/8] move test to c++17
---
clang/test/SemaCXX/static-assert-cxx17.cpp | 12 ++++++++++++
clang/test/SemaCXX/static-assert.cpp | 12 ------------
2 files changed, 12 insertions(+), 12 deletions(-)
diff --git a/clang/test/SemaCXX/static-assert-cxx17.cpp b/clang/test/SemaCXX/static-assert-cxx17.cpp
index 41a7b025d0eb7..e3038f8cec130 100644
--- a/clang/test/SemaCXX/static-assert-cxx17.cpp
+++ b/clang/test/SemaCXX/static-assert-cxx17.cpp
@@ -104,3 +104,15 @@ void foo6() {
}
template void foo6<ExampleTypes>();
// expected-note at -1{{in instantiation of function template specialization 'foo6<ExampleTypes>' requested here}}
+
+namespace GH203701 {
+ struct S {
+ constexpr S(auto) {}
+ constexpr operator int() const { return 0; }
+ };
+
+ constexpr auto a = [](this S) { return 1; };
+
+ static_assert((&decltype(a)::operator())(1) == 42, ""); // expected-error-re at -1 {{static assertion failed due to requirement '\(&const GH203701::\(lambda at {{.*}}\)::operator\(\)\)\(1\) == 42'}}
+ static_assert((&S::operator int) == nullptr, ""); // expected-error {{static assertion failed due to requirement '(&GH203701::S::operator int) == nullptr'}}
+}
diff --git a/clang/test/SemaCXX/static-assert.cpp b/clang/test/SemaCXX/static-assert.cpp
index 21a11ee7a5c45..354016db36432 100644
--- a/clang/test/SemaCXX/static-assert.cpp
+++ b/clang/test/SemaCXX/static-assert.cpp
@@ -364,15 +364,3 @@ namespace Diagnostics {
static_assert(1 << 3 != 8, ""); // expected-error {{failed}} \
// expected-note {{evaluates to '8 != 8'}}
}
-
-namespace GH203701 {
- struct S {
- constexpr S(auto) {}
- constexpr operator int() const { return 0; }
- };
-
- constexpr auto a = [](this S) { return 1; };
-
- static_assert((&decltype(a)::operator())(1) == 42, ""); // expected-error-re {{static assertion failed due to requirement '(&const GH203701::(lambda at {.*})::operator())(1) == 42'}}
- static_assert((&S::operator int) == nullptr, ""); // expected-error {{static assertion failed due to requirement '(&GH203701::S::operator int) == nullptr'}}
-}
>From a192beb4169f620b13e587a42fb1843a4ae0f64d Mon Sep 17 00:00:00 2001
From: Fan Mo <w007878 at hotmail.com>
Date: Sun, 14 Jun 2026 00:13:11 -0500
Subject: [PATCH 4/8] use independent test file
---
clang/test/SemaCXX/GH203701.cpp | 14 ++++++++++++++
clang/test/SemaCXX/static-assert-cxx17.cpp | 12 ------------
2 files changed, 14 insertions(+), 12 deletions(-)
create mode 100644 clang/test/SemaCXX/GH203701.cpp
diff --git a/clang/test/SemaCXX/GH203701.cpp b/clang/test/SemaCXX/GH203701.cpp
new file mode 100644
index 0000000000000..f583865de9ac4
--- /dev/null
+++ b/clang/test/SemaCXX/GH203701.cpp
@@ -0,0 +1,14 @@
+// RUN: %clang_cc1 -std=c++2b -fsyntax-only -verify %s
+
+namespace GH203701 {
+ struct S {
+ constexpr S(auto) {}
+ constexpr operator int() const { return 0; }
+ };
+
+ constexpr auto a = [](this S) { return 1; };
+
+ static_assert((&decltype(a)::operator())(1) == 42, ""); // expected-error-re {{static assertion failed due to requirement '(&const GH203701::(lambda at {{.*}})::operator())(1) == 42'{{.*}}}} \
+ // expected-note {{expression evaluates to '1 == 42'}}
+ static_assert((&S::operator int) == nullptr, ""); // expected-error {{static assertion failed due to requirement '(&GH203701::S::operator int) == nullptr'}}
+}
diff --git a/clang/test/SemaCXX/static-assert-cxx17.cpp b/clang/test/SemaCXX/static-assert-cxx17.cpp
index e3038f8cec130..41a7b025d0eb7 100644
--- a/clang/test/SemaCXX/static-assert-cxx17.cpp
+++ b/clang/test/SemaCXX/static-assert-cxx17.cpp
@@ -104,15 +104,3 @@ void foo6() {
}
template void foo6<ExampleTypes>();
// expected-note at -1{{in instantiation of function template specialization 'foo6<ExampleTypes>' requested here}}
-
-namespace GH203701 {
- struct S {
- constexpr S(auto) {}
- constexpr operator int() const { return 0; }
- };
-
- constexpr auto a = [](this S) { return 1; };
-
- static_assert((&decltype(a)::operator())(1) == 42, ""); // expected-error-re at -1 {{static assertion failed due to requirement '\(&const GH203701::\(lambda at {{.*}}\)::operator\(\)\)\(1\) == 42'}}
- static_assert((&S::operator int) == nullptr, ""); // expected-error {{static assertion failed due to requirement '(&GH203701::S::operator int) == nullptr'}}
-}
>From c22872c3e73372bf0ebeb523a9addde77f9f9c70 Mon Sep 17 00:00:00 2001
From: Fan Mo <w007878 at hotmail.com>
Date: Wed, 1 Jul 2026 15:38:08 -0500
Subject: [PATCH 5/8] fix
---
clang/lib/Sema/SemaTemplate.cpp | 2 +-
clang/test/SemaCXX/static-assert-cxx17.cpp | 12 ------------
2 files changed, 1 insertion(+), 13 deletions(-)
diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp
index 41664f36dd6a3..cf28b4d3839bb 100644
--- a/clang/lib/Sema/SemaTemplate.cpp
+++ b/clang/lib/Sema/SemaTemplate.cpp
@@ -3647,7 +3647,7 @@ class FailedBooleanConditionPrinterHelper : public PrinterHelper {
DR->getQualifier().print(OS, Policy, true);
// Then print the decl itself.
const ValueDecl *VD = DR->getDecl();
- OS << VD->getDeclName();
+ OS << *VD;
if (const auto *IV = dyn_cast<VarTemplateSpecializationDecl>(VD)) {
// This is a template variable, print the expanded template arguments.
printTemplateArgumentList(
diff --git a/clang/test/SemaCXX/static-assert-cxx17.cpp b/clang/test/SemaCXX/static-assert-cxx17.cpp
index e3038f8cec130..41a7b025d0eb7 100644
--- a/clang/test/SemaCXX/static-assert-cxx17.cpp
+++ b/clang/test/SemaCXX/static-assert-cxx17.cpp
@@ -104,15 +104,3 @@ void foo6() {
}
template void foo6<ExampleTypes>();
// expected-note at -1{{in instantiation of function template specialization 'foo6<ExampleTypes>' requested here}}
-
-namespace GH203701 {
- struct S {
- constexpr S(auto) {}
- constexpr operator int() const { return 0; }
- };
-
- constexpr auto a = [](this S) { return 1; };
-
- static_assert((&decltype(a)::operator())(1) == 42, ""); // expected-error-re at -1 {{static assertion failed due to requirement '\(&const GH203701::\(lambda at {{.*}}\)::operator\(\)\)\(1\) == 42'}}
- static_assert((&S::operator int) == nullptr, ""); // expected-error {{static assertion failed due to requirement '(&GH203701::S::operator int) == nullptr'}}
-}
>From 42ac73d11744831e843e8f2931714fc9ba13531a Mon Sep 17 00:00:00 2001
From: Fan Mo <w007878 at hotmail.com>
Date: Wed, 8 Jul 2026 00:54:48 -0500
Subject: [PATCH 6/8] fix: check if TemplateAlias is valid
---
clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index fa740d5581e5f..d84c32dbcd331 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -1557,6 +1557,8 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
CXXDeductionGuideDecl *DeclareAggregateDeductionGuideForTypeAlias(
Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate,
MutableArrayRef<QualType> ParamTypes, SourceLocation Loc) {
+ if (AliasTemplate->isInvalidDecl())
+ return nullptr;
TemplateDecl *RHSTemplate =
getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate).first;
if (!RHSTemplate)
>From e5dd9245cf83d361fba9ebeb2df079ae02eb4622 Mon Sep 17 00:00:00 2001
From: Fan Mo <w007878 at hotmail.com>
Date: Thu, 16 Jul 2026 23:18:26 -0500
Subject: [PATCH 7/8] [clang] Fix crash on aggregate CTAD for invalid alias
template (#207156)
Bail out of DeclareAggregateDeductionGuideForTypeAlias when the alias
template is already invalid, instead of crashing during overload
candidate classification.
Co-Authored-By: Claude Fable 5 <noreply at anthropic.com>
---
clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index fa740d5581e5f..d84c32dbcd331 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -1557,6 +1557,8 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
CXXDeductionGuideDecl *DeclareAggregateDeductionGuideForTypeAlias(
Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate,
MutableArrayRef<QualType> ParamTypes, SourceLocation Loc) {
+ if (AliasTemplate->isInvalidDecl())
+ return nullptr;
TemplateDecl *RHSTemplate =
getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate).first;
if (!RHSTemplate)
>From 224adb762b846d3e38808d7a0ffb152a21e79c88 Mon Sep 17 00:00:00 2001
From: Fan Mo <w007878 at hotmail.com>
Date: Fri, 17 Jul 2026 00:55:29 -0500
Subject: [PATCH 8/8] fix it by handling empty deduction
---
clang/lib/Sema/SemaInit.cpp | 3 ++-
clang/lib/Sema/SemaTemplateDeductionGuide.cpp | 2 --
clang/test/SemaCXX/cxx20-ctad-type-alias.cpp | 15 +++++++++++++++
3 files changed, 17 insertions(+), 3 deletions(-)
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index d24a50fed0860..c11101b492dbe 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -10390,7 +10390,8 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
LookupTemplateDecl, ElementTypes,
TSInfo->getTypeLoc().getEndLoc())) {
auto *TD = GD->getDescribedFunctionTemplate();
- addDeductionCandidate(TD, GD, DeclAccessPair::make(TD, AS_public),
+ NamedDecl *Found = TD ? static_cast<NamedDecl *>(TD) : GD;
+ addDeductionCandidate(TD, GD, DeclAccessPair::make(Found, AS_public),
OnlyListConstructors,
/*AllowAggregateDeductionCandidate=*/true);
HasAnyDeductionGuide = true;
diff --git a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
index d84c32dbcd331..fa740d5581e5f 100644
--- a/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
+++ b/clang/lib/Sema/SemaTemplateDeductionGuide.cpp
@@ -1557,8 +1557,6 @@ void DeclareImplicitDeductionGuidesForTypeAlias(
CXXDeductionGuideDecl *DeclareAggregateDeductionGuideForTypeAlias(
Sema &SemaRef, TypeAliasTemplateDecl *AliasTemplate,
MutableArrayRef<QualType> ParamTypes, SourceLocation Loc) {
- if (AliasTemplate->isInvalidDecl())
- return nullptr;
TemplateDecl *RHSTemplate =
getRHSTemplateDeclAndArgs(SemaRef, AliasTemplate).first;
if (!RHSTemplate)
diff --git a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
index 78911cbaed67b..46b47b727e1ab 100644
--- a/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
+++ b/clang/test/SemaCXX/cxx20-ctad-type-alias.cpp
@@ -629,3 +629,18 @@ template <typename T> using S3 = S2<T>; // expected-note {{candidate function no
// expected-note {{cannot deduce template arguments for 'GH190517::S3' from 'GH190517::S1<char>'}}
S3 foo(42); // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'S3'}}
}
+
+namespace GH207156 {
+template <typename T> struct Foo { T t; }; // expected-error {{field has incomplete type 'GH207156::Y'}}
+
+template <Missing class Y> using AFoo = Foo<Y>; // expected-error {{unknown type name 'Missing'}} \
+ // expected-note {{forward declaration of 'GH207156::Y'}} \
+ // expected-note 3 {{candidate function not viable}} \
+ // expected-note 3 {{implicit deduction guide declared as}}
+AFoo s = {42}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'AFoo'}} \
+ // expected-note {{in instantiation of template class 'GH207156::Foo<GH207156::Y>' requested here}}
+
+template <typename Z> using BFoo = Foo<int>; // expected-note 3 {{candidate function not viable}} \
+ // expected-note 3 {{implicit deduction guide declared as}}
+BFoo b = {nullptr}; // expected-error {{no viable constructor or deduction guide for deduction of template arguments of 'BFoo'}}
+}
More information about the cfe-commits
mailing list