Allow deduction guides to look into primary template.

* cp-tree.h (struct saved_scope): Add deduction_guide_type.
	(struct cp_decl_specifier_seq): Add constructor_p.
	* parser.c (cp_parser_decl_specifier_seq): Set constructor_p.
	(cp_parser_init_declarator): Check it.  Set ctor_dtor_or_conv_p.
	Clear deduction_guide_type.  Don't handle deduction guide names.
	(cp_parser_declarator): Don't clear ctor_dtor_or_conv_p.
	(cp_parser_direct_declarator): Likewise.  Handle deduction guides.
	(cp_parser_member_declaration, cp_parser_cache_defarg)
	(cp_parser_objc_class_ivars): Set ctor_dtor_or_conv_p.
	* pt.c (tsubst_copy, tsubst_copy_and_build): Revert last change.
	(build_deduction_guide): Set deduction_guide_type.
	(dependent_scope_p): Check deduction_guide_type.
	* search.c (lookup_member): Likewise.

From-SVN: r245858
This commit is contained in:
Jason Merrill 2017-03-02 20:26:47 -05:00 committed by Jason Merrill
parent 9e01c6ce92
commit de35db4271
6 changed files with 90 additions and 50 deletions

View File

@ -1,3 +1,20 @@
2017-03-02 Jason Merrill <jason@redhat.com>
Allow deduction guides to look into primary template.
* cp-tree.h (struct saved_scope): Add deduction_guide_type.
(struct cp_decl_specifier_seq): Add constructor_p.
* parser.c (cp_parser_decl_specifier_seq): Set constructor_p.
(cp_parser_init_declarator): Check it. Set ctor_dtor_or_conv_p.
Clear deduction_guide_type. Don't handle deduction guide names.
(cp_parser_declarator): Don't clear ctor_dtor_or_conv_p.
(cp_parser_direct_declarator): Likewise. Handle deduction guides.
(cp_parser_member_declaration, cp_parser_cache_defarg)
(cp_parser_objc_class_ivars): Set ctor_dtor_or_conv_p.
* pt.c (tsubst_copy, tsubst_copy_and_build): Revert last change.
(build_deduction_guide): Set deduction_guide_type.
(dependent_scope_p): Check deduction_guide_type.
* search.c (lookup_member): Likewise.
2017-03-02 Jakub Jelinek <jakub@redhat.com>
PR c++/79782

View File

