https://github.com/GeorgeKA created https://github.com/llvm/llvm-project/pull/133597
Alias template class template argument deduction is a C++20 feature. Also updated relevant CTAD test cases. >From 5b6d72ce1503196bf1c06a8b3dbc3f913265d76c Mon Sep 17 00:00:00 2001 From: George Asante <gkasa...@gmail.com> Date: Sat, 29 Mar 2025 16:42:29 -0400 Subject: [PATCH] Disable alias template CTAD for C++17 Alias template class template argument deduction is a C++20 feature. Also updated relevant CTAD test cases. --- .../clang/Basic/DiagnosticSemaKinds.td | 8 ++-- clang/lib/Sema/SemaInit.cpp | 44 ++++++++++--------- clang/test/SemaCXX/cxx17-compat.cpp | 6 +-- ...xx1z-class-template-argument-deduction.cpp | 2 +- 4 files changed, 33 insertions(+), 27 deletions(-) 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@-4 {{class template argument deduction for alias templates is incompatible with C++ standards before C++20}} + // expected-error@-2 {{alias template 'B' requires template arguments; argument deduction only allowed for class templates or alias templates}} + // expected-warning@-3 {{class template argument deduction for alias templates is incompatible with C++ standards before C++20}} + // expected-note@-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>(); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits