Author: Erich Keane Date: 2022-11-28T14:41:14-08:00 New Revision: 07008a8df57f8eb75e934a3a01ed0a4a76ae92ce
URL: https://github.com/llvm/llvm-project/commit/07008a8df57f8eb75e934a3a01ed0a4a76ae92ce DIFF: https://github.com/llvm/llvm-project/commit/07008a8df57f8eb75e934a3a01ed0a4a76ae92ce.diff LOG: CWG2635: Disallow constrained structured bindings. CWG2635 prohibits adding a constraint to a structured as a defect report. This patch implements that restriction. Differential Revision: https://reviews.llvm.org/D138852 Added: clang/test/FixIt/fixit-constrained-structured-binding.cpp Modified: clang/docs/ReleaseNotes.rst clang/include/clang/Basic/DiagnosticSemaKinds.td clang/lib/Sema/SemaDeclCXX.cpp clang/test/CXX/drs/dr26xx.cpp clang/www/cxx_dr_status.html Removed: ################################################################################ diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 3f99bc2f7c939..86911bd3b1a1e 100644 --- a/clang/docs/ReleaseNotes.rst +++ b/clang/docs/ReleaseNotes.rst @@ -655,6 +655,7 @@ C++20 Feature Support - Do not hide templated base members introduced via using-decl in derived class (useful specially for constrained members). Fixes `GH50886 <https://github.com/llvm/llvm-project/issues/50886>`_. +- Implemented CWG2635 as a Defect Report, which prohibits structured bindings from being constrained. C++2b Feature Support ^^^^^^^^^^^^^^^^^^^^^ diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 9678fd58b997c..71093da21b0d5 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -492,6 +492,8 @@ def warn_cxx17_compat_decomp_decl_spec : Warning< def err_decomp_decl_type : Error< "decomposition declaration cannot be declared with type %0; " "declared type must be 'auto' or reference to 'auto'">; +def err_decomp_decl_constraint : Error< + "decomposition declaration cannot be declared with constrained 'auto'">; def err_decomp_decl_parens : Error< "decomposition declaration cannot be declared with parentheses">; def err_decomp_decl_template : Error< diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index e714ffec87592..174fe43a2cd51 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/lib/Sema/SemaDeclCXX.cpp @@ -760,11 +760,16 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, // C++17 [dcl.dcl]/8: // The decl-specifier-seq shall contain only the type-specifier auto // and cv-qualifiers. - // C++2a [dcl.dcl]/8: + // C++20 [dcl.dcl]/8: // If decl-specifier-seq contains any decl-specifier other than static, // thread_local, auto, or cv-qualifiers, the program is ill-formed. + // C++2b [dcl.pre]/6: + // Each decl-specifier in the decl-specifier-seq shall be static, + // thread_local, auto (9.2.9.6 [dcl.spec.auto]), or a cv-qualifier. auto &DS = D.getDeclSpec(); { + // Note: While constrained-auto needs to be checked, we do so separately so + // we can emit a better diagnostic. SmallVector<StringRef, 8> BadSpecifiers; SmallVector<SourceLocation, 8> BadSpecifierLocs; SmallVector<StringRef, 8> CPlusPlus20Specifiers; @@ -791,6 +796,7 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, BadSpecifiers.push_back("inline"); BadSpecifierLocs.push_back(DS.getInlineSpecLoc()); } + if (!BadSpecifiers.empty()) { auto &&Err = Diag(BadSpecifierLocs.front(), diag::err_decomp_decl_spec); Err << (int)BadSpecifiers.size() @@ -851,6 +857,20 @@ Sema::ActOnDecompositionDeclarator(Scope *S, Declarator &D, D.setInvalidType(); } + // Constrained auto is prohibited by [decl.pre]p6, so check that here. + if (DS.isConstrainedAuto()) { + TemplateIdAnnotation *TemplRep = DS.getRepAsTemplateId(); + assert(TemplRep->Kind == TNK_Concept_template && + "No other template kind should be possible for a constrained auto"); + + SourceRange TemplRange{TemplRep->TemplateNameLoc, + TemplRep->RAngleLoc.isValid() + ? TemplRep->RAngleLoc + : TemplRep->TemplateNameLoc}; + Diag(TemplRep->TemplateNameLoc, diag::err_decomp_decl_constraint) + << TemplRange << FixItHint::CreateRemoval(TemplRange); + } + // Build the BindingDecls. SmallVector<BindingDecl*, 8> Bindings; diff --git a/clang/test/CXX/drs/dr26xx.cpp b/clang/test/CXX/drs/dr26xx.cpp index 7f590ca4cc1b2..7e8866045a7cd 100644 --- a/clang/test/CXX/drs/dr26xx.cpp +++ b/clang/test/CXX/drs/dr26xx.cpp @@ -27,6 +27,34 @@ void f() { // expected-note@#DR2628_CTOR {{marked deleted here}} } +} + +namespace dr2635 { // dr2635: yes +template<typename T> +concept UnaryC = true; +template<typename T, typename U> +concept BinaryC = true; + +struct S{ int i, j; }; +S get_S(); + +template<typename T> +T get_T(); + +void use() { + // expected-error@+1{{decomposition declaration cannot be declared with constrained 'auto'}} + UnaryC auto [a, b] = get_S(); + // expected-error@+1{{decomposition declaration cannot be declared with constrained 'auto'}} + BinaryC<int> auto [c, d] = get_S(); +} + +template<typename T> +void TemplUse() { + // expected-error@+1{{decomposition declaration cannot be declared with constrained 'auto'}} + UnaryC auto [a, b] = get_T<T>(); + // expected-error@+1{{decomposition declaration cannot be declared with constrained 'auto'}} + BinaryC<T> auto [c, d] = get_T<T>(); +} } // dr2636: na diff --git a/clang/test/FixIt/fixit-constrained-structured-binding.cpp b/clang/test/FixIt/fixit-constrained-structured-binding.cpp new file mode 100644 index 0000000000000..3f21c1da45a4a --- /dev/null +++ b/clang/test/FixIt/fixit-constrained-structured-binding.cpp @@ -0,0 +1,33 @@ +// RUN: not %clang_cc1 -std=c++20 -fdiagnostics-parseable-fixits -x c++ %s 2> %t +// RUN: FileCheck %s < %t + +template<typename T> +concept UnaryC = true; +template<typename T, typename U> +concept BinaryC = true; + +struct S{ int i, j; }; +S get_S(); + +template<typename T> +T get_T(); + +void use() { + UnaryC auto [a, b] = get_S(); + // CHECK: error: decomposition declaration cannot be declared with constrained 'auto' + // CHECK: fix-it:{{.*}}:{16:3-16:10}:"" + BinaryC<int> auto [c, d] = get_S(); + // CHECK: error: decomposition declaration cannot be declared with constrained 'auto' + // CHECK: fix-it:{{.*}}:{19:3-19:16}:"" +} + +template<typename T> +void TemplUse() { + UnaryC auto [a, b] = get_T<T>(); + // CHECK: error: decomposition declaration cannot be declared with constrained 'auto' + // XCHECK: fix-it:{{.*}}:{26:3-26:10}:"" + BinaryC<T> auto [c, d] = get_T<T>(); + // CHECK: error: decomposition declaration cannot be declared with constrained 'auto' + // XCHECK: fix-it:{{.*}}:{29:3-29:14}:"" +} + diff --git a/clang/www/cxx_dr_status.html b/clang/www/cxx_dr_status.html index a85b966a9f955..678c91313a47e 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -15618,7 +15618,7 @@ <h2 id="cxxdr">C++ defect report implementation status</h2> <td><a href="https://wg21.link/cwg2635">2635</a></td> <td>DR</td> <td>Constrained structured bindings</td> - <td class="none" align="center">Unknown</td> + <td class="unreleased" align="center">Clang 16</td> </tr> <tr id="2636"> <td><a href="https://wg21.link/cwg2636">2636</a></td> _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits