[clang] Disable alias template CTAD for C++17 (PR #133597)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Mar 29 13:48:19 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: None (GeorgeKA)
<details>
<summary>Changes</summary>
Alias template class template argument deduction is a C++20 feature. Also updated relevant CTAD test cases.
---
Full diff: https://github.com/llvm/llvm-project/pull/133597.diff
4 Files Affected:
- (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+5-3)
- (modified) clang/lib/Sema/SemaInit.cpp (+24-20)
- (modified) clang/test/SemaCXX/cxx17-compat.cpp (+3-3)
- (modified) clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp (+1-1)
``````````diff
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c77cde297dc32..811501e0cacac 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -8444,9 +8444,11 @@ let CategoryName = "Lambda Issue" in {
"C++ standards before C++20">, InGroup<CXXPre20Compat>, DefaultIgnore;
// C++20 class template argument deduction for alias templates.
- def warn_cxx17_compat_ctad_for_alias_templates : Warning<
- "class template argument deduction for alias templates is incompatible with "
- "C++ standards before C++20">, InGroup<CXXPre20Compat>, DefaultIgnore;
+ def warn_cxx17_compat_ctad_for_alias_templates
+ : Warning<"class template argument deduction for alias templates is "
+ "incompatible with "
+ "C++ standards before C++20">,
+ InGroup<CXXPre20Compat>;
}
def err_return_in_captured_stmt : Error<
diff --git a/clang/lib/Sema/SemaInit.cpp b/clang/lib/Sema/SemaInit.cpp
index cea121d576c5c..a8ffa804b3c57 100644
--- a/clang/lib/Sema/SemaInit.cpp
+++ b/clang/lib/Sema/SemaInit.cpp
@@ -9895,26 +9895,30 @@ QualType Sema::DeduceTemplateSpecializationFromInitializer(
if (!Template) {
if (auto *AliasTemplate = dyn_cast_or_null<TypeAliasTemplateDecl>(
TemplateName.getAsTemplateDecl())) {
- Diag(Kind.getLocation(),
- diag::warn_cxx17_compat_ctad_for_alias_templates);
- LookupTemplateDecl = AliasTemplate;
- auto UnderlyingType = AliasTemplate->getTemplatedDecl()
- ->getUnderlyingType()
- .getCanonicalType();
- // C++ [over.match.class.deduct#3]: ..., the defining-type-id of A must be
- // of the form
- // [typename] [nested-name-specifier] [template] simple-template-id
- if (const auto *TST =
- UnderlyingType->getAs<TemplateSpecializationType>()) {
- Template = dyn_cast_or_null<ClassTemplateDecl>(
- TST->getTemplateName().getAsTemplateDecl());
- } else if (const auto *RT = UnderlyingType->getAs<RecordType>()) {
- // Cases where template arguments in the RHS of the alias are not
- // dependent. e.g.
- // using AliasFoo = Foo<bool>;
- if (const auto *CTSD = llvm::dyn_cast<ClassTemplateSpecializationDecl>(
- RT->getAsCXXRecordDecl()))
- Template = CTSD->getSpecializedTemplate();
+ if (getLangOpts().CPlusPlus20) {
+ LookupTemplateDecl = AliasTemplate;
+ auto UnderlyingType = AliasTemplate->getTemplatedDecl()
+ ->getUnderlyingType()
+ .getCanonicalType();
+ // C++ [over.match.class.deduct#3]: ..., the defining-type-id of A must
+ // be of the form
+ // [typename] [nested-name-specifier] [template] simple-template-id
+ if (const auto *TST =
+ UnderlyingType->getAs<TemplateSpecializationType>()) {
+ Template = dyn_cast_or_null<ClassTemplateDecl>(
+ TST->getTemplateName().getAsTemplateDecl());
+ } else if (const auto *RT = UnderlyingType->getAs<RecordType>()) {
+ // Cases where template arguments in the RHS of the alias are not
+ // dependent. e.g.
+ // using AliasFoo = Foo<bool>;
+ if (const auto *CTSD =
+ llvm::dyn_cast<ClassTemplateSpecializationDecl>(
+ RT->getAsCXXRecordDecl()))
+ Template = CTSD->getSpecializedTemplate();
+ }
+ } else {
+ Diag(Kind.getLocation(),
+ diag::warn_cxx17_compat_ctad_for_alias_templates);
}
}
}
diff --git a/clang/test/SemaCXX/cxx17-compat.cpp b/clang/test/SemaCXX/cxx17-compat.cpp
index 54ea3384022d4..d0da4b0f81646 100644
--- a/clang/test/SemaCXX/cxx17-compat.cpp
+++ b/clang/test/SemaCXX/cxx17-compat.cpp
@@ -137,8 +137,8 @@ template<typename T> struct A { A(T); };
template<typename T> using B = A<T>;
B b = {1};
#if __cplusplus <= 201703L
- // FIXME: diagnose as well
-#else
- // expected-warning at -4 {{class template argument deduction for alias templates is incompatible with C++ standards before C++20}}
+ // expected-error at -2 {{alias template 'B' requires template arguments; argument deduction only allowed for class templates or alias templates}}
+ // expected-warning at -3 {{class template argument deduction for alias templates is incompatible with C++ standards before C++20}}
+ // expected-note at -5 {{template is declared here}}
#endif
}
diff --git a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
index 9aaa13d7ac41a..e96bfc4147d41 100644
--- a/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
+++ b/clang/test/SemaCXX/cxx1z-class-template-argument-deduction.cpp
@@ -113,7 +113,7 @@ namespace dependent {
};
template<typename T> void f() {
typename T::X tx = 0;
- typename T::Y ty = 0;
+ typename T::template Y<int> ty = 0;
}
template void f<B>();
``````````
</details>
https://github.com/llvm/llvm-project/pull/133597
More information about the cfe-commits
mailing list