===================================================================
@@ -22532,6 +22547,35 @@ cp_parser_std_attribute (cp_parser *parser)
return attribute;
}
+/* Check that the attribute ATTRIBUTE appears at most once in the
+ attribute-list ATTRIBUTES. This is enforced for noreturn (7.6.3)
+ and deprecated (7.6.5). Note that carries_dependency (7.6.4)
+ isn't implemented yet in GCC. */
+
+static bool
+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");
+ return false;
+ }
+ else if (is_attribute_p ("deprecated", name)
+ && lookup_attribute ("deprecated", attributes))
+ {
+ error ("attribute deprecated can appear at most once "
+ "in an attribute-list");
+ return false;
+ }
+ }
+ return true;
+}
+
/* Parse a list of standard C++-11 attributes.
attribute-list:
@@ -22554,6 +22598,8 @@ cp_parser_std_attribute_list (cp_parser *parser)
break;
if (attribute != NULL_TREE)
{
+ if (!cp_parser_check_std_attribute (attributes, attribute))
+ break;
TREE_CHAIN (attribute) = attributes;
attributes = attribute;
}
===================================================================
@@ -0,0 +1,4 @@
+// PR c++/60365
+// { dg-do compile { target c++11 } }
+
+void func [[noreturn, noreturn]] (); // { dg-error "at most once" }
===================================================================
@@ -0,0 +1,4 @@
+// PR c++/60365
+// { dg-do compile { target c++14 } }
+
+void func [[deprecated, deprecated]] (); // { dg-error "at most once" }