@ -1272,6 +1272,7 @@ struct GTY(()) saved_scope {
vec<tree, va_gc> *lang_base;
tree lang_name;
tree template_parms;
tree deduction_guide_type;
cp_binding_level *x_previous_class_level;
tree x_saved_tree;
@ -5422,6 +5423,9 @@ struct cp_decl_specifier_seq {
BOOL_BITFIELD gnu_thread_keyword_p : 1;
/* True iff the type is a decltype. */
BOOL_BITFIELD decltype_p : 1;
/* True iff the declaration declares a constructor or C++17 deduction
guide. */
BOOL_BITFIELD constructor_p : 1;
};
/* The various kinds of declarators. */

View File

@ -13313,6 +13313,8 @@ cp_parser_decl_specifier_seq (cp_parser* parser,
&& constructor_possible_p
&& (cp_parser_constructor_declarator_p
(parser, decl_spec_seq_has_spec_p (decl_specs, ds_friend))));
if (constructor_p)
decl_specs->constructor_p = true;
/* If we don't have a DECL_SPEC yet, then we must be looking at
a type-specifier. */
@ -19010,7 +19012,7 @@ cp_parser_init_declarator (cp_parser* parser,
enum cpp_ttype initialization_kind;
bool is_direct_init = false;
bool is_non_constant_init;
int ctor_dtor_or_conv_p;
int ctor_dtor_or_conv_p = decl_specifiers->constructor_p ? -1 : 0;
bool friend_p = cp_parser_friend_p (decl_specifiers);
tree pushed_scope = NULL_TREE;
bool range_for_decl_p = false;
@ -19048,6 +19050,9 @@ cp_parser_init_declarator (cp_parser* parser,
parser->default_arg_ok_p = saved_default_arg_ok_p;
if (cxx_dialect >= cxx1z)
scope_chain->deduction_guide_type = NULL_TREE;
/* If the DECLARATOR was erroneous, there's no need to go
further. */
if (declarator == cp_error_declarator)
@ -19095,25 +19100,6 @@ cp_parser_init_declarator (cp_parser* parser,
if (function_declarator_p (declarator))
{
/* Handle C++17 deduction guides. */
if (!decl_specifiers->type
&& ctor_dtor_or_conv_p <= 0
&& cxx_dialect >= cxx1z)
{
cp_declarator *id = get_id_declarator (declarator);
tree name = id->u.id.unqualified_name;
parser->scope = id->u.id.qualifying_scope;
tree tmpl = cp_parser_lookup_name_simple (parser, name, id->id_loc);
if (tmpl
&& (DECL_CLASS_TEMPLATE_P (tmpl)
|| DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)))
{
id->u.id.unqualified_name = dguide_name (tmpl);
id->u.id.sfk = sfk_deduction_guide;
ctor_dtor_or_conv_p = 1;
}
}
/* Check to see if the token indicates the start of a
function-definition. */
if (cp_parser_token_starts_function_definition_p (token))
@ -19432,8 +19418,10 @@ cp_parser_init_declarator (cp_parser* parser,
If CTOR_DTOR_OR_CONV_P is not NULL, *CTOR_DTOR_OR_CONV_P is used to
detect constructors, destructors, deduction guides, or conversion operators.
It is set to -1 if the declarator is a name, and +1 if it is a
function. Otherwise it is set to zero. Usually you just want to
The caller should set it before the call, to -1 if parsing the
decl-specifier-seq determined that we're declaring a constructor or
deduction guide, or 0 otherwise. This function sets it to -1 if the
declarator is a name, and +1 if it is a function. Usually you just want to
test for >0, but internally the negative value is used.
(The reason for CTOR_DTOR_OR_CONV_P is that a declaration must have
@ -19464,11 +19452,6 @@ cp_parser_declarator (cp_parser* parser,
tree class_type;
tree gnu_attributes = NULL_TREE, std_attributes = NULL_TREE;
/* Assume this is not a constructor, destructor, or type-conversion
operator. */
if (ctor_dtor_or_conv_p)
*ctor_dtor_or_conv_p = 0;
if (cp_parser_allow_gnu_extensions_p (parser))
gnu_attributes = cp_parser_gnu_attributes_opt (parser);
@ -19766,9 +19749,6 @@ cp_parser_direct_declarator (cp_parser* parser,
/* Parse an array-declarator. */
tree bounds, attrs;
if (ctor_dtor_or_conv_p)
*ctor_dtor_or_conv_p = 0;
first = false;
parser->default_arg_ok_p = false;
parser->in_declarator_p = true;
@ -20023,6 +20003,34 @@ cp_parser_direct_declarator (cp_parser* parser,
*ctor_dtor_or_conv_p = -1;
}
}
if (cxx_dialect >= cxx1z
&& sfk == sfk_none
&& ctor_dtor_or_conv_p
&& *ctor_dtor_or_conv_p == -1)
{
/* If *ctor_dtor_or_conv_p is set and we aren't declaring a
constructor, we must be declaring a deduction guide. */
tree tmpl;
if (qualifying_scope)
tmpl = (lookup_qualified_name
(qualifying_scope, unqualified_name,
/*prefer_type*/false, /*complain*/true));
else
tmpl = lookup_name (unqualified_name);
if (tmpl
&& (DECL_CLASS_TEMPLATE_P (tmpl)
|| DECL_TEMPLATE_TEMPLATE_PARM_P (tmpl)))
{
unqualified_name = dguide_name (tmpl);
scope_chain->deduction_guide_type
= TREE_TYPE (unqualified_name);
sfk = sfk_deduction_guide;
}
else
gcc_checking_assert (false);
}
declarator = make_id_declarator (qualifying_scope,
unqualified_name,
sfk);
@ -23251,7 +23259,7 @@ cp_parser_member_declaration (cp_parser* parser)
cp_declarator *declarator;
tree initializer;
tree asm_specification;
int ctor_dtor_or_conv_p;
int ctor_dtor_or_conv_p = decl_specifiers.constructor_p ? -1 : 0;
/* Parse the declarator. */
declarator
@ -28334,7 +28342,7 @@ cp_parser_cache_defarg (cp_parser *parser, bool nsdmi)
declarator. */
do
{
int ctor_dtor_or_conv_p;
int ctor_dtor_or_conv_p = 0;
cp_lexer_consume_token (parser->lexer);
cp_parser_declarator (parser, CP_PARSER_DECLARATOR_NAMED,
&ctor_dtor_or_conv_p,
@ -29655,7 +29663,7 @@ cp_parser_objc_class_ivars (cp_parser* parser)
{
tree width = NULL_TREE, attributes, first_attribute, decl;
cp_declarator *declarator = NULL;
int ctor_dtor_or_conv_p;
int ctor_dtor_or_conv_p = 0;
/* Check for a (possibly unnamed) bitfield declaration. */
token = cp_lexer_peek_token (parser->lexer);

View File

@ -14641,15 +14641,6 @@ tsubst_copy (tree t, tree args, tsubst_flags_t complain, tree in_decl)
have to substitute this with one having context `D<int>'. */
tree context = tsubst (DECL_CONTEXT (t), args, complain, in_decl);
if (dependent_scope_p (context))
{
/* When rewriting a constructor into a deduction guide, a
non-dependent name can become dependent, so memtmpl<args>
becomes context::template memtmpl<args>. */
tree type = tsubst (TREE_TYPE (t), args, complain, in_decl);
return build_qualified_name (type, context, DECL_NAME (t),
/*template*/true);
}
return lookup_field (context, DECL_NAME(t), 0, false);
}
else
@ -16633,14 +16624,6 @@ tsubst_copy_and_build (tree t,
if (targs == error_mark_node)
return error_mark_node;
if (TREE_CODE (templ) == SCOPE_REF)
{
tree name = TREE_OPERAND (templ, 1);
tree tid = lookup_template_function (name, targs);
TREE_OPERAND (templ, 1) = tid;
return templ;
}
if (variable_template_p (templ))
RETURN (lookup_and_finish_template_variable (templ, targs, complain));
@ -23476,6 +23459,9 @@ bool
dependent_scope_p (tree scope)
{
return (scope && TYPE_P (scope) && dependent_type_p (scope)
&& !(cxx_dialect >= cxx1z
&& scope_chain->deduction_guide_type
&& same_type_p (scope, scope_chain->deduction_guide_type))
&& !currently_open_class (scope));
}
@ -24997,6 +24983,7 @@ build_deduction_guide (tree ctor, tree outer_args, tsubst_flags_t complain)
if (outer_args)
ctor = tsubst (ctor, outer_args, complain, ctor);
type = DECL_CONTEXT (ctor);
scope_chain->deduction_guide_type = type;
tree fn_tmpl;
if (TREE_CODE (ctor) == TEMPLATE_DECL)
{
@ -25089,6 +25076,7 @@ build_deduction_guide (tree ctor, tree outer_args, tsubst_flags_t complain)
current_template_parms = save_parms;
--processing_template_decl;
}
scope_chain->deduction_guide_type = NULL_TREE;
}
if (!memtmpl)

View File

@ -1279,6 +1279,13 @@ lookup_member (tree xbasetype, tree name, int protect, bool want_type,
if (tree t = currently_open_class (type))
type = t;
/* Declaration of a deduction guide can look inside the primary class
template; replace a compatible type with the real one. */
if (cxx_dialect >= cxx1z
&& scope_chain->deduction_guide_type
&& same_type_p (type, scope_chain->deduction_guide_type))
type = scope_chain->deduction_guide_type;
if (!basetype_path)
basetype_path = TYPE_BINFO (type);

View File

@ -0,0 +1,16 @@
// { dg-options -std=c++1z }
template <class T> struct A
{
using value_t = T;
A(value_t);
};
template <class T>
A(typename A<T>::value_t) -> A<double>;
template <class,class> struct same;
template <class T> struct same<T,T> {};
A a(42);
same<decltype(a),A<double>> s1;