Bootstrapped/regtested on x86_64-pc-linux-gnu, ok for trunk?
gcc/c-family/ChangeLog:
DR 1914
* c-common.c (attribute_fallthrough_p): Update comment.
gcc/cp/ChangeLog:
DR 1914
* parser.c (cp_parser_check_std_attribute): Remove.
(cp_parser_std_attribute_list): Don't call it.
gcc/testsuite/ChangeLog:
DR 1914
* g++.dg/cpp0x/gen-attrs-60.C: Remove dg-error.
* g++.dg/cpp2a/nodiscard-once.C: Likewise.
* g++.dg/cpp1y/attr-deprecated-2.C: Likewise.
* g++.dg/cpp0x/gen-attrs-72.C: New test.
---
gcc/c-family/c-common.c | 3 +-
gcc/cp/parser.c | 27 ------------
gcc/testsuite/g++.dg/cpp0x/gen-attrs-60.C | 2 +-
gcc/testsuite/g++.dg/cpp0x/gen-attrs-72.C | 42 +++++++++++++++++++
.../g++.dg/cpp1y/attr-deprecated-2.C | 2 +-
gcc/testsuite/g++.dg/cpp2a/nodiscard-once.C | 2 +-
6 files changed, 47 insertions(+), 31 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-72.C
diff --git a/gcc/c-family/c-common.c b/gcc/c-family/c-common.c
index 232a4797c09..03d8fec9936 100644
--- a/gcc/c-family/c-common.c
+++ b/gcc/c-family/c-common.c
@@ -5751,7 +5751,8 @@ attribute_fallthrough_p (tree attr)
tree t = lookup_attribute ("fallthrough", attr);
if (t == NULL_TREE)
return false;
- /* This attribute shall appear at most once in each attribute-list. */
+ /* It is no longer true that "this attribute shall appear at most once in
+ each attribute-list", but we still give a warning. */
if (lookup_attribute ("fallthrough", TREE_CHAIN (t)))
warning (OPT_Wattributes, "%<fallthrough%> attribute specified multiple "
"times");
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 6e7b982f073..0567646fbe2 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -27269,32 +27269,6 @@ cp_parser_std_attribute (cp_parser *parser, tree
attr_ns)
return attribute;
}
-/* Check that the attribute ATTRIBUTE appears at most once in the
- attribute-list ATTRIBUTES. This is enforced for noreturn (7.6.3),
- nodiscard, and deprecated (7.6.5). Note that
- carries_dependency (7.6.4) isn't implemented yet in GCC. */
-
-static void
-cp_parser_check_std_attribute (tree attributes, tree attribute)
-{
- if (attributes)
- {
- tree name = get_attribute_name (attribute);
- if (is_attribute_p ("noreturn", name)
- && lookup_attribute ("noreturn", attributes))
- error ("attribute %<noreturn%> can appear at most once "
- "in an attribute-list");
- else if (is_attribute_p ("deprecated", name)
- && lookup_attribute ("deprecated", attributes))
- error ("attribute %<deprecated%> can appear at most once "
- "in an attribute-list");
- else if (is_attribute_p ("nodiscard", name)
- && lookup_attribute ("nodiscard", attributes))
- error ("attribute %<nodiscard%> can appear at most once "
- "in an attribute-list");
- }
-}
-
/* Parse a list of standard C++-11 attributes.
attribute-list:
@@ -27317,7 +27291,6 @@ cp_parser_std_attribute_list (cp_parser *parser, tree
attr_ns)
break;
if (attribute != NULL_TREE)
{
- cp_parser_check_std_attribute (attributes, attribute);
TREE_CHAIN (attribute) = attributes;
attributes = attribute;
}
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-60.C
b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-60.C
index cb0c31ec63f..4e905c394ca 100644
--- a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-60.C
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-60.C
@@ -1,4 +1,4 @@
// PR c++/60365
// { dg-do compile { target c++11 } }
-void func [[noreturn, noreturn]] (); // { dg-error "at most once" }
+void func [[noreturn, noreturn]] ();
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-72.C
b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-72.C
new file mode 100644
index 00000000000..0cb874b6191
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-72.C
@@ -0,0 +1,42 @@
+// DR 1914 - Duplicate standard attributes
+// { dg-do compile { target c++11 } }
+
+[[noreturn, noreturn]] void fn0();
+[[noreturn]] [[noreturn]] void fn1();
+[[deprecated, deprecated]] void fn2();
+[[deprecated]] [[deprecated]] void fn3();
+[[maybe_unused]] [[maybe_unused]] int fn4();
+[[maybe_unused, maybe_unused]] int fn5();
+[[nodiscard]] [[nodiscard]] int fn6();
+[[nodiscard, nodiscard]] int fn7();
+
+struct E { };
+struct A {
+ [[no_unique_address]] [[no_unique_address]] E e;
+};
+struct B {
+ [[no_unique_address, no_unique_address]] E e;
+};
+
+int
+f (int n)
+{
+ switch (n)
+ {
+ case 1:
+ [[fallthrough, fallthrough]]; // { dg-warning "attribute specified multiple
times" }
+ case 2:
+ [[fallthrough]] [[fallthrough]]; // { dg-warning "attribute specified
multiple times" }
+ case 3:
+ return 15;
+ }
+
+ if (n == 10)
+ [[likely]] [[likely]] return 42; // { dg-warning "ignoring attribute" }
+ else if (n == 11)
+ [[unlikely]] [[unlikely]] return 10; // { dg-warning "ignoring attribute" }
+ else if (n == 12)
+ [[likely, likely]] return 42; // { dg-warning "ignoring attribute" }
+ else
+ [[unlikely, unlikely]] return 0; // { dg-warning "ignoring attribute" }
+}
diff --git a/gcc/testsuite/g++.dg/cpp1y/attr-deprecated-2.C
b/gcc/testsuite/g++.dg/cpp1y/attr-deprecated-2.C
index 12c75c7ba73..1669bbf5376 100644
--- a/gcc/testsuite/g++.dg/cpp1y/attr-deprecated-2.C
+++ b/gcc/testsuite/g++.dg/cpp1y/attr-deprecated-2.C
@@ -1,4 +1,4 @@
// PR c++/60365
// { dg-do compile { target c++14 } }
-void func [[deprecated, deprecated]] (); // { dg-error "at most once" }
+void func [[deprecated, deprecated]] ();
diff --git a/gcc/testsuite/g++.dg/cpp2a/nodiscard-once.C
b/gcc/testsuite/g++.dg/cpp2a/nodiscard-once.C
index c810fd0daad..da992f9f0c7 100644
--- a/gcc/testsuite/g++.dg/cpp2a/nodiscard-once.C
+++ b/gcc/testsuite/g++.dg/cpp2a/nodiscard-once.C
@@ -2,7 +2,7 @@
/* { dg-do compile { target c++20 } } */
/* { dg-options "-O -ftrack-macro-expansion=0" } */
-[[nodiscard, nodiscard]] int check1 (void); /* { dg-error "nodiscard\[^\n\r]*can appear at most once" } */
+[[nodiscard, nodiscard]] int check1 (void);
void
test (void)
base-commit: 05f1883cfd041adba5f595e97118100b6e00a524