-
Notifications
You must be signed in to change notification settings - Fork 14.3k
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
Disable alias template CTAD for C++17 #133597
Conversation
Alias template class template argument deduction is a C++20 feature. Also updated relevant CTAD test cases.
@llvm/pr-subscribers-clang Author: None (GeorgeKA) ChangesAlias 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:
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>();
|
There was a problem hiding this 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?
Diag(Kind.getLocation(), | ||
diag::warn_cxx17_compat_ctad_for_alias_templates); |
There was a problem hiding this comment.
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; |
There was a problem hiding this comment.
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.
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. |
It is generally ok, we only do not allow it when that would cause some significant backwards compatibility issues. |
Gotcha. Thanks for the feedback. I'll comment in the issue. |
I think the issue here is that there is no extension warning in C++17. There should probably be one. |
Opened a separate PR given the branch I used here implies disabling the feature. |
Alias template class template argument deduction is a C++20 feature. Also updated relevant CTAD test cases.
PR for 125913