From: Jakub Jelinek Date: Tue, 3 Dec 2019 08:19:04 +0000 (+0100) Subject: re PR c++/92695 (P1064R0 - virtual constexpr fails if object taken from array) X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=5558a0da3248524d5fc081dc0580ab4f9e6eb0e2;p=gcc.git 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 --- diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 9ca25aea635..1565d72b455 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,10 @@ +2019-12-03 Jakub Jelinek + + 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 PR c++/92695 diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index cc3ef1056f2..39118200285 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 520581de661..edd1869f384 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2019-12-03 Jakub Jelinek + + PR c++/92695 + * g++.dg/cpp2a/constexpr-virtual14.C: New test. + 2019-12-03 Luo Xiong Hu * 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 00000000000..b29d3f6aefb --- /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 +constexpr int get () { T f; return f.add (); } +static_assert (get () == 20); +static_assert (get () == 20);