This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH for c++/65945 (nullptr_t alignment)


It's trivial to fix the alignment of nullptr_t, but I was concerned about ABI impact. On further research it seems that it won't cause any trouble with argument alignment, since that doesn't seem to rely on TYPE_ALIGN at all; I think the only ABI breakage would come from unaligned nullptr_t fields in classes, which I expect to be very rare. The testcases that were breaking on SPARC and ARM without this fix have to do with local stack slots, which are not part of an interface.

Activating the warning requires passing an explicit version number to -Wabi, e.g. -Wabi=8.

Tested x86_64-pc-linux-gnu, applying to trunk and 5.
commit 6ec8347672eec505f13f03f3612a847327a96815
Author: Jason Merrill <jason@redhat.com>
Date:   Fri Jun 19 15:29:33 2015 -0400

    	PR c++/65945
    gcc/c-family/
    	* c-opts.c (c_common_post_options): Highest ABI version is 9.
    gcc/cp/
    	* decl.c (cxx_init_decl_processing): Set TYPE_ALIGN of nullptr_t.
    	* class.c (layout_nonempty_base_or_field): Warn if that affects
    	the offset of a field.

diff --git a/gcc/c-family/c-opts.c b/gcc/c-family/c-opts.c
index 1a67b5a..718a052 100644
--- a/gcc/c-family/c-opts.c
+++ b/gcc/c-family/c-opts.c
@@ -889,7 +889,7 @@ c_common_post_options (const char **pfilename)
   /* Change flag_abi_version to be the actual current ABI level for the
      benefit of c_cpp_builtins.  */
   if (flag_abi_version == 0)
-    flag_abi_version = 8;
+    flag_abi_version = 9;
 
   if (cxx_dialect >= cxx11)
     {
diff --git a/gcc/common.opt b/gcc/common.opt
index e5553cd..1218a71 100644
--- a/gcc/common.opt
+++ b/gcc/common.opt
@@ -833,6 +833,9 @@ Driver Undocumented
 ; 8: The version of the ABI that corrects the substitution behavior of
 ;    function types with function-cv-qualifiers.
 ;    First selectable in G++ 4.9 and default in G++ 5
+;
+; 9: The version of the ABI that corrects the alignment of nullptr_t.
+;    First selectable and default in G++ 5.2.
 ;    (set in c_common_post_options).
 ;
 ; Additional positive integers will be assigned as new versions of
diff --git a/gcc/cp/class.c b/gcc/cp/class.c
index 12e62df..d59d351 100644
--- a/gcc/cp/class.c
+++ b/gcc/cp/class.c
@@ -4286,6 +4286,25 @@ layout_nonempty_base_or_field (record_layout_info rli,
 				       : TYPE_ALIGN (type)));
 	  normalize_rli (rli);
 	}
+      else if (TREE_CODE (type) == NULLPTR_TYPE
+	       && warn_abi && abi_version_crosses (9))
+	{
+	  /* Before ABI v9, we were giving nullptr_t alignment of 1; if
+	     the offset wasn't aligned like a pointer when we started to
+	     layout this field, that affects its position.  */
+	  tree pos = rli_size_unit_so_far (&old_rli);
+	  if (int_cst_value (pos) % TYPE_ALIGN_UNIT (ptr_type_node) != 0)
+	    {
+	      if (abi_version_at_least (9))
+		warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wabi,
+			    "alignment of %qD increased in -fabi-version=9 "
+			    "(GCC 5.2)", decl);
+	      else
+		warning_at (DECL_SOURCE_LOCATION (decl), OPT_Wabi, "alignment "
+			    "of %qD will increase in -fabi-version=9", decl);
+	    }
+	  break;
+	}
       else
 	/* There was no conflict.  We're done laying out this field.  */
 	break;
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index 0adb3ce..d24b02a 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -4013,6 +4013,8 @@ cxx_init_decl_processing (void)
     TYPE_SIZE_UNIT (nullptr_type_node) = size_int (GET_MODE_SIZE (ptr_mode));
     TYPE_UNSIGNED (nullptr_type_node) = 1;
     TYPE_PRECISION (nullptr_type_node) = GET_MODE_BITSIZE (ptr_mode);
+    if (abi_version_at_least (9))
+      TYPE_ALIGN (nullptr_type_node) = GET_MODE_ALIGNMENT (ptr_mode);
     SET_TYPE_MODE (nullptr_type_node, ptr_mode);
     record_builtin_type (RID_MAX, "decltype(nullptr)", nullptr_type_node);
     nullptr_node = build_int_cst (nullptr_type_node, 0);
diff --git a/gcc/testsuite/g++.dg/abi/macro0.C b/gcc/testsuite/g++.dg/abi/macro0.C
index fbcbb2c..35b8769 100644
--- a/gcc/testsuite/g++.dg/abi/macro0.C
+++ b/gcc/testsuite/g++.dg/abi/macro0.C
@@ -1,6 +1,6 @@
 // This testcase will need to be kept in sync with c_common_post_options.
 // { dg-options "-fabi-version=0" }
 
-#if __GXX_ABI_VERSION != 1008
+#if __GXX_ABI_VERSION != 1009
 #error "Incorrect value of __GXX_ABI_VERSION"
 #endif
diff --git a/gcc/testsuite/g++.dg/abi/nullptr-align.C b/gcc/testsuite/g++.dg/abi/nullptr-align.C
new file mode 100644
index 0000000..7de365a
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/nullptr-align.C
@@ -0,0 +1,5 @@
+// PR c++/65945
+// { dg-do compile { target c++11 } }
+// { dg-options "-fabi-version=9" }
+
+static_assert(alignof (decltype (nullptr)) == alignof (void *), "");
diff --git a/gcc/testsuite/g++.dg/abi/nullptr-align2.C b/gcc/testsuite/g++.dg/abi/nullptr-align2.C
new file mode 100644
index 0000000..66a9011
--- /dev/null
+++ b/gcc/testsuite/g++.dg/abi/nullptr-align2.C
@@ -0,0 +1,20 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "-fabi-version=0 -Wabi=8" }
+
+struct A
+{
+  decltype(nullptr) n;
+  decltype(nullptr) n2;
+};
+
+struct B
+{
+  void *p;
+  decltype(nullptr) n;
+};
+
+struct C
+{
+  char c;
+  decltype(nullptr) n;		// { dg-warning "alignment" }
+};

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]