From: Joseph Myers Date: Fri, 15 Nov 2019 23:22:41 +0000 (+0000) Subject: Diagnose duplicate C2x standard attributes. X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d5fbe5e014bc9fc803604eec805392c21ff4da16;p=gcc.git 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 --- diff --git a/gcc/c/ChangeLog b/gcc/c/ChangeLog index 75a44e28927..0076e836888 100644 --- a/gcc/c/ChangeLog +++ b/gcc/c/ChangeLog @@ -1,3 +1,8 @@ +2019-11-15 Joseph Myers + + * c-parser.c (c_parser_std_attribute_specifier): Diagnose + duplicate standard attributes. + 2019-11-15 Joseph Myers * c-decl.c (std_attribute_table): Add maybe_unused. diff --git a/gcc/c/c-parser.c b/gcc/c/c-parser.c index 5b290bf7567..e48760dfd63 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 % 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 % 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 % 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; diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index 997096cf1d6..4376337e333 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-11-15 Joseph Myers + + * 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 * g++.dg/warn/Walways-true-1.C: Check locations too. diff --git a/gcc/testsuite/gcc.dg/c2x-attr-deprecated-4.c b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-4.c new file mode 100644 index 00000000000..ce6615b4ba1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-attr-deprecated-4.c @@ -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]]; diff --git a/gcc/testsuite/gcc.dg/c2x-attr-fallthrough-4.c b/gcc/testsuite/gcc.dg/c2x-attr-fallthrough-4.c new file mode 100644 index 00000000000..75aceff9941 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-attr-fallthrough-4.c @@ -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; +} diff --git a/gcc/testsuite/gcc.dg/c2x-attr-maybe_unused-4.c b/gcc/testsuite/gcc.dg/c2x-attr-maybe_unused-4.c new file mode 100644 index 00000000000..ae7e1dcd0b7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/c2x-attr-maybe_unused-4.c @@ -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]];