mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-22 21:31:19 +08:00
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
This commit is contained in:
parent
b61148dd4f
commit
22e9174f54
@ -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 ()
|
||||
|
@ -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;
|
||||
}
|
||||
|
103
gcc/cp/pt.c
103
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 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:
|
||||
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);
|
||||
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.
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
return fn;
|
||||
}
|
||||
}
|
||||
else if (DECL_TEMPLATE_SPECIALIZATION (fn))
|
||||
{
|
||||
duplicate_decls (spec, fn);
|
||||
return fn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
DECL_TEMPLATE_SPECIALIZATIONS (tmpl)
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
|
37
gcc/testsuite/g++.old-deja/g++.pt/crash49.C
Normal file
37
gcc/testsuite/g++.old-deja/g++.pt/crash49.C
Normal file
@ -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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user