92 lines
2.9 KiB
Diff
92 lines
2.9 KiB
Diff
From de31f5445b12fd9ab9969dc536d821fe6f0edad0 Mon Sep 17 00:00:00 2001
|
|
From: Patrick Palka <ppalka@redhat.com>
|
|
Date: Mon, 21 Jun 2021 07:54:26 -0400
|
|
Subject: [PATCH] c++: conversion to base of vbase in NSDMI [PR80431]
|
|
|
|
The delayed processing of conversions to a virtual base in an NSDMI
|
|
assumes the target base type is a (possibly indirect) virtual base of
|
|
the current class, but the target base type could also be a base of a
|
|
virtual base, as in the testcase below. Since such a base isn't a part
|
|
of CLASSTYPE_VBASECLASSES, we end up miscompiling the testcase due to
|
|
the call to build_base_path (with binfo=NULL_TREE) silently returning
|
|
error_mark_node. Fix this by using convert_to_base to build the
|
|
conversion instead.
|
|
|
|
PR c++/80431
|
|
|
|
gcc/cp/ChangeLog:
|
|
|
|
* tree.c (bot_replace): Use convert_to_base to build the
|
|
conversion to the (morally) virtual base.
|
|
|
|
gcc/testsuite/ChangeLog:
|
|
|
|
* g++.dg/cpp0x/nsdmi-virtual1a.C: New test.
|
|
---
|
|
gcc/cp/tree.c | 14 ++++------
|
|
gcc/testsuite/g++.dg/cpp0x/nsdmi-virtual1a.C | 28 ++++++++++++++++++++
|
|
2 files changed, 33 insertions(+), 9 deletions(-)
|
|
create mode 100644 gcc/testsuite/g++.dg/cpp0x/nsdmi-virtual1a.C
|
|
|
|
diff --git a/gcc/cp/tree.c b/gcc/cp/tree.c
|
|
index fec5afaa2be..297da2b1550 100644
|
|
--- a/gcc/cp/tree.c
|
|
+++ b/gcc/cp/tree.c
|
|
@@ -3242,15 +3242,11 @@ bot_replace (tree* t, int* /*walk_subtrees*/, void* data_)
|
|
else if (TREE_CODE (*t) == CONVERT_EXPR
|
|
&& CONVERT_EXPR_VBASE_PATH (*t))
|
|
{
|
|
- /* In an NSDMI build_base_path defers building conversions to virtual
|
|
- bases, and we handle it here. */
|
|
- tree basetype = TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (*t)));
|
|
- vec<tree, va_gc> *vbases = CLASSTYPE_VBASECLASSES (current_class_type);
|
|
- int i; tree binfo;
|
|
- FOR_EACH_VEC_SAFE_ELT (vbases, i, binfo)
|
|
- if (BINFO_TYPE (binfo) == basetype)
|
|
- break;
|
|
- *t = build_base_path (PLUS_EXPR, TREE_OPERAND (*t, 0), binfo, true,
|
|
+ /* In an NSDMI build_base_path defers building conversions to morally
|
|
+ virtual bases, and we handle it here. */
|
|
+ tree basetype = TREE_TYPE (*t);
|
|
+ *t = convert_to_base (TREE_OPERAND (*t, 0), basetype,
|
|
+ /*check_access=*/false, /*nonnull=*/true,
|
|
tf_warning_or_error);
|
|
}
|
|
|
|
diff --git a/gcc/testsuite/g++.dg/cpp0x/nsdmi-virtual1a.C b/gcc/testsuite/g++.dg/cpp0x/nsdmi-virtual1a.C
|
|
new file mode 100644
|
|
index 00000000000..dc847cc16e5
|
|
--- /dev/null
|
|
+++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-virtual1a.C
|
|
@@ -0,0 +1,28 @@
|
|
+// PR c++/80431
|
|
+// { dg-do run { target c++11 } }
|
|
+
|
|
+// A variant of nsdmi-virtual1.C where A is only a morally virtual base of B.
|
|
+
|
|
+struct A
|
|
+{
|
|
+ A(): i(42) { }
|
|
+ int i;
|
|
+ int f() { return i; }
|
|
+};
|
|
+
|
|
+struct D : A { int pad; };
|
|
+
|
|
+struct B : virtual D
|
|
+{
|
|
+ int j = i + f();
|
|
+ int k = A::i + A::f();
|
|
+};
|
|
+
|
|
+struct C: B { int pad; };
|
|
+
|
|
+int main()
|
|
+{
|
|
+ C c;
|
|
+ if (c.j != 84 || c.k != 84)
|
|
+ __builtin_abort();
|
|
+}
|
|
--
|
|
2.31.1
|
|
|