Skip to content

Commit

Permalink
Implement P0195R2, C++17 variadic using.
Browse files Browse the repository at this point in the history
	* parser.c (cp_parser_using_declaration): Handle ellipsis and comma.
	* pt.c (tsubst_decl): Handle pack expansion in USING_DECL_SCOPE.
	* error.c (dump_decl): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@244246 138bc75d-0d04-0410-961f-82ee72b054a4
  • Loading branch information
jason committed Jan 9, 2017
1 parent d0abd9e commit caba101
Show file tree
Hide file tree
Showing 7 changed files with 119 additions and 13 deletions.
7 changes: 7 additions & 0 deletions gcc/cp/ChangeLog
Original file line number Original file line Diff line number Diff line change
@@ -1,3 +1,10 @@
2017-01-09 Jason Merrill <jason@redhat.com>

Implement P0195R2, C++17 variadic using.
* parser.c (cp_parser_using_declaration): Handle ellipsis and comma.
* pt.c (tsubst_decl): Handle pack expansion in USING_DECL_SCOPE.
* error.c (dump_decl): Likewise.

2017-01-09 Jakub Jelinek <jakub@redhat.com> 2017-01-09 Jakub Jelinek <jakub@redhat.com>


PR translation/79019 PR translation/79019
Expand Down
3 changes: 2 additions & 1 deletion gcc/cp/cp-tree.def
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ DEFTREECODE (BOUND_TEMPLATE_TEMPLATE_PARM, "bound_template_template_parm",
DEFTREECODE (UNBOUND_CLASS_TEMPLATE, "unbound_class_template", tcc_type, 0) DEFTREECODE (UNBOUND_CLASS_TEMPLATE, "unbound_class_template", tcc_type, 0)


/* A using declaration. USING_DECL_SCOPE contains the specified /* A using declaration. USING_DECL_SCOPE contains the specified
scope. In a member using decl, unless DECL_DEPENDENT_P is true, scope. In a variadic using-declaration, this is a TYPE_PACK_EXPANSION.
In a member using decl, unless DECL_DEPENDENT_P is true,
USING_DECL_DECLS contains the _DECL or OVERLOAD so named. This is USING_DECL_DECLS contains the _DECL or OVERLOAD so named. This is
not an alias, but is later expanded into multiple aliases. */ not an alias, but is later expanded into multiple aliases. */
DEFTREECODE (USING_DECL, "using_decl", tcc_declaration, 0) DEFTREECODE (USING_DECL, "using_decl", tcc_declaration, 0)
Expand Down
19 changes: 15 additions & 4 deletions gcc/cp/error.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -1268,10 +1268,21 @@ dump_decl (cxx_pretty_printer *pp, tree t, int flags)
break; break;


case USING_DECL: case USING_DECL:
pp_cxx_ws_string (pp, "using"); {
dump_type (pp, USING_DECL_SCOPE (t), flags); pp_cxx_ws_string (pp, "using");
pp_cxx_colon_colon (pp); tree scope = USING_DECL_SCOPE (t);
dump_decl (pp, DECL_NAME (t), flags); bool variadic = false;
if (PACK_EXPANSION_P (scope))
{
scope = PACK_EXPANSION_PATTERN (scope);
variadic = true;
}
dump_type (pp, scope, flags);
pp_cxx_colon_colon (pp);
dump_decl (pp, DECL_NAME (t), flags);
if (variadic)
pp_cxx_ws_string (pp, "...");
}
break; break;


case STATIC_ASSERT: case STATIC_ASSERT:
Expand Down
24 changes: 23 additions & 1 deletion gcc/cp/parser.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -18372,6 +18372,7 @@ cp_parser_using_declaration (cp_parser* parser,
/* Look for the `using' keyword. */ /* Look for the `using' keyword. */
cp_parser_require_keyword (parser, RID_USING, RT_USING); cp_parser_require_keyword (parser, RID_USING, RT_USING);


again:
/* Peek at the next token. */ /* Peek at the next token. */
token = cp_lexer_peek_token (parser->lexer); token = cp_lexer_peek_token (parser->lexer);
/* See if it's `typename'. */ /* See if it's `typename'. */
Expand Down Expand Up @@ -18438,6 +18439,16 @@ cp_parser_using_declaration (cp_parser* parser,
if (!cp_parser_parse_definitely (parser)) if (!cp_parser_parse_definitely (parser))
return false; return false;
} }
else if (cp_lexer_next_token_is (parser->lexer, CPP_ELLIPSIS))
{
cp_token *ell = cp_lexer_consume_token (parser->lexer);
if (cxx_dialect < cxx1z
&& !in_system_header_at (ell->location))
pedwarn (ell->location, 0,
"pack expansion in using-declaration only available "
"with -std=c++1z or -std=gnu++1z");
qscope = make_pack_expansion (qscope);
}


/* The function we call to handle a using-declaration is different /* The function we call to handle a using-declaration is different
depending on what scope we are in. */ depending on what scope we are in. */
Expand All @@ -18455,7 +18466,7 @@ cp_parser_using_declaration (cp_parser* parser,
if (at_class_scope_p ()) if (at_class_scope_p ())
{ {
/* Create the USING_DECL. */ /* Create the USING_DECL. */
decl = do_class_using_decl (parser->scope, identifier); decl = do_class_using_decl (qscope, identifier);


if (decl && typename_p) if (decl && typename_p)
USING_DECL_TYPENAME_P (decl) = 1; USING_DECL_TYPENAME_P (decl) = 1;
Expand Down Expand Up @@ -18490,6 +18501,17 @@ cp_parser_using_declaration (cp_parser* parser,
} }
} }


if (!access_declaration_p
&& cp_lexer_next_token_is (parser->lexer, CPP_COMMA))
{
cp_token *comma = cp_lexer_consume_token (parser->lexer);
if (cxx_dialect < cxx1z)
pedwarn (comma->location, 0,
"comma-separated list in using-declaration only available "
"with -std=c++1z or -std=gnu++1z");
goto again;
}

/* Look for the final `;'. */ /* Look for the final `;'. */
cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON); cp_parser_require (parser, CPP_SEMICOLON, RT_SEMICOLON);


