aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorJakub Jelinek <jakub@redhat.com>2019-12-03 09:19:04 +0100
committerJakub Jelinek <jakub@gcc.gnu.org>2019-12-03 09:19:04 +0100
commit5558a0da3248524d5fc081dc0580ab4f9e6eb0e2 (patch)
treeea748b6074ebac645335ae075a76ac871e132270 /gcc
parent3d109462bdd666cc5ce2d0b6b0c3b7a3c19b0b4c (diff)
downloadgcc-5558a0da3248524d5fc081dc0580ab4f9e6eb0e2.zip
gcc-5558a0da3248524d5fc081dc0580ab4f9e6eb0e2.tar.gz
gcc-5558a0da3248524d5fc081dc0580ab4f9e6eb0e2.tar.bz2
re PR c++/92695 (P1064R0 - virtual constexpr fails if object taken from array)
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. From-SVN: r278921
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/ChangeLog7
-rw-r--r--gcc/cp/constexpr.c20
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-virtual14.C27
4 files changed, 59 insertions, 0 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index 9ca25ae..1565d72 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,10 @@
+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
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c
index cc3ef10..3911820 100644
--- a/gcc/cp/constexpr.c
+++ b/gcc/cp/constexpr.c
@@ -1441,6 +1441,26 @@ 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));
+ }
+ }
TREE_VEC_ELT (binds, i) = arg;
}
parms = TREE_CHAIN (parms);
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 520581d..edd1869 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,8 @@
+2019-12-03 Jakub Jelinek <jakub@redhat.com>
+
+ PR c++/92695
+ * g++.dg/cpp2a/constexpr-virtual14.C: New test.
+
2019-12-03 Luo Xiong Hu <luoxhu@linux.ibm.com>
* gcc.target/powerpc/pr72804.c: Fix missing space.
diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual14.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual14.C
new file mode 100644
index 0000000..b29d3f6
--- /dev/null
+++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual14.C
@@ -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);