public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: Jason Merrill <jason@redhat.com>
To: "H.J. Lu" <hjl.tools@gmail.com>, Ulrich Weigand <uweigand@de.ibm.com>
Cc: GCC Patches <gcc-patches@gcc.gnu.org>,
	Jakub Jelinek <jakub@redhat.com>,
	       Richard Biener <richard.guenther@gmail.com>,
	       Markus Trippelsdorf <markus@trippelsdorf.de>,
	       Jakub Jelinek <jakub@redhat.com>
Subject: Re: PING^1: [PATCH] Add TYPE_EMPTY_RECORD for C++ empty class
Date: Tue, 15 Mar 2016 15:35:00 -0000	[thread overview]
Message-ID: <56E82BC4.7070401@redhat.com> (raw)
In-Reply-To: <CAMe9rOqF-B-he1JWaxq5++1a75vKtpECRAgcMDd+EbjdxQzLdQ@mail.gmail.com>

[-- Attachment #1: Type: text/plain, Size: 409 bytes --]

I'm concerned about how this patch changes both target-independent code 
and target-specific code, with a passing remark that other targets might 
need to make similar changes.  I'm also concerned about the effect of 
this on other languages that might not want the same change.  So, here's 
an alternative patch that implements the change in the front end (and 
includes your testcases, thanks!).

Thoughts?

[-- Attachment #2: empty-fe.patch --]
[-- Type: text/x-patch, Size: 28382 bytes --]

commit 96d0f7ffec807b5a6b71dd2fc2f6745f441fabe0
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Mar 11 13:39:52 2016 -0500

    	* class.c (is_really_empty_class): An unnamed bit-field doesn't
    	make a class non-empty.

diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index f6ad696..1027dad 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -8361,6 +8361,8 @@ is_really_empty_class (tree type)
       for (field = TYPE_FIELDS (type); field; field = DECL_CHAIN (field))
 	if (TREE_CODE (field) == FIELD_DECL
 	    && !DECL_ARTIFICIAL (field)
+	    /* An unnamed bit-field is not a data member.  */
+	    && (DECL_NAME (field) || !DECL_C_BIT_FIELD (field))
 	    && !is_really_empty_class (TREE_TYPE (field)))
 	  return false;
       return true;

commit 4a683e9e5e3b3ee824dbf86dd2ad7508ea4fdc3f
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Mar 11 13:40:02 2016 -0500

    	Pass empty class parameters like C.
    
    	* call.c (pass_as_empty_struct, empty_class_arg)
    	(warn_empty_class_abi): New.
    	(type_passed_as, build_x_va_arg): Use pass_as_empty_struct.
    	(build_call_a): Use empty_class_arg, warn_empty_class_abi.
    	* cp-tree.h (CPTI_EMPTY_STRUCT, empty_struct_type): New.
    	* decl.c (cxx_init_decl_processing): Create empty_struct_type.
    	(store_parm_decls): Use warn_empty_class_abi.

diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 3ad3bd5..d7cfb99 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -214,6 +214,8 @@ static void add_candidates (tree, tree, const vec<tree, va_gc> *, tree, tree,
 			    tsubst_flags_t);
 static conversion *merge_conversion_sequences (conversion *, conversion *);
 static tree build_temp (tree, tree, int, diagnostic_t *, tsubst_flags_t);
+static bool pass_as_empty_struct (tree type);
+static tree empty_class_arg (tree);
 
 /* Returns nonzero iff the destructor name specified in NAME matches BASETYPE.
    NAME can take many forms...  */
@@ -341,7 +343,6 @@ build_call_a (tree function, int n, tree *argarray)
   tree decl;
   tree result_type;
   tree fntype;
-  int i;
 
   function = build_addr_func (function, tf_warning_or_error);
 
@@ -379,16 +380,24 @@ build_call_a (tree function, int n, tree *argarray)
   /* Don't pass empty class objects by value.  This is useful
      for tags in STL, which are used to control overload resolution.
      We don't need to handle other cases of copying empty classes.  */
+  bool warned = false;
+  if (decl && !TREE_PUBLIC (decl))
+    /* Don't warn about the ABI of a function local to this TU.  */
+    warned = true;
   if (! decl || ! DECL_BUILT_IN (decl))
-    for (i = 0; i < n; i++)
+    for (int i = 0; i < n; i++)
       {
 	tree arg = CALL_EXPR_ARG (function, i);
-	if (is_empty_class (TREE_TYPE (arg))
-	    && ! TREE_ADDRESSABLE (TREE_TYPE (arg)))
+	tree type = TREE_TYPE (arg);
+	if (is_really_empty_class (type)
+	    && ! TREE_ADDRESSABLE (type))
 	  {
-	    tree t = build0 (EMPTY_CLASS_EXPR, TREE_TYPE (arg));
-	    arg = build2 (COMPOUND_EXPR, TREE_TYPE (t), arg, t);
-	    CALL_EXPR_ARG (function, i) = arg;
+	    location_t loc = EXPR_LOC_OR_LOC (arg, input_location);
+	    CALL_EXPR_ARG (function, i) = empty_class_arg (arg);
+	    /* Warn about ABI changes for a non-final argument.  */
+	    if (!warned && i < n-1
+		&& warn_empty_class_abi (arg, loc))
+	      warned = true;
 	  }
       }
 
@@ -6871,6 +6880,14 @@ build_x_va_arg (source_location loc, tree expr, tree type)
       expr = build_va_arg (loc, expr, ref);
       return convert_from_reference (expr);
     }
+  else if (is_really_empty_class (type) && !TREE_ADDRESSABLE (type))
+    {
+      /* Do the reverse of empty_class_arg.  */
+      tree etype = pass_as_empty_struct (type) ? empty_struct_type : type;
+      expr = build_va_arg (loc, expr, etype);
+      tree ec = build0 (EMPTY_CLASS_EXPR, type);
+      return build2 (COMPOUND_EXPR, type, expr, ec);
+    }
 
   return build_va_arg (loc, expr, type);
 }
