-
Notifications
You must be signed in to change notification settings - Fork 13.6k
[clang] Allow parentheses around CTAD declarators #132829
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
Conversation
@llvm/pr-subscribers-clang Author: None (offsetof) ChangesFixes #39811 Full diff: https://github.com/llvm/llvm-project/pull/132829.diff 5 Files Affected:
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index f919b66dd0e41..24c65dbef5869 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -358,6 +358,8 @@ Bug Fixes to C++ Support
- Fixed a Clang regression in C++20 mode where unresolved dependent call expressions were created inside non-dependent contexts (#GH122892)
- Clang now emits the ``-Wunused-variable`` warning when some structured bindings are unused
and the ``[[maybe_unused]]`` attribute is not applied. (#GH125810)
+- Declarations using class template argument deduction with redundant
+ parentheses around the declarator are no longer rejected. (#GH39811)
Bug Fixes to AST Handling
^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index c77cde297dc32..a19975f6d6bdf 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2612,10 +2612,9 @@ def err_decltype_auto_initializer_list : Error<
"cannot deduce 'decltype(auto)' from initializer list">;
// C++17 deduced class template specialization types
-def err_deduced_class_template_compound_type : Error<
- "cannot %select{form pointer to|form reference to|form array of|"
- "form function returning|use parentheses when declaring variable with}0 "
- "deduced class template specialization type">;
+def err_deduced_class_template_compound_type
+ : Error<"cannot form %select{pointer to|reference to|array of|function "
+ "returning}0 deduced class template specialization type">;
def err_deduced_non_class_or_alias_template_specialization_type : Error<
"%select{<error>|function template|variable template|alias template|"
"template template parameter|concept|template}0 %1 requires template "
diff --git a/clang/lib/Sema/SemaType.cpp b/clang/lib/Sema/SemaType.cpp
index aec33303780a0..16315d93ef8ce 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -4282,8 +4282,8 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
// If T is 'decltype(auto)', the only declarators we can have are parens
// and at most one function declarator if this is a function declaration.
- // If T is a deduced class template specialization type, we can have no
- // declarator chunks at all.
+ // If T is a deduced class template specialization type, only parentheses
+ // are allowed.
if (auto *DT = T->getAs<DeducedType>()) {
const AutoType *AT = T->getAs<AutoType>();
bool IsClassTemplateDeduction = isa<DeducedTemplateSpecializationType>(DT);
@@ -4297,11 +4297,6 @@ static TypeSourceInfo *GetFullTypeForDeclarator(TypeProcessingState &state,
unsigned DiagKind = 0;
switch (DeclChunk.Kind) {
case DeclaratorChunk::Paren:
- // FIXME: Rejecting this is a little silly.
- if (IsClassTemplateDeduction) {
- DiagKind = 4;
- break;
- }
continue;
case DeclaratorChunk::Function: {
if (IsClassTemplateDeduction) {
diff --git a/clang/test/Parser/cxx1z-class-template-argument-deduction.cpp b/clang/test/Parser/cxx1z-class-template-argument-deduction.cpp
index a1594333abae7..d29eed40b1864 100644
--- a/clang/test/Parser/cxx1z-class-template-argument-deduction.cpp
+++ b/clang/test/Parser/cxx1z-class-template-argument-deduction.cpp
@@ -39,7 +39,7 @@ namespace template_template_arg_pack {
template<typename...> struct YP {};
struct Z { template<typename T> struct Q {}; }; // expected-note 2{{here}}
-
+
template<typename T> using ZId = Z;
template<typename ...Ts> struct A {
@@ -152,7 +152,7 @@ namespace decl {
A a;
A b = 0;
const A c = 0;
- A (parens) = 0; // expected-error {{cannot use parentheses when declaring variable with deduced class template specialization type}}
+ A (parens) = 0;
A *p = 0; // expected-error {{cannot form pointer to deduced class template specialization type}}
A &r = *p; // expected-error {{cannot form reference to deduced class template specialization type}}
A arr[3] = 0; // expected-error {{cannot form array of deduced class template specialization type}}
@@ -179,7 +179,7 @@ namespace typename_specifier {
}
typename ::A a = 0;
const typename ::A b = 0;
- typename ::A (parens) = 0; // expected-error {{cannot use parentheses when declaring variable with deduced class template specialization type}}
+ typename ::A (parens) = 0;
typename ::A *p = 0; // expected-error {{cannot form pointer to deduced class template specialization type}}
typename ::A &r = *p; // expected-error {{cannot form reference to deduced class template specialization type}}
typename ::A arr[3] = 0; // expected-error {{cannot form array of deduced class template specialization type}}
@@ -217,7 +217,7 @@ namespace typename_specifier {
}
namespace parenthesized {
- template<typename T> struct X { X(T); };
+ template<typename T> struct X { X(T); };
auto n = (X([]{}));
}
diff --git a/clang/test/SemaCXX/ctad.cpp b/clang/test/SemaCXX/ctad.cpp
index 00a861d0f567c..d727c7e66c34c 100644
--- a/clang/test/SemaCXX/ctad.cpp
+++ b/clang/test/SemaCXX/ctad.cpp
@@ -1,5 +1,31 @@
// RUN: %clang_cc1 -fsyntax-only -verify -Wno-unused-value -std=c++20 %s
+namespace GH39811 {
+
+template<int = 0> class C {};
+
+C (a);
+C (b) = C();
+C (c) {};
+C (((((d)))));
+
+template<C (e)> class X;
+template<C (...f)> class Y;
+
+void test() {
+ C (g);
+ C (h) = C();
+ C (i) {};
+ (void)g;
+ (void)h;
+ (void)i;
+}
+
+C* (bad1); // expected-error {{cannot form pointer to deduced class template specialization type}}
+C (*bad2); // expected-error {{cannot form pointer to deduced class template specialization type}}
+
+}
+
namespace GH64347 {
template<typename X, typename Y> struct A { X x; Y y;};
|
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.
So the implementation of this seems fine, but looking at how other compilers handle this, GCC and MSVC accept this, whereas EDG rejects. I agree w/ the comment that that is a bit silly to reject this, but can you check what the standard has to say about this? If this is disallowed by the standard, we might want to issue an extension warning (disabled by default) here.
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.
Actually, I just checked #39811, and apparently this was a CWG issue that has been resolved, so in that case this seems fine.
CC @Endilll Should this also add a test to cwg23xx.cpp? |
Yes, please! |
Add test for CWG2376
Added a test for CWG2376. |
clang/test/CXX/drs/cwg23xx.cpp
Outdated
@@ -379,6 +379,20 @@ class C { | |||
}; | |||
} // namespace cwg2370 | |||
|
|||
namespace cwg2376 { // cwg2376: 21 | |||
#if __cpp_deduction_guides >= 201703 |
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.
#if __cpp_deduction_guides >= 201703 | |
#if __cplusplus >= 201703L |
Replace feature-test macro with `__cplusplus`
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.
LGTM, thanks. Will you need me to merge that for you?
Yes please, thank you @cor3ntin |
Fixes #39811