]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
* constexpr.c (cxx_eval_store_expression): Delay target evaluation.
authorjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 18 Jun 2019 16:08:29 +0000 (16:08 +0000)
committerjason <jason@138bc75d-0d04-0410-961f-82ee72b054a4>
Tue, 18 Jun 2019 16:08:29 +0000 (16:08 +0000)
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@272431 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/constexpr.c

index 1071a52a5586f22fdbe7b1b554d2dc7bbf7fb6b2..7bd47cf4b569f8f9f85e0dd31d6d9abb7edee280 100644 (file)
@@ -1,3 +1,7 @@
+2019-06-18  Jason Merrill  <jason@redhat.com>
+
+       * constexpr.c (cxx_eval_store_expression): Delay target evaluation.
+
 2019-06-18  Jason Merrill  <jason@redhat.com>
 
        * constexpr.c (eval_and_check_array_index): Split out from...
index 7c733d78b5b6a7ef5d3a5c6a0eae8838d3144f92..22f4fa0d3511b3285dabc7bf9e844e0c3796520f 100644 (file)
@@ -3747,22 +3747,18 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
       if (*non_constant_p)
        return t;
     }
-  target = cxx_eval_constant_expression (ctx, target,
-                                        true,
-                                        non_constant_p, overflow_p);
-  if (*non_constant_p)
-    return t;
 
-  if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (target), type))
+  bool evaluated = false;
+  if (lval)
     {
-      /* For initialization of an empty base, the original target will be
-         *(base*)this, which the above evaluation resolves to the object
-        argument, which has the derived type rather than the base type.  In
-        this situation, just evaluate the initializer and return, since
-        there's no actual data to store.  */
-      gcc_assert (is_empty_class (type));
-      return cxx_eval_constant_expression (ctx, init, false,
-                                          non_constant_p, overflow_p);
+      /* If we want to return a reference to the target, we need to evaluate it
+        as a whole; otherwise, only evaluate the innermost piece to avoid
+        building up unnecessary *_REFs.  */
+      target = cxx_eval_constant_expression (ctx, target, true,
+                                            non_constant_p, overflow_p);
+      evaluated = true;
+      if (*non_constant_p)
+       return t;
     }
 
   /* Find the underlying variable.  */
@@ -3792,7 +3788,17 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
          break;
 
        default:
-         object = probe;
+         if (evaluated)
+           object = probe;
+         else
+           {
+             probe = cxx_eval_constant_expression (ctx, probe, true,
+                                                   non_constant_p, overflow_p);
+             evaluated = true;
+             if (*non_constant_p)
+               return t;
+           }
+         break;
        }
     }
 
@@ -3948,7 +3954,7 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
       new_ctx.object = target;
       init = cxx_eval_constant_expression (&new_ctx, init, false,
                                           non_constant_p, overflow_p);
-      if (target == object)
+      if (ctors->is_empty())
        /* The hash table might have moved since the get earlier.  */
        valp = ctx->values->get (object);
     }
@@ -3961,6 +3967,17 @@ cxx_eval_store_expression (const constexpr_ctx *ctx, tree t,
     {
       /* An outer ctx->ctor might be pointing to *valp, so replace
         its contents.  */
+      if (!same_type_ignoring_top_level_qualifiers_p (TREE_TYPE (init),
+                                                     TREE_TYPE (*valp)))
+       {
+         /* For initialization of an empty base, the original target will be
+          *(base*)this, evaluation of which resolves to the object
+          argument, which has the derived type rather than the base type.  In
+          this situation, just evaluate the initializer and return, since
+          there's no actual data to store.  */
+         gcc_assert (is_empty_class (TREE_TYPE (init)) && !lval);
+         return init;
+       }
       CONSTRUCTOR_ELTS (*valp) = CONSTRUCTOR_ELTS (init);
       TREE_CONSTANT (*valp) = TREE_CONSTANT (init);
       TREE_SIDE_EFFECTS (*valp) = TREE_SIDE_EFFECTS (init);