PR c++/82360 - ICE with static_cast in template.
authorJason Merrill <jason@redhat.com>
Mon, 13 Nov 2017 21:49:16 +0000 (16:49 -0500)
committerJason Merrill <jason@gcc.gnu.org>
Mon, 13 Nov 2017 21:49:16 +0000 (16:49 -0500)
* call.c (perform_direct_initialization_if_possible): Check
processing_template_decl.
* typeck.c (build_static_cast_1): Likewise.

From-SVN: r254710

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/typeck.c
gcc/testsuite/g++.dg/template/cast5.C [new file with mode: 0644]

index 73fa99967edc0bfb6d8a8b37152093dc41fe098e..37741f6fdc3b571e1b9152bb4b7d7de4a9c35d84 100644 (file)
@@ -1,3 +1,10 @@
+2017-11-13  Jason Merrill  <jason@redhat.com>
+
+       PR c++/82360 - ICE with static_cast in template.
+       * call.c (perform_direct_initialization_if_possible): Check
+       processing_template_decl.
+       * typeck.c (build_static_cast_1): Likewise.
+
 2017-11-13  Ville Voutilainen  <ville.voutilainen@gmail.com>
 
        Remove the null check from placement new in all modes
index 6875492e68708877a797406fd6d7972a4c45244b..e6e0f9011668d6200d85e08be7a5481df174eb0d 100644 (file)
@@ -10647,6 +10647,16 @@ perform_direct_initialization_if_possible (tree type,
                              LOOKUP_NORMAL, complain);
   if (!conv || conv->bad_p)
     expr = NULL_TREE;
+  else if (processing_template_decl && conv->kind != ck_identity)
+    {
+      /* In a template, we are only concerned about determining the
+        type of non-dependent expressions, so we do not have to
+        perform the actual conversion.  But for initializers, we
+        need to be able to perform it at instantiation
+        (or instantiate_non_dependent_expr) time.  */
+      expr = build1 (IMPLICIT_CONV_EXPR, type, expr);
+      IMPLICIT_CONV_EXPR_DIRECT_INIT (expr) = true;
+    }
   else
     expr = convert_like_real (conv, expr, NULL_TREE, 0,
                              /*issue_conversion_warnings=*/false,
index 9130c10f3908f573f176e02fe2b8b22ab5bc61d6..38ec363dc95a1b2c14eef9262dfb12333a1702de 100644 (file)
@@ -6820,6 +6820,9 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
     {
       tree base;
 
+      if (processing_template_decl)
+       return expr;
+
       /* There is a standard conversion from "D*" to "B*" even if "B"
         is ambiguous or inaccessible.  If this is really a
         static_cast, then we check both for inaccessibility and
@@ -6864,6 +6867,8 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
       && reference_related_p (TREE_TYPE (type), intype)
       && (c_cast_p || at_least_as_qualified_p (TREE_TYPE (type), intype)))
     {
+      if (processing_template_decl)
+       return expr;
       if (clk == clk_ordinary)
        {
          /* Handle the (non-bit-field) lvalue case here by casting to
@@ -6911,6 +6916,9 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
                                                      c_cast_p, complain);
   if (result)
     {
+      if (processing_template_decl)
+       return expr;
+
       result = convert_from_reference (result);
 
       /* [expr.static.cast]
@@ -6952,7 +6960,11 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
        || SCALAR_FLOAT_TYPE_P (type))
       && (INTEGRAL_OR_ENUMERATION_TYPE_P (intype)
          || SCALAR_FLOAT_TYPE_P (intype)))
-    return ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL, complain);
+    {
+      if (processing_template_decl)
+       return expr;
+      return ocp_convert (type, expr, CONV_C_CAST, LOOKUP_NORMAL, complain);
+    }
 
   if (TYPE_PTR_P (type) && TYPE_PTR_P (intype)
       && CLASS_TYPE_P (TREE_TYPE (type))
@@ -6965,6 +6977,9 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
     {
       tree base;
 
+      if (processing_template_decl)
+       return expr;
+
       if (!c_cast_p
          && check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR,
                                               complain))
@@ -7019,6 +7034,8 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
                                                   STATIC_CAST_EXPR,
                                                   complain))
            return error_mark_node;
+         if (processing_template_decl)
+           return expr;
          return convert_ptrmem (type, expr, /*allow_inverse_p=*/1,
                                 c_cast_p, complain);
        }
@@ -7038,6 +7055,8 @@ build_static_cast_1 (tree type, tree expr, bool c_cast_p,
          && check_for_casting_away_constness (intype, type, STATIC_CAST_EXPR,
                                               complain))
        return error_mark_node;
+      if (processing_template_decl)
+       return expr;
       return build_nop (type, expr);
     }
 
diff --git a/gcc/testsuite/g++.dg/template/cast5.C b/gcc/testsuite/g++.dg/template/cast5.C
new file mode 100644 (file)
index 0000000..4e48d1d
--- /dev/null
@@ -0,0 +1,8 @@
+// PR c++/82360
+// { dg-do compile { target c++11 } }
+
+class a {};
+template <class> class b {
+  b(b &&c) : d(static_cast<a &&>(c.d)) {}
+  a d;
+};