diff options
author | Mark Mitchell <mark@codesourcery.com> | 1999-08-20 22:07:22 +0000 |
---|---|---|
committer | Mark Mitchell <mmitchel@gcc.gnu.org> | 1999-08-20 22:07:22 +0000 |
commit | 22e9174f5416123df52503b2dc2248de0f4ca27e (patch) | |
tree | dfbbd22a6059f25bb2e777e3a7ab7bdd17945040 /gcc | |
parent | b61148dd4f5b244381b91b86dd7e921698f92687 (diff) | |
download | gcc-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/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cp/init.c | 9 | ||||
-rw-r--r-- | gcc/cp/pt.c | 113 | ||||
-rw-r--r-- | gcc/cp/semantics.c | 2 | ||||
-rw-r--r-- | gcc/cp/tree.c | 4 | ||||
-rw-r--r-- | gcc/testsuite/g++.old-deja/g++.pt/crash49.C | 37 |
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; +} |