diff mbox series

[C++] Use releasing_vec more broadly.

Message ID 20190513212748.16118-1-jason@redhat.com
State New
Headers show
Series [C++] Use releasing_vec more broadly. | expand

Commit Message

Jason Merrill May 13, 2019, 9:27 p.m. UTC
The releasing_vec class is useful anywhere we want to release_tree_vector on
exit, particularly in the presence of multiple returns.

Tested x86_64-pc-linux-gnu, applying to trunk.

	* cp-tree.h (struct releasing_vec): Replace get_ref method with
	operator&.
	(vec_safe_push, vec_safe_reserve, vec_safe_length, vec_safe_splice):
	Forwarding functions for releasing_vec.
	(release_tree_vector): Declare but don't define.
	* call.c (build_op_delete_call, build_temp, call_copy_ctor)
	(perform_direct_initialization_if_possible): Use releasing_vec.
	* constexpr.c (cxx_eval_vec_init_1, cxx_eval_store_expression):
	Likewise.
	* cp-gimplify.c (cp_fold): Likewise.
	* cvt.c (force_rvalue, ocp_convert): Likewise.
	* decl.c (get_tuple_decomp_init): Likewise.
	* except.c (build_throw): Likewise.
	* init.c (perform_member_init, expand_default_init): Likewise.
	* method.c (do_build_copy_assign, locate_fn_flags): Likewise.
	* parser.c (cp_parser_userdef_char_literal)
	(cp_parser_userdef_numeric_literal)
	(cp_parser_userdef_string_literal)
	(cp_parser_perform_range_for_lookup)
	(cp_parser_range_for_member_function, cp_parser_omp_for_loop)
	(cp_parser_omp_for_loop_init): Likewise.
	* pt.c (tsubst_copy_and_build, do_class_deduction): Likewise.
	* semantics.c (calculate_direct_bases, calculate_bases)
	(finish_omp_barrier, finish_omp_flush, finish_omp_taskwait)
	(finish_omp_taskyield, finish_omp_cancel)
	(finish_omp_cancellation_point): Likewise.
	* tree.c (build_vec_init_elt, strip_typedefs, strip_typedefs_expr)
	(build_min_non_dep_op_overload): Likewise.
	* typeck.c (build_function_call_vec, cp_build_function_call_nary)
	(cp_build_modify_expr): Likewise.
	* typeck2.c (build_functional_cast): Likewise.
---
 gcc/cp/cp-tree.h     | 16 +++++++++++++---
 gcc/cp/call.c        | 13 ++++---------
 gcc/cp/constexpr.c   | 11 ++++-------
 gcc/cp/cp-gimplify.c |  4 +---
 gcc/cp/cvt.c         |  6 ++----
 gcc/cp/decl.c        |  2 +-
 gcc/cp/except.c      |  7 ++-----
 gcc/cp/init.c        |  6 ++----
 gcc/cp/method.c      |  8 ++------
 gcc/cp/parser.c      | 35 +++++++++--------------------------
 gcc/cp/pt.c          | 32 +++++++-------------------------
 gcc/cp/semantics.c   | 31 ++++++++++---------------------
 gcc/cp/tree.c        | 17 +++++------------
 gcc/cp/typeck.c      | 11 +++--------
 gcc/cp/typeck2.c     |  4 +---
 gcc/cp/ChangeLog     | 35 +++++++++++++++++++++++++++++++++++
 16 files changed, 101 insertions(+), 137 deletions(-)


base-commit: b95ab4713bf1395f3433e994f0a89c5f3bf30de1
diff mbox series

Patch

diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7fb25a93e44..827b471aa80 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -890,15 +890,25 @@  struct releasing_vec
   vec_t *operator-> () const { return v; }
   vec_t *get() const { return v; }
   operator vec_t *() const { return v; }
-  tree& operator[] (unsigned i) const { return (*v)[i]; }
+  vec_t ** operator& () { return &v; }
 
-  /* Necessary for use with vec** and vec*& interfaces.  */
-  vec_t *&get_ref () { return v; }
+  /* Breaks pointer/value consistency for convenience.  */
+  tree& operator[] (unsigned i) const { return (*v)[i]; }
 
   ~releasing_vec() { release_tree_vector (v); }
 private:
   vec_t *v;
 };
+/* Forwarding functions for vec_safe_* that might reallocate.  */
+inline tree* vec_safe_push (releasing_vec& r, const tree &t CXX_MEM_STAT_INFO)
+{ return vec_safe_push (*&r, t PASS_MEM_STAT); }
+inline bool vec_safe_reserve (releasing_vec& r, unsigned n, bool e = false CXX_MEM_STAT_INFO)
+{ return vec_safe_reserve (*&r, n, e PASS_MEM_STAT); }
+inline unsigned vec_safe_length (releasing_vec &r)
+{ return r->length(); }
+inline void vec_safe_splice (releasing_vec &r, vec<tree, va_gc> *p CXX_MEM_STAT_INFO)
+{ vec_safe_splice (*&r, p PASS_MEM_STAT); }
+void release_tree_vector (releasing_vec &); // cause link error
 
 struct GTY(()) tree_template_decl {
   struct tree_decl_common common;
diff --git a/gcc/cp/call.c b/gcc/cp/call.c
index 2329c4cb43e..00cb3993471 100644
--- a/gcc/cp/call.c
+++ b/gcc/cp/call.c
@@ -6671,7 +6671,7 @@  build_op_delete_call (enum tree_code code, tree addr, tree size,
 	    }
 
 	  tree ret;
-	  vec<tree, va_gc> *args = make_tree_vector ();
+	  releasing_vec args;
 	  args->quick_push (addr);
 	  if (destroying)
 	    args->quick_push (destroying);
@@ -6683,7 +6683,6 @@  build_op_delete_call (enum tree_code code, tree addr, tree size,
 	      args->quick_push (al);
 	    }
 	  ret = cp_build_function_call_vec (fn, &args, complain);
-	  release_tree_vector (args);
 	  return ret;
 	}
     }
