]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
PR c/87795 - Excessive alignment permitted for functions and labels
authormsebor <msebor@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 9 Nov 2018 17:17:47 +0000 (17:17 +0000)
committermsebor <msebor@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 9 Nov 2018 17:17:47 +0000 (17:17 +0000)
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.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@265977 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/c-family/ChangeLog
gcc/c-family/c-attribs.c
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/c/c-decl.c
gcc/doc/tm.texi
gcc/doc/tm.texi.in
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/attr-aligned.c [new file with mode: 0644]

index f1b9b27f8c003e1a70255893d671b46c4c2a224a..ab45ebe89371d4724aefd21787e730e4863068f6 100644 (file)
@@ -1,3 +1,8 @@
+2018-11-09  Martin Sebor  <msebor@redhat.com>
+
+       PR c/87795
+       * c-common.c (check_user_alignment): Use MAX_OFILE_ALIGNMENT.
+
 2018-11-08  Jakub Jelinek  <jakub@redhat.com>
 
        * c-common.h (c_finish_omp_taskgroup): Add CLAUSES argument.
index 4416b5042f7592762b2850cfed33bbc6509626b9..336c63ec0dd2aeb46d80bc9e5a235cd1723edfc7 100644 (file)
@@ -1813,8 +1813,11 @@ common_handle_aligned_attribute (tree *node, tree name, tree args, int flags,
   else if (TYPE_P (*node))
     type = node, is_type = true;
 
+  /* True to consider invalid alignments greater than MAX_OFILE_ALIGNMENT.  */
+  bool objfile = (TREE_CODE (*node) == FUNCTION_DECL
+                 || (VAR_P (*node) && TREE_STATIC (*node)));
   /* Log2 of specified alignment.  */
-  int pow2align = check_user_alignment (align_expr, true);
+  int pow2align = check_user_alignment (align_expr, objfile, true);
   if (pow2align == -1
       || !check_cxx_fundamental_alignment_constraints (*node, pow2align, flags))
     {
index 534d928fd1bd82e4bc48c7889f3ee4b4b9eaf2f3..0adee8bf98f4e093328d2b3d1a52faebaeccc5fd 100644 (file)
@@ -5123,37 +5123,59 @@ 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 the supported maximum.  If so, return ALIGN's
+   base-2 log; if not, output an error and return -1.  If OBJFILE
+   then reject alignments greater than MAX_OFILE_ALIGNMENT when
+   converted to bits.  Otherwise, consider valid only alignments
+   that are less than HOST_BITS_PER_INT - LOG2_BITS_PER_UNIT.
+   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)
+check_user_alignment (const_tree align, bool objfile, bool allow_zero)
 {
-  int i;
-
   if (error_operand_p (align))
     return -1;
+
   if (TREE_CODE (align) != INTEGER_CST
       || !INTEGRAL_TYPE_P (TREE_TYPE (align)))
     {
       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)
+
+  int log2bitalign;
+  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)
+
+  if (objfile)
     {
-      error ("requested alignment is too large");
+      unsigned maxalign = MAX_OFILE_ALIGNMENT / BITS_PER_UNIT;
+      if (tree_to_shwi (align) > maxalign)
+       {
+         error ("requested alignment %qE exceeds object file maximum %u",
+                align, maxalign);
+         return -1;
+       }
+    }
+
+  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 i;
+
+  return log2bitalign;
 }
 
 /* Determine the ELF symbol visibility for DECL, which is either a
index a2184325a10f652896dad58ddff13cbb994aa665..31cc27325c21a1e99166d9b88ce8f8f4b991b502 100644 (file)
@@ -798,7 +798,7 @@ extern void finish_fname_decls (void);
 extern const char *fname_as_string (int);
 extern tree fname_decl (location_t, unsigned, tree);
 
-extern int check_user_alignment (const_tree, bool);
+extern int check_user_alignment (const_tree, bool, bool);
 extern bool check_function_arguments (location_t loc, const_tree, const_tree,
                                      int, tree *, vec<location_t> *);
 extern void check_function_arguments_recurse (void (*)
index cbbf7eba51fd8c5c547a0fe9e91c53a00103b6ee..8de5ffcc25e14a82290be82e8821e9d35de9ae5c 100644 (file)
@@ -11034,7 +11034,7 @@ declspecs_add_alignas (source_location loc,
   specs->locations[cdw_alignas] = loc;
   if (align == error_mark_node)
     return specs;
-  align_log = check_user_alignment (align, true);
+  align_log = check_user_alignment (align, false, true);
   if (align_log > specs->align_log)
     specs->align_log = align_log;
   return specs;
index 54ca518349367df709e0eca8da75730b05294fdc..ce3e9ff2f8f662164fa2de60f283e98a662dfc81 100644 (file)
@@ -1081,8 +1081,11 @@ If not defined, the default value is @code{STACK_BOUNDARY}.
 @defmac MAX_OFILE_ALIGNMENT
 Biggest alignment supported by the object file format of this machine.
 Use this macro to limit the alignment which can be specified using the
-@code{__attribute__ ((aligned (@var{n})))} construct.  If not defined,
-the default value is @code{BIGGEST_ALIGNMENT}.
+@code{__attribute__ ((aligned (@var{n})))} construct for functions and
+objects with static storage duration.  The alignment of automatic
+objects may exceed the object file format maximum up to the maximum
+supported by GCC.  If not defined, the default value is
+@code{BIGGEST_ALIGNMENT}.
 
 On systems that use ELF, the default (in @file{config/elfos.h}) is
 the largest supported 32-bit ELF section alignment representable on
index e8af1bfa2c100f977da2ecd938304e42477d3ae3..f1ad80da467c095b9372d05eaf1bf83c5a4aeaa6 100644 (file)
@@ -1027,8 +1027,11 @@ If not defined, the default value is @code{STACK_BOUNDARY}.
 @defmac MAX_OFILE_ALIGNMENT
 Biggest alignment supported by the object file format of this machine.
 Use this macro to limit the alignment which can be specified using the
-@code{__attribute__ ((aligned (@var{n})))} construct.  If not defined,
-the default value is @code{BIGGEST_ALIGNMENT}.
+@code{__attribute__ ((aligned (@var{n})))} construct for functions and
+objects with static storage duration.  The alignment of automatic
+objects may exceed the object file format maximum up to the maximum
+supported by GCC.  If not defined, the default value is
+@code{BIGGEST_ALIGNMENT}.
 
 On systems that use ELF, the default (in @file{config/elfos.h}) is
 the largest supported 32-bit ELF section alignment representable on
index 0e257c3e6b0ff9dd691d28dedabf78f95b3d1f1d..a27efa66456c4eaf83856b0a6d33031fa0bcbbe4 100644 (file)
@@ -1,3 +1,8 @@
+2018-11-09  Martin Sebor  <msebor@redhat.com>
+
+       PR c/87795
+       * gcc.dg/attr-aligned.c: New test.
+
 2018-11-09  Martin Liska  <mliska@suse.cz>
 
        * gcc.target/i386/ipa-stack-alignment.c: New test.
        * gcc.dg/pr87600-1.c: New test.
        * gcc.dg/pr87600-2.c: Likewise.
 
+>>>>>>> .r265976
 2018-11-08  Jakub Jelinek  <jakub@redhat.com>
 
        * c-c++-common/gomp/atomic-17.c: New test.
diff --git a/gcc/testsuite/gcc.dg/attr-aligned.c b/gcc/testsuite/gcc.dg/attr-aligned.c
new file mode 100644 (file)
index 0000000..ec54563
--- /dev/null
@@ -0,0 +1,147 @@
+/* PR c/87795 - Excessive alignment permitted for functions and labels
+   { dg-do compile }
+   { dg-options "-Wno-pedantic" } */
+
+/* The maximum alignment GCC can handle.  */
+#define ALIGN_MAX_HARD 0x10000000
+
+/* Hardcode a few known values for testing the tight bounds.  */
+#if __hpux__ && __hppa__ && __LP64__
+   /* Maximum alignment for functions and objects with static storage
+      duration that's expected to be accepted.  */
+#  define ALIGN_MAX_STATIC      0x1000
+   /* Excessive alignment for functions and objects with static storage
+      duration that's expected to trigger an error.  */
+#elif __MACH__
+#  define ALIGN_MAX_STATIC      0x8000
+#elif pdp11
+#  define ALIGN_MAX_STATIC      2
+/* Work around a pdp11 ICE (see PR target/87821).  */
+#  define ALIGN_MAX_AUTO        (ALIGN_MAX_HARD >> 14)
+#elif __powerpc64__ || __x86_64__
+/* Is this processor- or operating-system specific?  */
+#  define ALIGN_MAX_STATIC      ALIGN_MAX_HARD
+#else
+   /* Guaranteed to be accepted regardless of the target.  */
+#  define ALIGN_MAX_STATIC      __BIGGEST_ALIGNMENT__
+   /* Guaranteed to be rejected regardless of the target.  */
+#  define ALIGN_TOO_BIG_OFILE   (ALIGN_MAX_HARD << 1)
+#endif
+
+/* Maximum alignment for auto objects that's expected to be accepted.  */
+#ifndef ALIGN_MAX_AUTO
+#  define ALIGN_MAX_AUTO        ALIGN_MAX_HARD
+#endif
+
+#ifndef ALIGN_TOO_BIG_OFILE
+#  define ALIGN_TOO_BIG_OFILE   (ALIGN_MAX_STATIC << 1)
+#endif
+
+
+#define ALIGN(N) __attribute__ ((aligned (N)))
+
+
+/* Verify that types can be defined maximally overaligned using
+   attribute aligned.  */
+typedef ALIGN (ALIGN_MAX_HARD) char CharAlignedMaxHard;
+typedef ALIGN (ALIGN_MAX_AUTO) char CharAlignedMaxAuto;
+typedef ALIGN (ALIGN_MAX_STATIC) char CharAlignedMaxStatic;
+
+#if ALIGN_TOO_BIG_OFILE < ALIGN_MAX_HARD
+/* Also verify that an alignment greater than MAX_OFILE_ALIGNMENT
+   is accepted unless the constant is as large as GCC's maximum
+   supported alignment in any context.  */
+typedef ALIGN (ALIGN_TOO_BIG_OFILE) char CharAlignedTooBig;
+#endif
+
+CharAlignedMaxStatic t_max;
+
+/* Verify that globals can be defined maximally overaligned using
+   attribute aligned.  */
+ALIGN (ALIGN_MAX_STATIC) static const char aligned_sc_max = 0;
+ALIGN (ALIGN_MAX_STATIC) const char aligned_c_max = aligned_sc_max;
+ALIGN (ALIGN_MAX_STATIC) char aligned_v_max;
+ALIGN (ALIGN_MAX_STATIC) void aligned_f_max (void);
+
+_Static_assert (__alignof__ (aligned_sc_max) == ALIGN_MAX_STATIC);
+_Static_assert (__alignof__ (aligned_c_max) == ALIGN_MAX_STATIC);
+_Static_assert (__alignof__ (aligned_v_max) == ALIGN_MAX_STATIC);
+_Static_assert (__alignof__ (aligned_f_max) == ALIGN_MAX_STATIC);
+
+
+/* Verify that globals can be defined maximally overaligned using
+   _Alignas.  */
+_Alignas (ALIGN_MAX_STATIC) static const char alignas_sc_max = 0;
+_Alignas (ALIGN_MAX_STATIC) const char alignas_c_max = alignas_sc_max;
+_Alignas (ALIGN_MAX_STATIC) char alignas_v_max;
+
+_Static_assert (__alignof__ (alignas_sc_max) == ALIGN_MAX_STATIC);
+_Static_assert (__alignof__ (alignas_c_max) == ALIGN_MAX_STATIC);
+_Static_assert (__alignof__ (alignas_v_max) == ALIGN_MAX_STATIC);
+
+
+/* Verify that auto and static local variables can be defined maximally
+   overaligned.  */
+
+int accept_local_attribute_aligned (void)
+{
+#if ALIGN_TOO_BIG_OFILE < ALIGN_MAX_HARD
+  /* Same as above.  */
+  typedef ALIGN (ALIGN_TOO_BIG_OFILE) char LocalCharAlignedTooBig;
+  LocalCharAlignedTooBig aligned_lt_too_big = 0;
+  (void)&aligned_lt_too_big;
+#endif
+
+  static CharAlignedMaxStatic aligned_st_max;
+  _Static_assert (_Alignof (aligned_st_max) == ALIGN_MAX_STATIC);
+
+  CharAlignedMaxAuto aligned_t_max;
+  _Static_assert (_Alignof (aligned_t_max) == ALIGN_MAX_AUTO);
+
+  ALIGN (ALIGN_MAX_STATIC) char aligned_s_max;
+  _Static_assert (_Alignof (aligned_s_max) == ALIGN_MAX_STATIC);
+
+  ALIGN (ALIGN_MAX_AUTO) char aligned_l_max;
+  _Static_assert (_Alignof (aligned_l_max) == ALIGN_MAX_AUTO);
+
+  return aligned_st_max++ + aligned_t_max++ + aligned_s_max++ + aligned_l_max++;
+}
+
+
+int accept_local_alignas (void)
+{
+  _Alignas (ALIGN_MAX_STATIC) char alignas_s_max;
+  _Static_assert (_Alignof (alignas_s_max) == ALIGN_MAX_STATIC);
+
+  _Alignas (ALIGN_MAX_AUTO) char alignas_l_max;
+  _Static_assert (_Alignof (alignas_l_max) == ALIGN_MAX_AUTO);
+
+  return alignas_s_max++ + alignas_l_max++;
+}
+
+
+/* Verify that auto and static local variables are subject to the object
+   file alignment limit.  The "object file" part may not be mentioned if
+   the object file maximum is the same as GCC's internal maximum.  */
+
+int reject_local_align (void)
+{
+  /* Ironically, the errors below are on different lines for each
+     of the two declarations if the aligned attribute is on a line
+     of its own.  */
+  ALIGN (ALIGN_TOO_BIG_OFILE) static char aligned_sl_max;       /* { dg-error "requested alignment .\[0-9\]+. exceeds\( object file\)* maximum \[0-9\]+" } */
+
+  _Alignas (ALIGN_TOO_BIG_OFILE) static char alignas_sl_max;    /* { dg-error "alignment" } */
+
+  return aligned_sl_max++ + alignas_sl_max++;
+}
+
+
+/* Verify that global variables are subject to the object file
+   alignment limit.  */
+
+ALIGN (ALIGN_TOO_BIG_OFILE) char a_max_x_2;                    /* { dg-error "requested alignment .\[0-9\]+. exceeds\( object file\)* maximum \[0-9\]+" } */
+
+_Alignas (ALIGN_TOO_BIG_OFILE) char a_max_x_2;                    /* { dg-error "alignment" } */
+
+ALIGN (ALIGN_TOO_BIG_OFILE) void f_max_x_2 (void);             /* { dg-error "requested alignment .\[0-9\]+. exceeds\( object file\)* maximum \[0-9\]+" } */