This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
[PATCH] Fix PR c++/29573: ICE after parse error in template argument
- From: Simon Martin <simartin at users dot sourceforge dot net>
- To: gcc-patches at gcc dot gnu dot org
- Date: Wed, 1 Nov 2006 00:11:49 +0100
- Subject: [PATCH] Fix PR c++/29573: ICE after parse error in template argument
Hi all.
Currently, the following invalid snippet triggers a segmentation fault:
=== cut here ===
template<int> struct A {};
template<typename> struct B : A <sizeof(=)> {};
template<typename> struct C : A <sizeof(=)> {};
=== cut here ===
as does this valid (I guess; Comeau accepts it) one:
=== cut here ===
int a;
template<int> struct A {};
template<typename> struct B : A <sizeof(a=2)> {};
template<typename> struct C : A <sizeof(a=2)> {};
=== cut here ===
The problem is that when parsing sizeof(a=2) (or sizeof(=)),
build_x_modify_expr is called, and returns
build_min_nt (MODOP_EXPR, lhs,
build_min_nt (modifycode, NULL_TREE, NULL_TREE), rhs);
When both 'sizeof(a=2)' are compared (via the lookup_template_class function),
we end up comparing trees for which TREE_OPERAND(t, 0) is NULL, which
triggers the segmentation fault in the following loop in cp_tree_equal:
for (code1 = TREE_CODE (t1);
code1 == NOP_EXPR || code1 == CONVERT_EXPR
|| code1 == NON_LVALUE_EXPR;
code1 = TREE_CODE (t1))
t1 = TREE_OPERAND (t1, 0);
(we have the very same loop for t2 just after this one).
The attached patch fixes this by breaking if t1 or t2 becomes NULL, and
checking for their nullity after the loops.
This has been successfully bootstrapped and regtested with no new unexpected
failures on i686-pc-linux-gnu. Is it OK? If so, could someone commit it for
me please?
Thanks in advance.
Best regards,
Simon
:ADDPATCH c++:
2006-10-31 Simon Martin <simartin@users.sourceforge.net>
PR c++/29573
* tree.c (cp_tree_equal): Ensure that t1 and t2 are not dereferenced if
they are NULL.
Index: gcc/cp/tree.c
===================================================================
--- gcc/cp/tree.c (revision 118220)
+++ gcc/cp/tree.c (working copy)
@@ -1435,16 +1435,26 @@ cp_tree_equal (tree t1, tree t2)
code1 == NOP_EXPR || code1 == CONVERT_EXPR
|| code1 == NON_LVALUE_EXPR;
code1 = TREE_CODE (t1))
- t1 = TREE_OPERAND (t1, 0);
+ {
+ t1 = TREE_OPERAND (t1, 0);
+ if (!t1)
+ break;
+ }
for (code2 = TREE_CODE (t2);
code2 == NOP_EXPR || code2 == CONVERT_EXPR
|| code1 == NON_LVALUE_EXPR;
code2 = TREE_CODE (t2))
- t2 = TREE_OPERAND (t2, 0);
+ {
+ t2 = TREE_OPERAND (t2, 0);
+ if (!t2)
+ break;
+ }
/* They might have become equal now. */
if (t1 == t2)
return true;
+ if (!t1 || !t2)
+ return false;
if (code1 != code2)
return false;
2006-10-31 Simon Martin <simartin@users.sourceforge.net>
PR c++/29573
* g++.dg/template/sizeof-template-argument.C: New test.
/* This used to ICE (PR c++/29573) */
/* { dg-do "compile" } */
template<int> struct A {};
template<typename> struct B : A <sizeof(=)> {}; /* { dg-error "parse error in template argument list" } */
template<typename> struct C : A <sizeof(=)> {}; /* { dg-error "parse error in template argument list" } */
int a;
template<typename> struct D : A <sizeof(a=1)> {}; /* This used to ICE as well. */
template<typename> struct E : A <sizeof(a=1)> {}; /* This used to ICE as well. */