@@ -6787,7 +6786,6 @@  build_temp (tree expr, tree type, int flags,
 	    diagnostic_t *diagnostic_kind, tsubst_flags_t complain)
 {
   int savew, savee;
-  vec<tree, va_gc> *args;
 
   *diagnostic_kind = DK_UNSPECIFIED;
 
@@ -6801,10 +6799,9 @@  build_temp (tree expr, tree type, int flags,
     return get_target_expr_sfinae (expr, complain);
 
   savew = warningcount + werrorcount, savee = errorcount;
-  args = make_tree_vector_single (expr);
+  releasing_vec args (make_tree_vector_single (expr));
   expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
 				    &args, type, flags, complain);
-  release_tree_vector (args);
   if (warningcount + werrorcount > savew)
     *diagnostic_kind = DK_WARNING;
   else if (errorcount > savee)
@@ -7897,10 +7894,9 @@  call_copy_ctor (tree a, tsubst_flags_t complain)
   tree copy = get_copy_ctor (ctype, complain);
   copy = build_baselink (binfo, binfo, copy, NULL_TREE);
   tree ob = build_dummy_object (ctype);
-  vec<tree, va_gc>* args = make_tree_vector_single (a);
+  releasing_vec args (make_tree_vector_single (a));
   tree r = build_new_method_call (ob, copy, &args, NULL_TREE,
 				  LOOKUP_NORMAL, NULL, complain);
-  release_tree_vector (args);
   return r;
 }
 
@@ -11283,10 +11279,9 @@  perform_direct_initialization_if_possible (tree type,
      ill-formed.  */
   if (CLASS_TYPE_P (type))
     {
-      vec<tree, va_gc> *args = make_tree_vector_single (expr);
+      releasing_vec args (make_tree_vector_single (expr));
       expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
 					&args, type, LOOKUP_NORMAL, complain);
-      release_tree_vector (args);
       return build_cplus_new (type, expr, complain);
     }
 
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index 9c13f0d5f32..8ae0fd5715f 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -3113,11 +3113,10 @@  cxx_eval_vec_init_1 (const constexpr_ctx *ctx, tree atype, tree init,
     }
   else if (!init)
     {
-      vec<tree, va_gc> *argvec = make_tree_vector ();
+      releasing_vec argvec;
       init = build_special_member_call (NULL_TREE, complete_ctor_identifier,
 					&argvec, elttype, LOOKUP_NORMAL,
 					complain);
-      release_tree_vector (argvec);
       init = build_aggr_init_expr (elttype, init);
       pre_init = true;
     }
@@ -3740,7 +3739,7 @@  cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
     }
 
   /* And then find the underlying variable.  */
-  vec<tree,va_gc> *refs = make_tree_vector();
+  releasing_vec refs;
   tree object = NULL_TREE;
   for (tree probe = target; object == NULL_TREE; )
     {
@@ -3784,7 +3783,7 @@  cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
   type = TREE_TYPE (object);
   bool no_zero_init = true;
 
-  vec<tree,va_gc> *ctors = make_tree_vector ();
+  releasing_vec ctors;
   while (!refs->is_empty())
     {
       if (*valp == NULL_TREE)
@@ -3897,7 +3896,6 @@  cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
 	}
       valp = &cep->value;
     }
-  release_tree_vector (refs);
 
   if (!preeval)
     {
@@ -3941,14 +3939,13 @@  cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
   bool c = TREE_CONSTANT (init);
   bool s = TREE_SIDE_EFFECTS (init);
   if (!c || s)
-    FOR_EACH_VEC_SAFE_ELT (ctors, i, elt)
+    FOR_EACH_VEC_ELT (*ctors, i, elt)
       {
 	if (!c)
 	  TREE_CONSTANT (elt) = false;
 	if (s)
 	  TREE_SIDE_EFFECTS (elt) = true;
       }
-  release_tree_vector (ctors);
 
   if (*non_constant_p)
     return t;
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index 7a243addb92..4e63a4a6944 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -2654,7 +2654,7 @@  cp_fold (tree x)
     case TREE_VEC:
       {
 	bool changed = false;
-	vec<tree, va_gc> *vec = make_tree_vector ();
+	releasing_vec vec;
 	int i, n = TREE_VEC_LENGTH (x);
 	vec_safe_reserve (vec, n);
 
@@ -2673,8 +2673,6 @@  cp_fold (tree x)
 	      TREE_VEC_ELT (r, i) = (*vec)[i];
 	    x = r;
 	  }
-
-	release_tree_vector (vec);
       }
 
       break;
