c++: Fix class NTTP with template arguments [PR92948]
authorMarek Polacek <polacek@redhat.com>
Tue, 28 Jan 2020 22:44:21 +0000 (17:44 -0500)
committerMarek Polacek <polacek@redhat.com>
Wed, 29 Jan 2020 19:07:58 +0000 (14:07 -0500)
commit423284053ec51832bc4c823fb90dc41e632e37ac
tree31c68739d30bdd25bb42e502b72f14664e4d0a80
parent0a8f4febf75e9e44f847b65776d7f5f38940b3bf
c++: Fix class NTTP with template arguments [PR92948]

This PR points out an ICE with an alias template and class NTTP, but I
found that there are more issues.  Trouble arise when we use a
(non-type) template parameter as an argument to the template arg list of
a template that accepts a class NTTP and a conversion to a class is
involved, e.g.

  struct A { A(int) { } };
  template<A a> struct B { };

  template<int X> void fn () {
      B<X> b;
  }

Normally for such a conversion we create a TARGET_EXPR with an
AGGR_INIT_EXPR that calls a __ct_comp with some arguments, but not in
this case: when converting X to type A in convert_nontype_argument we
are in a template and the template parameter 'X' is value-dependent, and
AGGR_INIT_EXPR don't work in templates.  So it just creates a TARGET_EXPR
that contains "A::A(*this, X)", but with that overload resolution fails:
  error: no matching function for call to 'A::A(A*, int)'
That happens because finish_call_expr for a BASELINK creates a dummy
object, so we have 'this' twice.  I thought for the value-dependent case
we could use IMPLICIT_CONV_EXPR, as in the patch below.  Note that I
only do this when we convert to a different type than the type of the
expr.  The point is to avoid the call to a converting ctor.

The second issue was an ICE in tsubst_copy: when there's a conversion
like the above involved then
 /* Wrapper to make a C++20 template parameter object const.  */
  op = tsubst_copy (op, args, complain, in_decl);
might not produce a _ZT... VAR_DECL with const type, so the assert
  gcc_assert (CP_TYPE_CONST_P (TREE_TYPE (op)));
fails.  Allowing IMPLICIT_CONV_EXPR there probably makes sense.

And since convert_nontype_argument uses value_dependent_expression_p
a lot, I used a dedicated bool to speed things up.

2020-01-29  Marek Polacek  <polacek@redhat.com>

PR c++/92948 - Fix class NTTP with template arguments.
* pt.c (convert_nontype_argument): Use IMPLICIT_CONV_EXPR when
converting a value-dependent expression to a class type.
(tsubst_copy) <case VIEW_CONVERT_EXPR>: Allow IMPLICIT_CONV_EXPR
as the result of the tsubst_copy call.

* g++.dg/cpp2a/nontype-class28.C: New test.
* g++.dg/cpp2a/nontype-class29.C: New test.
gcc/cp/ChangeLog
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp2a/nontype-class28.C [new file with mode: 0644]
gcc/testsuite/g++.dg/cpp2a/nontype-class29.C [new file with mode: 0644]