mirror of git://gcc.gnu.org/git/gcc.git
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
This commit is contained in:
parent
63cdb7a08d
commit
9952908a4b
|
|
@ -1,5 +1,15 @@
|
|||
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.
|
||||
|
||||
PR c++/77553
|
||||
* constexpr.c (cxx_fold_pointer_plus_expression): New function.
|
||||
(cxx_eval_binary_expression): Use it for POINTER_PLUS_EXPR.
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
2016-09-13 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* 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.
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
Loading…
Reference in New Issue