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. From-SVN: r244246
This commit is contained in:
parent
bd2c62704b
commit
f4da28a0ab
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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");
|
pp_cxx_ws_string (pp, "using");
|
||||||
dump_type (pp, USING_DECL_SCOPE (t), flags);
|
tree scope = USING_DECL_SCOPE (t);
|
||||||
|
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);
|
pp_cxx_colon_colon (pp);
|
||||||
dump_decl (pp, DECL_NAME (t), flags);
|
dump_decl (pp, DECL_NAME (t), flags);
|
||||||
|
if (variadic)
|
||||||
|
pp_cxx_ws_string (pp, "...");
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case STATIC_ASSERT:
|
case STATIC_ASSERT:
|
||||||
|
|
|
@ -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'. */
|
||||||
|
@ -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. */
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
|
||||||
|
|
28
gcc/cp/pt.c
28
gcc/cp/pt.c
|
@ -12590,10 +12590,35 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
|
||||||
instantiation (c++/53549). */
|
instantiation (c++/53549). */
|
||||||
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 scope = USING_DECL_SCOPE (t);
|
||||||
|
tree name = tsubst_copy (DECL_NAME (t), args, complain, in_decl);
|
||||||
|
if (PACK_EXPANSION_P (scope))
|
||||||
|
{
|
||||||
|
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
|
||||||
{
|
{
|
||||||
tree inst_scope = tsubst_copy (USING_DECL_SCOPE (t), args,
|
tree inst_scope = tsubst_copy (USING_DECL_SCOPE (t), args,
|
||||||
complain, in_decl);
|
complain, in_decl);
|
||||||
tree name = tsubst_copy (DECL_NAME (t), args, complain, in_decl);
|
|
||||||
r = do_class_using_decl (inst_scope, name);
|
r = do_class_using_decl (inst_scope, name);
|
||||||
if (!r)
|
if (!r)
|
||||||
r = error_mark_node;
|
r = error_mark_node;
|
||||||
|
@ -12603,6 +12628,7 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
|
||||||
TREE_PRIVATE (r) = TREE_PRIVATE (t);
|
TREE_PRIVATE (r) = TREE_PRIVATE (t);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
r = copy_node (t);
|
r = copy_node (t);
|
||||||
|
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
|
@ -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 }
|
||||||
|
};
|
Loading…
Reference in New Issue