This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH: PR27904
- From: Mark Mitchell <mark at codesourcery dot com>
- To: gcc-patches at gcc dot gnu dot org
- Date: Sun, 30 Apr 2006 16:28:35 -0700
- Subject: C++ PATCH: PR27904
- Reply-to: mark at codesourcery dot com
This patch fixes PR c++/27904, which, as Jakub deduced, is a case
where we care collecting garbage with unmarked, but live, variables on
the stack. Because we are not inside a function, we do not expect to
have such local variables -- but we are in a default-argument
expression, and in that context we do have to evaluate expressions.
Tested on x86_64-unknown-linux-gnu, applied on the mainline and on the
4.1 branch.
--
Mark Mitchell
CodeSourcery
mark@codesourcery.com
(650) 331-3385 x713
2006-04-30 Mark Mitchell <mark@codesourcery.com>
PR c++/27094
* pt.c (tsubst_default_argument): Increment function_depth around
call to tsubst_expr.
* parser.c (cp_parser_parameter_declaration): Likewise.
* decl2.c (mark_used): Tidy.
2006-04-30 Mark Mitchell <mark@codesourcery.com>
PR c++/27094
* g++.dg/template/defarg8.C: New test.
Index: gcc/cp/pt.c
===================================================================
--- gcc/cp/pt.c (revision 113394)
+++ gcc/cp/pt.c (working copy)
@@ -6150,8 +6150,15 @@ tsubst_default_argument (tree fn, tree t
}
push_deferring_access_checks(dk_no_deferred);
+ /* The default argument expression may cause implicitly defined
+ member functions to be synthesized, which will result in garbage
+ collection. We must treat this situation as if we were within
+ the body of function so as to avoid collecting live data on the
+ stack. */
+ ++function_depth;
arg = tsubst_expr (arg, DECL_TI_ARGS (fn),
tf_warning_or_error, NULL_TREE);
+ --function_depth;
pop_deferring_access_checks();
/* Restore the "this" pointer. */
Index: gcc/cp/decl2.c
===================================================================
--- gcc/cp/decl2.c (revision 113394)
+++ gcc/cp/decl2.c (working copy)
@@ -3319,29 +3319,28 @@ mark_used (tree decl)
{
synthesize_method (decl);
/* If we've already synthesized the method we don't need to
- instantiate it, so we can return right away. */
- return;
+ do the instantiation test below. */
}
-
- /* If this is a function or variable that is an instance of some
- template, we now know that we will need to actually do the
- instantiation. We check that DECL is not an explicit
- instantiation because that is not checked in instantiate_decl. */
- if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)
- && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
- && (!DECL_EXPLICIT_INSTANTIATION (decl)
- || (TREE_CODE (decl) == FUNCTION_DECL
- && DECL_INLINE (DECL_TEMPLATE_RESULT
- (template_for_substitution (decl))))
- /* We need to instantiate static data members so that there
- initializers are available in integral constant
- expressions. */
- || (TREE_CODE (decl) == VAR_DECL
- && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))))
- /* We put off instantiating functions in order to improve compile
+ else if ((DECL_NON_THUNK_FUNCTION_P (decl) || TREE_CODE (decl) == VAR_DECL)
+ && DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl)
+ && (!DECL_EXPLICIT_INSTANTIATION (decl)
+ || (TREE_CODE (decl) == FUNCTION_DECL
+ && DECL_INLINE (DECL_TEMPLATE_RESULT
+ (template_for_substitution (decl))))
+ /* We need to instantiate static data members so that there
+ initializers are available in integral constant
+ expressions. */
+ || (TREE_CODE (decl) == VAR_DECL
+ && DECL_INITIALIZED_BY_CONSTANT_EXPRESSION_P (decl))))
+ /* If this is a function or variable that is an instance of some
+ template, we now know that we will need to actually do the
+ instantiation. We check that DECL is not an explicit
+ instantiation because that is not checked in instantiate_decl.
+
+ We put off instantiating functions in order to improve compile
times. Maintaining a stack of active functions is expensive,
and the inliner knows to instantiate any functions it might
- need. */
+ need. Therefore, we always try to defer instantiation. */
instantiate_decl (decl, /*defer_ok=*/true,
/*expl_inst_class_mem_p=*/false);
Index: gcc/cp/parser.c
===================================================================
--- gcc/cp/parser.c (revision 113394)
+++ gcc/cp/parser.c (working copy)
@@ -12431,10 +12431,17 @@ cp_parser_parameter_declaration (cp_pars
saved_local_variables_forbidden_p
= parser->local_variables_forbidden_p;
parser->local_variables_forbidden_p = true;
+ /* The default argument expression may cause implicitly
+ defined member functions to be synthesized, which will
+ result in garbage collection. We must treat this
+ situation as if we were within the body of function so as
+ to avoid collecting live data on the stack. */
+ ++function_depth;
/* Parse the assignment-expression. */
default_argument
= cp_parser_assignment_expression (parser, /*cast_p=*/false);
/* Restore saved state. */
+ --function_depth;
parser->greater_than_is_operator_p
= saved_greater_than_is_operator_p;
parser->local_variables_forbidden_p
Index: gcc/testsuite/g++.dg/template/defarg8.C
===================================================================
--- gcc/testsuite/g++.dg/template/defarg8.C (revision 0)
+++ gcc/testsuite/g++.dg/template/defarg8.C (revision 0)
@@ -0,0 +1,19 @@
+// PR c++/27094
+// { dg-options "--param ggc-min-expand=0 --param ggc-min-heapsize=0" }
+
+struct A
+{
+ ~A();
+};
+
+struct B : A
+{
+ B();
+};
+
+template<int> struct C
+{
+ C(const B& = B());
+};
+
+C<0> c;