+2016-10-06 Jakub Jelinek <jakub@redhat.com>
+
+ Implement P0258R2 - helper for C++17
+ std::has_unique_object_representations trait
+ * c-common.h (enum rid): Add RID_HAS_UNIQUE_OBJ_REPRESENTATIONS.
+ * c-common.c (c_common_reswords): Add
+ __has_unique_object_representations.
+
2016-10-05 Jakub Jelinek <jakub@redhat.com>
PR sanitizer/66343
{ "__has_trivial_constructor", RID_HAS_TRIVIAL_CONSTRUCTOR, D_CXXONLY },
{ "__has_trivial_copy", RID_HAS_TRIVIAL_COPY, D_CXXONLY },
{ "__has_trivial_destructor", RID_HAS_TRIVIAL_DESTRUCTOR, D_CXXONLY },
+ { "__has_unique_object_representations", RID_HAS_UNIQUE_OBJ_REPRESENTATIONS,
+ D_CXXONLY },
{ "__has_virtual_destructor", RID_HAS_VIRTUAL_DESTRUCTOR, D_CXXONLY },
{ "__imag", RID_IMAGPART, 0 },
{ "__imag__", RID_IMAGPART, 0 },
RID_HAS_NOTHROW_ASSIGN, RID_HAS_NOTHROW_CONSTRUCTOR,
RID_HAS_NOTHROW_COPY, RID_HAS_TRIVIAL_ASSIGN,
RID_HAS_TRIVIAL_CONSTRUCTOR, RID_HAS_TRIVIAL_COPY,
- RID_HAS_TRIVIAL_DESTRUCTOR, RID_HAS_VIRTUAL_DESTRUCTOR,
+ RID_HAS_TRIVIAL_DESTRUCTOR, RID_HAS_UNIQUE_OBJ_REPRESENTATIONS,
+ RID_HAS_VIRTUAL_DESTRUCTOR,
RID_IS_ABSTRACT, RID_IS_BASE_OF,
RID_IS_CLASS,
RID_IS_EMPTY, RID_IS_ENUM,
+2016-10-06 Jakub Jelinek <jakub@redhat.com>
+
+ Implement P0258R2 - helper for C++17
+ std::has_unique_object_representations trait
+ * cp-tree.h (enum cp_trait_kind): Add
+ CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS.
+ (struct lang_type_class): Add unique_obj_representations
+ and unique_obj_representations_set bitfields.
+ (CLASSTYPE_UNIQUE_OBJ_REPRESENTATIONS,
+ CLASSTYPE_UNIQUE_OBJ_REPRESENTATIONS_SET): Define.
+ (type_has_unique_obj_representations): Declare.
+ * parser.c (cp_parser_primary_expression): Handle
+ RID_HAS_UNIQUE_OBJ_REPRESENTATIONS.
+ (cp_parser_trait_expr): Likewise. Formatting fix.
+ * semantics.c (trait_expr_value, finish_trait_expr): Handle
+ CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS.
+ * tree.c (type_has_unique_obj_representations): New function.
+ (record_has_unique_obj_representations): New function.
+ * cxx-pretty-print.c (pp_cxx_trait_expression): Handle
+ CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS.
+
2016-10-05 Jason Merrill <jason@redhat.com>
Implement P0135R1, Guaranteed copy elision.
CPTK_HAS_TRIVIAL_CONSTRUCTOR,
CPTK_HAS_TRIVIAL_COPY,
CPTK_HAS_TRIVIAL_DESTRUCTOR,
+ CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS,
CPTK_HAS_VIRTUAL_DESTRUCTOR,
CPTK_IS_ABSTRACT,
CPTK_IS_BASE_OF,
unsigned has_complex_move_ctor : 1;
unsigned has_complex_move_assign : 1;
unsigned has_constexpr_ctor : 1;
+ unsigned unique_obj_representations : 1;
+ unsigned unique_obj_representations_set : 1;
/* When adding a flag here, consider whether or not it ought to
apply to a template instance if it applies to the template. If
/* There are some bits left to fill out a 32-bit word. Keep track
of this by updating the size of this bitfield whenever you add or
remove a flag. */
- unsigned dummy : 4;
+ unsigned dummy : 2;
tree primary_base;
vec<tree_pair_s, va_gc> *vcall_indices;
#define CLASSTYPE_NON_STD_LAYOUT(NODE) \
(LANG_TYPE_CLASS_CHECK (NODE)->non_std_layout)
+/* Nonzero means that this class type does have unique object
+ representations. */
+#define CLASSTYPE_UNIQUE_OBJ_REPRESENTATIONS(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->unique_obj_representations)
+
+/* Nonzero means that this class type has
+ CLASSTYPE_UNIQUE_OBJ_REPRESENTATIONS computed. */
+#define CLASSTYPE_UNIQUE_OBJ_REPRESENTATIONS_SET(NODE) \
+ (LANG_TYPE_CLASS_CHECK (NODE)->unique_obj_representations_set)
+
/* Nonzero means that this class contains pod types whose default
initialization is not a zero initialization (namely, pointers to
data members). */
extern bool std_layout_type_p (const_tree);
extern bool trivial_type_p (const_tree);
extern bool trivially_copyable_p (const_tree);
+extern bool type_has_unique_obj_representations (const_tree);
extern bool scalarish_type_p (const_tree);
extern bool type_has_nontrivial_default_init (const_tree);
extern bool type_has_nontrivial_copy_init (const_tree);
case CPTK_HAS_TRIVIAL_DESTRUCTOR:
pp_cxx_ws_string (pp, "__has_trivial_destructor");
break;
+ case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
+ pp_cxx_ws_string (pp, "__has_unique_object_representations");
+ break;
case CPTK_HAS_VIRTUAL_DESTRUCTOR:
pp_cxx_ws_string (pp, "__has_virtual_destructor");
break;
case RID_HAS_TRIVIAL_CONSTRUCTOR:
case RID_HAS_TRIVIAL_COPY:
case RID_HAS_TRIVIAL_DESTRUCTOR:
+ case RID_HAS_UNIQUE_OBJ_REPRESENTATIONS:
case RID_HAS_VIRTUAL_DESTRUCTOR:
case RID_IS_ABSTRACT:
case RID_IS_BASE_OF:
case RID_HAS_TRIVIAL_DESTRUCTOR:
kind = CPTK_HAS_TRIVIAL_DESTRUCTOR;
break;
+ case RID_HAS_UNIQUE_OBJ_REPRESENTATIONS:
+ kind = CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS;
+ break;
case RID_HAS_VIRTUAL_DESTRUCTOR:
kind = CPTK_HAS_VIRTUAL_DESTRUCTOR;
break;
/* Complete the trait expression, which may mean either processing
the trait expr now or saving it for template instantiation. */
- switch(kind)
+ switch (kind)
{
case CPTK_UNDERLYING_TYPE:
return finish_underlying_type (type1);
case CPTK_HAS_VIRTUAL_DESTRUCTOR:
return type_has_virtual_destructor (type1);
+ case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
+ return type_has_unique_obj_representations (type1);
+
case CPTK_IS_ABSTRACT:
return (ABSTRACT_CLASS_TYPE_P (type1));
case CPTK_HAS_NOTHROW_COPY:
case CPTK_HAS_TRIVIAL_COPY:
case CPTK_HAS_TRIVIAL_DESTRUCTOR:
+ case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
case CPTK_HAS_VIRTUAL_DESTRUCTOR:
case CPTK_IS_ABSTRACT:
case CPTK_IS_EMPTY:
return scalarish_type_p (t);
}
+static bool record_has_unique_obj_representations (const_tree, const_tree);
+
+/* Returns true iff T satisfies std::has_unique_object_representations<T>,
+ as defined in [meta.unary.prop]. */
+
+bool
+type_has_unique_obj_representations (const_tree t)
+{
+ bool ret;
+
+ t = strip_array_types (CONST_CAST_TREE (t));
+
+ if (!trivially_copyable_p (t))
+ return false;
+
+ if (CLASS_TYPE_P (t) && CLASSTYPE_UNIQUE_OBJ_REPRESENTATIONS_SET (t))
+ return CLASSTYPE_UNIQUE_OBJ_REPRESENTATIONS (t);
+
+ switch (TREE_CODE (t))
+ {
+ case INTEGER_TYPE:
+ case POINTER_TYPE:
+ case REFERENCE_TYPE:
+ /* If some backend has any paddings in these types, we should add
+ a target hook for this and handle it there. */
+ return true;
+
+ case BOOLEAN_TYPE:
+ /* For bool values other than 0 and 1 should only appear with
+ undefined behavior. */
+ return true;
+
+ case ENUMERAL_TYPE:
+ return type_has_unique_obj_representations (ENUM_UNDERLYING_TYPE (t));
+
+ case REAL_TYPE:
+ /* XFmode certainly contains padding on x86, which the CPU doesn't store
+ when storing long double values, so for that we have to return false.
+ Other kinds of floating point values are questionable due to +.0/-.0
+ and NaNs, let's play safe for now. */
+ return false;
+
+ case FIXED_POINT_TYPE:
+ return false;
+
+ case OFFSET_TYPE:
+ return true;
+
+ case COMPLEX_TYPE:
+ case VECTOR_TYPE:
+ return type_has_unique_obj_representations (TREE_TYPE (t));
+
+ case RECORD_TYPE:
+ ret = record_has_unique_obj_representations (t, TYPE_SIZE (t));
+ if (CLASS_TYPE_P (t))
+ {
+ CLASSTYPE_UNIQUE_OBJ_REPRESENTATIONS_SET (t) = 1;
+ CLASSTYPE_UNIQUE_OBJ_REPRESENTATIONS (t) = ret;
+ }
+ return ret;
+
+ case UNION_TYPE:
+ ret = true;
+ bool any_fields;
+ any_fields = false;
+ for (tree field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL)
+ {
+ any_fields = true;
+ if (!type_has_unique_obj_representations (TREE_TYPE (field))
+ || simple_cst_equal (DECL_SIZE (field), TYPE_SIZE (t)) != 1)
+ {
+ ret = false;
+ break;
+ }
+ }
+ if (!any_fields && !integer_zerop (TYPE_SIZE (t)))
+ ret = false;
+ if (CLASS_TYPE_P (t))
+ {
+ CLASSTYPE_UNIQUE_OBJ_REPRESENTATIONS_SET (t) = 1;
+ CLASSTYPE_UNIQUE_OBJ_REPRESENTATIONS (t) = ret;
+ }
+ return ret;
+
+ case NULLPTR_TYPE:
+ return false;
+
+ case ERROR_MARK:
+ return false;
+
+ default:
+ gcc_unreachable ();
+ }
+}
+
+/* Helper function for type_has_unique_obj_representations. */
+
+static bool
+record_has_unique_obj_representations (const_tree t, const_tree sz)
+{
+ for (tree field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
+ if (TREE_CODE (field) != FIELD_DECL)
+ ;
+ /* For bases, can't use type_has_unique_obj_representations here, as in
+ struct S { int i : 24; S (); };
+ struct T : public S { int j : 8; T (); };
+ S doesn't have unique obj representations, but T does. */
+ else if (DECL_FIELD_IS_BASE (field))
+ {
+ if (!record_has_unique_obj_representations (TREE_TYPE (field),
+ DECL_SIZE (field)))
+ return false;
+ }
+ else if (DECL_C_BIT_FIELD (field))
+ {
+ tree btype = DECL_BIT_FIELD_TYPE (field);
+ if (!type_has_unique_obj_representations (btype))
+ return false;
+ }
+ else if (!type_has_unique_obj_representations (TREE_TYPE (field)))
+ return false;
+
+ offset_int cur = 0;
+ for (tree field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
+ if (TREE_CODE (field) == FIELD_DECL)
+ {
+ offset_int fld = wi::to_offset (DECL_FIELD_OFFSET (field));
+ offset_int bitpos = wi::to_offset (DECL_FIELD_BIT_OFFSET (field));
+ fld = fld * BITS_PER_UNIT + bitpos;
+ if (cur != fld)
+ return false;
+ if (DECL_SIZE (field))
+ {
+ offset_int size = wi::to_offset (DECL_SIZE (field));
+ cur += size;
+ }
+ }
+ if (cur != wi::to_offset (sz))
+ return false;
+
+ return true;
+}
+
/* Nonzero iff type T is a class template implicit specialization. */
bool
+2016-10-06 Jakub Jelinek <jakub@redhat.com>
+
+ * g++.dg/cpp1z/has-unique-obj-representations1.C: New test.
+ * g++.dg/cpp1z/has-unique-obj-representations2.C: New test.
+
2016-10-06 Kugan Vivekanandarajah <kuganv@linaro.org>
PR tree-optimization/77862
--- /dev/null
+// { dg-do compile { target c++11 } }
+
+#define INTB (__SIZEOF_INT__ * __CHAR_BIT__)
+struct S { int i : INTB * 3 / 4; S (); };
+struct T : public S { int j : INTB / 4; T (); };
+struct U { int i : INTB * 3 / 4; int j : INTB / 4; };
+struct V { int i : INTB * 3 / 4; int j : INTB / 4 + 1; };
+struct W {};
+struct X : public W { int i; void bar (); };
+struct Y { char a[3]; char b[]; };
+struct Z { int a; float b; };
+struct A { int i : INTB * 2; int j; }; // { dg-warning "exceeds its type" }
+union B { long a; unsigned long b; };
+union C { int a; int b : INTB - 1; };
+struct D { int a : INTB + 1; int b : INTB - 1; }; // { dg-warning "exceeds its type" }
+static_assert (__has_unique_object_representations (char) == true, "");
+static_assert (__has_unique_object_representations (unsigned char) == true, "");
+static_assert (__has_unique_object_representations (int) == true, "");
+static_assert (__has_unique_object_representations (unsigned int) == true, "");
+static_assert (__has_unique_object_representations (bool) == true, "");
+static_assert (sizeof (S) != sizeof (int) || __has_unique_object_representations (S) == false, "");
+static_assert (sizeof (T) != sizeof (int) || __has_unique_object_representations (T) == true, "");
+static_assert (sizeof (U) != sizeof (int) || __has_unique_object_representations (U) == true, "");
+static_assert (__has_unique_object_representations (V) == false, "");
+static_assert (__has_unique_object_representations (W) == false, "");
+static_assert (sizeof (X) != sizeof (int) || __has_unique_object_representations (X) == true, "");
+static_assert (__has_unique_object_representations (float) == false, "");
+static_assert (__has_unique_object_representations (double) == false, "");
+static_assert (__has_unique_object_representations (long double) == false, "");
+static_assert (__has_unique_object_representations (void) == false, "");
+static_assert (__has_unique_object_representations (_Complex int) == true, "");
+static_assert (__has_unique_object_representations (_Complex float) == false, "");
+static_assert (__has_unique_object_representations (_Complex double) == false, "");
+static_assert (__has_unique_object_representations (_Complex long double) == false, "");
+static_assert (__has_unique_object_representations (int __attribute__((vector_size (16)))) == true, "");
+static_assert (__has_unique_object_representations (float __attribute__((vector_size (16)))) == false, "");
+static_assert (__has_unique_object_representations (int X::*) == true, "");
+static_assert (__has_unique_object_representations (void (X::*) ()) == true, "");
+static_assert (__has_unique_object_representations (int *) == true, "");
+static_assert (__has_unique_object_representations (int (*) ()) == true, "");
+static_assert (__has_unique_object_representations (decltype (nullptr)) == false, "");
+static_assert (__has_unique_object_representations (Y) == (sizeof (Y) == 3 * sizeof (char)), "");
+static_assert (__has_unique_object_representations (Z) == false, "");
+static_assert (__has_unique_object_representations (A) == false, "");
+static_assert (sizeof (B) != sizeof (long) || __has_unique_object_representations (B) == true, "");
+static_assert (__has_unique_object_representations (C) == false, "");
+static_assert (__has_unique_object_representations (D) == false, "");
--- /dev/null
+struct S;
+struct T { S t; }; // { dg-error "incomplete type" }
+struct U { int u[sizeof (S)]; }; // { dg-error "incomplete type" }
+union V { char c; char d[]; }; // { dg-error "flexible array member in union" }
+bool a = __has_unique_object_representations (S); // { dg-error "incomplete type" }
+bool b = __has_unique_object_representations (T);
+bool c = __has_unique_object_representations (U);
+bool d = __has_unique_object_representations (V);