Commit 6f1abb06 by Dodji Seketeli Committed by Dodji Seketeli

Restore canonical type comparison for dependent type(def)s

This patch restores canonical type comparison for dependent types and
then dependent typedefs. After this patch, two template type
parameters T are equal if they have the same index, level, *and*
number of sibling parameters. The novelty is to take in account the
number of sibling parameters.

To do this we first build the template parameters w/o taking in
account their number of siblings. When we know the number of template
parameters we fix up each template parameter with the number of
slibling parameters and we build the appropriate canonical types
accordingly. The patch fixes the fallouts deemed necessary.

This fixes PR c++/45606 but actually fixes all the previous bugs
related to dependent typedef comparison we had since we started to
properly representing dependent typedefs.

gcc/cp/ChangeLog:
	PR c++/45606
	* cp-tree.h (TEMPLATE_TYPE_PARM_SIBLING_PARMS): Remove.
	(struct template_parm_index_s)<num_siblings>: New field.
	(TEMPLATE_PARM_NUM_SIBLINGS): New accessor.
	(process_template_parm): Extend the API to accept the number of
	template parms in argument.
	(cp_set_underlying_type): Remove this.
	* class.c (build_self_reference): Require canonical type equality
	back on the self reference of class.
	* decl2.c (grokfield): Require canonical type equality back on
	typedef class fields.
	* name-lookup.c (pushdecl_maybe_friend): Require canonical type
	equality back on typedefs.
	* parser.c (cp_parser_template_parameter_list): Do not require
	canonical type equality on dependent types created during
	template parameters parsing.
	* pt.c (fixup_template_type_parm_type, fixup_template_parm_index)
	(fixup_template_parm, fixup_template_parms): New private
	functions.
	(current_template_args): Declare this.
	(process_template_parm): Pass the total number of template parms
	to canonical_type_parameter.
	(build_template_parm_index): Add a new argument to carry the total
	number of template parms.
	(reduce_template_parm_level, process_template_parm, make_auto): Adjust.
	(current_template_args): Fix this for template template
	parameters.
	(tsubst_template_parm): Split out of ...
	(tsubst_template_parms): ... this.
	(reduce_template_parm_level): Don't loose
	TEMPLATE_PARM_NUM_SIBLINGS when cloning a TEMPLATE_PARM_INDEX.
	(template_parm_to_arg): Extracted this function from
	current_template_args. Make it represent invalid template parms
	with an error_mark_node instead of a LIST_TREE containing an
	error_mark_node.
	(current_template_args): Use template_parm_to_arg.
	(dependent_template_arg_p): Consider an invalid template argument
	as dependent.
	(end_template_parm_list): Do not update template sibling parms
	here anymore. Use fixup_template_parms instead.
	(process_template_parm): Pass the number of template parms to
	canonical_type_parameter.
	(make_auto): Require structural equality on auto
	TEMPLATE_TYPE_PARM for now.
	(unify)<BOUND_TEMPLATE_TEMPLATE_PARM>: Coerce template parameters
	using all the arguments deduced so far.
	(tsubst)<TEMPLATE_TYPE_PARM>: Pass the number of sibling parms to
	canonical_type_parameter.
	* tree.c (cp_set_underlying_type): Remove.
	* typeck.c (get_template_parms_of_dependent_type)
	(incompatible_dependent_types_p): Remove.
	(structural_comptypes): Do not call incompatible_dependent_types_p
	anymore.
	(comp_template_parms_position): Re-organized. Take the length of
	template parms list in account.

gcc/testsuite/ChangeLog:
	PR c++/45606
	* g++.dg/template/typedef36.C: New test.
	* gcc/testsuite/g++.dg/template/canon-type-9.C: Likewise.
	* g++.dg/template/canon-type-10.C: Likewise.
	* g++.dg/template/canon-type-11.C: Likewise.
	* g++.dg/template/canon-type-12.C: Likewise.
	* g++.dg/template/canon-type-13.C: Likewise.

