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:
parent
32999d87d6
commit
4c7bd36194
9 changed files with 211 additions and 22 deletions
|
@ -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.
|
||||
|
|
|
@ -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))
|
||||
{
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 (*)
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.
|
||||
|
|
147
gcc/testsuite/gcc.dg/attr-aligned.c
Normal file
147
gcc/testsuite/gcc.dg/attr-aligned.c
Normal 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\]+" } */
|
Loading…
Add table
Reference in a new issue