[clang] ccca93b - Don't allow structured binding declarations to decompose a
Richard Smith via cfe-commits
cfe-commits at lists.llvm.org
Fri Oct 23 16:28:36 PDT 2020
Author: Richard Smith
Date: 2020-10-23T16:28:25-07:00
New Revision: ccca93b5a2cb284dcdfecd34db1ca14632d6a1c1
URL: https://github.com/llvm/llvm-project/commit/ccca93b5a2cb284dcdfecd34db1ca14632d6a1c1
DIFF: https://github.com/llvm/llvm-project/commit/ccca93b5a2cb284dcdfecd34db1ca14632d6a1c1.diff
LOG: Don't allow structured binding declarations to decompose a
lambda-expression's captures.
The built-in structured binding rules for classes require that all
fields can be accessed by name, and the fields introduced for lambda
captures are unnamed, so decomposing a capturing lambda is ill-formed.
Added:
Modified:
clang/include/clang/Basic/DiagnosticSemaKinds.td
clang/lib/Sema/SemaDeclCXX.cpp
clang/test/SemaCXX/cxx1z-decomposition.cpp
Removed:
################################################################################
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 641d3e73905e..1aa6064d2210 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -486,6 +486,8 @@ def err_decomp_decl_inaccessible_base : Error<
def err_decomp_decl_inaccessible_field : Error<
"cannot decompose %select{private|protected}0 member %1 of %3">,
AccessControl;
+def err_decomp_decl_lambda : Error<
+ "cannot decompose lambda closure type">;
def err_decomp_decl_anon_union_member : Error<
"cannot decompose class type %0 because it has an anonymous "
"%select{struct|union}1 member">;
diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp
index 72dfa37c321e..6589b37338e9 100644
--- a/clang/lib/Sema/SemaDeclCXX.cpp
+++ b/clang/lib/Sema/SemaDeclCXX.cpp
@@ -1374,11 +1374,23 @@ static bool checkMemberDecomposition(Sema &S, ArrayRef<BindingDecl*> Bindings,
if (FD->isUnnamedBitfield())
continue;
- if (FD->isAnonymousStructOrUnion()) {
- S.Diag(Src->getLocation(), diag::err_decomp_decl_anon_union_member)
- << DecompType << FD->getType()->isUnionType();
- S.Diag(FD->getLocation(), diag::note_declared_at);
- return true;
+ // All the non-static data members are required to be nameable, so they
+ // must all have names.
+ if (!FD->getDeclName()) {
+ if (RD->isLambda()) {
+ S.Diag(Src->getLocation(), diag::err_decomp_decl_lambda);
+ S.Diag(RD->getLocation(), diag::note_lambda_decl);
+ return true;
+ }
+
+ if (FD->isAnonymousStructOrUnion()) {
+ S.Diag(Src->getLocation(), diag::err_decomp_decl_anon_union_member)
+ << DecompType << FD->getType()->isUnionType();
+ S.Diag(FD->getLocation(), diag::note_declared_at);
+ return true;
+ }
+
+ // FIXME: Are there any other ways we could have an anonymous member?
}
// We have a real field to bind.
diff --git a/clang/test/SemaCXX/cxx1z-decomposition.cpp b/clang/test/SemaCXX/cxx1z-decomposition.cpp
index 336c103ef0a4..45a062a916f3 100644
--- a/clang/test/SemaCXX/cxx1z-decomposition.cpp
+++ b/clang/test/SemaCXX/cxx1z-decomposition.cpp
@@ -103,4 +103,49 @@ int f2() {
} // namespace instantiate_template
+namespace lambdas {
+ void f() {
+ int n;
+ auto [a] = // expected-error {{cannot decompose lambda closure type}}
+ [n] {}; // expected-note {{lambda expression}}
+ }
+
+ auto [] = []{}; // expected-warning {{ISO C++17 does not allow a decomposition group to be empty}}
+
+ int g() {
+ int n = 0;
+ auto a = [=](auto &self) { // expected-note {{lambda expression}}
+ auto &[capture] = self; // expected-error {{cannot decompose lambda closure type}}
+ ++capture;
+ return n;
+ };
+ return a(a); // expected-note {{in instantiation of}}
+ }
+
+ int h() {
+ auto x = [] {};
+ struct A : decltype(x) {
+ int n;
+ };
+ auto &&[r] = A{x, 0}; // OK (presumably), non-capturing lambda has no non-static data members
+ return r;
+ }
+
+ int i() {
+ int n;
+ auto x = [n] {};
+ struct A : decltype(x) {
+ int n;
+ };
+ auto &&[r] = A{x, 0}; // expected-error-re {{cannot decompose class type 'A': both it and its base class 'decltype(x)' (aka '(lambda {{.*}})') have non-static data members}}
+ return r;
+ }
+
+ void j() {
+ auto x = [] {};
+ struct A : decltype(x) {};
+ auto &&[] = A{x}; // expected-warning {{ISO C++17 does not allow a decomposition group to be empty}}
+ }
+}
+
// FIXME: by-value array copies
More information about the cfe-commits
mailing list