PR c/88172 - attribute aligned of zero silently accepted but ignored
authorMartin Sebor <msebor@redhat.com>
Thu, 29 Nov 2018 17:48:58 +0000 (17:48 +0000)
committerMartin Sebor <msebor@gcc.gnu.org>
Thu, 29 Nov 2018 17:48:58 +0000 (10:48 -0700)
PR c/88172 - attribute aligned of zero silently accepted but ignored
PR testsuite/88208 - new test case c-c++-common/builtin-has-attribute-3.c in r266335 has multiple excess errors

gcc/ChangeLog:

PR c/88172
PR testsuite/88208
* doc/extend.texi (attribute constructor): Clarify.

gcc/c/ChangeLog:

PR c/88172
PR testsuite/88208
* c-decl.c (declspec_add_alignas): Adjust call to check_user_alignment.

gcc/c-family/ChangeLog:

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.

gcc/testsuite/ChangeLog:

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.

From-SVN: r266633

18 files changed:
gcc/ChangeLog
gcc/c-family/ChangeLog
gcc/c-family/c-attribs.c
gcc/c-family/c-common.c
gcc/c/ChangeLog
gcc/c/c-decl.c
gcc/doc/extend.texi
gcc/testsuite/ChangeLog
gcc/testsuite/c-c++-common/builtin-has-attribute-2.c
gcc/testsuite/c-c++-common/builtin-has-attribute-3.c
gcc/testsuite/c-c++-common/builtin-has-attribute-4.c
gcc/testsuite/c-c++-common/builtin-has-attribute-5.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/attr-aligned-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/builtin-has-attribute.c
gcc/testsuite/gcc.target/aarch64/attr-aligned.c [new file with mode: 0644]
gcc/testsuite/gcc.target/i386/attr-aligned.c [new file with mode: 0644]
gcc/testsuite/gcc.target/powerpc/attr-aligned.c [new file with mode: 0644]
gcc/testsuite/gcc.target/sparc/attr-aligned.c [new file with mode: 0644]

index 02c2403..bc8d2b1 100644 (file)
@@ -1,3 +1,9 @@
+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
index ee193d9..890b014 100644 (file)
@@ -1,3 +1,14 @@
+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
index 373381d..1454e2f 100644 (file)
@@ -2003,7 +2003,8 @@ common_handle_aligned_attribute (tree *node, tree name, tree args, int flags,
   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))
     {
@@ -2019,6 +2020,9 @@ common_handle_aligned_attribute (tree *node, tree name, tree args, int 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))
@@ -2067,23 +2071,35 @@ common_handle_aligned_attribute (tree *node, tree name, tree args, int flags,
        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)
@@ -2100,33 +2116,29 @@ common_handle_aligned_attribute (tree *node, tree name, tree args, int flags,
           && 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)
     {
@@ -2134,6 +2146,11 @@ common_handle_aligned_attribute (tree *node, tree name, tree args, int flags,
             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;
 }
@@ -4086,11 +4103,6 @@ has_attribute (location_t atloc, tree t, tree attr, tree (*convert)(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.  */
index 9d51815..4c90365 100644 (file)
@@ -5143,11 +5143,11 @@ c_init_attributes (void)
    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;
@@ -5159,8 +5159,14 @@ check_user_alignment (const_tree align, bool objfile, bool allow_zero)
       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
index bcb282c..4ed5b4b 100644 (file)
@@ -1,3 +1,9 @@
+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
index cdd10ab..b50f2bf 100644 (file)
@@ -11061,12 +11061,15 @@ struct c_declspecs *
 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;
index 4e8be5b..8c7b178 100644 (file)
@@ -2552,8 +2552,9 @@ called.  Functions with these attributes are useful for
 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
@@ -2566,6 +2567,10 @@ decorated with attribute @code{constructor} are invoked is unspecified.
 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
index 5dcc0b4..ecb1ad6 100644 (file)
@@ -1,3 +1,18 @@
+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.
index 0f692ff..f842241 100644 (file)
@@ -42,8 +42,8 @@ void test_type (int n)
 
   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)); */
@@ -132,7 +132,7 @@ void test_typedef (int n)
   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));
@@ -141,7 +141,7 @@ void test_typedef (int n)
 
   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));
index 237dc72..f048059 100644 (file)
@@ -35,7 +35,7 @@ ATTR (alias ("fnoreturn")) void falias (void);
 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));
@@ -43,18 +43,18 @@ void test_aligned (void)
   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));
@@ -193,18 +193,6 @@ void test_ctor_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));
 }
 
 
index 14bdd3f..d56ef6b 100644 (file)
@@ -19,7 +19,7 @@ ATTR (aligned (8)) char valigned_8;
 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));
@@ -27,18 +27,18 @@ void test_aligned (void)
   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));
diff --git a/gcc/testsuite/c-c++-common/builtin-has-attribute-5.c b/gcc/testsuite/c-c++-common/builtin-has-attribute-5.c
new file mode 100644 (file)
index 0000000..20d95d8
--- /dev/null
@@ -0,0 +1,48 @@
+/* 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));
+}
diff --git a/gcc/testsuite/gcc.dg/attr-aligned-2.c b/gcc/testsuite/gcc.dg/attr-aligned-2.c
new file mode 100644 (file)
index 0000000..ff6516c
--- /dev/null
@@ -0,0 +1,21 @@
+/* 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);
index 8c11cf8..9668ace 100644 (file)
@@ -3,16 +3,14 @@
    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                                                   \
@@ -24,22 +22,27 @@ A (0, struct A { int i; }, aligned);   /* { dg-warning "expression is invalid in
 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" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/attr-aligned.c b/gcc/testsuite/gcc.target/aarch64/attr-aligned.c
new file mode 100644 (file)
index 0000000..fe37dba
--- /dev/null
@@ -0,0 +1,65 @@
+/* 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));
diff --git a/gcc/testsuite/gcc.target/i386/attr-aligned.c b/gcc/testsuite/gcc.target/i386/attr-aligned.c
new file mode 100644 (file)
index 0000000..1ed9c8c
--- /dev/null
@@ -0,0 +1,65 @@
+/* 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));
diff --git a/gcc/testsuite/gcc.target/powerpc/attr-aligned.c b/gcc/testsuite/gcc.target/powerpc/attr-aligned.c
new file mode 100644 (file)
index 0000000..4b5b666
--- /dev/null
@@ -0,0 +1,65 @@
+/* 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));
diff --git a/gcc/testsuite/gcc.target/sparc/attr-aligned.c b/gcc/testsuite/gcc.target/sparc/attr-aligned.c
new file mode 100644 (file)
index 0000000..7dc9b19
--- /dev/null
@@ -0,0 +1,65 @@
+/* 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));