diff options
author | Joseph Myers <joseph@codesourcery.com> | 2019-11-15 23:22:41 +0000 |
---|---|---|
committer | Joseph Myers <jsm28@gcc.gnu.org> | 2019-11-15 23:22:41 +0000 |
commit | d5fbe5e014bc9fc803604eec805392c21ff4da16 (patch) | |
tree | 5a5b4f07e9d4923388a279c438f4ea282c9f6ead /gcc/c/c-parser.c | |
parent | 2ab340fe17e7b5021c980badab9f5318d1517646 (diff) | |
download | gcc-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.c | 54 |
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; |