PR c++/89852 - ICE with C++11 functional cast with { }.
authorMarek Polacek <polacek@redhat.com>
Sun, 31 Mar 2019 20:37:22 +0000 (20:37 +0000)
committerMarek Polacek <mpolacek@gcc.gnu.org>
Sun, 31 Mar 2019 20:37:22 +0000 (20:37 +0000)
* constexpr.c (fold_non_dependent_expr_template): New static function
broken out of...
(fold_non_dependent_expr): ...here.
(fold_non_dependent_init): New function.
* cp-tree.h (fold_non_dependent_init): Declare.
* typeck2.c (massage_init_elt): Call fold_non_dependent_init instead
of fold_non_dependent_expr.  Don't call maybe_constant_init.

* g++.dg/cpp0x/initlist115.C: New test.

From-SVN: r270048

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/cp/cp-tree.h
gcc/cp/typeck2.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/cpp0x/initlist115.C [new file with mode: 0644]

index 8a5e9209b34143511e4a077ad1b5f82c64a5336e..8c6e9931db161361e59663ad7a348e9bbfbb8246 100644 (file)
@@ -1,3 +1,14 @@
+2019-03-31  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/89852 - ICE with C++11 functional cast with { }.
+       * constexpr.c (fold_non_dependent_expr_template): New static function
+       broken out of...
+       (fold_non_dependent_expr): ...here.
+       (fold_non_dependent_init): New function.
+       * cp-tree.h (fold_non_dependent_init): Declare.
+       * typeck2.c (massage_init_elt): Call fold_non_dependent_init instead
+       of fold_non_dependent_expr.  Don't call maybe_constant_init.
+
 2019-03-30  Jason Merrill  <jason@redhat.com>
 
        PR c++/89744 - ICE with specialization of member class template.
index daf34e1078418b239fa3b49bac991aba01a4e6e5..53854a8acd4a08ef5310a334584159c9f70b46bb 100644 (file)
@@ -5581,6 +5581,58 @@ clear_cv_and_fold_caches (void)
   clear_fold_cache ();
 }
 
