aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2018-06-04 09:22:52 -0400
committerJason Merrill <jason@gcc.gnu.org>2018-06-04 09:22:52 -0400
commit92a38cfd775c045d7ed8b989b231410849fc22fe (patch)
tree0931316aa775c55c29c9f1c229082afea2bd3b05 /gcc
parent1ccaa21f0cdab09acd959883dd4d5a68692807dd (diff)
downloadgcc-92a38cfd775c045d7ed8b989b231410849fc22fe.zip
gcc-92a38cfd775c045d7ed8b989b231410849fc22fe.tar.gz
gcc-92a38cfd775c045d7ed8b989b231410849fc22fe.tar.bz2
PR c++/85765 - SFINAE and non-type default template arg.
* pt.c (type_unification_real): Do full semantic processing if substituting a partial args list replaces all template parms. From-SVN: r261146
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog6
-rw-r--r--gcc/cp/pt.c30
-rw-r--r--gcc/testsuite/g++.dg/cpp0x/fntmpdefarg10.C18
3 files changed, 47 insertions, 7 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 5d4cacc..773e933 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2018-06-04 Jason Merrill <jason@redhat.com>
+
+ PR c++/85765 - SFINAE and non-type default template arg.
+ * pt.c (type_unification_real): Do full semantic processing if
+ substituting a partial args list replaces all template parms.
+
2018-06-03 Jason Merrill <jason@redhat.com>
PR c++/85739 - ICE with pointer to member template parm.
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 4c5890d..d3915dd 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -20387,8 +20387,6 @@ type_unification_real (tree tparms,
location_t save_loc = input_location;
if (DECL_P (parm))
input_location = DECL_SOURCE_LOCATION (parm);
- if (saw_undeduced == 1)
- ++processing_template_decl;
if (saw_undeduced == 1
&& TREE_CODE (parm) == PARM_DECL
@@ -20396,11 +20394,14 @@ type_unification_real (tree tparms,
{
/* The type of this non-type parameter depends on undeduced
parameters. Don't try to use its default argument yet,
+ since we might deduce an argument for it on the next pass,
but do check whether the arguments we already have cause
substitution failure, so that that happens before we try
later default arguments (78489). */
+ ++processing_template_decl;
tree type = tsubst (TREE_TYPE (parm), full_targs, complain,
NULL_TREE);
+ --processing_template_decl;
if (type == error_mark_node)
arg = error_mark_node;
else
@@ -20408,10 +20409,27 @@ type_unification_real (tree tparms,
}
else
{
- arg = tsubst_template_arg (arg, full_targs, complain, NULL_TREE);
+ tree substed = NULL_TREE;
+ if (saw_undeduced == 1 && processing_template_decl == 0)
+ {
+ /* First instatiate in template context, in case we still
+ depend on undeduced template parameters. */
+ ++processing_template_decl;
+ substed = tsubst_template_arg (arg, full_targs, complain,
+ NULL_TREE);
+ --processing_template_decl;
+ if (substed != error_mark_node
+ && !uses_template_parms (substed))
+ /* We replaced all the tparms, substitute again out of
+ template context. */
+ substed = NULL_TREE;
+ }
+ if (!substed)
+ substed = tsubst_template_arg (arg, full_targs, complain,
+ NULL_TREE);
- if (!uses_template_parms (arg))
- arg = convert_template_argument (parm, arg, full_targs,
+ if (!uses_template_parms (substed))
+ arg = convert_template_argument (parm, substed, full_targs,
complain, i, NULL_TREE);
else if (saw_undeduced == 1)
arg = NULL_TREE;
@@ -20419,8 +20437,6 @@ type_unification_real (tree tparms,
arg = error_mark_node;
}
- if (saw_undeduced == 1)
- --processing_template_decl;
input_location = save_loc;
*checks = get_deferred_access_checks ();
pop_deferring_access_checks ();
diff --git a/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg10.C b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg10.C
new file mode 100644
index 0000000..f0f9dfb
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/fntmpdefarg10.C
@@ -0,0 +1,18 @@
+// PR c++/85765
+// { dg-do compile { target c++11 } }
+
+struct il { il(); il(const il&); };
+
+int* begin(il);
+
+template<class T> T&& declval();
+
+template<class T, class U = decltype(begin(declval<T&>())), decltype(*U(),0) = 0>
+U g(T& t, long) { return begin(t); } // #1
+
+template<class T>
+int g(T& t, ...); // #2
+
+volatile il a;
+
+auto n = g(a, 0); // calls #1 and ends with a hard error, should call #2