* 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
+2016-11-14 Jason Merrill <jason@redhat.com>
+
+ * 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 <jakub@redhat.com>
Jason Merrill <jason@redhat.com>
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, ...);
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)
{
{
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);
{
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);
{
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,
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,
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
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
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 %<sizeof%> to a bit-field");
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");
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)
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);
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" }
--- /dev/null
+// Test of bit-fields.
+// { dg-options -std=c++1z }
+
+struct A { long i: 2; } a;
+
+template <class,class> struct same_type;
+template <class T> struct same_type<T,T> {};
+
+void f()
+{
+ auto [ x ] = a;
+
+ same_type<decltype(x),long>{};
+ same_type<decltype(x+x),int>{};
+
+ long &r = x; // { dg-error "bit" }
+ &x; // { dg-error "bit" }
+ sizeof(x); // { dg-error "bit" }
+}
--- /dev/null
+// 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);
+ }
+}
template <int I> int& get() { return ar[I]; }
} a4;
template<> struct std::tuple_size<A4> { enum { value = 3 }; };
-template <int I>
void f4() { auto [ x, y, z ] = a4; } // { dg-error "tuple_element" }
struct A5 { } a5;
template <int I> int& get(A5&& a);
template<> struct std::tuple_size<A5> { enum { value = 3 }; };
-template <int I>
void f5() { auto [ x, y, z ] = a5; } // { dg-error "tuple_element" }
struct A6 { } a6;
template <int I> int& get(A6&& a);
template<> struct std::tuple_size<A6> { enum { value = 3 }; };
template<> struct std::tuple_element<0, A6> { };
-template <int I>
void f6() { auto [ x, y, z ] = a6; } // { dg-error "no type named .type" }
--- /dev/null
+// Test for decltype of direct decomposition.
+// { dg-options -std=c++1z }
+
+template <class,class> struct same_type;
+template <class T> struct same_type<T,T> {};
+
+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<decltype(i),int>{};
+ same_type<decltype(ci),const int>{};
+ same_type<decltype(mi),int>{};
+ same_type<decltype(r),int&>{};
+ same_type<decltype(cr),const int&>{};
+}
+void frr() {
+ auto &&[i,ci,mi,r,cr] = a;
+
+ same_type<decltype(i),int>{};
+ same_type<decltype(ci),const int>{};
+ same_type<decltype(mi),int>{};
+ same_type<decltype(r),int&>{};
+ same_type<decltype(cr),const int&>{};
+}
+void fc() {
+ const auto [i,ci,mi,r,cr] = a;
+
+ same_type<decltype(i),const int>{};
+ same_type<decltype(ci),const int>{};
+ same_type<decltype(mi),int>{};
+ same_type<decltype(r),int&>{};
+ same_type<decltype(cr),const int&>{};
+}
+void frc() {
+ const A ca{};
+ auto &[i,ci,mi,r,cr] = ca;
+
+ same_type<decltype(i),const int>{};
+ same_type<decltype(ci),const int>{};
+ same_type<decltype(mi),int>{};
+ same_type<decltype(r),int&>{};
+ same_type<decltype(cr),const int&>{};
+}