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 + + PR c/87795 + * c-common.c (check_user_alignment): Use MAX_OFILE_ALIGNMENT. + 2018-11-08 Jakub Jelinek * 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. */ -int -check_user_alignment (const_tree align, bool allow_zero) -{ - int i; +/* 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 objfile, bool allow_zero) +{ 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 *); 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 + + PR c/87795 + * gcc.dg/attr-aligned.c: New test. + 2018-11-09 Martin Liska * 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 * 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\]+" } */