+/* Internal function handling expressions in templates for
+   fold_non_dependent_expr and fold_non_dependent_init.
+
+   If we're in a template, but T isn't value dependent, simplify
+   it.  We're supposed to treat:
+
+     template <typename T> void f(T[1 + 1]);
+     template <typename T> void f(T[2]);
+
+   as two declarations of the same function, for example.  */
+
+static tree
+fold_non_dependent_expr_template (tree t, tsubst_flags_t complain,
+                                 bool manifestly_const_eval)
+{
+  gcc_assert (processing_template_decl);
+
+  if (is_nondependent_constant_expression (t))
+    {
+      processing_template_decl_sentinel s;
+      t = instantiate_non_dependent_expr_internal (t, complain);
+
+      if (type_unknown_p (t) || BRACE_ENCLOSED_INITIALIZER_P (t))
+       {
+         if (TREE_OVERFLOW_P (t))
+           {
+             t = build_nop (TREE_TYPE (t), t);
+             TREE_CONSTANT (t) = false;
+           }
+         return t;
+       }
+
+      tree r = cxx_eval_outermost_constant_expr (t, true, true,
+                                                manifestly_const_eval,
+                                                NULL_TREE);
+      /* cp_tree_equal looks through NOPs, so allow them.  */
+      gcc_checking_assert (r == t
+                          || CONVERT_EXPR_P (t)
+                          || TREE_CODE (t) == VIEW_CONVERT_EXPR
+                          || (TREE_CONSTANT (t) && !TREE_CONSTANT (r))
+                          || !cp_tree_equal (r, t));
+      return r;
+    }
+  else if (TREE_OVERFLOW_P (t))
+    {
+      t = build_nop (TREE_TYPE (t), t);
+      TREE_CONSTANT (t) = false;
+    }
+
+  return t;
+}
+
 /* Like maybe_constant_value but first fully instantiate the argument.
 
    Note: this is equivalent to instantiate_non_dependent_expr_sfinae
@@ -5604,51 +5656,39 @@ fold_non_dependent_expr (tree t,
   if (t == NULL_TREE)
     return NULL_TREE;
 
-  /* If we're in a template, but T isn't value dependent, simplify
-     it.  We're supposed to treat:
+  if (processing_template_decl)
+    return fold_non_dependent_expr_template (t, complain,
+                                            manifestly_const_eval);
 
-       template <typename T> void f(T[1 + 1]);
-       template <typename T> void f(T[2]);
+  return maybe_constant_value (t, NULL_TREE, manifestly_const_eval);
+}
 
-     as two declarations of the same function, for example.  */
-  if (processing_template_decl)
-    {
-      if (is_nondependent_constant_expression (t))
-       {
-         processing_template_decl_sentinel s;
-         t = instantiate_non_dependent_expr_internal (t, complain);
 
-         if (type_unknown_p (t)
-             || BRACE_ENCLOSED_INITIALIZER_P (t))
-           {
-             if (TREE_OVERFLOW_P (t))
-               {
-                 t = build_nop (TREE_TYPE (t), t);
-                 TREE_CONSTANT (t) = false;
-               }
-             return t;
-           }
+/* Like maybe_constant_init but first fully instantiate the argument.  */
 
-         tree r = cxx_eval_outermost_constant_expr (t, true, true,
-                                                    manifestly_const_eval,
-                                                    NULL_TREE);
-         /* cp_tree_equal looks through NOPs, so allow them.  */
-         gcc_checking_assert (r == t
-                              || CONVERT_EXPR_P (t)
-                              || TREE_CODE (t) == VIEW_CONVERT_EXPR
-                              || (TREE_CONSTANT (t) && !TREE_CONSTANT (r))
-                              || !cp_tree_equal (r, t));
-         return r;
-       }
-      else if (TREE_OVERFLOW_P (t))
+tree
+fold_non_dependent_init (tree t,
+                        tsubst_flags_t complain /*=tf_warning_or_error*/,
+                        bool manifestly_const_eval /*=false*/)
+{
+  if (t == NULL_TREE)
+    return NULL_TREE;
+
+  if (processing_template_decl)
+    {
+      t = fold_non_dependent_expr_template (t, complain,
+                                           manifestly_const_eval);
+      /* maybe_constant_init does this stripping, so do it here too.  */
+      if (TREE_CODE (t) == TARGET_EXPR)
        {
-         t = build_nop (TREE_TYPE (t), t);
-         TREE_CONSTANT (t) = false;
+         tree init = TARGET_EXPR_INITIAL (t);
+         if (TREE_CODE (init) == CONSTRUCTOR)
+           t = init;
        }
       return t;
     }
 
-  return maybe_constant_value (t, NULL_TREE, manifestly_const_eval);
+  return maybe_constant_init (t, NULL_TREE, manifestly_const_eval);
 }
 
 /* Like maybe_constant_value, but returns a CONSTRUCTOR directly, rather
index 5915275382555d35de45ae396a28f4f31945298d..b87b968fa4e555ff2a0ed73b189df148cc9cde20 100644 (file)
@@ -7716,6 +7716,9 @@ extern tree maybe_constant_init                   (tree, tree = NULL_TREE, bool = false);
 extern tree fold_non_dependent_expr            (tree,
                                                 tsubst_flags_t = tf_warning_or_error,
                                                 bool = false);
+extern tree fold_non_dependent_init            (tree,
+                                                tsubst_flags_t = tf_warning_or_error,
+                                                bool = false);
 extern tree fold_simple                                (tree);
 extern bool is_sub_constant_expr                (tree);
 extern bool reduced_constant_expression_p       (tree);
index 7f242ba93daa3f236ef91d57442c46d766f9ebec..fa98b1cb8b5595a4fd34a438197493996d9eb917 100644 (file)
@@ -1346,8 +1346,7 @@ massage_init_elt (tree type, tree init, int nested, int flags,
     init = TARGET_EXPR_INITIAL (init);
   /* When we defer constant folding within a statement, we may want to
      defer this folding as well.  */
-  tree t = fold_non_dependent_expr (init, complain);
-  t = maybe_constant_init (t);
+  tree t = fold_non_dependent_init (init, complain);
   if (TREE_CONSTANT (t))
     init = t;
   return init;
index 3c173b5b7265a2cec7c4d1781189de2f56acb6b6..deb903bdc69eb202a64d8584607bc36f6f4a6d7d 100644 (file)
@@ -1,3 +1,8 @@
+2019-03-31  Marek Polacek  <polacek@redhat.com>
+
+       PR c++/89852 - ICE with C++11 functional cast with { }.
+       * g++.dg/cpp0x/initlist115.C: New test.
+
 2019-03-31  Harald Anlauf  <anlauf@gmx.de>
 
        PR fortran/83515
diff --git a/gcc/testsuite/g++.dg/cpp0x/initlist115.C b/gcc/testsuite/g++.dg/cpp0x/initlist115.C
new file mode 100644 (file)
index 0000000..ee4b6d4
--- /dev/null
@@ -0,0 +1,18 @@
+// PR c++/89852
+// { dg-do compile { target c++11 } }
+
+struct A {
+  int b;
+};
+
+struct B {
+  A g;
+};
+
+const auto j = A{};
+
+template <typename>
+void k()
+{
+  B{j};
+}