From-SVN: r166179
parent 9d8477b6
2010-11-02 Dodji Seketeli <dodji@redhat.com>
PR c++/45606
* cp-tree.h (TEMPLATE_TYPE_PARM_SIBLING_PARMS): Remove.
(struct template_parm_index_s)<num_siblings>: New field.
(TEMPLATE_PARM_NUM_SIBLINGS): New accessor.
(process_template_parm): Extend the API to accept the number of
template parms in argument.
(cp_set_underlying_type): Remove this.
* class.c (build_self_reference): Require canonical type equality
back on the self reference of class.
* decl2.c (grokfield): Require canonical type equality back on
typedef class fields.
* name-lookup.c (pushdecl_maybe_friend): Require canonical type
equality back on typedefs.
* parser.c (cp_parser_template_parameter_list): Do not require
canonical type equality on dependent types created during template
parameters parsing.
* pt.c (fixup_template_type_parm_type, fixup_template_parm_index)
(fixup_template_parm, fixup_template_parms): New private
functions.
(current_template_args): Declare this.
(process_template_parm): Pass the total number of template parms
to canonical_type_parameter.
(build_template_parm_index): Add a new argument to carry the total
number of template parms.
(reduce_template_parm_level, process_template_parm, make_auto):
Adjust.
(current_template_args): Fix this for template template
parameters.
(tsubst_template_parm): Split out of ...
(tsubst_template_parms): ... this.
(reduce_template_parm_level): Don't loose
TEMPLATE_PARM_NUM_SIBLINGS when cloning a TEMPLATE_PARM_INDEX.
(template_parm_to_arg): Extracted this function from
current_template_args. Make it represent invalid template parms
with an error_mark_node instead of a LIST_TREE containing an
error_mark_node.
(current_template_args): Use template_parm_to_arg.
(dependent_template_arg_p): Consider an invalid template argument
as dependent.
(end_template_parm_list): Do not update template sibling parms
here anymore. Use fixup_template_parms instead.
(process_template_parm): Pass the number of template parms to
canonical_type_parameter.
(make_auto): Require structural equality on auto
TEMPLATE_TYPE_PARM for now.
(unify)<BOUND_TEMPLATE_TEMPLATE_PARM>: Coerce template parameters
using all the arguments deduced so far.
(tsubst)<TEMPLATE_TYPE_PARM>: Pass the number of sibling parms to
canonical_type_parameter.
* tree.c (cp_set_underlying_type): Remove.
* typeck.c (get_template_parms_of_dependent_type)
(incompatible_dependent_types_p): Remove.
(structural_comptypes): Do not call incompatible_dependent_types_p
anymore.
(comp_template_parms_position): Re-organized. Take the length of
template parms list in account.
2010-11-01 Jason Merrill <jason@redhat.com> 2010-11-01 Jason Merrill <jason@redhat.com>
* semantics.c (call_stack, call_stack_tick, cx_error_context): New. * semantics.c (call_stack, call_stack_tick, cx_error_context): New.
......
...@@ -6768,7 +6768,7 @@ build_self_reference (void) ...@@ -6768,7 +6768,7 @@ build_self_reference (void)
DECL_CONTEXT (value) = current_class_type; DECL_CONTEXT (value) = current_class_type;
DECL_ARTIFICIAL (value) = 1; DECL_ARTIFICIAL (value) = 1;
SET_DECL_SELF_REFERENCE_P (value); SET_DECL_SELF_REFERENCE_P (value);
cp_set_underlying_type (value); set_underlying_type (value);
if (processing_template_decl) if (processing_template_decl)
value = push_template_decl (value); value = push_template_decl (value);
......
...@@ -236,6 +236,7 @@ struct GTY(()) template_parm_index_s { ...@@ -236,6 +236,7 @@ struct GTY(()) template_parm_index_s {
int index; int index;
int level; int level;
int orig_level; int orig_level;
int num_siblings;
tree decl; tree decl;
}; };
typedef struct template_parm_index_s template_parm_index; typedef struct template_parm_index_s template_parm_index;
...@@ -4310,6 +4311,9 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG }; ...@@ -4310,6 +4311,9 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
((template_parm_index*)TEMPLATE_PARM_INDEX_CHECK (NODE)) ((template_parm_index*)TEMPLATE_PARM_INDEX_CHECK (NODE))
#define TEMPLATE_PARM_IDX(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->index) #define TEMPLATE_PARM_IDX(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->index)
#define TEMPLATE_PARM_LEVEL(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->level) #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_DESCENDANTS(NODE) (TREE_CHAIN (NODE))
#define TEMPLATE_PARM_ORIG_LEVEL(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->orig_level) #define TEMPLATE_PARM_ORIG_LEVEL(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->orig_level)
#define TEMPLATE_PARM_DECL(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->decl) #define TEMPLATE_PARM_DECL(NODE) (TEMPLATE_PARM_INDEX_CAST (NODE)->decl)
...@@ -4331,10 +4335,6 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG }; ...@@ -4331,10 +4335,6 @@ enum overload_flags { NO_SPECIAL = 0, DTOR_FLAG, TYPENAME_FLAG };
(TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE))) (TEMPLATE_PARM_DECL (TEMPLATE_TYPE_PARM_INDEX (NODE)))
#define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \ #define TEMPLATE_TYPE_PARAMETER_PACK(NODE) \
(TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE))) (TEMPLATE_PARM_PARAMETER_PACK (TEMPLATE_TYPE_PARM_INDEX (NODE)))
/* The list of template parms that a given template parameter of type
TEMPLATE_TYPE_PARM belongs to.*/
#define TEMPLATE_TYPE_PARM_SIBLING_PARMS(NODE) \
(TREE_CHECK ((NODE), TEMPLATE_TYPE_PARM))->type.maxval
/* These constants can used as bit flags in the process of tree formatting. /* These constants can used as bit flags in the process of tree formatting.
...@@ -5022,7 +5022,7 @@ extern void append_type_to_template_for_access_check (tree, tree, tree, ...@@ -5022,7 +5022,7 @@ extern void append_type_to_template_for_access_check (tree, tree, tree,
extern tree splice_late_return_type (tree, tree); extern tree splice_late_return_type (tree, tree);
extern bool is_auto (const_tree); extern bool is_auto (const_tree);
extern tree process_template_parm (tree, location_t, tree, extern tree process_template_parm (tree, location_t, tree,
bool, bool); bool, bool, unsigned);
extern tree end_template_parm_list (tree); extern tree end_template_parm_list (tree);
extern void end_template_decl (void); extern void end_template_decl (void);
extern tree maybe_update_decl_type (tree, tree); extern tree maybe_update_decl_type (tree, tree);
...@@ -5366,7 +5366,6 @@ extern bool type_has_nontrivial_copy_init (const_tree); ...@@ -5366,7 +5366,6 @@ extern bool type_has_nontrivial_copy_init (const_tree);
extern bool class_tmpl_impl_spec_p (const_tree); extern bool class_tmpl_impl_spec_p (const_tree);
extern int zero_init_p (const_tree); extern int zero_init_p (const_tree);
extern tree strip_typedefs (tree); extern tree strip_typedefs (tree);
extern void cp_set_underlying_type (tree);
extern tree copy_binfo (tree, tree, tree, extern tree copy_binfo (tree, tree, tree,
tree *, int); tree *, int);
extern int member_p (const_tree); extern int member_p (const_tree);
......
...@@ -864,7 +864,7 @@ grokfield (const cp_declarator *declarator, ...@@ -864,7 +864,7 @@ grokfield (const cp_declarator *declarator,
if (declspecs->specs[(int)ds_typedef] if (declspecs->specs[(int)ds_typedef]
&& TREE_TYPE (value) != error_mark_node && TREE_TYPE (value) != error_mark_node
&& TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value) && TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
cp_set_underlying_type (value); set_underlying_type (value);
return value; return value;
} }
......
...@@ -872,7 +872,7 @@ pushdecl_maybe_friend (tree x, bool is_friend) ...@@ -872,7 +872,7 @@ pushdecl_maybe_friend (tree x, bool is_friend)
inlining. */ inlining. */
&& (!TYPE_NAME (type) && (!TYPE_NAME (type)
|| TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x)))) || TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
cp_set_underlying_type (x); set_underlying_type (x);
if (type != error_mark_node if (type != error_mark_node
&& TYPE_NAME (type) && TYPE_NAME (type)
......
...@@ -11045,6 +11045,13 @@ cp_parser_template_parameter_list (cp_parser* parser) ...@@ -11045,6 +11045,13 @@ cp_parser_template_parameter_list (cp_parser* parser)
tree parameter_list = NULL_TREE; tree parameter_list = NULL_TREE;
begin_template_parm_list (); begin_template_parm_list ();
/* The loop below parses the template parms. We first need to know
the total number of template parms to be able to compute proper
canonical types of each dependent type. So after the loop, when
we know the total number of template parms,
end_template_parm_list computes the proper canonical types and
fixes up the dependent types accordingly. */
while (true) while (true)
{ {
tree parameter; tree parameter;
...@@ -11063,11 +11070,11 @@ cp_parser_template_parameter_list (cp_parser* parser) ...@@ -11063,11 +11070,11 @@ cp_parser_template_parameter_list (cp_parser* parser)
parm_loc, parm_loc,
parameter, parameter,
is_non_type, is_non_type,
is_parameter_pack); is_parameter_pack,
0);
else else
{ {
tree err_parm = build_tree_list (parameter, parameter); tree err_parm = build_tree_list (parameter, parameter);
TREE_VALUE (err_parm) = error_mark_node;
parameter_list = chainon (parameter_list, err_parm); parameter_list = chainon (parameter_list, err_parm);
} }
......
...@@ -1096,22 +1096,6 @@ strip_typedefs (tree t) ...@@ -1096,22 +1096,6 @@ strip_typedefs (tree t)
return cp_build_qualified_type (result, cp_type_quals (t)); return cp_build_qualified_type (result, cp_type_quals (t));
} }
/* Setup a TYPE_DECL node as a typedef representation.
See comments of set_underlying_type in c-common.c. */
void
cp_set_underlying_type (tree t)
{
set_underlying_type (t);
/* If T is a template type parm, make it require structural equality.
This is useful when comparing two template type parms,
because it forces the comparison of the template parameters of their
decls. */
if (TREE_CODE (TREE_TYPE (t)) == TEMPLATE_TYPE_PARM)
SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (t));
}
/* Makes a copy of BINFO and TYPE, which is to be inherited into a /* 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, 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. and we do a shallow copy. If BINFO is non-NULL, we do a deep copy.
......
...@@ -1143,120 +1143,30 @@ comp_array_types (const_tree t1, const_tree t2, bool allow_redeclaration) ...@@ -1143,120 +1143,30 @@ comp_array_types (const_tree t1, const_tree t2, bool allow_redeclaration)
static bool static bool
comp_template_parms_position (tree t1, tree t2) comp_template_parms_position (tree t1, tree t2)
{ {
tree index1, index2;
gcc_assert (t1 && t2 gcc_assert (t1 && t2
&& TREE_CODE (t1) == TREE_CODE (t2) && TREE_CODE (t1) == TREE_CODE (t2)
&& (TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM && (TREE_CODE (t1) == BOUND_TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM || TREE_CODE (t1) == TEMPLATE_TEMPLATE_PARM
|| TREE_CODE (t1) == TEMPLATE_TYPE_PARM)); || TREE_CODE (t1) == TEMPLATE_TYPE_PARM));
if (TEMPLATE_TYPE_IDX (t1) != TEMPLATE_TYPE_IDX (t2) index1 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t1));
|| TEMPLATE_TYPE_LEVEL (t1) != TEMPLATE_TYPE_LEVEL (t2) index2 = TEMPLATE_TYPE_PARM_INDEX (TYPE_MAIN_VARIANT (t2));
|| (TEMPLATE_TYPE_PARAMETER_PACK (t1)
!= TEMPLATE_TYPE_PARAMETER_PACK (t2)))
return false;
return true;
}
/* Subroutine of incompatible_dependent_types_p.
Return the template parameter of the dependent type T.
If T is a typedef, return the template parameters of
the _decl_ of the typedef. T must be a dependent type. */
static tree
get_template_parms_of_dependent_type (tree t)
{
tree tinfo = NULL_TREE, tparms = NULL_TREE;
/* First, try the obvious case of getting the
template info from T itself. */
if ((tinfo = get_template_info (t)))
;
else if (TREE_CODE (t) == TEMPLATE_TYPE_PARM)
return TEMPLATE_TYPE_PARM_SIBLING_PARMS (t);
else if (typedef_variant_p (t)
&& !NAMESPACE_SCOPE_P (TYPE_NAME (t)))
tinfo = get_template_info (DECL_CONTEXT (TYPE_NAME (t)));
/* If T is a TYPENAME_TYPE which context is a template type
parameter, get the template parameters from that context. */
else if (TYPE_CONTEXT (t)
&& TREE_CODE (TYPE_CONTEXT (t)) == TEMPLATE_TYPE_PARM)
return TEMPLATE_TYPE_PARM_SIBLING_PARMS (TYPE_CONTEXT (t));
else if (TYPE_CONTEXT (t)
&& !NAMESPACE_SCOPE_P (t))
tinfo = get_template_info (TYPE_CONTEXT (t));
if (tinfo)
tparms = DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo));
return tparms;
}
/* Subroutine of structural_comptypes.
Compare the dependent types T1 and T2.
Return TRUE if we are sure they can't be equal, FALSE otherwise.
The whole point of this function is to support cases where either T1 or
T2 is a typedef. In those cases, we need to compare the template parameters
of the _decl_ of the typedef. If those don't match then we know T1
and T2 cannot be equal. */
static bool
incompatible_dependent_types_p (tree t1, tree t2)
{
tree tparms1 = NULL_TREE, tparms2 = NULL_TREE;
bool t1_typedef_variant_p, t2_typedef_variant_p;
if (!uses_template_parms (t1) || !uses_template_parms (t2))
return false;
if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM)
{
/* If T1 and T2 don't have the same relative position in their
template parameters set, they can't be equal. */
if (!comp_template_parms_position (t1, t2))
return true;
}
t1_typedef_variant_p = typedef_variant_p (t1);
t2_typedef_variant_p = typedef_variant_p (t2);
/* Either T1 or T2 must be a typedef. */ /* If T1 and T2 belong to template parm lists of different size,
if (!t1_typedef_variant_p && !t2_typedef_variant_p) let's assume they are different. */
if (TEMPLATE_PARM_NUM_SIBLINGS (index1)
!= TEMPLATE_PARM_NUM_SIBLINGS (index2))
return false; return false;
if (!t1_typedef_variant_p || !t2_typedef_variant_p) /* Then compare their relative position. */
/* Either T1 or T2 is not a typedef so we cannot compare the if (TEMPLATE_PARM_IDX (index1) != TEMPLATE_PARM_IDX (index2)
template parms of the typedefs of T1 and T2. || TEMPLATE_PARM_LEVEL (index1) != TEMPLATE_PARM_LEVEL (index2)
At this point, if the main variant type of T1 and T2 are equal || (TEMPLATE_PARM_PARAMETER_PACK (index1)
it means the two types can't be incompatible, from the perspective != TEMPLATE_PARM_PARAMETER_PACK (index2)))
of this function. */
if (TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
return false;
/* So if we reach this point, it means either T1 or T2 is a typedef variant.
Let's compare their template parameters. */
tparms1 = get_template_parms_of_dependent_type (t1);
tparms2 = get_template_parms_of_dependent_type (t2);
/* If T2 is a template type parm and if we could not get the template
parms it belongs to, that means we have not finished parsing the
full set of template parameters of the template declaration it
belongs to yet. If we could get the template parms T1 belongs to,
that mostly means T1 and T2 belongs to templates that are
different and incompatible. */
if (TREE_CODE (t1) == TEMPLATE_TYPE_PARM
&& (tparms1 == NULL_TREE || tparms2 == NULL_TREE)
&& tparms1 != tparms2)
return true;
if (tparms1 == NULL_TREE
|| tparms2 == NULL_TREE
|| tparms1 == tparms2)
return false; return false;
/* And now compare the mighty template parms! */ return true;
return !comp_template_parms (tparms1, tparms2);
} }
/* Subroutine in comptypes. */ /* Subroutine in comptypes. */
...@@ -1301,12 +1211,6 @@ structural_comptypes (tree t1, tree t2, int strict) ...@@ -1301,12 +1211,6 @@ structural_comptypes (tree t1, tree t2, int strict)
if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2)) if (TYPE_FOR_JAVA (t1) != TYPE_FOR_JAVA (t2))
return false; return false;
/* If T1 and T2 are dependent typedefs then check upfront that
the template parameters of their typedef DECLs match before
going down checking their subtypes. */
if (incompatible_dependent_types_p (t1, t2))
return false;
/* Allow for two different type nodes which have essentially the same /* Allow for two different type nodes which have essentially the same
definition. Note that we already checked for equality of the type definition. Note that we already checked for equality of the type
qualifiers (just above). */ qualifiers (just above). */
...@@ -1407,8 +1311,10 @@ structural_comptypes (tree t1, tree t2, int strict) ...@@ -1407,8 +1311,10 @@ structural_comptypes (tree t1, tree t2, int strict)
break; break;
case TEMPLATE_TYPE_PARM: case TEMPLATE_TYPE_PARM:
/* If incompatible_dependent_types_p called earlier didn't decide /* If T1 and T2 don't have the same relative position in their
T1 and T2 were different, they might be equal. */ template parameters set, they can't be equal. */
if (!comp_template_parms_position (t1, t2))
return false;
break; break;
case TYPENAME_TYPE: case TYPENAME_TYPE:
......
2010-11-02 Dodji Seketeli <dodji@redhat.com>
PR c++/45606
* g++.dg/template/typedef36.C: New test.
* gcc/testsuite/g++.dg/template/canon-type-9.C: Likewise.
* g++.dg/template/canon-type-10.C: Likewise.
* g++.dg/template/canon-type-11.C: Likewise.
* g++.dg/template/canon-type-12.C: Likewise.
* g++.dg/template/canon-type-13.C: Likewise.
2010-11-02 Iain Sandoe <iains@gcc.gnu.org> 2010-11-02 Iain Sandoe <iains@gcc.gnu.org>
* g++.dg/debug/dwarf2/pubnames-1.C: Amend to check for only one instance * g++.dg/debug/dwarf2/pubnames-1.C: Amend to check for only one instance
......
// Contributed by Dodji Seketeli <dodji@redhat.com>
// { dg-do "compile" }
template<class T>
struct C
{
};
template<class T,
template<class TT_T0, template<class TT_T1> class TT_TT> class TT,
class U = TT<int, C> >
struct S
{
void foo(TT<T, C>);
};
template<class T,
template<class TT_T0, template<class TT_T1> class TT_TT> class TT,
class U>
void
S<T, TT, U>::foo(TT<T, C>)
{
}
// Contributed by Dodji Seketeli <dodji@redhat.com>
// { dg-do "compile" }
template<class T>
struct C
{
void bar();
};
template<class T>
void
C<T>::bar()
{
}
template<class U,
template<class TT0_T0> class TT0 = C,
template<class TT1_T0> class TT1 = TT0>
struct S
{
C<U> s;
void foo(TT1<U>);
void bar()
{
foo(s);
}
};
template<class T,
template<class TT0_T0> class TT0,
template<class TT1_T0> class TT1>
void
S<T, TT0, TT1>::foo(TT1<T>)
{
C<T> c;
}
// { dg-options "-std=c++0x" }
template<class T, T t = (T)0>
struct S
{
void
foo(decltype(t) = t);
};
template<class T, T t>
void
S<T, t>::foo(T)
{
}
void
bar()
{
S<int> s;
s.foo();
}
// Contributed by Dodji Seketeli <dodji@redhat.com>
// { dg-do "compile" }
template<class T>
struct S0
{
};
template<class T>
struct S1
{
};
template<class T, template<class T> class A, template<class T> class B = A>
struct C
{
B<T> m;
};
void
foo()
{
C<int, S0> s;
S0<int> s0;
s.m = s0;
}
// Contributed by Dodji Seketeli <dodji@redhat.com>
// { dg-options "-std=c++0x" }
// { dg-do "compile" }
struct F { F(int) {}};
template<class T, T* u>
struct S
{
decltype(u) foo(T);
};
template<class T, T *u>
T* S<T, u>::foo(T)
{
T t;
return t;
}
// Origin: PR c++/45606
// { dg-do compile }
template<class T, class U = int>
struct S0
{
typedef int const_iterator;
};
template<class T>
struct Test
{
typedef S0<T> SAlias;
typedef typename SAlias::const_iterator const_iterator;
const_iterator begin ();
};
template<class T>
typename S0<T>::const_iterator
Test<T>::begin()
{
return 0;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment