mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-16 17:11:07 +08:00
Merge trunk r263667.
From-SVN: r263668
This commit is contained in:
commit
c014d99632
@ -1,5 +1,7 @@
|
||||
2018-08-20 Nathan Sidwell <nathan@acm.org>
|
||||
|
||||
Merge trunk r263667.
|
||||
|
||||
Merge trunk r263658.
|
||||
|
||||
2018-08-17 Nathan Sidwell <nathan@acm.org>
|
||||
|
@ -1,3 +1,36 @@
|
||||
2018-08-20 Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
|
||||
* expr.c (store_field): Change gcc_assert to gcc_checking_assert.
|
||||
|
||||
2018-08-20 Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
|
||||
PR target/86984
|
||||
* expr.c (expand_assignment): Assert that bitpos is positive.
|
||||
(store_field): Likewise
|
||||
(expand_expr_real_1): Make sure that bitpos is positive.
|
||||
* config/alpha/alpha.h (CONSTANT_ADDRESS_P): Avoid signed
|
||||
integer overflow.
|
||||
|
||||
2018-08-20 Nathan Sidwell <nathan@acm.org>
|
||||
|
||||
* Makefile.in (CPP_ID_DATA_H): Delete.
|
||||
(CPP_INTERNAL_H): Don't add it.
|
||||
(GTFILES): Replace CPP_ID_DATA_H with CPPLIB_H.
|
||||
* gengtype.c (open_base_files): Replace cpp-id-data.h with cpplib.h
|
||||
|
||||
2018-08-20 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/78655
|
||||
* tree-vrp.c (extract_range_from_binary_expr_1): Make
|
||||
pointer + offset nonnull if either operand is nonnull work.
|
||||
|
||||
2018-08-20 Tom de Vries <tdevries@suse.de>
|
||||
|
||||
* dwarf2out.c (add_scalar_info): Don't add reference to existing die
|
||||
unless the referenced die describes the added property using
|
||||
DW_AT_location or DW_AT_const_value. Fall back to exprloc case.
|
||||
Otherwise, add a DW_AT_location to the referenced die.
|
||||
|
||||
2018-08-19 Uros Bizjak <ubizjak@gmail.com>
|
||||
|
||||
PR target/86994
|
||||
|
@ -678,7 +678,7 @@ enum reg_class {
|
||||
|
||||
#define CONSTANT_ADDRESS_P(X) \
|
||||
(CONST_INT_P (X) \
|
||||
&& (unsigned HOST_WIDE_INT) (INTVAL (X) + 0x8000) < 0x10000)
|
||||
&& (UINTVAL (X) + 0x8000) < 0x10000)
|
||||
|
||||
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
|
||||
and check its validity for a certain class.
|
||||
|
@ -20598,7 +20598,7 @@ static void
|
||||
add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
|
||||
int forms, struct loc_descr_context *context)
|
||||
{
|
||||
dw_die_ref context_die, decl_die;
|
||||
dw_die_ref context_die, decl_die = NULL;
|
||||
dw_loc_list_ref list;
|
||||
bool strip_conversions = true;
|
||||
bool placeholder_seen = false;
|
||||
@ -20675,7 +20675,7 @@ add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
|
||||
|
||||
if (decl != NULL_TREE)
|
||||
{
|
||||
dw_die_ref decl_die = lookup_decl_die (decl);
|
||||
decl_die = lookup_decl_die (decl);
|
||||
|
||||
/* ??? Can this happen, or should the variable have been bound
|
||||
first? Probably it can, since I imagine that we try to create
|
||||
@ -20684,8 +20684,12 @@ add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
|
||||
later parameter. */
|
||||
if (decl_die != NULL)
|
||||
{
|
||||
add_AT_die_ref (die, attr, decl_die);
|
||||
return;
|
||||
if (get_AT (decl_die, DW_AT_location)
|
||||
|| get_AT (decl_die, DW_AT_const_value))
|
||||
{
|
||||
add_AT_die_ref (die, attr, decl_die);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -20729,15 +20733,19 @@ add_scalar_info (dw_die_ref die, enum dwarf_attribute attr, tree value,
|
||||
|| placeholder_seen)
|
||||
return;
|
||||
|
||||
if (current_function_decl == 0)
|
||||
context_die = comp_unit_die ();
|
||||
else
|
||||
context_die = lookup_decl_die (current_function_decl);
|
||||
if (!decl_die)
|
||||
{
|
||||
if (current_function_decl == 0)
|
||||
context_die = comp_unit_die ();
|
||||
else
|
||||
context_die = lookup_decl_die (current_function_decl);
|
||||
|
||||
decl_die = new_die (DW_TAG_variable, context_die, value);
|
||||
add_AT_flag (decl_die, DW_AT_artificial, 1);
|
||||
add_type_attribute (decl_die, TREE_TYPE (value), TYPE_QUAL_CONST, false,
|
||||
context_die);
|
||||
}
|
||||
|
||||
decl_die = new_die (DW_TAG_variable, context_die, value);
|
||||
add_AT_flag (decl_die, DW_AT_artificial, 1);
|
||||
add_type_attribute (decl_die, TREE_TYPE (value), TYPE_QUAL_CONST, false,
|
||||
context_die);
|
||||
add_AT_location_description (decl_die, DW_AT_location, list);
|
||||
add_AT_die_ref (die, attr, decl_die);
|
||||
}
|
||||
|
11
gcc/expr.c
11
gcc/expr.c
@ -5270,6 +5270,7 @@ expand_assignment (tree to, tree from, bool nontemporal)
|
||||
MEM_VOLATILE_P (to_rtx) = 1;
|
||||
}
|
||||
|
||||
gcc_checking_assert (known_ge (bitpos, 0));
|
||||
if (optimize_bitfield_assignment_op (bitsize, bitpos,
|
||||
bitregion_start, bitregion_end,
|
||||
mode1, to_rtx, to, from,
|
||||
@ -7046,6 +7047,7 @@ store_field (rtx target, poly_int64 bitsize, poly_int64 bitpos,
|
||||
}
|
||||
|
||||
/* Store the value in the bitfield. */
|
||||
gcc_checking_assert (known_ge (bitpos, 0));
|
||||
store_bit_field (target, bitsize, bitpos,
|
||||
bitregion_start, bitregion_end,
|
||||
mode, temp, reverse);
|
||||
@ -10545,6 +10547,14 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
|
||||
mode2
|
||||
= CONSTANT_P (op0) ? TYPE_MODE (TREE_TYPE (tem)) : GET_MODE (op0);
|
||||
|
||||
/* Make sure bitpos is not negative, it can wreak havoc later. */
|
||||
if (maybe_lt (bitpos, 0))
|
||||
{
|
||||
gcc_checking_assert (offset == NULL_TREE);
|
||||
offset = size_int (bits_to_bytes_round_down (bitpos));
|
||||
bitpos = num_trailing_bits (bitpos);
|
||||
}
|
||||
|
||||
/* If we have either an offset, a BLKmode result, or a reference
|
||||
outside the underlying object, we must force it to memory.
|
||||
Such a case can occur in Ada if we have unchecked conversion
|
||||
@ -10795,6 +10805,7 @@ expand_expr_real_1 (tree exp, rtx target, machine_mode tmode,
|
||||
&& GET_MODE_CLASS (ext_mode) == MODE_INT)
|
||||
reversep = TYPE_REVERSE_STORAGE_ORDER (type);
|
||||
|
||||
gcc_checking_assert (known_ge (bitpos, 0));
|
||||
op0 = extract_bit_field (op0, bitsize, bitpos, unsignedp,
|
||||
(modifier == EXPAND_STACK_PARM
|
||||
? NULL_RTX : target),
|
||||
|
@ -1,3 +1,13 @@
|
||||
2018-08-20 Bernd Edlinger <bernd.edlinger@hotmail.de>
|
||||
|
||||
PR target/86984
|
||||
* gcc.target/alpha/pr86984.c: New test.
|
||||
|
||||
2018-08-20 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/78655
|
||||
* gcc.dg/tree-ssa/evrp11.c: New testcase.
|
||||
|
||||
2018-08-18 Iain Sandoe <iain@sandoe.co.uk>
|
||||
|
||||
* gcc.dg/debug/dwarf2/pr80263.c: Suppress pubtypes output
|
||||
|
23
gcc/testsuite/gcc.dg/tree-ssa/evrp11.c
Normal file
23
gcc/testsuite/gcc.dg/tree-ssa/evrp11.c
Normal file
@ -0,0 +1,23 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -fdump-tree-evrp" } */
|
||||
|
||||
extern void link_error ();
|
||||
|
||||
void foo (int *x)
|
||||
{
|
||||
int *p = x + 1;
|
||||
if (p == 0)
|
||||
link_error ();
|
||||
}
|
||||
|
||||
void bar (char *x, int a)
|
||||
{
|
||||
if (a != 0)
|
||||
{
|
||||
char *p = x + a;
|
||||
if (p == 0)
|
||||
link_error ();
|
||||
}
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-not "link_error" "evrp" } } */
|
96
gcc/testsuite/gcc.target/alpha/pr86984.c
Normal file
96
gcc/testsuite/gcc.target/alpha/pr86984.c
Normal file
@ -0,0 +1,96 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -Wall -Wwrite-strings -Werror -fmerge-all-constants -fno-stack-protector -mieee -fdump-rtl-expand" } */
|
||||
|
||||
struct expression {
|
||||
unsigned long int num;
|
||||
};
|
||||
union YYSTYPE {
|
||||
unsigned long int num;
|
||||
struct expression *exp;
|
||||
};
|
||||
|
||||
typedef union YYSTYPE YYSTYPE;
|
||||
|
||||
struct expression * new_exp_0 (int);
|
||||
|
||||
union yyalloc {
|
||||
short yyss_alloc;
|
||||
};
|
||||
|
||||
static const signed char yypact[] = {
|
||||
-9, -9, -10, -10, -9, 8, 36, -10, 13, -10, -9, -9, -9, -9, -9, -9, -9, -10, 26, 41, 45, 18, -2, 14, -10, -9, 36 };
|
||||
static const unsigned char yydefact[] = {
|
||||
0, 0, 12, 11, 0, 0, 2, 10, 0, 1, 0, 0, 0, 0, 0, 0, 0, 13, 0, 4, 5, 6, 7, 8, 9, 0, 3 };
|
||||
|
||||
static const signed char yypgoto[3] = "\366\366\377";
|
||||
static const signed char yydefgoto[3] = "\377\005\006";
|
||||
|
||||
static const unsigned char yytable[] = {
|
||||
7, 1, 2, 8, 3, 4, 15, 16, 9, 18, 19, 20, 21, 22, 23, 24, 10, 11, 12, 13, 14, 15, 16, 16, 26, 14, 15, 16, 17, 10, 11, 12, 13, 14, 15, 16, 0, 0, 25, 10, 11, 12, 13, 14, 15, 16, 12, 13, 14, 15, 16, 13, 14, 15, 16 };
|
||||
|
||||
static const signed char yycheck[] = {
|
||||
1, 10, 11, 4, 13, 14, 8, 9, 0, 10, 11, 12, 13, 14, 15, 16, 3, 4, 5, 6, 7, 8, 9, 9, 25, 7, 8, 9, 15, 3, 4, 5, 6, 7, 8, 9, -1, -1, 12, 3, 4, 5, 6, 7, 8, 9, 5, 6, 7, 8, 9, 6, 7, 8, 9 };
|
||||
|
||||
static const unsigned char yyr1[] = {
|
||||
0, 16, 17, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18, 18 };
|
||||
|
||||
static const unsigned char yyr2[] = {
|
||||
0, 2, 1, 5, 3, 3, 3, 3, 3, 3, 2, 1, 1, 3 };
|
||||
|
||||
int __gettextparse (void)
|
||||
{
|
||||
int yystate = 0;
|
||||
short yyssa[200];
|
||||
short *yyss = yyss;
|
||||
short *yyssp = yyssa;
|
||||
YYSTYPE yyvsa[200];
|
||||
YYSTYPE *yyvsp = yyvsa;
|
||||
enum { yystacksize = 200 };
|
||||
int yylen = 0;
|
||||
goto yysetstate;
|
||||
yynewstate: yyssp++;
|
||||
yysetstate: *yyssp = yystate;
|
||||
|
||||
if (yyss + yystacksize - 1 <= yyssp)
|
||||
{
|
||||
long unsigned int yysize = yyssp - yyss + 1;
|
||||
{
|
||||
short *yyss1 = yyss;
|
||||
union yyalloc *yyptr = (union yyalloc *) __builtin_malloc ((yystacksize * (sizeof (short) + sizeof (YYSTYPE)) + (sizeof (union yyalloc) - 1)));
|
||||
if (!yyptr) return 0;
|
||||
__builtin_memcpy (&yyptr->yyss_alloc, yyss, yysize * sizeof *(yyss));
|
||||
yyss = &yyptr->yyss_alloc;
|
||||
if (yyss1 != yyssa) __builtin_free (yyss1);
|
||||
}
|
||||
if (yyss + yystacksize - 1 <= yyssp)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int yyn = yypact[yystate];
|
||||
if (yyn == -10)
|
||||
goto yydefault;
|
||||
|
||||
yyn = yytable[yyn];
|
||||
if (yyn <= 0)
|
||||
goto yyreduce;
|
||||
|
||||
yydefault: yyn = yydefact[yystate];
|
||||
yyreduce: yylen = yyr2[yyn];
|
||||
|
||||
YYSTYPE yyval;
|
||||
if (yyn == 12 && (yyval.exp = new_exp_0 (0)) != 0)
|
||||
(yyval.exp)->num = (yyvsp[0].num);
|
||||
|
||||
(yyvsp -= yylen, yyssp -= yylen);
|
||||
yyn = yyr1[yyn];
|
||||
yystate = yypgoto[yyn - 16] + *yyssp;
|
||||
if (0 <= yystate && yystate <= 54 && yycheck[yystate] == *yyssp)
|
||||
yystate = yytable[yystate];
|
||||
else
|
||||
yystate = yydefgoto[yyn - 16];
|
||||
|
||||
goto yynewstate;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-rtl-dump-not "const_int 230584300921" "expand" } } */
|
||||
/* { dg-final { scan-assembler-not "yypgoto\\+230584300921" } } */
|
@ -1437,6 +1437,7 @@ extract_range_from_binary_expr_1 (value_range *vr,
|
||||
&& code != PLUS_EXPR
|
||||
&& code != MINUS_EXPR
|
||||
&& code != RSHIFT_EXPR
|
||||
&& code != POINTER_PLUS_EXPR
|
||||
&& (vr0.type == VR_VARYING
|
||||
|| vr1.type == VR_VARYING
|
||||
|| vr0.type != vr1.type
|
||||
@ -1467,7 +1468,11 @@ extract_range_from_binary_expr_1 (value_range *vr,
|
||||
{
|
||||
/* For pointer types, we are really only interested in asserting
|
||||
whether the expression evaluates to non-NULL. */
|
||||
if (range_is_nonnull (&vr0) || range_is_nonnull (&vr1))
|
||||
if (range_is_nonnull (&vr0)
|
||||
|| range_is_nonnull (&vr1)
|
||||
|| (vr1.type == VR_RANGE
|
||||
&& !symbolic_range_p (&vr1)
|
||||
&& !range_includes_zero_p (vr1.min, vr1.max)))
|
||||
set_value_range_to_nonnull (vr, expr_type);
|
||||
else if (range_is_null (&vr0) && range_is_null (&vr1))
|
||||
set_value_range_to_null (vr, expr_type);
|
||||
|
@ -1,5 +1,43 @@
|
||||
2018-08-20 Nathan Sidwell <nathan@acm.org>
|
||||
|
||||
* include/cpplib.h (NODE_BUILTIN, NODE_MACRO_ARG): Delete.
|
||||
Renumber others.
|
||||
(enum node_type): Replace NT_MACRO with NT_USER_MACRO,
|
||||
NT_BUILTIN_MACRO, NT_MACRO_ARG. Delete NT_ASSERTION.
|
||||
(NTV_MACRO, NTV_ANSWER, NTV_BUILTIN, NTV_ARGUMENT, NTV_NONE):
|
||||
Delete.
|
||||
(CPP_HASHNODE_VALUE_IDX): Delete.
|
||||
(union _cpp_hashnode_value): GTY tag from enum node_type directly.
|
||||
(struct cpp_hashnode): Adjust GTY desc for value field.
|
||||
(cpp_user_macro_p, cpp_builtin_macro_p, cpp_macro_p): Adjust.
|
||||
* directives.c (undefine_macros): Clear value.anwers, adjust flag
|
||||
clearing.
|
||||
(_cpp_test_assertion): No need to check NT_ASSERTION.
|
||||
(do_assert, do_unassert): Likewise.
|
||||
* init.c (cpp_init_special_builtins): Set type not flags.
|
||||
* macro.c (struct macro_arg_saved_data): Add type field.
|
||||
(cpp_get_token_1): Check type not NT_VOID.
|
||||
(_cpp_free_definition): Adjust flag clearing. Nullify
|
||||
value.answers.
|
||||
(_cpp_save_parameter, _cpp_unsave_parameters): Save and restore
|
||||
type.
|
||||
(lex_expansion_token): Check type not flags.
|
||||
(_cpp_create_definition): Set type to NT_USER_MACRO.
|
||||
(_cpp_notify_macro_use): Adjust type checking.
|
||||
* pch.c (write_macdef, count_defs, write_defs, cpp_valid_state)
|
||||
(save_macros): Adjust node type/flag handling.
|
||||
* traditional.c (_cpp_scan_out_logical_line): Check type not flags.
|
||||
|
||||
* directives.c (do_undef): Use cpp_macro_p & cpp_builtin_macro_p.
|
||||
* include/cpplib.h (enum cpp_macro_kind): Remove trailing comma.
|
||||
(cpp_fun_like_macro_p): Make inline, define.
|
||||
* macro.c (cpp_define_lazily): Use UCHAR_MAX.
|
||||
(cpp_fun_like_macro_p): Delete.
|
||||
|
||||
* Makefile.in (TAGS_SOURCES): Remove cpp-id-data.h.
|
||||
* include/cpp-id-data.h: Delete.
|
||||
* internal.h: Include cpplib.h not cpp-id-data.h.
|
||||
|
||||
* include/cpp-id-data.h (struct answer): Delete.
|
||||
* include/cpplib.h (struct answer): Don't forward-declare.
|
||||
(enum cpp_macro_kind): Add cmk_assert.
|
||||
|
@ -695,8 +695,8 @@ undefine_macros (cpp_reader *pfile ATTRIBUTE_UNUSED, cpp_hashnode *h,
|
||||
/* Body of _cpp_free_definition inlined here for speed.
|
||||
Macros and assertions no longer have anything to free. */
|
||||
h->type = NT_VOID;
|
||||
h->flags &= ~(NODE_POISONED|NODE_DISABLED|NODE_USED);
|
||||
h->value.answers = NULL;
|
||||
h->flags &= ~(NODE_POISONED|NODE_DISABLED|NODE_USED);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -2218,9 +2218,10 @@ parse_answer (cpp_reader *pfile, int type, source_location pred_loc,
|
||||
}
|
||||
|
||||
/* Parses an assertion directive of type TYPE, returning a pointer to
|
||||
the hash node of the predicate, or 0 on error. If an answer was
|
||||
supplied, it is placed in EXP_PTR & EXP_COUNT, which is otherwise
|
||||
set to 0. */
|
||||
the hash node of the predicate, or 0 on error. The node is
|
||||
guaranteed to be disjoint from the macro namespace, so can only
|
||||
have type 'NT_VOID'. If an answer was supplied, it is placed in
|
||||
*ANSWER_PTR, which is otherwise set to 0. */
|
||||
static cpp_hashnode *
|
||||
parse_assertion (cpp_reader *pfile, int type, cpp_macro **answer_ptr)
|
||||
{
|
||||
|
@ -675,7 +675,7 @@ struct cpp_dir
|
||||
enum cpp_macro_kind {
|
||||
cmk_macro, /* An ISO macro (token expansion). */
|
||||
cmk_assert, /* An assertion. */
|
||||
cmk_traditional, /* A traditional macro (text expansion). */
|
||||
cmk_traditional /* A traditional macro (text expansion). */
|
||||
};
|
||||
|
||||
/* Each macro definition is recorded in a cpp_macro structure.
|
||||
@ -743,6 +743,13 @@ struct GTY(()) cpp_macro {
|
||||
} GTY ((desc ("%1.kind == cmk_traditional"))) exp;
|
||||
};
|
||||
|
||||
/* Poisoned identifiers are flagged NODE_POISONED. NODE_OPERATOR (C++
|
||||
only) indicates an identifier that behaves like an operator such as
|
||||
"xor". NODE_DIAGNOSTIC is for speed in lex_token: it indicates a
|
||||
diagnostic may be required for this node. Currently this only
|
||||
applies to __VA_ARGS__, poisoned identifiers, and -Wc++-compat
|
||||
warnings about NODE_OPERATOR. */
|
||||
|
||||
/* Hash node flags. */
|
||||
#define NODE_OPERATOR (1 << 0) /* C++ named operator. */
|
||||
#define NODE_POISONED (1 << 1) /* Poisoned identifier. */
|
||||
@ -759,7 +766,8 @@ enum node_type
|
||||
NT_VOID = 0, /* Maybe an assert? */
|
||||
NT_MACRO_ARG, /* A macro arg. */
|
||||
NT_USER_MACRO, /* A user macro. */
|
||||
NT_BUILTIN_MACRO /* A builtin macro. */
|
||||
NT_BUILTIN_MACRO, /* A builtin macro. */
|
||||
NT_MACRO_MASK = NT_USER_MACRO /* Mask for either macro kind. */
|
||||
};
|
||||
|
||||
/* Different flavors of builtin macro. _Pragma is an operator, but we
|
||||
@ -945,7 +953,7 @@ inline bool cpp_builtin_macro_p (const cpp_hashnode *node)
|
||||
}
|
||||
inline bool cpp_macro_p (const cpp_hashnode *node)
|
||||
{
|
||||
return node->type & NT_USER_MACRO;
|
||||
return node->type & NT_MACRO_MASK;
|
||||
}
|
||||
|
||||
/* Returns true if NODE is a function-like user macro. */
|
||||
|
@ -3041,8 +3041,8 @@ _cpp_free_definition (cpp_hashnode *h)
|
||||
{
|
||||
/* Macros and assertions no longer have anything to free. */
|
||||
h->type = NT_VOID;
|
||||
h->value.answers = NULL;
|
||||
h->flags &= ~(NODE_DISABLED | NODE_USED);
|
||||
h->value.macro = NULL;
|
||||
}
|
||||
|
||||
/* Save parameter NODE (spelling SPELLING) to the parameter list of
|
||||
@ -3554,7 +3554,7 @@ cpp_define_lazily (cpp_reader *pfile, cpp_hashnode *node, unsigned num)
|
||||
{
|
||||
cpp_macro *macro = node->value.macro;
|
||||
|
||||
gcc_checking_assert (pfile->cb.user_lazy_macro && macro && num < 255);
|
||||
gcc_checking_assert (pfile->cb.user_lazy_macro && macro && num < UCHAR_MAX);
|
||||
|
||||
macro->lazy = num + 1;
|
||||
}
|
||||
|
@ -1,5 +1,19 @@
|
||||
2018-08-20 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR libstdc++/86963
|
||||
* include/std/tuple (_Tuple_impl::operator=): Define as deleted.
|
||||
(_Tuple_impl::_M_assign): New functions to perform assignment instead
|
||||
of assignment operators.
|
||||
(_Tuple_impl::_M_swap): Remove exception specification.
|
||||
(_Tuple_impl<_Idx, _Head>): Likewise.
|
||||
(_TC::_NonNestedTuple, _TC::_NotSameTuple): Use __remove_cvref_t.
|
||||
(__tuple_base): Remove.
|
||||
(tuple, tuple<_T1, _T2>): Remove inheritance from __tuple_base.
|
||||
(tuple::operator=, tuple<_T1, _T2>::operator=): Call _M_assign.
|
||||
(tuple::swap, tuple<_T1, _T2>::swap): Define exception specification
|
||||
using __is_nothrow_swappable.
|
||||
(tuple<_T1, _T2>::tuple(_U1&&, _U2&&)): Use __remove_cvref_t.
|
||||
|
||||
* include/std/optional (_Optional_payload): Use variable templates
|
||||
for conditions in default template arguments and exception
|
||||
specifications.
|
||||
|
@ -219,6 +219,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
constexpr _Tuple_impl(const _Tuple_impl&) = default;
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 2729. Missing SFINAE on std::pair::operator=
|
||||
_Tuple_impl& operator=(const _Tuple_impl&) = delete;
|
||||
|
||||
constexpr
|
||||
_Tuple_impl(_Tuple_impl&& __in)
|
||||
noexcept(__and_<is_nothrow_move_constructible<_Head>,
|
||||
@ -288,49 +292,28 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
std::forward<_UHead>
|
||||
(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { }
|
||||
|
||||
_Tuple_impl&
|
||||
operator=(const _Tuple_impl& __in)
|
||||
{
|
||||
_M_head(*this) = _M_head(__in);
|
||||
_M_tail(*this) = _M_tail(__in);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_Tuple_impl&
|
||||
operator=(_Tuple_impl&& __in)
|
||||
noexcept(__and_<is_nothrow_move_assignable<_Head>,
|
||||
is_nothrow_move_assignable<_Inherited>>::value)
|
||||
{
|
||||
_M_head(*this) = std::forward<_Head>(_M_head(__in));
|
||||
_M_tail(*this) = std::move(_M_tail(__in));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename... _UElements>
|
||||
_Tuple_impl&
|
||||
operator=(const _Tuple_impl<_Idx, _UElements...>& __in)
|
||||
void
|
||||
_M_assign(const _Tuple_impl<_Idx, _UElements...>& __in)
|
||||
{
|
||||
_M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in);
|
||||
_M_tail(*this) = _Tuple_impl<_Idx, _UElements...>::_M_tail(__in);
|
||||
return *this;
|
||||
_M_tail(*this)._M_assign(
|
||||
_Tuple_impl<_Idx, _UElements...>::_M_tail(__in));
|
||||
}
|
||||
|
||||
template<typename _UHead, typename... _UTails>
|
||||
_Tuple_impl&
|
||||
operator=(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
|
||||
void
|
||||
_M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in)
|
||||
{
|
||||
_M_head(*this) = std::forward<_UHead>
|
||||
(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in));
|
||||
_M_tail(*this) = std::move
|
||||
(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in));
|
||||
return *this;
|
||||
_M_tail(*this)._M_assign(
|
||||
std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)));
|
||||
}
|
||||
|
||||
protected:
|
||||
void
|
||||
_M_swap(_Tuple_impl& __in)
|
||||
noexcept(__is_nothrow_swappable<_Head>::value
|
||||
&& noexcept(_M_tail(__in)._M_swap(_M_tail(__in))))
|
||||
{
|
||||
using std::swap;
|
||||
swap(_M_head(*this), _M_head(__in));
|
||||
@ -367,6 +350,10 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
constexpr _Tuple_impl(const _Tuple_impl&) = default;
|
||||
|
||||
// _GLIBCXX_RESOLVE_LIB_DEFECTS
|
||||
// 2729. Missing SFINAE on std::pair::operator=
|
||||
_Tuple_impl& operator=(const _Tuple_impl&) = delete;
|
||||
|
||||
constexpr
|
||||
_Tuple_impl(_Tuple_impl&& __in)
|
||||
noexcept(is_nothrow_move_constructible<_Head>::value)
|
||||
@ -420,42 +407,24 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)))
|
||||
{ }
|
||||
|
||||
_Tuple_impl&
|
||||
operator=(const _Tuple_impl& __in)
|
||||
{
|
||||
_M_head(*this) = _M_head(__in);
|
||||
return *this;
|
||||
}
|
||||
|
||||
_Tuple_impl&
|
||||
operator=(_Tuple_impl&& __in)
|
||||
noexcept(is_nothrow_move_assignable<_Head>::value)
|
||||
{
|
||||
_M_head(*this) = std::forward<_Head>(_M_head(__in));
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename _UHead>
|
||||
_Tuple_impl&
|
||||
operator=(const _Tuple_impl<_Idx, _UHead>& __in)
|
||||
void
|
||||
_M_assign(const _Tuple_impl<_Idx, _UHead>& __in)
|
||||
{
|
||||
_M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in);
|
||||
return *this;
|
||||
}
|
||||
|
||||
template<typename _UHead>
|
||||
_Tuple_impl&
|
||||
operator=(_Tuple_impl<_Idx, _UHead>&& __in)
|
||||
void
|
||||
_M_assign(_Tuple_impl<_Idx, _UHead>&& __in)
|
||||
{
|
||||
_M_head(*this)
|
||||
= std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in));
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
void
|
||||
_M_swap(_Tuple_impl& __in)
|
||||
noexcept(__is_nothrow_swappable<_Head>::value)
|
||||
{
|
||||
using std::swap;
|
||||
swap(_M_head(*this), _M_head(__in));
|
||||
@ -495,20 +464,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
static constexpr bool _NonNestedTuple()
|
||||
{
|
||||
return __and_<__not_<is_same<tuple<_Elements...>,
|
||||
typename remove_cv<
|
||||
typename remove_reference<_SrcTuple>::type
|
||||
>::type>>,
|
||||
__remove_cvref_t<_SrcTuple>>>,
|
||||
__not_<is_convertible<_SrcTuple, _Elements...>>,
|
||||
__not_<is_constructible<_Elements..., _SrcTuple>>
|
||||
>::value;
|
||||
}
|
||||
|
||||
template<typename... _UElements>
|
||||
static constexpr bool _NotSameTuple()
|
||||
{
|
||||
return __not_<is_same<tuple<_Elements...>,
|
||||
typename remove_const<
|
||||
typename remove_reference<_UElements...>::type
|
||||
>::type>>::value;
|
||||
__remove_cvref_t<_UElements>...>>::value;
|
||||
}
|
||||
};
|
||||
|
||||
@ -544,30 +510,17 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename... _UElements>
|
||||
static constexpr bool _NotSameTuple()
|
||||
{
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
// The tag parameter ensures that in nested tuples each __tuple_base
|
||||
// is a different type and can use the empty base-class optimisation.
|
||||
template<typename _Tag>
|
||||
class __tuple_base
|
||||
{
|
||||
template<typename...> friend struct tuple;
|
||||
__tuple_base() = default;
|
||||
~__tuple_base() = default;
|
||||
__tuple_base(const __tuple_base&) = default;
|
||||
__tuple_base& operator=(const __tuple_base&) = delete;
|
||||
};
|
||||
|
||||
/// Primary class template, tuple
|
||||
template<typename... _Elements>
|
||||
class tuple
|
||||
: public _Tuple_impl<0, _Elements...>,
|
||||
private __tuple_base<tuple<_Elements...>>
|
||||
class tuple : public _Tuple_impl<0, _Elements...>
|
||||
{
|
||||
typedef _Tuple_impl<0, _Elements...> _Inherited;
|
||||
|
||||
@ -858,13 +811,15 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
static_cast<_Tuple_impl<0, _UElements...>&&>(__in))
|
||||
{ }
|
||||
|
||||
// tuple assignment
|
||||
|
||||
tuple&
|
||||
operator=(typename conditional<__assignable<const _Elements&...>(),
|
||||
const tuple&,
|
||||
const __nonesuch_no_braces&>::type __in)
|
||||
noexcept(__nothrow_assignable<const _Elements&...>())
|
||||
{
|
||||
static_cast<_Inherited&>(*this) = __in;
|
||||
this->_M_assign(__in);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -874,7 +829,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
__nonesuch_no_braces&&>::type __in)
|
||||
noexcept(__nothrow_assignable<_Elements...>())
|
||||
{
|
||||
static_cast<_Inherited&>(*this) = std::move(__in);
|
||||
this->_M_assign(std::move(__in));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -883,7 +838,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
operator=(const tuple<_UElements...>& __in)
|
||||
noexcept(__nothrow_assignable<const _UElements&...>())
|
||||
{
|
||||
static_cast<_Inherited&>(*this) = __in;
|
||||
this->_M_assign(__in);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -892,13 +847,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
operator=(tuple<_UElements...>&& __in)
|
||||
noexcept(__nothrow_assignable<_UElements...>())
|
||||
{
|
||||
static_cast<_Inherited&>(*this) = std::move(__in);
|
||||
this->_M_assign(std::move(__in));
|
||||
return *this;
|
||||
}
|
||||
|
||||
// tuple swap
|
||||
void
|
||||
swap(tuple& __in)
|
||||
noexcept(noexcept(__in._M_swap(__in)))
|
||||
noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value)
|
||||
{ _Inherited::_M_swap(__in); }
|
||||
};
|
||||
|
||||
@ -934,9 +890,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
/// Partial specialization, 2-element tuple.
|
||||
/// Includes construction and assignment from a pair.
|
||||
template<typename _T1, typename _T2>
|
||||
class tuple<_T1, _T2>
|
||||
: public _Tuple_impl<0, _T1, _T2>,
|
||||
private __tuple_base<tuple<_T1, _T2>>
|
||||
class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2>
|
||||
{
|
||||
typedef _Tuple_impl<0, _T1, _T2> _Inherited;
|
||||
|
||||
@ -1009,8 +963,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
_MoveConstructibleTuple<_U1, _U2>()
|
||||
&& _TMC::template
|
||||
_ImplicitlyMoveConvertibleTuple<_U1, _U2>()
|
||||
&& !is_same<typename decay<_U1>::type,
|
||||
allocator_arg_t>::value,
|
||||
&& !is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value,
|
||||
bool>::type = true>
|
||||
constexpr tuple(_U1&& __a1, _U2&& __a2)
|
||||
: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
|
||||
@ -1020,8 +973,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
_MoveConstructibleTuple<_U1, _U2>()
|
||||
&& !_TMC::template
|
||||
_ImplicitlyMoveConvertibleTuple<_U1, _U2>()
|
||||
&& !is_same<typename decay<_U1>::type,
|
||||
allocator_arg_t>::value,
|
||||
&& !is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value,
|
||||
bool>::type = false>
|
||||
explicit constexpr tuple(_U1&& __a1, _U2&& __a2)
|
||||
: _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { }
|
||||
@ -1255,7 +1207,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
const __nonesuch_no_braces&>::type __in)
|
||||
noexcept(__nothrow_assignable<const _T1&, const _T2&>())
|
||||
{
|
||||
static_cast<_Inherited&>(*this) = __in;
|
||||
this->_M_assign(__in);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -1265,7 +1217,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
__nonesuch_no_braces&&>::type __in)
|
||||
noexcept(__nothrow_assignable<_T1, _T2>())
|
||||
{
|
||||
static_cast<_Inherited&>(*this) = std::move(__in);
|
||||
this->_M_assign(std::move(__in));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -1274,7 +1226,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
operator=(const tuple<_U1, _U2>& __in)
|
||||
noexcept(__nothrow_assignable<const _U1&, const _U2&>())
|
||||
{
|
||||
static_cast<_Inherited&>(*this) = __in;
|
||||
this->_M_assign(__in);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -1283,7 +1235,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
operator=(tuple<_U1, _U2>&& __in)
|
||||
noexcept(__nothrow_assignable<_U1, _U2>())
|
||||
{
|
||||
static_cast<_Inherited&>(*this) = std::move(__in);
|
||||
this->_M_assign(std::move(__in));
|
||||
return *this;
|
||||
}
|
||||
|
||||
@ -1309,7 +1261,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||
|
||||
void
|
||||
swap(tuple& __in)
|
||||
noexcept(noexcept(__in._M_swap(__in)))
|
||||
noexcept(__and_<__is_nothrow_swappable<_T1>,
|
||||
__is_nothrow_swappable<_T2>>::value)
|
||||
{ _Inherited::_M_swap(__in); }
|
||||
};
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user