* [C++ PATCH] Implement P0028R4, C++17 using attribute namespaces without repetition
@ 2016-09-13 8:16 Jakub Jelinek
2016-09-13 15:43 ` Jason Merrill
0 siblings, 1 reply; 3+ messages in thread
From: Jakub Jelinek @ 2016-09-13 8:16 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches
Hi!
This patch implements the P0028R4 C++17 enhancement.
First I found a bug in the C++11 std attribute handling, where
[[bitand, bitand::foo]] has been allowed, but not [[foo::bitand]]
(i.e. the identifier after :: accepted only non-keyword and keyword identifiers
but not alternative tokens, while the first identifier accepted both).
As mentioned privately, I think there is an inconsistency in the current
C++17 draft, where keywords/alternative tokens are allowed only in
attribute-token, but not in in attribute-using-prefix's attribute-namespace.
The second testcaser in the last function includes a testcase of this and
cp_parser_std_attribute_spec has such addition commented out, so it is easy
to change afterwards.
Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
2016-09-13 Jakub Jelinek <jakub@redhat.com>
Implement P0028R4, C++17 using attribute namespaces without repetition
* parser.c (cp_parser_std_attribute): Add ATTR_NS argument. Diagnose
non-NULL ATTR_NS with scoped attribute token. Handle non-NULL
ATTR_NS with non-scoped attribute tokens. Allow named ops in
identifier after ::.
(cp_parser_std_attribute_list): Add ATTR_NS argument, pass it down
to cp_parser_std_attribute calls.
(cp_parser_std_attribute_spec): Parse optional C++17
attribute-using-prefix, adjust grammar in function comment.
* g++.dg/cpp0x/gen-attrs-61.C: New test.
* g++.dg/cpp1z/gen-attrs1.C: New test.
--- gcc/cp/parser.c.jj 2016-09-06 20:00:36.000000000 +0200
+++ gcc/cp/parser.c 2016-09-12 21:01:40.801317995 +0200
@@ -2392,7 +2392,7 @@ static tree cp_parser_gnu_attributes_opt
static tree cp_parser_gnu_attribute_list
(cp_parser *);
static tree cp_parser_std_attribute
- (cp_parser *);
+ (cp_parser *, tree);
static tree cp_parser_std_attribute_spec
(cp_parser *);
static tree cp_parser_std_attribute_spec_seq
@@ -24055,9 +24055,9 @@ cp_parser_gnu_attribute_list (cp_parser*
{ balanced-token-seq }. */
static tree
-cp_parser_std_attribute (cp_parser *parser)
+cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
{
- tree attribute, attr_ns = NULL_TREE, attr_id = NULL_TREE, arguments;
+ tree attribute, attr_id = NULL_TREE, arguments;
cp_token *token;
/* First, parse name of the attribute, a.k.a attribute-token. */
@@ -24081,6 +24081,9 @@ cp_parser_std_attribute (cp_parser *pars
/* We are seeing a scoped attribute token. */
cp_lexer_consume_token (parser->lexer);
+ if (attr_ns)
+ error_at (token->location, "attribute using prefix used together "
+ "with scoped attribute token");
attr_ns = attr_id;
token = cp_lexer_consume_token (parser->lexer);
@@ -24088,6 +24091,8 @@ cp_parser_std_attribute (cp_parser *pars
attr_id = token->u.value;
else if (token->type == CPP_KEYWORD)
attr_id = ridpointers[(int) token->keyword];
+ else if (token->flags & NAMED_OP)
+ attr_id = get_identifier (cpp_type2name (token->type, token->flags));
else
{
error_at (token->location,
@@ -24098,6 +24103,9 @@ cp_parser_std_attribute (cp_parser *pars
NULL_TREE);
token = cp_lexer_peek_token (parser->lexer);
}
+ else if (attr_ns)
+ attribute = build_tree_list (build_tree_list (attr_ns, attr_id),
+ NULL_TREE);
else
{
attribute = build_tree_list (build_tree_list (NULL_TREE, attr_id),
@@ -24191,14 +24199,14 @@ cp_parser_check_std_attribute (tree attr
*/
static tree
-cp_parser_std_attribute_list (cp_parser *parser)
+cp_parser_std_attribute_list (cp_parser *parser, tree attr_ns)
{
tree attributes = NULL_TREE, attribute = NULL_TREE;
cp_token *token = NULL;
while (true)
{
- attribute = cp_parser_std_attribute (parser);
+ attribute = cp_parser_std_attribute (parser, attr_ns);
if (attribute == error_mark_node)
break;
if (attribute != NULL_TREE)
@@ -24226,9 +24234,12 @@ cp_parser_std_attribute_list (cp_parser
/* Parse a standard C++-11 attribute specifier.
attribute-specifier:
- [ [ attribute-list ] ]
+ [ [ attribute-using-prefix [opt] attribute-list ] ]
alignment-specifier
+ attribute-using-prefix:
+ using attribute-namespace :
+
alignment-specifier:
alignas ( type-id ... [opt] )
alignas ( alignment-expression ... [opt] ). */
@@ -24242,10 +24253,40 @@ cp_parser_std_attribute_spec (cp_parser
if (token->type == CPP_OPEN_SQUARE
&& cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_OPEN_SQUARE)
{
+ tree attr_ns = NULL_TREE;
+
cp_lexer_consume_token (parser->lexer);
cp_lexer_consume_token (parser->lexer);
- attributes = cp_parser_std_attribute_list (parser);
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_USING))
+ {
+ token = cp_lexer_peek_nth_token (parser->lexer, 2);
+ if (token->type == CPP_NAME)
+ attr_ns = token->u.value;
+ /* Not allowed in the current draft: */
+ /* else if (token->type == CPP_KEYWORD)
+ attr_ns = ridpointers[(int) token->keyword];
+ else if (token->flags & NAMED_OP)
+ attr_ns = get_identifier (cpp_type2name (token->type,
+ token->flags)); */
+ if (attr_ns
+ && cp_lexer_nth_token_is (parser->lexer, 3, CPP_COLON))
+ {
+ if (cxx_dialect < cxx1z
+ && !in_system_header_at (input_location))
+ pedwarn (input_location, 0,
+ "attribute using prefix only available "
+ "with -std=c++1z or -std=gnu++1z");
+
+ cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else
+ attr_ns = NULL_TREE;
+ }
+
+ attributes = cp_parser_std_attribute_list (parser, attr_ns);
if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE)
|| !cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE))
--- gcc/testsuite/g++.dg/cpp0x/gen-attrs-61.C.jj 2016-09-12 20:23:36.813211882 +0200
+++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-61.C 2016-09-12 20:27:35.975471024 +0200
@@ -0,0 +1,10 @@
+// { dg-do compile { target c++11 } }
+int
+foo ()
+{
+ int i [[and::bitor, bar::xor_eq, compl::baz(1), bitand::xor_eq(2, 3)]]; // { dg-warning "ignored" }
+ int j [[using, using::baz, bar::using, using::using (2)]]; // { dg-warning "ignored" }
+ i = 0;
+ j = 0;
+ return i + j;
+}
--- gcc/testsuite/g++.dg/cpp1z/gen-attrs1.C.jj 2016-09-12 20:31:41.937652236 +0200
+++ gcc/testsuite/g++.dg/cpp1z/gen-attrs1.C 2016-09-12 21:28:18.059013028 +0200
@@ -0,0 +1,42 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+int
+foo ()
+{
+ static int a [[using gnu: unused, used]]; // { dg-warning "attribute using prefix only available" "" { target c++14_down } }
+ int b [[ using foo : bar (2), baz ]]; // { dg-warning "'foo::bar' scoped attribute directive ignored" }
+ // { dg-warning "'foo::baz' scoped attribute directive ignored" "" { target *-*-* } 8 }
+ // { dg-warning "attribute using prefix only available" "" { target c++14_down } 8 }
+ int c [[ using foo : using ("foo")]]; // { dg-warning "'foo::using' scoped attribute directive ignored" }
+ // { dg-warning "attribute using prefix only available" "" { target c++14_down } 11 }
+ b = 0;
+ c = 0;
+ return b + c;
+}
+
+int
+bar ()
+{
+ int a [[ using BAR: foo::bar]]; // { dg-error "attribute using prefix used together with scoped attribute token" }
+ // { dg-warning "ignored" "" { target *-*-* } 21 }
+ // { dg-warning "attribute using prefix only available" "" { target c++14_down } 21 }
+ int b [[ using BAZ: bar(2), bar::bar(3, 4) ]];// { dg-error "attribute using prefix used together with scoped attribute token" }
+ // { dg-warning "ignored" "" { target *-*-* } 24 }
+ // { dg-warning "attribute using prefix only available" "" { target c++14_down } 24 }
+ a = 0;
+ b = 0;
+ return a + b;
+}
+
+int
+baz ()
+{
+ int a [[ using using: using]]; // { dg-error "expected" }
+ // { dg-warning "ignored" "" { target *-*-* } 35 }
+ int b [[ using bitand: bitor, xor]]; // { dg-error "expected" }
+ // { dg-warning "ignored" "" { target *-*-* } 37 }
+ a = 0;
+ b = 0;
+ return a + b;
+}
Jakub
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [C++ PATCH] Implement P0028R4, C++17 using attribute namespaces without repetition
2016-09-13 8:16 [C++ PATCH] Implement P0028R4, C++17 using attribute namespaces without repetition Jakub Jelinek
@ 2016-09-13 15:43 ` Jason Merrill
2016-09-13 19:22 ` Jakub Jelinek
0 siblings, 1 reply; 3+ messages in thread
From: Jason Merrill @ 2016-09-13 15:43 UTC (permalink / raw)
To: Jakub Jelinek; +Cc: gcc-patches List
On Tue, Sep 13, 2016 at 4:03 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> This patch implements the P0028R4 C++17 enhancement.
> First I found a bug in the C++11 std attribute handling, where
> [[bitand, bitand::foo]] has been allowed, but not [[foo::bitand]]
> (i.e. the identifier after :: accepted only non-keyword and keyword identifiers
> but not alternative tokens, while the first identifier accepted both).
>
> As mentioned privately, I think there is an inconsistency in the current
> C++17 draft, where keywords/alternative tokens are allowed only in
> attribute-token, but not in in attribute-using-prefix's attribute-namespace.
> The second testcaser in the last function includes a testcase of this and
> cp_parser_std_attribute_spec has such addition commented out, so it is easy
> to change afterwards.
Let's go ahead and support it now, this is just a wording oversight.
I've emailed the committee about it. OK with that change.
Jason
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [C++ PATCH] Implement P0028R4, C++17 using attribute namespaces without repetition
2016-09-13 15:43 ` Jason Merrill
@ 2016-09-13 19:22 ` Jakub Jelinek
0 siblings, 0 replies; 3+ messages in thread
From: Jakub Jelinek @ 2016-09-13 19:22 UTC (permalink / raw)
To: Jason Merrill; +Cc: gcc-patches List
On Tue, Sep 13, 2016 at 11:40:20AM -0400, Jason Merrill wrote:
> On Tue, Sep 13, 2016 at 4:03 AM, Jakub Jelinek <jakub@redhat.com> wrote:
> > This patch implements the P0028R4 C++17 enhancement.
> > First I found a bug in the C++11 std attribute handling, where
> > [[bitand, bitand::foo]] has been allowed, but not [[foo::bitand]]
> > (i.e. the identifier after :: accepted only non-keyword and keyword identifiers
> > but not alternative tokens, while the first identifier accepted both).
> >
> > As mentioned privately, I think there is an inconsistency in the current
> > C++17 draft, where keywords/alternative tokens are allowed only in
> > attribute-token, but not in in attribute-using-prefix's attribute-namespace.
> > The second testcaser in the last function includes a testcase of this and
> > cp_parser_std_attribute_spec has such addition commented out, so it is easy
> > to change afterwards.
>
> Let's go ahead and support it now, this is just a wording oversight.
> I've emailed the committee about it. OK with that change.
Ok, here is what I've committed after another bootstrap/regtest:
2016-09-13 Jakub Jelinek <jakub@redhat.com>
Implement P0028R4, C++17 using attribute namespaces without repetition
* parser.c (cp_parser_std_attribute): Add ATTR_NS argument. Diagnose
non-NULL ATTR_NS with scoped attribute token. Handle non-NULL
ATTR_NS with non-scoped attribute tokens. Allow named ops in
identifier after ::.
(cp_parser_std_attribute_list): Add ATTR_NS argument, pass it down
to cp_parser_std_attribute calls.
(cp_parser_std_attribute_spec): Parse optional C++17
attribute-using-prefix, adjust grammar in function comment.
* g++.dg/cpp0x/gen-attrs-61.C: New test.
* g++.dg/cpp1z/gen-attrs1.C: New test.
--- gcc/cp/parser.c.jj 2016-09-13 19:06:26.412217482 +0200
+++ gcc/cp/parser.c 2016-09-13 19:12:04.958161786 +0200
@@ -2392,7 +2392,7 @@ static tree cp_parser_gnu_attributes_opt
static tree cp_parser_gnu_attribute_list
(cp_parser *);
static tree cp_parser_std_attribute
- (cp_parser *);
+ (cp_parser *, tree);
static tree cp_parser_std_attribute_spec
(cp_parser *);
static tree cp_parser_std_attribute_spec_seq
@@ -24056,9 +24056,9 @@ cp_parser_gnu_attribute_list (cp_parser*
{ balanced-token-seq }. */
static tree
-cp_parser_std_attribute (cp_parser *parser)
+cp_parser_std_attribute (cp_parser *parser, tree attr_ns)
{
- tree attribute, attr_ns = NULL_TREE, attr_id = NULL_TREE, arguments;
+ tree attribute, attr_id = NULL_TREE, arguments;
cp_token *token;
/* First, parse name of the attribute, a.k.a attribute-token. */
@@ -24082,6 +24082,9 @@ cp_parser_std_attribute (cp_parser *pars
/* We are seeing a scoped attribute token. */
cp_lexer_consume_token (parser->lexer);
+ if (attr_ns)
+ error_at (token->location, "attribute using prefix used together "
+ "with scoped attribute token");
attr_ns = attr_id;
token = cp_lexer_consume_token (parser->lexer);
@@ -24089,6 +24092,8 @@ cp_parser_std_attribute (cp_parser *pars
attr_id = token->u.value;
else if (token->type == CPP_KEYWORD)
attr_id = ridpointers[(int) token->keyword];
+ else if (token->flags & NAMED_OP)
+ attr_id = get_identifier (cpp_type2name (token->type, token->flags));
else
{
error_at (token->location,
@@ -24099,6 +24104,9 @@ cp_parser_std_attribute (cp_parser *pars
NULL_TREE);
token = cp_lexer_peek_token (parser->lexer);
}
+ else if (attr_ns)
+ attribute = build_tree_list (build_tree_list (attr_ns, attr_id),
+ NULL_TREE);
else
{
attribute = build_tree_list (build_tree_list (NULL_TREE, attr_id),
@@ -24192,14 +24200,14 @@ cp_parser_check_std_attribute (tree attr
*/
static tree
-cp_parser_std_attribute_list (cp_parser *parser)
+cp_parser_std_attribute_list (cp_parser *parser, tree attr_ns)
{
tree attributes = NULL_TREE, attribute = NULL_TREE;
cp_token *token = NULL;
while (true)
{
- attribute = cp_parser_std_attribute (parser);
+ attribute = cp_parser_std_attribute (parser, attr_ns);
if (attribute == error_mark_node)
break;
if (attribute != NULL_TREE)
@@ -24227,9 +24235,12 @@ cp_parser_std_attribute_list (cp_parser
/* Parse a standard C++-11 attribute specifier.
attribute-specifier:
- [ [ attribute-list ] ]
+ [ [ attribute-using-prefix [opt] attribute-list ] ]
alignment-specifier
+ attribute-using-prefix:
+ using attribute-namespace :
+
alignment-specifier:
alignas ( type-id ... [opt] )
alignas ( alignment-expression ... [opt] ). */
@@ -24243,10 +24254,39 @@ cp_parser_std_attribute_spec (cp_parser
if (token->type == CPP_OPEN_SQUARE
&& cp_lexer_peek_nth_token (parser->lexer, 2)->type == CPP_OPEN_SQUARE)
{
+ tree attr_ns = NULL_TREE;
+
cp_lexer_consume_token (parser->lexer);
cp_lexer_consume_token (parser->lexer);
- attributes = cp_parser_std_attribute_list (parser);
+ if (cp_lexer_next_token_is_keyword (parser->lexer, RID_USING))
+ {
+ token = cp_lexer_peek_nth_token (parser->lexer, 2);
+ if (token->type == CPP_NAME)
+ attr_ns = token->u.value;
+ else if (token->type == CPP_KEYWORD)
+ attr_ns = ridpointers[(int) token->keyword];
+ else if (token->flags & NAMED_OP)
+ attr_ns = get_identifier (cpp_type2name (token->type,
+ token->flags));
+ if (attr_ns
+ && cp_lexer_nth_token_is (parser->lexer, 3, CPP_COLON))
+ {
+ if (cxx_dialect < cxx1z
+ && !in_system_header_at (input_location))
+ pedwarn (input_location, 0,
+ "attribute using prefix only available "
+ "with -std=c++1z or -std=gnu++1z");
+
+ cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ cp_lexer_consume_token (parser->lexer);
+ }
+ else
+ attr_ns = NULL_TREE;
+ }
+
+ attributes = cp_parser_std_attribute_list (parser, attr_ns);
if (!cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE)
|| !cp_parser_require (parser, CPP_CLOSE_SQUARE, RT_CLOSE_SQUARE))
--- gcc/testsuite/g++.dg/cpp0x/gen-attrs-61.C.jj 2016-09-13 19:11:09.568825336 +0200
+++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-61.C 2016-09-13 19:11:09.568825336 +0200
@@ -0,0 +1,10 @@
+// { dg-do compile { target c++11 } }
+int
+foo ()
+{
+ int i [[and::bitor, bar::xor_eq, compl::baz(1), bitand::xor_eq(2, 3)]]; // { dg-warning "ignored" }
+ int j [[using, using::baz, bar::using, using::using (2)]]; // { dg-warning "ignored" }
+ i = 0;
+ j = 0;
+ return i + j;
+}
--- gcc/testsuite/g++.dg/cpp1z/gen-attrs1.C.jj 2016-09-13 19:11:09.568825336 +0200
+++ gcc/testsuite/g++.dg/cpp1z/gen-attrs1.C 2016-09-13 19:14:09.350671595 +0200
@@ -0,0 +1,43 @@
+// { dg-do compile { target c++11 } }
+// { dg-options "" }
+
+int
+foo ()
+{
+ static int a [[using gnu: unused, used]]; // { dg-warning "attribute using prefix only available" "" { target c++14_down } }
+ int b [[ using foo : bar (2), baz ]]; // { dg-warning "'foo::bar' scoped attribute directive ignored" }
+ // { dg-warning "'foo::baz' scoped attribute directive ignored" "" { target *-*-* } 8 }
+ // { dg-warning "attribute using prefix only available" "" { target c++14_down } 8 }
+ int c [[ using foo : using ("foo")]]; // { dg-warning "'foo::using' scoped attribute directive ignored" }
+ // { dg-warning "attribute using prefix only available" "" { target c++14_down } 11 }
+ b = 0;
+ c = 0;
+ return b + c;
+}
+
+int
+bar ()
+{
+ int a [[ using BAR: foo::bar]]; // { dg-error "attribute using prefix used together with scoped attribute token" }
+ // { dg-warning "ignored" "" { target *-*-* } 21 }
+ // { dg-warning "attribute using prefix only available" "" { target c++14_down } 21 }
+ int b [[ using BAZ: bar(2), bar::bar(3, 4) ]];// { dg-error "attribute using prefix used together with scoped attribute token" }
+ // { dg-warning "ignored" "" { target *-*-* } 24 }
+ // { dg-warning "attribute using prefix only available" "" { target c++14_down } 24 }
+ a = 0;
+ b = 0;
+ return a + b;
+}
+
+int
+baz ()
+{
+ int a [[ using using: using]]; // { dg-warning "attribute using prefix only available" "" { target c++14_down } }
+ // { dg-warning "'using::using' scoped attribute directive ignored" "" { target *-*-* } 35 }
+ int b [[ using bitand: bitor, xor]]; // { dg-warning "attribute using prefix only available" "" { target c++14_down } }
+ // { dg-warning "'bitand::bitor' scoped attribute directive ignored" "" { target *-*-* } 37 }
+ // { dg-warning "'bitand::xor' scoped attribute directive ignored" "" { target *-*-* } 37 }
+ a = 0;
+ b = 0;
+ return a + b;
+}
Jakub
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2016-09-13 19:21 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-09-13 8:16 [C++ PATCH] Implement P0028R4, C++17 using attribute namespaces without repetition Jakub Jelinek
2016-09-13 15:43 ` Jason Merrill
2016-09-13 19:22 ` Jakub Jelinek
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).