This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
PATCH for template regression
- To: gcc-patches at gcc dot gnu dot org
- Subject: PATCH for template regression
- From: Mark Mitchell <mark at codesourcery dot com>
- Date: Fri, 20 Aug 1999 15:08:32 -0700
- Cc: Loring Holden <lsh at cs dot brown dot edu>
- Organization: CodeSourcery, LLC
Here's a fix for another memory corruption problem caused, at least
indirectly, by my recent template changes. Unfortunately, I denoted
the original poster's email, so I cannot reply directly to that
message.
--
Mark Mitchell mark@codesourcery.com
CodeSourcery, LLC http://www.codesourcery.com
1999-08-20 Mark Mitchell <mark@codesourcery.com>
* semantics.c (finish_stmt_expr): Fix typo in comment.
* tree.c (search_tree): Handle EXIT_EXPR, LOOP_EXPR.
(mapcar): Likewise.
* init.c (build_vec_delete_1): Make the children of a permanent
BIND_EXPR permanent.
* pt.c (register_specialization): Don't register a specialization
more than once.
Index: testsuite/g++.old-deja/g++.pt/crash49.C
===================================================================
RCS file: crash49.C
diff -N crash49.C
*** /dev/null Sat Dec 5 20:30:03 1998
--- crash49.C Fri Aug 20 14:59:00 1999
***************
*** 0 ****
--- 1,37 ----
+ // Build don't link:
+ // Origin: Loring Holden <lsh@cs.brown.edu>
+
+ template <class T>
+ class REFptr {
+ public:
+ virtual ~REFptr();
+ REFptr<T> &operator = (const REFptr<T>& p);
+ };
+
+ class STR { };
+ class str_ptr : public REFptr<STR> { };
+
+ template <class T>
+ class ARRAY {
+ protected:
+ T *_array;
+ int _num;
+ int _max;
+ public:
+ virtual void realloc(int new_max) {
+ _max = new_max;
+ T *tmp = new T [_max];
+ if (tmp == 0) return;
+ for (int i=0; i<_num; i++) {
+ tmp[i] = _array[i];
+ }
+ delete [] _array;
+ _array = tmp;
+ }
+ };
+
+ int
+ main()
+ {
+ ARRAY<str_ptr> tags;
+ }
Index: cp/init.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/init.c,v
retrieving revision 1.120
diff -c -p -r1.120 init.c
*** init.c 1999/08/18 20:44:10 1.120
--- init.c 1999/08/20 21:59:08
*************** build_vec_delete_1 (base, maxindex, type
*** 2673,2678 ****
--- 2673,2687 ----
if (controller)
{
+ /* The CONTROLLER is a BIND_EXPR. Such things are always
+ allocated on at least the saveable obstack. Since we may
+ need to copy this expression to the permanent obstack, we
+ must make sure that the operand is on the same obstack as the
+ BIND_EXPR. Otherwise, copy_to_permanent will not copy the
+ operand, since it will assume that anything under a permanent
+ node is permanent. */
+ if (TREE_PERMANENT (controller))
+ body = copy_to_permanent (body);
TREE_OPERAND (controller, 1) = body;
return controller;
}
Index: cp/pt.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/pt.c,v
retrieving revision 1.337
diff -c -p -r1.337 pt.c
*** pt.c 1999/08/20 06:11:46 1.337
--- pt.c 1999/08/20 21:59:14
*************** register_specialization (spec, tmpl, arg
*** 842,900 ****
for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
s != NULL_TREE;
s = TREE_CHAIN (s))
! if (comp_template_args (TREE_PURPOSE (s), args))
! {
! tree fn = TREE_VALUE (s);
!
! if (DECL_TEMPLATE_SPECIALIZATION (spec))
! {
! if (DECL_TEMPLATE_INSTANTIATION (fn))
! {
! if (TREE_USED (fn)
! || DECL_EXPLICIT_INSTANTIATION (fn))
! {
! cp_error ("specialization of %D after instantiation",
! fn);
! return spec;
! }
! else
! {
! /* This situation should occur only if the first
! specialization is an implicit instantiation,
! the second is an explicit specialization, and
! the implicit instantiation has not yet been
! used. That situation can occur if we have
! implicitly instantiated a member function and
! then specialized it later.
!
! We can also wind up here if a friend
! declaration that looked like an instantiation
! turns out to be a specialization:
!
! template <class T> void foo(T);
! class S { friend void foo<>(int) };
! template <> void foo(int);
!
! We transform the existing DECL in place so that
! any pointers to it become pointers to the
! updated declaration.
!
! If there was a definition for the template, but
! not for the specialization, we want this to
! look as if there is no definition, and vice
! versa. */
! DECL_INITIAL (fn) = NULL_TREE;
! duplicate_decls (spec, fn);
!
! return fn;
! }
! }
! else if (DECL_TEMPLATE_SPECIALIZATION (fn))
! {
! duplicate_decls (spec, fn);
! return fn;
! }
! }
}
DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
--- 842,909 ----
for (s = DECL_TEMPLATE_SPECIALIZATIONS (tmpl);
s != NULL_TREE;
s = TREE_CHAIN (s))
! {
! tree fn = TREE_VALUE (s);
!
! /* We can sometimes try to re-register a specialization that we've
! already got. In particular, regenerate_decl_from_template
! calls duplicate_decls which will update the specialization
! list. But, we'll still get called again here anyhow. It's
! more convenient to simply allow this than to try to prevent it. */
! if (fn == spec)
! return spec;
! else if (comp_template_args (TREE_PURPOSE (s), args))
! {
! if (DECL_TEMPLATE_SPECIALIZATION (spec))
! {
! if (DECL_TEMPLATE_INSTANTIATION (fn))
! {
! if (TREE_USED (fn)
! || DECL_EXPLICIT_INSTANTIATION (fn))
! {
! cp_error ("specialization of %D after instantiation",
! fn);
! return spec;
! }
! else
! {
! /* This situation should occur only if the first
! specialization is an implicit instantiation,
! the second is an explicit specialization, and
! the implicit instantiation has not yet been
! used. That situation can occur if we have
! implicitly instantiated a member function and
! then specialized it later.
!
! We can also wind up here if a friend
! declaration that looked like an instantiation
! turns out to be a specialization:
!
! template <class T> void foo(T);
! class S { friend void foo<>(int) };
! template <> void foo(int);
!
! We transform the existing DECL in place so that
! any pointers to it become pointers to the
! updated declaration.
!
! If there was a definition for the template, but
! not for the specialization, we want this to
! look as if there is no definition, and vice
! versa. */
! DECL_INITIAL (fn) = NULL_TREE;
! duplicate_decls (spec, fn);
!
! return fn;
! }
! }
! else if (DECL_TEMPLATE_SPECIALIZATION (fn))
! {
! duplicate_decls (spec, fn);
! return fn;
! }
! }
! }
}
DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
Index: cp/semantics.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/semantics.c,v
retrieving revision 1.61
diff -c -p -r1.61 semantics.c
*** semantics.c 1999/08/19 08:06:17 1.61
--- semantics.c 1999/08/20 21:59:15
*************** finish_stmt_expr (rtl_expr, expr)
*** 1057,1063 ****
if (TREE_CODE (expr) == BLOCK)
{
! /* Make a CP_BIND_EXPR for the BLOCK already made. */
if (building_stmt_tree ())
{
result = build_min (STMT_EXPR, last_expr_type, last_tree);
--- 1057,1063 ----
if (TREE_CODE (expr) == BLOCK)
{
! /* Make a BIND_EXPR for the BLOCK already made. */
if (building_stmt_tree ())
{
result = build_min (STMT_EXPR, last_expr_type, last_tree);
Index: cp/tree.c
===================================================================
RCS file: /egcs/carton/cvsfiles/egcs/gcc/cp/tree.c,v
retrieving revision 1.135
diff -c -p -r1.135 tree.c
*** tree.c 1999/08/19 08:06:17 1.135
--- tree.c 1999/08/20 21:59:16
*************** search_tree (t, func)
*** 1668,1673 ****
--- 1668,1675 ----
case CLEANUP_POINT_EXPR:
case LOOKUP_EXPR:
case THROW_EXPR:
+ case EXIT_EXPR:
+ case LOOP_EXPR:
TRY (TREE_OPERAND (t, 0));
break;
*************** mapcar (t, func)
*** 2001,2006 ****
--- 2003,2010 ----
return t;
case LOOKUP_EXPR:
+ case EXIT_EXPR:
+ case LOOP_EXPR:
t = copy_node (t);
TREE_OPERAND (t, 0) = mapcar (TREE_OPERAND (t, 0), func);
return t;