c++: Redetermine whether to write vtables on stream-in [PR114229]

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.
	* decl2.cc (import_export_decl): Add fixme for ABI changes with
	module 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>
This commit is contained in:
Nathaniel Shead 2024-03-07 23:09:03 +11:00
parent f5c1224708
commit 9ccd03dee4
7 changed files with 42 additions and 4 deletions

View file

@ -3398,6 +3398,10 @@ import_export_decl (tree decl)
unit. */
import_p = false;
/* FIXME: Since https://github.com/itanium-cxx-abi/cxx-abi/pull/171,
the ABI specifies that classes attached to named modules should
have their vtables uniquely emitted in the object for the module
unit in which it is defined. And similarly for RTTI structures. */
if (VAR_P (decl) && DECL_VTABLE_OR_VTT_P (decl))
{
class_type = DECL_CONTEXT (decl);

View file

@ -5376,7 +5376,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);

View file

@ -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:} } }

View file

@ -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;

View file

@ -0,0 +1,6 @@
// PR c++/114229
// { dg-additional-options "-fmodules-ts -fno-module-lazy" }
// { dg-module-cmi modB }
export module modB;
import modA;

View file

@ -0,0 +1,3 @@
// PR c++/114229
template<class> struct basic_streambuf { virtual void overflow() { } };
template struct basic_streambuf<long>;

View file

@ -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() { }