re PR c++/42225 (GCC 4.5 ICE (segfault) on C++ templated code)

Fix PR c++/42225

gcc/cp/ChangeLog:
	PR c++/42225
	* typeck.c (incompatible_dependent_typedefs_p): New function.
	(structural_comptypes): Use it.
	* cp-tree.h (cp_set_underlying_type): Declare ...
	* tree.c (cp_set_underlying_type): ... new function.
	* class.c (build_self_reference): Use cp_set_underlying_type
	instead of set_underlying_type.
	* decl2.c (grokfield): Likewise.
	* name-lookup.c (pushdecl_maybe_friend): Likewise.

gcc/testsuite/ChangeLog:
	PR c++/42225
	* g++.dg/template/typedef24.C: New test.
	* g++.dg/template/typedef25.C: New test.

From-SVN: r155160
This commit is contained in:
Dodji Seketeli 2009-12-11 14:36:05 +00:00 committed by Dodji Seketeli
parent c9e900454a
commit 9cf10655bb
10 changed files with 158 additions and 3 deletions

View File

@ -1,3 +1,15 @@
2009-12-11 Dodji Seketeli <dodji@redhat.com>
PR c++/42225
* typeck.c (incompatible_dependent_typedefs_p): New function.
(structural_comptypes): Use it.
* cp-tree.h (cp_set_underlying_type): Declare ...
* tree.c (cp_set_underlying_type): ... new function.
* class.c (build_self_reference): Use cp_set_underlying_type
instead of set_underlying_type.
* decl2.c (grokfield): Likewise.
* name-lookup.c (pushdecl_maybe_friend): Likewise.
2009-12-11 Dodji Seketeli <dodji@redhat.com>
PR c++/42251

View File

@ -6514,7 +6514,7 @@ build_self_reference (void)
DECL_CONTEXT (value) = current_class_type;
DECL_ARTIFICIAL (value) = 1;
SET_DECL_SELF_REFERENCE_P (value);
set_underlying_type (value);
cp_set_underlying_type (value);
if (processing_template_decl)
value = push_template_decl (value);

View File

@ -5189,6 +5189,7 @@ extern bool class_tmpl_impl_spec_p (const_tree);
extern int zero_init_p (const_tree);
extern tree strip_typedefs (tree);
extern bool typedef_variant_p (tree);
extern void cp_set_underlying_type (tree);
extern tree copy_binfo (tree, tree, tree,
tree *, int);
extern int member_p (const_tree);

View File

@ -844,7 +844,7 @@ grokfield (const cp_declarator *declarator,
if (declspecs->specs[(int)ds_typedef]
&& TREE_TYPE (value) != error_mark_node
&& TYPE_NAME (TYPE_MAIN_VARIANT (TREE_TYPE (value))) != value)
set_underlying_type (value);
cp_set_underlying_type (value);
return value;
}

View File

@ -874,7 +874,7 @@ pushdecl_maybe_friend (tree x, bool is_friend)
inlining. */
&& (!TYPE_NAME (type)
|| TYPE_NAME (type) != DECL_ABSTRACT_ORIGIN (x))))
set_underlying_type (x);
cp_set_underlying_type (x);
if (type != error_mark_node
&& TYPE_NAME (type)

View File

@ -1076,6 +1076,22 @@ typedef_variant_p (tree type)
return is_typedef_decl (TYPE_NAME (type));
}
/* 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 the typedef variant type is dependent, make it require
structural equality.
This is useful when comparing two dependent typedef variant types,
because it forces the comparison of the template parameters of their
decls for instance. */
if (dependent_type_p (TREE_TYPE (t)))
SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (t));
}
/* 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,

View File

@ -1073,6 +1073,47 @@ comp_array_types (const_tree t1, const_tree t2, bool allow_redeclaration)
return true;
}
/* Subroutine of structural_comptypes.
Compare the template parameters of the
typedef decl of T1 and T2.
Return TRUE if the template parameters of the typedef decls of T1 and T2 are
different, FALSE otherwise. */
static bool
incompatible_dependent_typedefs_p (tree t1, tree t2)
{
tree decl1, tinfo1,
decl2, tinfo2;
if (!typedef_variant_p (t1)
|| !typedef_variant_p (t2)
|| !dependent_type_p (t1)
|| !dependent_type_p (t2))
return false;
decl1 = TYPE_NAME (t1);
decl2 = TYPE_NAME (t2);
if (decl1 == decl2)
return false ;
tinfo1 = get_template_info (decl1);
if (!tinfo1)
tinfo1 = get_template_info (DECL_CONTEXT (decl1));
tinfo2 = get_template_info (decl2);
if (!tinfo2)
tinfo2 = get_template_info (DECL_CONTEXT (decl2));
gcc_assert (tinfo1 != NULL_TREE
&& tinfo2 != NULL_TREE);
if (tinfo1 == tinfo2)
return false;
return !comp_template_parms (DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo1)),
DECL_TEMPLATE_PARMS (TI_TEMPLATE (tinfo2)));
}
/* Subroutine in comptypes. */
static bool
@ -1120,6 +1161,9 @@ structural_comptypes (tree t1, tree t2, int strict)
&& TYPE_MAIN_VARIANT (t1) == TYPE_MAIN_VARIANT (t2))
return true;
if (incompatible_dependent_typedefs_p (t1, t2))
return false;
/* Compare the types. Break out if they could be the same. */
switch (TREE_CODE (t1))
{

View File

@ -1,3 +1,9 @@
2009-12-11 Dodji Seketeli <dodji@redhat.com>
PR c++/42225
* g++.dg/template/typedef24.C: New test.
* g++.dg/template/typedef25.C: New test.
2009-12-11 Dodji Seketeli <dodji@redhat.com>
PR c++/42251

View File

@ -0,0 +1,33 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin PR c++/42225
// { dg-do compile }
template<class T>
struct A
{
typedef T I;
};
template<class T, int>
struct B
{
typedef T TT;
typedef typename TT::I TT_I;
typedef A<TT_I> TA;
};
template<class T>
void
foo()
{
typedef T TT;
typedef typename TT::I TT_I;
typedef A<TT_I> TA;
}
int
main()
{
foo<A<int> >();
}

View File

@ -0,0 +1,43 @@
// Contributed by Dodji Seketeli <dodji@redhat.com>
// Origin PR c++/42225
// { dg-options "-std=c++0x" }
// { dg-do compile }
template<class T>
struct A
{
typedef T I;
static const char *i;
};
template<class T, int>
struct B
{
typedef T TT;
typedef decltype(TT::i) TT_I0;
typedef decltype(&TT::i) TT_I1;
typedef decltype(*TT::i) TT_I2;
typedef A<TT_I0> TA0;
typedef A<TT_I1> TA1;
typedef A<TT_I2> TA2;
};
template<class T>
void
foo()
{
typedef T TT;
typedef decltype(TT::i) TT_I0;
typedef decltype(&TT::i) TT_I1;
typedef decltype(*TT::i) TT_I2;
typedef A<TT_I0> TA0;
typedef A<TT_I1> TA1;
typedef A<TT_I2> TA2;
}
int
main()
{
foo<A<int> >();
}