aboutsummaryrefslogtreecommitdiff
path: root/gcc/c/c-parser.c
diff options
context:
space:
mode:
authorJoseph Myers <joseph@codesourcery.com>2019-11-15 23:22:41 +0000
committerJoseph Myers <jsm28@gcc.gnu.org>2019-11-15 23:22:41 +0000
commitd5fbe5e014bc9fc803604eec805392c21ff4da16 (patch)
tree5a5b4f07e9d4923388a279c438f4ea282c9f6ead /gcc/c/c-parser.c
parent2ab340fe17e7b5021c980badab9f5318d1517646 (diff)
downloadgcc-d5fbe5e014bc9fc803604eec805392c21ff4da16.zip
gcc-d5fbe5e014bc9fc803604eec805392c21ff4da16.tar.gz
gcc-d5fbe5e014bc9fc803604eec805392c21ff4da16.tar.bz2
Diagnose duplicate C2x standard attributes.
For each of the attributes currently included in C2x, it has a constraint that the attribute shall appear at most once in each attribute list (attribute-list being what appear between a single [[ and ]]). This patch implements that check. As the corresponding check in the C++ front end (cp_parser_check_std_attribute) makes violations into errors, I made them into errors, with the same wording, for C as well. There is an existing check in the case of the fallthrough attribute, with a warning rather than an error, in attribute_fallthrough_p. That is more general, as it also covers __attribute__ ((fallthrough)) and the case of [[fallthrough]] [[fallthrough]] (multiple attribute-lists in a single attribute-specifier-sequence), which is not a constraint violation. To avoid some [[fallthrough, fallthrough]] being diagnosed twice, the check I added avoids adding duplicate attributes to the list. Bootstrapped with no regressions on x86_64-pc-linux-gnu. gcc/c: * c-parser.c (c_parser_std_attribute_specifier): Diagnose duplicate standard attributes. gcc/testsuite: * gcc.dg/c2x-attr-deprecated-4.c, gcc.dg/c2x-attr-fallthrough-4.c, gcc.dg/c2x-attr-maybe_unused-4.c: New tests. From-SVN: r278324
Diffstat (limited to 'gcc/c/c-parser.c')
-rw-r--r--gcc/c/c-parser.c54
1 files changed, 52 insertions, 2 deletions
diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c
index 5b290bf..e48760d 100644
--- a/gcc/c/c-parser.c
+++ b/gcc/c/c-parser.c
@@ -4873,6 +4873,9 @@ c_parser_std_attribute (c_parser *parser)
static tree
c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
{
+ bool seen_deprecated = false;
+ bool seen_fallthrough = false;
+ bool seen_maybe_unused = false;
location_t loc = c_parser_peek_token (parser)->location;
if (!c_parser_require (parser, CPP_OPEN_SQUARE, "expected %<[%>"))
return NULL_TREE;
@@ -4898,8 +4901,55 @@ c_parser_std_attribute_specifier (c_parser *parser, bool for_tm)
tree attribute = c_parser_std_attribute (parser);
if (attribute != error_mark_node)
{
- TREE_CHAIN (attribute) = attributes;
- attributes = attribute;
+ bool duplicate = false;
+ tree name = get_attribute_name (attribute);
+ tree ns = get_attribute_namespace (attribute);
+ if (ns == NULL_TREE)
+ {
+ /* Some standard attributes may appear at most once in
+ each attribute list. Diagnose duplicates and remove
+ them from the list to avoid subsequent diagnostics
+ such as the more general one for multiple
+ "fallthrough" attributes in the same place (including
+ in separate attribute lists in the same attribute
+ specifier sequence, which is not a constraint
+ violation). */
+ if (is_attribute_p ("deprecated", name))
+ {
+ if (seen_deprecated)
+ {
+ error ("attribute %<deprecated%> can appear at most "
+ "once in an attribute-list");
+ duplicate = true;
+ }
+ seen_deprecated = true;
+ }
+ else if (is_attribute_p ("fallthrough", name))
+ {
+ if (seen_fallthrough)
+ {
+ error ("attribute %<fallthrough%> can appear at most "
+ "once in an attribute-list");
+ duplicate = true;
+ }
+ seen_fallthrough = true;
+ }
+ else if (is_attribute_p ("maybe_unused", name))
+ {
+ if (seen_maybe_unused)
+ {
+ error ("attribute %<maybe_unused%> can appear at most "
+ "once in an attribute-list");
+ duplicate = true;
+ }
+ seen_maybe_unused = true;
+ }
+ }
+ if (!duplicate)
+ {
+ TREE_CHAIN (attribute) = attributes;
+ attributes = attribute;
+ }
}
if (c_parser_next_token_is_not (parser, CPP_COMMA))
break;