]> gcc.gnu.org Git - gcc.git/commitdiff
backport: re PR c++/92695 (P1064R0 - virtual constexpr fails if object taken from...
authorJakub Jelinek <jakub@redhat.com>
Fri, 20 Dec 2019 17:33:13 +0000 (18:33 +0100)
committerJakub Jelinek <jakub@redhat.com>
Wed, 22 Jan 2020 20:09:10 +0000 (21:09 +0100)
Backported from mainline
2019-12-03  Jakub Jelinek  <jakub@redhat.com>

PR c++/92695
* constexpr.c (cxx_bind_parameters_in_call): For virtual calls,
adjust the first argument to point to the derived object rather
than its base.

* g++.dg/cpp2a/constexpr-virtual14.C: New test.

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

index 2e47b485d5469b0f13669789bccecdf9d0e9dc28..b727db680e7e5a0f2d710f79affbf1a104e431b7 100644 (file)
@@ -1,6 +1,13 @@
 2019-12-20  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
+       2019-12-03  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/92695
+       * constexpr.c (cxx_bind_parameters_in_call): For virtual calls,
+       adjust the first argument to point to the derived object rather
+       than its base.
+
        2019-12-02  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/92695
index 13d8a17c3e0423de70fec8e368e70262d7185bae..e2ca305aaca0a6136ec739beaa2f76d80d65da84 100644 (file)
@@ -1419,6 +1419,28 @@ cxx_bind_parameters_in_call (const constexpr_ctx *ctx, tree t,
            arg = adjust_temp_type (type, arg);
          if (!TREE_CONSTANT (arg))
            *non_constant_args = true;
+
+         /* For virtual calls, adjust the this argument, so that it is
+            the object on which the method is called, rather than
+            one of its bases.  */
+         if (i == 0 && DECL_VIRTUAL_P (fun))
+           {
+             tree addr = arg;
+             STRIP_NOPS (addr);
+             if (TREE_CODE (addr) == ADDR_EXPR)
+               {
+                 tree obj = TREE_OPERAND (addr, 0);
+                 while (TREE_CODE (obj) == COMPONENT_REF
+                        && DECL_FIELD_IS_BASE (TREE_OPERAND (obj, 1))
+                        && !same_type_ignoring_top_level_qualifiers_p
+                                       (TREE_TYPE (obj), DECL_CONTEXT (fun)))
+                   obj = TREE_OPERAND (obj, 0);
+                 if (obj != TREE_OPERAND (addr, 0))
+                   arg = build_fold_addr_expr_with_type (obj,
+                                                         TREE_TYPE (arg));
+               }
+           }
+
          *p = build_tree_list (parms, arg);
          p = &TREE_CHAIN (*p);
        }
index e46f3fce6ceb65e619339c38641cc89ac98cecde..76a6a84d2c101b320922eb3b8952959d343f97da 100644 (file)
@@ -1,6 +1,11 @@
 2019-12-20  Jakub Jelinek  <jakub@redhat.com>
 
        Backported from mainline
+       2019-12-03  Jakub Jelinek  <jakub@redhat.com>
+
+       PR c++/92695
+       * g++.dg/cpp2a/constexpr-virtual14.C: New test.
+
        2019-12-02  Jakub Jelinek  <jakub@redhat.com>
 
        PR c++/92695
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual14.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual14.C
new file mode 100644 (file)
index 0000000..b29d3f6
--- /dev/null
@@ -0,0 +1,27 @@
+// PR c++/92695
+// { dg-do compile { target c++2a } }
+
+struct A {
+  virtual int get () = 0;
+  virtual int set (A *o) = 0;
+};
+struct B : A {
+  constexpr int get () override { return 10; }
+  constexpr int set (A *o) override { a = o; return 20; }
+  A *a {};
+};
+constexpr auto addressof = [] (A &n) { return &n; };
+struct C {
+  B b;
+  A *c { addressof (b) };
+  constexpr int add () { return c->set (addressof (b)); }
+};
+struct D {
+  B b[2];
+  A *c { addressof (b[0]) };
+  constexpr int add () { return c->set (addressof (b[0])); }
+};
+template <typename T>
+constexpr int get () { T f; return f.add (); }
+static_assert (get<C> () == 20);
+static_assert (get<D> () == 20);
This page took 0.087522 seconds and 5 git commands to generate.