diff --git a/gcc/cp/cvt.c b/gcc/cp/cvt.c
index b63a9ff6e98..3d409279f22 100644
--- a/gcc/cp/cvt.c
+++ b/gcc/cp/cvt.c
@@ -562,10 +562,9 @@  force_rvalue (tree expr, tsubst_flags_t complain)
   tree type = TREE_TYPE (expr);
   if (MAYBE_CLASS_TYPE_P (type) && TREE_CODE (expr) != TARGET_EXPR)
     {
-      vec<tree, va_gc> *args = make_tree_vector_single (expr);
+      releasing_vec args (make_tree_vector_single (expr));
       expr = build_special_member_call (NULL_TREE, complete_ctor_identifier,
 					&args, type, LOOKUP_NORMAL, complain);
-      release_tree_vector (args);
       expr = build_cplus_new (type, expr, complain);
     }
   else
@@ -925,12 +924,11 @@  ocp_convert (tree type, tree expr, int convtype, int flags,
 	ctor = build_user_type_conversion (type, ctor, flags, complain);
       else
 	{
-	  vec<tree, va_gc> *ctor_vec = make_tree_vector_single (ctor);
+	  releasing_vec ctor_vec (make_tree_vector_single (ctor));
 	  ctor = build_special_member_call (NULL_TREE,
 					    complete_ctor_identifier,
 					    &ctor_vec,
 					    type, flags, complain);
-	  release_tree_vector (ctor_vec);
 	}
       if (ctor)
 	return build_cplus_new (type, ctor, complain);
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c
index a776f8fcd98..86cfcbe0db5 100644
--- a/gcc/cp/decl.c
+++ b/gcc/cp/decl.c
@@ -7590,7 +7590,7 @@  get_tuple_decomp_init (tree decl, unsigned i)
     }
   else
     {
-      vec<tree,va_gc> *args = make_tree_vector_single (e);
+      releasing_vec args (make_tree_vector_single (e));
       fns = lookup_template_function (get__identifier, targs);
       fns = perform_koenig_lookup (fns, args, tf_warning_or_error);
       return finish_call_expr (fns, &args, /*novirt*/false,
diff --git a/gcc/cp/except.c b/gcc/cp/except.c
index afc261073d7..3b792cbc62b 100644
--- a/gcc/cp/except.c
+++ b/gcc/cp/except.c
@@ -756,7 +756,6 @@  build_throw (tree exp)
       if (CLASS_TYPE_P (temp_type))
 	{
 	  int flags = LOOKUP_NORMAL | LOOKUP_ONLYCONVERTING;
-	  vec<tree, va_gc> *exp_vec;
 	  bool converted = false;
 
 	  /* Under C++0x [12.8/16 class.copy], a thrown lvalue is sometimes
@@ -767,12 +766,11 @@  build_throw (tree exp)
 	      && !CP_TYPE_VOLATILE_P (TREE_TYPE (exp)))
 	    {
 	      tree moved = move (exp);
-	      exp_vec = make_tree_vector_single (moved);
+	      releasing_vec exp_vec (make_tree_vector_single (moved));
 	      moved = (build_special_member_call
 		       (object, complete_ctor_identifier, &exp_vec,
 			TREE_TYPE (object), flags|LOOKUP_PREFER_RVALUE,
 			tf_none));
-	      release_tree_vector (exp_vec);
 	      if (moved != error_mark_node)
 		{
 		  exp = moved;
@@ -783,11 +781,10 @@  build_throw (tree exp)
 	  /* Call the copy constructor.  */
 	  if (!converted)
 	    {
-	      exp_vec = make_tree_vector_single (exp);
+	      releasing_vec exp_vec (make_tree_vector_single (exp));
 	      exp = (build_special_member_call
 		     (object, complete_ctor_identifier, &exp_vec,
 		      TREE_TYPE (object), flags, tf_warning_or_error));
-	      release_tree_vector (exp_vec);
 	    }
 
 	  if (exp == error_mark_node)
diff --git a/gcc/cp/init.c b/gcc/cp/init.c
index 79a93a297a9..68d04ad7417 100644
--- a/gcc/cp/init.c
+++ b/gcc/cp/init.c
@@ -847,7 +847,7 @@  perform_member_init (tree member, tree init)
 	 reference member in a constructor’s ctor-initializer (12.6.2)
 	 persists until the constructor exits."  */
       unsigned i; tree t;
-      vec<tree, va_gc> *cleanups = make_tree_vector ();
+      releasing_vec cleanups;
       if (TREE_CODE (init) == TREE_LIST)
 	init = build_x_compound_expr_from_list (init, ELK_MEM_INIT,
 						tf_warning_or_error);
@@ -871,7 +871,6 @@  perform_member_init (tree member, tree init)
       finish_expr_stmt (init);
       FOR_EACH_VEC_ELT (*cleanups, i, t)
 	push_cleanup (decl, t, false);
-      release_tree_vector (cleanups);
     }
   else if (type_build_ctor_call (type)
 	   || (init && CLASS_TYPE_P (strip_array_types (type))))
@@ -1952,7 +1951,7 @@  expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
       tree elt; unsigned i;
 
       /* Unshare the arguments for the second call.  */
-      vec<tree, va_gc> *parms2 = make_tree_vector ();
+      releasing_vec parms2;
       FOR_EACH_VEC_SAFE_ELT (parms, i, elt)
 	{
 	  elt = break_out_target_exprs (elt);
@@ -1962,7 +1961,6 @@  expand_default_init (tree binfo, tree true_exp, tree exp, tree init, int flags,
 					    &parms2, binfo, flags,
 					    complain);
       complete = fold_build_cleanup_point_expr (void_type_node, complete);
-      release_tree_vector (parms2);
 
       base = build_special_member_call (exp, base_ctor_identifier,
 					&parms, binfo, flags,
diff --git a/gcc/cp/method.c b/gcc/cp/method.c
index 9ebc99eb394..31737d1353c 100644
--- a/gcc/cp/method.c
+++ b/gcc/cp/method.c
@@ -790,7 +790,6 @@  do_build_copy_assign (tree fndecl)
 	   BINFO_BASE_ITERATE (binfo, i, base_binfo); i++)
 	{
 	  tree converted_parm;
-	  vec<tree, va_gc> *parmvec;
 
 	  /* We must convert PARM directly to the base class
 	     explicitly since the base class may be ambiguous.  */
@@ -799,7 +798,7 @@  do_build_copy_assign (tree fndecl)
 	  if (move_p)
 	    converted_parm = move (converted_parm);
 	  /* Call the base class assignment operator.  */
-	  parmvec = make_tree_vector_single (converted_parm);
+	  releasing_vec parmvec (make_tree_vector_single (converted_parm));
 	  finish_expr_stmt
 	    (build_special_member_call (current_class_ref,
 					assign_op_identifier,
@@ -807,7 +806,6 @@  do_build_copy_assign (tree fndecl)
 					base_binfo,
 					flags,
                                         tf_warning_or_error));
-	  release_tree_vector (parmvec);
 	}
 
       /* Assign to each of the non-static data members.  */
@@ -993,7 +991,6 @@  locate_fn_flags (tree type, tree name, tree argtype, int flags,
 		 tsubst_flags_t complain)
 {
   tree ob, fn, fns, binfo, rval;
-  vec<tree, va_gc> *args;
 
   if (TYPE_P (type))
     binfo = TYPE_BINFO (type);
@@ -1004,7 +1001,7 @@  locate_fn_flags (tree type, tree name, tree argtype, int flags,
     }
 
   ob = build_stub_object (cp_build_reference_type (type, false));
-  args = make_tree_vector ();
+  releasing_vec args;
   if (argtype)
     {
       if (TREE_CODE (argtype) == TREE_LIST)
@@ -1027,7 +1024,6 @@  locate_fn_flags (tree type, tree name, tree argtype, int flags,
   fns = lookup_fnfields (binfo, name, 0);
   rval = build_new_method_call (ob, fns, &args, binfo, flags, &fn, complain);
 
-  release_tree_vector (args);
   if (fn && rval == error_mark_node)
     return rval;
   else
diff --git a/gcc/cp/parser.c b/gcc/cp/parser.c
index 5881d932fba..c90782eafde 100644
--- a/gcc/cp/parser.c
+++ b/gcc/cp/parser.c
@@ -4345,18 +4345,16 @@  cp_parser_userdef_char_literal (cp_parser *parser)
 
   /* Build up a call to the user-defined operator  */
   /* Lookup the name we got back from the id-expression.  */
-  vec<tree, va_gc> *args = make_tree_vector ();
+  releasing_vec args;
   vec_safe_push (args, value);
   decl = lookup_literal_operator (name, args);
   if (!decl || decl == error_mark_node)
     {
       error ("unable to find character literal operator %qD with %qT argument",
 	     name, TREE_TYPE (value));
-      release_tree_vector (args);
       return error_mark_node;
     }
   result = finish_call_expr (decl, &args, false, true, tf_warning_or_error);
-  release_tree_vector (args);
   return result;
 }
 
@@ -4443,11 +4441,10 @@  cp_parser_userdef_numeric_literal (cp_parser *parser)
   tree num_string = USERDEF_LITERAL_NUM_STRING (literal);
   tree name = cp_literal_operator_id (IDENTIFIER_POINTER (suffix_id));
   tree decl, result;
-  vec<tree, va_gc> *args;
 
   /* Look for a literal operator taking the exact type of numeric argument
      as the literal value.  */
-  args = make_tree_vector ();
+  releasing_vec args;
   vec_safe_push (args, value);
   decl = lookup_literal_operator (name, args);
   if (decl && decl != error_mark_node)
@@ -4472,30 +4469,26 @@  cp_parser_userdef_numeric_literal (cp_parser *parser)
 			"floating literal truncated to zero");
 	}
 
-      release_tree_vector (args);
       return result;
     }
-  release_tree_vector (args);
 
   /* If the numeric argument didn't work, look for a raw literal
      operator taking a const char* argument consisting of the number
      in string format.  */
-  args = make_tree_vector ();
+  args->truncate (0);
   vec_safe_push (args, num_string);
   decl = lookup_literal_operator (name, args);
   if (decl && decl != error_mark_node)
     {
       result = finish_call_expr (decl, &args, false, true,
 				 tf_warning_or_error);
-      release_tree_vector (args);
       return result;
     }
-  release_tree_vector (args);
 
   /* If the raw literal didn't work, look for a non-type template
      function with parameter pack char....  Call the function with
      template parameter characters representing the number.  */
-  args = make_tree_vector ();
+  args->truncate (0);
   decl = lookup_literal_operator (name, args);
   if (decl && decl != error_mark_node)
     {
@@ -4509,12 +4502,9 @@  cp_parser_userdef_numeric_literal (cp_parser *parser)
       decl = lookup_template_function (decl, tmpl_args);
       result = finish_call_expr (decl, &args, false, true,
 				 tf_warning_or_error);
-      release_tree_vector (args);
       return result;
     }
 
-  release_tree_vector (args);
-
   /* In C++14 the standard library defines complex number suffixes that
      conflict with GNU extensions.  Prefer them if <complex> is #included.  */
   bool ext = cpp_get_options (parse_in)->ext_numeric_literals;
@@ -4602,8 +4592,7 @@  cp_parser_userdef_string_literal (tree literal)
 
   /* Build up a call to the user-defined operator.  */
   /* Lookup the name we got back from the id-expression.  */
-  releasing_vec rargs;
-  vec<tree, va_gc> *&args = rargs.get_ref();
+  releasing_vec args;
   vec_safe_push (args, value);
   vec_safe_push (args, build_int_cst (size_type_node, len));
   decl = lookup_literal_operator (name, args);
@@ -12539,8 +12528,7 @@  cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end)
       else
 	{
 	  /* Use global functions with ADL.  */
-	  vec<tree, va_gc> *vec;
-	  vec = make_tree_vector ();
+	  releasing_vec vec;
 
 	  vec_safe_push (vec, range);
 
@@ -12552,8 +12540,6 @@  cp_parser_perform_range_for_lookup (tree range, tree *begin, tree *end)
 					      tf_warning_or_error);
 	  *end = finish_call_expr (member_end, &vec, false, true,
 				   tf_warning_or_error);
-
-	  release_tree_vector (vec);
 	}
 
       /* Last common checks.  */
