diff --git a/gcc/cp/call.cc b/gcc/cp/call.cc
index 673ec91d60e..432ac99b4bb 100644
--- a/gcc/cp/call.cc
+++ b/gcc/cp/call.cc
@@ -4646,6 +4646,9 @@ build_user_type_conversion (tree totype, tree expr, int flags,
   tree ret;
 
   auto_cond_timevar tv (TV_OVERLOAD);
+
+  conversion_obstack_sentinel cos;
+
   cand = build_user_type_conversion_1 (totype, expr, flags, complain);
 
   if (cand)
@@ -4698,15 +4701,13 @@ build_converted_constant_expr_internal (tree type, tree expr,
 					int flags, tsubst_flags_t complain)
 {
   conversion *conv;
-  void *p;
   tree t;
   location_t loc = cp_expr_loc_or_input_loc (expr);
 
   if (error_operand_p (expr))
     return error_mark_node;
 
-  /* Get the high-water mark for the CONVERSION_OBSTACK.  */
-  p = conversion_obstack_alloc (0);
+  conversion_obstack_sentinel cos;
 
   conv = implicit_conversion (type, TREE_TYPE (expr), expr,
 			      /*c_cast_p=*/false, flags, complain);
@@ -4815,9 +4816,6 @@ build_converted_constant_expr_internal (tree type, tree expr,
       expr = error_mark_node;
     }
 
-  /* Free all the conversions we allocated.  */
-  obstack_free (&conversion_obstack, p);
-
   return expr;
 }
 
@@ -4985,8 +4983,7 @@ perform_dguide_overload_resolution (tree dguides, const vec<tree, va_gc> *args,
 
   gcc_assert (deduction_guide_p (OVL_FIRST (dguides)));
 
-  /* Get the high-water mark for the CONVERSION_OBSTACK.  */
-  void *p = conversion_obstack_alloc (0);
+  conversion_obstack_sentinel cos;
 
   z_candidate *cand = perform_overload_resolution (dguides, args, &candidates,
 						   &any_viable_p, complain);
@@ -4999,9 +4996,6 @@ perform_dguide_overload_resolution (tree dguides, const vec<tree, va_gc> *args,
   else
     result = cand->fn;
 
-  /* Free all the conversions we allocated.  */
-  obstack_free (&conversion_obstack, p);
-
   return result;
 }
 
@@ -5015,7 +5009,6 @@ build_new_function_call (tree fn, vec<tree, va_gc> **args,
 {
   struct z_candidate *candidates, *cand;
   bool any_viable_p;
-  void *p;
   tree result;
 
   if (args != NULL && *args != NULL)
@@ -5028,8 +5021,7 @@ build_new_function_call (tree fn, vec<tree, va_gc> **args,
   if (flag_tm)
     tm_malloc_replacement (fn);
 
-  /* Get the high-water mark for the CONVERSION_OBSTACK.  */
-  p = conversion_obstack_alloc (0);
+  conversion_obstack_sentinel cos;
 
   cand = perform_overload_resolution (fn, *args, &candidates, &any_viable_p,
 				      complain);
@@ -5061,9 +5053,6 @@ build_new_function_call (tree fn, vec<tree, va_gc> **args,
 	  == BUILT_IN_NORMAL)
    result = coro_validate_builtin_call (result);
 
-  /* Free all the conversions we allocated.  */
-  obstack_free (&conversion_obstack, p);
-
   return result;
 }
 
@@ -5108,6 +5097,8 @@ build_operator_new_call (tree fnname, vec<tree, va_gc> **args,
   if (*args == NULL)
     return error_mark_node;
 
+  conversion_obstack_sentinel cos;
+
   /* Based on:
 
        [expr.new]
@@ -5234,7 +5225,6 @@ build_op_call (tree obj, vec<tree, va_gc> **args, tsubst_flags_t complain)
   tree fns, convs, first_mem_arg = NULL_TREE;
   bool any_viable_p;
   tree result = NULL_TREE;
-  void *p;
 
   auto_cond_timevar tv (TV_OVERLOAD);
 
@@ -5273,8 +5263,7 @@ build_op_call (tree obj, vec<tree, va_gc> **args, tsubst_flags_t complain)
 	return error_mark_node;
     }
 
-  /* Get the high-water mark for the CONVERSION_OBSTACK.  */
-  p = conversion_obstack_alloc (0);
+  conversion_obstack_sentinel cos;
 
   if (fns)
     {
@@ -5377,9 +5366,6 @@ build_op_call (tree obj, vec<tree, va_gc> **args, tsubst_flags_t complain)
 	}
     }
 
-  /* Free all the conversions we allocated.  */
-  obstack_free (&conversion_obstack, p);
-
   return result;
 }
 
@@ -5587,7 +5573,6 @@ build_conditional_expr (const op_location_t &loc,
   bool is_glvalue = true;
   struct z_candidate *candidates = 0;
   struct z_candidate *cand;
-  void *p;
   tree orig_arg2, orig_arg3;
 
   auto_cond_timevar tv (TV_OVERLOAD);
@@ -5631,6 +5616,8 @@ build_conditional_expr (const op_location_t &loc,
       || error_operand_p (arg3))
     return error_mark_node;
 
+  conversion_obstack_sentinel cos;
+
   orig_arg2 = arg2;
   orig_arg3 = arg3;
 
@@ -5911,9 +5898,6 @@ build_conditional_expr (const op_location_t &loc,
       conversion *conv3;
       bool converted = false;
 
-      /* Get the high-water mark for the CONVERSION_OBSTACK.  */
-      p = conversion_obstack_alloc (0);
-
       conv2 = conditional_conversion (arg2, arg3, complain);
       conv3 = conditional_conversion (arg3, arg2, complain);
 
@@ -5969,9 +5953,6 @@ build_conditional_expr (const op_location_t &loc,
 	  converted = true;
 	}
 
-      /* Free all the conversions we allocated.  */
-      obstack_free (&conversion_obstack, p);
-
       if (result)
 	return result;
 
@@ -6961,7 +6942,6 @@ build_new_op (const op_location_t &loc, enum tree_code code, int flags,
   enum tree_code code2 = ERROR_MARK;
   enum tree_code code_orig_arg1 = ERROR_MARK;
   enum tree_code code_orig_arg2 = ERROR_MARK;
-  void *p;
   bool strict_p;
   bool any_viable_p;
 
@@ -6972,6 +6952,8 @@ build_new_op (const op_location_t &loc, enum tree_code code, int flags,
       || error_operand_p (arg3))
     return error_mark_node;
 
+  conversion_obstack_sentinel cos;
+
   bool ismodop = code == MODIFY_EXPR;
   if (ismodop)
     {
@@ -7042,13 +7024,10 @@ build_new_op (const op_location_t &loc, enum tree_code code, int flags,
   if (arg3 != NULL_TREE)
     arglist->quick_push (arg3);
 
-  /* Get the high-water mark for the CONVERSION_OBSTACK.  */
-  p = conversion_obstack_alloc (0);
-
   result = add_operator_candidates (&candidates, code, code2, arglist,
 				    lookups, flags, complain);
   if (result == error_mark_node)
-    goto user_defined_result_ready;
+    return error_mark_node;
 
   switch (code)
     {
@@ -7343,11 +7322,6 @@ build_new_op (const op_location_t &loc, enum tree_code code, int flags,
 	}
     }
 
- user_defined_result_ready:
-
-  /* Free all the conversions we allocated.  */
-  obstack_free (&conversion_obstack, p);
-
   if (result || result_valid_p)
     return result;
 
@@ -7443,7 +7417,6 @@ build_op_subscript (const op_location_t &loc, tree obj,
   tree fns, first_mem_arg = NULL_TREE;
   bool any_viable_p;
   tree result = NULL_TREE;
-  void *p;
 
   auto_cond_timevar tv (TV_OVERLOAD);
 
@@ -7473,8 +7446,7 @@ build_op_subscript (const op_location_t &loc, tree obj,
 	return error_mark_node;
     }
 
-  /* Get the high-water mark for the CONVERSION_OBSTACK.  */
-  p = conversion_obstack_alloc (0);
+  conversion_obstack_sentinel cos;
 
   if (fns)
     {
@@ -7542,9 +7514,6 @@ build_op_subscript (const op_location_t &loc, tree obj,
 	gcc_unreachable ();
     }
 
-  /* Free all the conversions we allocated.  */
-  obstack_free (&conversion_obstack, p);
-
   return result;
 }
 
@@ -9687,8 +9656,7 @@ ref_conv_binds_to_temporary (tree type, tree expr, bool direct_init_p/*=false*/)
 {
   gcc_assert (TYPE_REF_P (type));
 
-  /* Get the high-water mark for the CONVERSION_OBSTACK.  */
-  void *p = conversion_obstack_alloc (0);
+  conversion_obstack_sentinel cos;
 
   const int flags = direct_init_p ? LOOKUP_NORMAL : LOOKUP_IMPLICIT;
   conversion *conv = implicit_conversion (type, TREE_TYPE (expr), expr,
@@ -9697,9 +9665,6 @@ ref_conv_binds_to_temporary (tree type, tree expr, bool direct_init_p/*=false*/)
   if (conv && !conv->bad_p)
     ret = tristate (conv_binds_ref_to_temporary (conv));
 
-  /* Free all the conversions we allocated.  */
-  obstack_free (&conversion_obstack, p);
-
   return ret;
 }
 
@@ -11423,7 +11388,6 @@ build_new_method_call (tree instance, tree fns, vec<tree, va_gc> **args,
   tree orig_instance;
   tree orig_fns;
   vec<tree, va_gc> *orig_args = NULL;
-  void *p;
 
   auto_cond_timevar tv (TV_OVERLOAD);
 
@@ -11550,8 +11514,7 @@ build_new_method_call (tree instance, tree fns, vec<tree, va_gc> **args,
   else
     first_mem_arg = maybe_resolve_dummy (instance, false);
 
-  /* Get the high-water mark for the CONVERSION_OBSTACK.  */
-  p = conversion_obstack_alloc (0);
+  conversion_obstack_sentinel cos;
 
   /* The number of arguments artificial parms in ARGS; we subtract one because
      there's no 'this' in ARGS.  */
@@ -11816,9 +11779,6 @@ skip_prune:
 	call = build_nop (void_type_node, call);
     }
 
- /* Free all the conversions we allocated.  */
-  obstack_free (&conversion_obstack, p);
-
   if (orig_args != NULL)
     release_tree_vector (orig_args);
 
@@ -13335,11 +13295,9 @@ can_convert_arg (tree to, tree from, tree arg, int flags,
 		 tsubst_flags_t complain)
 {
   conversion *t;
-  void *p;
   bool ok_p;
 
-  /* Get the high-water mark for the CONVERSION_OBSTACK.  */
-  p = conversion_obstack_alloc (0);
+  conversion_obstack_sentinel cos;
   /* We want to discard any access checks done for this test,
      as we might not be in the appropriate access context and
      we'll do the check again when we actually perform the
@@ -13352,8 +13310,6 @@ can_convert_arg (tree to, tree from, tree arg, int flags,
 
   /* Discard the access checks now.  */
   pop_deferring_access_checks ();
-  /* Free all the conversions we allocated.  */
-  obstack_free (&conversion_obstack, p);
 
   return ok_p;
 }
@@ -13365,15 +13321,11 @@ can_convert_arg_bad (tree to, tree from, tree arg, int flags,
 		     tsubst_flags_t complain)
 {
   conversion *t;
-  void *p;
 
-  /* Get the high-water mark for the CONVERSION_OBSTACK.  */
-  p = conversion_obstack_alloc (0);
+  conversion_obstack_sentinel cos;
   /* Try to perform the conversion.  */
   t  = implicit_conversion (to, from, arg, /*c_cast_p=*/false,
 			    flags, complain);
-  /* Free all the conversions we allocated.  */
-  obstack_free (&conversion_obstack, p);
 
   return t != NULL;
 }
@@ -13408,7 +13360,6 @@ perform_implicit_conversion_flags (tree type, tree expr,
 				   tsubst_flags_t complain, int flags)
 {
   conversion *conv;
-  void *p;
   location_t loc = cp_expr_loc_or_input_loc (expr);
 
   if (TYPE_REF_P (type))
@@ -13419,8 +13370,7 @@ perform_implicit_conversion_flags (tree type, tree expr,
   if (error_operand_p (expr))
     return error_mark_node;
 
-  /* Get the high-water mark for the CONVERSION_OBSTACK.  */
-  p = conversion_obstack_alloc (0);
+  conversion_obstack_sentinel cos;
 
   conv = implicit_conversion (type, TREE_TYPE (expr), expr,
 			      /*c_cast_p=*/false,
@@ -13441,9 +13391,6 @@ perform_implicit_conversion_flags (tree type, tree expr,
       expr = convert_like (conv, expr, complain);
     }
 
-  /* Free all the conversions we allocated.  */
-  obstack_free (&conversion_obstack, p);
-
   return expr;
 }
 
@@ -13469,7 +13416,6 @@ perform_direct_initialization_if_possible (tree type,
                                            tsubst_flags_t complain)
 {
   conversion *conv;
-  void *p;
 
   if (type == error_mark_node || error_operand_p (expr))
     return error_mark_node;
@@ -13496,8 +13442,7 @@ perform_direct_initialization_if_possible (tree type,
       return build_cplus_new (type, expr, complain);
     }
 
-  /* Get the high-water mark for the CONVERSION_OBSTACK.  */
-  p = conversion_obstack_alloc (0);
+  conversion_obstack_sentinel cos;
 
   conv = implicit_conversion (type, TREE_TYPE (expr), expr,
 			      c_cast_p,
@@ -13519,9 +13464,6 @@ perform_direct_initialization_if_possible (tree type,
 			 /*issue_conversion_warnings=*/false,
 			 c_cast_p, /*nested_p=*/false, complain);
 
-  /* Free all the conversions we allocated.  */
-  obstack_free (&conversion_obstack, p);
-
   return expr;
 }
 
@@ -13760,14 +13702,12 @@ initialize_reference (tree type, tree expr,
 		      int flags, tsubst_flags_t complain)
 {
   conversion *conv;
-  void *p;
   location_t loc = cp_expr_loc_or_input_loc (expr);
 
   if (type == error_mark_node || error_operand_p (expr))
     return error_mark_node;
 
-  /* Get the high-water mark for the CONVERSION_OBSTACK.  */
-  p = conversion_obstack_alloc (0);
+  conversion_obstack_sentinel cos;
 
   conv = reference_binding (type, TREE_TYPE (expr), expr, /*c_cast_p=*/false,
 			    flags, complain);
@@ -13814,9 +13754,6 @@ initialize_reference (tree type, tree expr,
   else
     gcc_unreachable ();
 
-  /* Free all the conversions we allocated.  */
-  obstack_free (&conversion_obstack, p);
-
   return expr;
 }
 
