re PR c++/50852 (ICE: internal compiler error: in tsubst, at cp/pt.c:11030)
PR c++/50852 PR c++/53039 * tree.c (strip_typedefs_expr): New. * cp-tree.h: Declare it. * pt.c (convert_template_argument, unify): Use it. * parser.c (cp_parser_template_declaration_after_export): Don't call fixup_template_parms. * cp-tree.h (TEMPLATE_PARM_NUM_SIBLINGS): Remove. (struct template_parm_index_s): Remove num_siblings. * pt.c (fixup_template_parms, fixup_template_parm_index): Remove. (fixup_template_type_parm_type): Remove. (build_template_parm_index): Remove num_siblings parm. (process_template_parm): Likewise. * parser.c (cp_parser_template_parameter_list): Adjust. * tree.c (cp_tree_equal): Don't compare num_siblings. * typeck.c (comp_template_parms_position): Likewise. * pt.c (arg_from_parm_pack_p): Go back to using same_type_p or cp_tree_equal. From-SVN: r193955
This commit is contained in:
parent
0c0d9de605
commit
1c44f40a48
|
@ -1,3 +1,27 @@
|
|||
2012-11-29 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/53039
|
||||
* pt.c (arg_from_parm_pack_p): Go back to using same_type_p or
|
||||
cp_tree_equal.
|
||||
|
||||
* cp-tree.h (TEMPLATE_PARM_NUM_SIBLINGS): Remove.
|
||||
(struct template_parm_index_s): Remove num_siblings.
|
||||
* pt.c (fixup_template_parms, fixup_template_parm_index): Remove.
|
||||
(fixup_template_type_parm_type): Remove.
|
||||
(build_template_parm_index): Remove num_siblings parm.
|
||||
(process_template_parm): Likewise.
|
||||
* parser.c (cp_parser_template_parameter_list): Adjust.
|
||||
* tree.c (cp_tree_equal): Don't compare num_siblings.
|
||||
* typeck.c (comp_template_parms_position): Likewise.
|
||||
|
||||
PR c++/50852
|
||||
PR c++/53039
|
||||
* tree.c (strip_typedefs_expr): New.
|
||||
* cp-tree.h: Declare it.
|
||||
* pt.c (convert_template_argument, unify): Use it.
|
||||
* parser.c (cp_parser_template_declaration_after_export): Don't call
|
||||
fixup_template_parms.
|
||||
|
||||
2012-11-29 Kai Tietz <ktietz@redhat.com>
|
||||
|
||||
PR target/53912
|
||||
|
|
|
@ -248,7 +248,6 @@ struct GTY(()) template_parm_index_s {
|
|||
int index;
|
||||
int level;
|
||||
int orig_level;
|
||||
int num_siblings;
|
||||
tree decl;
|
||||
};
|
||||
typedef struct template_parm_index_s template_parm_index;
|
||||
|
@ -4515,9 +4514,6 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
|
|||
((template_parm_index*)TEMPLATE_PARM_INDEX_CHECK (NODE))
|
||||
#define TEMPLATE_PARM_IDX(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->index)
|
||||
#define TEMPLATE_PARM_LEVEL(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->level)
|
||||
/* The Number of sibling parms this template parm has. */
|
||||
#define TEMPLATE_PARM_NUM_SIBLINGS(NODE) \
|
||||
(TEMPLATE_PARM_INDEX_CAST (NODE)->num_siblings)
|
||||
#define TEMPLATE_PARM_DESCENDANTS(NODE) (TREE_CHAIN (NODE))
|
||||
#define TEMPLATE_PARM_ORIG_LEVEL(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->orig_level)
|
||||
#define TEMPLATE_PARM_DECL(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->decl)
|
||||
|
@ -5288,9 +5284,8 @@ extern void append_type_to_template_for_access_check (tree, tree, tree,
|
|||
extern tree splice_late_return_type (tree, tree);
|
||||
extern bool is_auto (const_tree);
|
||||
extern tree process_template_parm (tree, location_t, tree,
|
||||
bool, bool, unsigned);
|
||||
bool, bool);
|
||||
extern tree end_template_parm_list (tree);
|
||||
void fixup_template_parms (void);
|
||||
extern void end_template_decl (void);
|
||||
extern tree maybe_update_decl_type (tree, tree);
|
||||
extern bool check_default_tmpl_args (tree, tree, int, int, int);
|
||||
|
@ -5663,6 +5658,7 @@ extern bool type_has_nontrivial_copy_init (const_tree);
|
|||
extern bool class_tmpl_impl_spec_p (const_tree);
|
||||
extern int zero_init_p (const_tree);
|
||||
extern tree strip_typedefs (tree);
|
||||
extern tree strip_typedefs_expr (tree);
|
||||
extern tree copy_binfo (tree, tree, tree,
|
||||
tree *, int);
|
||||
extern int member_p (const_tree);
|
||||
|
|
|
@ -11967,8 +11967,7 @@ cp_parser_template_parameter_list (cp_parser* parser)
|
|||
parm_loc,
|
||||
parameter,
|
||||
is_non_type,
|
||||
is_parameter_pack,
|
||||
0);
|
||||
is_parameter_pack);
|
||||
else
|
||||
{
|
||||
tree err_parm = build_tree_list (parameter, parameter);
|
||||
|
@ -21134,7 +21133,6 @@ cp_parser_template_declaration_after_export (cp_parser* parser, bool member_p)
|
|||
{
|
||||
/* Parse the template parameters. */
|
||||
parameter_list = cp_parser_template_parameter_list (parser);
|
||||
fixup_template_parms ();
|
||||
}
|
||||
|
||||
/* Get the deferred access checks from the parameter list. These
|
||||
|
|
354
gcc/cp/pt.c
354
gcc/cp/pt.c
|
@ -148,7 +148,7 @@ static tree convert_template_argument (tree, tree, tree,
|
|||
static int for_each_template_parm (tree, tree_fn_t, void*,
|
||||
struct pointer_set_t*, bool);
|
||||
static tree expand_template_argument_pack (tree);
|
||||
static tree build_template_parm_index (int, int, int, int, tree, tree);
|
||||
static tree build_template_parm_index (int, int, int, tree, tree);
|
||||
static bool inline_needs_template_parms (tree);
|
||||
static void push_inline_template_parms_recursive (tree, int);
|
||||
static tree retrieve_local_specialization (tree);
|
||||
|
@ -205,8 +205,6 @@ static tree listify_autos (tree, tree);
|
|||
static tree template_parm_to_arg (tree t);
|
||||
static bool arg_from_parm_pack_p (tree, tree);
|
||||
static tree current_template_args (void);
|
||||
static tree fixup_template_type_parm_type (tree, int);
|
||||
static tree fixup_template_parm_index (tree, tree, int);
|
||||
static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
|
||||
|
||||
/* Make the current scope suitable for access checking when we are
|
||||
|
@ -3430,14 +3428,12 @@ check_template_shadow (tree decl)
|
|||
}
|
||||
|
||||
/* Return a new TEMPLATE_PARM_INDEX with the indicated INDEX, LEVEL,
|
||||
ORIG_LEVEL, DECL, and TYPE. NUM_SIBLINGS is the total number of
|
||||
template parameters. */
|
||||
ORIG_LEVEL, DECL, and TYPE. */
|
||||
|
||||
static tree
|
||||
build_template_parm_index (int index,
|
||||
int level,
|
||||
int orig_level,
|
||||
int num_siblings,
|
||||
tree decl,
|
||||
tree type)
|
||||
{
|
||||
|
@ -3445,7 +3441,6 @@ build_template_parm_index (int index,
|
|||
TEMPLATE_PARM_IDX (t) = index;
|
||||
TEMPLATE_PARM_LEVEL (t) = level;
|
||||
TEMPLATE_PARM_ORIG_LEVEL (t) = orig_level;
|
||||
TEMPLATE_PARM_NUM_SIBLINGS (t) = num_siblings;
|
||||
TEMPLATE_PARM_DECL (t) = decl;
|
||||
TREE_TYPE (t) = type;
|
||||
TREE_CONSTANT (t) = TREE_CONSTANT (decl);
|
||||
|
@ -3511,7 +3506,6 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
|
|||
t = build_template_parm_index (TEMPLATE_PARM_IDX (index),
|
||||
TEMPLATE_PARM_LEVEL (index) - levels,
|
||||
TEMPLATE_PARM_ORIG_LEVEL (index),
|
||||
TEMPLATE_PARM_NUM_SIBLINGS (index),
|
||||
decl, type);
|
||||
TEMPLATE_PARM_DESCENDANTS (index) = t;
|
||||
TEMPLATE_PARM_PARAMETER_PACK (t)
|
||||
|
@ -3539,8 +3533,7 @@ reduce_template_parm_level (tree index, tree type, int levels, tree args,
|
|||
|
||||
tree
|
||||
process_template_parm (tree list, location_t parm_loc, tree parm,
|
||||
bool is_non_type, bool is_parameter_pack,
|
||||
unsigned num_template_parms)
|
||||
bool is_non_type, bool is_parameter_pack)
|
||||
{
|
||||
tree decl = 0;
|
||||
tree defval;
|
||||
|
@ -3615,7 +3608,6 @@ process_template_parm (tree list, location_t parm_loc, tree parm,
|
|||
DECL_INITIAL (parm) = DECL_INITIAL (decl)
|
||||
= build_template_parm_index (idx, processing_template_decl,
|
||||
processing_template_decl,
|
||||
num_template_parms,
|
||||
decl, TREE_TYPE (parm));
|
||||
|
||||
TEMPLATE_PARM_PARAMETER_PACK (DECL_INITIAL (parm))
|
||||
|
@ -3649,7 +3641,6 @@ process_template_parm (tree list, location_t parm_loc, tree parm,
|
|||
TEMPLATE_TYPE_PARM_INDEX (t)
|
||||
= build_template_parm_index (idx, processing_template_decl,
|
||||
processing_template_decl,
|
||||
num_template_parms,
|
||||
decl, TREE_TYPE (parm));
|
||||
TEMPLATE_TYPE_PARAMETER_PACK (t) = is_parameter_pack;
|
||||
TYPE_CANONICAL (t) = canonical_type_parameter (t);
|
||||
|
@ -3689,305 +3680,6 @@ end_template_parm_list (tree parms)
|
|||
return saved_parmlist;
|
||||
}
|
||||
|
||||
/* Create a new type almost identical to TYPE but which has the
|
||||
following differences:
|
||||
|
||||
1/ T has a new TEMPLATE_PARM_INDEX that carries the new number of
|
||||
template sibling parameters of T.
|
||||
|
||||
2/ T has a new canonical type that matches the new number
|
||||
of sibling parms.
|
||||
|
||||
3/ From now on, T is going to be what lookups referring to the
|
||||
name of TYPE will return. No lookup should return TYPE anymore.
|
||||
|
||||
NUM_PARMS is the new number of sibling parms TYPE belongs to.
|
||||
|
||||
This is a subroutine of fixup_template_parms. */
|
||||
|
||||
static tree
|
||||
fixup_template_type_parm_type (tree type, int num_parms)
|
||||
{
|
||||
tree orig_idx = TEMPLATE_TYPE_PARM_INDEX (type), idx;
|
||||
tree t;
|
||||
/* This is the decl which name is inserted into the symbol table for
|
||||
the template parm type. So whenever we lookup the type name, this
|
||||
is the DECL we get. */
|
||||
tree decl;
|
||||
|
||||
/* Do not fix up the type twice. */
|
||||
if (orig_idx && TEMPLATE_PARM_NUM_SIBLINGS (orig_idx) != 0)
|
||||
return type;
|
||||
|
||||
t = copy_type (type);
|
||||
decl = TYPE_NAME (t);
|
||||
|
||||
TYPE_MAIN_VARIANT (t) = t;
|
||||
TYPE_NEXT_VARIANT (t)= NULL_TREE;
|
||||
TYPE_POINTER_TO (t) = 0;
|
||||
TYPE_REFERENCE_TO (t) = 0;
|
||||
|
||||
idx = build_template_parm_index (TEMPLATE_PARM_IDX (orig_idx),
|
||||
TEMPLATE_PARM_LEVEL (orig_idx),
|
||||
TEMPLATE_PARM_ORIG_LEVEL (orig_idx),
|
||||
num_parms,
|
||||
decl, t);
|
||||
TEMPLATE_PARM_DESCENDANTS (idx) = TEMPLATE_PARM_DESCENDANTS (orig_idx);
|
||||
TEMPLATE_PARM_PARAMETER_PACK (idx) = TEMPLATE_PARM_PARAMETER_PACK (orig_idx);
|
||||
TEMPLATE_TYPE_PARM_INDEX (t) = idx;
|
||||
|
||||
TYPE_STUB_DECL (t) = decl;
|
||||
TEMPLATE_TYPE_DECL (t) = decl;
|
||||
if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM)
|
||||
TREE_TYPE (DECL_TEMPLATE_RESULT (decl)) = t;
|
||||
|
||||
/* Update the type associated to the type name stored in the symbol
|
||||
table. Now, whenever the type name is looked up, the resulting
|
||||
type is properly fixed up. */
|
||||
TREE_TYPE (decl) = t;
|
||||
|
||||
TYPE_CANONICAL (t) = canonical_type_parameter (t);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
/* Create and return a new TEMPLATE_PARM_INDEX that is almost
|
||||
identical to I, but that is fixed up as to:
|
||||
|
||||
1/ carry the number of sibling parms (NUM_PARMS) of the template
|
||||
parm represented by I.
|
||||
|
||||
2/ replace all references to template parm types declared before I
|
||||
(in the same template parm list as I) by references to template
|
||||
parm types contained in ARGS. ARGS should contain the list of
|
||||
template parms that have been fixed up so far, in a form suitable
|
||||
to be passed to tsubst.
|
||||
|
||||
This is a subroutine of fixup_template_parms. */
|
||||
|
||||
static tree
|
||||
fixup_template_parm_index (tree i, tree args, int num_parms)
|
||||
{
|
||||
tree index, decl, type;
|
||||
|
||||
if (i == NULL_TREE
|
||||
|| TREE_CODE (i) != TEMPLATE_PARM_INDEX
|
||||
/* Do not fix up the index twice. */
|
||||
|| (TEMPLATE_PARM_NUM_SIBLINGS (i) != 0))
|
||||
return i;
|
||||
|
||||
decl = TEMPLATE_PARM_DECL (i);
|
||||
type = TREE_TYPE (decl);
|
||||
|
||||
index = build_template_parm_index (TEMPLATE_PARM_IDX (i),
|
||||
TEMPLATE_PARM_LEVEL (i),
|
||||
TEMPLATE_PARM_ORIG_LEVEL (i),
|
||||
num_parms,
|
||||
decl, type);
|
||||
|
||||
TEMPLATE_PARM_DESCENDANTS (index) = TEMPLATE_PARM_DESCENDANTS (i);
|
||||
TEMPLATE_PARM_PARAMETER_PACK (index) = TEMPLATE_PARM_PARAMETER_PACK (i);
|
||||
|
||||
type = tsubst (type, args, tf_none, NULL_TREE);
|
||||
|
||||
TREE_TYPE (decl) = type;
|
||||
TREE_TYPE (index) = type;
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
/*
|
||||
This is a subroutine of fixup_template_parms.
|
||||
|
||||
It computes the canonical type of the type of the template
|
||||
parameter PARM_DESC and update all references to that type so that
|
||||
they use the newly computed canonical type. No access check is
|
||||
performed during the fixup. PARM_DESC is a TREE_LIST which
|
||||
TREE_VALUE is the template parameter and its TREE_PURPOSE is the
|
||||
default argument of the template parm if any. IDX is the index of
|
||||
the template parameter, starting at 0. NUM_PARMS is the number of
|
||||
template parameters in the set PARM_DESC belongs to. ARGLIST is a
|
||||
TREE_VEC containing the full set of template parameters in a form
|
||||
suitable to be passed to substs functions as their ARGS
|
||||
argument. This is what current_template_args returns for a given
|
||||
template. The innermost vector of args in ARGLIST is the set of
|
||||
template parms that have been fixed up so far. This function adds
|
||||
the fixed up parameter into that vector. */
|
||||
|
||||
static void
|
||||
fixup_template_parm (tree parm_desc,
|
||||
int idx,
|
||||
int num_parms,
|
||||
tree arglist)
|
||||
{
|
||||
tree parm = TREE_VALUE (parm_desc);
|
||||
tree fixedup_args = INNERMOST_TEMPLATE_ARGS (arglist);
|
||||
|
||||
push_deferring_access_checks (dk_no_check);
|
||||
|
||||
if (TREE_CODE (parm) == TYPE_DECL)
|
||||
{
|
||||
/* PARM is a template type parameter. Fix up its type, add
|
||||
the fixed-up template parm to the vector of fixed-up
|
||||
template parms so far, and substitute the fixed-up
|
||||
template parms into the default argument of this
|
||||
parameter. */
|
||||
tree t =
|
||||
fixup_template_type_parm_type (TREE_TYPE (parm), num_parms);
|
||||
TREE_TYPE (parm) = t;
|
||||
|
||||
TREE_VEC_ELT (fixedup_args, idx) = template_parm_to_arg (parm_desc);
|
||||
}
|
||||
else if (TREE_CODE (parm) == TEMPLATE_DECL)
|
||||
{
|
||||
/* PARM is a template template parameter. This is going to
|
||||
be interesting. */
|
||||
tree tparms, targs, innermost_args, t;
|
||||
int j;
|
||||
|
||||
/* First, fix up the parms of the template template parm
|
||||
because the parms are involved in defining the new canonical
|
||||
type of the template template parm. */
|
||||
|
||||
/* So we need to substitute the template parm types that have
|
||||
been fixed up so far into the template parms of this template
|
||||
template parm. E.g, consider this:
|
||||
|
||||
template<class T, template<T u> class TT> class S;
|
||||
|
||||
In this case we want to substitute T into the
|
||||
template parameters of TT.
|
||||
|
||||
So let's walk the template parms of PARM here, and
|
||||
tsubst ARGLIST into into each of the template
|
||||
parms. */
|
||||
|
||||
/* For this substitution we need to build the full set of
|
||||
template parameters and use that as arguments for the
|
||||
tsubsting function. */
|
||||
tparms = INNERMOST_TEMPLATE_PARMS (DECL_TEMPLATE_PARMS (parm));
|
||||
|
||||
/* This will contain the innermost parms of PARM into which
|
||||
we have substituted so far. */
|
||||
innermost_args = make_tree_vec (TREE_VEC_LENGTH (tparms));
|
||||
targs = add_to_template_args (arglist, innermost_args);
|
||||
for (j = 0; j < TREE_VEC_LENGTH (tparms); ++j)
|
||||
{
|
||||
tree parameter;
|
||||
|
||||
parameter = TREE_VEC_ELT (tparms, j);
|
||||
|
||||
/* INNERMOST_ARGS needs to have at least the same number
|
||||
of elements as the index PARAMETER, ortherwise
|
||||
tsubsting into PARAMETER will result in partially
|
||||
instantiating it, reducing its tempate parm
|
||||
level. Let's tactically fill INNERMOST_ARGS for that
|
||||
purpose. */
|
||||
TREE_VEC_ELT (innermost_args, j) =
|
||||
template_parm_to_arg (parameter);
|
||||
|
||||
fixup_template_parm (parameter, j,
|
||||
TREE_VEC_LENGTH (tparms),
|
||||
targs);
|
||||
}
|
||||
|
||||
/* Now fix up the type of the template template parm. */
|
||||
|
||||
t = fixup_template_type_parm_type (TREE_TYPE (parm), num_parms);
|
||||
TREE_TYPE (parm) = t;
|
||||
|
||||
TREE_VEC_ELT (fixedup_args, idx) =
|
||||
template_parm_to_arg (parm_desc);
|
||||
}
|
||||
else if (TREE_CODE (parm) == PARM_DECL)
|
||||
{
|
||||
/* PARM is a non-type template parameter. We need to:
|
||||
|
||||
* Fix up its TEMPLATE_PARM_INDEX to make it carry the
|
||||
proper number of sibling parameters.
|
||||
|
||||
* Make lookups of the template parameter return a reference
|
||||
to the fixed-up index. No lookup should return references
|
||||
to the former index anymore.
|
||||
|
||||
* Substitute the template parms that got fixed up so far
|
||||
|
||||
* into the type of PARM. */
|
||||
|
||||
tree index = DECL_INITIAL (parm);
|
||||
|
||||
/* PUSHED_DECL is the decl added to the symbol table with
|
||||
the name of the parameter. E,g:
|
||||
|
||||
template<class T, T u> //#0
|
||||
auto my_function(T t) -> decltype(u); //#1
|
||||
|
||||
Here, when looking up u at //#1, we get the decl of u
|
||||
resulting from the declaration in #0. This is what
|
||||
PUSHED_DECL is. We need to replace the reference to the
|
||||
old TEMPLATE_PARM_INDEX carried by PUSHED_DECL by the
|
||||
fixed-up TEMPLATE_PARM_INDEX. */
|
||||
tree pushed_decl = TEMPLATE_PARM_DECL (index);
|
||||
|
||||
/* Let's fix up the TEMPLATE_PARM_INDEX then. Note that we must
|
||||
fixup the type of PUSHED_DECL as well and luckily
|
||||
fixup_template_parm_index does it for us too. */
|
||||
tree fixed_up_index =
|
||||
fixup_template_parm_index (index, arglist, num_parms);
|
||||
|
||||
DECL_INITIAL (pushed_decl) = DECL_INITIAL (parm) = fixed_up_index;
|
||||
|
||||
/* Add this fixed up PARM to the template parms we've fixed
|
||||
up so far and use that to substitute the fixed-up
|
||||
template parms into the type of PARM. */
|
||||
TREE_VEC_ELT (fixedup_args, idx) =
|
||||
template_parm_to_arg (parm_desc);
|
||||
TREE_TYPE (parm) = tsubst (TREE_TYPE (parm), arglist,
|
||||
tf_none, NULL_TREE);
|
||||
}
|
||||
|
||||
TREE_PURPOSE (parm_desc) =
|
||||
tsubst_template_arg (TREE_PURPOSE (parm_desc),
|
||||
arglist, tf_none, parm);
|
||||
|
||||
pop_deferring_access_checks ();
|
||||
}
|
||||
|
||||
/* Walk the current template parms and properly compute the canonical
|
||||
types of the dependent types created during
|
||||
cp_parser_template_parameter_list. */
|
||||
|
||||
void
|
||||
fixup_template_parms (void)
|
||||
{
|
||||
tree arglist;
|
||||
tree parameter_vec;
|
||||
tree fixedup_args;
|
||||
int i, num_parms;
|
||||
|
||||
parameter_vec = INNERMOST_TEMPLATE_PARMS (current_template_parms);
|
||||
if (parameter_vec == NULL_TREE)
|
||||
return;
|
||||
|
||||
num_parms = TREE_VEC_LENGTH (parameter_vec);
|
||||
|
||||
/* This vector contains the current innermost template parms that
|
||||
have been fixed up so far. The form of FIXEDUP_ARGS is suitable
|
||||
to be passed to tsubst* functions as their ARGS argument. */
|
||||
fixedup_args = make_tree_vec (num_parms);
|
||||
|
||||
/* This vector contains the full set of template parms in a form
|
||||
suitable to be passed to substs functions as their ARGS
|
||||
argument. */
|
||||
arglist = current_template_args ();
|
||||
arglist = add_outermost_template_args (arglist, fixedup_args);
|
||||
|
||||
/* Let's do the proper fixup now. */
|
||||
for (i = 0; i < num_parms; ++i)
|
||||
fixup_template_parm (TREE_VEC_ELT (parameter_vec, i),
|
||||
i, num_parms, arglist);
|
||||
}
|
||||
|
||||
/* end_template_decl is called after a template declaration is seen. */
|
||||
|
||||
void
|
||||
|
@ -4091,34 +3783,13 @@ arg_from_parm_pack_p (tree arg_pack, tree parm_pack)
|
|||
{
|
||||
tree expansion = TREE_VEC_ELT (ARGUMENT_PACK_ARGS (arg_pack), 0);
|
||||
tree pattern = PACK_EXPANSION_PATTERN (expansion);
|
||||
/* So we have an argument_pack<P...>. We want to test if P
|
||||
is actually PARM_PACK. We will not use cp_tree_equal to
|
||||
test P and PARM_PACK because during type fixup (by
|
||||
fixup_template_parm) P can be a pre-fixup version of a
|
||||
type and PARM_PACK be its post-fixup version.
|
||||
cp_tree_equal would consider them as different even
|
||||
though we would want to consider them compatible for our
|
||||
precise purpose here.
|
||||
|
||||
Thus we are going to consider that P and PARM_PACK are
|
||||
compatible if they have the same DECL. */
|
||||
if ((/* If ARG_PACK is a type parameter pack named by the
|
||||
same DECL as parm_pack ... */
|
||||
(TYPE_P (pattern)
|
||||
&& TYPE_P (parm_pack)
|
||||
&& TYPE_NAME (pattern) == TYPE_NAME (parm_pack))
|
||||
/* ... or if PARM_PACK is a non-type parameter named by the
|
||||
same DECL as ARG_PACK. Note that PARM_PACK being a
|
||||
non-type parameter means it's either a PARM_DECL or a
|
||||
TEMPLATE_PARM_INDEX. */
|
||||
|| (TREE_CODE (pattern) == TEMPLATE_PARM_INDEX
|
||||
&& ((TREE_CODE (parm_pack) == PARM_DECL
|
||||
&& (TEMPLATE_PARM_DECL (pattern)
|
||||
== TEMPLATE_PARM_DECL (DECL_INITIAL (parm_pack))))
|
||||
|| (TREE_CODE (parm_pack) == TEMPLATE_PARM_INDEX
|
||||
&& (TEMPLATE_PARM_DECL (pattern)
|
||||
== TEMPLATE_PARM_DECL (parm_pack))))))
|
||||
&& template_parameter_pack_p (pattern))
|
||||
if ((TYPE_P (pattern) && same_type_p (pattern, parm_pack))
|
||||
|| (!TYPE_P (pattern) && cp_tree_equal (parm_pack, pattern)))
|
||||
/* The argument pack that the parameter maps to is just an
|
||||
expansion of the parameter itself, such as one would
|
||||
find in the implicit typedef of a class inside the
|
||||
class itself. Consider this parameter "unsubstituted",
|
||||
so that we will maintain the outer pack expansion. */
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -6609,7 +6280,7 @@ convert_template_argument (tree parm,
|
|||
argument specification is valid. */
|
||||
val = convert_nontype_argument (t, orig_arg, complain);
|
||||
else
|
||||
val = orig_arg;
|
||||
val = strip_typedefs_expr (orig_arg);
|
||||
|
||||
if (val == NULL_TREE)
|
||||
val = error_mark_node;
|
||||
|
@ -16592,6 +16263,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict,
|
|||
&& !TEMPLATE_PARM_PARAMETER_PACK (parm))
|
||||
return unify_parameter_pack_mismatch (explain_p, parm, arg);
|
||||
|
||||
arg = strip_typedefs_expr (arg);
|
||||
TREE_VEC_ELT (INNERMOST_TEMPLATE_ARGS (targs), idx) = arg;
|
||||
return unify_success (explain_p);
|
||||
|
||||
|
@ -20325,7 +19997,7 @@ make_auto (void)
|
|||
TYPE_STUB_DECL (au) = TYPE_NAME (au);
|
||||
TEMPLATE_TYPE_PARM_INDEX (au) = build_template_parm_index
|
||||
(0, processing_template_decl + 1, processing_template_decl + 1,
|
||||
0, TYPE_NAME (au), NULL_TREE);
|
||||
TYPE_NAME (au), NULL_TREE);
|
||||
TYPE_CANONICAL (au) = canonical_type_parameter (au);
|
||||
DECL_ARTIFICIAL (TYPE_NAME (au)) = 1;
|
||||
SET_DECL_TEMPLATE_PARM_P (TYPE_NAME (au));
|
||||
|
|
195
gcc/cp/tree.c
195
gcc/cp/tree.c
|
@ -1097,7 +1097,7 @@ cv_unqualified (tree type)
|
|||
* If T is a type that needs structural equality
|
||||
its TYPE_CANONICAL (T) will be NULL.
|
||||
* TYPE_CANONICAL (T) desn't carry type attributes
|
||||
and looses template parameter names. */
|
||||
and loses template parameter names. */
|
||||
|
||||
tree
|
||||
strip_typedefs (tree t)
|
||||
|
@ -1187,6 +1187,16 @@ strip_typedefs (tree t)
|
|||
TYPENAME_TYPE_FULLNAME (t),
|
||||
typename_type, tf_none);
|
||||
break;
|
||||
case DECLTYPE_TYPE:
|
||||
result = strip_typedefs_expr (DECLTYPE_TYPE_EXPR (t));
|
||||
if (result == DECLTYPE_TYPE_EXPR (t))
|
||||
return t;
|
||||
else
|
||||
result = (finish_decltype_type
|
||||
(result,
|
||||
DECLTYPE_TYPE_ID_EXPR_OR_MEMBER_ACCESS_P (t),
|
||||
tf_none));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1208,6 +1218,186 @@ strip_typedefs (tree t)
|
|||
return cp_build_qualified_type (result, cp_type_quals (t));
|
||||
}
|
||||
|
||||
/* Like strip_typedefs above, but works on expressions, so that in
|
||||
|
||||
template<class T> struct A
|
||||
{
|
||||
typedef T TT;
|
||||
B<sizeof(TT)> b;
|
||||
};
|
||||
|
||||
sizeof(TT) is replaced by sizeof(T). */
|
||||
|
||||
tree
|
||||
strip_typedefs_expr (tree t)
|
||||
{
|
||||
unsigned i,n;
|
||||
tree r, type, *ops;
|
||||
enum tree_code code;
|
||||
|
||||
if (t == NULL_TREE || t == error_mark_node)
|
||||
return t;
|
||||
|
||||
if (DECL_P (t) || CONSTANT_CLASS_P (t))
|
||||
return t;
|
||||
|
||||
/* Some expressions have type operands, so let's handle types here rather
|
||||
than check TYPE_P in multiple places below. */
|
||||
if (TYPE_P (t))
|
||||
return strip_typedefs (t);
|
||||
|
||||
code = TREE_CODE (t);
|
||||
switch (code)
|
||||
{
|
||||
case IDENTIFIER_NODE:
|
||||
case TEMPLATE_PARM_INDEX:
|
||||
case OVERLOAD:
|
||||
case BASELINK:
|
||||
case ARGUMENT_PACK_SELECT:
|
||||
return t;
|
||||
|
||||
case TRAIT_EXPR:
|
||||
{
|
||||
tree type1 = strip_typedefs (TRAIT_EXPR_TYPE1 (t));
|
||||
tree type2 = strip_typedefs (TRAIT_EXPR_TYPE2 (t));
|
||||
if (type1 == TRAIT_EXPR_TYPE1 (t)
|
||||
&& type2 == TRAIT_EXPR_TYPE2 (t))
|
||||
return t;
|
||||
r = copy_node (t);
|
||||
TRAIT_EXPR_TYPE1 (t) = type1;
|
||||
TRAIT_EXPR_TYPE2 (t) = type2;
|
||||
return r;
|
||||
}
|
||||
|
||||
case TREE_LIST:
|
||||
{
|
||||
VEC(tree,gc) *vec = make_tree_vector ();
|
||||
bool changed = false;
|
||||
tree it;
|
||||
for (it = t; it; it = TREE_CHAIN (it))
|
||||
{
|
||||
tree val = strip_typedefs_expr (TREE_VALUE (t));
|
||||
VEC_safe_push (tree, gc, vec, val);
|
||||
if (val != TREE_VALUE (t))
|
||||
changed = true;
|
||||
gcc_assert (TREE_PURPOSE (it) == NULL_TREE);
|
||||
}
|
||||
if (changed)
|
||||
{
|
||||
r = NULL_TREE;
|
||||
FOR_EACH_VEC_ELT_REVERSE (tree, vec, i, it)
|
||||
r = tree_cons (NULL_TREE, it, r);
|
||||
}
|
||||
else
|
||||
r = t;
|
||||
release_tree_vector (vec);
|
||||
return r;
|
||||
}
|
||||
|
||||
case TREE_VEC:
|
||||
{
|
||||
bool changed = false;
|
||||
VEC(tree,gc)* vec = make_tree_vector ();
|
||||
n = TREE_VEC_LENGTH (t);
|
||||
VEC_reserve (tree, gc, vec, n);
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
tree op = strip_typedefs_expr (TREE_VEC_ELT (t, i));
|
||||
VEC_quick_push (tree, vec, op);
|
||||
if (op != TREE_VEC_ELT (t, i))
|
||||
changed = true;
|
||||
}
|
||||
if (changed)
|
||||
{
|
||||
r = copy_node (t);
|
||||
for (i = 0; i < n; ++i)
|
||||
TREE_VEC_ELT (r, i) = VEC_index (tree, vec, i);
|
||||
}
|
||||
else
|
||||
r = t;
|
||||
release_tree_vector (vec);
|
||||
return r;
|
||||
}
|
||||
|
||||
case CONSTRUCTOR:
|
||||
{
|
||||
bool changed = false;
|
||||
VEC(constructor_elt,gc) *vec
|
||||
= VEC_copy (constructor_elt, gc, CONSTRUCTOR_ELTS (t));
|
||||
n = CONSTRUCTOR_NELTS (t);
|
||||
type = strip_typedefs (TREE_TYPE (t));
|
||||
for (i = 0; i < n; ++i)
|
||||
{
|
||||
constructor_elt *e = VEC_index (constructor_elt, vec, i);
|
||||
tree op = strip_typedefs_expr (e->value);
|
||||
if (op != e->value)
|
||||
{
|
||||
changed = true;
|
||||
e->value = op;
|
||||
}
|
||||
gcc_checking_assert (e->index == strip_typedefs_expr (e->index));
|
||||
}
|
||||
|
||||
if (!changed && type == TREE_TYPE (t))
|
||||
{
|
||||
VEC_free (constructor_elt, gc, vec);
|
||||
return t;
|
||||
}
|
||||
else
|
||||
{
|
||||
r = copy_node (t);
|
||||
TREE_TYPE (r) = type;
|
||||
CONSTRUCTOR_ELTS (r) = vec;
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
||||
case LAMBDA_EXPR:
|
||||
gcc_unreachable ();
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
gcc_assert (EXPR_P (t));
|
||||
|
||||
n = TREE_OPERAND_LENGTH (t);
|
||||
ops = XALLOCAVEC (tree, n);
|
||||
type = TREE_TYPE (t);
|
||||
|
||||
switch (code)
|
||||
{
|
||||
CASE_CONVERT:
|
||||
case IMPLICIT_CONV_EXPR:
|
||||
case DYNAMIC_CAST_EXPR:
|
||||
case STATIC_CAST_EXPR:
|
||||
case CONST_CAST_EXPR:
|
||||
case REINTERPRET_CAST_EXPR:
|
||||
case CAST_EXPR:
|
||||
case NEW_EXPR:
|
||||
type = strip_typedefs (type);
|
||||
/* fallthrough */
|
||||
|
||||
default:
|
||||
for (i = 0; i < n; ++i)
|
||||
ops[i] = strip_typedefs_expr (TREE_OPERAND (t, i));
|
||||
break;
|
||||
}
|
||||
|
||||
/* If nothing changed, return t. */
|
||||
for (i = 0; i < n; ++i)
|
||||
if (ops[i] != TREE_OPERAND (t, i))
|
||||
break;
|
||||
if (i == n && type == TREE_TYPE (t))
|
||||
return t;
|
||||
|
||||
r = copy_node (t);
|
||||
TREE_TYPE (r) = type;
|
||||
for (i = 0; i < n; ++i)
|
||||
TREE_OPERAND (r, i) = ops[i];
|
||||
return r;
|
||||
}
|
||||
|
||||
/* Makes a copy of BINFO and TYPE, which is to be inherited into a
|
||||
graph dominated by T. If BINFO is NULL, TYPE is a dependent base,
|
||||
and we do a shallow copy. If BINFO is non-NULL, we do a deep copy.
|
||||
|
@ -2381,9 +2571,6 @@ cp_tree_equal (tree t1, tree t2)
|
|||
BASELINK_FUNCTIONS (t2)));
|
||||
|
||||
case TEMPLATE_PARM_INDEX:
|
||||
if (TEMPLATE_PARM_NUM_SIBLINGS (t1)
|
||||
!= TEMPLATE_PARM_NUM_SIBLINGS (t2))
|
||||
return false;
|
||||
return (TEMPLATE_PARM_IDX (t1) == TEMPLATE_PARM_IDX (t2)
|
||||
&& TEMPLATE_PARM_LEVEL (t1) == TEMPLATE_PARM_LEVEL (t2)
|
||||
&& (TEMPLATE_PARM_PARAMETER_PACK (t1)
|
||||
|
|
|
@ -1137,12 +1137,6 @@ comp_template_parms_position (tree t1, tree t2)
|
|||
index1 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t1));
|
||||
index2 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t2));
|
||||
|
||||
/* If T1 and T2 belong to template parm lists of different size,
|
||||
let's assume they are different. */
|
||||
if (TEMPLATE_PARM_NUM_SIBLINGS (index1)
|
||||
!= TEMPLATE_PARM_NUM_SIBLINGS (index2))
|
||||
return false;
|
||||
|
||||
/* Then compare their relative position. */
|
||||
if (TEMPLATE_PARM_IDX (index1) != TEMPLATE_PARM_IDX (index2)
|
||||
|| TEMPLATE_PARM_LEVEL (index1) != TEMPLATE_PARM_LEVEL (index2)
|
||||
|
|
|
@ -1,3 +1,15 @@
|
|||
2012-11-29 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/53858
|
||||
* g++.dg/cpp0x/alias-decl-20.C: New.
|
||||
|
||||
PR c++/50852
|
||||
* g++.dg/template/typedef39.C: New.
|
||||
|
||||
PR c++/53039
|
||||
* g++.dg/cpp0x/variadic133.C: New.
|
||||
* g++.dg/template/param1.C: Adjust.
|
||||
|
||||
2012-11-27 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR middle-end/55331
|
||||
|
|
|
@ -0,0 +1,9 @@
|
|||
// PR c++/53858
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
template <typename T> struct s0 { typedef T tdef0; };
|
||||
template <typename T> struct s1 { typedef T tdef1; };
|
||||
template <typename T> using us1 = typename s1<T>::tdef1;
|
||||
template <typename T, typename TT = typename us1<T>::tdef0> struct s2 {};
|
||||
|
||||
int main () { return 0; }
|
|
@ -0,0 +1,46 @@
|
|||
// PR c++/53039
|
||||
// { dg-do compile { target c++11 } }
|
||||
|
||||
template <class, class>
|
||||
struct is_convertible
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<bool, class T>
|
||||
struct enable_if
|
||||
{
|
||||
typedef T type;
|
||||
};
|
||||
|
||||
template <bool...>
|
||||
struct Xs
|
||||
{
|
||||
static const bool value = true;
|
||||
};
|
||||
|
||||
template<typename... BTs>
|
||||
class BType
|
||||
{
|
||||
template <typename... BUs,
|
||||
typename enable_if<
|
||||
Xs<is_convertible<BUs, BTs>::value...>::value,
|
||||
bool>::type = false>
|
||||
void fooX(BUs&&...);
|
||||
};
|
||||
|
||||
template <typename... ATs>
|
||||
struct AType
|
||||
{
|
||||
template <typename... AUs,
|
||||
typename enable_if<
|
||||
Xs<is_convertible<AUs, ATs>::value...>::value,
|
||||
bool>::type = false>
|
||||
void foo(AUs&&...);
|
||||
};
|
||||
|
||||
int main()
|
||||
{
|
||||
AType<int, int> t;
|
||||
t.foo(1, 1);
|
||||
}
|
|
@ -2,11 +2,11 @@
|
|||
// Origin: Volker Reichelt <reichelt@igpm.rwth-aachen.de>
|
||||
// { dg-do compile }
|
||||
|
||||
template<int> struct A // { dg-error "declaration" }
|
||||
template<int> struct A
|
||||
{
|
||||
A();
|
||||
};
|
||||
|
||||
template<int N, char> A<N>::A() {} // { dg-error "invalid use of incomplete type" }
|
||||
template<int N, char> A<N>::A() {} // { dg-error "got 2 template parameters|1 required" }
|
||||
|
||||
A<0> a;
|
||||
|
|
|
@ -0,0 +1,15 @@
|
|||
// PR c++/50852
|
||||
|
||||
template<int d> class A;
|
||||
template<class T> struct B {typedef int K;typedef int L;};
|
||||
template<class U,class V> struct C
|
||||
{
|
||||
typedef typename U::L X;
|
||||
typedef A<X::a-1> W;
|
||||
};
|
||||
template<class U,int d> struct D
|
||||
{
|
||||
typedef typename U::L X;
|
||||
typedef A<X::a-1> W; // { dg-error "not a member" }
|
||||
};
|
||||
template class D<B<A<1> >,3>;
|
Loading…
Reference in New Issue