From: Jason Merrill Date: Tue, 15 Nov 2016 05:22:28 +0000 (-0500) Subject: Various C++17 decomposition fixes. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=47e5d7ccf12c5d11abdd18e8e9089735e4fd3d05;p=gcc.git Various C++17 decomposition fixes. * tree.c (bitfield_p): New. * cp-tree.h: Declare it. * typeck.c (cxx_sizeof_expr, cxx_alignof_expr) (cp_build_addr_expr_1): Use it instead of DECL_C_BIT_FIELD. * decl.c (cp_finish_decomp): Look through reference. Always SET_DECL_DECOMPOSITION_P. * semantics.c (finish_decltype_type): Adjust decomposition handling. From-SVN: r242408 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 1a92ffa0e4b..e9dd17c5d36 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,13 @@ +2016-11-14 Jason Merrill + + * tree.c (bitfield_p): New. + * cp-tree.h: Declare it. + * typeck.c (cxx_sizeof_expr, cxx_alignof_expr) + (cp_build_addr_expr_1): Use it instead of DECL_C_BIT_FIELD. + * decl.c (cp_finish_decomp): Look through reference. Always + SET_DECL_DECOMPOSITION_P. + * semantics.c (finish_decltype_type): Adjust decomposition handling. + 2016-11-13 Jakub Jelinek Jason Merrill diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 8c2dbe1fba6..edcd3b47fa8 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -6572,6 +6572,7 @@ extern cp_lvalue_kind lvalue_kind (const_tree); extern bool glvalue_p (const_tree); extern bool obvalue_p (const_tree); extern bool xvalue_p (const_tree); +extern bool bitfield_p (const_tree); extern tree cp_stabilize_reference (tree); extern bool builtin_valid_in_constant_expr_p (const_tree); extern tree build_min (enum tree_code, tree, ...); diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index f142c1fb931..2af95a7568d 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -7350,18 +7350,23 @@ cp_finish_decomp (tree decl, tree first, unsigned int count) for (unsigned int i = 0; i < count; i++, d = DECL_CHAIN (d)) { v[count - i - 1] = d; - if (processing_template_decl) - { - retrofit_lang_decl (d); - SET_DECL_DECOMPOSITION_P (d); - } + retrofit_lang_decl (d); + SET_DECL_DECOMPOSITION_P (d); } tree type = TREE_TYPE (decl); - tree eltype = NULL_TREE; + tree dexp = decl; + if (TREE_CODE (type) == REFERENCE_TYPE) - type = TREE_TYPE (type); + { + /* If e is a constant reference, use the referent directly. */ + if (DECL_INITIAL (decl)) + dexp = DECL_INITIAL (decl); + dexp = convert_from_reference (dexp); + type = TREE_TYPE (type); + } + tree eltype = NULL_TREE; unsigned HOST_WIDE_INT eltscnt = 0; if (TREE_CODE (type) == ARRAY_TYPE) { @@ -7391,7 +7396,7 @@ cp_finish_decomp (tree decl, tree first, unsigned int count) { TREE_TYPE (v[i]) = eltype; layout_decl (v[i], 0); - tree t = convert_from_reference (decl); + tree t = dexp; t = build4_loc (DECL_SOURCE_LOCATION (v[i]), ARRAY_REF, eltype, t, size_int (i), NULL_TREE, NULL_TREE); @@ -7410,7 +7415,7 @@ cp_finish_decomp (tree decl, tree first, unsigned int count) { TREE_TYPE (v[i]) = eltype; layout_decl (v[i], 0); - tree t = convert_from_reference (decl); + tree t = dexp; t = build1_loc (DECL_SOURCE_LOCATION (v[i]), i ? IMAGPART_EXPR : REALPART_EXPR, eltype, t); @@ -7428,7 +7433,7 @@ cp_finish_decomp (tree decl, tree first, unsigned int count) { TREE_TYPE (v[i]) = eltype; layout_decl (v[i], 0); - tree t = convert_from_reference (decl); + tree t = dexp; convert_vector_to_array_for_subscript (DECL_SOURCE_LOCATION (v[i]), &t, size_int (i)); t = build4_loc (DECL_SOURCE_LOCATION (v[i]), ARRAY_REF, @@ -7501,7 +7506,7 @@ cp_finish_decomp (tree decl, tree first, unsigned int count) eltscnt++; if (count != eltscnt) goto cnt_mismatch; - tree t = convert_from_reference (decl); + tree t = dexp; if (type != btype) { t = convert_to_base (t, btype, /*check_access*/true, diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c index 0164f2e5c74..29f52333a94 100644 --- a/gcc/cp/semantics.c +++ b/gcc/cp/semantics.c @@ -8873,8 +8873,13 @@ finish_decltype_type (tree expr, bool id_expression_or_member_access_p, if (identifier_p (expr)) expr = lookup_name (expr); - if (VAR_P (expr) && DECL_HAS_VALUE_EXPR_P (expr)) - expr = DECL_VALUE_EXPR (expr); + /* The decltype rules for decomposition are different from the rules for + member access; in particular, the decomposition decl gets + cv-qualifiers from the aggregate object, whereas decltype of a member + access expr ignores the object. */ + if (VAR_P (expr) && DECL_DECOMPOSITION_P (expr) + && DECL_HAS_VALUE_EXPR_P (expr)) + return unlowered_expr_type (DECL_VALUE_EXPR (expr)); if (INDIRECT_REF_P (expr)) /* This can happen when the expression is, e.g., "a.b". Just diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c index c59543768a8..d1dd7c40680 100644 --- a/gcc/cp/tree.c +++ b/gcc/cp/tree.c @@ -305,6 +305,14 @@ xvalue_p (const_tree ref) return (lvalue_kind (ref) == clk_rvalueref); } +/* True if REF is a bit-field. */ + +bool +bitfield_p (const_tree ref) +{ + return (lvalue_kind (ref) & clk_bitfield); +} + /* C++-specific version of stabilize_reference. */ tree diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c index 2d8b7b10440..6f9ad0ed3cb 100644 --- a/gcc/cp/typeck.c +++ b/gcc/cp/typeck.c @@ -1650,9 +1650,7 @@ cxx_sizeof_expr (tree e, tsubst_flags_t complain) e = mark_type_use (e); - if (TREE_CODE (e) == COMPONENT_REF - && TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL - && DECL_C_BIT_FIELD (TREE_OPERAND (e, 1))) + if (bitfield_p (e)) { if (complain & tf_error) error ("invalid application of % to a bit-field"); @@ -1709,9 +1707,7 @@ cxx_alignof_expr (tree e, tsubst_flags_t complain) if (VAR_P (e)) t = size_int (DECL_ALIGN_UNIT (e)); - else if (TREE_CODE (e) == COMPONENT_REF - && TREE_CODE (TREE_OPERAND (e, 1)) == FIELD_DECL - && DECL_C_BIT_FIELD (TREE_OPERAND (e, 1))) + else if (bitfield_p (e)) { if (complain & tf_error) error ("invalid application of %<__alignof%> to a bit-field"); @@ -5751,6 +5747,13 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) if (argtype != error_mark_node) argtype = build_pointer_type (argtype); + if (bitfield_p (arg)) + { + if (complain & tf_error) + error ("attempt to take address of bit-field"); + return error_mark_node; + } + /* In a template, we are processing a non-dependent expression so we can just form an ADDR_EXPR with the correct type. */ if (processing_template_decl || TREE_CODE (arg) != COMPONENT_REF) @@ -5775,13 +5778,6 @@ cp_build_addr_expr_1 (tree arg, bool strict_lvalue, tsubst_flags_t complain) val = build2 (COMPOUND_EXPR, TREE_TYPE (val), TREE_OPERAND (arg, 0), val); } - else if (DECL_C_BIT_FIELD (TREE_OPERAND (arg, 1))) - { - if (complain & tf_error) - error ("attempt to take address of bit-field structure member %qD", - TREE_OPERAND (arg, 1)); - return error_mark_node; - } else { tree object = TREE_OPERAND (arg, 0); diff --git a/gcc/testsuite/g++.dg/cpp0x/addressof2.C b/gcc/testsuite/g++.dg/cpp0x/addressof2.C index 28b71d83b3c..bf218cca481 100644 --- a/gcc/testsuite/g++.dg/cpp0x/addressof2.C +++ b/gcc/testsuite/g++.dg/cpp0x/addressof2.C @@ -15,7 +15,7 @@ struct S { int s : 5; int t; void foo (); } s; auto c = __builtin_addressof (s); auto d = addressof (s); -auto e = __builtin_addressof (s.s); // { dg-error "attempt to take address of bit-field structure member" } +auto e = __builtin_addressof (s.s); // { dg-error "attempt to take address of bit-field" } auto f = addressof (s.s); // { dg-error "cannot bind bitfield" } auto g = __builtin_addressof (S{}); // { dg-error "taking address of temporary" } auto h = addressof (S{}); // { dg-error "cannot bind non-const lvalue reference of type" } diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp-bitfield1.C b/gcc/testsuite/g++.dg/cpp1z/decomp-bitfield1.C new file mode 100644 index 00000000000..73edc871320 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/decomp-bitfield1.C @@ -0,0 +1,19 @@ +// Test of bit-fields. +// { dg-options -std=c++1z } + +struct A { long i: 2; } a; + +template struct same_type; +template struct same_type {}; + +void f() +{ + auto [ x ] = a; + + same_type{}; + same_type{}; + + long &r = x; // { dg-error "bit" } + &x; // { dg-error "bit" } + sizeof(x); // { dg-error "bit" } +} diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp-constexpr1.C b/gcc/testsuite/g++.dg/cpp1z/decomp-constexpr1.C new file mode 100644 index 00000000000..722ff76de19 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/decomp-constexpr1.C @@ -0,0 +1,18 @@ +// Test for reference address comparison in constant expression. +// { dg-options -std=c++1z } + +int i[2]; +struct A { int i, j; } a; + +void f() +{ + { + auto& [ x, y ] = i; + static_assert (&x == &i[0]); + } + + { + auto& [ x, y ] = a; + static_assert (&x == &a.i && &y != &a.i); + } +} diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp10.C b/gcc/testsuite/g++.dg/cpp1z/decomp10.C index 316cea98811..2abbaaebe9a 100644 --- a/gcc/testsuite/g++.dg/cpp1z/decomp10.C +++ b/gcc/testsuite/g++.dg/cpp1z/decomp10.C @@ -31,18 +31,15 @@ struct A4 { template int& get() { return ar[I]; } } a4; template<> struct std::tuple_size { enum { value = 3 }; }; -template void f4() { auto [ x, y, z ] = a4; } // { dg-error "tuple_element" } struct A5 { } a5; template int& get(A5&& a); template<> struct std::tuple_size { enum { value = 3 }; }; -template void f5() { auto [ x, y, z ] = a5; } // { dg-error "tuple_element" } struct A6 { } a6; template int& get(A6&& a); template<> struct std::tuple_size { enum { value = 3 }; }; template<> struct std::tuple_element<0, A6> { }; -template void f6() { auto [ x, y, z ] = a6; } // { dg-error "no type named .type" } diff --git a/gcc/testsuite/g++.dg/cpp1z/decomp11.C b/gcc/testsuite/g++.dg/cpp1z/decomp11.C new file mode 100644 index 00000000000..9c8aaa48b4a --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/decomp11.C @@ -0,0 +1,51 @@ +// Test for decltype of direct decomposition. +// { dg-options -std=c++1z } + +template struct same_type; +template struct same_type {}; + +struct A { + int i; + const int ci = 42; + mutable int mi; + int& r = i; + const int& cr = ci; +} a; + +void f() { + auto [i,ci,mi,r,cr] = a; + + same_type{}; + same_type{}; + same_type{}; + same_type{}; + same_type{}; +} +void frr() { + auto &&[i,ci,mi,r,cr] = a; + + same_type{}; + same_type{}; + same_type{}; + same_type{}; + same_type{}; +} +void fc() { + const auto [i,ci,mi,r,cr] = a; + + same_type{}; + same_type{}; + same_type{}; + same_type{}; + same_type{}; +} +void frc() { + const A ca{}; + auto &[i,ci,mi,r,cr] = ca; + + same_type{}; + same_type{}; + same_type{}; + same_type{}; + same_type{}; +}