diff --git a/gcc/cp/class.cc b/gcc/cp/class.cc index 718601756ddc154d643644aa19d380ef2803a52e..fb6c337095007b6ca5a146b7265d59bf40bb0bce 100644 --- a/gcc/cp/class.cc +++ b/gcc/cp/class.cc @@ -2312,6 +2312,7 @@ fixup_type_variants (tree type) TYPE_PRECISION (variant) = TYPE_PRECISION (type); TYPE_MODE_RAW (variant) = TYPE_MODE_RAW (type); TYPE_EMPTY_P (variant) = TYPE_EMPTY_P (type); + TREE_ADDRESSABLE (variant) = TREE_ADDRESSABLE (type); } } @@ -2378,8 +2379,17 @@ fixup_attribute_variants (tree t) static void finish_struct_bits (tree t) { - /* Fix up variants (if any). */ - fixup_type_variants (t); + /* If this type has a copy constructor or a destructor, force its + mode to be BLKmode, and force its TREE_ADDRESSABLE bit to be + nonzero. This will cause it to be passed by invisible reference + and prevent it from being returned in a register. */ + if (type_has_nontrivial_copy_init (t) + || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)) + { + SET_DECL_MODE (TYPE_MAIN_DECL (t), BLKmode); + SET_TYPE_MODE (t, BLKmode); + TREE_ADDRESSABLE (t) = 1; + } if (BINFO_N_BASE_BINFOS (TYPE_BINFO (t)) && TYPE_POLYMORPHIC_P (t)) /* For a class w/o baseclasses, 'finish_struct' has set @@ -2392,21 +2402,8 @@ finish_struct_bits (tree t) looking in the vtables). */ get_pure_virtuals (t); - /* If this type has a copy constructor or a destructor, force its - mode to be BLKmode, and force its TREE_ADDRESSABLE bit to be - nonzero. This will cause it to be passed by invisible reference - and prevent it from being returned in a register. */ - if (type_has_nontrivial_copy_init (t) - || TYPE_HAS_NONTRIVIAL_DESTRUCTOR (t)) - { - tree variants; - SET_DECL_MODE (TYPE_MAIN_DECL (t), BLKmode); - for (variants = t; variants; variants = TYPE_NEXT_VARIANT (variants)) - { - SET_TYPE_MODE (variants, BLKmode); - TREE_ADDRESSABLE (variants) = 1; - } - } + /* Fix up variants (if any). */ + fixup_type_variants (t); } /* Issue warnings about T having private constructors, but no friends, diff --git a/gcc/testsuite/g++.dg/modules/pr115062_a.H b/gcc/testsuite/g++.dg/modules/pr115062_a.H new file mode 100644 index 0000000000000000000000000000000000000000..3c9daac317e6fc43f61428eee9606d3c59134c3e --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/pr115062_a.H @@ -0,0 +1,6 @@ +// PR c++/115062 +// { dg-additional-options "-fmodule-header" } +// { dg-module-cmi {} } + +template <typename T> class S; +typedef S<char> X; diff --git a/gcc/testsuite/g++.dg/modules/pr115062_b.H b/gcc/testsuite/g++.dg/modules/pr115062_b.H new file mode 100644 index 0000000000000000000000000000000000000000..d8da59591ec5dad9448b19bda8833054ac2bad79 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/pr115062_b.H @@ -0,0 +1,14 @@ +// PR c++/115062 +// { dg-additional-options "-fmodule-header" } +// { dg-module-cmi {} } + +template <typename> +struct S { + int a; + long b; + union {}; + ~S(); + void foo(); +}; +extern template void S<char>::foo(); +S<char> operator+(S<char>, const char *); diff --git a/gcc/testsuite/g++.dg/modules/pr115062_c.C b/gcc/testsuite/g++.dg/modules/pr115062_c.C new file mode 100644 index 0000000000000000000000000000000000000000..5255b9ffca7a090a42625d7d2511092d453e6fdb --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/pr115062_c.C @@ -0,0 +1,9 @@ +// PR c++/115062 +// { dg-additional-options "-fmodules-ts" } + +import "pr115062_a.H"; +import "pr115062_b.H"; + +int main() { + X x = X() + ""; +}