OSDN Git Service

* c-decl.c (shadow_tag_warned, grokdeclarator): Handle _Alignas
authorjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 6 Nov 2011 23:51:19 +0000 (23:51 +0000)
committerjsm28 <jsm28@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 6 Nov 2011 23:51:19 +0000 (23:51 +0000)
specifiers.
(build_null_declspecs): Initialize align_log and alignas_p fields.
(declspecs_add_alignas): New.
* c-parser.c (c_token_starts_declspecs): Handle RID_ALIGNAS.
(c_parser_declspecs): Handle _Alignas specifiers.
(c_parser_alignas_specifier): New.
(c_parser_alignof_expression): Diagnose alignof use for non-C1X.
Diagnose _Alignof (expression).
* c-tree.h (struct c_declspecs): Add align_log and alignas_p
fields.
(declspecs_add_alignas): Declare.
* ginclude/stddef.h (max_align_t): Define for C1X and C++11.
* ginclude/stdalign.h: New.
* Makefile.in (USER_H): Add stdalign.h.

c-family:
* c-common.c (c_common_reswords): Add _Alignas and _Alignof.
(c_sizeof_or_alignof_type): Diagnose alignof applied to a function
type.
(check_user_alignment): New.  Split out of
handle_aligned_attribute.  Disallow integer constants with
noninteger types.  Conditionally allow zero.
(handle_aligned_attribute): Use check_user_alignment.
* c-common.h (RID_ALIGNAS, check_user_alignment): New.

testsuite:
* g++.dg/cpp0x/alignof3.C, gcc.dg/c1x-align-1.c,
gcc.dg/c1x-align-2.c, gcc.dg/c1x-align-3.c, gcc.dg/c1x-align-4.c,
gcc.dg/c90-align-1.c, gcc.dg/c99-align-1.c: New tests.
* gcc.dg/gnu89-const-expr-1.c, gcc.dg/gnu90-const-expr-1.c,
gcc.dg/gnu99-const-expr-1.c, gcc.dg/gnu99-static-1.c: Update
expected diagnostics.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@181048 138bc75d-0d04-0410-961f-82ee72b054a4

22 files changed:
gcc/ChangeLog
gcc/Makefile.in
gcc/c-decl.c
gcc/c-family/ChangeLog
gcc/c-family/c-common.c
gcc/c-family/c-common.h
gcc/c-parser.c
gcc/c-tree.h
gcc/ginclude/stdalign.h [new file with mode: 0644]
gcc/ginclude/stddef.h
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/alignof3.C [new file with mode: 0644]
gcc/testsuite/gcc.dg/c1x-align-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c1x-align-2.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c1x-align-3.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c1x-align-4.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c90-align-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/c99-align-1.c [new file with mode: 0644]
gcc/testsuite/gcc.dg/gnu89-const-expr-1.c
gcc/testsuite/gcc.dg/gnu90-const-expr-1.c
gcc/testsuite/gcc.dg/gnu99-const-expr-1.c
gcc/testsuite/gcc.dg/gnu99-static-1.c

index 0a6059a..c40541f 100644 (file)
@@ -1,3 +1,21 @@
+2011-11-06  Joseph Myers  <joseph@codesourcery.com>
+
+       * c-decl.c (shadow_tag_warned, grokdeclarator): Handle _Alignas
+       specifiers.
+       (build_null_declspecs): Initialize align_log and alignas_p fields.
+       (declspecs_add_alignas): New.
+       * c-parser.c (c_token_starts_declspecs): Handle RID_ALIGNAS.
+       (c_parser_declspecs): Handle _Alignas specifiers.
+       (c_parser_alignas_specifier): New.
+       (c_parser_alignof_expression): Diagnose alignof use for non-C1X.
+       Diagnose _Alignof (expression).
+       * c-tree.h (struct c_declspecs): Add align_log and alignas_p
+       fields.
+       (declspecs_add_alignas): Declare.
+       * ginclude/stddef.h (max_align_t): Define for C1X and C++11.
+       * ginclude/stdalign.h: New.
+       * Makefile.in (USER_H): Add stdalign.h.
+
 2011-11-06  Joern Rennecke  <joern.rennecke@embecosm.com>
            Eric Botcazou  <ebotcazou@adacore.com>
 
index aebd098..20bb98a 100644 (file)
@@ -376,6 +376,7 @@ USER_H = $(srcdir)/ginclude/float.h \
         $(srcdir)/ginclude/varargs.h \
         $(srcdir)/ginclude/stdfix.h \
         $(srcdir)/ginclude/stdnoreturn.h \
