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

-- 8< --

The problem here was that we were building an IMPLICIT_CONV_EXPR around a
capture proxy, so that when we try to substitute that into the alias
template we are no longer within the lambda scope and fall over.

convert_nontype_argument properly calls mark_rvalue_use, which resolves the
use of the capture to its constant value.  So instead of only adding an
IMPLICIT_CONV_EXPR wrapper, in this situation let's do the normal conversion
and then rewrite a NOP_EXPR/CONVERT_EXPR in the result to
IMPLICIT_CONV_EXPR.

        PR c++/126828
        PR c++/112632

gcc/cp/ChangeLog:

        * pt.cc (dependent_implicit_conv_p): Remove.
        (convert_nontype_argument_maybe_dependent): Rewrite
        simple conversion when force_conv.
        (tsubst_expr): Use it.

gcc/testsuite/ChangeLog:

        * g++.dg/cpp0x/alias-decl-nontype2.C: New test.
---
 gcc/cp/pt.cc                                  | 46 +++++++++----------
 .../g++.dg/cpp0x/alias-decl-nontype2.C        | 11 +++++
 2 files changed, 32 insertions(+), 25 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/cpp0x/alias-decl-nontype2.C

diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc
index 85204c5536e..6b8fbcd1c14 100644
--- a/gcc/cp/pt.cc
+++ b/gcc/cp/pt.cc
@@ -8881,19 +8881,6 @@ maybe_build_nontype_implicit_conv (tree type, tree arg, 
bool force)
   return arg;
 }
 
-/* True if we need an IMPLICIT_CONV_EXPR for converting EXPR to TYPE, possibly
-   in a FORCED context (i.e. alias or concept).  */
-
-static bool
-dependent_implicit_conv_p (tree type, tree expr, bool forced)
-{
-  return (dependent_type_p (type) || type_dependent_expression_p (expr)
-         || (forced
-             && !(same_type_ignoring_top_level_qualifiers_p
-                  (TREE_TYPE (expr), type))
-             && value_dependent_expression_p (expr)));
-}
-
 /* Convert the non-type template parameter ARG to the indicated TYPE.
    If one of them is dependent, create an appropriate conversion.
    FORCE_CONV is true in a forced context (i.e. alias or concept).  */
@@ -8903,7 +8890,7 @@ convert_nontype_argument_maybe_dependent (tree type, tree 
arg,
                                          bool force_conv,
                                          tsubst_flags_t complain)
 {
-  if (dependent_implicit_conv_p (type, arg, force_conv))
+  if (dependent_type_p (type) || type_dependent_expression_p (arg))
     {
       tree val = canonicalize_expr_argument (arg, complain);
       return maybe_build_nontype_implicit_conv (type, val, force_conv);
@@ -8917,8 +8904,24 @@ convert_nontype_argument_maybe_dependent (tree type, 
tree arg,
      deciding whether or not these conversions can occur is part of
      determining which function template to call, or whether a given
      explicit argument specification is valid.  */
-  return convert_nontype_argument (type, convert_from_reference (arg),
-                                  complain);
+  tree r = convert_nontype_argument (type, convert_from_reference (arg),
+                                    complain);
+
+  /* When force_conv, we need to express this conversion with
+     IMPLICIT_CONV_EXPR rather than NOP_EXPR so we go through
+     convert_nontype_argument again at substitution time for
+     e.g. narrowing checks.  */
+  if (force_conv && r && CONVERT_EXPR_P (r)
+      && !same_type_ignoring_top_level_qualifiers_p (type, TREE_TYPE (arg))
+      && value_dependent_expression_p (arg))
+    {
+      tree op = TREE_OPERAND (r, 0);
+      gcc_assert (same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (op),
+                                                            TREE_TYPE (arg)));
+      r = maybe_build_nontype_implicit_conv (type, op, force_conv);
+    }
+
+  return r;
 }
 
 /* Convert the indicated template ARG as necessary to match the
@@ -21789,17 +21792,10 @@ tsubst_expr (tree t, tree args, tsubst_flags_t 
complain, tree in_decl)
        if (type == error_mark_node)
          RETURN (error_mark_node);
        tree expr = RECUR (TREE_OPERAND (t, 0));
-       if (dependent_implicit_conv_p (type, expr,
-                                      IMPLICIT_CONV_EXPR_FORCED (t)))
-         {
-           retval = copy_node (t);
-           TREE_TYPE (retval) = type;
-           TREE_OPERAND (retval, 0) = expr;
-           RETURN (retval);
-         }
        if (IMPLICIT_CONV_EXPR_NONTYPE_ARG (t))
          {
-           tree r = convert_nontype_argument (type, expr, complain);
+           tree r = (convert_nontype_argument_maybe_dependent
+                     (type, expr, IMPLICIT_CONV_EXPR_FORCED (t), complain));
            if (r == NULL_TREE)
              r = error_mark_node;
            RETURN (r);
diff --git a/gcc/testsuite/g++.dg/cpp0x/alias-decl-nontype2.C 
b/gcc/testsuite/g++.dg/cpp0x/alias-decl-nontype2.C
new file mode 100644
index 00000000000..067382642bf
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp0x/alias-decl-nontype2.C
@@ -0,0 +1,11 @@
+// PR c++/126828
+// { dg-do compile { target c++11 } }
+
+template <int> class a{};
+template <int b> using c = a<b>;
+template <int> void d() {
+  constexpr unsigned blocksize = 8;
+  [&] {
+    c<blocksize> g;
+  };
+}

base-commit: 33600590ba53735410de9bf619171691b2703301
-- 
2.55.0

Reply via email to