aboutsummaryrefslogtreecommitdiff
path: root/gcc/c/c-parser.c
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/c/c-parser.c')
-rw-r--r--gcc/c/c-parser.c45
1 files changed, 37 insertions, 8 deletions
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index e9267fe..d398548 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -504,6 +504,7 @@ c_keyword_starts_typename (enum rid keyword)
case RID_ACCUM:
case RID_SAT:
case RID_AUTO_TYPE:
+ case RID_ALIGNAS:
return true;
default:
if (keyword >= RID_FIRST_INT_N
@@ -2594,7 +2595,8 @@ c_parser_declspecs (c_parser *parser, struct c_declspecs *specs,
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))
@@ -3225,6 +3227,7 @@ c_parser_struct_or_union_specifier (c_parser *parser)
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:
@@ -4410,20 +4413,22 @@ c_parser_attributes (c_parser *parser)
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)
{
@@ -7019,7 +7024,7 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
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)
{
@@ -7035,6 +7040,9 @@ c_parser_cast_expression (c_parser *parser, struct c_expr *after)
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);
@@ -7238,7 +7246,7 @@ c_parser_sizeof_expression (c_parser *parser)
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)
@@ -7260,6 +7268,9 @@ c_parser_sizeof_expression (c_parser *parser)
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);
@@ -7321,7 +7332,7 @@ c_parser_alignof_expression (c_parser *parser)
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)
@@ -7342,6 +7353,10 @@ c_parser_alignof_expression (c_parser *parser)
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,
@@ -8969,7 +8984,21 @@ c_parser_postfix_expression_after_paren_type (c_parser *parser,
? 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;