aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/constexpr.c44
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-new12.C2
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-virtual16.C22
-rw-r--r--gcc/testsuite/g++.dg/cpp2a/constexpr-virtual17.C28
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');