aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gcc/cp/ChangeLog3
-rw-r--r--gcc/cp/pt.c75
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/decltype48.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/diag1.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/error4.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/pr77655.C2
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C16
-rw-r--r--gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C10
8 files changed, 61 insertions, 51 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]
diff --git a/gcc/testsuite/g++.dg/cpp0x/decltype48.C b/gcc/testsuite/g++.dg/cpp0x/decltype48.C
index 39fc4eb..7f5005b 100644
--- a/gcc/testsuite/g++.dg/cpp0x/decltype48.C
+++ b/gcc/testsuite/g++.dg/cpp0x/decltype48.C
@@ -6,7 +6,7 @@ template<typename T> struct baz { };
template<typename T> T bar();
template<typename T, typename ... U>
-baz<decltype(bar<Int>(bar<U>() ...))> // { dg-error "no match" }
+baz<decltype(bar<Int>(bar<U>() ...))> // { dg-error "" }
foo();
int main()
diff --git a/gcc/testsuite/g++.dg/cpp0x/diag1.C b/gcc/testsuite/g++.dg/cpp0x/diag1.C
index 9bf7cfe..1f8c4a4 100644
--- a/gcc/testsuite/g++.dg/cpp0x/diag1.C
+++ b/gcc/testsuite/g++.dg/cpp0x/diag1.C
@@ -23,7 +23,7 @@ struct TypeC
// TypeC::fn()
// we don't want to see the template header, return type, or parameter bindings
// for TypeB::fn.
- template <int N> auto fn() -> decltype(b.fn<N>()); // { dg-bogus "typename|with" }
+ template <int N> auto fn() -> decltype(b.fn<N>()); // { dg-bogus "typename" }
};
int main()
diff --git a/gcc/testsuite/g++.dg/cpp0x/error4.C b/gcc/testsuite/g++.dg/cpp0x/error4.C
index bd73b2a7..1f365b7 100644
--- a/gcc/testsuite/g++.dg/cpp0x/error4.C
+++ b/gcc/testsuite/g++.dg/cpp0x/error4.C
@@ -12,7 +12,7 @@ struct S {
template<typename U>
static decltype(*declval<U>()) get(...); // { dg-error "operator*" }
- typedef decltype(get<T>(declval<T>())) type; // { dg-error "no match" }
+ typedef decltype(get<T>(declval<T>())) type; // { dg-error "" }
};
struct X { };
diff --git a/gcc/testsuite/g++.dg/cpp0x/pr77655.C b/gcc/testsuite/g++.dg/cpp0x/pr77655.C
index ab2e942..8b4ffa6 100644
--- a/gcc/testsuite/g++.dg/cpp0x/pr77655.C
+++ b/gcc/testsuite/g++.dg/cpp0x/pr77655.C
@@ -3,7 +3,7 @@
template <class F> void g(F);
template <class... A>
-auto h(A &&... a) -> decltype(g(0, g<decltype(a)>(a)...)) { // { dg-error "no matching" }
+auto h(A &&... a) -> decltype(g(0, g<decltype(a)>(a)...)) { // { dg-error "" }
h([] {}); // { dg-error "no matching" }
}
diff --git a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C
index f74f8d3..b19655d 100644
--- a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C
+++ b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch-2.C
@@ -134,21 +134,17 @@ int test_7 (int one, T two, float three); // { dg-line test_7_decl }
int test_7 (int first, const char *second, float third)
{
return test_7 <const char **> (first, second, third); // { dg-line test_7_usage }
- // { dg-error "no matching function" "" { target *-*-* } test_7_usage }
+ // { dg-message "cannot convert 'const char\\*' to 'const char\\*\\*'" "" { target *-*-* } test_7_usage }
/* { dg-begin-multiline-output "" }
return test_7 <const char **> (first, second, third);
- ^
+ ^~~~~~
+ |
+ const char*
{ dg-end-multiline-output "" } */
- // { dg-message "candidate: 'template<class T> int test_7\\(int, T, float\\)'" "" { target *-*-* } test_7_decl }
+ // { dg-message "initializing argument 2 of 'int test_7\\(int, T, float\\) .with T = const char\\*\\*.'" "" { target *-*-* } test_7_decl }
/* { dg-begin-multiline-output "" }
int test_7 (int one, T two, float three);
- ^~~~~~
- { dg-end-multiline-output "" } */
- // { dg-message "template argument deduction/substitution failed:" "" { target *-*-* } test_7_decl }
- // { dg-message "cannot convert 'second' \\(type 'const char\\*'\\) to type 'const char\\*\\*'" "" { target *-*-* } test_7_usage }
- /* { dg-begin-multiline-output "" }
- return test_7 <const char **> (first, second, third);
- ^~~~~~
+ ~~^~~
{ dg-end-multiline-output "" } */
}
diff --git a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
index 50bbd4a..cb5c360 100644
--- a/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
+++ b/gcc/testsuite/g++.dg/diagnostic/param-type-mismatch.C
@@ -130,18 +130,16 @@ int test_7 (int one, T two, float three);
int test_7 (int first, int second, float third)
{
- return test_7 <const char *> (first, second, third); // { dg-error "no matching function" }
- /* { dg-begin-multiline-output "" }
- return test_7 <const char *> (first, second, third);
- ^
- { dg-end-multiline-output "" } */
+ return test_7 <const char *> (first, second, third); // { dg-error "invalid conversion from 'int' to 'const char\\*'" }
/* { dg-begin-multiline-output "" }
return test_7 <const char *> (first, second, third);
^~~~~~
+ |
+ int
{ dg-end-multiline-output "" } */
/* { dg-begin-multiline-output "" }
int test_7 (int one, T two, float three);
- ^~~~~~
+ ~~^~~
{ dg-end-multiline-output "" } */
}