aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2023-05-10 11:37:04 +0200
committerJakub Jelinek <jakub@redhat.com>2023-05-10 11:37:04 +0200
commit39d6d4256d16d676f8b9031c4d1d115ddf4ad76b (patch)
tree3792b0295005f4fb5e08088a199915b38a886169
parent046551108378a00ee09cc2a071dd83b3fc7c35cf (diff)
downloadgcc-39d6d4256d16d676f8b9031c4d1d115ddf4ad76b.zip
gcc-39d6d4256d16d676f8b9031c4d1d115ddf4ad76b.tar.gz
gcc-39d6d4256d16d676f8b9031c4d1d115ddf4ad76b.tar.bz2
c++: Reject attributes without arguments used as pack expansion [PR109756]
The following testcase shows we silently accept (and ignore) attributes without arguments used as pack expansions. This is because we call make_pack_expansion and that starts with if (!arg || arg == error_mark_node) return arg; Now, an attribute without arguments like [[noreturn...]] is IMHO always invalid, in this case for 2 reasons; one is that as it has no arguments, no pack can be present and second is that the standard says that attributes need to specially permit uses of parameter pack and doesn't explicitly permit it for any of the standard attributes (except for alignas? which has different syntax). If an attribute has some arguments but doesn't contain packs in those arguments, make_pack_expansion will already diagnose it. The patch also changes cp_parser_std_attribute, such that for attributes unknown to the compiler (or perhaps registered just for -Wno-attributes=) we differentiate between the attribute having no arguments (in that case we want to diagnose them when followed by ellipsis even if they are unknown, as they can't contain a pack in that case) and the case where they do have arguments but we've just skipped over those arguments because we don't know how to parse them (except that they are a balanced token sequence) - in that case we really don't know if they contain packs or not. 2023-05-10 Jakub Jelinek <jakub@redhat.com> PR c++/109756 * parser.cc (cp_parser_std_attribute): For unknown attributes with arguments set TREE_VALUE (attribute) to error_mark_node after skipping the balanced tokens. (cp_parser_std_attribute_list): If ... is used after attribute without arguments, diagnose it and return error_mark_node. If TREE_VALUE (attribute) is error_mark_node, don't call make_pack_expansion nor return early error_mark_node. * g++.dg/cpp0x/gen-attrs-78.C: New test.
-rw-r--r--gcc/cp/parser.cc13
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/gen-attrs-78.C29
2 files changed, 40 insertions, 2 deletions
diff --git a/gcc/cp/parser.cc b/gcc/cp/parser.cc
index 7f4bc0f..5feed77 100644
--- a/gcc/cp/parser.cc
+++ b/gcc/cp/parser.cc
@@ -29467,9 +29467,12 @@ cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
}
/* For unknown attributes, just skip balanced tokens instead of
- trying to parse the arguments. */
+ trying to parse the arguments. Set TREE_VALUE (attribute) to
+ error_mark_node to distinguish skipped arguments from attributes
+ with no arguments. */
for (size_t n = cp_parser_skip_balanced_tokens (parser, 1) - 1; n; --n)
cp_lexer_consume_token (parser->lexer);
+ TREE_VALUE (attribute) = error_mark_node;
return attribute;
}
@@ -29561,7 +29564,13 @@ cp_parser_std_attribute_list (cp_parser *parser, tree attr_ns)
if (attribute == NULL_TREE)
error_at (token->location,
"expected attribute before %<...%>");
- else
+ else if (TREE_VALUE (attribute) == NULL_TREE)
+ {
+ error_at (token->location, "attribute with no arguments "
+ "contains no parameter packs");
+ return error_mark_node;
+ }
+ else if (TREE_VALUE (attribute) != error_mark_node)
{
tree pack = make_pack_expansion (TREE_VALUE (attribute));
if (pack == error_mark_node)
diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-78.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-78.C
new file mode 100644
index 0000000..28b9543
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-78.C
@@ -0,0 +1,29 @@
+// PR c++/109756
+// { dg-do compile { target c++11 } }
+// { dg-options "-Wno-attributes" }
+
+template <int ...args>
+[[noreturn...]] // { dg-error "attribute with no arguments contains no parameter packs" }
+[[deprecated...]] // { dg-error "attribute with no arguments contains no parameter packs" }
+[[nodiscard...]] // { dg-error "attribute with no arguments contains no parameter packs" }
+int foo (int x)
+{
+ switch (x)
+ {
+ case 1:
+ [[likely...]]; // { dg-error "attribute with no arguments contains no parameter packs" }
+ [[fallthrough...]]; // { dg-error "attribute with no arguments contains no parameter packs" }
+ case 2:
+ [[unlikely...]]; // { dg-error "attribute with no arguments contains no parameter packs" }
+
+ break;
+ default:
+ break;
+ }
+ struct T {};
+ struct S { [[no_unique_address...]] T t; }; // { dg-error "attribute with no arguments contains no parameter packs" }
+ for (;;)
+ ;
+}
+
+int a = foo <1, 2, 3> (4);