diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 57c80275bd6c8fe58a2206890dea26b267a5d9a0..bdc1f41268c8d3fff4f8794f2054330dea562e5f 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,11 @@
+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  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
 	PR c++/27278
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index fe5db71c653e06e25a9f5518ae1296deb52816e9..df85e4cba7b4d4319c2ea96ff3a67797a50c85af 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -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;
-    }
-
-  /* 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
+	 do the instantiation test below.  */
+    }
+  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);
 
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index f673c16bacf46c198b8e14416cb4fe7c08564b3e..ff8086fd559c088b5e1c7002f8a90c2d7a896554 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -12431,10 +12431,17 @@ cp_parser_parameter_declaration (cp_parser *parser,
 	  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
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index fbe01dbfb4188819aa6a2c8ec12861bbc4be90cd..43efc63a3af6d31a1cabf159b84c7a228677bcd1 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6150,8 +6150,15 @@ tsubst_default_argument (tree fn, tree type, tree arg)
     }
 
   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.  */
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index b82e646e90de2e932121c099233fdcc26e1ba120..b9ca4cff981a922b197a7d49905823078ddc5ac9 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2006-04-30  Mark Mitchell  <mark@codesourcery.com>
+
+	PR c++/27094
+	* g++.dg/template/defarg8.C: New test.
+
 2006-04-30  Volker Reichelt  <reichelt@igpm.rwth-aachen.de>
 
 	PR c++/27278
diff --git a/gcc/testsuite/g++.dg/template/defarg8.C b/gcc/testsuite/g++.dg/template/defarg8.C
new file mode 100644
index 0000000000000000000000000000000000000000..61d819c7cdc25bc24a814f87e61c1a296290522d
--- /dev/null
+++ b/gcc/testsuite/g++.dg/template/defarg8.C
@@ -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;