Bug 87795 - Excessive alignment permitted for functions and labels
points out that the handler for attribute aligned makes it possible
for unsupported alignments to be accepted by the front end only to
be either rejected later on by some targets for variables, or to
cause an ICE for overaligned functions.

The reason for the problems is that the attribute handler considers
any power of two alignment valid whose log2  is less than
HOST_BITS_PER_INT - LOG2_BITS_PER_UNIT, but later parts of GCC
assume values of at most MAX_OFILE_ALIGNMENT / BITS_PER_UNIT.
The internals manual documents MAX_OFILE_ALIGNMENT as:

  Biggest alignment supported by the object file format of this
  machine. Use this macro to limit the alignment which can be
  specified using the __attribute__ ((aligned (n))) construct.

So it seems that the attribute handler should be using this macro
instead.  I also took the liberty to add more detail to the error
messages.  Attached is a patch that makes this change.  Tested on
x86_64-linux, plus using cross-compilers for arm, hppa64, pdp11,
and powerpc64.

Martin
PR c/87795 - Excessive alignment permitted for functions and labels

gcc/c-family/ChangeLog:

	PR c/87795
	* c-common.c (check_user_alignment): Use MAX_OFILE_ALIGNMENT.

gcc/testsuite/ChangeLog:

	PR c/87795
	* gcc.dg/attr-aligned.c: New test.

Index: gcc/c-family/c-common.c
===================================================================
--- gcc/c-family/c-common.c	(revision 265630)
+++ gcc/c-family/c-common.c	(working copy)
@@ -5123,17 +5123,20 @@ c_init_attributes (void)
 #undef DEF_ATTR_TREE_LIST
 }
 
-/* Check whether ALIGN is a valid user-specified alignment.  If so,
-   return its base-2 log; if not, output an error and return -1.  If
-   ALLOW_ZERO then 0 is valid and should result in a return of -1 with
-   no error.  */
+/* Check whether the byte alignment ALIGN is a valid user-specified
+   alignment less than MAX_OFILE_ALIGNMENT when converted to bits.
+   If so, return ALIGN's base-2 log; if not, output an error and
+   return -1.  If ALLOW_ZERO then 0 is valid and should result in
+   a return of -1 with no error.  */
+
 int
 check_user_alignment (const_tree align, bool allow_zero)
 {
-  int i;
+  int log2bitalign;
 
   if (error_operand_p (align))
     return -1;
+
   if (TREE_CODE (align) != INTEGER_CST
       || !INTEGRAL_TYPE_P (TREE_TYPE (align)))
     {
@@ -5140,20 +5143,35 @@ check_user_alignment (const_tree align, bool allow
       error ("requested alignment is not an integer constant");
       return -1;
     }
-  else if (allow_zero && integer_zerop (align))
+
+  if (allow_zero && integer_zerop (align))
     return -1;
-  else if (tree_int_cst_sgn (align) == -1
-           || (i = tree_log2 (align)) == -1)
+
+  if (tree_int_cst_sgn (align) == -1
+      || (log2bitalign = tree_log2 (align)) == -1)
     {
-      error ("requested alignment is not a positive power of 2");
+      error ("requested alignment %qE is not a positive power of 2",
+	     align);
       return -1;
     }
-  else if (i >= HOST_BITS_PER_INT - LOG2_BITS_PER_UNIT)
+
+  unsigned maxalign = MAX_OFILE_ALIGNMENT / BITS_PER_UNIT;
+  if (tree_to_shwi (align) > maxalign)
     {
-      error ("requested alignment is too large");
+      error ("requested alignment %qE exceeds object file maximum %u",
+	     align, maxalign);
       return -1;
     }
-  return i;
+
+  /* The following is probably redundant given the test above.  */
+  if (log2bitalign >= HOST_BITS_PER_INT - LOG2_BITS_PER_UNIT)
+    {
+      error ("requested alignment %qE exceeds maximum %u",
+	     align, 1U << (HOST_BITS_PER_INT - 1));
+      return -1;
+    }
+
+  return log2bitalign;
 }
 
 /* Determine the ELF symbol visibility for DECL, which is either a
Index: gcc/testsuite/gcc.dg/attr-aligned.c
===================================================================
--- gcc/testsuite/gcc.dg/attr-aligned.c	(nonexistent)
+++ gcc/testsuite/gcc.dg/attr-aligned.c	(working copy)
@@ -0,0 +1,35 @@
+/* PR c/87795 - Excessive alignment permitted for functions and labels
+   { dg-do compile } */
+
+/* Hardcode a few known values for testing the tight bounds.  */
+#if __hpux__ && __hppa__ && __LP64__
+#  define ALIGN_MAX       4096
+#  define ALIGN_TOO_BIG   (ALIGN_MAX << 1)
+#elif pdp11
+#  define ALIGN_MAX       2
+#  define ALIGN_TOO_BIG   4
+#elif __powerpc64__ || __x86_64__
+#  define ALIGN_MAX       0x10000000
+#else
+   /* Guaranteed to be accepted regardless of the target.  */
+#  define ALIGN_MAX  __BIGGEST_ALIGNMENT__
+#endif
+
+#ifndef ALIGN_TOO_BIG
+   /* Guaranteed to be rejected regardless of the target.  */
+#  define ALIGN_TOO_BIG   (0x10000000 << 1)
+#endif
+
+__attribute__ ((aligned (ALIGN_MAX))) const char c_max = 0;
+__attribute__ ((aligned (ALIGN_MAX))) char v_max;
+__attribute__ ((aligned (ALIGN_MAX))) void f_max (void);
+
+_Static_assert (_Alignof (c_max) == ALIGN_MAX);
+_Static_assert (_Alignof (v_max) == ALIGN_MAX);
+
+
+__attribute__ ((aligned (ALIGN_TOO_BIG))) char
+a_max_x_2;          /* { dg-error "requested alignment .\[0-9\]+. exceeds object file maximum \[0-9\]+" } */
+
+__attribute__ ((aligned (ALIGN_TOO_BIG))) void
+f_max_x_2 (void);   /* { dg-error "requested alignment .\[0-9\]+. exceeds object file maximum \[0-9\]+" } */

Reply via email to