@@ -6967,6 +6984,65 @@ convert_default_arg (tree type, tree arg, tree fn, int parmnum,
   return arg;
 }
 
+/* Return true iff TYPE should be passed and returned as a size 0 type rather
+   than its normal size, for compatibility with C.  */
+
+static bool
+pass_as_empty_struct (tree type)
+{
+  return (abi_version_at_least (10)
+	  && type != error_mark_node
+	  && COMPLETE_TYPE_P (type)
+	  && !TREE_ADDRESSABLE (type)
+	  && is_really_empty_class (type));
+}
+
+/* Adjust the value VAL of empty class type TYPE for argument passing.
+   Keep this synced with build_x_va_arg.  */
+
+static tree
+empty_class_arg (tree val)
+{
+  /* Don't pass empty class objects by value.  This is useful
+     for tags in STL, which are used to control overload resolution.
+     We don't need to handle other cases of copying empty classes.  */
+  tree type = TREE_TYPE (val);
+  tree etype = pass_as_empty_struct (type) ? empty_struct_type : type;
+  tree empty = build0 (EMPTY_CLASS_EXPR, etype);
+  return build2 (COMPOUND_EXPR, etype, val, empty);
+}
+
+/* Warn about the change in empty class parameter passing ABI.  Returns true
+   if we warned.  */
+
+bool
+warn_empty_class_abi (tree arg, location_t loc)
+{
+  if (!warn_abi || !abi_version_crosses (10))
+    return false;
+
+  tree type;
+  if (TYPE_P (arg))
+    type = arg;
+  else
+    {
+      if (TREE_TYPE (arg) == empty_struct_type
+	  && TREE_CODE (arg) == COMPOUND_EXPR)
+	arg = TREE_OPERAND (arg, 0);
+      type = TREE_TYPE (arg);
+    }
+
+  if (!dependent_type_p (type)
+      && !TREE_ADDRESSABLE (type)
+      && is_really_empty_class (type))
+    {
+      warning_at (loc, OPT_Wabi, "empty class %qT parameter passing ABI "
+	       "changes in -fabi-version=10 (GCC 6)", type);
+      return true;
+    }
+  return false;
+}
+
 /* Returns the type which will really be used for passing an argument of
    type TYPE.  */
 
@@ -6985,6 +7061,8 @@ type_passed_as (tree type)
 	   && COMPLETE_TYPE_P (type)
 	   && tree_int_cst_lt (TYPE_SIZE (type), TYPE_SIZE (integer_type_node)))
     type = integer_type_node;
+  else if (pass_as_empty_struct (type))
+    type = empty_struct_type;
 
   return type;
 }
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index a08c59b..3f24f7d 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -1150,6 +1150,8 @@ enum cp_tree_index
     CPTI_NULLPTR,
     CPTI_NULLPTR_TYPE,
 
+    CPTI_EMPTY_STRUCT,
+
     CPTI_MAX
 };
 
@@ -1185,6 +1187,7 @@ extern GTY(()) tree cp_global_trees[CPTI_MAX];
 #define current_aggr			cp_global_trees[CPTI_AGGR_TAG]
 #define nullptr_node			cp_global_trees[CPTI_NULLPTR]
 #define nullptr_type_node		cp_global_trees[CPTI_NULLPTR_TYPE]
+#define empty_struct_type		cp_global_trees[CPTI_EMPTY_STRUCT]
 
 /* We cache these tree nodes so as to call get_identifier less
    frequently.  */
@@ -5571,6 +5574,7 @@ extern tree build_addr_func			(tree, tsubst_flags_t);
 extern void set_flags_from_callee		(tree);
 extern tree build_call_a			(tree, int, tree*);
 extern tree build_call_n			(tree, int, ...);