+        $(srcdir)/ginclude/stdalign.h \
         $(EXTRA_HEADERS)
 
 USER_H_INC_NEXT_PRE = @user_headers_inc_next_pre@
index 7af70f0..3cb29c0 100644 (file)
@@ -3707,6 +3707,17 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
              warned = 1;
              pending_xref_error ();
            }
+         else if (declspecs->typespec_kind != ctsk_tagdef
+                   && declspecs->typespec_kind != ctsk_tagfirstref
+                  && declspecs->alignas_p)
+           {
+             if (warned != 1)
+               pedwarn (input_location, 0,
+                        "empty declaration with %<_Alignas%> "
+                         "does not redeclare tag");
+             warned = 1;
+             pending_xref_error ();
+           }
          else
            {
              pending_invalid_xref = 0;
@@ -3782,6 +3793,12 @@ shadow_tag_warned (const struct c_declspecs *declspecs, int warned)
       warned = 2;
     }
 
+  if (!warned && !in_system_header && declspecs->alignas_p)
+    {
+      warning (0, "useless %<_Alignas%> in empty declaration");
+      warned = 2;
+    }
+
   if (warned != 1)
     {
       if (!found_tag)
@@ -4894,6 +4911,7 @@ grokdeclarator (const struct c_declarator *declarator,
   tree expr_dummy;
   bool expr_const_operands_dummy;
   enum c_declarator_kind first_non_attr_kind;
+  unsigned int alignas_align = 0;
 
   if (TREE_CODE (type) == ERROR_MARK)
     return error_mark_node;
@@ -5737,6 +5755,46 @@ grokdeclarator (const struct c_declarator *declarator,
   if (bitfield)
     check_bitfield_type_and_width (&type, width, name);
 
+  /* Reject invalid uses of _Alignas.  */
+  if (declspecs->alignas_p)
+    {
+      if (storage_class == csc_typedef)
+       error_at (loc, "alignment specified for typedef %qE", name);
+      else if (storage_class == csc_register)
+       error_at (loc, "alignment specified for %<register%> object %qE",
+                 name);
+      else if (decl_context == PARM)
+       {
+         if (name)
+           error_at (loc, "alignment specified for parameter %qE", name);
+         else
+           error_at (loc, "alignment specified for unnamed parameter");
+       }
+      else if (bitfield)
+       {
+         if (name)
+           error_at (loc, "alignment specified for bit-field %qE", name);
+         else
+           error_at (loc, "alignment specified for unnamed bit-field");
+       }
+      else if (TREE_CODE (type) == FUNCTION_TYPE)
+       error_at (loc, "alignment specified for function %qE", name);
+      else if (declspecs->align_log != -1)
+       {
+         alignas_align = 1U << declspecs->align_log;
+         if (alignas_align < TYPE_ALIGN_UNIT (type))
+           {
+             if (name)
+               error_at (loc, "%<_Alignas%> specifiers cannot reduce "
+                         "alignment of %qE", name);
+             else
+               error_at (loc, "%<_Alignas%> specifiers cannot reduce "
+                         "alignment of unnamed field");
+             alignas_align = 0;
+           }
+       }
+    }
+
   /* Did array size calculations overflow?  */
 
   if (TREE_CODE (type) == ARRAY_TYPE
@@ -6117,6 +6175,13 @@ grokdeclarator (const struct c_declarator *declarator,
     /* Record constancy and volatility.  */
     c_apply_type_quals_to_decl (type_quals, decl);
 
+    /* Apply _Alignas specifiers.  */
+    if (alignas_align)
+      {
+       DECL_ALIGN (decl) = alignas_align * BITS_PER_UNIT;
+       DECL_USER_ALIGN (decl) = 1;
+      }
+
     /* If a type has volatile components, it should be stored in memory.
        Otherwise, the fact that those components are volatile
        will be ignored, and would even crash the compiler.
@@ -8709,6 +8774,7 @@ build_null_declspecs (void)
   ret->expr = 0;
   ret->decl_attr = 0;
   ret->attrs = 0;
+  ret->align_log = -1;
   ret->typespec_word = cts_none;
   ret->storage_class = csc_none;
   ret->expr_const_operands = true;
@@ -8732,6 +8798,7 @@ build_null_declspecs (void)
   ret->volatile_p = false;
   ret->restrict_p = false;
   ret->saturating_p = false;
+  ret->alignas_p = false;
   ret->address_space = ADDR_SPACE_GENERIC;
   return ret;
 }
@@ -9522,6 +9589,22 @@ declspecs_add_attrs (struct c_declspecs *specs, tree attrs)
   return specs;
 }
 
+/* Add an _Alignas specifier (expression ALIGN, or type whose
+   alignment is ALIGN) to the declaration specifiers SPECS, returning
+   SPECS.  */
+struct c_declspecs *
+declspecs_add_alignas (struct c_declspecs *specs, tree align)
+{
+  int align_log;
+  specs->alignas_p = true;
+  if (align == error_mark_node)
+    return specs;
+  align_log = check_user_alignment (align, true);
+  if (align_log > specs->align_log)
+    specs->align_log = align_log;
+  return specs;
+}
+
 /* Combine "long", "short", "signed", "unsigned" and "_Complex" type
    specifiers with any other type specifier to determine the resulting
    type.  This is where ISO C checks on complex types are made, since
index 1c8a6b4..3829411 100644 (file)
@@ -1,3 +1,14 @@
+2011-11-06  Joseph Myers  <joseph@codesourcery.com>
+
+       * c-common.c (c_common_reswords): Add _Alignas and _Alignof.
+       (c_sizeof_or_alignof_type): Diagnose alignof applied to a function
+       type.
+       (check_user_alignment): New.  Split out of
+       handle_aligned_attribute.  Disallow integer constants with
+       noninteger types.  Conditionally allow zero.
+       (handle_aligned_attribute): Use check_user_alignment.
+       * c-common.h (RID_ALIGNAS, check_user_alignment): New.
+
 2011-11-06  Andrew MacLeod  <amacleod@redhat.com>
            Richard Henderson  <rth@redhat.com>
 
index aa5f3bf..0329bc7 100644 (file)
@@ -404,6 +404,8 @@ static int resort_field_decl_cmp (const void *, const void *);
 */
 const struct c_common_resword c_common_reswords[] =
 {
+  { "_Alignas",                RID_ALIGNAS,   D_CONLY },
+  { "_Alignof",                RID_ALIGNOF,   D_CONLY },
   { "_Bool",           RID_BOOL,      D_CONLY },
   { "_Complex",                RID_COMPLEX,    0 },
   { "_Imaginary",      RID_IMAGINARY, D_CONLY },
@@ -4332,7 +4334,18 @@ c_sizeof_or_alignof_type (location_t loc,
          value = size_one_node;
        }
       else
-       value = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
+       {
+         if (complain)
+           {
+             if (c_dialect_cxx ())
+               pedwarn (loc, OPT_pedantic, "ISO C++ does not permit "
+                        "%<alignof%> applied to a function type");
+             else
+               pedwarn (loc, OPT_pedantic, "ISO C does not permit "
+                        "%<_Alignof%> applied to a function type");
+           }
+         value = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
+       }
     }
   else if (type_code == VOID_TYPE || type_code == ERROR_MARK)
     {
@@ -6670,6 +6683,36 @@ handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args,
   return NULL_TREE;
 }
 
+/* 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;
+
+  if (!INTEGRAL_TYPE_P (TREE_TYPE (align))
+      || TREE_CODE (align) != INTEGER_CST)
+    {
+      error ("requested alignment is not an integer constant");
+      return -1;
+    }
+  else if (allow_zero && integer_zerop (align))
+    return -1;
+  else if ((i = tree_log2 (align)) == -1)
+    {
+      error ("requested alignment is not a power of 2");
+      return -1;
+    }
+  else if (i >= HOST_BITS_PER_INT - BITS_PER_UNIT_LOG)
+    {
+      error ("requested alignment is too large");
+      return -1;
+    }
+  return i;
+}
+
 /* Handle a "aligned" attribute; arguments as in
    struct attribute_spec.handler.  */
 
@@ -6693,21 +6736,8 @@ handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
   else if (TYPE_P (*node))
     type = node, is_type = 1;
 
-  if (TREE_CODE (align_expr) != INTEGER_CST)
-    {
-      error ("requested alignment is not a constant");
-      *no_add_attrs = true;
-    }
-  else if ((i = tree_log2 (align_expr)) == -1)
-    {
-      error ("requested alignment is not a power of 2");
-      *no_add_attrs = true;
-    }
-  else if (i >= HOST_BITS_PER_INT - BITS_PER_UNIT_LOG)
-    {
-      error ("requested alignment is too large");
-      *no_add_attrs = true;
-    }
+  if ((i = check_user_alignment (align_expr, false)) == -1)
+    *no_add_attrs = true;
   else if (is_type)
     {
       if ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
index 7ecb57e..bff6956 100644 (file)
@@ -106,6 +106,9 @@ enum rid
   RID_DFLOAT32, RID_DFLOAT64, RID_DFLOAT128,
   RID_FRACT, RID_ACCUM,
 
+  /* C1X */
+  RID_ALIGNAS,
+
   /* This means to warn that this is a C++ keyword, and then treat it
      as a normal identifier.  */
   RID_CXX_COMPAT_WARN,
@@ -724,6 +727,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 void check_function_arguments (const_tree, int, tree *);
 extern void check_function_arguments_recurse (void (*)
                                              (void *, tree,
index 8db203a..58bcb02 100644 (file)
@@ -650,6 +650,7 @@ c_token_starts_declspecs (c_token *token)
        case RID_FRACT:
        case RID_ACCUM:
        case RID_SAT:
+       case RID_ALIGNAS:
          return true;
        default:
          return false;
@@ -1120,6 +1121,7 @@ static struct c_typespec c_parser_enum_specifier (c_parser *);
 static struct c_typespec c_parser_struct_or_union_specifier (c_parser *);
 static tree c_parser_struct_declaration (c_parser *);
 static struct c_typespec c_parser_typeof_specifier (c_parser *);
+static tree c_parser_alignas_specifier (c_parser *);
 static struct c_declarator *c_parser_declarator (c_parser *, bool, c_dtr_syn,
                                                 bool *);
 static struct c_declarator *c_parser_direct_declarator (c_parser *, bool,
@@ -1890,9 +1892,11 @@ c_parser_static_assert_declaration_no_semi (c_parser *parser)
      type-specifier declaration-specifiers[opt]
      type-qualifier declaration-specifiers[opt]
      function-specifier declaration-specifiers[opt]
+     alignment-specifier declaration-specifiers[opt]
 
    Function specifiers (inline) are from C99, and are currently
-   handled as storage class specifiers, as is __thread.
+   handled as storage class specifiers, as is __thread.  Alignment
+   specifiers are from C1X.
 
    C90 6.5.1, C99 6.7.1:
    storage-class-specifier:
@@ -1991,6 +1995,7 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
     {
       struct c_typespec t;
       tree attrs;
+      tree align;
       location_t loc = c_parser_peek_token (parser)->location;
 
       /* If we cannot accept a type, exit if the next token must start
@@ -2169,6 +2174,10 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
          attrs = c_parser_attributes (parser);
          declspecs_add_attrs (specs, attrs);
          break;
+       case RID_ALIGNAS:
+         align = c_parser_alignas_specifier (parser);
+         declspecs_add_alignas (specs, align);
+         break;
        default:
          goto out;
        }
@@ -2751,6 +2760,45 @@ c_parser_typeof_specifier (c_parser *parser)
   return ret;
 }
 
+/* Parse an alignment-specifier.
+
+   C1X 6.7.5:
+
+   alignment-specifier:
+     _Alignas ( type-name )
+     _Alignas ( constant-expression )
+*/
+
+static tree
+c_parser_alignas_specifier (c_parser * parser)
+{
+  tree ret = error_mark_node;
+  location_t loc = c_parser_peek_token (parser)->location;
+  gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNAS));
+  c_parser_consume_token (parser);
+  if (!flag_isoc1x)
+    {
+      if (flag_isoc99)
+       pedwarn (loc, OPT_pedantic,
+                "ISO C99 does not support %<_Alignas%>");
+      else
+       pedwarn (loc, OPT_pedantic,
+                "ISO C90 does not support %<_Alignas%>");
+    }
+  if (!c_parser_require (parser, CPP_OPEN_PAREN, "expected %<(%>"))
+    return ret;
+  if (c_parser_next_tokens_start_typename (parser, cla_prefer_id))
+    {
+      struct c_type_name *type = c_parser_type_name (parser);
+      if (type != NULL)
+       ret = c_alignof (loc, groktypename (type, NULL, NULL));
+    }
+  else
+    ret = c_parser_expr_no_commas (parser, NULL).value;
+  c_parser_skip_until_found (parser, CPP_CLOSE_PAREN, "expected %<)%>");
+  return ret;
+}
+
 /* Parse a declarator, possibly an abstract declarator (C90 6.5.4,
    6.5.5, C99 6.7.5, 6.7.6).  If TYPE_SEEN_P then a typedef name may
    be redeclared; otherwise it may not.  KIND indicates which kind of
@@ -5759,6 +5807,8 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
      __alignof__ ( type-name )
      && identifier
 
+   (C1X permits _Alignof with type names only.)
+
    unary-operator: one of
      __extension__ __real__ __imag__
 
@@ -5942,7 +5992,21 @@ c_parser_alignof_expression (c_parser *parser)
 {
   struct c_expr expr;
   location_t loc = c_parser_peek_token (parser)->location;
+  tree alignof_spelling = c_parser_peek_token (parser)->value;
   gcc_assert (c_parser_next_token_is_keyword (parser, RID_ALIGNOF));
+  /* A diagnostic is not required for the use of this identifier in
+     the implementation namespace; only diagnose it for the C1X
+     spelling because of existing code using the other spellings.  */
+  if (!flag_isoc1x
+      && strcmp (IDENTIFIER_POINTER (alignof_spelling), "_Alignof") == 0)
+    {
+      if (flag_isoc99)
+       pedwarn (loc, OPT_pedantic, "ISO C99 does not support %qE",
+                alignof_spelling);
+      else
+       pedwarn (loc, OPT_pedantic, "ISO C90 does not support %qE",
+                alignof_spelling);
+    }
   c_parser_consume_token (parser);
   c_inhibit_evaluation_warnings++;
   in_alignof++;
@@ -5991,6 +6055,8 @@ c_parser_alignof_expression (c_parser *parser)
       mark_exp_read (expr.value);
       c_inhibit_evaluation_warnings--;
       in_alignof--;
+      pedwarn (loc, OPT_pedantic, "ISO C does not allow %<%E (expression)%>",
+              alignof_spelling);
       ret.value = c_alignof_expr (loc, expr.value);
       ret.original_code = ERROR_MARK;
       ret.original_type = NULL;
index b3e756c..6801db2 100644 (file)
@@ -238,6 +238,10 @@ struct c_declspecs {
      NULL; attributes (possibly from multiple lists) will be passed
      separately.  */
   tree attrs;
+  /* The base-2 log of the greatest alignment required by an _Alignas
+     specifier, in bytes, or -1 if no such specifiers with nonzero
+     alignment.  */
+  int align_log;
   /* The storage class specifier, or csc_none if none.  */
   enum c_storage_class storage_class;
   /* Any type specifier keyword used such as "int", not reflecting
@@ -294,6 +298,9 @@ struct c_declspecs {
   BOOL_BITFIELD restrict_p : 1;
   /* Whether "_Sat" was specified.  */
   BOOL_BITFIELD saturating_p : 1;
+  /* Whether any alignment specifier (even with zero alignment) was
+     specified.  */
+  BOOL_BITFIELD alignas_p : 1;
   /* The address space that the declaration belongs to.  */
   addr_space_t address_space;
 };
@@ -510,6 +517,7 @@ extern struct c_declspecs *declspecs_add_scspec (struct c_declspecs *, tree);
 extern struct c_declspecs *declspecs_add_attrs (struct c_declspecs *, tree);
 extern struct c_declspecs *declspecs_add_addrspace (struct c_declspecs *,
                                                    addr_space_t);
+extern struct c_declspecs *declspecs_add_alignas (struct c_declspecs *, tree);
 extern struct c_declspecs *finish_declspecs (struct c_declspecs *);
 
 /* in c-objc-common.c */
diff --git a/gcc/ginclude/stdalign.h b/gcc/ginclude/stdalign.h
new file mode 100644 (file)
index 0000000..fd55ed3
--- /dev/null
@@ -0,0 +1,39 @@
+/* Copyright (C) 2011 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3, or (at your option)
+any later version.
+
+GCC is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+Under Section 7 of GPL version 3, you are granted additional
+permissions described in the GCC Runtime Library Exception, version
+3.1, as published by the Free Software Foundation.
+
+You should have received a copy of the GNU General Public License and
+a copy of the GCC Runtime Library Exception along with this program;
+see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
+<http://www.gnu.org/licenses/>.  */
+
+/* ISO C1X: 7.15 Alignment <stdalign.h>.  */
+
+#ifndef _STDALIGN_H
+#define _STDALIGN_H
+
+#ifndef __cplusplus
+
+#define alignas _Alignas
+#define alignof _Alignof
+
+#define __alignas_is_defined 1
+#define __alignof_is_defined 1
+
+#endif
+
+#endif /* stdalign.h */
index 565ef7b..1cc3cb4 100644 (file)
@@ -1,4 +1,4 @@
-/* Copyright (C) 1989, 1997, 1998, 1999, 2000, 2002, 2004, 2009
+/* Copyright (C) 1989, 1997, 1998, 1999, 2000, 2002, 2004, 2009, 2011
    Free Software Foundation, Inc.
 
 This file is part of GCC.
@@ -412,6 +412,20 @@ typedef __WINT_TYPE__ wint_t;
 /* Offset of member MEMBER in a struct of type TYPE. */
 #define offsetof(TYPE, MEMBER) __builtin_offsetof (TYPE, MEMBER)
 
+#if (defined (__STDC_VERSION__) && __STDC_VERSION__ > 199901L) \
+  || (defined(__cplusplus) && __cplusplus >= 201103L)
+#ifndef _GCC_MAX_ALIGN_T
+#define _GCC_MAX_ALIGN_T
+/* Type whose alignment is supported in every context and is at least
+   as great as that of any standard type not using alignment
+   specifiers.  */
+typedef struct {
+  long long __max_align_ll __attribute__((__aligned__(__alignof__(long long))));
+  long double __max_align_ld __attribute__((__aligned__(__alignof__(long double))));
+} max_align_t;
+#endif
+#endif /* C1X or C++11.  */
+
 #endif /* _STDDEF_H was defined this time */
 
 #endif /* !_STDDEF_H && !_STDDEF_H_ && !_ANSI_STDDEF_H && !__STDDEF_H__
index aa0b7b6..62f76f9 100644 (file)
@@ -1,3 +1,12 @@
+2011-11-06  Joseph Myers  <joseph@codesourcery.com>
+
+       * g++.dg/cpp0x/alignof3.C, gcc.dg/c1x-align-1.c,
+       gcc.dg/c1x-align-2.c, gcc.dg/c1x-align-3.c, gcc.dg/c1x-align-4.c,
+       gcc.dg/c90-align-1.c, gcc.dg/c99-align-1.c: New tests.
+       * gcc.dg/gnu89-const-expr-1.c, gcc.dg/gnu90-const-expr-1.c,
+       gcc.dg/gnu99-const-expr-1.c, gcc.dg/gnu99-static-1.c: Update
+       expected diagnostics.
+
 2011-11-06  Andrew MacLeod  <amacleod@redhat.com>
            Richard Henderson  <rth@redhat.com>
            Aldy Hernandez  <aldyh@redhat.com>
diff --git a/gcc/testsuite/g++.dg/cpp0x/alignof3.C b/gcc/testsuite/g++.dg/cpp0x/alignof3.C
new file mode 100644 (file)
index 0000000..50c6ac9
--- /dev/null
@@ -0,0 +1,6 @@
+// { dg-do compile }
+// { dg-options "-std=c++0x -pedantic" }
+int main(void)
+{
+  alignof(void (void));   // { dg-warning "function type" }
+}
diff --git a/gcc/testsuite/gcc.dg/c1x-align-1.c b/gcc/testsuite/gcc.dg/c1x-align-1.c
new file mode 100644 (file)
index 0000000..9fe5757
--- /dev/null
@@ -0,0 +1,41 @@
+/* Test C1X alignment support.  Test valid code.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c1x -pedantic-errors" } */
+
+#include <stddef.h>
+
+_Alignas (_Alignof (max_align_t)) char c;
+extern _Alignas (max_align_t) char c;
+extern char c;
+
+extern _Alignas (max_align_t) short s;
+_Alignas (max_align_t) short s;
+
+_Alignas (int) int i;
+extern int i;
+
+_Alignas (max_align_t) long l;
+
+_Alignas (max_align_t) long long ll;
+
+_Alignas (max_align_t) float f;
+
+_Alignas (max_align_t) double d;
+
+_Alignas (max_align_t) _Complex long double cld;
+
+_Alignas (0) _Alignas (int) _Alignas (char) char ca[10];
+
+_Alignas ((int) _Alignof (max_align_t) + 0) int x;
+
+enum e { E = _Alignof (max_align_t) };
+_Alignas (E) int y;
+
+void
+func (void)
+{
+  _Alignas (max_align_t) long long auto_ll;
+}
+
+/* Valid, but useless.  */
+_Alignas (0) struct s; /* { dg-warning "useless" } */
diff --git a/gcc/testsuite/gcc.dg/c1x-align-2.c b/gcc/testsuite/gcc.dg/c1x-align-2.c
new file mode 100644 (file)
index 0000000..19f7dd6
--- /dev/null
@@ -0,0 +1,92 @@
+/* Test C1X alignment support.  Test valid code using stdalign.h.  */
+/* { dg-do run } */
+/* { dg-options "-std=c1x -pedantic-errors" } */
+
+#include <stdalign.h>
+#include <stddef.h>
+
+extern int strcmp (const char *, const char *);
+
+extern void exit (int);
+extern void abort (void);
+
+alignas (alignof (max_align_t)) char c;
+extern alignas (max_align_t) char c;
+extern char c;
+
+extern alignas (max_align_t) short s;
+alignas (max_align_t) short s;
+
+alignas (int) int i;
+extern int i;
+
+alignas (max_align_t) long l;
+
+alignas (max_align_t) long long ll;
+
+alignas (max_align_t) float f;
+
+alignas (max_align_t) double d;
+
+alignas (max_align_t) _Complex long double cld;
+
+alignas (0) alignas (int) alignas (char) char ca[10];
+
+alignas ((int) alignof (max_align_t) + 0) int x;
+
+enum e { E = alignof (max_align_t) };
+alignas (E) int y;
+
+void
+func (void)
+{
+  alignas (max_align_t) long long auto_ll;
+}
+
+/* Valid, but useless.  */
+alignas (0) struct s; /* { dg-warning "useless" } */
+
+#ifndef alignas
+#error "alignas not defined"
+#endif
+
+#ifndef alignof
+#error "alignof not defined"
+#endif
+
+#ifndef __alignas_is_defined
+#error "__alignas_is_defined not defined"
+#endif
+
+#if __alignas_is_defined != 1
+#error "__alignas_is_defined not 1"
+#endif
+
+#ifndef __alignof_is_defined
+#error "__alignof_is_defined not defined"
+#endif
+
+#if __alignof_is_defined != 1
+#error "__alignof_is_defined not 1"
+#endif
+
+#define str(x) #x
+#define xstr(x) str(x)
+
+const char *s1 = xstr(alignas);
+const char *s2 = xstr(alignof);
+const char *s3 = xstr(__alignas_is_defined);
+const char *s4 = xstr(__alignof_is_defined);
+
+int
+main (void)
+{
+  if (strcmp (s1, "_Alignas") != 0)
+    abort ();
+  if (strcmp (s2, "_Alignof") != 0)
+    abort ();
+  if (strcmp (s3, "1") != 0)
+    abort ();
+  if (strcmp (s4, "1") != 0)
+    abort ();
+}
diff --git a/gcc/testsuite/gcc.dg/c1x-align-3.c b/gcc/testsuite/gcc.dg/c1x-align-3.c
new file mode 100644 (file)
index 0000000..0b2a77f
--- /dev/null
@@ -0,0 +1,42 @@
+/* Test C1X alignment support.  Test invalid code.  */
+/* { dg-do compile } */
+/* { dg-options "-std=c1x -pedantic-errors" } */
+
+int a = _Alignof (void (void)); /* { dg-error "function" } */
+struct s;
+int b = _Alignof (struct s); /* { dg-error "incomplete" } */
+int c = _Alignof (void); /* { dg-error "void" } */
+int d = _Alignof (a); /* { dg-error "expression" } */
+
+_Alignas (void (void)) char e; /* { dg-error "function" } */
+_Alignas (struct s) char f; /* { dg-error "incomplete" } */
+_Alignas (void) char g; /* { dg-error "void" } */
+
+_Alignas (-__INT_MAX__-1) char h; /* { dg-error "too large|power of 2" } */
+_Alignas (-__INT_MAX__) char h2; /* { dg-error "too large|power of 2" } */
+_Alignas ((-__INT_MAX__-1)/2) char h3; /* { dg-error "too large|power of 2" } */
+_Alignas ((-__INT_MAX__-1)/4) char h4; /* { dg-error "too large|power of 2" } */
+_Alignas ((-__INT_MAX__-1)/8) char h5; /* { dg-error "too large|power of 2" } */
+_Alignas (-__LONG_LONG_MAX__-1) char i; /* { dg-error "too large|power of 2" } */
+_Alignas (-(__LONG_LONG_MAX__-1)/2) char i2; /* { dg-error "too large|power of 2" } */
+_Alignas (-(__LONG_LONG_MAX__-1)/4) char i3; /* { dg-error "too large|power of 2" } */
+_Alignas (-(__LONG_LONG_MAX__-1)/8) char i4; /* { dg-error "too large|power of 2" } */
+_Alignas (-(__LONG_LONG_MAX__-1)/16) char i5; /* { dg-error "too large|power of 2" } */
+_Alignas (-1) char j; /* { dg-error "power of 2" } */
+_Alignas (3) char k; /* { dg-error "power of 2" } */
+
+_Alignas ((void *) 1) char k; /* { dg-error "integer constant" } */
+int x;
+_Alignas (x) char l; /* { dg-error "integer constant" } */
+
+_Alignas (0) struct s; /* { dg-error "does not redeclare tag" } */
+
+_Alignas (0) typedef int T; /* { dg-error "alignment specified for typedef" } */
+void func (_Alignas (0) int); /* { dg-error "alignment specified for unnamed parameter" } */
+void f2 (_Alignas (0) int parm2) {} /* { dg-error "alignment specified for parameter" } */
+void
+f3 (void)
+{
+  register _Alignas (0) int reg; /* { dg-error "register" } */
+}
+_Alignas (0) void f4 (void); /* { dg-error "alignment specified for function" } */
diff --git a/gcc/testsuite/gcc.dg/c1x-align-4.c b/gcc/testsuite/gcc.dg/c1x-align-4.c
new file mode 100644 (file)
index 0000000..432650c
--- /dev/null
@@ -0,0 +1,8 @@
+/* Test C1X alignment support.  Test reducing alignment (assumes there
+   are at least some alignment constraints).  */
+/* { dg-do compile } */
+/* { dg-options "-std=c1x -pedantic-errors" } */
+
+#include <stddef.h>
+
+_Alignas (_Alignof (char)) max_align_t x; /* { dg-error "reduce alignment" } */
diff --git a/gcc/testsuite/gcc.dg/c90-align-1.c b/gcc/testsuite/gcc.dg/c90-align-1.c
new file mode 100644 (file)
index 0000000..77510f4
--- /dev/null
@@ -0,0 +1,6 @@
+/* Test _Alignof and _Alignas not in C90.  */
+/* { dg-do compile } */
+/* { dg-options "-std=iso9899:1990 -pedantic-errors" } */
+
+int a = _Alignof (int); /* { dg-error "ISO C90 does not support '_Alignof'" } */
+_Alignas (int) int b; /* { dg-error "ISO C90 does not support '_Alignas'" } */
diff --git a/gcc/testsuite/gcc.dg/c99-align-1.c b/gcc/testsuite/gcc.dg/c99-align-1.c
new file mode 100644 (file)
index 0000000..1fb2cb0
--- /dev/null
@@ -0,0 +1,6 @@
+/* Test _Alignof and _Alignas not in C99.  */
+/* { dg-do compile } */
+/* { dg-options "-std=iso9899:1999 -pedantic-errors" } */
+
+int a = _Alignof (int); /* { dg-error "ISO C99 does not support '_Alignof'" } */
+_Alignas (int) int b; /* { dg-error "ISO C99 does not support '_Alignas'" } */
index 4fd6671..0cc14da 100644 (file)
@@ -23,7 +23,7 @@ f (void)
     E5 = __imag__ 0,
     /* __alignof__ always constant.  */
     E6 = __alignof__ (int[n]), /* { dg-error "ISO C90 forbids variable length array" } */
-    E7 = __alignof__ (a),
+    E7 = __alignof__ (a), /* { dg-error "__alignof__ \\(expression\\)" } */
     /* __extension__ ignored for constant expression purposes.  */
     E8 = __extension__ (1 ? 0 : i++), /* { dg-error "constant expression" } */
     E9 = __extension__ 0,
index 3f7f1af..e052114 100644 (file)
@@ -23,7 +23,7 @@ f (void)
     E5 = __imag__ 0,
     /* __alignof__ always constant.  */
     E6 = __alignof__ (int[n]), /* { dg-error "ISO C90 forbids variable length array" } */
-    E7 = __alignof__ (a),
+    E7 = __alignof__ (a), /* { dg-error "__alignof__ \\(expression\\)" } */
     /* __extension__ ignored for constant expression purposes.  */
     E8 = __extension__ (1 ? 0 : i++), /* { dg-error "constant expression" } */
     E9 = __extension__ 0,
index 3f5f25e..da7076f 100644 (file)
@@ -23,7 +23,7 @@ f (void)
     E5 = __imag__ 0,
     /* __alignof__ always constant.  */
     E6 = __alignof__ (int[n]),
-    E7 = __alignof__ (a),
+    E7 = __alignof__ (a), /* { dg-error "__alignof__ \\(expression\\)" } */
     /* __extension__ ignored for constant expression purposes.  */
     E8 = __extension__ (1 ? 0 : i++), /* { dg-error "constant expression" } */
     E9 = __extension__ 0,
index b600a4b..3fece61 100644 (file)
@@ -11,7 +11,7 @@
 
 /* __alignof__, OK.  */
 static int f0(void);
-void g0(void) { __alignof__(f0()); }
+void g0(void) { __alignof__(f0()); } /* { dg-error "__alignof__ \\(expression\\)" } */
 
 /* __typeof__ not variably modified, OK.  */
 static int f1(void);