Author: offsetof
Date: 2025-04-11T08:47:07+02:00
New Revision: 9604bdf1180950c04f194584fdd2cca0f0668971
URL: 
https://github.com/llvm/llvm-project/commit/9604bdf1180950c04f194584fdd2cca0f0668971
DIFF: 
https://github.com/llvm/llvm-project/commit/9604bdf1180950c04f194584fdd2cca0f0668971.diff

LOG: [clang] Allow parentheses around CTAD declarators (#132829)

Fixes #39811

Added: 
    

Modified: 
    clang/docs/ReleaseNotes.rst
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/lib/Sema/SemaType.cpp
    clang/test/CXX/drs/cwg23xx.cpp
    clang/test/Parser/cxx1z-class-template-argument-deduction.cpp
    clang/test/SemaCXX/ctad.cpp
    clang/www/cxx_dr_status.html

Removed: 
    


################################################################################
diff  --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 5983621a7a875..46d2debec3621 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -452,6 +452,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)
 - Fixed a crash caused by invalid declarations of ``std::initializer_list``. 
(#GH132256)
 - Clang no longer crashes when establishing subsumption between some 
constraint expressions. (#GH122581)
 - Clang now issues an error when placement new is used to modify a 
const-qualified variable

diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td 
b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index b0972541cb4ab..180ca39bc07e9 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -2617,10 +2617,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 4e7726e258110..e711a5c5d2a18 100644
--- a/clang/lib/Sema/SemaType.cpp
+++ b/clang/lib/Sema/SemaType.cpp
@@ -4281,8 +4281,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);
@@ -4296,11 +4296,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/CXX/drs/cwg23xx.cpp b/clang/test/CXX/drs/cwg23xx.cpp
index d144cf9e4e868..78cecb8b71bca 100644
--- a/clang/test/CXX/drs/cwg23xx.cpp
+++ b/clang/test/CXX/drs/cwg23xx.cpp
@@ -379,6 +379,20 @@ class C {
 };
 } // namespace cwg2370
 
+namespace cwg2376 { // cwg2376: 21
+#if __cplusplus >= 201703L
+template<int = 0> class C {};
+
+C a;
+const volatile C b = C<2>();
+C (c) = {};
+C* d;
+// expected-error@-1 {{cannot form pointer to deduced class template 
specialization type}}
+C e[1];
+// expected-error@-1 {{cannot form array of deduced class template 
specialization type}}
+#endif
+}
+
 namespace cwg2386 { // cwg2386: 9
 // Otherwise, if the qualified-id std::tuple_size<E> names a complete class
 // type **with a member value**, the expression std::tuple_size<E>::value shall

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;};

diff  --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html
index eeb1d9d74bf00..8fe53ad46aca9 100755
--- a/clang/www/cxx_dr_status.html
+++ b/clang/www/cxx_dr_status.html
@@ -14091,7 +14091,7 @@ <h2 id="cxxdr">C++ defect report implementation 
status</h2>
     <td><a 
href="https://cplusplus.github.io/CWG/issues/2376.html";>2376</a></td>
     <td>CD5</td>
     <td>Class template argument deduction with array declarator</td>
-    <td class="unknown" align="center">Unknown</td>
+    <td class="unreleased" align="center">Clang 21</td>
   </tr>
   <tr id="2377">
     <td><a 
href="https://cplusplus.github.io/CWG/issues/2377.html";>2377</a></td>


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to