diff options
Diffstat (limited to '0232-Backport-SME-c-Add-support-for-__extension__.patch')
-rw-r--r-- | 0232-Backport-SME-c-Add-support-for-__extension__.patch | 327 |
1 files changed, 327 insertions, 0 deletions
diff --git a/0232-Backport-SME-c-Add-support-for-__extension__.patch b/0232-Backport-SME-c-Add-support-for-__extension__.patch new file mode 100644 index 0000000..5ba9828 --- /dev/null +++ b/0232-Backport-SME-c-Add-support-for-__extension__.patch @@ -0,0 +1,327 @@ +From 3714cfb47fafef884aa2ff330935fb44b7966909 Mon Sep 17 00:00:00 2001 +From: Richard Sandiford <richard.sandiford@arm.com> +Date: Thu, 24 Aug 2023 11:49:58 +0100 +Subject: [PATCH 133/157] [Backport][SME] c: Add support for [[__extension__ + ...]] + +Reference: https://gcc.gnu.org/git/?p=gcc.git;a=commit;h=207a5daa9dcf31e367152163ad2a2ab4a0858967 + +[[]] attributes are a recent addition to C, but as a GNU extension, +GCC allows them to be used in C11 and earlier. Normally this use +would trigger a pedwarn (for -pedantic, -Wc11-c2x-compat, etc.). + +This patch allows the pedwarn to be suppressed by starting the +attribute-list with __extension__. + +Also, :: is not a single lexing token prior to C2X, so it wasn't +possible to use scoped attributes in C11, even as a GNU extension. +The patch allows two colons to be used in place of :: when +__extension__ is used. No attempt is made to check whether the +two colons are immediately adjacent. + +gcc/ + * doc/extend.texi: Document the C [[__extension__ ...]] construct. + +gcc/c/ + * c-parser.cc (c_parser_std_attribute): Conditionally allow + two colons to be used in place of ::. + (c_parser_std_attribute_list): New function, split out from... + (c_parser_std_attribute_specifier): ...here. Allow the attribute-list + to start with __extension__. When it does, also allow two colons + to be used in place of ::. + +gcc/testsuite/ + * gcc.dg/c2x-attr-syntax-6.c: New test. + * gcc.dg/c2x-attr-syntax-7.c: Likewise. +--- + gcc/c/c-parser.cc | 64 ++++++++++++++++++------ + gcc/doc/extend.texi | 27 ++++++++-- + gcc/testsuite/gcc.dg/c2x-attr-syntax-6.c | 62 +++++++++++++++++++++++ + gcc/testsuite/gcc.dg/c2x-attr-syntax-7.c | 60 ++++++++++++++++++++++ + 4 files changed, 193 insertions(+), 20 deletions(-) + create mode 100644 gcc/testsuite/gcc.dg/c2x-attr-syntax-6.c + create mode 100644 gcc/testsuite/gcc.dg/c2x-attr-syntax-7.c + +diff --git a/gcc/c/c-parser.cc b/gcc/c/c-parser.cc +index 78a313fe3..486f46e1c 100644 +--- a/gcc/c/c-parser.cc ++++ b/gcc/c/c-parser.cc +@@ -4894,10 +4894,18 @@ c_parser_balanced_token_sequence (c_parser *parser) + ( balanced-token-sequence[opt] ) + + Keywords are accepted as identifiers for this purpose. +-*/ ++ ++ As an extension, we permit an attribute-specifier to be: ++ ++ [ [ __extension__ attribute-list ] ] ++ ++ Two colons are then accepted as a synonym for ::. No attempt is made ++ to check whether the colons are immediately adjacent. LOOSE_SCOPE_P ++ indicates whether this relaxation is in effect. */ + + static tree +-c_parser_std_attribute (c_parser *parser, bool for_tm) ++c_parser_std_attribute (c_parser *parser, bool for_tm, ++ bool loose_scope_p = false) + { + c_token *token = c_parser_peek_token (parser); + tree ns, name, attribute; +@@ -4910,9 +4918,14 @@ c_parser_std_attribute (c_parser *parser, bool for_tm) + } + name = canonicalize_attr_name (token->value); + c_parser_consume_token (parser); +- if (c_parser_next_token_is (parser, CPP_SCOPE)) ++ if (c_parser_next_token_is (parser, CPP_SCOPE) ++ || (loose_scope_p ++ && c_parser_next_token_is (parser, CPP_COLON) ++ && c_parser_peek_2nd_token (parser)->type == CPP_COLON)) + { + ns = name; ++ if (c_parser_next_token_is (parser, CPP_COLON)) ++ c_parser_consume_token (parser); + c_parser_consume_token (parser); + token = c_parser_peek_token (parser); + if (token->type != CPP_NAME && token->type != CPP_KEYWORD) +@@ -4981,19 +4994,9 @@ c_parser_std_attribute (c_parser *parser, bool for_tm) + } + + static tree +-c_parser_std_attribute_specifier (c_parser *parser, bool for_tm) ++c_parser_std_attribute_list (c_parser *parser, bool for_tm, ++ bool loose_scope_p = false) + { +- location_t loc = c_parser_peek_token (parser)->location; +- if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>")) +- return NULL_TREE; +- if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>")) +- { +- c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>"); +- return NULL_TREE; +- } +- if (!for_tm) +- pedwarn_c11 (loc, OPT_Wpedantic, +- "ISO C does not support %<[[]]%> attributes before C2X"); + tree attributes = NULL_TREE; + while (true) + { +@@ -5005,7 +5008,7 @@ c_parser_std_attribute_specifier (c_parser *parser, bool for_tm) + c_parser_consume_token (parser); + continue; + } +- tree attribute = c_parser_std_attribute (parser, for_tm); ++ tree attribute = c_parser_std_attribute (parser, for_tm, loose_scope_p); + if (attribute != error_mark_node) + { + TREE_CHAIN (attribute) = attributes; +@@ -5014,6 +5017,35 @@ c_parser_std_attribute_specifier (c_parser *parser, bool for_tm) + if (c_parser_next_token_is_not (parser, CPP_COMMA)) + break; + } ++ return attributes; ++} ++ ++static tree ++c_parser_std_attribute_specifier (c_parser *parser, bool for_tm) ++{ ++ location_t loc = c_parser_peek_token (parser)->location; ++ if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>")) ++ return NULL_TREE; ++ if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>")) ++ { ++ c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>"); ++ return NULL_TREE; ++ } ++ tree attributes; ++ if (c_parser_next_token_is_keyword (parser, RID_EXTENSION)) ++ { ++ auto ext = disable_extension_diagnostics (); ++ c_parser_consume_token (parser); ++ attributes = c_parser_std_attribute_list (parser, for_tm, true); ++ restore_extension_diagnostics (ext); ++ } ++ else ++ { ++ if (!for_tm) ++ pedwarn_c11 (loc, OPT_Wpedantic, ++ "ISO C does not support %<[[]]%> attributes before C2X"); ++ attributes = c_parser_std_attribute_list (parser, for_tm); ++ } + c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>"); + c_parser_skip_until_found (parser, CPP_CLOSE_SQUARE, "expected %<]%>"); + return nreverse (attributes); +diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi +index 674db2f1a..3cfecee53 100644 +--- a/gcc/doc/extend.texi ++++ b/gcc/doc/extend.texi +@@ -11726,10 +11726,29 @@ macros to replace them with the customary keywords. It looks like this: + @findex __extension__ + @opindex pedantic + @option{-pedantic} and other options cause warnings for many GNU C extensions. +-You can +-prevent such warnings within one expression by writing +-@code{__extension__} before the expression. @code{__extension__} has no +-effect aside from this. ++You can suppress such warnings using the keyword @code{__extension__}. ++Specifically: ++ ++@itemize @bullet ++@item ++Writing @code{__extension__} before an expression prevents warnings ++about extensions within that expression. ++ ++@item ++In C, writing: ++ ++@smallexample ++[[__extension__ @dots{}]] ++@end smallexample ++ ++suppresses warnings about using @samp{[[]]} attributes in C versions ++that predate C2X@. Since the scope token @samp{::} is not a single ++lexing token in earlier versions of C, this construct also allows two colons ++to be used in place of @code{::}. GCC does not check whether the two ++colons are immediately adjacent. ++@end itemize ++ ++@code{__extension__} has no effect aside from this. + + @node Incomplete Enums + @section Incomplete @code{enum} Types +diff --git a/gcc/testsuite/gcc.dg/c2x-attr-syntax-6.c b/gcc/testsuite/gcc.dg/c2x-attr-syntax-6.c +new file mode 100644 +index 000000000..9e5f65ce4 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/c2x-attr-syntax-6.c +@@ -0,0 +1,62 @@ ++/* Test C2x attribute syntax: use of __extension__ in C11 mode. */ ++/* { dg-do compile } */ ++/* { dg-options "-std=c11 -pedantic-errors" } */ ++ ++#define FOO :: ++#define BAR : ++#define JOIN(A, B) A/**/B ++#define JOIN2(A, B) A##B ++ ++typedef int [[__extension__ gnu::vector_size (4)]] g1; ++typedef int [[__extension__ gnu :: vector_size (4)]] g2; ++typedef int [[__extension__ gnu : : vector_size (4)]] g3; ++typedef int [[__extension__ gnu: :vector_size (4)]] g4; ++typedef int [[__extension__ gnu FOO vector_size (4)]] g5; ++typedef int [[__extension__ gnu BAR BAR vector_size (4)]] g6; ++typedef int [[__extension__ gnu :/**/: vector_size (4)]] g7; ++typedef int [[__extension__ gnu JOIN(:,:) vector_size (4)]] g8; ++typedef int [[__extension__ gnu :: vector_size (sizeof (void (*)(...)))]] g10; ++typedef int [[__extension__]] g11; ++typedef int [[__extension__,]] g12; ++typedef int [[__extension__, ,,,, ,, ,]] g13; ++[[__extension__ deprecated]] int g14 (); ++[[__extension__ nodiscard]] int g15 (); ++[[__extension__ noreturn]] void g16 (); ++ ++int ++cases (int x) ++{ ++ switch (x) ++ { ++ case 1: ++ case 2: ++ case 4: ++ x += 1; ++ [[__extension__ fallthrough]]; ++ case 19: ++ case 33: ++ x *= 2; ++ [[fallthrough]]; /* { dg-error {attributes before C2X} } */ ++ case 99: ++ return x; ++ ++ default: ++ return 0; ++ } ++} ++ ++typedef int [[__extension__ vector_size (4)]] b1; /* { dg-error {'vector_size' attribute ignored} } */ ++typedef int [[__extension__ __extension__]] b2; /* { dg-error {'extension' attribute ignored} } */ ++typedef int [[__extension__ unknown_attribute]] b3; /* { dg-error {'unknown_attribute' attribute ignored} } */ ++typedef int [[__extension__ gnu:vector_size(4)]] b4; /* { dg-error {expected '\]' before ':'} } */ ++/* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-1 } */ ++typedef int [[__extension__ gnu JOIN2(:,:) vector_size (4)]] b5; /* { dg-error {pasting ":" and ":" does not give a valid preprocessing token} } */ ++typedef int [[gnu::vector_size(4)]] b6; /* { dg-error {expected '\]' before ':'} } */ ++/* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-1 } */ ++/* { dg-error {attributes before C2X} "" { target *-*-* } .-2 } */ ++typedef int [[gnu : : vector_size(4)]] b7; /* { dg-error {expected '\]' before ':'} } */ ++/* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-1 } */ ++/* { dg-error {attributes before C2X} "" { target *-*-* } .-2 } */ ++typedef int [[gnu : vector_size(4)]] b8; /* { dg-error {expected '\]' before ':'} } */ ++/* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-1 } */ ++/* { dg-error {attributes before C2X} "" { target *-*-* } .-2 } */ +diff --git a/gcc/testsuite/gcc.dg/c2x-attr-syntax-7.c b/gcc/testsuite/gcc.dg/c2x-attr-syntax-7.c +new file mode 100644 +index 000000000..702f733b1 +--- /dev/null ++++ b/gcc/testsuite/gcc.dg/c2x-attr-syntax-7.c +@@ -0,0 +1,60 @@ ++/* Test C2x attribute syntax: use of __extension__ in C11 mode. */ ++/* { dg-do compile } */ ++/* { dg-options "-std=c2x -pedantic-errors -Wc11-c2x-compat" } */ ++ ++#define FOO :: ++#define BAR : ++#define JOIN(A, B) A/**/B ++#define JOIN2(A, B) A##B ++ ++typedef int [[__extension__ gnu::vector_size (4)]] g1; ++typedef int [[__extension__ gnu :: vector_size (4)]] g2; ++typedef int [[__extension__ gnu : : vector_size (4)]] g3; ++typedef int [[__extension__ gnu: :vector_size (4)]] g4; ++typedef int [[__extension__ gnu FOO vector_size (4)]] g5; ++typedef int [[__extension__ gnu BAR BAR vector_size (4)]] g6; ++typedef int [[__extension__ gnu :/**/: vector_size (4)]] g7; ++typedef int [[__extension__ gnu JOIN(:,:) vector_size (4)]] g8; ++typedef int [[__extension__ gnu :: vector_size (sizeof (void (*)(...)))]] g10; ++typedef int [[__extension__]] g11; ++typedef int [[__extension__,]] g12; ++typedef int [[__extension__, ,,,, ,, ,]] g13; ++[[__extension__ deprecated]] int g14 (); ++[[__extension__ nodiscard]] int g15 (); ++[[__extension__ noreturn]] void g16 (); ++ ++int ++cases (int x) ++{ ++ switch (x) ++ { ++ case 1: ++ case 2: ++ case 4: ++ x += 1; ++ [[__extension__ fallthrough]]; ++ case 19: ++ case 33: ++ x *= 2; ++ [[fallthrough]]; /* { dg-warning {attributes before C2X} } */ ++ case 99: ++ return x; ++ ++ default: ++ return 0; ++ } ++} ++ ++typedef int [[__extension__ vector_size (4)]] b1; /* { dg-error {'vector_size' attribute ignored} } */ ++typedef int [[__extension__ __extension__]] b2; /* { dg-error {'extension' attribute ignored} } */ ++typedef int [[__extension__ unknown_attribute]] b3; /* { dg-error {'unknown_attribute' attribute ignored} } */ ++typedef int [[__extension__ gnu:vector_size(4)]] b4; /* { dg-error {expected '\]' before ':'} } */ ++/* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-1 } */ ++typedef int [[__extension__ gnu JOIN2(:,:) vector_size (4)]] b5; ++typedef int [[gnu::vector_size(4)]] b6; /* { dg-warning {attributes before C2X} } */ ++typedef int [[gnu : : vector_size(4)]] b7; /* { dg-error {expected '\]' before ':'} } */ ++/* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-1 } */ ++/* { dg-warning {attributes before C2X} "" { target *-*-* } .-2 } */ ++typedef int [[gnu : vector_size(4)]] b8; /* { dg-error {expected '\]' before ':'} } */ ++/* { dg-error {'gnu' attribute ignored} "" { target *-*-* } .-1 } */ ++/* { dg-warning {attributes before C2X} "" { target *-*-* } .-2 } */ +-- +2.33.0 + |