+2017-12-07 Joseph Myers <joseph@codesourcery.com>
+
+ * c-decl.c (build_compound_literal): Add parameter alignas_align
+ and set alignment of decl if nonzero.
+ * c-parser.c (c_keyword_starts_typename): Allow RID_ALIGNAS.
+ (c_parser_declspecs): Allow RID_ALIGNAS to follow a type, like a
+ qualifier.
+ (c_parser_struct_declaration): Update syntax comment.
+ (c_parser_type_name): Add alignas_ok argument and pass it to
+ c_parser_declspecs.
+ (c_parser_cast_expression): Pass true to c_parser_type_name and
+ give error if a cast used an _Alignas specifier.
+ (c_parser_sizeof_expression): Pass true to c_parser_type_name and
+ give error if sizeof (type-name) used an _Alignas specifier.
+ (c_parser_alignof_expression): Pass true to c_parser_type_name and
+ give error if _Alignof (type-name) used an _Alignas specifier.
+ (c_parser_postfix_expression_after_paren_type): Check specified
+ alignment for a compound literal and pass it to
+ build_compound_literal.
+ * c-parser.h (c_parser_type_name): Update prototype.
+ * c-tree.h (build_compound_literal): Update prototype.
+
2017-12-07 Martin Sebor <msebor@redhat.com>
PR c/81544
literal, which may be an incomplete array type completed by the
initializer; INIT is a CONSTRUCTOR at LOC that initializes the compound
literal. NON_CONST is true if the initializers contain something
- that cannot occur in a constant expression. */
+ that cannot occur in a constant expression. If ALIGNAS_ALIGN is nonzero,
+ it is the (valid) alignment for this compound literal, as specified
+ with _Alignas. */
tree
-build_compound_literal (location_t loc, tree type, tree init, bool non_const)
+build_compound_literal (location_t loc, tree type, tree init, bool non_const,
+ unsigned int alignas_align)
{
/* We do not use start_decl here because we have a type, not a declarator;
and do not use finish_decl because the decl should be stored inside
DECL_IGNORED_P (decl) = 1;
TREE_TYPE (decl) = type;
c_apply_type_quals_to_decl (TYPE_QUALS (strip_array_types (type)), decl);
+ if (alignas_align)
+ {
+ SET_DECL_ALIGN (decl, alignas_align * BITS_PER_UNIT);
+ DECL_USER_ALIGN (decl) = 1;
+ }
store_init_value (loc, decl, init, NULL_TREE);
if (TREE_CODE (type) == ARRAY_TYPE && !COMPLETE_TYPE_P (type))
case RID_ACCUM:
case RID_SAT:
case RID_AUTO_TYPE:
+ case RID_ALIGNAS:
return true;
default:
if (keyword >= RID_FIRST_INT_N
has simply forgotten a semicolon, so we exit. */
if ((!typespec_ok || specs->typespec_kind == ctsk_tagdef)
&& c_parser_next_tokens_start_typename (parser, la)
- && !c_parser_next_token_is_qualifier (parser))
+ && !c_parser_next_token_is_qualifier (parser)
+ && !c_parser_next_token_is_keyword (parser, RID_ALIGNAS))
break;
if (c_parser_next_token_is (parser, CPP_NAME))
specifier-qualifier-list:
type-specifier specifier-qualifier-list[opt]
type-qualifier specifier-qualifier-list[opt]
+ alignment-specifier specifier-qualifier-list[opt]
attributes specifier-qualifier-list[opt]
struct-declarator-list:
return attrs;
}
-/* Parse a type name (C90 6.5.5, C99 6.7.6, C11 6.7.7).
+/* Parse a type name (C90 6.5.5, C99 6.7.6, C11 6.7.7). ALIGNAS_OK
+ says whether alignment specifiers are OK (only in cases that might
+ be the type name of a compound literal).
type-name:
specifier-qualifier-list abstract-declarator[opt]
*/
struct c_type_name *
-c_parser_type_name (c_parser *parser)
+c_parser_type_name (c_parser *parser, bool alignas_ok)
{
struct c_declspecs *specs = build_null_declspecs ();
struct c_declarator *declarator;
struct c_type_name *ret;
bool dummy = false;
- c_parser_declspecs (parser, specs, false, true, true, false, false,
+ c_parser_declspecs (parser, specs, false, true, true, alignas_ok, false,
cla_prefer_type);
if (!specs->declspecs_seen_p)
{
struct c_expr expr;
matching_parens parens;
parens.consume_open (parser);
- type_name = c_parser_type_name (parser);
+ type_name = c_parser_type_name (parser, true);
parens.skip_until_found_close (parser);
if (type_name == NULL)
{
if (c_parser_next_token_is (parser, CPP_OPEN_BRACE))
return c_parser_postfix_expression_after_paren_type (parser, type_name,
cast_loc);
+ if (type_name->specs->alignas_p)
+ error_at (type_name->specs->locations[cdw_alignas],
+ "alignment specified for type name in cast");
{
location_t expr_loc = c_parser_peek_token (parser)->location;
expr = c_parser_cast_expression (parser, NULL);
matching_parens parens;
parens.consume_open (parser);
expr_loc = c_parser_peek_token (parser)->location;
- type_name = c_parser_type_name (parser);
+ type_name = c_parser_type_name (parser, true);
parens.skip_until_found_close (parser);
finish = parser->tokens_buf[0].location;
if (type_name == NULL)
goto sizeof_expr;
}
/* sizeof ( type-name ). */
+ if (type_name->specs->alignas_p)
+ error_at (type_name->specs->locations[cdw_alignas],
+ "alignment specified for type name in %<sizeof%>");
c_inhibit_evaluation_warnings--;
in_sizeof--;
result = c_expr_sizeof_type (expr_loc, type_name);
matching_parens parens;
parens.consume_open (parser);
loc = c_parser_peek_token (parser)->location;
- type_name = c_parser_type_name (parser);
+ type_name = c_parser_type_name (parser, true);
end_loc = c_parser_peek_token (parser)->location;
parens.skip_until_found_close (parser);
if (type_name == NULL)
goto alignof_expr;
}
/* alignof ( type-name ). */
+ if (type_name->specs->alignas_p)
+ error_at (type_name->specs->locations[cdw_alignas],
+ "alignment specified for type name in %qE",
+ alignof_spelling);
c_inhibit_evaluation_warnings--;
in_alignof--;
ret.value = c_sizeof_or_alignof_type (loc, groktypename (type_name,
? CONSTRUCTOR_NON_CONST (init.value)
: init.original_code == C_MAYBE_CONST_EXPR);
non_const |= !type_expr_const;
- expr.value = build_compound_literal (start_loc, type, init.value, non_const);
+ unsigned int alignas_align = 0;
+ if (type != error_mark_node
+ && type_name->specs->align_log != -1)
+ {
+ alignas_align = 1U << type_name->specs->align_log;
+ if (alignas_align < min_align_of_type (type))
+ {
+ error_at (type_name->specs->locations[cdw_alignas],
+ "%<_Alignas%> specifiers cannot reduce "
+ "alignment of compound literal");
+ alignas_align = 0;
+ }
+ }
+ expr.value = build_compound_literal (start_loc, type, init.value, non_const,
+ alignas_align);
set_c_expr_source_range (&expr, init.src_range);
expr.original_code = ERROR_MARK;
expr.original_type = NULL;
bool *seen_id);
extern void c_parser_declspecs (c_parser *, struct c_declspecs *, bool, bool,
bool, bool, bool, enum c_lookahead_kind);
-extern struct c_type_name *c_parser_type_name (c_parser *);
+extern struct c_type_name *c_parser_type_name (c_parser *, bool = false);
#endif
extern void set_init_label (location_t, tree, location_t, struct obstack *);
extern void process_init_element (location_t, struct c_expr, bool,
struct obstack *);
-extern tree build_compound_literal (location_t, tree, tree, bool);
+extern tree build_compound_literal (location_t, tree, tree, bool,
+ unsigned int);
extern void check_compound_literal_type (location_t, struct c_type_name *);
extern tree c_start_case (location_t, location_t, tree, bool);
extern void c_finish_case (tree, tree);
+2017-12-07 Joseph Myers <joseph@codesourcery.com>
+
+ * gcc.dg/c11-align-7.c, gcc.dg/c11-align-8.c,
+ gcc.dg/c11-align-9.c, gcc.dg/gnu11-align-1.c: New tests.
+ * gcc.dg/c11-align-5.c (test): Update expected error for sizeof
+ case.
+
2017-12-07 Richard Sandiford <richard.sandiford@linaro.org>
* gcc.target/aarch64/asm-2.c: New test.
struct s { int n; };
__builtin_offsetof (struct s _Alignas (int), n); /* { dg-error "expected" } */
__typeof (long double _Alignas (0)) e; /* { dg-error "expected" } */
- sizeof (int _Alignas (int)); /* { dg-error "expected" } */
+ sizeof (int _Alignas (int)); /* { dg-error "specified for type name" } */
_Alignas (int _Alignas (float)) int t; /* { dg-error "expected" } */
__builtin_types_compatible_p (signed _Alignas (0), unsigned); /* { dg-error "expected" } */
int a[_Alignas (int) 10]; /* { dg-error "expected expression before" } */
--- /dev/null
+/* Test C11 alignment support. Test code valid after the resolution
+ of DR#444: alignment specifiers for struct and union members and
+ compound literals. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stddef.h>
+
+struct s
+{
+ _Alignas (_Alignof (max_align_t)) char c;
+};
+
+union u
+{
+ _Alignas (_Alignof (max_align_t)) char c;
+};
+
+char *p = &(_Alignas (_Alignof (max_align_t)) char) { 1 };
+size_t size = sizeof (_Alignas (_Alignof (max_align_t)) char) { 1 };
--- /dev/null
+/* Test C11 alignment support. Test invalid use of alignment
+ specifiers in type names in cases not permitted by the resolution
+ of DR#444. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+
+#include <stddef.h>
+
+void
+f (void)
+{
+ _Generic (1, int: 1, _Alignas (8) long: 2); /* { dg-error "expected" } */
+ sizeof (_Alignas (8) long); /* { dg-error "specified for type name" } */
+ _Alignof (_Alignas (8) long); /* { dg-error "specified for type name" } */
+ (_Alignas (8) long) 0; /* { dg-error "specified for type name" } */
+ _Atomic (_Alignas (8) long) x; /* { dg-error "expected" } */
+ _Alignas (_Alignas (8) long) long y; /* { dg-error "expected" } */
+}
--- /dev/null
+/* Test C11 alignment support. Test reducing alignment (assumes there
+ are at least some alignment constraints), case of compound literals. */
+/* { dg-do compile } */
+/* { dg-options "-std=c11 -pedantic-errors" } */
+/* { dg-skip-if "no alignment constraints" { "avr-*-*" } } */
+
+#include <stddef.h>
+
+max_align_t *p = &(_Alignas (_Alignof (char)) max_align_t) { 1 }; /* { dg-error "reduce alignment" } */
--- /dev/null
+/* Test C11 alignment support. Test code valid after the resolution
+ of DR#444: alignment specifiers for compound literals in _Alignof. */
+/* { dg-do compile } */
+/* { dg-options "-std=gnu11" } */
+
+#include <stddef.h>
+
+size_t align = _Alignof (_Alignas (_Alignof (max_align_t)) char) { 1 };