+extern bool warn_empty_class_abi		(tree, location_t);
 extern bool null_ptr_cst_p			(tree);
 extern bool null_member_pointer_value_p		(tree);
 extern bool sufficient_parms_p			(const_tree);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 27c3597..4ee4ccc 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4145,6 +4145,10 @@ cxx_init_decl_processing (void)
     nullptr_node = build_int_cst (nullptr_type_node, 0);
   }
 
+  empty_struct_type = make_node (RECORD_TYPE);
+  finish_builtin_struct (empty_struct_type, "__empty_struct",
+			 NULL_TREE, NULL_TREE);
+
   abort_fndecl
     = build_library_fn_ptr ("__cxa_pure_virtual", void_ftype,
 			    ECF_NORETURN | ECF_NOTHROW);
@@ -14243,6 +14247,9 @@ store_parm_decls (tree current_function_parms)
 	     they end in the correct forward order.  */
       specparms = nreverse (specparms);
 
+      /* Don't warn about the ABI of a function local to this TU.  */
+      bool warned = (processing_template_decl
+		     || !TREE_PUBLIC (current_function_decl));
       for (parm = specparms; parm; parm = next)
 	{
 	  next = DECL_CHAIN (parm);
@@ -14253,6 +14260,13 @@ store_parm_decls (tree current_function_parms)
 		pushdecl (parm);
 	      else
 		error ("parameter %qD declared void", parm);
+	      /* If this isn't the last parameter, maybe warn about ABI change
+		 in passing empty classes.  */
+	      if (!warned
+		  && (parm != specparms
+		      || varargs_function_p (current_function_decl))
+		  && warn_empty_class_abi (parm, DECL_SOURCE_LOCATION (parm)))
+		warned = true;
 	    }
 	  else
 	    {
diff --git a/gcc/testsuite/g++.dg/abi/empty12.C b/gcc/testsuite/g++.dg/abi/empty12.C
new file mode 100644
index 0000000..ce1f6f2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/empty12.C
@@ -0,0 +1,17 @@
+// PR c++/60336
+// { dg-do run }
+// { dg-options "-Wabi=9 -x c" }
+// { dg-additional-sources "empty12a.c" }
+// { dg-prune-output "command line option" }
+
+#include "empty12.h"
+extern "C" void fun(struct dummy, struct foo);
+
+int main()
+{
+  struct dummy d;
+  struct foo f = { -1, -2, -3, -4, -5 };
+
+  fun(d, f); // { dg-warning "empty" }
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/abi/empty12.h b/gcc/testsuite/g++.dg/abi/empty12.h
new file mode 100644
index 0000000..c61afcd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/empty12.h
@@ -0,0 +1,9 @@
+struct dummy { };
+struct foo
+{
+  int i1;
+  int i2;
+  int i3;
+  int i4;
+  int i5;
+};
diff --git a/gcc/testsuite/g++.dg/abi/empty12a.c b/gcc/testsuite/g++.dg/abi/empty12a.c
new file mode 100644
index 0000000..34a25ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/empty12a.c
@@ -0,0 +1,6 @@
+#include "empty12.h"
+void fun(struct dummy d, struct foo f)
+{
+  if (f.i1 != -1)
+    __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/abi/empty13.C b/gcc/testsuite/g++.dg/abi/empty13.C
new file mode 100644
index 0000000..d1e0946
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/empty13.C
@@ -0,0 +1,17 @@
+// PR c++/60336
+// { dg-do run }
+// { dg-options "-x c -fabi-version=9" }
+// { dg-additional-sources "empty13a.c" }
+// { dg-prune-output "command line option" }
+
+#include "empty13.h"
+extern "C" void fun(struct dummy, struct foo);
+
+int main()
+{
+  struct dummy d;
+  struct foo f = { -1, -2, -3, -4, -5 };
+
+  fun(d, f);
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/abi/empty13.h b/gcc/testsuite/g++.dg/abi/empty13.h
new file mode 100644
index 0000000..c61afcd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/empty13.h
@@ -0,0 +1,9 @@
+struct dummy { };
+struct foo
+{
+  int i1;
+  int i2;
+  int i3;
+  int i4;
+  int i5;
+};
diff --git a/gcc/testsuite/g++.dg/abi/empty13a.c b/gcc/testsuite/g++.dg/abi/empty13a.c
new file mode 100644
index 0000000..b4303a6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/empty13a.c
@@ -0,0 +1,6 @@
+#include "empty13.h"
+void fun(struct dummy d, struct foo f)
+{
+  if (f.i1 == -1)
+    __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/abi/empty14.C b/gcc/testsuite/g++.dg/abi/empty14.C
new file mode 100644
index 0000000..1b9c397
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/empty14.C
@@ -0,0 +1,17 @@
+// PR c++/60336
+// { dg-do run }
+// { dg-options "-Wabi=9 -x c" }
+// { dg-additional-sources "empty14a.c" }
+// { dg-prune-output "command line option" }
+
+#include "empty14.h"
+extern "C" void fun(struct dummy, struct foo);
+
+int main()
+{
+  struct dummy d;
+  struct foo f = { -1, -2, -3, -4, -5 };
+
+  fun(d, f); // { dg-warning "empty" }
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/abi/empty14.h b/gcc/testsuite/g++.dg/abi/empty14.h
new file mode 100644
index 0000000..5842279
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/empty14.h
@@ -0,0 +1,10 @@
+struct dummy0 { };
+struct dummy { struct dummy0 d[140]; };
+struct foo
+{
+  int i1;
+  int i2;
+  int i3;
+  int i4;
+  int i5;
+};
diff --git a/gcc/testsuite/g++.dg/abi/empty14a.c b/gcc/testsuite/g++.dg/abi/empty14a.c
new file mode 100644
index 0000000..8b3d780
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/empty14a.c
@@ -0,0 +1,6 @@
+#include "empty14.h"
+void fun(struct dummy d, struct foo f)
+{
+  if (f.i1 != -1)
+    __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/abi/empty15.C b/gcc/testsuite/g++.dg/abi/empty15.C
new file mode 100644
index 0000000..ac0a868
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/empty15.C
@@ -0,0 +1,17 @@
+// PR c++/60336
+// { dg-do run }
+// { dg-options "-Wabi=9 -x c" }
+// { dg-additional-sources "empty15a.c" }
+// { dg-prune-output "command line option" }
+
+#include "empty15.h"
+extern "C" void fun(struct dummy, struct foo);
+
+int main()
+{
+  struct dummy d;
+  struct foo f = { -1, -2, -3, -4, -5 };
+
+  fun(d, f); // { dg-warning "empty" }
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/abi/empty15.h b/gcc/testsuite/g++.dg/abi/empty15.h
new file mode 100644
index 0000000..1c6f26f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/empty15.h
@@ -0,0 +1,30 @@
+struct A1 {};
+struct A2 {};
+struct B1 { struct A1 a; struct A2 b; };
+struct B2 { struct A1 a; struct A2 b; };
+struct C1 { struct B1 a; struct B2 b; };
+struct C2 { struct B1 a; struct B2 b; };
+struct D1 { struct C1 a; struct C2 b; };
+struct D2 { struct C1 a; struct C2 b; };
+struct E1 { struct D1 a; struct D2 b; };
+struct E2 { struct D1 a; struct D2 b; };
+struct F1 { struct E1 a; struct E2 b; };
+struct F2 { struct E1 a; struct E2 b; };
+struct G1 { struct F1 a; struct F2 b; };
+struct G2 { struct F1 a; struct F2 b; };
+struct H1 { struct G1 a; struct G2 b; };
+struct H2 { struct G1 a; struct G2 b; };
+struct I1 { struct H1 a; struct H2 b; };
+struct I2 { struct H1 a; struct H2 b; };
+struct J1 { struct I1 a; struct I2 b; };
+struct J2 { struct I1 a; struct I2 b; };
+struct dummy { struct J1 a; struct J2 b; };
+
+struct foo
+{
+  int i1;
+  int i2;
+  int i3;
+  int i4;
+  int i5;
+};
diff --git a/gcc/testsuite/g++.dg/abi/empty15a.c b/gcc/testsuite/g++.dg/abi/empty15a.c
new file mode 100644
index 0000000..325b2c5
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/empty15a.c
@@ -0,0 +1,6 @@
+#include "empty15.h"
+void fun(struct dummy d, struct foo f)
+{
+  if (f.i1 != -1)
+    __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/abi/empty16.C b/gcc/testsuite/g++.dg/abi/empty16.C
new file mode 100644
index 0000000..de2bf5c
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/empty16.C
@@ -0,0 +1,17 @@
+// PR c++/60336
+// { dg-do run }
+// { dg-options "-Wabi=9 -x c" }
+// { dg-additional-sources "empty16a.c" }
+// { dg-prune-output "command line option" }
+
+#include "empty16.h"
+extern "C" void fun(struct dummy, struct foo);
+
+int main()
+{
+  struct dummy d;
+  struct foo f = { -1, -2, -3, -4, -5 };
+
+  fun(d, f); // { dg-warning "empty" }
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/abi/empty16.h b/gcc/testsuite/g++.dg/abi/empty16.h
new file mode 100644
index 0000000..7552ae0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/empty16.h
@@ -0,0 +1,16 @@
+#ifdef __cplusplus
+struct A1 {};
+struct A2 {};
+struct dummy : A1, A2 {} ;
+#else
+struct dummy {};
+#endif
+
+struct foo
+{
+  int i1;
+  int i2;
+  int i3;
+  int i4;
+  int i5;
+};
diff --git a/gcc/testsuite/g++.dg/abi/empty16a.c b/gcc/testsuite/g++.dg/abi/empty16a.c
new file mode 100644
index 0000000..6cb7fbc
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/empty16a.c
@@ -0,0 +1,6 @@
+#include "empty16.h"
+void fun(struct dummy d, struct foo f)
+{
+  if (f.i1 != -1)
+    __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/abi/empty17.C b/gcc/testsuite/g++.dg/abi/empty17.C
new file mode 100644
index 0000000..c7a37c0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/empty17.C
@@ -0,0 +1,17 @@
+// PR c++/60336
+// { dg-do run }
+// { dg-options "-Wabi=9 -x c" }
+// { dg-additional-sources "empty17a.c" }
+// { dg-prune-output "command line option" }
+
+#include "empty17.h"
+extern "C" void fun(struct dummy, struct foo);
+
+int main()
+{
+  struct dummy d;
+  struct foo f = { -1, -2, -3, -4, -5 };
+
+  fun(d, f); // { dg-warning "empty" }
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/abi/empty17.h b/gcc/testsuite/g++.dg/abi/empty17.h
new file mode 100644
index 0000000..9cf72ba
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/empty17.h
@@ -0,0 +1,27 @@
+#ifdef __cplusplus
+struct A1
+{
+  void foo (void);
+  unsigned int : 15;
+};
+struct A2
+{
+  void bar (void);
+  unsigned int : 15;
+};
+struct dummy : A1, A2
+{
+  unsigned int : 15;
+};
+#else
+struct dummy {};
+#endif
+
+struct foo
+{
+  int i1;
+  int i2;
+  int i3;
+  int i4;
+  int i5;
+};
diff --git a/gcc/testsuite/g++.dg/abi/empty17a.c b/gcc/testsuite/g++.dg/abi/empty17a.c
new file mode 100644
index 0000000..24408fd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/empty17a.c
@@ -0,0 +1,6 @@
+#include "empty17.h"
+void fun(struct dummy d, struct foo f)
+{
+  if (f.i1 != -1)
+    __builtin_abort();
+}
diff --git a/gcc/testsuite/g++.dg/abi/pr60336-1.C b/gcc/testsuite/g++.dg/abi/pr60336-1.C
new file mode 100644
index 0000000..af08638
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/pr60336-1.C
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-options "-O2 -std=c++11 -fno-pic" }
+// { dg-require-effective-target fpic }
+
+struct dummy { };
+struct true_type { struct dummy i; };
+
+extern true_type y;
+extern void xxx (true_type c);
+
+void
+yyy (void)
+{
+  xxx (y);
+}
+
+// { dg-final { scan-assembler "jmp\[\t \]+\[^\$\]*?_Z3xxx9true_type" { target i?86-*-* x86_64-*-* } } }
diff --git a/gcc/testsuite/g++.dg/abi/pr60336-10.C b/gcc/testsuite/g++.dg/abi/pr60336-10.C
new file mode 100644
index 0000000..6c9c990
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/pr60336-10.C
@@ -0,0 +1,50 @@
+// { dg-do run }
+// { dg-options "-O2" }
+
+#include <stdarg.h>
+
+struct dummy0 { };
+struct dummy1 { };
+struct dummy : dummy0, dummy1 { };
+
+void
+test (struct dummy a, int m, ...)
+{
+  va_list va_arglist;
+  int i;
+  int count = 0;
+
+  if (m == 0)
+    count++;
+  va_start (va_arglist, m);
+  i = va_arg (va_arglist, int);
+  if (i == 1)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 2)
+  i = va_arg (va_arglist, int);
+    count++;
+  if (i == 3)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 4)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 5)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 6)
+    count++;
+  va_end (va_arglist);
+  if (count != 7)
+    __builtin_abort ();
+}
+
+struct dummy a0;
+
+int
+main ()
+{
+  test (a0, 0, 1, 2, 3, 4, 5, 6);
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/abi/pr60336-11.C b/gcc/testsuite/g++.dg/abi/pr60336-11.C
new file mode 100644
index 0000000..c92f3d4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/pr60336-11.C
@@ -0,0 +1,56 @@
+// { dg-do run }
+// { dg-options "-O2" }
+
+#include <stdarg.h>
+
+struct dummy0
+{
+  void bar (void);
+};
+struct dummy1
+{
+  void foo (void);
+};
+struct dummy : dummy0, dummy1 { };
+
+void
+test (struct dummy a, int m, ...)
+{
+  va_list va_arglist;
+  int i;
+  int count = 0;
+
+  if (m == 0)
+    count++;
+  va_start (va_arglist, m);
+  i = va_arg (va_arglist, int);
+  if (i == 1)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 2)
+  i = va_arg (va_arglist, int);
+    count++;
+  if (i == 3)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 4)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 5)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 6)
+    count++;
+  va_end (va_arglist);
+  if (count != 7)
+    __builtin_abort ();
+}
+
+struct dummy a0;
+
+int
+main ()
+{
+  test (a0, 0, 1, 2, 3, 4, 5, 6);
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/abi/pr60336-12.C b/gcc/testsuite/g++.dg/abi/pr60336-12.C
new file mode 100644
index 0000000..83a7bb0
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/pr60336-12.C
@@ -0,0 +1,57 @@
+// { dg-do run }
+// { dg-options "-O2" }
+
+#include <stdarg.h>
+
+struct dummy0
+{
+};
+struct dummy1
+{
+  unsigned : 15;
+};
+struct dummy : dummy0, dummy1
+{
+};
+
+void
+test (struct dummy a, int m, ...)
+{
+  va_list va_arglist;
+  int i;
+  int count = 0;
+
+  if (m == 0)
+    count++;
+  va_start (va_arglist, m);
+  i = va_arg (va_arglist, int);
+  if (i == 1)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 2)
+  i = va_arg (va_arglist, int);
+    count++;
+  if (i == 3)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 4)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 5)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 6)
+    count++;
+  va_end (va_arglist);
+  if (count != 7)
+    __builtin_abort ();
+}
+
+struct dummy a0;
+
+int
+main ()
+{
+  test (a0, 0, 1, 2, 3, 4, 5, 6);
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/abi/pr60336-2.C b/gcc/testsuite/g++.dg/abi/pr60336-2.C
new file mode 100644
index 0000000..32eecb3
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/pr60336-2.C
@@ -0,0 +1,48 @@
+// { dg-do run }
+// { dg-options "-O2 -Wabi=9" }
+
+#include <stdarg.h>
+
+struct dummy { };
+
+void
+test (struct dummy a, int m, ...) // { dg-message "empty" }
+{
+  va_list va_arglist;
+  int i;
+  int count = 0;
+
+  if (m == 0)
+    count++;
+  va_start (va_arglist, m);
+  i = va_arg (va_arglist, int);
+  if (i == 1)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 2)
+  i = va_arg (va_arglist, int);
+    count++;
+  if (i == 3)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 4)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 5)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 6)
+    count++;
+  va_end (va_arglist);
+  if (count != 7)
+    __builtin_abort ();
+}
+
+struct dummy a0;
+
+int
+main ()
+{
+  test (a0, 0, 1, 2, 3, 4, 5, 6); // { dg-message "empty" }
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/abi/pr60336-3.C b/gcc/testsuite/g++.dg/abi/pr60336-3.C
new file mode 100644
index 0000000..8ebd4dd
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/pr60336-3.C
@@ -0,0 +1,15 @@
+// { dg-do compile }
+// { dg-options "-O2 -Wabi=9" }
+
+struct dummy { struct{}__attribute__((aligned (4))) a[7]; };
+
+extern void test1 (struct dummy, ...);
+extern void (*test2) (struct dummy, ...);
+
+void
+foo ()
+{
+  struct dummy a0;
+  test1 (a0, 42); // { dg-message "empty" }
+  test2 (a0, 42); // { dg-message "empty" }
+}
diff --git a/gcc/testsuite/g++.dg/abi/pr60336-4.C b/gcc/testsuite/g++.dg/abi/pr60336-4.C
new file mode 100644
index 0000000..8790a66
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/pr60336-4.C
@@ -0,0 +1,48 @@
+// { dg-do run { target { { i?86-*-* x86_64-*-* } && { ! { ia32 } } } } }
+// { dg-options "-O2 -fabi-version=9" }
+
+#include <stdarg.h>
+
+struct dummy { };
+
+void
+test (struct dummy a, int m, ...)
+{
+  va_list va_arglist;
+  int i;
+  int count = 0;
+
+  if (m == 0)
+    count++;
+  va_start (va_arglist, m);
+  i = va_arg (va_arglist, int);
+  if (i == 1)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 2)
+  i = va_arg (va_arglist, int);
+    count++;
+  if (i == 3)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 4)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 5)
+    count++;
+  i = va_arg (va_arglist, int);
+  if (i == 6)
+    count++;
+  va_end (va_arglist);
+  if (count == 7)
+    __builtin_abort ();
+}
+
+struct dummy a0;
+
+int
+main ()
+{
+  test (a0, 0, 1, 2, 3, 4, 5, 6);
+  return 0;
+}
diff --git a/gcc/testsuite/g++.dg/abi/pr60336-5.C b/gcc/testsuite/g++.dg/abi/pr60336-5.C
new file mode 100644
index 0000000..b0c76ad
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/pr60336-5.C
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-options "-O2 -std=c++11 -fno-pic" }
+// { dg-require-effective-target fpic }
+
+struct dummy { };
+struct true_type { struct dummy i; struct dummy j; };
+
+extern true_type y;
+extern void xxx (true_type c);
+
+void
+yyy (void)
+{
+  xxx (y);
+}
+
+// { dg-final { scan-assembler "jmp\[\t \]+\[^\$\]*?_Z3xxx9true_type" { target i?86-*-* x86_64-*-* } } }
diff --git a/gcc/testsuite/g++.dg/abi/pr60336-6.C b/gcc/testsuite/g++.dg/abi/pr60336-6.C
new file mode 100644
index 0000000..5879651
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/pr60336-6.C
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-options "-O2 -std=c++11 -fno-pic" }
+// { dg-require-effective-target fpic }
+
+struct dummy { };
+struct true_type { struct dummy i1; struct dummy i2; };
+
+extern true_type y;
+extern void xxx (true_type c);
+
+void
+yyy (void)
+{
+  xxx (y);
+}
+
+// { dg-final { scan-assembler "jmp\[\t \]+\[^\$\]*?_Z3xxx9true_type" { target i?86-*-* x86_64-*-* } } }
diff --git a/gcc/testsuite/g++.dg/abi/pr60336-7.C b/gcc/testsuite/g++.dg/abi/pr60336-7.C
new file mode 100644
index 0000000..0e5d2ef
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/pr60336-7.C
@@ -0,0 +1,17 @@
+// { dg-do compile }
+// { dg-options "-O2 -std=c++11 -fno-pic" }
+// { dg-require-effective-target fpic }
+
+struct dummy { };
+struct true_type { struct dummy i[120]; };
+
+extern true_type y;
+extern void xxx (true_type c);
+
+void
+yyy (void)
+{
+  xxx (y);
+}
+
+// { dg-final { scan-assembler "jmp\[\t \]+\[^\$\]*?_Z3xxx9true_type" { target i?86-*-* x86_64-*-* } } }
diff --git a/gcc/testsuite/g++.dg/abi/pr60336-8.C b/gcc/testsuite/g++.dg/abi/pr60336-8.C
new file mode 100644
index 0000000..fdfc924
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/pr60336-8.C
@@ -0,0 +1,15 @@
+// { dg-do compile }
+// { dg-options "-O2 -Wabi=9" }
+
+struct dummy { struct{} a[7][3]; };
+
+extern void test1 (struct dummy, ...);
+extern void (*test2) (struct dummy, ...);
+
+void
+foo ()
+{
+  struct dummy a0;
+  test1 (a0, 42); // { dg-message "empty" }
+  test2 (a0, 42); // { dg-message "empty" }
+}
diff --git a/gcc/testsuite/g++.dg/abi/pr60336-9.C b/gcc/testsuite/g++.dg/abi/pr60336-9.C
new file mode 100644
index 0000000..4ad333f
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/pr60336-9.C
@@ -0,0 +1,28 @@
+// { dg-do compile }
+// { dg-options "-O2 -std=c++11 -fno-pic" }
+// { dg-require-effective-target fpic }
+
+struct A1 {}; struct A2 {};
+struct B1 { A1 a; A2 b; }; struct B2 { A1 a; A2 b; };
+struct C1 { B1 a; B2 b; }; struct C2 { B1 a; B2 b; };
+struct D1 { C1 a; C2 b; }; struct D2 { C1 a; C2 b; };
+struct E1 { D1 a; D2 b; }; struct E2 { D1 a; D2 b; };
+struct F1 { E1 a; E2 b; }; struct F2 { E1 a; E2 b; };
+struct G1 { F1 a; F2 b; }; struct G2 { F1 a; F2 b; };
+struct H1 { G1 a; G2 b; }; struct H2 { G1 a; G2 b; };
+struct I1 { H1 a; H2 b; }; struct I2 { H1 a; H2 b; };
+struct J1 { I1 a; I2 b; }; struct J2 { I1 a; I2 b; };
+struct dummy { J1 a; J2 b; };
+
+struct true_type { struct dummy i; };
+
+extern true_type y;
+extern void xxx (true_type c);
+
+void
+yyy (void)
+{
+  xxx (y);
+}
+
+// { dg-final { scan-assembler "jmp\[\t \]+\[^\$\]*?_Z3xxx9true_type" { target i?86-*-* x86_64-*-* } } }
diff --git a/gcc/testsuite/g++.dg/abi/pr68355.C b/gcc/testsuite/g++.dg/abi/pr68355.C
new file mode 100644
index 0000000..1354fc4
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/pr68355.C
@@ -0,0 +1,24 @@
+// { dg-do compile }
+// { dg-options "-O2 -std=c++11 -fno-pic" }
+// { dg-require-effective-target fpic }
+
+template<typename _Tp, _Tp __v>
+struct integral_constant
+{
+  static constexpr _Tp value = __v;
+  typedef _Tp value_type;
+  typedef integral_constant<_Tp, __v> type;
+  constexpr operator value_type() const { return value; }
+};
+
+typedef integral_constant<bool, true> true_type;
+extern void xxx (true_type c);
+
+void
+yyy (void)
+{
+  true_type y;
+  xxx (y);
+}
+
+// { dg-final { scan-assembler "jmp\[\t \]+\[^\$\]*?_Z3xxx17integral_constantIbLb1EE" { target i?86-*-* x86_64-*-* } } }