@@ -12601,19 +12587,17 @@  static tree
 cp_parser_range_for_member_function (tree range, tree identifier)
 {
   tree member, res;
-  vec<tree, va_gc> *vec;
 
   member = finish_class_member_access_expr (range, identifier,
 					    false, tf_warning_or_error);
   if (member == error_mark_node)
     return error_mark_node;
 
-  vec = make_tree_vector ();
+  releasing_vec vec;
   res = finish_call_expr (member, &vec,
 			  /*disallow_virtual=*/false,
 			  /*koenig_p=*/false,
 			  tf_warning_or_error);
-  release_tree_vector (vec);
   return res;
 }
 
@@ -36430,7 +36414,7 @@  cp_parser_omp_for_incr (cp_parser *parser, tree decl)
 static tree
 cp_parser_omp_for_loop_init (cp_parser *parser,
 			     tree &this_pre_body,
-			     vec<tree, va_gc> *&for_block,
+			     releasing_vec &for_block,
 			     tree &init,
 			     tree &orig_init,
 			     tree &decl,
@@ -36851,7 +36835,7 @@  cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
   location_t loc_first;
   bool collapse_err = false;
   int i, collapse = 1, ordered = 0, count, nbraces = 0;
-  vec<tree, va_gc> *for_block = make_tree_vector ();
+  releasing_vec for_block;
   auto_vec<tree, 4> orig_inits;
   bool tiling = false;
 
@@ -37240,7 +37224,6 @@  cp_parser_omp_for_loop (cp_parser *parser, enum tree_code code, tree clauses,
       else
 	add_stmt (t);
     }
-  release_tree_vector (for_block);
 
   return ret;
 }
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 08da94ae0c9..42d128744ab 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -18750,7 +18750,6 @@  tsubst_copy_and_build (tree t,
     case CALL_EXPR:
       {
 	tree function;
-	vec<tree, va_gc> *call_args;
 	unsigned int nargs, i;
 	bool qualified_p;
 	bool koenig_p;
@@ -18818,7 +18817,7 @@  tsubst_copy_and_build (tree t,
 	  }
 
 	nargs = call_expr_nargs (t);
-	call_args = make_tree_vector ();
+	releasing_vec call_args;
 	for (i = 0; i < nargs; ++i)
 	  {
 	    tree arg = CALL_EXPR_ARG (t, i);
@@ -18894,7 +18893,6 @@  tsubst_copy_and_build (tree t,
 	    if (CLASS_TYPE_P (TREE_TYPE (ret)))
 	      CALL_EXPR_RETURN_SLOT_OPT (ret) = true;
 
-	    release_tree_vector (call_args);
 	    RETURN (ret);
 	  }
 
@@ -18927,10 +18925,7 @@  tsubst_copy_and_build (tree t,
 			    (function, args, complain, in_decl, true,
 			     integral_constant_expression_p));
 		if (unq == error_mark_node)
-		  {
-		    release_tree_vector (call_args);
-		    RETURN (error_mark_node);
-		  }
+		  RETURN (error_mark_node);
 
 		if (unq != function)
 		  {
@@ -18985,10 +18980,7 @@  tsubst_copy_and_build (tree t,
 				  "%qD declared here, later in the "
 				  "translation unit", fn);
 			if (in_lambda)
-			  {
-			    release_tree_vector (call_args);
-			    RETURN (error_mark_node);
-			  }
+			  RETURN (error_mark_node);
 		      }
 
 		    function = unq;
@@ -18998,7 +18990,6 @@  tsubst_copy_and_build (tree t,
 	      {
 		if (complain & tf_error)
 		  unqualified_name_lookup_error (function);
-		release_tree_vector (call_args);
 		RETURN (error_mark_node);
 	      }
 	  }
@@ -19007,10 +18998,7 @@  tsubst_copy_and_build (tree t,
 	if (function != NULL_TREE
 	    && DECL_P (function)
 	    && !mark_used (function, complain) && !(complain & tf_error))
-	  {
-	    release_tree_vector (call_args);
-	    RETURN (error_mark_node);
-	  }
+	  RETURN (error_mark_node);
 
 	/* Put back tf_decltype for the actual call.  */
 	complain |= decltype_flag;
@@ -19048,10 +19036,7 @@  tsubst_copy_and_build (tree t,
 						  complain, in_decl),
 					  complain);
 	      if (TREE_CODE (ret) == VIEW_CONVERT_EXPR)
-		{
-		  release_tree_vector (call_args);
-		  RETURN (ret);
-		}
+		RETURN (ret);
 	      break;
 
 	    default:
@@ -19094,8 +19079,6 @@  tsubst_copy_and_build (tree t,
 				  koenig_p,
 				  complain);
 
-	release_tree_vector (call_args);
-
 	if (ret != error_mark_node)
 	  {
 	    bool op = CALL_EXPR_OPERATOR_SYNTAX (t);
@@ -27314,7 +27297,8 @@  do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
 
   bool try_list_ctor = false;
 
-  vec<tree,va_gc> *args;
+  releasing_vec rv_args = NULL;
+  vec<tree,va_gc> *&args = *&rv_args;
   if (init == NULL_TREE
       || TREE_CODE (init) == TREE_LIST)
     args = make_tree_vector_from_list (init);
@@ -27487,8 +27471,6 @@  do_class_deduction (tree ptype, tree tmpl, tree init, int flags,
 		"for copy-initialization");
     }
 
-  release_tree_vector (args);
-
   return cp_build_qualified_type (TREE_TYPE (call), cp_type_quals (ptype));
 }
 
diff --git a/gcc/cp/semantics.c b/gcc/cp/semantics.c
index 1093cbef134..38459342384 100644
--- a/gcc/cp/semantics.c
+++ b/gcc/cp/semantics.c
@@ -3992,7 +3992,7 @@  calculate_direct_bases (tree type, tsubst_flags_t complain)
       || !NON_UNION_CLASS_TYPE_P (type))
     return make_tree_vec (0);
 
-  vec<tree, va_gc> *vector = make_tree_vector ();
+  releasing_vec vector;
   vec<tree, va_gc> *base_binfos = BINFO_BASE_BINFOS (TYPE_BINFO (type));
   tree binfo;
   unsigned i;
@@ -4012,7 +4012,6 @@  calculate_direct_bases (tree type, tsubst_flags_t complain)
   for (i = 0; i < vector->length (); ++i)
     TREE_VEC_ELT (bases_vec, i) = BINFO_TYPE ((*vector)[i]);
 
-  release_tree_vector (vector);
   return bases_vec;
 }
 
@@ -4058,27 +4057,24 @@  calculate_bases (tree type, tsubst_flags_t complain)
       || !NON_UNION_CLASS_TYPE_P (type))
     return make_tree_vec (0);
 
-  vec<tree, va_gc> *vector = make_tree_vector ();
+  releasing_vec vector;
   tree bases_vec = NULL_TREE;
   unsigned i;
   vec<tree, va_gc> *vbases;
-  vec<tree, va_gc> *nonvbases;
   tree binfo;
 
   /* First go through virtual base classes */
   for (vbases = CLASSTYPE_VBASECLASSES (type), i = 0;
        vec_safe_iterate (vbases, i, &binfo); i++)
     {
-      vec<tree, va_gc> *vbase_bases
+      releasing_vec vbase_bases
 	= calculate_bases_helper (BINFO_TYPE (binfo));
       vec_safe_splice (vector, vbase_bases);
-      release_tree_vector (vbase_bases);
     }
 
   /* Now for the non-virtual bases */
-  nonvbases = calculate_bases_helper (type);
+  releasing_vec nonvbases = calculate_bases_helper (type);
   vec_safe_splice (vector, nonvbases);
-  release_tree_vector (nonvbases);
 
   /* Note that during error recovery vector->length can even be zero.  */
   if (vector->length () > 1)
