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.

From-SVN: r265977
This commit is contained in:
Martin Sebor 2018-11-09 10:17:47 -07:00
parent 32999d87d6
commit 4c7bd36194
9 changed files with 211 additions and 22 deletions

View 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.

View 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))
{

View 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. */
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

View 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 (*)

View 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;

View 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

View 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

View 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.
@ -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.

View File

@ -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\]+" } */