If require_all_args, we aren't waiting for more args to be deduced later.

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

        * pt.c (coerce_template_parms): Do add empty pack when
        require_all_args.
---
 gcc/cp/pt.c                              |  2 +-
 gcc/testsuite/g++.dg/cpp1y/var-templ62.C | 80 ++++++++++++++++++++++++
 gcc/cp/ChangeLog                         |  6 ++
 3 files changed, 87 insertions(+), 1 deletion(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp1y/var-templ62.C

diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index 5f73fac3e8f..e682b6d51be 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -8477,7 +8477,7 @@ coerce_template_parms (tree parms,
        arg = NULL_TREE;
 
       if (template_parameter_pack_p (TREE_VALUE (parm))
-         && (arg || !(complain & tf_partial))
+         && (arg || require_all_args || !(complain & tf_partial))
          && !(arg && ARGUMENT_PACK_P (arg)))
         {
          /* Some arguments will be placed in the
diff --git a/gcc/testsuite/g++.dg/cpp1y/var-templ62.C 
b/gcc/testsuite/g++.dg/cpp1y/var-templ62.C
new file mode 100644
index 00000000000..f78ca858ce9
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp1y/var-templ62.C
@@ -0,0 +1,80 @@
+// PR c++/90227
+// { dg-do compile { target c++14 } }
+
+template <int b> struct c { static constexpr int d = b; typedef c e; };
+template <bool, typename a> using f = a;
+template <bool g> using h = c<g>;
+template <int g> using i = c<g>;
+template <typename...> struct ab {};
+template <typename... j> struct k { using e = ab<j...>; };
+template <typename> struct ad;
+template <typename j, typename... l> struct ad<ab<j, l...>> { using e = 
ab<l...>; };
+template <typename> struct ae;
+template <typename... m> struct ae<ab<m...>> : i<sizeof...(m)> {};
+template <typename af, int, int = ae<af>::d> struct ag;
+template <typename... m> struct ag<ab<m...>, 0, 0> { using e = ab<>; };
+template <typename... m, int ah>
+struct ag<ab<m...>, 0, ah> : k<typename ag<typename ad<ab<m...>>::e, ah - 
1>::e> {};
+template <typename... m, int ai, int ah>
+struct ag<ab<m...>, ai, ah> : ag<typename ad<ab<m...>>::e, ai - 1> {};
+template <typename, template <typename> class> struct aj;
+template <typename... j, template <typename> class ak> struct aj<ab<j...>, ak> 
{
+  using e = ab<typename ak<j>::e...>;
+};
+template <unsigned long> struct an;
+struct ao { typedef an<0> ap; };
+template <typename a, a...> struct aq {};
+template <typename, typename = ao::ap> struct as;
+template <typename a, unsigned long... at> struct as<a, an<at...>> { typedef 
aq<a> ap; };
+template <typename a, a> using au = typename as<a>::ap;
+template <long... at> using av = aq<unsigned long, at...>;
+template <long ar> using aw = au<unsigned long, ar>;
+struct ay { using e = h<c<false>::d>; };
+template <typename, template <typename> class, typename...>
+struct bb : ay::e {};
+struct bd { using e = av<>; };
+struct bg { using e = bd::e; };
+namespace bi {
+enum bj { bk };
+struct bo { enum n { bp }; };
+struct bq { bool br; static const bo::n bs = bo::bp; };
+template <typename bv> struct bw { using e = bv; };
+template <typename, bj, int, typename...> class bx;
+template <typename bv, bj by, int bz, typename... j, long... anchors>
+struct bx<bv, by, bz, ab<j...>, av<anchors...>> : bo {
+  static const n bs = bv::bs;
+  static const long ca = sizeof bv::br;
+  using cb = int;
+  using cc = ab<j...>;
+  using cd = typename ag<cc, bz>::e;
+  using ce = typename ag<cc, bz>::e;
+  using cf = aw<ca>;
+  using cg = typename bw<bv>::e;
+  using ch = decltype(cg()(cb(), cd(), ce(), cf()));
+};
+class ck;
+template <typename> struct cl : c<false> {};
+template <typename bv, bj by, int bz, typename... j>
+struct bx<bv, by, bz, ab<j...>> : public bx<bv, by, bz, typename aj<ab<j...>, 
cl>::e, bg::e> {};
+}
+using bi::bj;
+using bi::ck;
+template <typename cn> class co {
+  template <typename p> co(p) { c<cn::bs>(); }
+  static co o;
+};
+namespace bi {
+template <typename> class cp;
+template <typename j> using cq = bb<j, cp>;
+template <typename, typename cr> void cs(cr, f<cq<cr>::d, void *> = nullptr);
+}
+using bi::cs;
+struct cu : bi::bq {
+  template <typename... cw, typename... cx>
+  auto operator()(int q, ab<cw...>, ab<cx...>, av<>) {
+    cs<cw...>(q);
+  }
+};
+template <>
+co<bi::bx<cu, bj::bk, 1, ab<int, ck>>>
+co<bi::bx<cu, bj::bk, 1, ab<int, ck>>>::o(0);
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 3a6dc65dd5e..059a7fd0ea6 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,9 @@
+2019-04-24  Jason Merrill  <ja...@redhat.com>
+
+       PR c++/90227 - error with template parameter packs.
+       * pt.c (coerce_template_parms): Do add empty pack when
+       require_all_args.
+
 2019-04-24  Richard Biener  <rguent...@suse.de>
 
        * call.c (null_ptr_cst_p): Order checks according to expensiveness.

base-commit: b66add0735ce28186c6cc3494c24200b75deeb73
-- 
2.20.1

Reply via email to