@@ -4092,7 +4088,6 @@  calculate_bases (tree type, tsubst_flags_t complain)
   else
     bases_vec = make_tree_vec (0);
 
-  release_tree_vector (vector);
   return bases_vec;
 }
 
@@ -9002,9 +8997,8 @@  void
 finish_omp_barrier (void)
 {
   tree fn = builtin_decl_explicit (BUILT_IN_GOMP_BARRIER);
-  vec<tree, va_gc> *vec = make_tree_vector ();
+  releasing_vec vec;
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
-  release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
 
@@ -9047,14 +9041,13 @@  void
 finish_omp_flush (int mo)
 {
   tree fn = builtin_decl_explicit (BUILT_IN_SYNC_SYNCHRONIZE);
-  vec<tree, va_gc> *vec = make_tree_vector ();
+  releasing_vec vec;
   if (mo != MEMMODEL_LAST)
     {
       fn = builtin_decl_explicit (BUILT_IN_ATOMIC_THREAD_FENCE);
       vec->quick_push (build_int_cst (integer_type_node, mo));
     }
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
-  release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
 
@@ -9062,9 +9055,8 @@  void
 finish_omp_taskwait (void)
 {
   tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKWAIT);
-  vec<tree, va_gc> *vec = make_tree_vector ();
+  releasing_vec vec;
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
-  release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
 
@@ -9072,9 +9064,8 @@  void
 finish_omp_taskyield (void)
 {
   tree fn = builtin_decl_explicit (BUILT_IN_GOMP_TASKYIELD);
-  vec<tree, va_gc> *vec = make_tree_vector ();
+  releasing_vec vec;
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
-  release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
 
@@ -9097,7 +9088,7 @@  finish_omp_cancel (tree clauses)
 	     "%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> clauses");
       return;
     }
-  vec<tree, va_gc> *vec = make_tree_vector ();
+  releasing_vec vec;
   tree ifc = omp_find_clause (clauses, OMP_CLAUSE_IF);
   if (ifc != NULL_TREE)
     {
@@ -9131,7 +9122,6 @@  finish_omp_cancel (tree clauses)
   vec->quick_push (build_int_cst (integer_type_node, mask));
   vec->quick_push (ifc);
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
-  release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
 
@@ -9154,10 +9144,9 @@  finish_omp_cancellation_point (tree clauses)
 	     "%<parallel%>, %<for%>, %<sections%> or %<taskgroup%> clauses");
       return;
     }
