On Wed, 10 Sep 2025, Nathaniel Shead wrote: > Does this fix seem reasonable, or is there something I've missed? > > My change to g++.dg/lto/pr101396_0.C also causes it to fail link with > some flags on my machine, with: > > FAIL: g++.dg/lto/pr101396 cp_lto_pr101396_0.o-cp_lto_pr101396_1.o link, -O0 > -flto -flto-partition=none -fuse-linker-plugin > FAIL: g++.dg/lto/pr101396 cp_lto_pr101396_0.o-cp_lto_pr101396_1.o link, -O0 > -flto -flto-partition=1to1 -fno-use-linker-plugin > FAIL: g++.dg/lto/pr101396 cp_lto_pr101396_0.o-cp_lto_pr101396_1.o link, -O0 > -flto -fuse-linker-plugin -fno-fat-lto-objects > > But the logs doesn't indicate exactly what failed with the link, and > when I try running the commands from the log myself it works fine (exit > status 0, executable generated and can be ran, etc.). This seems to > happen also on a clean tree without my changes, so not sure if this is a > bug or I've misconfigured something or what; any hints? > > Other than that failure, successfully bootstrapped and regtested on > x86_64-pc-linux-gnu. > > -- >8 -- > > On a DECL, TREE_CHAIN will find any other declarations in the same > binding level. This caused an ICE in PR121865 because the next entity > in the binding level was the uninstantiated unique friend 'foo', for > which after being found the compiler tries to generate a mangled name > for it and crashes. > > This didn't happen in non-modules testcases only because normally the > unique friend function would have been chained after its template_decl, > and find_decl_types_r bails on lang-specific nodes so it never saw the > uninstantiated decl. With modules however the order of chaining > changed, causing the error.
So it didn't visit TREE_CHAIN of a lang specific thing? That would have been a bug I think. Btw, what context was this chained in? I suppose we could change things like fld_worklist_push (TYPE_ATTRIBUTES (t), fld); to be fld_worklist_push_{chain,list} (note there's also TREE_PURPOSE and TREE_VALUE on list nodes). The way we exempt field/type decls is definitely a bit vague (I'll note we also have LABEL_DECLs at least). > > I don't think it's ever necessary to walk into the TREE_CHAIN, from what > I can see; other cases where it might be useful (block vars or type > fields) are already handled explicitly elsewhere, and only one test > fails because of the change, due to accidentally relying on this "walk > into the next in-scope declaration" behaviour. We have various tree lists for which this is necessary, for example DECL/TYPE_ATTRIBUTES. So I think this is wrong. > PR c++/121865 > > gcc/ChangeLog: > > * ipa-free-lang-data.cc (find_decls_types_r): Don't walk into > TREE_CHAINs of DECLs. > > gcc/testsuite/ChangeLog: > > * g++.dg/lto/pr101396_0.C: Ensure A will be walked into (and > isn't constant-folded out of the GIMPLE for the function). > * g++.dg/modules/lto-4_a.C: New test. > * g++.dg/modules/lto-4_b.C: New test. > > Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com> > --- > gcc/ipa-free-lang-data.cc | 3 --- > gcc/testsuite/g++.dg/lto/pr101396_0.C | 3 ++- > gcc/testsuite/g++.dg/modules/lto-4_a.C | 10 ++++++++++ > gcc/testsuite/g++.dg/modules/lto-4_b.C | 8 ++++++++ > 4 files changed, 20 insertions(+), 4 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/modules/lto-4_a.C > create mode 100644 gcc/testsuite/g++.dg/modules/lto-4_b.C > > diff --git a/gcc/ipa-free-lang-data.cc b/gcc/ipa-free-lang-data.cc > index 8c4fb3c6b64..41afc6ec82f 100644 > --- a/gcc/ipa-free-lang-data.cc > +++ b/gcc/ipa-free-lang-data.cc > @@ -750,9 +750,6 @@ find_decls_types_r (tree *tp, int *ws, void *data) > && DECL_HAS_VALUE_EXPR_P (t)) > fld_worklist_push (DECL_VALUE_EXPR (t), fld); > > - if (TREE_CODE (t) != FIELD_DECL > - && TREE_CODE (t) != TYPE_DECL) > - fld_worklist_push (TREE_CHAIN (t), fld); > *ws = 0; > } > else if (TYPE_P (t)) > diff --git a/gcc/testsuite/g++.dg/lto/pr101396_0.C > b/gcc/testsuite/g++.dg/lto/pr101396_0.C > index b7a2947a880..d26174df8e0 100644 > --- a/gcc/testsuite/g++.dg/lto/pr101396_0.C > +++ b/gcc/testsuite/g++.dg/lto/pr101396_0.C > @@ -8,5 +8,6 @@ enum A : __UINT32_TYPE__ { // { dg-lto-warning "6: type 'A' > violates the C\\+\\+ > > int main() > { > - return (int) A::a; > + enum A x = A::a; > + return (int) x; > } > diff --git a/gcc/testsuite/g++.dg/modules/lto-4_a.C > b/gcc/testsuite/g++.dg/modules/lto-4_a.C > new file mode 100644 > index 00000000000..16629158dc2 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/modules/lto-4_a.C > @@ -0,0 +1,10 @@ > +// PR c++/121865 > +// { dg-require-effective-target lto } > +// { dg-additional-options "-fmodules -flto" } > + > +export module M; > +export template <typename T> struct S; > +export template <typename T> void foo(S<T>) {} > +template <typename T> struct S { > + friend void foo<>(S); > +}; > diff --git a/gcc/testsuite/g++.dg/modules/lto-4_b.C > b/gcc/testsuite/g++.dg/modules/lto-4_b.C > new file mode 100644 > index 00000000000..0322855caf4 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/modules/lto-4_b.C > @@ -0,0 +1,8 @@ > +// PR c++/121865 > +// { dg-module-do link } > +// { dg-require-effective-target lto } > +// { dg-additional-options "-fmodules -flto" } > + > +import M; > +template struct S<int>; > +int main() {} > -- Richard Biener <rguent...@suse.de> SUSE Software Solutions Germany GmbH, Frankenstrasse 146, 90461 Nuernberg, Germany; GF: Ivo Totev, Andrew McDonald, Werner Knoblich; (HRB 36809, AG Nuernberg)