2
0
mirror of git://gcc.gnu.org/git/gcc.git synced 2025-04-10 01:40:47 +08:00

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
This commit is contained in:
Joseph Myers 2019-11-15 23:22:41 +00:00 committed by Joseph Myers
parent 2ab340fe17
commit d5fbe5e014
6 changed files with 111 additions and 2 deletions

@ -1,3 +1,8 @@
2019-11-15 Joseph Myers <joseph@codesourcery.com>
* c-parser.c (c_parser_std_attribute_specifier): Diagnose
duplicate standard attributes.
2019-11-15 Joseph Myers <joseph@codesourcery.com>
* c-decl.c (std_attribute_table): Add maybe_unused.

@ -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;

@ -1,3 +1,8 @@
2019-11-15 Joseph Myers <joseph@codesourcery.com>
* gcc.dg/c2x-attr-deprecated-4.c, gcc.dg/c2x-attr-fallthrough-4.c,
gcc.dg/c2x-attr-maybe_unused-4.c: New tests.
2019-11-15 Paolo Carlini <paolo.carlini@oracle.com>
* g++.dg/warn/Walways-true-1.C: Check locations too.

@ -0,0 +1,13 @@
/* Test C2x deprecated attribute: duplicates. */
/* { dg-do compile } */
/* { dg-options "-std=c2x -pedantic-errors" } */
[[deprecated, __deprecated__]] int a; /* { dg-error "can appear at most once" } */
[[__deprecated__, deprecated("message")]] int b; /* { dg-error "can appear at most once" } */
int c [[deprecated("message"), deprecated]]; /* { dg-error "can appear at most once" } */
[[deprecated, deprecated]]; /* { dg-error "can appear at most once" } */
/* { dg-warning "ignored" "ignored" { target *-*-* } .-1 } */
/* Separate attribute lists in the same attribute specifier sequence,
with the same attribute in them, are OK. */
[[deprecated]] [[deprecated]] int d [[deprecated]] [[deprecated]];

@ -0,0 +1,23 @@
/* Test C2x fallthrough attribute: duplicates. */
/* { dg-do compile } */
/* { dg-options "-std=c2x -pedantic-errors" } */
int
f (int a)
{
switch (a)
{
case 1:
a++;
[[fallthrough, __fallthrough__]]; /* { dg-error "can appear at most once" } */
case 2:
a++;
/* Separate attribute lists in the same attribute specifier
sequence, with the same attribute in them, are OK (but
receive a warning). */
[[fallthrough]] [[fallthrough]]; /* { dg-warning "specified multiple times" } */
case 3:
a++;
}
return a;
}

@ -0,0 +1,13 @@
/* Test C2x maybe_unused attribute: duplicates. */
/* { dg-do compile } */
/* { dg-options "-std=c2x -pedantic-errors" } */
[[maybe_unused, __maybe_unused__]] int a; /* { dg-error "can appear at most once" } */
[[__maybe_unused__, maybe_unused]] int b; /* { dg-error "can appear at most once" } */
int c [[maybe_unused, maybe_unused]]; /* { dg-error "can appear at most once" } */
[[maybe_unused, maybe_unused]]; /* { dg-error "can appear at most once" } */
/* { dg-warning "ignored" "ignored" { target *-*-* } .-1 } */
/* Separate attribute lists in the same attribute specifier sequence,
with the same attribute in them, are OK. */
[[maybe_unused]] [[maybe_unused]] int d [[maybe_unused]] [[maybe_unused]];