-  vec<tree, va_gc> *vec
+  releasing_vec vec
     = make_tree_vector_single (build_int_cst (integer_type_node, mask));
   tree stmt = finish_call_expr (fn, &vec, false, false, tf_warning_or_error);
-  release_tree_vector (vec);
   finish_expr_stmt (stmt);
 }
 
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
index ebc6cb6278d..7b8889ea7b2 100644
--- a/gcc/cp/tree.c
+++ b/gcc/cp/tree.c
@@ -698,7 +698,6 @@  static tree
 build_vec_init_elt (tree type, tree init, tsubst_flags_t complain)
 {
   tree inner_type = strip_array_types (type);
-  vec<tree, va_gc> *argvec;
 
   if (integer_zerop (array_type_nelts_total (type))
       || !CLASS_TYPE_P (inner_type))
@@ -711,7 +710,7 @@  build_vec_init_elt (tree type, tree init, tsubst_flags_t complain)
 	      || (same_type_ignoring_top_level_qualifiers_p
 		  (type, TREE_TYPE (init))));
 
-  argvec = make_tree_vector ();
+  releasing_vec argvec;
   if (init)
     {
       tree init_type = strip_array_types (TREE_TYPE (init));
@@ -723,7 +722,6 @@  build_vec_init_elt (tree type, tree init, tsubst_flags_t complain)
   init = build_special_member_call (NULL_TREE, complete_ctor_identifier,
 				    &argvec, inner_type, LOOKUP_NORMAL,
 				    complain);
-  release_tree_vector (argvec);
 
   /* For a trivial constructor, build_over_call creates a TARGET_EXPR.  But
      we don't want one here because we aren't creating a temporary.  */
@@ -1451,7 +1449,7 @@  strip_typedefs (tree t, bool *remove_attributes)
   if (TREE_CODE (t) == TREE_LIST)
     {
       bool changed = false;
-      vec<tree,va_gc> *vec = make_tree_vector ();
+      releasing_vec vec;
       tree r = t;
       for (; t; t = TREE_CHAIN (t))
 	{
@@ -1463,7 +1461,6 @@  strip_typedefs (tree t, bool *remove_attributes)
 	}
       if (changed)
 	r = build_tree_list_vec (vec);
-      release_tree_vector (vec);
       return r;
     }
 
@@ -1751,7 +1748,7 @@  strip_typedefs_expr (tree t, bool *remove_attributes)
 
     case TREE_LIST:
       {
-	vec<tree, va_gc> *vec = make_tree_vector ();
+	releasing_vec vec;
 	bool changed = false;
 	tree it;
 	for (it = t; it; it = TREE_CHAIN (it))
@@ -1770,14 +1767,13 @@  strip_typedefs_expr (tree t, bool *remove_attributes)
 	  }
 	else
 	  r = t;
-	release_tree_vector (vec);
 	return r;
       }
 
     case TREE_VEC:
       {
 	bool changed = false;
-	vec<tree, va_gc> *vec = make_tree_vector ();
+	releasing_vec vec;
 	n = TREE_VEC_LENGTH (t);
 	vec_safe_reserve (vec, n);
 	for (i = 0; i < n; ++i)
@@ -1798,7 +1794,6 @@  strip_typedefs_expr (tree t, bool *remove_attributes)
 	  }
 	else
 	  r = t;
-	release_tree_vector (vec);
 	return r;
       }
 
