diff mbox series

[LTO,RFA] PR c++/88049 - ICE with undefined destructor and anon namespace.

Message ID 20190220015806.3999-1-jason@redhat.com
State New
Headers show
Series [LTO,RFA] PR c++/88049 - ICE with undefined destructor and anon namespace. | expand

Commit Message

Jason Merrill Feb. 20, 2019, 1:58 a.m. UTC
A type in an anonymous namespace can never be merged with one from
another translation unit, so a member of such a type is always its own
prevailing decl.

I don't really understand the LTO concept of prevailing decl, or why we don't
get here if the destructor is defined, but this seems reasonable and fixes the
bug.

Tested x86_64-pc-linux-gnu.  OK for trunk?

	* lto-symtab.c (lto_symtab_prevailing_virtual_decl): Return early
	for a type in an anonymous namespace.
---
 gcc/lto/lto-symtab.c                 |  8 ++++++--
 gcc/testsuite/g++.dg/lto/pr88049_0.C | 16 ++++++++++++++++
 gcc/lto/ChangeLog                    |  6 ++++++
 3 files changed, 28 insertions(+), 2 deletions(-)
 create mode 100644 gcc/testsuite/g++.dg/lto/pr88049_0.C


base-commit: 79ae32275d4a19a1fc6ffebec9ac15a8c94b0b8f

Comments

Richard Biener Feb. 20, 2019, 8:52 a.m. UTC | #1
On Wed, Feb 20, 2019 at 2:58 AM Jason Merrill <jason@redhat.com> wrote:
>
> A type in an anonymous namespace can never be merged with one from
> another translation unit, so a member of such a type is always its own
> prevailing decl.
>
> I don't really understand the LTO concept of prevailing decl, or why we don't
> get here if the destructor is defined, but this seems reasonable and fixes the
> bug.

We're probably not supposed to end up here but get the "precomputed"
prevailing decl from symtab merging.  Honza should know more precisely.
The resolution file does have an entry for the UNDEF destructor.

Does this make the testcase invalid btw?  There's no way another TU
can inject a definition into the same anonymous namespace, no?
And does the point of instantiation really determine the containing
namespace of the class?

Richard.

