This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[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. */


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]