aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2024-10-02 08:05:28 -0400
committerJason Merrill <jason@redhat.com>2024-10-03 12:33:53 -0400
commit5b08ae503dd4aef2789a667daaf1984e7cc94aaa (patch)
tree0623a6d88a839df7d72b7a014996af6bf8ca7eae
parent8d63d87c6d45bf8feecdaf54b1743c94938ce7ff (diff)
downloadgcc-5b08ae503dd4aef2789a667daaf1984e7cc94aaa.zip
gcc-5b08ae503dd4aef2789a667daaf1984e7cc94aaa.tar.gz
gcc-5b08ae503dd4aef2789a667daaf1984e7cc94aaa.tar.bz2
c++: free garbage vec in coerce_template_parms
coerce_template_parms can create two different vecs for the inner template arguments, new_inner_args and (potentially) the result of expand_template_argument_pack. One or the other, or possibly both, end up being garbage: in the typical case, the expanded vec is garbage because it's only used as the source for convert_template_argument. In some dependent cases, the new vec is garbage because we decide to return the original args instead. In these cases, ggc_free the garbage vec to reduce the memory overhead of overload resolution. gcc/cp/ChangeLog: * pt.cc (struct free_if_changed_proxy): New. (coerce_template_parms): Use it. Co-authored-by: Richard Biener <rguenther@suse.de>
-rw-r--r--gcc/cp/pt.cc36
1 files changed, 30 insertions, 6 deletions
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 20affcd..6d48812 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -9079,6 +9079,30 @@ pack_expansion_args_count (tree args)
return count;
}
+/* Used for a variable of pointer type T (typically 'tree') that starts out
+ pointing to exposed data, but might get changed to point to internal data
+ that can be safely discarded at scope exit. Use .release when exposing the
+ internal data to prevent ggc_free. */
+
+template <class T>
+struct free_if_changed_proxy
+{
+ T val;
+ T orig;
+
+ free_if_changed_proxy (T t): val(t), orig(t) { }
+ ~free_if_changed_proxy ()
+ {
+ if (val != orig)
+ ggc_free (val);
+ }
+
+ T release () { return orig = val; }
+
+ operator T () { return val; }
+ free_if_changed_proxy& operator= (const T& t) { val = t; return *this; }
+};
+
/* Convert all template arguments to their appropriate types, and
return a vector containing the innermost resulting template
arguments. If any error occurs, return error_mark_node. Error and
@@ -9105,8 +9129,6 @@ coerce_template_parms (tree parms,
bool require_all_args /* = true */)
{
int nparms, nargs, parm_idx, arg_idx, lost = 0;
- tree orig_inner_args;
- tree inner_args;
/* When used as a boolean value, indicates whether this is a
variadic template parameter list. Since it's an int, we can also
@@ -9152,7 +9174,6 @@ coerce_template_parms (tree parms,
++default_p;
}
- inner_args = orig_inner_args = INNERMOST_TEMPLATE_ARGS (args);
/* If there are no parameters that follow a parameter pack, we need to
expand any argument packs so that we can deduce a parameter pack from
some non-packed args followed by an argument pack, as in variadic85.C.
@@ -9161,6 +9182,7 @@ coerce_template_parms (tree parms,
with a nested class inside a partial specialization of a class
template, as in variadic92.C, or when deducing a template parameter pack
from a sub-declarator, as in variadic114.C. */
+ free_if_changed_proxy<tree> inner_args = INNERMOST_TEMPLATE_ARGS (args);
if (!post_variadic_parms)
inner_args = expand_template_argument_pack (inner_args);
@@ -9275,7 +9297,8 @@ coerce_template_parms (tree parms,
{
/* We don't know how many args we have yet, just use the
unconverted (and still packed) ones for now. */
- new_inner_args = orig_inner_args;
+ ggc_free (new_inner_args);
+ new_inner_args = inner_args.orig;
arg_idx = nargs;
break;
}
@@ -9329,8 +9352,9 @@ coerce_template_parms (tree parms,
= make_pack_expansion (conv, complain);
/* We don't know how many args we have yet, just
- use the unconverted ones for now. */
- new_inner_args = inner_args;
+ use the unconverted (but unpacked) ones for now. */
+ ggc_free (new_inner_args);
+ new_inner_args = inner_args.release ();
arg_idx = nargs;
break;
}