>
> Tested x86_64-pc-linux-gnu.  OK for trunk?
>
>         * lto-symtab.c (lto_symtab_prevailing_virtual_decl): Return early
>         for a type in an anonymous namespace.
> ---
>  gcc/lto/lto-symtab.c                 |  8 ++++++--
>  gcc/testsuite/g++.dg/lto/pr88049_0.C | 16 ++++++++++++++++
>  gcc/lto/ChangeLog                    |  6 ++++++
>  3 files changed, 28 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/lto/pr88049_0.C
>
> diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c
> index 22da4c78b8c..343915c3cec 100644
> --- a/gcc/lto/lto-symtab.c
> +++ b/gcc/lto/lto-symtab.c
> @@ -1085,8 +1085,12 @@ lto_symtab_prevailing_virtual_decl (tree decl)
>  {
>    if (DECL_ABSTRACT_P (decl))
>      return decl;
> -  gcc_checking_assert (!type_in_anonymous_namespace_p (DECL_CONTEXT (decl))
> -                      && DECL_ASSEMBLER_NAME_SET_P (decl));
> +
> +  if (type_in_anonymous_namespace_p (DECL_CONTEXT (decl)))
> +    /* There can't be any other declarations.  */
> +    return decl;
> +
> +  gcc_checking_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
>
>    symtab_node *n = symtab_node::get_for_asmname
>                      (DECL_ASSEMBLER_NAME (decl));
> diff --git a/gcc/testsuite/g++.dg/lto/pr88049_0.C b/gcc/testsuite/g++.dg/lto/pr88049_0.C
> new file mode 100644
> index 00000000000..7ac3618c2c8
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/lto/pr88049_0.C
> @@ -0,0 +1,16 @@
> +// PR c++/88049
> +// { dg-lto-do link }
> +// { dg-lto-options {{ -flto -O2 -w }} }
> +// { dg-extra-ld-options -r }
> +
> +template <typename> class a;
> +class b {};
> +template <typename e> a<e> d(char);
> +template <typename> class a : public b {
> +public:
> +  virtual ~a();
> +};
> +namespace {
> +  class f;
> +  b c = d<f>(int());
> +} // namespace
> diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
> index 6b183df3b0f..71a2a109e64 100644
> --- a/gcc/lto/ChangeLog
> +++ b/gcc/lto/ChangeLog
> @@ -1,3 +1,9 @@
> +2019-02-18  Jason Merrill  <jason@redhat.com>
> +
> +       PR c++/88049 - ICE with undefined destructor and anon namespace.
> +       * lto-symtab.c (lto_symtab_prevailing_virtual_decl): Return early
> +       for a type in an anonymous namespace.
> +
>  2019-01-09  Sandra Loosemore  <sandra@codesourcery.com>
>
>         PR other/16615
>
> base-commit: 79ae32275d4a19a1fc6ffebec9ac15a8c94b0b8f
> --
> 2.20.1
>
Jason Merrill Feb. 20, 2019, 6:41 p.m. UTC | #2
On Tue, Feb 19, 2019 at 10:53 PM Richard Biener
<richard.guenther@gmail.com> wrote:
> On Wed, Feb 20, 2019 at 2:58 AM Jason Merrill <jason@redhat.com> wrote:
> >
> > A type in an anonymous namespace can never be merged with one from
> > another translation unit, so a member of such a type is always its own
> > prevailing decl.
> >
> > I don't really understand the LTO concept of prevailing decl, or why we don't
> > get here if the destructor is defined, but this seems reasonable and fixes the
> > bug.
>
> We're probably not supposed to end up here but get the "precomputed"
> prevailing decl from symtab merging.  Honza should know more precisely.
> The resolution file does have an entry for the UNDEF destructor.
>
> Does this make the testcase invalid btw?  There's no way another TU
> can inject a definition into the same anonymous namespace, no?

Correct.  The destructor is needed to destroy 'c', and there's no way
it could be defined in another TU, so the testcase will fail to link.
So we could probably reject the testcase (in cgraph?) before we touch
LTO at all.

> And does the point of instantiation really determine the containing
> namespace of the class?

No.  a<f> isn't really in an anonymous namespace, but since f is, a<f>
also gets internal linkage.  So type_in_anonymous_namespace_p is a
somewhat misleading name; perhaps type_internal_p?  type_nonpublic_p?

Jason
Christophe Lyon March 4, 2019, 1:41 p.m. UTC | #3
On Wed, 20 Feb 2019 at 02:58, Jason Merrill <jason@redhat.com> wrote:
>
> A type in an anonymous namespace can never be merged with one from
> another translation unit, so a member of such a type is always its own
> prevailing decl.
>
> I don't really understand the LTO concept of prevailing decl, or why we don't
> get here if the destructor is defined, but this seems reasonable and fixes the
> bug.
>
> Tested x86_64-pc-linux-gnu.  OK for trunk?
>
>         * lto-symtab.c (lto_symtab_prevailing_virtual_decl): Return early
>         for a type in an anonymous namespace.
> ---
>  gcc/lto/lto-symtab.c                 |  8 ++++++--
>  gcc/testsuite/g++.dg/lto/pr88049_0.C | 16 ++++++++++++++++
>  gcc/lto/ChangeLog                    |  6 ++++++
>  3 files changed, 28 insertions(+), 2 deletions(-)
>  create mode 100644 gcc/testsuite/g++.dg/lto/pr88049_0.C
>
> diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c
> index 22da4c78b8c..343915c3cec 100644
> --- a/gcc/lto/lto-symtab.c
> +++ b/gcc/lto/lto-symtab.c
> @@ -1085,8 +1085,12 @@ lto_symtab_prevailing_virtual_decl (tree decl)
>  {
>    if (DECL_ABSTRACT_P (decl))
>      return decl;
> -  gcc_checking_assert (!type_in_anonymous_namespace_p (DECL_CONTEXT (decl))
> -                      && DECL_ASSEMBLER_NAME_SET_P (decl));
> +
> +  if (type_in_anonymous_namespace_p (DECL_CONTEXT (decl)))
> +    /* There can't be any other declarations.  */
> +    return decl;
> +
> +  gcc_checking_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
>
>    symtab_node *n = symtab_node::get_for_asmname
>                      (DECL_ASSEMBLER_NAME (decl));
> diff --git a/gcc/testsuite/g++.dg/lto/pr88049_0.C b/gcc/testsuite/g++.dg/lto/pr88049_0.C
> new file mode 100644
> index 00000000000..7ac3618c2c8
> --- /dev/null
> +++ b/gcc/testsuite/g++.dg/lto/pr88049_0.C
> @@ -0,0 +1,16 @@
> +// PR c++/88049
> +// { dg-lto-do link }
> +// { dg-lto-options {{ -flto -O2 -w }} }
> +// { dg-extra-ld-options -r }
> +
> +template <typename> class a;
> +class b {};
> +template <typename e> a<e> d(char);
> +template <typename> class a : public b {
> +public:
> +  virtual ~a();
> +};
> +namespace {
> +  class f;
> +  b c = d<f>(int());
> +} // namespace


Hi Jason,

On bare-metal targets (arm, aarch64 using newlib), I'm using dejagnu's
testglue, which makes this new test fail because it also uses
g++_tg.o, leading to:
/arm-none-eabi/bin/ld: warning: incremental linking of LTO and non-LTO
objects; using -flinker-output=nolto-rel which will bypass whole
program optimization

Is there a way to avoid that (besides not using testglue) ?

Thanks,

Christophe

> diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
> index 6b183df3b0f..71a2a109e64 100644
> --- a/gcc/lto/ChangeLog
> +++ b/gcc/lto/ChangeLog
> @@ -1,3 +1,9 @@
> +2019-02-18  Jason Merrill  <jason@redhat.com>
> +
> +       PR c++/88049 - ICE with undefined destructor and anon namespace.
> +       * lto-symtab.c (lto_symtab_prevailing_virtual_decl): Return early
> +       for a type in an anonymous namespace.
> +
>  2019-01-09  Sandra Loosemore  <sandra@codesourcery.com>
>
>         PR other/16615
>
> base-commit: 79ae32275d4a19a1fc6ffebec9ac15a8c94b0b8f
> --
> 2.20.1
>
Jason Merrill March 4, 2019, 4:37 p.m. UTC | #4
On Mon, Mar 4, 2019 at 8:41 AM Christophe Lyon
<christophe.lyon@linaro.org> wrote:
> On Wed, 20 Feb 2019 at 02:58, Jason Merrill <jason@redhat.com> wrote:
> >
> > A type in an anonymous namespace can never be merged with one from
> > another translation unit, so a member of such a type is always its own
> > prevailing decl.
> >
> > I don't really understand the LTO concept of prevailing decl, or why we don't
> > get here if the destructor is defined, but this seems reasonable and fixes the
> > bug.
> >
> > Tested x86_64-pc-linux-gnu.  OK for trunk?
> >
> >         * lto-symtab.c (lto_symtab_prevailing_virtual_decl): Return early
> >         for a type in an anonymous namespace.
> > ---
> >  gcc/lto/lto-symtab.c                 |  8 ++++++--
> >  gcc/testsuite/g++.dg/lto/pr88049_0.C | 16 ++++++++++++++++
> >  gcc/lto/ChangeLog                    |  6 ++++++
> >  3 files changed, 28 insertions(+), 2 deletions(-)
> >  create mode 100644 gcc/testsuite/g++.dg/lto/pr88049_0.C
> >
> > diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c
> > index 22da4c78b8c..343915c3cec 100644
> > --- a/gcc/lto/lto-symtab.c
> > +++ b/gcc/lto/lto-symtab.c
> > @@ -1085,8 +1085,12 @@ lto_symtab_prevailing_virtual_decl (tree decl)
> >  {
> >    if (DECL_ABSTRACT_P (decl))
> >      return decl;
> > -  gcc_checking_assert (!type_in_anonymous_namespace_p (DECL_CONTEXT (decl))
> > -                      && DECL_ASSEMBLER_NAME_SET_P (decl));
> > +
> > +  if (type_in_anonymous_namespace_p (DECL_CONTEXT (decl)))
> > +    /* There can't be any other declarations.  */
> > +    return decl;
> > +
> > +  gcc_checking_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
> >
> >    symtab_node *n = symtab_node::get_for_asmname
> >                      (DECL_ASSEMBLER_NAME (decl));
> > diff --git a/gcc/testsuite/g++.dg/lto/pr88049_0.C b/gcc/testsuite/g++.dg/lto/pr88049_0.C
> > new file mode 100644
> > index 00000000000..7ac3618c2c8
> > --- /dev/null
> > +++ b/gcc/testsuite/g++.dg/lto/pr88049_0.C
> > @@ -0,0 +1,16 @@
> > +// PR c++/88049
> > +// { dg-lto-do link }
> > +// { dg-lto-options {{ -flto -O2 -w }} }
> > +// { dg-extra-ld-options -r }
> > +
> > +template <typename> class a;
> > +class b {};
> > +template <typename e> a<e> d(char);
> > +template <typename> class a : public b {
> > +public:
> > +  virtual ~a();
> > +};
> > +namespace {
> > +  class f;
> > +  b c = d<f>(int());
> > +} // namespace
>
>
> Hi Jason,
>
> On bare-metal targets (arm, aarch64 using newlib), I'm using dejagnu's
> testglue, which makes this new test fail because it also uses
> g++_tg.o, leading to:
> /arm-none-eabi/bin/ld: warning: incremental linking of LTO and non-LTO
> objects; using -flinker-output=nolto-rel which will bypass whole
> program optimization
>
> Is there a way to avoid that (besides not using testglue) ?

Does adding

// { dg-require-effective-target lto_incremental }

to the testcase help?

Jason
Christophe Lyon March 4, 2019, 6:31 p.m. UTC | #5
On Mon, 4 Mar 2019 at 17:37, Jason Merrill <jason@redhat.com> wrote:
>
> On Mon, Mar 4, 2019 at 8:41 AM Christophe Lyon
> <christophe.lyon@linaro.org> wrote:
> > On Wed, 20 Feb 2019 at 02:58, Jason Merrill <jason@redhat.com> wrote:
> > >
> > > A type in an anonymous namespace can never be merged with one from
> > > another translation unit, so a member of such a type is always its own
> > > prevailing decl.
> > >
> > > I don't really understand the LTO concept of prevailing decl, or why we don't
> > > get here if the destructor is defined, but this seems reasonable and fixes the
> > > bug.
> > >
> > > Tested x86_64-pc-linux-gnu.  OK for trunk?
> > >
> > >         * lto-symtab.c (lto_symtab_prevailing_virtual_decl): Return early
> > >         for a type in an anonymous namespace.
> > > ---
> > >  gcc/lto/lto-symtab.c                 |  8 ++++++--
> > >  gcc/testsuite/g++.dg/lto/pr88049_0.C | 16 ++++++++++++++++
> > >  gcc/lto/ChangeLog                    |  6 ++++++
> > >  3 files changed, 28 insertions(+), 2 deletions(-)
> > >  create mode 100644 gcc/testsuite/g++.dg/lto/pr88049_0.C
> > >
> > > diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c
> > > index 22da4c78b8c..343915c3cec 100644
> > > --- a/gcc/lto/lto-symtab.c
> > > +++ b/gcc/lto/lto-symtab.c
> > > @@ -1085,8 +1085,12 @@ lto_symtab_prevailing_virtual_decl (tree decl)
> > >  {
> > >    if (DECL_ABSTRACT_P (decl))
> > >      return decl;
> > > -  gcc_checking_assert (!type_in_anonymous_namespace_p (DECL_CONTEXT (decl))
> > > -                      && DECL_ASSEMBLER_NAME_SET_P (decl));
> > > +
> > > +  if (type_in_anonymous_namespace_p (DECL_CONTEXT (decl)))
> > > +    /* There can't be any other declarations.  */
> > > +    return decl;
> > > +
> > > +  gcc_checking_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
> > >
> > >    symtab_node *n = symtab_node::get_for_asmname
> > >                      (DECL_ASSEMBLER_NAME (decl));
> > > diff --git a/gcc/testsuite/g++.dg/lto/pr88049_0.C b/gcc/testsuite/g++.dg/lto/pr88049_0.C
> > > new file mode 100644
> > > index 00000000000..7ac3618c2c8
> > > --- /dev/null
> > > +++ b/gcc/testsuite/g++.dg/lto/pr88049_0.C
> > > @@ -0,0 +1,16 @@
> > > +// PR c++/88049
> > > +// { dg-lto-do link }
> > > +// { dg-lto-options {{ -flto -O2 -w }} }
> > > +// { dg-extra-ld-options -r }
> > > +
> > > +template <typename> class a;
> > > +class b {};
> > > +template <typename e> a<e> d(char);
> > > +template <typename> class a : public b {
> > > +public:
> > > +  virtual ~a();
> > > +};
> > > +namespace {
> > > +  class f;
> > > +  b c = d<f>(int());
> > > +} // namespace
> >
> >
> > Hi Jason,
> >
> > On bare-metal targets (arm, aarch64 using newlib), I'm using dejagnu's
> > testglue, which makes this new test fail because it also uses
> > g++_tg.o, leading to:
> > /arm-none-eabi/bin/ld: warning: incremental linking of LTO and non-LTO
> > objects; using -flinker-output=nolto-rel which will bypass whole
> > program optimization
> >
> > Is there a way to avoid that (besides not using testglue) ?
>
> Does adding
>
> // { dg-require-effective-target lto_incremental }
>
> to the testcase help?
>

Yes, it does, thanks. I was unaware if this effective-target.

> Jason
diff mbox series

Patch

diff --git a/gcc/lto/lto-symtab.c b/gcc/lto/lto-symtab.c
index 22da4c78b8c..343915c3cec 100644
--- a/gcc/lto/lto-symtab.c
+++ b/gcc/lto/lto-symtab.c
@@ -1085,8 +1085,12 @@  lto_symtab_prevailing_virtual_decl (tree decl)
 {
   if (DECL_ABSTRACT_P (decl))
     return decl;
-  gcc_checking_assert (!type_in_anonymous_namespace_p (DECL_CONTEXT (decl))
-		       && DECL_ASSEMBLER_NAME_SET_P (decl));
+
+  if (type_in_anonymous_namespace_p (DECL_CONTEXT (decl)))
+    /* There can't be any other declarations.  */
+    return decl;
+
+  gcc_checking_assert (DECL_ASSEMBLER_NAME_SET_P (decl));
 
   symtab_node *n = symtab_node::get_for_asmname
 		     (DECL_ASSEMBLER_NAME (decl));
diff --git a/gcc/testsuite/g++.dg/lto/pr88049_0.C b/gcc/testsuite/g++.dg/lto/pr88049_0.C
new file mode 100644
index 00000000000..7ac3618c2c8
--- /dev/null
+++ b/gcc/testsuite/g++.dg/lto/pr88049_0.C
@@ -0,0 +1,16 @@ 
+// PR c++/88049
+// { dg-lto-do link }
+// { dg-lto-options {{ -flto -O2 -w }} }
+// { dg-extra-ld-options -r }
+
+template <typename> class a;
+class b {};
+template <typename e> a<e> d(char);
+template <typename> class a : public b {
+public:
+  virtual ~a();
+};
+namespace {
+  class f;
+  b c = d<f>(int());
+} // namespace
diff --git a/gcc/lto/ChangeLog b/gcc/lto/ChangeLog
index 6b183df3b0f..71a2a109e64 100644
--- a/gcc/lto/ChangeLog
+++ b/gcc/lto/ChangeLog
@@ -1,3 +1,9 @@ 
+2019-02-18  Jason Merrill  <jason@redhat.com>
+
+	PR c++/88049 - ICE with undefined destructor and anon namespace.
+	* lto-symtab.c (lto_symtab_prevailing_virtual_decl): Return early
+	for a type in an anonymous namespace.
+
 2019-01-09  Sandra Loosemore  <sandra@codesourcery.com>
 
 	PR other/16615