commit b3d57318c2372703cf725d4cfd3752bc1f2a65fa
Author: Jason Merrill <jason@redhat.com>
Date:   Thu Mar 10 13:56:16 2016 -0500

    wabi

diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4
index 95df24a..94fde7e 100644
--- a/libstdc++-v3/acinclude.m4
+++ b/libstdc++-v3/acinclude.m4
@@ -765,7 +765,7 @@ AC_DEFUN([GLIBCXX_EXPORT_FLAGS], [
   # OPTIMIZE_CXXFLAGS = -O3 -fstrict-aliasing -fvtable-gc
   AC_SUBST(OPTIMIZE_CXXFLAGS)
 
-  WARN_FLAGS='-Wall -Wextra -Wwrite-strings -Wcast-qual -Wabi'
+  WARN_FLAGS='-Wall -Wextra -Wwrite-strings -Wcast-qual -Werror=abi -Wabi=9'
   AC_SUBST(WARN_FLAGS)
 ])
 
diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure
index acbc6a6..4913211 100755
--- a/libstdc++-v3/configure
+++ b/libstdc++-v3/configure
@@ -81354,7 +81354,7 @@ $as_echo "$gxx_include_dir" >&6; }
   # OPTIMIZE_CXXFLAGS = -O3 -fstrict-aliasing -fvtable-gc
 
 
