This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

C++ PATCH: PR27904


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;


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]