diff options
author | Jakub Jelinek <jakub@redhat.com> | 2024-07-02 22:07:30 +0200 |
---|---|---|
committer | Jakub Jelinek <jakub@redhat.com> | 2024-07-02 22:07:30 +0200 |
commit | f30bdb1f2d79fd787e0c270039179bf80830161f (patch) | |
tree | ae2a436eed647b8d9bd6fcf55ef35fe3433b1504 /gcc/cp/decl2.cc | |
parent | cc63b59e8843f049587b7a548a530f710085e577 (diff) | |
download | gcc-f30bdb1f2d79fd787e0c270039179bf80830161f.zip gcc-f30bdb1f2d79fd787e0c270039179bf80830161f.tar.gz gcc-f30bdb1f2d79fd787e0c270039179bf80830161f.tar.bz2 |
c++: Implement C++26 P0963R3 - Structured binding declaration as a condition [PR115745]
This C++26 paper allows structured bindings declaration in
if/while/for/switch conditions, where the structured binding shouldn't
be initialized by array (so in the standard only non-union class types;
as extension _Complex will also work and vectors will be diagnosed because
of conversion issues) and the decision variable is the artificial variable
(e in the standard) itself contextually converted to bool or converted to
some integer/enumeration type.
The standard requires that the conversion is evaluated before the get calls
in case of std::tuple* using class, so the largest part of the patch is making
sure this can be done during instantiation without duplicating too much
code.
In cp_parser_condition, creating a TARGET_EXPR to hold temporarily the
bool or int/enum result of the conversion across the get calls is easy, it
could be just added in between cp_finish_decl and cp_finish_decomp, but for
pt.cc there was no easy spot to add that.
In the end, the patch uses DECL_DECOMP_BASE for this. That tree is used
primarily for the user vars or var proxies to point back at the
DECL_ARTIFICIAL e variable, before this patch it has been NULL_TREE on
the base. In some places code was checking if DECL_DECOMP_BASE is NULL_TREE
to find out if it is the base or user var/var proxy.
The patch introduces DECL_DECOMP_IS_BASE macro for what used to be
!DECL_DECOMP_BASE and can stick something else in the base's
DECL_DECOMP_BASE as long as it is not a VAR_DECL.
The patch uses integer_zero_node to mark if/while/for condition structured
binding, integer_one_node to mark switch condition structured binding and
finally cp_finish_decomp sets it to TARGET_EXPR if some get method calls are
emitted and from there the callers can pick that up. This way I also
avoided code duplication between !processing_template_decl parsing and
pt.cc.
2024-07-02 Jakub Jelinek <jakub@redhat.com>
PR c++/115745
gcc/cp/
* cp-tree.h: Implement C++26 P0963R3 - Structured binding declaration
as a condition.
(DECL_DECOMP_BASE): Adjust comment.
(DECL_DECOMP_IS_BASE): Define.
* parser.cc (cp_parser_selection_statement): Adjust
cp_parser_condition caller.
(cp_parser_condition): Add KEYWORD argument. Parse
C++26 structured bindings in conditions.
(cp_parser_c_for, cp_parser_iteration_statement): Adjust
cp_parser_condition callers.
(cp_parser_simple_declaration): Adjust
cp_parser_decomposition_declaration caller.
(cp_parser_decomposition_declaration): Add KEYWORD argument.
If it is not RID_MAX, diagnose for C++23 and older rather than C++14
and older. Set DECL_DECOMP_BASE to integer_zero_node for structured
bindings used in if/while/for conditions or integer_one_node for
those used in switch conditions.
* decl.cc (poplevel, check_array_initializer): Use DECL_DECOMP_IS_BASE
instead of !DECL_DECOMP_BASE.
(cp_finish_decomp): Diagnose array initializer for structured bindings
used in conditions. If using std::tuple_{size,element}, emit
conversion to bool or integer/enumeration of e into a TARGET_EXPR
before emitting get method calls.
* decl2.cc (mark_used): Use DECL_DECOMP_IS_BASE instead of
!DECL_DECOMP_BASE.
* module.cc (trees_in::tree_node): Likewise.
* typeck.cc (maybe_warn_about_returning_address_of_local): Likewise.
* semantics.cc (maybe_convert_cond): For structured bindings with
TARGET_EXPR DECL_DECOMP_BASE use that as condition.
(finish_switch_cond): Likewise.
gcc/testsuite/
* g++.dg/cpp1z/decomp16.C: Adjust expected diagnostics.
* g++.dg/cpp26/decomp3.C: New test.
* g++.dg/cpp26/decomp4.C: New test.
* g++.dg/cpp26/decomp5.C: New test.
* g++.dg/cpp26/decomp6.C: New test.
* g++.dg/cpp26/decomp7.C: New test.
* g++.dg/cpp26/decomp8.C: New test.
* g++.dg/cpp26/decomp9.C: New test.
* g++.dg/cpp26/decomp10.C: New test.
Diffstat (limited to 'gcc/cp/decl2.cc')
-rw-r--r-- | gcc/cp/decl2.cc | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/gcc/cp/decl2.cc b/gcc/cp/decl2.cc index cdd2b8a..6d67468 100644 --- a/gcc/cp/decl2.cc +++ b/gcc/cp/decl2.cc @@ -5893,7 +5893,7 @@ mark_used (tree decl, tsubst_flags_t complain /* = tf_warning_or_error */) TREE_USED (decl) = true; /* And for structured bindings also the underlying decl. */ - if (DECL_DECOMPOSITION_P (decl) && DECL_DECOMP_BASE (decl)) + if (DECL_DECOMPOSITION_P (decl) && !DECL_DECOMP_IS_BASE (decl)) TREE_USED (DECL_DECOMP_BASE (decl)) = true; if (TREE_CODE (decl) == TEMPLATE_DECL) |