c++: Fix static initialization from <=>.
authorJason Merrill <jason@redhat.com>
Mon, 10 Feb 2020 13:05:06 +0000 (14:05 +0100)
committerJason Merrill <jason@redhat.com>
Tue, 11 Feb 2020 08:17:42 +0000 (09:17 +0100)
Constant evaluation of genericize_spaceship produced a CONSTRUCTOR, which we
then wanted to bind to a reference, which we can't do.  So wrap the result
in a TARGET_EXPR so we get something with an address.

We also need to handle treating the result of cxx_eval_binary_expression as
a glvalue for SPACESHIP_EXPR.

My earlier change to add uid_sensitive to maybe_constant_value was wrong; we
don't even look at the cache when manifestly_const_eval, and I failed to
adjust the later call to cxx_eval_outermost_constant_expr.

gcc/cp/ChangeLog
2020-02-11  Jason Merrill  <jason@redhat.com>

PR c++/93650
PR c++/90691
* constexpr.c (maybe_constant_value): Correct earlier change.
(cxx_eval_binary_expression) [SPACESHIP_EXPR]: Pass lval through.
* method.c (genericize_spaceship): Wrap result in TARGET_EXPR.

gcc/cp/ChangeLog
gcc/cp/constexpr.c
gcc/cp/method.c
gcc/testsuite/g++.dg/cpp2a/spaceship-constexpr2.C [new file with mode: 0644]

index bf7bf5f71d1358c1be7839330e8c865f96630937..f4b04798d3c2afb0862b64ea8827481d505bf29f 100644 (file)
@@ -1,3 +1,11 @@
+2020-02-11  Jason Merrill  <jason@redhat.com>
+
+       PR c++/93650
+       PR c++/90691
+       * constexpr.c (maybe_constant_value): Correct earlier change.
+       (cxx_eval_binary_expression) [SPACESHIP_EXPR]: Pass lval through.
+       * method.c (genericize_spaceship): Wrap result in TARGET_EXPR.
+
 2020-02-12  Patrick Palka  <ppalka@redhat.com>
 
        PR c++/69448
index 6495cf88e6916add1a73f71b3ed536c73a552ce6..bf7a2643003507d2d59def996481ab5f150fb1ea 100644 (file)
@@ -2834,7 +2834,7 @@ cxx_fold_pointer_plus_expression (const constexpr_ctx *ctx, tree t,
 
 static tree
 cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t,
-                           bool /*lval*/,
+                           bool lval,
                            bool *non_constant_p, bool *overflow_p)
 {
   tree r = NULL_TREE;
@@ -2902,7 +2902,7 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, tree t,
   else if (code == SPACESHIP_EXPR)
     {
       r = genericize_spaceship (type, lhs, rhs);
-      r = cxx_eval_constant_expression (ctx, r, false, non_constant_p,
+      r = cxx_eval_constant_expression (ctx, r, lval, non_constant_p,
                                        overflow_p);
     }
 
@@ -6686,13 +6686,11 @@ maybe_constant_value (tree t, tree decl, bool manifestly_const_eval,
          r = unshare_expr_without_location (r);
          protected_set_expr_location (r, EXPR_LOCATION (t));
        }
-      if (r != t || TREE_CONSTANT (t) || !manifestly_const_eval)
-       return r;
-      /* If we cached this as non-constant and we need a constant value, try
-        again; we might have failed before due to UID_SENSITIVE.  */
+      return r;
     }
 
-  r = cxx_eval_outermost_constant_expr (t, true, true, false, false, decl);
+  r = cxx_eval_outermost_constant_expr (t, true, true, false, false,
+                                       decl, uid_sensitive);
   gcc_checking_assert (r == t
                       || CONVERT_EXPR_P (t)
                       || TREE_CODE (t) == VIEW_CONVERT_EXPR
index fef19e18196b991c0beab6a7c22ca07bdea003a5..cfc37bc1b17b213c2dcb2b65aa09e55848a193f7 100644 (file)
@@ -1075,6 +1075,9 @@ genericize_spaceship (tree type, tree op0, tree op1)
   comp = fold_build2 (EQ_EXPR, boolean_type_node, op0, op1);
   r = fold_build3 (COND_EXPR, type, comp, eq, r);
 
+  /* Wrap the whole thing in a TARGET_EXPR like build_conditional_expr_1.  */
+  r = get_target_expr (r);
+
   return r;
 }
 
diff --git a/gcc/testsuite/g++.dg/cpp2a/spaceship-constexpr2.C b/gcc/testsuite/g++.dg/cpp2a/spaceship-constexpr2.C
new file mode 100644 (file)
index 0000000..02f92b1
--- /dev/null
@@ -0,0 +1,14 @@
+// PR c++/93650
+// { dg-do compile { target c++2a } }
+
+namespace std {
+  using type = enum _Ord { less };
+  class strong_ordering {
+    type _M_value;
+    constexpr strong_ordering(_Ord) : _M_value() {}
+    static const strong_ordering less;
+    static strong_ordering equal;
+    static strong_ordering greater;
+  } constexpr strong_ordering::less(_Ord::less);
+  auto v = 1 <=> 2;
+}