-  WARN_FLAGS='-Wall -Wextra -Wwrite-strings -Wcast-qual -Wabi'
+  WARN_FLAGS='-Wall -Wextra -Wwrite-strings -Wcast-qual -Werror=abi -Wabi=9'
 
 
 

  reply	other threads:[~2016-03-15 15:35 UTC|newest]

Thread overview: 52+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-12-08 16:22 H.J. Lu
2015-12-09 14:05 ` Richard Biener
2015-12-09 18:53   ` H.J. Lu
2015-12-09 21:14     ` H.J. Lu
2015-12-09 21:31     ` Markus Trippelsdorf
2015-12-10 11:24       ` Richard Biener
2015-12-11 23:52         ` H.J. Lu
2015-12-12 14:51           ` Jason Merrill
2015-12-12 15:27             ` Jakub Jelinek
2015-12-12 16:45               ` H.J. Lu
2015-12-12 18:43               ` Marc Glisse
2015-12-14 20:16                 ` Jason Merrill
2015-12-14 20:39                   ` H.J. Lu
2015-12-14 20:44                     ` Jason Merrill
2015-12-14 22:08                       ` H.J. Lu
2016-01-26 19:27                         ` Jason Merrill
2016-01-26 19:52                           ` H.J. Lu
2016-01-26 20:23                             ` Marc Glisse
2016-01-26 20:26                               ` H.J. Lu
2016-01-26 20:44                                 ` Marc Glisse
2016-01-26 21:21                                   ` H.J. Lu
2016-01-26 21:40                                     ` Jakub Jelinek
2016-01-26 22:21                                       ` H.J. Lu
2016-01-27  8:10                                         ` Marc Glisse
2016-01-27  8:21                                           ` Jakub Jelinek
2016-01-27  9:03                                             ` Marc Glisse
2016-01-27 13:46                                               ` H.J. Lu
2016-01-27 15:39                                                 ` H.J. Lu
2016-03-01  1:02                                                   ` Jason Merrill
2016-03-01 22:44                                                     ` H.J. Lu
2016-03-02 16:25                                                       ` Ulrich Weigand
2016-03-02 17:34                                                         ` H.J. Lu
2016-03-15 15:35                                                           ` Jason Merrill [this message]
2016-03-15 16:00                                                             ` H.J. Lu
2016-03-15 19:32                                                               ` Jason Merrill
2016-03-16 12:38                                                                 ` H.J. Lu
2016-03-16 16:58                                                                   ` Jason Merrill
2016-03-16 17:02                                                                     ` H.J. Lu
2016-03-16 19:39                                                                       ` H.J. Lu
2016-03-16 19:43                                                                         ` Jason Merrill
2016-03-15 21:40                                                             ` Joseph Myers
2016-03-15 22:31                                                               ` H.J. Lu
2016-03-15 22:35                                                                 ` Joseph Myers
2016-03-16  0:23                                                                   ` H.J. Lu
2016-03-16  0:25                                                                     ` Joseph Myers
2016-03-16  2:17                                                                       ` H.J. Lu
2016-03-16  9:46                                                                         ` Bernhard Reutner-Fischer
2016-03-16 11:53                                                                           ` H.J. Lu
2016-03-16  2:51                                                                       ` Jason Merrill
2016-03-16 11:55                                                                         ` H.J. Lu
2016-03-16 14:33                                                                           ` Jason Merrill
2016-03-16 14:48                                                                             ` H.J. Lu

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=56E82BC4.7070401@redhat.com \
    --to=jason@redhat.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=hjl.tools@gmail.com \
    --cc=jakub@redhat.com \
    --cc=markus@trippelsdorf.de \
    --cc=richard.guenther@gmail.com \
    --cc=uweigand@de.ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).