aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Mitchell <mark@codesourcery.com>1999-08-20 22:07:22 +0000
committerMark Mitchell <mmitchel@gcc.gnu.org>1999-08-20 22:07:22 +0000
commit22e9174f5416123df52503b2dc2248de0f4ca27e (patch)
treedfbbd22a6059f25bb2e777e3a7ab7bdd17945040 /gcc
parentb61148dd4f5b244381b91b86dd7e921698f92687 (diff)
downloadgcc-22e9174f5416123df52503b2dc2248de0f4ca27e.zip
gcc-22e9174f5416123df52503b2dc2248de0f4ca27e.tar.gz
gcc-22e9174f5416123df52503b2dc2248de0f4ca27e.tar.bz2
semantics.c (finish_stmt_expr): Fix typo in comment.
* 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. From-SVN: r28781
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/init.c9
-rw-r--r--gcc/cp/pt.c113
-rw-r--r--gcc/cp/semantics.c2
-rw-r--r--gcc/cp/tree.c4
-rw-r--r--gcc/testsuite/g++.old-deja/g++.pt/crash49.C37
6 files changed, 122 insertions, 53 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index dd846fd..527783d 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,13 @@
+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.
+
1999-08-18 Andrew Haley <aph@cygnus.com>
* method.c (process_overload_item): Call build_mangled_C9x_name ()
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index f8c1980..ac962f6 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -2673,6 +2673,15 @@ build_vec_delete_1 (base, maxindex, type, auto_delete_vec, auto_delete,
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;
}
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 1940cfe..b62dc75 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -842,59 +842,68 @@ register_specialization (spec, tmpl, args)
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);
+ {
+ 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;
- }
- }
+ /* 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)
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index def1276..d11bb90 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -1057,7 +1057,7 @@ finish_stmt_expr (rtl_expr, expr)
if (TREE_CODE (expr) == BLOCK)
{
- /* Make a CP_BIND_EXPR for the BLOCK already made. */
+ /* Make a BIND_EXPR for the BLOCK already made. */
if (building_stmt_tree ())
{
result = build_min (STMT_EXPR, last_expr_type, last_tree);
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index 8d36753..808e829 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -1668,6 +1668,8 @@ search_tree (t, func)
case CLEANUP_POINT_EXPR:
case LOOKUP_EXPR:
case THROW_EXPR:
+ case EXIT_EXPR:
+ case LOOP_EXPR:
TRY (TREE_OPERAND (t, 0));
break;
@@ -2001,6 +2003,8 @@ mapcar (t, func)
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;
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/crash49.C b/gcc/testsuite/g++.old-deja/g++.pt/crash49.C
new file mode 100644
index 0000000..b9f7801
--- /dev/null
+++ b/gcc/testsuite/g++.old-deja/g++.pt/crash49.C
@@ -0,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;
+}