[C++ PATCH] Fix ICE on new with value dependent args (PR c++/34336)
Jakub Jelinek
jakub@redhat.com
Wed Dec 5 20:14:00 GMT 2007
Hi!
When building new with processing_template_decl, where neither args, placement
nor type are type dependent, but something is value dependent, build_new
might create NON_DEPENDENT_EXPRs:
if (processing_template_decl)
{
if (dependent_type_p (type)
|| any_type_dependent_arguments_p (placement)
|| (nelts && type_dependent_expression_p (nelts))
|| (init != void_zero_node
&& any_type_dependent_arguments_p (init)))
return build_raw_new_expr (placement, type, nelts, init,
use_global_new);
placement = build_non_dependent_args (placement);
if (nelts)
nelts = build_non_dependent_expr (nelts);
if (init != void_zero_node)
init = build_non_dependent_args (init);
}
and call build_new_1 with that. But stabilize_expr doesn't really like
to be called with NON_DEPENDENT_EXPR with side effects, e.g. get_target_expr
on it won't return a TARGET_EXPR, and there is really no point in
stabilizing expressions in templates, all we care about is issue proper
diagnostic and then throw everything away and just build_raw_new_expr
from the original arguments.
Attached are 2 possible approaches, one modifies stabilize_call and
stabilize_init to return immediately if processing_template_decl
(similarly e.g. to how cp_save_expr returns immediately), the other
modifies the caller (build_new_1) not to call these when
processing_template_decl. stabilize_call is only called by stabilize_init
and build_new_1, stabilize_init is only called by build_new_1 and
build_throw (but the later only if !processing_template_decl).
So both patches are functionally equivalent. I've regtested both with
make check-g++ and will throw the first one in the bootstrap/full regtest
I'm about to start.
Ok for trunk? Which one?
Jakub
-------------- next part --------------
2007-12-05 Jakub Jelinek <jakub@redhat.com>
PR c++/34336
* tree.c (stabilize_call, stabilize_init): Do nothing if
processing_template_decl.
* g++.dg/template/new8.C: New test.
--- gcc/cp/tree.c.jj 2007-11-29 19:38:34.000000000 +0100
+++ gcc/cp/tree.c 2007-12-05 17:57:06.000000000 +0100
@@ -2602,8 +2602,11 @@ stabilize_call (tree call, tree *initp)
int i;
int nargs = call_expr_nargs (call);
- if (call == error_mark_node)
- return;
+ if (call == error_mark_node || processing_template_decl)
+ {
+ *initp = NULL_TREE;
+ return;
+ }
gcc_assert (TREE_CODE (call) == CALL_EXPR);
@@ -2662,7 +2665,7 @@ stabilize_init (tree init, tree *initp)
*initp = NULL_TREE;
- if (t == error_mark_node)
+ if (t == error_mark_node || processing_template_decl)
return true;
if (TREE_CODE (t) == INIT_EXPR
--- gcc/testsuite/g++.dg/template/new8.C.jj 2007-12-05 18:02:04.000000000 +0100
+++ gcc/testsuite/g++.dg/template/new8.C 2007-12-05 18:01:30.000000000 +0100
@@ -0,0 +1,29 @@
+// PR c++/34336
+// { dg-do compile }
+
+struct A;
+
+template <class T>
+struct S
+{
+ T *m;
+ T &operator* () { return *m; }
+};
+
+struct B
+{
+ B (const A &);
+};
+
+template <class T>
+struct C
+{
+ C ();
+ S<A> c;
+};
+
+template <class T>
+C<T>::C ()
+{
+ B *b = new B (*c);
+}
-------------- next part --------------
2007-12-05 Jakub Jelinek <jakub@redhat.com>
PR c++/34336
* init.c (build_new_1): Don't call stabilize_call or stabilize_init
if processing_template_decl.
* g++.dg/template/new8.C: New test.
--- gcc/cp/init.c.jj 2007-11-23 20:33:49.000000000 +0100
+++ gcc/cp/init.c 2007-12-05 20:14:59.000000000 +0100
@@ -1889,7 +1889,7 @@ build_new_1 (tree placement, tree type,
/* Preevaluate the placement args so that we don't reevaluate them for a
placement delete. */
- if (placement_allocation_fn_p)
+ if (placement_allocation_fn_p && !processing_template_decl)
{
tree inits;
stabilize_call (alloc_call, &inits);
@@ -2000,7 +2000,10 @@ build_new_1 (tree placement, tree type,
complete_ctor_identifier,
init, elt_type,
LOOKUP_NORMAL);
- stable = stabilize_init (init_expr, &init_preeval_expr);
+ if (processing_template_decl)
+ stable = true;
+ else
+ stable = stabilize_init (init_expr, &init_preeval_expr);
}
else
{
@@ -2015,7 +2018,10 @@ build_new_1 (tree placement, tree type,
|| TREE_TYPE (init) != NULL_TREE);
init_expr = build_modify_expr (init_expr, INIT_EXPR, init);
- stable = stabilize_init (init_expr, &init_preeval_expr);
+ if (processing_template_decl)
+ stable = true;
+ else
+ stable = stabilize_init (init_expr, &init_preeval_expr);
}
}
--- gcc/testsuite/g++.dg/template/new8.C.jj 2007-12-05 18:02:04.000000000 +0100
+++ gcc/testsuite/g++.dg/template/new8.C 2007-12-05 18:01:30.000000000 +0100
@@ -0,0 +1,29 @@
+// PR c++/34336
+// { dg-do compile }
+
+struct A;
+
+template <class T>
+struct S
+{
+ T *m;
+ T &operator* () { return *m; }
+};
+
+struct B
+{
+ B (const A &);
+};
+
+template <class T>
+struct C
+{
+ C ();
+ S<A> c;
+};
+
+template <class T>
+C<T>::C ()
+{
+ B *b = new B (*c);
+}
More information about the Gcc-patches
mailing list