aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/lambda.cc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2023-11-30 09:09:21 +0100
committerJakub Jelinek <jakub@redhat.com>2023-11-30 09:09:21 +0100
commit6c9973e46bdb4496b5af8a7170269e91e36ad35a (patch)
tree69a956c0310de1cb8392167d46d0a8edb6e93b31 /gcc/cp/lambda.cc
parentb4a7c1c8c59d191bff64a720cca61d1d308af531 (diff)
downloadgcc-6c9973e46bdb4496b5af8a7170269e91e36ad35a.zip
gcc-6c9973e46bdb4496b5af8a7170269e91e36ad35a.tar.gz
gcc-6c9973e46bdb4496b5af8a7170269e91e36ad35a.tar.bz2
c++: Implement C++26 P2169R4 - Placeholder variables with no name [PR110349]
The following patch implements the C++26 P2169R4 paper. As written in the PR, the patch expects that: 1) https://eel.is/c++draft/expr.prim.lambda.capture#2 "Ignoring appearances in initializers of init-captures, an identifier or this shall not appear more than once in a lambda-capture." is adjusted such that name-independent lambda captures with initializers can violate this rule (but lambda captures which aren't name-independent can't appear after name-independent ones) 2) https://eel.is/c++draft/class.mem#general-5 "A member shall not be declared twice in the member-specification, except that" having an exception that name-independent non-static data member declarations can appear multiple times (but again, if there is a member which isn't name-independent, it can't appear after name-independent ones) 3) it assumes that any name-independent declarations which weren't previously valid result in the _ lookups being ambiguous, not just if there are 2 _ declarations in the same scope, in particular the https://eel.is/c++draft/basic.scope#block-2 mentioned cases 4) it assumes that _ in static function/block scope structured bindings is never name-independent like in namespace scope structured bindings; it matches clang behavior and is consistent with e.g. static type _; not being name-independent both at namespace scope and at function/block scope As you preferred in the PR, for local scope bindings, the ambiguous cases use a TREE_LIST with the ambiguous cases which can often be directly fed into print_candidates. For member_vec after sorting/deduping, I chose to use instead OVERLOAD with a new flag but only internally inside of the member_vec, get_class_binding_direct turns it into a TREE_LIST. There are 2 reasons for that, in order to keep the member_vec binary search fast, I think it is better to keep OVL_NAME usable on all elements because having to special case TREE_LIST would slow everything down, and the callers need to be able to chain the results anyway and so need an unshared TREE_LIST they can tweak/destroy anyway. name-independent declarations (even in older standards) will not have -Wunused{,-variable,-but-set-variable} or -Wshadow* warnings diagnosed, but unlike e.g. the clang implementation, this patch does diagnose -Wunused-parameter for parameters with _ names because they aren't name-independent and one can just omit their name instead. 2023-11-30 Jakub Jelinek <jakub@redhat.com> PR c++/110349 gcc/c-family/ * c-cppbuiltin.cc (c_cpp_builtins): Predefine __cpp_placeholder_variables=202306L for C++26. gcc/cp/ * cp-tree.h: Implement C++26 P2169R4 - Placeholder variables with no name. (OVL_NAME_INDEPENDENT_DECL_P): Define. (add_capture): Add unsigned * argument. (name_independent_decl_p): New inline function. * name-lookup.cc (class name_lookup): Make ambiguous and add_value members public. (name_independent_linear_search): New function. (get_class_binding_direct): Handle member_vec_binary_search returning OVL_NAME_INDEPENDENT_DECL_P OVERLOAD. Use name_independent_linear_search rather than fields_linear_search for linear lookup of _ name if !want_type. (member_name_cmp): Sort name-independent declarations first. (member_vec_dedup): Handle name-independent declarations. (pop_local_binding): Handle binding->value being a TREE_LIST for ambiguous name-independent declarations. (supplement_binding): Handle name-independent declarations. (update_binding): Likewise. (check_local_shadow): Return tree rather than void, normally NULL_TREE but old for name-independent declarations which used to conflict with outer scope declaration. Don't emit -Wshadow* warnings for name-independent declarations. (pushdecl): Handle name-independent declarations. * search.cc (lookup_field_r): Handle nval being a TREE_LIST. * lambda.cc (build_capture_proxy): Adjust for ___.<number> names of members. (add_capture): Add NAME_INDEPENDENT_CNT argument. Use ___.<number> name rather than ___ for second and following capture with _ name. (add_default_capture): Adjust add_capture caller. * decl.cc (poplevel): Don't warn about name-independent declarations. (duplicate_decls): If in C++26 a _ named declaration conflicts with earlier declarations, emit explaining note why the new declaration is not name-independent. (reshape_init_class): If field is a TREE_LIST, emit an ambiguity error with list of candidates rather than error about non-existing non-static data member. * parser.cc (cp_parser_lambda_introducer): Adjust add_capture callers. Allow name-independent capture redeclarations. (cp_parser_decomposition_declaration): Set decl_specs.storage_class to sc_static for static structured bindings. * pt.cc (tsubst_lambda_expr): Adjust add_capture caller. gcc/testsuite/ * g++.dg/cpp26/name-independent-decl1.C: New test. * g++.dg/cpp26/name-independent-decl2.C: New test. * g++.dg/cpp26/name-independent-decl3.C: New test. * g++.dg/cpp26/name-independent-decl4.C: New test. * g++.dg/cpp26/name-independent-decl5.C: New test. * g++.dg/cpp26/name-independent-decl6.C: New test. * g++.dg/cpp26/feat-cxx26.C: Add __cpp_placeholder_variables test.
Diffstat (limited to 'gcc/cp/lambda.cc')
-rw-r--r--gcc/cp/lambda.cc37
1 files changed, 29 insertions, 8 deletions
diff --git a/gcc/cp/lambda.cc b/gcc/cp/lambda.cc
index be8d240..5990a6de 100644
--- a/gcc/cp/lambda.cc
+++ b/gcc/cp/lambda.cc
@@ -411,7 +411,11 @@ build_capture_proxy (tree member, tree init)
object = TREE_OPERAND (object, 0);
/* Remove the __ inserted by add_capture. */
- name = get_identifier (IDENTIFIER_POINTER (DECL_NAME (member)) + 2);
+ if (IDENTIFIER_POINTER (DECL_NAME (member))[2] == '_'
+ && IDENTIFIER_POINTER (DECL_NAME (member))[3] == '.')
+ name = get_identifier ("_");
+ else
+ name = get_identifier (IDENTIFIER_POINTER (DECL_NAME (member)) + 2);
type = lambda_proxy_type (object);
@@ -515,7 +519,7 @@ vla_capture_type (tree array_type)
tree
add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
- bool explicit_init_p)
+ bool explicit_init_p, unsigned *name_independent_cnt)
{
char *buf;
tree type, member, name;
@@ -609,11 +613,28 @@ add_capture (tree lambda, tree id, tree orig_init, bool by_reference_p,
won't find the field with name lookup. We can't just leave the name
unset because template instantiation uses the name to find
instantiated fields. */
- buf = (char *) alloca (IDENTIFIER_LENGTH (id) + 3);
- buf[1] = buf[0] = '_';
- memcpy (buf + 2, IDENTIFIER_POINTER (id),
- IDENTIFIER_LENGTH (id) + 1);
- name = get_identifier (buf);
+ if (id_equal (id, "_") && name_independent_cnt)
+ {
+ if (*name_independent_cnt == 0)
+ name = get_identifier ("___");
+ else
+ {
+ /* For 2nd and later name-independent capture use
+ unique names. */
+ char buf2[5 + (HOST_BITS_PER_INT + 2) / 3];
+ sprintf (buf2, "___.%u", *name_independent_cnt);
+ name = get_identifier (buf2);
+ }
+ name_independent_cnt[0]++;
+ }
+ else
+ {
+ buf = XALLOCAVEC (char, IDENTIFIER_LENGTH (id) + 3);
+ buf[1] = buf[0] = '_';
+ memcpy (buf + 2, IDENTIFIER_POINTER (id),
+ IDENTIFIER_LENGTH (id) + 1);
+ name = get_identifier (buf);
+ }
if (variadic)
{
@@ -717,7 +738,7 @@ add_default_capture (tree lambda_stack, tree id, tree initializer)
(this_capture_p
|| (LAMBDA_EXPR_DEFAULT_CAPTURE_MODE (lambda)
== CPLD_REFERENCE)),
- /*explicit_init_p=*/false);
+ /*explicit_init_p=*/false, NULL);
initializer = convert_from_reference (var);
/* Warn about deprecated implicit capture of this via [=]. */