Expand Down
40 changes: 33 additions & 7 deletions gcc/cp/pt.c
Original file line number Original file line Diff line number Diff line change
Expand Up @@ -12591,16 +12591,42 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
if (DECL_DEPENDENT_P (t) if (DECL_DEPENDENT_P (t)
|| uses_template_parms (USING_DECL_SCOPE (t))) || uses_template_parms (USING_DECL_SCOPE (t)))
{ {
tree inst_scope = tsubst_copy (USING_DECL_SCOPE (t), args, tree scope = USING_DECL_SCOPE (t);
complain, in_decl);
tree name = tsubst_copy (DECL_NAME (t), args, complain, in_decl); tree name = tsubst_copy (DECL_NAME (t), args, complain, in_decl);
r = do_class_using_decl (inst_scope, name); if (PACK_EXPANSION_P (scope))
if (!r) {
r = error_mark_node; tree vec = tsubst_pack_expansion (scope, args, complain, in_decl);
int len = TREE_VEC_LENGTH (vec);
r = make_tree_vec (len);
for (int i = 0; i < len; ++i)
{
tree escope = TREE_VEC_ELT (vec, i);
tree elt = do_class_using_decl (escope, name);
if (!elt)
{
r = error_mark_node;
break;
}
else
{
TREE_PROTECTED (elt) = TREE_PROTECTED (t);
TREE_PRIVATE (elt) = TREE_PRIVATE (t);
}
TREE_VEC_ELT (r, i) = elt;
}
}
else else
{ {
TREE_PROTECTED (r) = TREE_PROTECTED (t); tree inst_scope = tsubst_copy (USING_DECL_SCOPE (t), args,
TREE_PRIVATE (r) = TREE_PRIVATE (t); complain, in_decl);
r = do_class_using_decl (inst_scope, name);
if (!r)
r = error_mark_node;
else
{
TREE_PROTECTED (r) = TREE_PROTECTED (t);
TREE_PRIVATE (r) = TREE_PRIVATE (t);
}
} }
} }
else else
Expand Down
19 changes: 19 additions & 0 deletions gcc/testsuite/g++.dg/cpp1z/using2.C
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,19 @@
// Test for P0195R2 variadic using.
// { dg-do compile { target c++11 } }
// { dg-options "" }

struct A { void f(); };
struct B { void f(int); };

template <class... Bases> struct C: Bases...
{
using Bases::f...; // { dg-warning "pack expansion" "" { target c++14_down } }
};

int main()
{
C<A,B> c;
c.f();
c.f(42);
}

20 changes: 20 additions & 0 deletions gcc/testsuite/g++.dg/cpp1z/using3.C
Original file line number Original file line Diff line number Diff line change
@@ -0,0 +1,20 @@
// Test for P0195R2 multiple using.
// { dg-options "" }

namespace A {
int i;
}

namespace A1 {
using A::i, A::i; // OK: double declaration
// { dg-warning "comma" "" { target c++14_down } .-1 }
}

struct B {
int i;
};

struct X : B {
using B::i, B::i; // { dg-error "redeclaration" }
// { dg-warning "comma" "" { target c++14_down } .-1 }
};

0 comments on commit caba101

Please sign in to comment.