about summary refs log tree commit diff
path: root/pkgs/development/compilers/gcc/fix-bug-80431.patch
diff options
context:
space:
mode:
Diffstat (limited to 'pkgs/development/compilers/gcc/fix-bug-80431.patch')
-rw-r--r--pkgs/development/compilers/gcc/fix-bug-80431.patch92
1 files changed, 92 insertions, 0 deletions
diff --git a/pkgs/development/compilers/gcc/fix-bug-80431.patch b/pkgs/development/compilers/gcc/fix-bug-80431.patch
new file mode 100644
index 0000000000000..2d688b8c79971
--- /dev/null
+++ b/pkgs/development/compilers/gcc/fix-bug-80431.patch
@@ -0,0 +1,92 @@
+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
+