aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMartin Sebor <msebor@redhat.com>2018-11-09 17:17:47 +0000
committerMartin Sebor <msebor@redhat.com>2018-11-09 17:17:47 +0000
commit06a1e91ffd0b802c19b9051fa0ec577b18856373 (patch)
treec03d55a7a70661243c37eb7fddc8bd2d673e9754 /gcc
parent7a68f3d7cdb0006f5a75c96fc276f1e3b99e1705 (diff)
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. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@265977 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/c-family/ChangeLog5
-rw-r--r--gcc/c-family/c-attribs.c5
-rw-r--r--gcc/c-family/c-common.c50
-rw-r--r--gcc/c-family/c-common.h2
-rw-r--r--gcc/c/c-decl.c2
-rw-r--r--gcc/doc/tm.texi7
-rw-r--r--gcc/doc/tm.texi.in7
-rw-r--r--gcc/testsuite/ChangeLog6
-rw-r--r--gcc/testsuite/gcc.dg/attr-aligned.c147
9 files changed, 210 insertions, 21 deletions
diff --git a/gcc/c-family/ChangeLog b/gcc/c-family/ChangeLog
index f1b9b27f8c0..ab45ebe8937 100644
--- a/gcc/c-family/ChangeLog
+++ b/gcc/c-family/ChangeLog
@@ -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.
diff --git a/gcc/c-family/c-attribs.c b/gcc/c-family/c-attribs.c
index 4416b5042f7..336c63ec0dd 100644
--- a/gcc/c-family/c-attribs.c
+++ b/gcc/c-family/c-attribs.c
@@ -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))
{
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 534d928fd1b..0adee8bf98f 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -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
diff --git a/gcc/c-family/c-common.h b/gcc/c-family/c-common.h
index a2184325a10..31cc27325c2 100644
--- a/gcc/c-family/c-common.h
+++ b/gcc/c-family/c-common.h
@@ -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 (*)
diff --git a/gcc/c/c-decl.c b/gcc/c/c-decl.c
index cbbf7eba51f..8de5ffcc25e 100644
--- a/gcc/c/c-decl.c
+++ b/gcc/c/c-decl.c
@@ -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;
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index 54ca5183493..ce3e9ff2f8f 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -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
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index e8af1bfa2c1..f1ad80da467 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -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
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 0e257c3e6b0..a27efa66456 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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.
@@ -120,6 +125,7 @@
* 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
index 00000000000..ec545639f79
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/attr-aligned.c
@@ -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\]+" } */