diff options
author | Jakub Jelinek <jakub@redhat.com> | 2023-11-30 09:09:21 +0100 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2023-11-30 09:09:21 +0100 |
commit | 6c9973e46bdb4496b5af8a7170269e91e36ad35a (patch) | |
tree | 69a956c0310de1cb8392167d46d0a8edb6e93b31 /gcc/cp/lambda.cc | |
parent | b4a7c1c8c59d191bff64a720cca61d1d308af531 (diff) | |
download | gcc-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.cc | 37 |
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 [=]. */ |