Message ID | 65e9b7fb.a70a0220.8763e.f61e@mx.google.com |
---|---|
State | New |
Headers | show |
Series | [v2] c++: Redetermine whether to write vtables on stream-in [PR114229] | expand |
On 3/7/24 07:49, Nathaniel Shead wrote: > On Wed, Mar 06, 2024 at 08:59:16AM -0500, Jason Merrill wrote: >> On 3/5/24 22:06, Nathaniel Shead wrote: >>> Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk? >>> >>> -- >8 -- >>> >>> Currently, reading a variable definition always marks that decl as >>> DECL_NOT_REALLY_EXTERN, with anything else imported still being >>> considered external. This is not sufficient for vtables, however; for an >>> extern template, a vtable may be generated (and its definition emitted) >>> but nonetheless the vtable should only be emitted in the TU where that >>> template is actually instantiated. >> >> Does the vtable go through import_export_decl? I've been thinking that that >> function (and import_export_class) need to be more module-aware. Would it >> make sense to do that rather than stream DECL_NOT_REALLY_EXTERN? >> >> Jason >> > > Right. It doesn't go through 'import_export_decl' because when it's > imported, DECL_INTERFACE_KNOWN is already set. So it seems an obvious > fix here is to just ensure that we clear that flag on stream-in for > vtables (we can't do it generally as it seems to be needed to be kept on > various other kinds of declarations). > > Linaro complained about the last version of this patch too on ARM; > hopefully this version is friendlier. > > I might also spend some time messing around to see if I can implement > https://github.com/itanium-cxx-abi/cxx-abi/issues/170 later, but that > will probably have to be a GCC 15 change. That's OK, but please add a FIXME in this change until then. OK with that adjustment. > Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk if > Linaro doesn't complain about this patch? > > -- >8 -- > > We currently always stream DECL_INTERFACE_KNOWN, which is needed since > many kinds of declarations already have their interface determined at > parse time. But for vtables and type-info declarations we need to > re-evaluate on stream-in, as whether they need to be emitted or not > changes in each TU, so this patch clears DECL_INTERFACE_KNOWN on these > kinds of declarations so that they can go through 'import_export_decl' > again. > > Note that the precise details of the virt-2 tests will need to change > when we implement the resolution of [1]; for now I just updated the test > to not fail with the new (current) semantics. > > [1]: https://github.com/itanium-cxx-abi/cxx-abi/pull/171 > > PR c++/114229 > > gcc/cp/ChangeLog: > > * module.cc (trees_out::core_bools): Redetermine > DECL_INTERFACE_KNOWN on stream-in for vtables and tinfo. > > gcc/testsuite/ChangeLog: > > * g++.dg/modules/virt-2_b.C: Update test to acknowledge that we > now emit vtables here too. > * g++.dg/modules/virt-3_a.C: New test. > * g++.dg/modules/virt-3_b.C: New test. > * g++.dg/modules/virt-3_c.C: New test. > * g++.dg/modules/virt-3_d.C: New test. > > Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com> > --- > gcc/cp/module.cc | 12 +++++++++++- > gcc/testsuite/g++.dg/modules/virt-2_b.C | 5 ++--- > gcc/testsuite/g++.dg/modules/virt-3_a.C | 9 +++++++++ > gcc/testsuite/g++.dg/modules/virt-3_b.C | 6 ++++++ > gcc/testsuite/g++.dg/modules/virt-3_c.C | 3 +++ > gcc/testsuite/g++.dg/modules/virt-3_d.C | 7 +++++++ > 6 files changed, 38 insertions(+), 4 deletions(-) > create mode 100644 gcc/testsuite/g++.dg/modules/virt-3_a.C > create mode 100644 gcc/testsuite/g++.dg/modules/virt-3_b.C > create mode 100644 gcc/testsuite/g++.dg/modules/virt-3_c.C > create mode 100644 gcc/testsuite/g++.dg/modules/virt-3_d.C > > diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc > index f7e8b357fc2..d77286328f5 100644 > --- a/gcc/cp/module.cc > +++ b/gcc/cp/module.cc > @@ -5390,7 +5390,17 @@ trees_out::core_bools (tree t) > WB (t->decl_common.lang_flag_2); > WB (t->decl_common.lang_flag_3); > WB (t->decl_common.lang_flag_4); > - WB (t->decl_common.lang_flag_5); > + > + { > + /* This is DECL_INTERFACE_KNOWN: We should redetermine whether > + we need to import or export any vtables or typeinfo objects > + on stream-in. */ > + bool interface_known = t->decl_common.lang_flag_5; > + if (VAR_P (t) && (DECL_VTABLE_OR_VTT_P (t) || DECL_TINFO_P (t))) > + interface_known = false; > + WB (interface_known); > + } > + > WB (t->decl_common.lang_flag_6); > WB (t->decl_common.lang_flag_7); > WB (t->decl_common.lang_flag_8); > diff --git a/gcc/testsuite/g++.dg/modules/virt-2_b.C b/gcc/testsuite/g++.dg/modules/virt-2_b.C > index e041f0721f9..2bc5eced013 100644 > --- a/gcc/testsuite/g++.dg/modules/virt-2_b.C > +++ b/gcc/testsuite/g++.dg/modules/virt-2_b.C > @@ -21,8 +21,7 @@ int main () > return !(Visit (&me) == 1); > } > > -// We do not emit Visitor vtable > -// but we do emit rtti here > -// { dg-final { scan-assembler-not {_ZTVW3foo7Visitor:} } } > +// Again, we emit Visitor vtable and rtti here > +// { dg-final { scan-assembler {_ZTVW3foo7Visitor:} } } > // { dg-final { scan-assembler {_ZTIW3foo7Visitor:} } } > // { dg-final { scan-assembler {_ZTSW3foo7Visitor:} } } > diff --git a/gcc/testsuite/g++.dg/modules/virt-3_a.C b/gcc/testsuite/g++.dg/modules/virt-3_a.C > new file mode 100644 > index 00000000000..a7eae7f9d35 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/modules/virt-3_a.C > @@ -0,0 +1,9 @@ > +// PR c++/114229 > +// { dg-additional-options "-fmodules-ts -Wno-global-module" } > +// { dg-module-cmi modA } > + > +module; > +template<class> struct basic_streambuf { virtual void overflow() { } }; > +extern template struct basic_streambuf<long>; > +export module modA; > +export basic_streambuf<long> *p; > diff --git a/gcc/testsuite/g++.dg/modules/virt-3_b.C b/gcc/testsuite/g++.dg/modules/virt-3_b.C > new file mode 100644 > index 00000000000..4d87b965bbf > --- /dev/null > +++ b/gcc/testsuite/g++.dg/modules/virt-3_b.C > @@ -0,0 +1,6 @@ > +// PR c++/114229 > +// { dg-additional-options "-fmodules-ts -fno-module-lazy" } > +// { dg-module-cmi modB } > + > +export module modB; > +import modA; > diff --git a/gcc/testsuite/g++.dg/modules/virt-3_c.C b/gcc/testsuite/g++.dg/modules/virt-3_c.C > new file mode 100644 > index 00000000000..224bb4aed49 > --- /dev/null > +++ b/gcc/testsuite/g++.dg/modules/virt-3_c.C > @@ -0,0 +1,3 @@ > +// PR c++/114229 > +template<class> struct basic_streambuf { virtual void overflow() { } }; > +template struct basic_streambuf<long>; > diff --git a/gcc/testsuite/g++.dg/modules/virt-3_d.C b/gcc/testsuite/g++.dg/modules/virt-3_d.C > new file mode 100644 > index 00000000000..b3a0aad7abe > --- /dev/null > +++ b/gcc/testsuite/g++.dg/modules/virt-3_d.C > @@ -0,0 +1,7 @@ > +// PR c++/114229 > +// { dg-module-do link } > +// { dg-additional-options "-fmodules-ts -fno-module-lazy" } > + > +import modA; > +import modB; > +int main() { }
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index f7e8b357fc2..d77286328f5 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -5390,7 +5390,17 @@ trees_out::core_bools (tree t) WB (t->decl_common.lang_flag_2); WB (t->decl_common.lang_flag_3); WB (t->decl_common.lang_flag_4); - WB (t->decl_common.lang_flag_5); + + { + /* This is DECL_INTERFACE_KNOWN: We should redetermine whether + we need to import or export any vtables or typeinfo objects + on stream-in. */ + bool interface_known = t->decl_common.lang_flag_5; + if (VAR_P (t) && (DECL_VTABLE_OR_VTT_P (t) || DECL_TINFO_P (t))) + interface_known = false; + WB (interface_known); + } + WB (t->decl_common.lang_flag_6); WB (t->decl_common.lang_flag_7); WB (t->decl_common.lang_flag_8); diff --git a/gcc/testsuite/g++.dg/modules/virt-2_b.C b/gcc/testsuite/g++.dg/modules/virt-2_b.C index e041f0721f9..2bc5eced013 100644 --- a/gcc/testsuite/g++.dg/modules/virt-2_b.C +++ b/gcc/testsuite/g++.dg/modules/virt-2_b.C @@ -21,8 +21,7 @@ int main () return !(Visit (&me) == 1); } -// We do not emit Visitor vtable -// but we do emit rtti here -// { dg-final { scan-assembler-not {_ZTVW3foo7Visitor:} } } +// Again, we emit Visitor vtable and rtti here +// { dg-final { scan-assembler {_ZTVW3foo7Visitor:} } } // { dg-final { scan-assembler {_ZTIW3foo7Visitor:} } } // { dg-final { scan-assembler {_ZTSW3foo7Visitor:} } } diff --git a/gcc/testsuite/g++.dg/modules/virt-3_a.C b/gcc/testsuite/g++.dg/modules/virt-3_a.C new file mode 100644 index 00000000000..a7eae7f9d35 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/virt-3_a.C @@ -0,0 +1,9 @@ +// PR c++/114229 +// { dg-additional-options "-fmodules-ts -Wno-global-module" } +// { dg-module-cmi modA } + +module; +template<class> struct basic_streambuf { virtual void overflow() { } }; +extern template struct basic_streambuf<long>; +export module modA; +export basic_streambuf<long> *p; diff --git a/gcc/testsuite/g++.dg/modules/virt-3_b.C b/gcc/testsuite/g++.dg/modules/virt-3_b.C new file mode 100644 index 00000000000..4d87b965bbf --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/virt-3_b.C @@ -0,0 +1,6 @@ +// PR c++/114229 +// { dg-additional-options "-fmodules-ts -fno-module-lazy" } +// { dg-module-cmi modB } + +export module modB; +import modA; diff --git a/gcc/testsuite/g++.dg/modules/virt-3_c.C b/gcc/testsuite/g++.dg/modules/virt-3_c.C new file mode 100644 index 00000000000..224bb4aed49 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/virt-3_c.C @@ -0,0 +1,3 @@ +// PR c++/114229 +template<class> struct basic_streambuf { virtual void overflow() { } }; +template struct basic_streambuf<long>; diff --git a/gcc/testsuite/g++.dg/modules/virt-3_d.C b/gcc/testsuite/g++.dg/modules/virt-3_d.C new file mode 100644 index 00000000000..b3a0aad7abe --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/virt-3_d.C @@ -0,0 +1,7 @@ +// PR c++/114229 +// { dg-module-do link } +// { dg-additional-options "-fmodules-ts -fno-module-lazy" } + +import modA; +import modB; +int main() { }