re PR c++/70139 (-fno-elide-constructor makes static std::regex to throw)
authorJason Merrill <jason@redhat.com>
Fri, 18 Mar 2016 20:16:05 +0000 (16:16 -0400)
committerJason Merrill <jason@gcc.gnu.org>
Fri, 18 Mar 2016 20:16:05 +0000 (16:16 -0400)
PR c++/70139
* constexpr.c (cxx_eval_call_expression): Fix trivial copy.

From-SVN: r234345

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

index 9e1dbbb29df02b948407437b51e641828a9dd801..cd98a53b0ac43ecc38a18f310fd134147c37a869 100644 (file)
@@ -1,5 +1,8 @@
 2016-03-18  Jason Merrill  <jason@redhat.com>
 
+       PR c++/70139
+       * constexpr.c (cxx_eval_call_expression): Fix trivial copy.
+
        PR c++/70147
        * class.c (vptr_via_virtual_p): New.
        (most_primary_binfo): Factor out of build_rtti_vtbl_entries.
index 5f97c9dad192bc0bc0ebe5380b85ec1b13f24872..1f496b5f9bd67b0e6989fca0b924ab8a4dd317d1 100644 (file)
@@ -1239,19 +1239,39 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
       return t;
     }
 
+  constexpr_ctx new_ctx = *ctx;
+  if (DECL_CONSTRUCTOR_P (fun) && !ctx->object
+      && TREE_CODE (t) == AGGR_INIT_EXPR)
+    {
+      /* We want to have an initialization target for an AGGR_INIT_EXPR.
+        If we don't already have one in CTX, use the AGGR_INIT_EXPR_SLOT.  */
+      new_ctx.object = AGGR_INIT_EXPR_SLOT (t);
+      tree ctor = new_ctx.ctor = build_constructor (DECL_CONTEXT (fun), NULL);
+      CONSTRUCTOR_NO_IMPLICIT_ZERO (ctor) = true;
+      ctx->values->put (new_ctx.object, ctor);
+      ctx = &new_ctx;
+    }
+
   /* Shortcut trivial constructor/op=.  */
   if (trivial_fn_p (fun))
     {
+      tree init = NULL_TREE;
       if (call_expr_nargs (t) == 2)
-       {
-         tree arg = convert_from_reference (get_nth_callarg (t, 1));
-         return cxx_eval_constant_expression (ctx, arg,
-                                              lval, non_constant_p,
-                                              overflow_p);
-       }
+       init = convert_from_reference (get_nth_callarg (t, 1));
       else if (TREE_CODE (t) == AGGR_INIT_EXPR
               && AGGR_INIT_ZERO_FIRST (t))
-       return build_zero_init (DECL_CONTEXT (fun), NULL_TREE, false);
+       init = build_zero_init (DECL_CONTEXT (fun), NULL_TREE, false);
+      if (init)
+       {
+         tree op = get_nth_callarg (t, 0);
+         if (is_dummy_object (op))
+           op = ctx->object;
+         else
+           op = build1 (INDIRECT_REF, TREE_TYPE (TREE_TYPE (op)), op);
+         tree set = build2 (MODIFY_EXPR, TREE_TYPE (op), op, init);
+         return cxx_eval_constant_expression (ctx, set, lval,
+                                              non_constant_p, overflow_p);
+       }
     }
 
   /* We can't defer instantiating the function any longer.  */
@@ -1287,19 +1307,6 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, tree t,
         }
     }
 
-  constexpr_ctx new_ctx = *ctx;
-  if (DECL_CONSTRUCTOR_P (fun) && !ctx->object
-      && TREE_CODE (t) == AGGR_INIT_EXPR)
-    {
-      /* We want to have an initialization target for an AGGR_INIT_EXPR.
-        If we don't already have one in CTX, use the AGGR_INIT_EXPR_SLOT.  */
-      new_ctx.object = AGGR_INIT_EXPR_SLOT (t);
-      tree ctor = new_ctx.ctor = build_constructor (DECL_CONTEXT (fun), NULL);
-      CONSTRUCTOR_NO_IMPLICIT_ZERO (ctor) = true;
-      ctx->values->put (new_ctx.object, ctor);
-      ctx = &new_ctx;
-    }
-
   bool non_constant_args = false;
   cxx_bind_parameters_in_call (ctx, t, &new_call,
                               non_constant_p, overflow_p, &non_constant_args);
diff --git a/gcc/testsuite/g++.dg/cpp0x/constexpr-trivial1.C b/gcc/testsuite/g++.dg/cpp0x/constexpr-trivial1.C
new file mode 100644 (file)
index 0000000..f4b74a7
--- /dev/null
@@ -0,0 +1,20 @@
+// PR c++/70139
+// { dg-options "-fno-elide-constructors" }
+// { dg-do compile { target c++11 } }
+
+template<class T, class U>
+struct A
+{
+  T a;
+  U b;
+  constexpr A () : a (), b () { }
+  constexpr A (const T &x, const U &y) : a (x), b (y) { }
+};
+struct B
+{
+  constexpr B (const bool x) : c (x) {}
+  constexpr bool operator!= (const B x) const { return c != x.c; }
+  bool c;
+};
+constexpr static A<B, B*> d[] = { { B (true), nullptr }, { B (false), nullptr } };
+static_assert (d[0].a != d[1].a, "");