+2018-11-29 Martin Sebor <msebor@redhat.com>
+
+ PR c/88172
+ PR testsuite/88208
+ * doc/extend.texi (attribute constructor): Clarify.
+
2018-11-29 Martin Liska <mliska@suse.cz>
PR middle-end/88246
+2018-11-29 Martin Sebor <msebor@redhat.com>
+
+ PR c/88172
+ PR testsuite/88208
+ * c-attribs.c (common_handle_aligned_attribute): Silently avoid setting
+ alignments to values less than the target requires.
+ (has_attribute): For attribute aligned consider both the attribute
+ and the alignment bits.
+ * c-common.c (c_init_attributes): Optionally issue a warning for
+ zero alignment.
+
2018-11-28 Martin Sebor <msebor@redhat.com>
PR c/88065
bool objfile = (TREE_CODE (*node) == FUNCTION_DECL
|| (VAR_P (*node) && TREE_STATIC (*node)));
/* Log2 of specified alignment. */
- int pow2align = check_user_alignment (align_expr, objfile, true);
+ int pow2align = check_user_alignment (align_expr, objfile,
+ /* warn_zero = */ true);
if (pow2align == -1
|| !check_cxx_fundamental_alignment_constraints (*node, pow2align, flags))
{
unsigned curalign = 0;
unsigned lastalign = 0;
+ /* True when SET_DECL_ALIGN() should be called for the decl when
+ *NO_ADD_ATTRS is false. */
+ bool set_align = true;
if (is_type)
{
if ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
curalign = lastalign;
curalign /= BITS_PER_UNIT;
- bitalign /= BITS_PER_UNIT;
+ unsigned newalign = bitalign / BITS_PER_UNIT;
- bool diagd = true;
auto_diagnostic_group d;
- if (DECL_USER_ALIGN (decl) || DECL_USER_ALIGN (last_decl))
- diagd = warning (OPT_Wattributes,
- "ignoring attribute %<%E (%u)%> because it conflicts "
- "with attribute %<%E (%u)%>",
- name, bitalign, name, curalign);
+ if ((DECL_USER_ALIGN (decl)
+ || DECL_USER_ALIGN (last_decl)))
+ {
+ if (warning (OPT_Wattributes,
+ "ignoring attribute %<%E (%u)%> because it conflicts "
+ "with attribute %<%E (%u)%>",
+ name, newalign, name, curalign)
+ && note)
+ inform (DECL_SOURCE_LOCATION (last_decl),
+ "previous declaration here");
+ /* Only reject attempts to relax/override an alignment
+ explicitly specified previously and accept declarations
+ that appear to relax the implicit function alignment for
+ the target. Both increasing and increasing the alignment
+ set by -falign-functions setting is permitted. */
+ *no_add_attrs = true;
+ }
else if (!warn_if_not_aligned_p)
- /* Do not error out for attribute warn_if_not_aligned. */
- error ("alignment for %q+D must be at least %d", decl, curalign);
-
- if (diagd && note)
- inform (DECL_SOURCE_LOCATION (last_decl), "previous declaration here");
-
- *no_add_attrs = true;
+ {
+ /* Do not fail for attribute warn_if_not_aligned. Otherwise,
+ silently avoid applying the alignment to the declaration
+ because it's implicitly satisfied by the target. Apply
+ the attribute nevertheless so it can be retrieved by
+ __builtin_has_attribute. */
+ set_align = false;
+ }
}
else if (DECL_USER_ALIGN (decl)
&& DECL_ALIGN (decl) > bitalign)
&& TREE_CODE (decl) == FUNCTION_DECL
&& DECL_ALIGN (decl) > bitalign)
{
- /* Don't warn function alignment here if warn_if_not_aligned_p is
- true. It will be warned later. */
+ /* Don't warn for function alignment here if warn_if_not_aligned_p
+ is true. It will be warned about later. */
if (DECL_USER_ALIGN (decl))
- error ("alignment for %q+D was previously specified as %d "
- "and may not be decreased", decl,
- DECL_ALIGN (decl) / BITS_PER_UNIT);
- else
- error ("alignment for %q+D must be at least %d", decl,
- DECL_ALIGN (decl) / BITS_PER_UNIT);
- *no_add_attrs = true;
- }
- else
- {
- if (warn_if_not_aligned_p)
- {
- if (TREE_CODE (decl) == FIELD_DECL && !DECL_C_BIT_FIELD (decl))
- {
- SET_DECL_WARN_IF_NOT_ALIGN (decl, bitalign);
- warn_if_not_aligned_p = false;
- }
- }
- else
{
- SET_DECL_ALIGN (decl, bitalign);
- DECL_USER_ALIGN (decl) = 1;
+ /* Only reject attempts to relax/override an alignment
+ explicitly specified previously and accept declarations
+ that appear to relax the implicit function alignment for
+ the target. Both increasing and increasing the alignment
+ set by -falign-functions setting is permitted. */
+ error ("alignment for %q+D was previously specified as %d "
+ "and may not be decreased", decl,
+ DECL_ALIGN (decl) / BITS_PER_UNIT);
+ *no_add_attrs = true;
}
}
+ else if (warn_if_not_aligned_p
+ && TREE_CODE (decl) == FIELD_DECL
+ && !DECL_C_BIT_FIELD (decl))
+ {
+ SET_DECL_WARN_IF_NOT_ALIGN (decl, bitalign);
+ warn_if_not_aligned_p = false;
+ set_align = false;
+ }
if (warn_if_not_aligned_p)
{
decl);
*no_add_attrs = true;
}
+ else if (!is_type && !*no_add_attrs && set_align)
+ {
+ SET_DECL_ALIGN (decl, bitalign);
+ DECL_USER_ALIGN (decl) = 1;
+ }
return NULL_TREE;
}
with the sought attributes) has been found on the attribute chain. */
bool found_attr = false;
- /* For attribute aligned ignore the attribute list and consider
- the tree node itself instead. */
- if (type && !strcmp ("aligned", namestr))
- atlist = NULL_TREE;
-
/* When clear, the first mismatched attribute argument results
in failure. Otherwise, the first matched attribute argument
results in success. */
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. */
+ Zero is not considered a valid argument (and results in -1 on
+ return) but it only triggers a warning when WARN_ZERO is set. */
int
-check_user_alignment (const_tree align, bool objfile, bool allow_zero)
+check_user_alignment (const_tree align, bool objfile, bool warn_zero)
{
if (error_operand_p (align))
return -1;
return -1;
}
- if (allow_zero && integer_zerop (align))
- return -1;
+ if (integer_zerop (align))
+ {
+ if (warn_zero)
+ warning (OPT_Wattributes,
+ "requested alignment %qE is not a positive power of 2",
+ align);
+ return -1;
+ }
int log2bitalign;
if (tree_int_cst_sgn (align) == -1
+2018-11-29 Martin Sebor <msebor@redhat.com>
+
+ PR c/88172
+ PR testsuite/88208
+ * c-decl.c (declspec_add_alignas): Adjust call to check_user_alignment.
+
2018-11-23 Martin Sebor <msebor@redhat.com>
PR testsuite/88098
declspecs_add_alignas (location_t loc,
struct c_declspecs *specs, tree align)
{
- int align_log;
specs->alignas_p = true;
specs->locations[cdw_alignas] = loc;
if (align == error_mark_node)
return specs;
- align_log = check_user_alignment (align, false, true);
+
+ /* Only accept the alignment if it's valid and greater than
+ the current one. Zero is invalid but by C11 required to
+ be silently ignored. */
+ int align_log = check_user_alignment (align, false, /* warn_zero = */false);
if (align_log > specs->align_log)
specs->align_log = align_log;
return specs;
initializing data that is used implicitly during the execution of
the program.
-You may provide an optional integer priority to control the order in
-which constructor and destructor functions are run. A constructor
+On some targets the attributes also accept an integer argument to
+specify a priority to control the order in which constructor and
+destructor functions are run. A constructor
with a smaller priority number runs before a constructor with a larger
priority number; the opposite relationship holds for destructors. So,
if you have a constructor that allocates a resource and a destructor
In mixed declarations, attribute @code{init_priority} can be used to
impose a specific ordering.
+Using the argument forms of the @code{constructor} and @code{destructor}
+attributes on targets where the feature is not supported is rejected with
+an error.
+
@item copy
@itemx copy (@var{function})
@cindex @code{copy} function attribute
+2018-11-29 Martin Sebor <msebor@redhat.com>
+
+ PR c/88172
+ PR testsuite/88208
+ * gcc.dg/attr-aligned-2.c: New test.
+ * gcc.dg/builtin-has-attribute.c: Adjust.
+ * c-c++-common/builtin-has-attribute-2.c: Same.
+ * c-c++-common/builtin-has-attribute-3.c: Same.
+ * c-c++-common/builtin-has-attribute-4.c: Same.
+ * c-c++-common/builtin-has-attribute-5.c: New test.
+ * gcc.target/aarch64/attr-aligned.c: Same.
+ * gcc.target/i386/attr-aligned.c: Same.
+ * gcc.target/powerpc/attr-aligned.c: Same.
+ * gcc.target/sparc/attr-aligned.c: Same.
+
2018-11-29 qing zhao <qing.zhao@oracle.com>
* gcc.dg/live-patching-1.c: New test.
A (0, int ATTR (aligned (4)), aligned (2));
A (0, int ATTR (aligned (2)), aligned (4));
- /* GCC retains both attributes in the */
- A (0, int ATTR (aligned (2), aligned (4)), aligned (2));
+ /* GCC retains both attributes when the type is defined in the builtin. */
+ A (1, int ATTR (aligned (2), aligned (4)), aligned (2));
A (1, int ATTR (aligned (2), aligned (4)), aligned (4));
/* The following fails due to bug 87524.
A (1, int ATTR (aligned (4), aligned (2))), aligned (4)); */
A (1, MAI, may_alias);
typedef ATTR (aligned (4), may_alias) char A4MAC;
- A (0, A4MAC, aligned (0));
+ A (0, A4MAC, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */
A (0, A4MAC, aligned (1));
A (0, A4MAC, aligned (2));
A (1, A4MAC, aligned (4));
typedef ATTR (may_alias, aligned (8)) char A8MAC;
A (1, A8MAC, aligned);
- A (0, A8MAC, aligned (0));
+ A (0, A8MAC, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */
A (0, A8MAC, aligned (1));
A (0, A8MAC, aligned (2));
A (0, A8MAC, aligned (4));
void test_aligned (void)
{
A (0, fnone, aligned);
- A (0, fnone, aligned (0));
+ A (0, fnone, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */
A (0, fnone, aligned (1));
A (0, fnone, aligned (2));
A (0, fnone, aligned (4));
A (0, fnone, aligned (16));
A (1, faligned, aligned);
- A (0, faligned, aligned (0));
+ A (0, faligned, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */
A (0, faligned, aligned (1));
A (0, faligned, aligned (2));
A (1, faligned_1, aligned);
- A (0, faligned_1, aligned (0));
+ A (0, faligned_1, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */
A (1, faligned_1, aligned (1));
A (0, faligned_1, aligned (2));
A (0, faligned_1, aligned (4));
A (1, faligned_2, aligned);
- A (0, faligned_2, aligned (0));
+ A (0, faligned_2, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */
A (0, faligned_2, aligned (1));
A (1, faligned_2, aligned (2));
A (0, faligned_2, aligned (4));
A (1, fctor_dtor, constructor);
A (1, fctor_dtor, destructor);
-
- extern ATTR (constructor (123)) void fctor_123 (void);
- A (1, fctor_123, constructor);
- A (0, fctor_123, destructor);
- A (1, fctor_123, constructor (123));
- A (0, fctor_123, constructor (124));
-
- extern ATTR (destructor (234)) void fctor_123 (void);
- A (1, fctor_123, constructor (123));
- A (1, fctor_123, destructor);
- A (1, fctor_123, destructor (234));
- A (0, fctor_123, destructor (235));
}
void test_aligned (void)
{
A (0, vnone, aligned);
- A (0, vnone, aligned (0));
+ A (0, vnone, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */
A (0, vnone, aligned (1));
A (0, vnone, aligned (2));
A (0, vnone, aligned (4));
A (0, vnone, aligned (16));
A (1, valigned, aligned);
- A (0, valigned, aligned (0));
+ A (0, valigned, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */
A (0, valigned, aligned (1));
A (0, valigned, aligned (2));
A (1, valigned_1, aligned);
- A (0, valigned_1, aligned (0));
+ A (0, valigned_1, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */
A (1, valigned_1, aligned (1));
A (0, valigned_1, aligned (2));
A (0, valigned_1, aligned (4));
A (1, valigned_2, aligned);
- A (0, valigned_2, aligned (0));
+ A (0, valigned_2, aligned (0)); /* { dg-warning "requested alignment .0. is not a positive power of 2" } */
A (0, valigned_2, aligned (1));
A (1, valigned_2, aligned (2));
A (0, valigned_2, aligned (4));
--- /dev/null
+/* Verify __builtin_has_attribute return value for attributes constructor
+ and destructor with explicit priorities.
+ { dg-do compile { target init_priority } }
+ { dg-options "-Wall -ftrack-macro-expansion=0" }
+ { dg-options "-Wall -Wno-narrowing -Wno-unused -ftrack-macro-expansion=0" { target c++ } } */
+
+#define ATTR(...) __attribute__ ((__VA_ARGS__))
+
+#define A(expect, sym, attr) \
+ typedef int Assert [1 - 2 * !(__builtin_has_attribute (sym, attr) == expect)]
+
+void fnone (void);
+
+void test_ctor_dtor_prio (void)
+{
+ extern ATTR (constructor) void fctor (void);
+ extern ATTR (destructor) void fdtor (void);
+ extern ATTR (constructor, destructor) void fctor_dtor (void);
+
+ A (0, fnone, constructor);
+ A (0, fnone, constructor (123));
+ A (0, fnone, destructor);
+ A (0, fnone, constructor (234));
+
+ A (1, fctor, constructor);
+ A (0, fctor, constructor (123));
+ A (1, fdtor, destructor);
+ A (0, fdtor, destructor (234));
+
+ extern ATTR (constructor) void fctor_dtor (void);
+ extern ATTR (destructor) void fctor_dtor (void);
+ extern ATTR (constructor, destructor) void fctor_dtor (void);
+
+ A (1, fctor_dtor, constructor);
+ A (1, fctor_dtor, destructor);
+
+ extern ATTR (constructor (123)) void fctor_123 (void);
+ A (1, fctor_123, constructor);
+ A (0, fctor_123, destructor);
+ A (1, fctor_123, constructor (123));
+ A (0, fctor_123, constructor (124));
+
+ extern ATTR (destructor (234)) void fctor_123 (void);
+ A (1, fctor_123, constructor (123));
+ A (1, fctor_123, destructor);
+ A (1, fctor_123, destructor (234));
+ A (0, fctor_123, destructor (235));
+}
--- /dev/null
+/* PR c/88172 - attribute aligned of zero silently accepted but ignored
+ Verify that valid alignment on functions is accepted for all targets
+ and that alignment of zero is ignored with a warning.
+ { dg-do compile }
+ { dg-options "-Wno-pedantic" } */
+
+#define ASSERT(expr) _Static_assert (expr, #expr)
+#define ALIGN(n) __attribute__ ((aligned (n)))
+#define alignof(expr) __alignof__ (expr)
+
+ALIGN (0) void f0 (void) { } /* { dg-warning "requested alignment .0. is not a positive power of 2" } */
+ALIGN (1) void f1 (void) { }
+ALIGN (2) void f2 (void) { }
+ALIGN (3) void f3 (void) { } /* { dg-error "requested alignment '3' is not a positive power of 2" } */
+ALIGN (4) void f4 (void) { }
+
+ASSERT (alignof (f0) > 0);
+ASSERT (alignof (f1) >= 1);
+ASSERT (alignof (f2) >= 2);
+ASSERT (alignof (f3) >= 1);
+ASSERT (alignof (f4) >= 4);
Also verify that the expression in __builtin_has_attribute is
not evaluated.
- { dg-do run }
- { dg-options "-O2 -Wall -Wc++-compat" } */
+ { dg-do compile }
+ { dg-options "-O2 -Wall -Wc++-compat -fdump-tree-optimized -ftrack-macro-expansion=0" } */
#define ATTR(list) __attribute__ (list)
#define A(expect, sym, attr) \
typedef int Assert [1 - 2 * !(__builtin_has_attribute (sym, attr) == expect)]
-int nfails;
-
#define assert(expr) \
((expr) \
? (void)0 \
A (1, struct ATTR ((aligned)) B { int i; }, aligned); /* { dg-warning "expression is invalid in C\\\+\\\+" } */
-int f (void)
+static int f (void)
{
__builtin_abort ();
}
-int n = 1;
-
int main (void)
{
+ int n = 0, nfails = 0;
+
assert (0 == __builtin_has_attribute (int[n++], aligned));
assert (1 == __builtin_has_attribute (ATTR ((aligned)) int[n++], aligned));
assert (1 == __builtin_has_attribute (ATTR ((aligned)) int[f ()], aligned));
assert (1 == 1);
+ if (n)
+ __builtin_abort ();
+
if (nfails)
__builtin_abort ();
return 0;
}
+
+/* { dg-final { scan-tree-dump-times "abort" 0 "optimized" } } */
--- /dev/null
+/* Verify that valid alignment on functions is accepted and results
+ in the alignment expected for the target and that alignment of
+ zero is ignored with a warning.
+ { dg-do compile }
+ { dg-options "-Wno-pedantic -ftrack-macro-expansion=0" } */
+
+#define ASSERT(expr) _Static_assert (expr, #expr)
+#define ALIGN(n) __attribute__ ((aligned (n)))
+#define alignof(expr) __alignof__ (expr)
+#define HAS_ALIGN(f, n) __builtin_has_attribute (f, __aligned__ (n))
+
+#define MINALIGN(N) ((N) < 4 ? 4 : (N))
+#define MAXALIGN 16
+
+/* No alignment specified. */
+void f (void) { }
+
+/* Empty alignment means maximum. */
+ALIGN () void f_ (void) { }
+
+ALIGN (0) void f0 (void) { } /* { dg-warning "requested alignment .0. is not a positive power of 2" } */
+ALIGN (1) void f1 (void) { }
+ALIGN (2) void f2 (void) { }
+ALIGN (4) void f4 (void) { }
+ALIGN (8) void f8 (void) { }
+ALIGN (16) void f16 (void) { }
+ALIGN (32) void f32 (void) { }
+
+ASSERT (alignof (f_) == MAXALIGN);
+ASSERT (alignof (f0) == alignof (f));
+ASSERT (alignof (f1) == MINALIGN (1));
+ASSERT (alignof (f2) == MINALIGN (2));
+ASSERT (alignof (f4) == MINALIGN (4));
+ASSERT (alignof (f8) == MINALIGN (8));
+ASSERT (alignof (f16) == MINALIGN (16));
+ASSERT (alignof (f32) == MINALIGN (32));
+
+ASSERT (!__builtin_has_attribute (f, aligned));
+ASSERT (__builtin_has_attribute (f_, aligned));
+ASSERT (!__builtin_has_attribute (f0, aligned));
+
+ASSERT (!HAS_ALIGN (f_, MAXALIGN));
+
+ASSERT (HAS_ALIGN (f1, 1));
+ASSERT (!HAS_ALIGN (f1, 2));
+
+ASSERT (!HAS_ALIGN (f2, 1));
+ASSERT (HAS_ALIGN (f2, 2));
+ASSERT (!HAS_ALIGN (f2, 4));
+
+ASSERT (!HAS_ALIGN (f4, 2));
+ASSERT (HAS_ALIGN (f4, 4));
+ASSERT (!HAS_ALIGN (f4, 8));
+
+ASSERT (!HAS_ALIGN (f8, 4));
+ASSERT (HAS_ALIGN (f8, 8));
+ASSERT (!HAS_ALIGN (f8, 16));
+
+ASSERT (!HAS_ALIGN (f16, 8));
+ASSERT (HAS_ALIGN (f16, 16));
+ASSERT (!HAS_ALIGN (f16, 32));
+
+ASSERT (!HAS_ALIGN (f32, 16));
+ASSERT (HAS_ALIGN (f32, 32));
+ASSERT (!HAS_ALIGN (f32, 64));
--- /dev/null
+/* Verify that valid alignment on functions is accepted and results
+ in the alignment expected for the target and that alignment of
+ zero is ignored with a warning.
+ { dg-do compile }
+ { dg-options "-Wno-pedantic -ftrack-macro-expansion=0" } */
+
+#define ASSERT(expr) _Static_assert (expr, #expr)
+#define ALIGN(n) __attribute__ ((aligned (n)))
+#define alignof(expr) __alignof__ (expr)
+#define HAS_ALIGN(f, n) __builtin_has_attribute (f, __aligned__ (n))
+
+#define MINALIGN(N) N
+#define MAXALIGN 16
+
+/* No alignment specified. */
+void f (void) { }
+
+/* Empty alignment means maximum. */
+ALIGN () void f_ (void) { }
+
+ALIGN (0) void f0 (void) { } /* { dg-warning "requested alignment .0. is not a positive power of 2" } */
+ALIGN (1) void f1 (void) { }
+ALIGN (2) void f2 (void) { }
+ALIGN (4) void f4 (void) { }
+ALIGN (8) void f8 (void) { }
+ALIGN (16) void f16 (void) { }
+ALIGN (32) void f32 (void) { }
+
+ASSERT (alignof (f_) == MAXALIGN);
+ASSERT (alignof (f0) == alignof (f));
+ASSERT (alignof (f1) == MINALIGN (1));
+ASSERT (alignof (f2) == MINALIGN (2));
+ASSERT (alignof (f4) == MINALIGN (4));
+ASSERT (alignof (f8) == MINALIGN (8));
+ASSERT (alignof (f16) == MINALIGN (16));
+ASSERT (alignof (f32) == MINALIGN (32));
+
+ASSERT (!__builtin_has_attribute (f, aligned));
+ASSERT (__builtin_has_attribute (f_, aligned));
+ASSERT (!__builtin_has_attribute (f0, aligned));
+
+ASSERT (!HAS_ALIGN (f_, MAXALIGN));
+
+ASSERT (HAS_ALIGN (f1, 1));
+ASSERT (!HAS_ALIGN (f1, 2));
+
+ASSERT (!HAS_ALIGN (f2, 1));
+ASSERT (HAS_ALIGN (f2, 2));
+ASSERT (!HAS_ALIGN (f2, 4));
+
+ASSERT (!HAS_ALIGN (f4, 2));
+ASSERT (HAS_ALIGN (f4, 4));
+ASSERT (!HAS_ALIGN (f4, 8));
+
+ASSERT (!HAS_ALIGN (f8, 4));
+ASSERT (HAS_ALIGN (f8, 8));
+ASSERT (!HAS_ALIGN (f8, 16));
+
+ASSERT (!HAS_ALIGN (f16, 8));
+ASSERT (HAS_ALIGN (f16, 16));
+ASSERT (!HAS_ALIGN (f16, 32));
+
+ASSERT (!HAS_ALIGN (f32, 16));
+ASSERT (HAS_ALIGN (f32, 32));
+ASSERT (!HAS_ALIGN (f32, 64));
--- /dev/null
+/* Verify that valid alignment on functions is accepted and results
+ in the alignment expected for the target and that alignment of
+ zero is ignored with a warning.
+ { dg-do compile }
+ { dg-options "-Wno-pedantic -ftrack-macro-expansion=0" } */
+
+#define ASSERT(expr) _Static_assert (expr, #expr)
+#define ALIGN(n) __attribute__ ((aligned (n)))
+#define alignof(expr) __alignof__ (expr)
+#define HAS_ALIGN(f, n) __builtin_has_attribute (f, __aligned__ (n))
+
+#define MINALIGN(N) (N < 4 ? 4 : N)
+#define MAXALIGN 16
+
+/* No alignment specified. */
+void f (void) { }
+
+/* Empty alignment means maximum. */
+ALIGN () void f_ (void) { }
+
+ALIGN (0) void f0 (void) { } /* { dg-warning "requested alignment .0. is not a positive power of 2" } */
+ALIGN (1) void f1 (void) { }
+ALIGN (2) void f2 (void) { }
+ALIGN (4) void f4 (void) { }
+ALIGN (8) void f8 (void) { }
+ALIGN (16) void f16 (void) { }
+ALIGN (32) void f32 (void) { }
+
+ASSERT (alignof (f_) == MAXALIGN);
+ASSERT (alignof (f0) == alignof (f));
+ASSERT (alignof (f1) == MINALIGN (1));
+ASSERT (alignof (f2) == MINALIGN (2));
+ASSERT (alignof (f4) == MINALIGN (4));
+ASSERT (alignof (f8) == MINALIGN (8));
+ASSERT (alignof (f16) == MINALIGN (16));
+ASSERT (alignof (f32) == MINALIGN (32));
+
+ASSERT (!__builtin_has_attribute (f, aligned));
+ASSERT (__builtin_has_attribute (f_, aligned));
+ASSERT (!__builtin_has_attribute (f0, aligned));
+
+ASSERT (!HAS_ALIGN (f_, MAXALIGN));
+
+ASSERT (HAS_ALIGN (f1, 1));
+ASSERT (!HAS_ALIGN (f1, 2));
+
+ASSERT (!HAS_ALIGN (f2, 1));
+ASSERT (HAS_ALIGN (f2, 2));
+ASSERT (!HAS_ALIGN (f2, 4));
+
+ASSERT (!HAS_ALIGN (f4, 2));
+ASSERT (HAS_ALIGN (f4, 4));
+ASSERT (!HAS_ALIGN (f4, 8));
+
+ASSERT (!HAS_ALIGN (f8, 4));
+ASSERT (HAS_ALIGN (f8, 8));
+ASSERT (!HAS_ALIGN (f8, 16));
+
+ASSERT (!HAS_ALIGN (f16, 8));
+ASSERT (HAS_ALIGN (f16, 16));
+ASSERT (!HAS_ALIGN (f16, 32));
+
+ASSERT (!HAS_ALIGN (f32, 16));
+ASSERT (HAS_ALIGN (f32, 32));
+ASSERT (!HAS_ALIGN (f32, 64));
--- /dev/null
+/* Verify that valid alignment on functions is accepted and results
+ in the alignment expected for the target and that alignment of
+ zero is ignored with a warning.
+ { dg-do compile }
+ { dg-options "-Wno-pedantic -ftrack-macro-expansion=0" } */
+
+#define ASSERT(expr) _Static_assert (expr, #expr)
+#define ALIGN(n) __attribute__ ((aligned (n)))
+#define alignof(expr) __alignof__ (expr)
+#define HAS_ALIGN(f, n) __builtin_has_attribute (f, __aligned__ (n))
+
+#define MINALIGN(N) ((N) < 4 ? 4 : (N))
+#define MAXALIGN 8
+
+/* No alignment specified. */
+void f (void) { }
+
+/* Empty alignment means maximum. */
+ALIGN () void f_ (void) { }
+
+ALIGN (0) void f0 (void) { } /* { dg-warning "requested alignment .0. is not a positive power of 2" } */
+ALIGN (1) void f1 (void) { }
+ALIGN (2) void f2 (void) { }
+ALIGN (4) void f4 (void) { }
+ALIGN (8) void f8 (void) { }
+ALIGN (16) void f16 (void) { }
+ALIGN (32) void f32 (void) { }
+
+ASSERT (alignof (f_) == MAXALIGN);
+ASSERT (alignof (f0) == alignof (f));
+ASSERT (alignof (f1) == MINALIGN (1));
+ASSERT (alignof (f2) == MINALIGN (2));
+ASSERT (alignof (f4) == MINALIGN (4));
+ASSERT (alignof (f8) == MINALIGN (8));
+ASSERT (alignof (f16) == MINALIGN (16));
+ASSERT (alignof (f32) == MINALIGN (32));
+
+ASSERT (!__builtin_has_attribute (f, aligned));
+ASSERT (__builtin_has_attribute (f_, aligned));
+ASSERT (!__builtin_has_attribute (f0, aligned));
+
+ASSERT (!HAS_ALIGN (f_, MAXALIGN));
+
+ASSERT (HAS_ALIGN (f1, 1));
+ASSERT (!HAS_ALIGN (f1, 2));
+
+ASSERT (!HAS_ALIGN (f2, 1));
+ASSERT (HAS_ALIGN (f2, 2));
+ASSERT (!HAS_ALIGN (f2, 4));
+
+ASSERT (!HAS_ALIGN (f4, 2));
+ASSERT (HAS_ALIGN (f4, 4));
+ASSERT (!HAS_ALIGN (f4, 8));
+
+ASSERT (!HAS_ALIGN (f8, 4));
+ASSERT (HAS_ALIGN (f8, 8));
+ASSERT (!HAS_ALIGN (f8, 16));
+
+ASSERT (!HAS_ALIGN (f16, 8));
+ASSERT (HAS_ALIGN (f16, 16));
+ASSERT (!HAS_ALIGN (f16, 32));
+
+ASSERT (!HAS_ALIGN (f32, 16));
+ASSERT (HAS_ALIGN (f32, 32));
+ASSERT (!HAS_ALIGN (f32, 64));