From 07008a8df57f8eb75e934a3a01ed0a4a76ae92ce Mon Sep 17 00:00:00 2001 From: Erich Keane Date: Mon, 28 Nov 2022 12:09:58 -0800 Subject: [PATCH] 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 --- clang/docs/ReleaseNotes.rst | 1 + clang/include/clang/Basic/DiagnosticSemaKinds.td | 2 ++ clang/lib/Sema/SemaDeclCXX.cpp | 22 ++++++++++++++- clang/test/CXX/drs/dr26xx.cpp | 28 ++++++++++++++++++ .../FixIt/fixit-constrained-structured-binding.cpp | 33 ++++++++++++++++++++++ clang/www/cxx_dr_status.html | 2 +- 6 files changed, 86 insertions(+), 2 deletions(-) create mode 100644 clang/test/FixIt/fixit-constrained-structured-binding.cpp diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst index 3f99bc2..86911bd 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 `_. +- 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 9678fd5..71093da 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 e714ffe..174fe43 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 BadSpecifiers; SmallVector BadSpecifierLocs; SmallVector 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 Bindings; diff --git a/clang/test/CXX/drs/dr26xx.cpp b/clang/test/CXX/drs/dr26xx.cpp index 7f590ca..7e88660 100644 --- a/clang/test/CXX/drs/dr26xx.cpp +++ b/clang/test/CXX/drs/dr26xx.cpp @@ -29,6 +29,34 @@ void f() { } +namespace dr2635 { // dr2635: yes +template +concept UnaryC = true; +template +concept BinaryC = true; + +struct S{ int i, j; }; +S get_S(); + +template +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 auto [c, d] = get_S(); +} + +template +void TemplUse() { + // expected-error@+1{{decomposition declaration cannot be declared with constrained 'auto'}} + UnaryC auto [a, b] = get_T(); + // expected-error@+1{{decomposition declaration cannot be declared with constrained 'auto'}} + BinaryC auto [c, d] = get_T(); +} +} + // dr2636: na // dr2642: 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 0000000..3f21c1d --- /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 +concept UnaryC = true; +template +concept BinaryC = true; + +struct S{ int i, j; }; +S get_S(); + +template +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 auto [c, d] = get_S(); + // CHECK: error: decomposition declaration cannot be declared with constrained 'auto' + // CHECK: fix-it:{{.*}}:{19:3-19:16}:"" +} + +template +void TemplUse() { + UnaryC auto [a, b] = get_T(); + // CHECK: error: decomposition declaration cannot be declared with constrained 'auto' + // XCHECK: fix-it:{{.*}}:{26:3-26:10}:"" + BinaryC auto [c, d] = get_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 a85b966..678c913 100755 --- a/clang/www/cxx_dr_status.html +++ b/clang/www/cxx_dr_status.html @@ -15618,7 +15618,7 @@ and POD class 2635 DR Constrained structured bindings - Unknown + Clang 16 2636 -- 2.7.4