aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2018-11-12 23:47:20 -0500
committerJason Merrill <jason@gcc.gnu.org>2018-11-12 23:47:20 -0500
commit7d119905abdf28f56486be0ca01a42f8efcea1a2 (patch)
treeea8bf50fae9497d15cbee4407a37515b686e65af /gcc/cp
parent7c23c87c93f3eafa5c22d1f4f52711d97f3a4329 (diff)
downloadgcc-7d119905abdf28f56486be0ca01a42f8efcea1a2.zip
gcc-7d119905abdf28f56486be0ca01a42f8efcea1a2.tar.gz
gcc-7d119905abdf28f56486be0ca01a42f8efcea1a2.tar.bz2
Avoid double substitution with complete explicit template arguments.
Previously, when we got a function template with explicit arguments for all of the template parameters, we still did "deduction", which of course couldn't deduce anything, but did other deduction-time checking of non-dependent conversions and such. This broke down with the unevaluated lambdas patch (to follow): substituting into the lambda multiple times, once to get the function type for deduction and then again to generate the actual decl, doesn't work, since different substitutions of a lambda produce different types. I believe that skipping the initial substitution when we have all the arguments is still conformant, and produces better diagnostics for some testcases. * pt.c (fn_type_unification): If we have a full set of explicit arguments, go straight to substitution. From-SVN: r266055
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog3
-rw-r--r--gcc/cp/pt.c75
2 files changed, 47 insertions, 31 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 79c162c..5cd1471 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,5 +1,8 @@
2018-11-12 Jason Merrill <jason@redhat.com>
+ * pt.c (fn_type_unification): If we have a full set of explicit
+ arguments, go straight to substitution.
+
* decl2.c (min_vis_expr_r, expr_visibility): New.
(min_vis_r): Call expr_visibility.
(constrain_visibility_for_template): Likewise.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 0c33c8e..f948aef 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -19800,6 +19800,11 @@ fn_type_unification (tree fn,
tsubst_flags_t complain = (explain_p ? tf_warning_or_error : tf_none);
bool ok;
static int deduction_depth;
+ /* type_unification_real will pass back any access checks from default
+ template argument substitution. */
+ vec<deferred_access_check, va_gc> *checks = NULL;
+ /* We don't have all the template args yet. */
+ bool incomplete = true;
tree orig_fn = fn;
if (flag_new_inheriting_ctors)
@@ -19857,7 +19862,7 @@ fn_type_unification (tree fn,
template results in an invalid type, type deduction fails. */
int i, len = TREE_VEC_LENGTH (tparms);
location_t loc = input_location;
- bool incomplete = false;
+ incomplete = false;
if (explicit_targs == error_mark_node)
goto fail;
@@ -19923,33 +19928,52 @@ fn_type_unification (tree fn,
}
}
- if (!push_tinst_level (fn, explicit_targs))
+ if (incomplete)
{
- excessive_deduction_depth = true;
- goto fail;
- }
- processing_template_decl += incomplete;
- input_location = DECL_SOURCE_LOCATION (fn);
- /* Ignore any access checks; we'll see them again in
- instantiate_template and they might have the wrong
- access path at this point. */
- push_deferring_access_checks (dk_deferred);
- fntype = tsubst (TREE_TYPE (fn), explicit_targs,
- complain | tf_partial | tf_fndecl_type, NULL_TREE);
- pop_deferring_access_checks ();
- input_location = loc;
- processing_template_decl -= incomplete;
- pop_tinst_level ();
+ if (!push_tinst_level (fn, explicit_targs))
+ {
+ excessive_deduction_depth = true;
+ goto fail;
+ }
+ ++processing_template_decl;
+ input_location = DECL_SOURCE_LOCATION (fn);
+ /* Ignore any access checks; we'll see them again in
+ instantiate_template and they might have the wrong
+ access path at this point. */
+ push_deferring_access_checks (dk_deferred);
+ tsubst_flags_t ecomplain = complain | tf_partial | tf_fndecl_type;
+ fntype = tsubst (TREE_TYPE (fn), explicit_targs, ecomplain, NULL_TREE);
+ pop_deferring_access_checks ();
+ input_location = loc;
+ --processing_template_decl;
+ pop_tinst_level ();
- if (fntype == error_mark_node)
- goto fail;
+ if (fntype == error_mark_node)
+ goto fail;
+ }
/* Place the explicitly specified arguments in TARGS. */
explicit_targs = INNERMOST_TEMPLATE_ARGS (explicit_targs);
for (i = NUM_TMPL_ARGS (explicit_targs); i--;)
TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (explicit_targs, i);
+ if (!incomplete && CHECKING_P
+ && !NON_DEFAULT_TEMPLATE_ARGS_COUNT (targs))
+ SET_NON_DEFAULT_TEMPLATE_ARGS_COUNT
+ (targs, NUM_TMPL_ARGS (explicit_targs));
+ }
+
+ if (return_type && strict != DEDUCE_CALL)
+ {
+ tree *new_args = XALLOCAVEC (tree, nargs + 1);
+ new_args[0] = return_type;
+ memcpy (new_args + 1, args, nargs * sizeof (tree));
+ args = new_args;
+ ++nargs;
}
+ if (!incomplete)
+ goto deduced;
+
/* Never do unification on the 'this' parameter. */
parms = skip_artificial_parms_for (fn, TYPE_ARG_TYPES (fntype));
@@ -19963,14 +19987,7 @@ fn_type_unification (tree fn,
}
else if (return_type)
{
- tree *new_args;
-
parms = tree_cons (NULL_TREE, TREE_TYPE (fntype), parms);
- new_args = XALLOCAVEC (tree, nargs + 1);
- new_args[0] = return_type;
- memcpy (new_args + 1, args, nargs * sizeof (tree));
- args = new_args;
- ++nargs;
}
/* We allow incomplete unification without an error message here
@@ -19988,11 +20005,6 @@ fn_type_unification (tree fn,
goto fail;
}
- /* type_unification_real will pass back any access checks from default
- template argument substitution. */
- vec<deferred_access_check, va_gc> *checks;
- checks = NULL;
-
ok = !type_unification_real (DECL_INNERMOST_TEMPLATE_PARMS (fn),
full_targs, parms, args, nargs, /*subr=*/0,
strict, &checks, explain_p);
@@ -20035,6 +20047,7 @@ fn_type_unification (tree fn,
convs, explain_p))
goto fail;
+ deduced:
/* All is well so far. Now, check:
[temp.deduct]