[PATCH] c++: conversion to base of vbase in NSDMI [PR80431]

Jason Merrill jason@redhat.com
Mon Jun 21 04:12:23 GMT 2021


On 6/18/21 4:39 PM, Patrick Palka wrote:
> The delayed processing of conversions to a virtual base inside 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 an indirect
> non-virtual base inherited from 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 build_base_path (called with
> binfo=NULL_TREE) silently returning error_mark_node.  Fix this by
> using convert_to_base to build the conversion.
> 
> Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK for
> trunk?
> 
> 	PR c++/80431
> 
> gcc/cp/ChangeLog:
> 
> 	* tree.c (bot_replace): Use convert_to_base instead of
> 	only looking through CLASSTYPE_VBASECLASSES of the current class
> 	type.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* g++.dg/cpp0x/nsdmi-virtual1a.C: New test.
> ---
>   gcc/cp/tree.c                                | 10 ++-----
>   gcc/testsuite/g++.dg/cpp0x/nsdmi-virtual1a.C | 29 ++++++++++++++++++++
>   2 files changed, 32 insertions(+), 7 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..3537f395960 100644
> --- a/gcc/cp/tree.c
> +++ b/gcc/cp/tree.c
> @@ -3244,13 +3244,9 @@ bot_replace (tree* t, int* /*walk_subtrees*/, void* data_)
>       {
>         /* In an NSDMI build_base_path defers building conversions to virtual

So this should be "morally virtual" 
(https://itanium-cxx-abi.github.io/cxx-abi/abi.html#definitions)

OK with that change.

>   	 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,
> +      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..fe647fe3cf7
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/cpp0x/nsdmi-virtual1a.C
> @@ -0,0 +1,29 @@
> +// PR c++/80431
> +// { dg-do run { target c++11 } }
> +
> +// A variant of nsdmi-virtual1.C that turns A from a virtual base of B to a base
> +// of a virtual base of B, using the intermediate class D.
> +
> +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();
> +}
> 



More information about the Gcc-patches mailing list