aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathaniel Shead <nathanieloshead@gmail.com>2024-11-07 21:37:28 +1100
committerNathaniel Shead <nathanieloshead@gmail.com>2024-12-14 12:28:23 +1100
commita6a15bc5b77c8703a95130f410a944f5408a5cc4 (patch)
tree672bd2203a09d3237b558fc6996c8e07a68bcd61 /gcc
parent7238b074b59d1e9356456c709df321bc9f6ab8bf (diff)
downloadgcc-a6a15bc5b77c8703a95130f410a944f5408a5cc4.zip
gcc-a6a15bc5b77c8703a95130f410a944f5408a5cc4.tar.gz
gcc-a6a15bc5b77c8703a95130f410a944f5408a5cc4.tar.bz2
c++: Disallow decomposition of lambda bases [PR90321]
Decomposition of lambda closure types is not allowed by [dcl.struct.bind] p6, since members of a closure have no name. r244909 made this an error, but missed the case where a lambda is used as a base. This patch moves the check to find_decomp_class_base to handle this case. As a drive-by improvement, we also slightly improve the diagnostics to indicate why a base class was being inspected. Ideally the diagnostic would point directly at the relevant base, but there doesn't seem to be an easy way to get this location just from the binfo so I don't worry about that here. PR c++/90321 gcc/cp/ChangeLog: * decl.cc (find_decomp_class_base): Check for decomposing a lambda closure type. Report base class chains if needed. (cp_finish_decomp): Remove no-longer-needed check. gcc/testsuite/ChangeLog: * g++.dg/cpp1z/decomp62.C: New test. Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com> Reviewed-by: Marek Polacek <polacek@redhat.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/decl.cc19
-rw-r--r--gcc/testsuite/g++.dg/cpp1z/decomp62.C12
2 files changed, 25 insertions, 6 deletions
diff --git a/gcc/cp/decl.cc b/gcc/cp/decl.cc
index 4ba6e37..a1b9957 100644
--- a/gcc/cp/decl.cc
+++ b/gcc/cp/decl.cc
@@ -9405,6 +9405,14 @@ cp_finish_decl (tree decl, tree init, bool init_const_expr_p,
static tree
find_decomp_class_base (location_t loc, tree type, tree ret)
{
+ if (LAMBDA_TYPE_P (type))
+ {
+ auto_diagnostic_group d;
+ error_at (loc, "cannot decompose lambda closure type %qT", type);
+ inform (location_of (type), "lambda declared here");
+ return error_mark_node;
+ }
+
bool member_seen = false;
for (tree field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
if (TREE_CODE (field) != FIELD_DECL
@@ -9447,9 +9455,13 @@ find_decomp_class_base (location_t loc, tree type, tree ret)
for (binfo = TYPE_BINFO (type), i = 0;
BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
{
+ auto_diagnostic_group d;
tree t = find_decomp_class_base (loc, TREE_TYPE (base_binfo), ret);
if (t == error_mark_node)
- return error_mark_node;
+ {
+ inform (location_of (type), "in base class of %qT", type);
+ return error_mark_node;
+ }
if (t != NULL_TREE && t != ret)
{
if (ret == type)
@@ -9905,11 +9917,6 @@ cp_finish_decomp (tree decl, cp_decomp *decomp, bool test_p)
error_at (loc, "cannot decompose non-array non-class type %qT", type);
goto error_out;
}
- else if (LAMBDA_TYPE_P (type))
- {
- error_at (loc, "cannot decompose lambda closure type %qT", type);
- goto error_out;
- }
else if (processing_template_decl && complete_type (type) == error_mark_node)
goto error_out;
else if (processing_template_decl && !COMPLETE_TYPE_P (type))
diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp62.C b/gcc/testsuite/g++.dg/cpp1z/decomp62.C
new file mode 100644
index 0000000..b0ce105
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1z/decomp62.C
@@ -0,0 +1,12 @@
+// PR c++/90321
+// { dg-do compile { target c++17 } }
+
+template<class F> struct hack : F { };
+template<class F> hack(F) -> hack<F>;
+
+int main()
+{
+ auto f = [x = 1, y = 2]() { };
+ auto [a, b] = hack { f }; // { dg-error "cannot decompose lambda closure type" }
+ return b;
+}