diff options
author | Nathan Sidwell <nathan@gcc.gnu.org> | 2018-08-20 17:20:30 +0000 |
---|---|---|
committer | Nathan Sidwell <nathan@gcc.gnu.org> | 2018-08-20 17:20:30 +0000 |
commit | c014d996322a3f44f356aa00fd5dd971e2018ab8 (patch) | |
tree | e48659c66599c015c4c556d7228de62ab7e40dd2 | |
parent | 942c7776a2bc34113bbf5d749102401d330dd258 (diff) | |
parent | a570d97f5b8612ad2756333e5f21098be64057df (diff) | |
download | gcc-c014d996322a3f44f356aa00fd5dd971e2018ab8.zip gcc-c014d996322a3f44f356aa00fd5dd971e2018ab8.tar.gz gcc-c014d996322a3f44f356aa00fd5dd971e2018ab8.tar.bz2 |
Merge trunk r263667.
From-SVN: r263668
-rw-r--r-- | ChangeLog.name-lookup | 2 | ||||
-rw-r--r-- | gcc/ChangeLog | 33 | ||||
-rw-r--r-- | gcc/config/alpha/alpha.h | 2 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 32 | ||||
-rw-r--r-- | gcc/expr.c | 11 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/testsuite/gcc.dg/tree-ssa/evrp11.c | 23 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/alpha/pr86984.c | 96 | ||||
-rw-r--r-- | gcc/tree-vrp.c | 7 | ||||
-rw-r--r-- | libcpp/ChangeLog | 38 | ||||
-rw-r--r-- | libcpp/directives.c | 9 | ||||
-rw-r--r-- | libcpp/include/cpplib.h | 14 | ||||
-rw-r--r-- | libcpp/macro.c | 4 | ||||
-rw-r--r-- | libstdc++-v3/ChangeLog | 14 | ||||
-rw-r--r-- | libstdc++-v3/include/std/tuple | 133 |
15 files changed, 315 insertions, 113 deletions
diff --git a/ChangeLog.name-lookup b/ChangeLog.name-lookup index 389ab08..fd7fe12 100644 --- a/ChangeLog.name-lookup +++ b/ChangeLog.name-lookup @@ -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> diff --git a/gcc/ChangeLog b/gcc/ChangeLog index ec1fb24..b1d0889 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -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 diff --git a/gcc/config/alpha/alpha.h b/gcc/config/alpha/alpha.h index 6802ef3..aa1de8a 100644 --- a/gcc/config/alpha/alpha.h +++ b/gcc/config/alpha/alpha.h @@ -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. diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 236f199..b80c909 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -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); } @@ -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), diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index e89f4a4..a0620b1 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -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 diff --git a/gcc/testsuite/gcc.dg/tree-ssa/evrp11.c b/gcc/testsuite/gcc.dg/tree-ssa/evrp11.c new file mode 100644 index 0000000..f1373bd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/evrp11.c @@ -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" } } */ diff --git a/gcc/testsuite/gcc.target/alpha/pr86984.c b/gcc/testsuite/gcc.target/alpha/pr86984.c new file mode 100644 index 0000000..f6a98d4 --- /dev/null +++ b/gcc/testsuite/gcc.target/alpha/pr86984.c @@ -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" } } */ diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index d553a25..2ddb0c2 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -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); diff --git a/libcpp/ChangeLog b/libcpp/ChangeLog index 2e347db..8998c0d 100644 --- a/libcpp/ChangeLog +++ b/libcpp/ChangeLog @@ -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. diff --git a/libcpp/directives.c b/libcpp/directives.c index 3425138..f7c460d 100644 --- a/libcpp/directives.c +++ b/libcpp/directives.c @@ -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) { diff --git a/libcpp/include/cpplib.h b/libcpp/include/cpplib.h index c9524a3..8b84fd7 100644 --- a/libcpp/include/cpplib.h +++ b/libcpp/include/cpplib.h @@ -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. */ diff --git a/libcpp/macro.c b/libcpp/macro.c index 8323d38..3629e83 100644 --- a/libcpp/macro.c +++ b/libcpp/macro.c @@ -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; } diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 39855d9..4845595 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -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. diff --git a/libstdc++-v3/include/std/tuple b/libstdc++-v3/include/std/tuple index 955b853..56b97c2 100644 --- a/libstdc++-v3/include/std/tuple +++ b/libstdc++-v3/include/std/tuple @@ -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); } }; |