From 9952908a4b6cf73e8de11af61e1d2c4d67e1b530 Mon Sep 17 00:00:00 2001 From: Jakub Jelinek Date: Tue, 13 Sep 2016 21:20:38 +0200 Subject: [PATCH] Implement P0028R4, C++17 using attribute namespaces without repetition 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. From-SVN: r240121 --- gcc/cp/ChangeLog | 10 +++++ gcc/cp/parser.c | 54 ++++++++++++++++++++--- gcc/testsuite/ChangeLog | 3 ++ gcc/testsuite/g++.dg/cpp0x/gen-attrs-61.C | 10 +++++ gcc/testsuite/g++.dg/cpp1z/gen-attrs1.C | 43 ++++++++++++++++++ 5 files changed, 113 insertions(+), 7 deletions(-) create mode 100644 gcc/testsuite/g++.dg/cpp0x/gen-attrs-61.C create mode 100644 gcc/testsuite/g++.dg/cpp1z/gen-attrs1.C diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index a8407fdaa75..97e9cda97ce 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,5 +1,15 @@ 2016-09-13 Jakub Jelinek + 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. + PR c++/77553 * constexpr.c (cxx_fold_pointer_plus_expression): New function. (cxx_eval_binary_expression): Use it for POINTER_PLUS_EXPR. diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c index 73a37814b59..d704593e6aa 100644 --- a/gcc/cp/parser.c +++ b/gcc/cp/parser.c @@ -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* 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 *parser) /* 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 *parser) 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 *parser) 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 attributes, tree attribute) */ 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 *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 *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)) diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index a8927370191..779145a05fd 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,5 +1,8 @@ 2016-09-13 Jakub Jelinek + * g++.dg/cpp0x/gen-attrs-61.C: New test. + * g++.dg/cpp1z/gen-attrs1.C: New test. + PR tree-optimization/77454 * gcc.dg/pr77454.c: New test. diff --git a/gcc/testsuite/g++.dg/cpp0x/gen-attrs-61.C b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-61.C new file mode 100644 index 00000000000..fd7f4437dbb --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp0x/gen-attrs-61.C @@ -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; +} diff --git a/gcc/testsuite/g++.dg/cpp1z/gen-attrs1.C b/gcc/testsuite/g++.dg/cpp1z/gen-attrs1.C new file mode 100644 index 00000000000..fe1ebb29a1d --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp1z/gen-attrs1.C @@ -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; +} -- 2.30.2