diff options
-rw-r--r-- | gcc/cp/constexpr.c | 44 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C | 2 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/constexpr-virtual16.C | 22 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/cpp2a/constexpr-virtual17.C | 28 |
4 files changed, 54 insertions, 42 deletions
diff --git a/gcc/cp/constexpr.c b/gcc/cp/constexpr.c index c7d17e9..c01c42b 100644 --- a/gcc/cp/constexpr.c +++ b/gcc/cp/constexpr.c @@ -6373,47 +6373,9 @@ cxx_eval_constant_expression (const constexpr_ctx *ctx, tree t, break; case OBJ_TYPE_REF: - { - /* Virtual function call. Let the constexpr machinery figure out - the dynamic type. */ - int token = tree_to_shwi (OBJ_TYPE_REF_TOKEN (t)); - tree obj = OBJ_TYPE_REF_OBJECT (t); - obj = cxx_eval_constant_expression (ctx, obj, lval, non_constant_p, - overflow_p); - STRIP_NOPS (obj); - /* We expect something in the form of &x.D.2103.D.2094; get x. */ - if (TREE_CODE (obj) != ADDR_EXPR - || !DECL_P (get_base_address (TREE_OPERAND (obj, 0)))) - { - if (!ctx->quiet) - error_at (loc, "expression %qE is not a constant expression", t); - *non_constant_p = true; - return t; - } - obj = TREE_OPERAND (obj, 0); - while (TREE_CODE (obj) == COMPONENT_REF - && DECL_FIELD_IS_BASE (TREE_OPERAND (obj, 1))) - obj = TREE_OPERAND (obj, 0); - tree objtype = TREE_TYPE (obj); - if (VAR_P (obj) - && DECL_NAME (obj) == heap_identifier - && TREE_CODE (objtype) == ARRAY_TYPE) - objtype = TREE_TYPE (objtype); - if (!CLASS_TYPE_P (objtype)) - { - if (!ctx->quiet) - error_at (loc, "expression %qE is not a constant expression", t); - *non_constant_p = true; - return t; - } - /* Find the function decl in the virtual functions list. TOKEN is - the DECL_VINDEX that says which function we're looking for. */ - tree virtuals = BINFO_VIRTUALS (TYPE_BINFO (objtype)); - if (TARGET_VTABLE_USES_DESCRIPTORS) - token /= MAX (TARGET_VTABLE_USES_DESCRIPTORS, 1); - r = TREE_VALUE (chain_index (token, virtuals)); - break; - } + /* Virtual function lookup. We don't need to do anything fancy. */ + return cxx_eval_constant_expression (ctx, OBJ_TYPE_REF_EXPR (t), + lval, non_constant_p, overflow_p); case PLACEHOLDER_EXPR: /* Use of the value or address of the current object. */ diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C index fcf398f..5a3d06a 100644 --- a/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C @@ -24,4 +24,4 @@ foo () return r; } -constexpr auto a = foo (); // { dg-error "is not a constant expression" } +constexpr auto a = foo (); // { dg-error "constant expression" } diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual16.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual16.C new file mode 100644 index 0000000..8cca8a6 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual16.C @@ -0,0 +1,22 @@ +// Test constexpr virtual in non-primary vtable. +// { dg-do compile { target c++20 } } + +struct A +{ + virtual constexpr int f() const { return 1; }; +}; + +struct B +{ + virtual constexpr int g() const { return 2; }; +}; + +struct C: A, B +{ +}; + +constexpr C c; + +constexpr int g(const B& b) { return b.g(); } +static_assert (g(c) == 2); + diff --git a/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual17.C b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual17.C new file mode 100644 index 0000000..a8a8995 --- /dev/null +++ b/gcc/testsuite/g++.dg/cpp2a/constexpr-virtual17.C @@ -0,0 +1,28 @@ +// PR c++/93310 +// { dg-do compile { target c++20 } } + +struct A +{ + virtual constexpr char f () const + { return 'A'; } +}; + +struct B : A +{ + char x; + + constexpr B () : x (0) + { x = ((A *)this)->f(); } + + virtual constexpr char f () const + { return 'B'; } +}; + +struct C : B +{ + virtual constexpr char f () const + { return 'C'; } +}; + +constexpr C c; +static_assert (c.x == 'B'); |