@@ -3355,7 +3350,6 @@  build_min_non_dep_op_overload (enum tree_code op,
   va_list p;
   int nargs, expected_nargs;
   tree fn, call;
-  vec<tree, va_gc> *args;
 
   non_dep = extract_call_expr (non_dep);
 
@@ -3369,7 +3363,7 @@  build_min_non_dep_op_overload (enum tree_code op,
     expected_nargs += 1;
   gcc_assert (nargs == expected_nargs);
 
-  args = make_tree_vector ();
+  releasing_vec args;
   va_start (p, overload);
 
   if (TREE_CODE (TREE_TYPE (overload)) == FUNCTION_TYPE)
@@ -3399,7 +3393,6 @@  build_min_non_dep_op_overload (enum tree_code op,
 
   va_end (p);
   call = build_min_non_dep_call_vec (non_dep, fn, args);
-  release_tree_vector (args);
 
   tree call_expr = extract_call_expr (call);
   KOENIG_LOOKUP_P (call_expr) = KOENIG_LOOKUP_P (non_dep);
diff --git a/gcc/cp/typeck.c b/gcc/cp/typeck.c
index d1f965be280..36e6b2474f0 100644
--- a/gcc/cp/typeck.c
+++ b/gcc/cp/typeck.c
@@ -3756,14 +3756,12 @@  build_function_call_vec (location_t /*loc*/, vec<location_t> /*arg_loc*/,
 static tree
 cp_build_function_call (tree function, tree params, tsubst_flags_t complain)
 {
-  vec<tree, va_gc> *vec;
   tree ret;
 
-  vec = make_tree_vector ();
+  releasing_vec vec;
   for (; params != NULL_TREE; params = TREE_CHAIN (params))
     vec_safe_push (vec, TREE_VALUE (params));
   ret = cp_build_function_call_vec (function, &vec, complain);
-  release_tree_vector (vec);
   return ret;
 }
 
@@ -3772,17 +3770,15 @@  cp_build_function_call (tree function, tree params, tsubst_flags_t complain)
 tree
 cp_build_function_call_nary (tree function, tsubst_flags_t complain, ...)
 {
-  vec<tree, va_gc> *vec;
   va_list args;
   tree ret, t;
 
-  vec = make_tree_vector ();
+  releasing_vec vec;
   va_start (args, complain);
   for (t = va_arg (args, tree); t != NULL_TREE; t = va_arg (args, tree))
     vec_safe_push (vec, t);
   va_end (args);
   ret = cp_build_function_call_vec (function, &vec, complain);
-  release_tree_vector (vec);
   return ret;
 }
 
@@ -8223,11 +8219,10 @@  cp_build_modify_expr (location_t loc, tree lhs, enum tree_code modifycode,
 	/* Do the default thing.  */;
       else
 	{
-	  vec<tree, va_gc> *rhs_vec = make_tree_vector_single (rhs);
+	  releasing_vec rhs_vec = make_tree_vector_single (rhs);
 	  result = build_special_member_call (lhs, complete_ctor_identifier,
 					      &rhs_vec, lhstype, LOOKUP_NORMAL,
                                               complain);
-	  release_tree_vector (rhs_vec);
 	  if (result == NULL_TREE)
 	    return error_mark_node;
 	  goto ret;
diff --git a/gcc/cp/typeck2.c b/gcc/cp/typeck2.c
index df002a1664c..618eed9a96d 100644
--- a/gcc/cp/typeck2.c
+++ b/gcc/cp/typeck2.c
@@ -2173,7 +2173,6 @@  build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
 
   /* The type to which we are casting.  */
   tree type;
-  vec<tree, va_gc> *parmvec;
 
   if (error_operand_p (exp) || parms == error_mark_node)
     return error_mark_node;
@@ -2295,12 +2294,11 @@  build_functional_cast (tree exp, tree parms, tsubst_flags_t complain)
     }
 
   /* Call the constructor.  */
-  parmvec = make_tree_vector ();
+  releasing_vec parmvec;
   for (; parms != NULL_TREE; parms = TREE_CHAIN (parms))
     vec_safe_push (parmvec, TREE_VALUE (parms));
   exp = build_special_member_call (NULL_TREE, complete_ctor_identifier,
 				   &parmvec, type, LOOKUP_NORMAL, complain);
-  release_tree_vector (parmvec);
 
   if (exp == error_mark_node)
     return error_mark_node;
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3da2493f08c..812f9f5a6be 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,38 @@ 
+2019-05-13  Jason Merrill  <jason@redhat.com>
+
+	Use releasing_vec more broadly.
+	* cp-tree.h (struct releasing_vec): Replace get_ref method with
+	operator&.
+	(vec_safe_push, vec_safe_reserve, vec_safe_length, vec_safe_splice):
+	Forwarding functions for releasing_vec.
+	(release_tree_vector): Declare but don't define.
+	* call.c (build_op_delete_call, build_temp, call_copy_ctor)
+	(perform_direct_initialization_if_possible): Use releasing_vec.
+	* constexpr.c (cxx_eval_vec_init_1, cxx_eval_store_expression):
+	Likewise.
+	* cp-gimplify.c (cp_fold): Likewise.
+	* cvt.c (force_rvalue, ocp_convert): Likewise.
+	* decl.c (get_tuple_decomp_init): Likewise.
+	* except.c (build_throw): Likewise.
+	* init.c (perform_member_init, expand_default_init): Likewise.
+	* method.c (do_build_copy_assign, locate_fn_flags): Likewise.
+	* parser.c (cp_parser_userdef_char_literal)
+	(cp_parser_userdef_numeric_literal)
+	(cp_parser_userdef_string_literal)
+	(cp_parser_perform_range_for_lookup)
+	(cp_parser_range_for_member_function, cp_parser_omp_for_loop)
+	(cp_parser_omp_for_loop_init): Likewise.
+	* pt.c (tsubst_copy_and_build, do_class_deduction): Likewise.
+	* semantics.c (calculate_direct_bases, calculate_bases)
+	(finish_omp_barrier, finish_omp_flush, finish_omp_taskwait)
+	(finish_omp_taskyield, finish_omp_cancel)
+	(finish_omp_cancellation_point): Likewise.
+	* tree.c (build_vec_init_elt, strip_typedefs, strip_typedefs_expr)
+	(build_min_non_dep_op_overload): Likewise.
+	* typeck.c (build_function_call_vec, cp_build_function_call_nary)
+	(cp_build_modify_expr): Likewise.
+	* typeck2.c (build_functional_cast): Likewise.
+
 2019-05-11  Paolo Carlini  <paolo.carlini@oracle.com>
 
 	* typeck.c (cp_build_function_call_vec): When mark_used fails