Hi,
this issue is an accepts invalid about multiple noreturn in an
attribute-list. The same issue exists for deprecated in C++14 (and will
exist for carries_dependency when we'll implement it...). Of course it
would be easy to imagine more efficient algorithms doing the check only
once after the entire attribute-list is parsed, but the simple-minded
check has the advantage that the locations are correct for free and I
suppose should be good enough efficiency-wise for reasonable
attribute-lists... Tested x86_64-linux.
Thanks,
Paolo.
//////////////////////
/cp
2015-06-30 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/60365
* parser.c (cp_parser_check_std_attribute): New.
(cp_parser_std_attribute_list): Call it.
/testsuite
2015-06-30 Paolo Carlini <paolo.carl...@oracle.com>
PR c++/60365
* g++.dg/cpp0x/gen-attrs-60.C: New.
* g++.dg/cpp1y/attr-deprecated-2.C: Likewise.
Index: cp/parser.c
===================================================================
--- cp/parser.c (revision 225177)
+++ cp/parser.c (working copy)
@@ -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;
}
Index: testsuite/g++.dg/cpp0x/gen-attrs-60.C
===================================================================
--- testsuite/g++.dg/cpp0x/gen-attrs-60.C (revision 0)
+++ testsuite/g++.dg/cpp0x/gen-attrs-60.C (working copy)
@@ -0,0 +1,4 @@
+// PR c++/60365
+// { dg-do compile { target c++11 } }
+
+void func [[noreturn, noreturn]] (); // { dg-error "at most once" }
Index: testsuite/g++.dg/cpp1y/attr-deprecated-2.C
===================================================================
--- testsuite/g++.dg/cpp1y/attr-deprecated-2.C (revision 0)
+++ testsuite/g++.dg/cpp1y/attr-deprecated-2.C (working copy)
@@ -0,0 +1,4 @@
+// PR c++/60365
+// { dg-do compile { target c++14 } }
+
+void func [[deprecated, deprecated]] (); // { dg-error "at most once" }