Skip to content

Disable alias template CTAD for C++17 #133597

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

GeorgeKA
Copy link
Contributor

@GeorgeKA GeorgeKA commented Mar 29, 2025

Alias template class template argument deduction is a C++20 feature. Also updated relevant CTAD test cases.

PR for 125913

Alias template class template argument deduction is a C++20 feature.
Also updated relevant CTAD test cases.
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Mar 29, 2025
@llvmbot
Copy link
Member

llvmbot commented Mar 29, 2025

@llvm/pr-subscribers-clang

Author: None (GeorgeKA)

Changes

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 --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>();
 

Copy link
Contributor

@mizvekov mizvekov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We do tend to offer newer features into older standards when that isn't a burden, as long as we have a warning advertising the incompatibility with the current standard, as we do.

What is the motivation for this change?

Comment on lines +9920 to +9921
Diag(Kind.getLocation(),
diag::warn_cxx17_compat_ctad_for_alias_templates);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This being still a warning is incompatible with the purpose of the change.

@@ -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;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is just removing the test. Ideally this would still be tested under C++20.

@GeorgeKA
Copy link
Contributor Author

GeorgeKA commented Mar 29, 2025

We do tend to offer newer features into older standards when that isn't a burden, as long as we have a warning advertising the incompatibility with the current standard, as we do.

What is the motivation for this change?

It was originally detailed in 125913. The motivation from the reporter was simply that the feature is being allowed in C++17 mode when it's documented as a C++20 feature.

From your response @mizvekov, sounds like it being allowed is okay.

@mizvekov
Copy link
Contributor

It is generally ok, we only do not allow it when that would cause some significant backwards compatibility issues.

@GeorgeKA
Copy link
Contributor Author

Gotcha. Thanks for the feedback. I'll comment in the issue.

@cor3ntin
Copy link
Contributor

I think the issue here is that there is no extension warning in C++17. There should probably be one.
Search for ExtWarn in DiagnosticSemaKinds.td and how these ext_xxxx diagnostics are used

@GeorgeKA
Copy link
Contributor Author

Opened a separate PR given the branch I used here implies disabling the feature.
#133806

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants