public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [C++ PATCH]  Implement P0840, language support for empty objects.
@ 2018-10-03 16:05 Jason Merrill
  2018-10-03 16:30 ` Jakub Jelinek
  0 siblings, 1 reply; 4+ messages in thread
From: Jason Merrill @ 2018-10-03 16:05 UTC (permalink / raw)
  To: gcc-patches

	The [[no_unique_address]] attribute on a non-static data member
	enables the equivalent of the empty base optimization.

	Tested x86_64-pc-linux-gnu, applying to trunk.

gcc/cp/
	* tree.c (handle_no_unique_addr_attribute): New.
	(cxx_attribute_table): Add [[no_unique_address]].
	* class.c (field_poverlapping_p): New.
	(layout_class_type): Check it.  Adjust DECL_SIZE of potentially
	overlapping fields.
	(layout_empty_base_or_field): Rename from layout_empty_base, handle
	FIELD_DECL as well.
	(build_base_field, record_subobject_offsets): Adjust.
c-family/
	* c-lex.c (c_common_has_attribute): Add no_unique_address.
---
 gcc/c-family/c-lex.c                          |   2 +
 gcc/cp/class.c                                | 180 ++++++++++++------
 gcc/cp/tree.c                                 |  27 +++
 gcc/testsuite/g++.dg/abi/empty4.C             |  27 +++
 gcc/testsuite/g++.dg/abi/empty5.C             |  11 ++
 gcc/testsuite/g++.dg/abi/empty8.C             |  10 +
 gcc/testsuite/g++.dg/abi/no_unique_address1.C |  38 ++++
 gcc/testsuite/g++.dg/abi/no_unique_address2.C |  43 +++++
 gcc/testsuite/g++.dg/abi/no_unique_address3.C |  19 ++
 .../g++.dg/cpp2a/no_unique_address1.C         |  13 ++
 gcc/c-family/ChangeLog                        |   4 +
 gcc/cp/ChangeLog                              |  12 ++
 12 files changed, 333 insertions(+), 53 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/abi/no_unique_address1.C
 create mode 100644 gcc/testsuite/g++.dg/abi/no_unique_address2.C
 create mode 100644 gcc/testsuite/g++.dg/abi/no_unique_address3.C
 create mode 100644 gcc/testsuite/g++.dg/cpp2a/no_unique_address1.C

diff --git a/gcc/c-family/c-lex.c b/gcc/c-family/c-lex.c
index ac58335cf3a..78a132484fc 100644
--- a/gcc/c-family/c-lex.c
+++ b/gcc/c-family/c-lex.c
@@ -356,6 +356,8 @@ c_common_has_attribute (cpp_reader *pfile)
 		       || is_attribute_p ("nodiscard", attr_name)
 		       || is_attribute_p ("fallthrough", attr_name))
 		result = 201603;
+	      else if (is_attribute_p ("no_unique_address", attr_name))
+		result = 20180312;
 	      if (result)
 		attr_name = NULL_TREE;
 	    }
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 9ca46441871..1789d1ecb70 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -180,8 +180,6 @@ static tree build_vtable (tree, tree, tree);
 static void initialize_vtable (tree, vec<constructor_elt, va_gc> *);
 static void layout_nonempty_base_or_field (record_layout_info,
 					   tree, tree, splay_tree);
-static tree end_of_class (tree, int);
-static bool layout_empty_base (record_layout_info, tree, tree, splay_tree);
 static void accumulate_vtbl_inits (tree, tree, tree, tree, tree,
 				   vec<constructor_elt, va_gc> **);
 static void dfs_accumulate_vtbl_inits (tree, tree, tree, tree, tree,
@@ -202,7 +200,6 @@ static int record_subobject_offset (tree, tree, splay_tree);
 static int check_subobject_offset (tree, tree, splay_tree);
 static int walk_subobject_offsets (tree, subobject_offset_fn,
 				   tree, splay_tree, tree, int);
-static void record_subobject_offsets (tree, tree, splay_tree, bool);
 static int layout_conflict_p (tree, tree, splay_tree, int);
 static int splay_tree_compare_integer_csts (splay_tree_key k1,
 					    splay_tree_key k2);
@@ -3960,20 +3957,52 @@ walk_subobject_offsets (tree type,
   return 0;
 }
 
-/* Record all of the empty subobjects of TYPE (either a type or a
-   binfo).  If IS_DATA_MEMBER is true, then a non-static data member
-   is being placed at OFFSET; otherwise, it is a base class that is
-   being placed at OFFSET.  */
+/* Return true iff FIELD_DECL DECL is potentially overlapping.  */
+
+static bool
+field_poverlapping_p (tree decl)
+{
+  /* Base fields are actually potentially overlapping, but C++ bases go through
+     a different code path based on binfos, and ObjC++ base fields are laid out
+     in objc-act, so we don't want layout_class_type to mess with them.  */
+  if (DECL_FIELD_IS_BASE (decl))
+    {
+      gcc_checking_assert (c_dialect_objc ());
+      return false;
+    }
+
+  return lookup_attribute ("no_unique_address",
+			   DECL_ATTRIBUTES (decl));
+}
+
+/* Record all of the empty subobjects of DECL_OR_BINFO.  */
 
 static void
-record_subobject_offsets (tree type,
-			  tree offset,
-			  splay_tree offsets,
-			  bool is_data_member)
+record_subobject_offsets (tree decl_or_binfo,
+			  splay_tree offsets)
 {
+  tree type, offset;
+  bool overlapping, vbases_p;
+
+  if (DECL_P (decl_or_binfo))
+    {
+      tree decl = decl_or_binfo;
+      type = TREE_TYPE (decl);
+      offset = byte_position (decl);
+      overlapping = field_poverlapping_p (decl);
+      vbases_p = true;
+    }
+  else
+    {
+      type = BINFO_TYPE (decl_or_binfo);
+      offset = BINFO_OFFSET (decl_or_binfo);
+      overlapping = true;
+      vbases_p = false;
+    }
+
   tree max_offset;
   /* If recording subobjects for a non-static data member or a
-     non-empty base class , we do not need to record offsets beyond
+     non-empty base class, we do not need to record offsets beyond
      the size of the biggest empty class.  Additional data members
      will go at the end of the class.  Additional base classes will go
      either at offset zero (if empty, in which case they cannot
@@ -3985,13 +4014,13 @@ record_subobject_offsets (tree type,
      other empty classes might later be placed) or at the end of the
      class (where other objects might then be placed, so other empty
      subobjects might later overlap).  */
-  if (is_data_member
-      || !is_empty_class (BINFO_TYPE (type)))
+  if (!overlapping
+      || !is_empty_class (type))
     max_offset = sizeof_biggest_empty_class;
   else
     max_offset = NULL_TREE;
   walk_subobject_offsets (type, record_subobject_offset, offset,
-			  offsets, max_offset, is_data_member);
+			  offsets, max_offset, vbases_p);
 }
 
 /* Returns nonzero if any of the empty subobjects of TYPE (located at
@@ -4151,55 +4180,80 @@ empty_base_at_nonzero_offset_p (tree type,
    type.  Return nonzero iff we added it at the end.  */
 
 static bool
-layout_empty_base (record_layout_info rli, tree binfo,
-		   tree eoc, splay_tree offsets)
+layout_empty_base_or_field (record_layout_info rli, tree binfo_or_decl,
+			    splay_tree offsets)
 {
   tree alignment;
-  tree basetype = BINFO_TYPE (binfo);
   bool atend = false;
+  tree binfo = NULL_TREE;
+  tree decl = NULL_TREE;
+  tree type;
+  if (TREE_CODE (binfo_or_decl) == TREE_BINFO)
+    {
+      binfo = binfo_or_decl;
+      type = BINFO_TYPE (binfo);
+    }
+  else
+    {
+      decl = binfo_or_decl;
+      type = TREE_TYPE (decl);
+    }
 
-  /* This routine should only be used for empty classes.  */
-  gcc_assert (is_empty_class (basetype));
-  alignment = ssize_int (CLASSTYPE_ALIGN_UNIT (basetype));
+  /* On some platforms (ARM), even empty classes will not be
+     byte-aligned.  */
+  tree eoc = round_up_loc (input_location,
+			   rli_size_unit_so_far (rli),
+			   CLASSTYPE_ALIGN_UNIT (type));
 
-  if (!integer_zerop (BINFO_OFFSET (binfo)))
-    propagate_binfo_offsets
-      (binfo, size_diffop_loc (input_location,
-			       size_zero_node, BINFO_OFFSET (binfo)));
+  /* This routine should only be used for empty classes.  */
+  gcc_assert (is_empty_class (type));
+  alignment = size_int (CLASSTYPE_ALIGN_UNIT (type));
 
   /* This is an empty base class.  We first try to put it at offset
      zero.  */
-  if (layout_conflict_p (binfo,
-			 BINFO_OFFSET (binfo),
+  tree offset = size_zero_node;
+  if (layout_conflict_p (type,
+			 offset,
 			 offsets,
 			 /*vbases_p=*/0))
     {
       /* That didn't work.  Now, we move forward from the next
 	 available spot in the class.  */
       atend = true;
-      propagate_binfo_offsets (binfo, fold_convert (ssizetype, eoc));
+      offset = eoc;
       while (1)
 	{
-	  if (!layout_conflict_p (binfo,
-				  BINFO_OFFSET (binfo),
+	  if (!layout_conflict_p (type,
+				  offset,
 				  offsets,
 				  /*vbases_p=*/0))
 	    /* We finally found a spot where there's no overlap.  */
 	    break;
 
 	  /* There's overlap here, too.  Bump along to the next spot.  */
-	  propagate_binfo_offsets (binfo, alignment);
+	  offset = size_binop (PLUS_EXPR, offset, alignment);
 	}
     }
 
-  if (CLASSTYPE_USER_ALIGN (basetype))
+  if (CLASSTYPE_USER_ALIGN (type))
     {
-      rli->record_align = MAX (rli->record_align, CLASSTYPE_ALIGN (basetype));
+      rli->record_align = MAX (rli->record_align, CLASSTYPE_ALIGN (type));
       if (warn_packed)
-	rli->unpacked_align = MAX (rli->unpacked_align, CLASSTYPE_ALIGN (basetype));
+	rli->unpacked_align = MAX (rli->unpacked_align, CLASSTYPE_ALIGN (type));
       TYPE_USER_ALIGN (rli->t) = 1;
     }
 
+  if (binfo)
+    /* Adjust BINFO_OFFSET (binfo) to be exactly OFFSET.  */
+    propagate_binfo_offsets (binfo,
+			     size_diffop (offset, BINFO_OFFSET (binfo)));
+  else
+    {
+      DECL_FIELD_OFFSET (decl) = offset;
+      DECL_FIELD_BIT_OFFSET (decl) = bitsize_zero_node;
+      SET_DECL_OFFSET_ALIGN (decl, BITS_PER_UNIT);
+    }
+
   return atend;
 }
 
@@ -4277,15 +4331,7 @@ build_base_field (record_layout_info rli, tree binfo,
     }
   else
     {
-      tree eoc;
-      bool atend;
-
-      /* On some platforms (ARM), even empty classes will not be
-	 byte-aligned.  */
-      eoc = round_up_loc (input_location,
-		      rli_size_unit_so_far (rli),
-		      CLASSTYPE_ALIGN_UNIT (basetype));
-      atend = layout_empty_base (rli, binfo, eoc, offsets);
+      bool atend = layout_empty_base_or_field (rli, binfo, offsets);
       /* A nearly-empty class "has no proper base class that is empty,
 	 not morally virtual, and at an offset other than zero."  */
       if (!BINFO_VIRTUAL_P (binfo) && CLASSTYPE_NEARLY_EMPTY_P (t))
@@ -4323,10 +4369,7 @@ build_base_field (record_layout_info rli, tree binfo,
     }
 
   /* Record the offsets of BINFO and its base subobjects.  */
-  record_subobject_offsets (binfo,
-			    BINFO_OFFSET (binfo),
-			    offsets,
-			    /*is_data_member=*/false);
+  record_subobject_offsets (binfo, offsets);
 
   return next_field;
 }
@@ -5886,10 +5929,11 @@ end_of_base (tree binfo)
 
 /* Returns the offset of the byte just past the end of the base class
    with the highest offset in T.  If INCLUDE_VIRTUALS_P is zero, then
-   only non-virtual bases are included.  */
+   only non-virtual bases are included.  If INCLUDE_FIELDS_P is true,
+   then also consider non-static data members.  */
 
 static tree
-end_of_class (tree t, int include_virtuals_p)
+end_of_class (tree t, bool include_virtuals_p, bool include_fields_p = false)
 {
   tree result = size_zero_node;
   vec<tree, va_gc> *vbases;
@@ -5912,6 +5956,16 @@ end_of_class (tree t, int include_virtuals_p)
 	result = offset;
     }
 
+  if (include_fields_p)
+    for (tree field = TYPE_FIELDS (t); field; field = DECL_CHAIN (field))
+      if (TREE_CODE (field) == FIELD_DECL)
+	{
+	  offset = size_binop (PLUS_EXPR, DECL_FIELD_OFFSET (field),
+			       DECL_SIZE_UNIT (field));
+	  if (tree_int_cst_lt (result, offset))
+	    result = offset;
+	}
+
   if (include_virtuals_p)
     for (vbases = CLASSTYPE_VBASECLASSES (t), i = 0;
 	 vec_safe_iterate (vbases, i, &base_binfo); i++)
@@ -6098,6 +6152,27 @@ layout_class_type (tree t, tree *virtuals_p)
 
       padding = NULL_TREE;
 
+      bool might_overlap = field_poverlapping_p (field);
+
+      if (might_overlap && CLASS_TYPE_P (type)
+	  && CLASSTYPE_NON_LAYOUT_POD_P (type))
+	{
+	  /* if D is a potentially-overlapping data member, update sizeof(C) to
+	     max (sizeof(C), offset(D)+max (nvsize(D), dsize(D))).  */
+	  tree nvsize = CLASSTYPE_SIZE_UNIT (type);
+	  tree dsize = end_of_class (type, /*vbases*/true, /*fields*/true);
+	  if (tree_int_cst_le (dsize, nvsize))
+	    {
+	      DECL_SIZE_UNIT (field) = nvsize;
+	      DECL_SIZE (field) = CLASSTYPE_SIZE (type);
+	    }
+	  else
+	    {
+	      DECL_SIZE_UNIT (field) = dsize;
+	      DECL_SIZE (field) = bit_from_pos (dsize, bitsize_zero_node);
+	    }
+	}
+
       /* If this field is a bit-field whose width is greater than its
 	 type, then there are some special rules for allocating
 	 it.  */
@@ -6164,15 +6239,14 @@ layout_class_type (tree t, tree *virtuals_p)
 	  /* We must also reset the DECL_MODE of the field.  */
 	  SET_DECL_MODE (field, TYPE_MODE (type));
 	}
+      else if (might_overlap && is_empty_class (type))
+	layout_empty_base_or_field (rli, field, empty_base_offsets);
       else
 	layout_nonempty_base_or_field (rli, field, NULL_TREE,
 				       empty_base_offsets);
 
       /* Remember the location of any empty classes in FIELD.  */
-      record_subobject_offsets (TREE_TYPE (field),
-				byte_position(field),
-				empty_base_offsets,
-				/*is_data_member=*/true);
+      record_subobject_offsets (field, empty_base_offsets);
 
       /* If a bit-field does not immediately follow another bit-field,
 	 and yet it starts in the middle of a byte, we have failed to
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index c6f216dab4b..e74b79c44e0 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -4428,6 +4428,31 @@ handle_nodiscard_attribute (tree *node, tree name, tree /*args*/,
   return NULL_TREE;
 }
 
+/* Handle a C++2a "no_unique_address" attribute; arguments as in
+   struct attribute_spec.handler.  */
+static tree
+handle_no_unique_addr_attribute (tree* node,
+				 tree name,
+				 tree /*args*/,
+				 int /*flags*/,
+				 bool* no_add_attrs)
+{
+  if (TREE_CODE (*node) != FIELD_DECL)
+    {
+      warning (OPT_Wattributes, "%qE attribute can only be applied to "
+	       "non-static data members", name);
+      *no_add_attrs = true;
+    }
+  else if (DECL_C_BIT_FIELD (*node))
+    {
+      warning (OPT_Wattributes, "%qE attribute cannot be applied to "
+	       "a bit-field", name);
+      *no_add_attrs = true;
+    }
+
+  return NULL_TREE;
+}
+
 /* Table of valid C++ attributes.  */
 const struct attribute_spec cxx_attribute_table[] =
 {
@@ -4449,6 +4474,8 @@ const struct attribute_spec std_attribute_table[] =
     handle_unused_attribute, NULL },
   { "nodiscard", 0, 0, false, false, false, false,
     handle_nodiscard_attribute, NULL },
+  { "no_unique_address", 0, 0, true, false, false, false,
+    handle_no_unique_addr_attribute, NULL },
   { NULL, 0, 0, false, false, false, false, NULL, NULL }
 };
 
diff --git a/gcc/testsuite/g++.dg/abi/empty4.C b/gcc/testsuite/g++.dg/abi/empty4.C
index d20a55cf7fc..8cc10a9fb0f 100644
--- a/gcc/testsuite/g++.dg/abi/empty4.C
+++ b/gcc/testsuite/g++.dg/abi/empty4.C
@@ -37,6 +37,16 @@ struct B
   B (long c) {m = c;}
 };
 
+#if __cpp_attributes
+struct B2
+{
+  [[no_unique_address]] Inter empty;
+  NonPod m;
+
+  B2 (long c) {m = c;}
+};
+#endif
+
 struct C : NonPod, Inter
 {
   C (long c) : NonPod (c), Inter () {}
@@ -65,6 +75,7 @@ int main ()
   if (b2.m.m != 0x32333435)
     return 2;	// we copied padding, which clobbered b2.m.m
   
+  {
   B c (0x12131415);
   was = c.m.m;
   c = 0x22232425;
@@ -76,6 +87,22 @@ int main ()
 
   if (c.m.m != 0x22232425)
     return 4;
+  }
+#if __cpp_attributes
+  {
+  B2 c (0x12131415);
+  was = c.m.m;
+  c = 0x22232425;
+  if (was != now)
+    return 3;
+  
+  B2 d (0x32333435);
+  c.empty = d.empty;
+
+  if (c.m.m != 0x22232425)
+    return 4;
+  }    
+#endif
 
   C e (0x32333435);
 
diff --git a/gcc/testsuite/g++.dg/abi/empty5.C b/gcc/testsuite/g++.dg/abi/empty5.C
index c3717727e21..9ad66d91f61 100644
--- a/gcc/testsuite/g++.dg/abi/empty5.C
+++ b/gcc/testsuite/g++.dg/abi/empty5.C
@@ -9,9 +9,20 @@ struct B {
 
 struct C : public B, public A {};
 
+#if __cpp_attributes
+struct C2 : public B
+{
+  [[no_unique_address]] A a;
+} c2;
+#endif
+
 C c;
 
 int main () {
   if ((void*) (A*) &c != &c)
     return 1;
+#if __cpp_attributes
+  if ((void*)&c2.a != &c2)
+    return 2;
+#endif
 }
diff --git a/gcc/testsuite/g++.dg/abi/empty8.C b/gcc/testsuite/g++.dg/abi/empty8.C
index a5287b15fa0..6d7954ec291 100644
--- a/gcc/testsuite/g++.dg/abi/empty8.C
+++ b/gcc/testsuite/g++.dg/abi/empty8.C
@@ -5,10 +5,20 @@ struct E1 {};
 struct E2 : public E1 {};
 struct S1 { int i; };
 struct S2 : public S1, E2 {};
+#if __cpp_attributes
+struct S22 : public S1
+{
+  [[no_unique_address]] E2 e2;
+} s22;
+#endif
 
 S2 s2;
 
 int main () {
   if ((char *)(E2*) &s2 != (char *)&s2)
     return 1;
+#if __cpp_attributes
+  if ((char *)&s22.e2 != (char *)&s22)
+    return 2;
+#endif
 }
diff --git a/gcc/testsuite/g++.dg/abi/no_unique_address1.C b/gcc/testsuite/g++.dg/abi/no_unique_address1.C
new file mode 100644
index 00000000000..853726dd4b0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/no_unique_address1.C
@@ -0,0 +1,38 @@
+// { dg-do run { target c++2a } }
+
+struct B { };
+
+struct A
+{
+  [[no_unique_address]] B b;
+  int i;
+};
+
+struct C
+{
+  B b;
+  int i;
+};
+
+struct D: B { };
+
+struct E
+{
+  B b [[no_unique_address]];
+  D d [[no_unique_address]];
+};
+
+constexpr bool same (void *x, void *y) { return x == y; }
+
+int main()
+{
+  A a;
+  if (!same(&a.b, &a.i))
+    __builtin_abort();
+  C c;
+  if (same(&c.b, &c.i))
+    __builtin_abort();
+  E e;
+  if (same (&e.b, &e.d))
+    __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/abi/no_unique_address2.C b/gcc/testsuite/g++.dg/abi/no_unique_address2.C
new file mode 100644
index 00000000000..bef6d5b43be
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/no_unique_address2.C
@@ -0,0 +1,43 @@
+// { dg-do compile { target c++11 } }
+
+struct A
+{
+  virtual void f();
+  char c;
+};
+
+struct B1 : A
+{
+  char c2;
+};
+
+struct B2
+{
+  A a [[no_unique_address]];
+  char c2;
+};
+
+struct C
+{
+  char c;
+};
+
+struct D: virtual C
+{
+  virtual void f();
+};
+
+struct B3: D
+{
+  char c2;
+};
+
+struct B4
+{
+  D d [[no_unique_address]];
+  char c2;
+};
+
+#define SA(X) static_assert ((X), #X)
+SA (sizeof (B2) == sizeof (B1));
+SA (sizeof (B3) == sizeof (B4));
diff --git a/gcc/testsuite/g++.dg/abi/no_unique_address3.C b/gcc/testsuite/g++.dg/abi/no_unique_address3.C
new file mode 100644
index 00000000000..0bda77777e5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/no_unique_address3.C
@@ -0,0 +1,19 @@
+// { dg-do compile { target c++11 } }
+
+struct A {
+  unsigned char i : 1;
+};
+
+struct B: A
+{
+  unsigned char j : 7;
+};
+
+struct B2
+{
+  [[no_unique_address]] A a;
+  unsigned char j : 7;
+};
+
+#define SA(X) static_assert ((X), #X)
+SA (sizeof (B) == sizeof (B2));
diff --git a/gcc/testsuite/g++.dg/cpp2a/no_unique_address1.C b/gcc/testsuite/g++.dg/cpp2a/no_unique_address1.C
new file mode 100644
index 00000000000..dd019393f28
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/no_unique_address1.C
@@ -0,0 +1,13 @@
+// { dg-do compile { target c++2a } }
+
+[[no_unique_address]] struct B { }; // { dg-warning "attribute" }
+[[no_unique_address]] int i;	    // { dg-warning "attribute" }
+[[no_unique_address]] void f();	    // { dg-warning "attribute" }
+
+struct A
+{
+  [[no_unique_address]] B b;
+  [[no_unique_address]] void f();   // { dg-warning "attribute" }
+  [[no_unique_address]] static B c; // { dg-warning "attribute" }
+  int i;
+};
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index 015ca8a2fb9..f2c1f0988f9 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -1,3 +1,7 @@
+2018-10-01  Jason Merrill  <jason@redhat.com>
+
+	* c-lex.c (c_common_has_attribute): Add no_unique_address.
+
 2018-10-01  Eric Botcazou  <ebotcazou@adacore.com>
 
 	* c-ada-spec.c (get_underlying_decl): Get to the main type variant.
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 53ff0eb0a27..40fa94fee4e 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,15 @@
+2018-10-03  Jason Merrill  <jason@redhat.com>
+
+	Implement P0840, language support for empty objects.
+	* tree.c (handle_no_unique_addr_attribute): New.
+	(cxx_attribute_table): Add [[no_unique_address]].
+	* class.c (field_poverlapping_p): New.
+	(layout_class_type): Check it.  Adjust DECL_SIZE of potentially
+	overlapping fields.
+	(layout_empty_base_or_field): Rename from layout_empty_base, handle
+	FIELD_DECL as well.
+	(build_base_field, record_subobject_offsets): Adjust.
+
 2018-10-03  Martin Liska  <mliska@suse.cz>
 
 	PR gcov-profile/86109

base-commit: d1b6467ac88990ef92f4b5844f6069419fef02e9
-- 
2.17.1

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [C++ PATCH]  Implement P0840, language support for empty objects.
  2018-10-03 16:05 [C++ PATCH] Implement P0840, language support for empty objects Jason Merrill
@ 2018-10-03 16:30 ` Jakub Jelinek
  2018-10-10 14:36   ` [C++ PATCH] Fix up __has_cpp_attribute (no_unique_address) Jakub Jelinek
  0 siblings, 1 reply; 4+ messages in thread
From: Jakub Jelinek @ 2018-10-03 16:30 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

On Wed, Oct 03, 2018 at 11:56:15AM -0400, Jason Merrill wrote:
> --- a/gcc/c-family/c-lex.c
> +++ b/gcc/c-family/c-lex.c
> @@ -356,6 +356,8 @@ c_common_has_attribute (cpp_reader *pfile)
>  		       || is_attribute_p ("nodiscard", attr_name)
>  		       || is_attribute_p ("fallthrough", attr_name))
>  		result = 201603;
> +	      else if (is_attribute_p ("no_unique_address", attr_name))
> +		result = 20180312;

Seems for all other attributes we return either 0, 1 or yyyymm, you return
here yyyymmdd, is that intentional?  If users think it is yyyymm, then
they'd read it as December 201803.

	Jakub

^ permalink raw reply	[flat|nested] 4+ messages in thread

* [C++ PATCH] Fix up __has_cpp_attribute (no_unique_address)
  2018-10-03 16:30 ` Jakub Jelinek
@ 2018-10-10 14:36   ` Jakub Jelinek
  2018-10-11  0:57     ` Jason Merrill
  0 siblings, 1 reply; 4+ messages in thread
From: Jakub Jelinek @ 2018-10-10 14:36 UTC (permalink / raw)
  To: Jason Merrill; +Cc: gcc-patches

On Wed, Oct 03, 2018 at 06:05:43PM +0200, Jakub Jelinek wrote:
> On Wed, Oct 03, 2018 at 11:56:15AM -0400, Jason Merrill wrote:
> > --- a/gcc/c-family/c-lex.c
> > +++ b/gcc/c-family/c-lex.c
> > @@ -356,6 +356,8 @@ c_common_has_attribute (cpp_reader *pfile)
> >  		       || is_attribute_p ("nodiscard", attr_name)
> >  		       || is_attribute_p ("fallthrough", attr_name))
> >  		result = 201603;
> > +	      else if (is_attribute_p ("no_unique_address", attr_name))
> > +		result = 20180312;
> 
> Seems for all other attributes we return either 0, 1 or yyyymm, you return
> here yyyymmdd, is that intentional?  If users think it is yyyymm, then
> they'd read it as December 201803.

Jonathan verified that the value should be 201803, tested on x86_64-linux,
ok for trunk?

2018-10-10  Jakub Jelinek  <jakub@redhat.com>

	* c-lex.c (c_common_has_attribute): Return 201803 instead of 20180312
	for no_unique_address.

	* g++.dg/cpp2a/feat-cxx2a.C: New test.

--- gcc/c-family/c-lex.c.jj	2018-10-08 15:18:36.665860856 +0200
+++ gcc/c-family/c-lex.c	2018-10-10 15:48:46.180923864 +0200
@@ -357,7 +357,7 @@ c_common_has_attribute (cpp_reader *pfil
 		       || is_attribute_p ("fallthrough", attr_name))
 		result = 201603;
 	      else if (is_attribute_p ("no_unique_address", attr_name))
-		result = 20180312;
+		result = 201803;
 	      if (result)
 		attr_name = NULL_TREE;
 	    }
--- gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C.jj	2018-10-10 15:52:00.896663247 +0200
+++ gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C	2018-10-10 15:52:59.865675782 +0200
@@ -0,0 +1,447 @@
+// { dg-options "-std=c++2a -I${srcdir}/g++.dg/cpp1y -I${srcdir}/g++.dg/cpp1y/testinc" }
+
+//  C++98 features:
+
+#ifndef __cpp_rtti
+#  error "__cpp_rtti"
+#elif  __cpp_rtti != 199711
+#  error "__cpp_rtti != 199711"
+#endif
+
+#ifndef __cpp_exceptions
+#  error "__cpp_exceptions"
+#elif  __cpp_exceptions != 199711
+#  error "__cpp_exceptions != 199711"
+#endif
+
+//  C++11 features:
+
+#ifndef __cpp_raw_strings
+#  error "__cpp_raw_strings"
+#elif __cpp_raw_strings != 200710
+#  error "__cpp_raw_strings != 200710"
+#endif
+
+#ifndef __cpp_unicode_literals
+#  error "__cpp_unicode_literals"
+#elif __cpp_unicode_literals != 200710
+#  error "__cpp_unicode_literals != 200710"
+#endif
+
+#ifndef __cpp_user_defined_literals
+#  error "__cpp_user_defined_literals"
+#elif __cpp_user_defined_literals != 200809
+#  error "__cpp_user_defined_literals != 200809"
+#endif
+
+#ifndef __cpp_lambdas
+#  error "__cpp_lambdas"
+#elif __cpp_lambdas != 200907
+#  error "__cpp_lambdas != 200907"
+#endif
+
+#ifndef __cpp_range_based_for
+#  error "__cpp_range_based_for"
+#elif __cpp_range_based_for != 201603
+#  error "__cpp_range_based_for != 201603"
+#endif
+
+#ifndef __cpp_decltype
+#  error "__cpp_decltype"
+#elif __cpp_decltype != 200707
+#  error "__cpp_decltype != 200707"
+#endif
+
+#ifndef __cpp_attributes
+#  error "__cpp_attributes"
+#elif __cpp_attributes != 200809
+#  error "__cpp_attributes != 200809"
+#endif
+
+#ifndef __cpp_rvalue_references
+#  error "__cpp_rvalue_references"
+#elif __cpp_rvalue_references != 200610
+#  error "__cpp_rvalue_references != 200610"
+#endif
+
+#ifndef __cpp_variadic_templates
+#  error "__cpp_variadic_templates"
+#elif __cpp_variadic_templates != 200704
+#  error "__cpp_variadic_templates != 200704"
+#endif
+
+#ifndef __cpp_initializer_lists
+#  error "__cpp_initializer_lists"
+#elif __cpp_initializer_lists != 200806
+#  error "__cpp_initializer_lists != 200806"
+#endif
+
+#ifndef __cpp_delegating_constructors
+#  error "__cpp_delegating_constructors"
+#elif __cpp_delegating_constructors != 200604
+#  error "__cpp_delegating_constructors != 200604"
+#endif
+
+#ifndef __cpp_nsdmi
+#  error "__cpp_nsdmi"
+#elif __cpp_nsdmi != 200809
+#  error "__cpp_nsdmi != 200809"
+#endif
+
+#ifndef __cpp_inheriting_constructors
+#  error "__cpp_inheriting_constructors"
+#elif  __cpp_inheriting_constructors!= 201511
+#  error "__cpp_inheriting_constructors != 201511"
+#endif
+
+#ifndef __cpp_ref_qualifiers
+#  error "__cpp_ref_qualifiers"
+#elif __cpp_ref_qualifiers != 200710
+#  error "__cpp_ref_qualifiers != 200710"
+#endif
+
+#ifndef __cpp_alias_templates
+#  error "__cpp_alias_templates"
+#elif __cpp_alias_templates != 200704
+#  error "__cpp_alias_templates != 200704"
+#endif
+
+#ifndef __cpp_threadsafe_static_init
+#  error "__cpp_threadsafe_static_init"
+#elif __cpp_threadsafe_static_init != 200806
+#  error "__cpp_threadsafe_static_init != 200806"
+#endif
+
+//  C++14 features:
+
+#ifndef __cpp_binary_literals
+#  error "__cpp_binary_literals"
+#elif __cpp_binary_literals != 201304
+#  error "__cpp_binary_literals != 201304"
+#endif
+
+#ifndef __cpp_init_captures
+#  error "__cpp_init_captures"
+#elif __cpp_init_captures != 201304
+#  error "__cpp_init_captures != 201304"
+#endif
+
+#ifndef __cpp_generic_lambdas
+#  error "__cpp_generic_lambdas"
+#elif __cpp_generic_lambdas != 201304
+#  error "__cpp_generic_lambdas != 201304"
+#endif
+
+#ifndef __cpp_constexpr
+#  error "__cpp_constexpr"
+#elif __cpp_constexpr != 201603
+#  error "__cpp_constexpr != 201603"
+#endif
+
+#ifndef __cpp_decltype_auto
+#  error "__cpp_decltype_auto"
+#elif __cpp_decltype_auto != 201304
+#  error "__cpp_decltype_auto != 201304"
+#endif
+
+#ifndef __cpp_return_type_deduction
+#  error "__cpp_return_type_deduction"
+#elif __cpp_return_type_deduction != 201304
+#  error "__cpp_return_type_deduction != 201304"
+#endif
+
+#ifndef __cpp_aggregate_nsdmi
+#  error "__cpp_aggregate_nsdmi"
+#elif __cpp_aggregate_nsdmi != 201304
+#  error "__cpp_aggregate_nsdmi != 201304"
+#endif
+
+#ifndef __cpp_variable_templates
+#  error "__cpp_variable_templates"
+#elif __cpp_variable_templates != 201304
+#  error "__cpp_variable_templates != 201304"
+#endif
+
+#ifndef __cpp_digit_separators
+#  error "__cpp_digit_separators"
+#elif __cpp_digit_separators != 201309
+#  error "__cpp_digit_separators != 201309"
+#endif
+
+#ifndef __cpp_sized_deallocation
+#  error "__cpp_sized_deallocation"
+#elif __cpp_sized_deallocation != 201309
+#  error "__cpp_sized_deallocation != 201309"
+#endif
+
+//  GNU VLA support:
+
+#ifndef __cpp_runtime_arrays
+#  error "__cpp_runtime_arrays"
+#elif __cpp_runtime_arrays != 198712
+#  error "__cpp_runtime_arrays != 198712"
+#endif
+
+//  C++11 attributes:
+
+#ifdef __has_cpp_attribute
+#  if ! __has_cpp_attribute(noreturn)
+#    error "__has_cpp_attribute(noreturn)"
+#  elif __has_cpp_attribute(noreturn) != 200809
+#    error "__has_cpp_attribute(noreturn) != 200809"
+#  endif
+#else
+#  error "__has_cpp_attribute"
+#endif
+
+//  Attribute carries_dependency not in yet.
+//#ifdef __has_cpp_attribute
+//#  if ! __has_cpp_attribute(carries_dependency)
+//#    error "__has_cpp_attribute(carries_dependency)"
+//#  elif __has_cpp_attribute(carries_dependency) != 200809
+//#    error "__has_cpp_attribute(carries_dependency) != 200809"
+//#  endif
+//#else
+//#  error "__has_cpp_attribute"
+//#endif
+
+//  C++14 attributes:
+
+#ifdef __has_cpp_attribute
+#  if ! __has_cpp_attribute(deprecated)
+#    error "__has_cpp_attribute(deprecated)"
+#  elif __has_cpp_attribute(deprecated) != 201309
+#    error "__has_cpp_attribute(deprecated) != 201309"
+#  endif
+#else
+#  error "__has_cpp_attribute"
+#endif
+
+//  Include checks:
+
+//  Check for __has_include macro.
+#ifndef __has_include
+#  error "__has_include"
+#endif
+
+//  Quoted complex.h should find at least the bracket version (use operator).
+#if __has_include__ "complex.h"
+#else
+#  error "complex.h"
+#endif
+
+//  Try known bracket header (use operator).
+#if __has_include__(<complex>)
+#else
+#  error "<complex>"
+#endif
+
+//  Define and use a macro to invoke the operator.
+#define sluggo(TXT) __has_include__(TXT)
+
+#if sluggo(<complex>)
+#else
+#  error "<complex>"
+#endif
+
+#if ! sluggo(<complex>)
+#  error "<complex>"
+#else
+#endif
+
+//  Quoted complex.h should find at least the bracket version.
+#if __has_include("complex.h")
+#else
+#  error "complex.h"
+#endif
+
+//  Try known local quote header.
+#if __has_include("complex_literals.h")
+#else
+#  error "\"complex_literals.h\""
+#endif
+
+//  Try nonexistent bracket header.
+#if __has_include(<stuff>)
+#  error "<stuff>"
+#else
+#endif
+
+//  Try nonexistent quote header.
+#if __has_include("phlegm")
+#  error "\"phlegm\""
+#else
+#endif
+
+//  Test __has_include_next.
+#if __has_include("phoobhar.h")
+#  include "phoobhar.h"
+#else
+#  error "__has_include(\"phoobhar.h\")"
+#endif
+
+//  Try a macro.
+#define COMPLEX_INC "complex.h"
+#if __has_include(COMPLEX_INC)
+#else
+#  error COMPLEX_INC
+#endif
+
+//  Realistic use of __has_include.
+#if __has_include(<array>)
+#  define STD_ARRAY 1
+#  include <array>
+  template<typename _Tp, size_t _Num>
+    using array = std::array<_Tp, _Num>;
+#elif __has_include(<tr1/array>)
+#  define TR1_ARRAY 1
+#  include <tr1/array>
+  template<typename _Tp, size_t _Num>
+    typedef std::tr1::array<_Tp, _Num> array;
+#endif
+
+// C++17 features:
+
+#ifndef __cpp_unicode_characters
+#  error "__cpp_unicode_characters"
+#elif __cpp_unicode_characters != 201411
+#  error "__cpp_unicode_characters != 201411"
+#endif
+
+#ifndef __cpp_static_assert
+#  error "__cpp_static_assert"
+#elif __cpp_static_assert != 201411
+#  error "__cpp_static_assert != 201411"
+#endif
+
+#ifndef __cpp_namespace_attributes
+#  error "__cpp_namespace_attributes"
+#elif __cpp_namespace_attributes != 201411
+#  error "__cpp_namespace_attributes != 201411"
+#endif
+
+#ifndef __cpp_enumerator_attributes
+#  error "__cpp_enumerator_attributes"
+#elif __cpp_enumerator_attributes != 201411
+#  error "__cpp_enumerator_attributes != 201411"
+#endif
+
+#ifndef __cpp_nested_namespace_definitions
+#  error "__cpp_nested_namespace_definitions"
+#elif __cpp_nested_namespace_definitions != 201411
+#  error "__cpp_nested_namespace_definitions != 201411"
+#endif
+
+#ifndef __cpp_fold_expressions
+#  error "__cpp_fold_expressions"
+#elif __cpp_fold_expressions != 201603
+#  error "__cpp_fold_expressions != 201603"
+#endif
+
+#ifndef __cpp_nontype_template_args
+#  error "__cpp_nontype_template_args"
+#elif __cpp_nontype_template_args != 201411
+#  error "__cpp_nontype_template_args != 201411"
+#endif
+
+#ifndef __cpp_hex_float
+#  error "__cpp_hex_float"
+#elif __cpp_hex_float != 201603
+#  error "__cpp_hex_float != 201603"
+#endif
+
+#ifndef __cpp_aggregate_bases
+#  error "__cpp_aggregate_bases"
+#elif __cpp_aggregate_bases != 201603
+#  error "__cpp_aggregate_bases != 201603"
+#endif
+
+#ifndef __cpp_deduction_guides
+#  error "__cpp_deduction_guides"
+#elif __cpp_deduction_guides != 201703
+#  error "__cpp_deduction_guides != 201703"
+#endif
+
+#ifndef __cpp_if_constexpr
+#  error "__cpp_if_constexpr"
+#elif __cpp_if_constexpr != 201606
+#  error "__cpp_if_constexpr != 201606"
+#endif
+
+#ifndef __cpp_aligned_new
+#  error "__cpp_aligned_new"
+#elif __cpp_aligned_new != 201606
+#  error "__cpp_aligned_new != 201606"
+#endif
+
+#ifndef __cpp_template_auto
+#  error "__cpp_template_auto"
+#elif __cpp_template_auto != 201606
+#  error "__cpp_template_auto != 201606"
+#endif
+
+#ifndef __cpp_inline_variables
+#  error "__cpp_inline_variables"
+#elif __cpp_inline_variables != 201606
+#  error "__cpp_inline_variables != 201606"
+#endif
+
+#ifndef __cpp_capture_star_this
+#  error "__cpp_capture_star_this"
+#elif __cpp_capture_star_this != 201603
+#  error "__cpp_capture_star_this != 201603"
+#endif
+
+#ifndef __cpp_noexcept_function_type
+#  error "__cpp_noexcept_function_type"
+#elif __cpp_noexcept_function_type != 201510
+#  error "__cpp_noexcept_function_type != 201510"
+#endif
+
+#ifndef __cpp_structured_bindings
+#  error "__cpp_structured_bindings"
+#elif __cpp_structured_bindings != 201606
+#  error "__cpp_structured_bindings != 201606"
+#endif
+
+#ifndef __cpp_template_template_args
+#  error "__cpp_template_template_args"
+#elif __cpp_template_template_args != 201611
+#  error "__cpp_template_template_args != 201611"
+#endif
+
+#ifndef __cpp_variadic_using
+#  error "__cpp_variadic_using"
+#elif __cpp_variadic_using != 201611
+#  error "__cpp_variadic_using != 201611"
+#endif
+
+#ifdef __has_cpp_attribute
+
+#  if ! __has_cpp_attribute(maybe_unused)
+#    error "__has_cpp_attribute(maybe_unused)"
+#  elif __has_cpp_attribute(maybe_unused) != 201603
+#    error "__has_cpp_attribute(maybe_unused) != 201603"
+#  endif
+
+#  if ! __has_cpp_attribute(nodiscard)
+#    error "__has_cpp_attribute(nodiscard)"
+#  elif __has_cpp_attribute(nodiscard) != 201603
+#    error "__has_cpp_attribute(nodiscard) != 201603"
+#  endif
+
+#  if ! __has_cpp_attribute(fallthrough)
+#    error "__has_cpp_attribute(fallthrough)"
+#  elif __has_cpp_attribute(fallthrough) != 201603
+#    error "__has_cpp_attribute(fallthrough) != 201603"
+#  endif
+
+#  if ! __has_cpp_attribute(no_unique_address)
+#    error "__has_cpp_attribute(no_unique_address)"
+#  elif __has_cpp_attribute(no_unique_address) != 201803
+#    error "__has_cpp_attribute(no_unique_address) != 201803"
+#  endif
+
+#else
+#  error "__has_cpp_attribute"
+#endif


	Jakub

^ permalink raw reply	[flat|nested] 4+ messages in thread

* Re: [C++ PATCH] Fix up __has_cpp_attribute (no_unique_address)
  2018-10-10 14:36   ` [C++ PATCH] Fix up __has_cpp_attribute (no_unique_address) Jakub Jelinek
@ 2018-10-11  0:57     ` Jason Merrill
  0 siblings, 0 replies; 4+ messages in thread
From: Jason Merrill @ 2018-10-11  0:57 UTC (permalink / raw)
  To: Jakub Jelinek; +Cc: gcc-patches List

OK, thanks.
On Wed, Oct 10, 2018 at 10:02 AM Jakub Jelinek <jakub@redhat.com> wrote:
>
> On Wed, Oct 03, 2018 at 06:05:43PM +0200, Jakub Jelinek wrote:
> > On Wed, Oct 03, 2018 at 11:56:15AM -0400, Jason Merrill wrote:
> > > --- a/gcc/c-family/c-lex.c
> > > +++ b/gcc/c-family/c-lex.c
> > > @@ -356,6 +356,8 @@ c_common_has_attribute (cpp_reader *pfile)
> > >                    || is_attribute_p ("nodiscard", attr_name)
> > >                    || is_attribute_p ("fallthrough", attr_name))
> > >             result = 201603;
> > > +         else if (is_attribute_p ("no_unique_address", attr_name))
> > > +           result = 20180312;
> >
> > Seems for all other attributes we return either 0, 1 or yyyymm, you return
> > here yyyymmdd, is that intentional?  If users think it is yyyymm, then
> > they'd read it as December 201803.
>
> Jonathan verified that the value should be 201803, tested on x86_64-linux,
> ok for trunk?
>
> 2018-10-10  Jakub Jelinek  <jakub@redhat.com>
>
>         * c-lex.c (c_common_has_attribute): Return 201803 instead of 20180312
>         for no_unique_address.
>
>         * g++.dg/cpp2a/feat-cxx2a.C: New test.
>
> --- gcc/c-family/c-lex.c.jj     2018-10-08 15:18:36.665860856 +0200
> +++ gcc/c-family/c-lex.c        2018-10-10 15:48:46.180923864 +0200
> @@ -357,7 +357,7 @@ c_common_has_attribute (cpp_reader *pfil
>                        || is_attribute_p ("fallthrough", attr_name))
>                 result = 201603;
>               else if (is_attribute_p ("no_unique_address", attr_name))
> -               result = 20180312;
> +               result = 201803;
>               if (result)
>                 attr_name = NULL_TREE;
>             }
> --- gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C.jj  2018-10-10 15:52:00.896663247 +0200
> +++ gcc/testsuite/g++.dg/cpp2a/feat-cxx2a.C     2018-10-10 15:52:59.865675782 +0200
> @@ -0,0 +1,447 @@
> +// { dg-options "-std=c++2a -I${srcdir}/g++.dg/cpp1y -I${srcdir}/g++.dg/cpp1y/testinc" }
> +
> +//  C++98 features:
> +
> +#ifndef __cpp_rtti
> +#  error "__cpp_rtti"
> +#elif  __cpp_rtti != 199711
> +#  error "__cpp_rtti != 199711"
> +#endif
> +
> +#ifndef __cpp_exceptions
> +#  error "__cpp_exceptions"
> +#elif  __cpp_exceptions != 199711
> +#  error "__cpp_exceptions != 199711"
> +#endif
> +
> +//  C++11 features:
> +
> +#ifndef __cpp_raw_strings
> +#  error "__cpp_raw_strings"
> +#elif __cpp_raw_strings != 200710
> +#  error "__cpp_raw_strings != 200710"
> +#endif
> +
> +#ifndef __cpp_unicode_literals
> +#  error "__cpp_unicode_literals"
> +#elif __cpp_unicode_literals != 200710
> +#  error "__cpp_unicode_literals != 200710"
> +#endif
> +
> +#ifndef __cpp_user_defined_literals
> +#  error "__cpp_user_defined_literals"
> +#elif __cpp_user_defined_literals != 200809
> +#  error "__cpp_user_defined_literals != 200809"
> +#endif
> +
> +#ifndef __cpp_lambdas
> +#  error "__cpp_lambdas"
> +#elif __cpp_lambdas != 200907
> +#  error "__cpp_lambdas != 200907"
> +#endif
> +
> +#ifndef __cpp_range_based_for
> +#  error "__cpp_range_based_for"
> +#elif __cpp_range_based_for != 201603
> +#  error "__cpp_range_based_for != 201603"
> +#endif
> +
> +#ifndef __cpp_decltype
> +#  error "__cpp_decltype"
> +#elif __cpp_decltype != 200707
> +#  error "__cpp_decltype != 200707"
> +#endif
> +
> +#ifndef __cpp_attributes
> +#  error "__cpp_attributes"
> +#elif __cpp_attributes != 200809
> +#  error "__cpp_attributes != 200809"
> +#endif
> +
> +#ifndef __cpp_rvalue_references
> +#  error "__cpp_rvalue_references"
> +#elif __cpp_rvalue_references != 200610
> +#  error "__cpp_rvalue_references != 200610"
> +#endif
> +
> +#ifndef __cpp_variadic_templates
> +#  error "__cpp_variadic_templates"
> +#elif __cpp_variadic_templates != 200704
> +#  error "__cpp_variadic_templates != 200704"
> +#endif
> +
> +#ifndef __cpp_initializer_lists
> +#  error "__cpp_initializer_lists"
> +#elif __cpp_initializer_lists != 200806
> +#  error "__cpp_initializer_lists != 200806"
> +#endif
> +
> +#ifndef __cpp_delegating_constructors
> +#  error "__cpp_delegating_constructors"
> +#elif __cpp_delegating_constructors != 200604
> +#  error "__cpp_delegating_constructors != 200604"
> +#endif
> +
> +#ifndef __cpp_nsdmi
> +#  error "__cpp_nsdmi"
> +#elif __cpp_nsdmi != 200809
> +#  error "__cpp_nsdmi != 200809"
> +#endif
> +
> +#ifndef __cpp_inheriting_constructors
> +#  error "__cpp_inheriting_constructors"
> +#elif  __cpp_inheriting_constructors!= 201511
> +#  error "__cpp_inheriting_constructors != 201511"
> +#endif
> +
> +#ifndef __cpp_ref_qualifiers
> +#  error "__cpp_ref_qualifiers"
> +#elif __cpp_ref_qualifiers != 200710
> +#  error "__cpp_ref_qualifiers != 200710"
> +#endif
> +
> +#ifndef __cpp_alias_templates
> +#  error "__cpp_alias_templates"
> +#elif __cpp_alias_templates != 200704
> +#  error "__cpp_alias_templates != 200704"
> +#endif
> +
> +#ifndef __cpp_threadsafe_static_init
> +#  error "__cpp_threadsafe_static_init"
> +#elif __cpp_threadsafe_static_init != 200806
> +#  error "__cpp_threadsafe_static_init != 200806"
> +#endif
> +
> +//  C++14 features:
> +
> +#ifndef __cpp_binary_literals
> +#  error "__cpp_binary_literals"
> +#elif __cpp_binary_literals != 201304
> +#  error "__cpp_binary_literals != 201304"
> +#endif
> +
> +#ifndef __cpp_init_captures
> +#  error "__cpp_init_captures"
> +#elif __cpp_init_captures != 201304
> +#  error "__cpp_init_captures != 201304"
> +#endif
> +
> +#ifndef __cpp_generic_lambdas
> +#  error "__cpp_generic_lambdas"
> +#elif __cpp_generic_lambdas != 201304
> +#  error "__cpp_generic_lambdas != 201304"
> +#endif
> +
> +#ifndef __cpp_constexpr
> +#  error "__cpp_constexpr"
> +#elif __cpp_constexpr != 201603
> +#  error "__cpp_constexpr != 201603"
> +#endif
> +
> +#ifndef __cpp_decltype_auto
> +#  error "__cpp_decltype_auto"
> +#elif __cpp_decltype_auto != 201304
> +#  error "__cpp_decltype_auto != 201304"
> +#endif
> +
> +#ifndef __cpp_return_type_deduction
> +#  error "__cpp_return_type_deduction"
> +#elif __cpp_return_type_deduction != 201304
> +#  error "__cpp_return_type_deduction != 201304"
> +#endif
> +
> +#ifndef __cpp_aggregate_nsdmi
> +#  error "__cpp_aggregate_nsdmi"
> +#elif __cpp_aggregate_nsdmi != 201304
> +#  error "__cpp_aggregate_nsdmi != 201304"
> +#endif
> +
> +#ifndef __cpp_variable_templates
> +#  error "__cpp_variable_templates"
> +#elif __cpp_variable_templates != 201304
> +#  error "__cpp_variable_templates != 201304"
> +#endif
> +
> +#ifndef __cpp_digit_separators
> +#  error "__cpp_digit_separators"
> +#elif __cpp_digit_separators != 201309
> +#  error "__cpp_digit_separators != 201309"
> +#endif
> +
> +#ifndef __cpp_sized_deallocation
> +#  error "__cpp_sized_deallocation"
> +#elif __cpp_sized_deallocation != 201309
> +#  error "__cpp_sized_deallocation != 201309"
> +#endif
> +
> +//  GNU VLA support:
> +
> +#ifndef __cpp_runtime_arrays
> +#  error "__cpp_runtime_arrays"
> +#elif __cpp_runtime_arrays != 198712
> +#  error "__cpp_runtime_arrays != 198712"
> +#endif
> +
> +//  C++11 attributes:
> +
> +#ifdef __has_cpp_attribute
> +#  if ! __has_cpp_attribute(noreturn)
> +#    error "__has_cpp_attribute(noreturn)"
> +#  elif __has_cpp_attribute(noreturn) != 200809
> +#    error "__has_cpp_attribute(noreturn) != 200809"
> +#  endif
> +#else
> +#  error "__has_cpp_attribute"
> +#endif
> +
> +//  Attribute carries_dependency not in yet.
> +//#ifdef __has_cpp_attribute
> +//#  if ! __has_cpp_attribute(carries_dependency)
> +//#    error "__has_cpp_attribute(carries_dependency)"
> +//#  elif __has_cpp_attribute(carries_dependency) != 200809
> +//#    error "__has_cpp_attribute(carries_dependency) != 200809"
> +//#  endif
> +//#else
> +//#  error "__has_cpp_attribute"
> +//#endif
> +
> +//  C++14 attributes:
> +
> +#ifdef __has_cpp_attribute
> +#  if ! __has_cpp_attribute(deprecated)
> +#    error "__has_cpp_attribute(deprecated)"
> +#  elif __has_cpp_attribute(deprecated) != 201309
> +#    error "__has_cpp_attribute(deprecated) != 201309"
> +#  endif
> +#else
> +#  error "__has_cpp_attribute"
> +#endif
> +
> +//  Include checks:
> +
> +//  Check for __has_include macro.
> +#ifndef __has_include
> +#  error "__has_include"
> +#endif
> +
> +//  Quoted complex.h should find at least the bracket version (use operator).
> +#if __has_include__ "complex.h"
> +#else
> +#  error "complex.h"
> +#endif
> +
> +//  Try known bracket header (use operator).
> +#if __has_include__(<complex>)
> +#else
> +#  error "<complex>"
> +#endif
> +
> +//  Define and use a macro to invoke the operator.
> +#define sluggo(TXT) __has_include__(TXT)
> +
> +#if sluggo(<complex>)
> +#else
> +#  error "<complex>"
> +#endif
> +
> +#if ! sluggo(<complex>)
> +#  error "<complex>"
> +#else
> +#endif
> +
> +//  Quoted complex.h should find at least the bracket version.
> +#if __has_include("complex.h")
> +#else
> +#  error "complex.h"
> +#endif
> +
> +//  Try known local quote header.
> +#if __has_include("complex_literals.h")
> +#else
> +#  error "\"complex_literals.h\""
> +#endif
> +
> +//  Try nonexistent bracket header.
> +#if __has_include(<stuff>)
> +#  error "<stuff>"
> +#else
> +#endif
> +
> +//  Try nonexistent quote header.
> +#if __has_include("phlegm")
> +#  error "\"phlegm\""
> +#else
> +#endif
> +
> +//  Test __has_include_next.
> +#if __has_include("phoobhar.h")
> +#  include "phoobhar.h"
> +#else
> +#  error "__has_include(\"phoobhar.h\")"
> +#endif
> +
> +//  Try a macro.
> +#define COMPLEX_INC "complex.h"
> +#if __has_include(COMPLEX_INC)
> +#else
> +#  error COMPLEX_INC
> +#endif
> +
> +//  Realistic use of __has_include.
> +#if __has_include(<array>)
> +#  define STD_ARRAY 1
> +#  include <array>
> +  template<typename _Tp, size_t _Num>
> +    using array = std::array<_Tp, _Num>;
> +#elif __has_include(<tr1/array>)
> +#  define TR1_ARRAY 1
> +#  include <tr1/array>
> +  template<typename _Tp, size_t _Num>
> +    typedef std::tr1::array<_Tp, _Num> array;
> +#endif
> +
> +// C++17 features:
> +
> +#ifndef __cpp_unicode_characters
> +#  error "__cpp_unicode_characters"
> +#elif __cpp_unicode_characters != 201411
> +#  error "__cpp_unicode_characters != 201411"
> +#endif
> +
> +#ifndef __cpp_static_assert
> +#  error "__cpp_static_assert"
> +#elif __cpp_static_assert != 201411
> +#  error "__cpp_static_assert != 201411"
> +#endif
> +
> +#ifndef __cpp_namespace_attributes
> +#  error "__cpp_namespace_attributes"
> +#elif __cpp_namespace_attributes != 201411
> +#  error "__cpp_namespace_attributes != 201411"
> +#endif
> +
> +#ifndef __cpp_enumerator_attributes
> +#  error "__cpp_enumerator_attributes"
> +#elif __cpp_enumerator_attributes != 201411
> +#  error "__cpp_enumerator_attributes != 201411"
> +#endif
> +
> +#ifndef __cpp_nested_namespace_definitions
> +#  error "__cpp_nested_namespace_definitions"
> +#elif __cpp_nested_namespace_definitions != 201411
> +#  error "__cpp_nested_namespace_definitions != 201411"
> +#endif
> +
> +#ifndef __cpp_fold_expressions
> +#  error "__cpp_fold_expressions"
> +#elif __cpp_fold_expressions != 201603
> +#  error "__cpp_fold_expressions != 201603"
> +#endif
> +
> +#ifndef __cpp_nontype_template_args
> +#  error "__cpp_nontype_template_args"
> +#elif __cpp_nontype_template_args != 201411
> +#  error "__cpp_nontype_template_args != 201411"
> +#endif
> +
> +#ifndef __cpp_hex_float
> +#  error "__cpp_hex_float"
> +#elif __cpp_hex_float != 201603
> +#  error "__cpp_hex_float != 201603"
> +#endif
> +
> +#ifndef __cpp_aggregate_bases
> +#  error "__cpp_aggregate_bases"
> +#elif __cpp_aggregate_bases != 201603
> +#  error "__cpp_aggregate_bases != 201603"
> +#endif
> +
> +#ifndef __cpp_deduction_guides
> +#  error "__cpp_deduction_guides"
> +#elif __cpp_deduction_guides != 201703
> +#  error "__cpp_deduction_guides != 201703"
> +#endif
> +
> +#ifndef __cpp_if_constexpr
> +#  error "__cpp_if_constexpr"
> +#elif __cpp_if_constexpr != 201606
> +#  error "__cpp_if_constexpr != 201606"
> +#endif
> +
> +#ifndef __cpp_aligned_new
> +#  error "__cpp_aligned_new"
> +#elif __cpp_aligned_new != 201606
> +#  error "__cpp_aligned_new != 201606"
> +#endif
> +
> +#ifndef __cpp_template_auto
> +#  error "__cpp_template_auto"
> +#elif __cpp_template_auto != 201606
> +#  error "__cpp_template_auto != 201606"
> +#endif
> +
> +#ifndef __cpp_inline_variables
> +#  error "__cpp_inline_variables"
> +#elif __cpp_inline_variables != 201606
> +#  error "__cpp_inline_variables != 201606"
> +#endif
> +
> +#ifndef __cpp_capture_star_this
> +#  error "__cpp_capture_star_this"
> +#elif __cpp_capture_star_this != 201603
> +#  error "__cpp_capture_star_this != 201603"
> +#endif
> +
> +#ifndef __cpp_noexcept_function_type
> +#  error "__cpp_noexcept_function_type"
> +#elif __cpp_noexcept_function_type != 201510
> +#  error "__cpp_noexcept_function_type != 201510"
> +#endif
> +
> +#ifndef __cpp_structured_bindings
> +#  error "__cpp_structured_bindings"
> +#elif __cpp_structured_bindings != 201606
> +#  error "__cpp_structured_bindings != 201606"
> +#endif
> +
> +#ifndef __cpp_template_template_args
> +#  error "__cpp_template_template_args"
> +#elif __cpp_template_template_args != 201611
> +#  error "__cpp_template_template_args != 201611"
> +#endif
> +
> +#ifndef __cpp_variadic_using
> +#  error "__cpp_variadic_using"
> +#elif __cpp_variadic_using != 201611
> +#  error "__cpp_variadic_using != 201611"
> +#endif
> +
> +#ifdef __has_cpp_attribute
> +
> +#  if ! __has_cpp_attribute(maybe_unused)
> +#    error "__has_cpp_attribute(maybe_unused)"
> +#  elif __has_cpp_attribute(maybe_unused) != 201603
> +#    error "__has_cpp_attribute(maybe_unused) != 201603"
> +#  endif
> +
> +#  if ! __has_cpp_attribute(nodiscard)
> +#    error "__has_cpp_attribute(nodiscard)"
> +#  elif __has_cpp_attribute(nodiscard) != 201603
> +#    error "__has_cpp_attribute(nodiscard) != 201603"
> +#  endif
> +
> +#  if ! __has_cpp_attribute(fallthrough)
> +#    error "__has_cpp_attribute(fallthrough)"
> +#  elif __has_cpp_attribute(fallthrough) != 201603
> +#    error "__has_cpp_attribute(fallthrough) != 201603"
> +#  endif
> +
> +#  if ! __has_cpp_attribute(no_unique_address)
> +#    error "__has_cpp_attribute(no_unique_address)"
> +#  elif __has_cpp_attribute(no_unique_address) != 201803
> +#    error "__has_cpp_attribute(no_unique_address) != 201803"
> +#  endif
> +
> +#else
> +#  error "__has_cpp_attribute"
> +#endif
>
>
>         Jakub

^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2018-10-11  0:14 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-10-03 16:05 [C++ PATCH] Implement P0840, language support for empty objects Jason Merrill
2018-10-03 16:30 ` Jakub Jelinek
2018-10-10 14:36   ` [C++ PATCH] Fix up __has_cpp_attribute (no_unique_address) Jakub Jelinek
2018-10-11  0:57     ` Jason Merrill

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).