> The testcase has failed since r9-5035, because obj_type_ref_class
> tries to look up an ODR type when no ODR type information is
> available.  (The information was available earlier in the
> compilation, but was freed during pass_ipa_free_lang_data.)
> We then crash dereferencing the null get_odr_type result.
> 
> The test passes with -O2.  However, it fails again if -fdump-tree-all
> is used, since obj_type_ref_class is called indirectly from the
> dump routines.
> 
> Other code seems to create ODR type entries on the fly by passing
> "true" as the insert parameter.  But since obj_type_ref_class is
> used by dump routines, I guess it should have no side-effects and
> should simply punt in this case.
Thanks for looking into this!

The ODR type hash is indeed supposed to be populated lazilly except for
LTO when we populate it at stream in time.  I think just making function
return NULL in case it should not is fragile, because we may hit missed
optimizations and other surprised elsewhere.

What about adding new "for_dump" parameter set implicitly to false that
will make the function return ret in case get_odr_type is NULL?
For dumping it probably does not matter what ODR variant you see, since
we end up with a type name in the dump anyway.

Honza
> 
> Tested on aarch64-linux-gnu and x86_64-linux-gnu.  OK for master
> and branches?
> 
> Richard
> 
> 
> 2020-05-14  Richard Sandiford  <richard.sandif...@arm.com>
> 
> gcc/
>       PR middle-end/95114
>       * ipa-devirt.c (obj_type_ref_class): Cope with a null return
>       from get_odr_type.
> 
> gcc/testsuite/
>       PR middle-end/95114
>       * g++.target/aarch64/pr95114.C: New test.
> ---
>  gcc/ipa-devirt.c                           | 4 ++--
>  gcc/testsuite/g++.target/aarch64/pr95114.C | 3 +++
>  2 files changed, 5 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/g++.target/aarch64/pr95114.C
> 
> diff --git a/gcc/ipa-devirt.c b/gcc/ipa-devirt.c
> index bd9f3441773..ac19eb75596 100644
> --- a/gcc/ipa-devirt.c
> +++ b/gcc/ipa-devirt.c
> @@ -1911,8 +1911,8 @@ obj_type_ref_class (const_tree ref)
>    tree ret = TREE_TYPE (ref);
>    if (!in_lto_p && !TYPE_STRUCTURAL_EQUALITY_P (ret))
>      ret = TYPE_CANONICAL (ret);
> -  else
> -    ret = get_odr_type (ret)->type;
> +  else if (odr_type ot = get_odr_type (ret))
> +    ret = ot->type;
>    return ret;
>  }
>  
> diff --git a/gcc/testsuite/g++.target/aarch64/pr95114.C 
> b/gcc/testsuite/g++.target/aarch64/pr95114.C
> new file mode 100644
> index 00000000000..1689159e47c
> --- /dev/null
> +++ b/gcc/testsuite/g++.target/aarch64/pr95114.C
> @@ -0,0 +1,3 @@
> +template<typename T> struct foo { virtual void f() = 0; };
> +extern foo<__Int8x8_t> &x;
> +void f() { x.f(); }

Reply via email to