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

Reply via email to