diff options
author | Nathan Sidwell <nathan@acm.org> | 2021-02-22 06:43:32 -0800 |
---|---|---|
committer | Nathan Sidwell <nathan@acm.org> | 2021-02-22 06:52:19 -0800 |
commit | c49fcfddaa47f2828fe2af11ae857cd67f53e23f (patch) | |
tree | 5a9c6bd1dd5971b2f2d39da68146a32d2590762b | |
parent | 4c31a3a6d31b6214ea774d403bf8ab7ebe1ea862 (diff) | |
download | gcc-c49fcfddaa47f2828fe2af11ae857cd67f53e23f.zip gcc-c49fcfddaa47f2828fe2af11ae857cd67f53e23f.tar.gz gcc-c49fcfddaa47f2828fe2af11ae857cd67f53e23f.tar.bz2 |
c++: cross-header-unit template definitions [PR 99153]
A member function can be defined in a different header-file than the
one defining the class. In such situations we must unmark the decl as
imported. When the entity is a template we failed to unmark the
template_decl.
Perhaps the duplication of these flags on the template_decl from the
underlying decl is an error. I set on the fence about it for a long
time during development, but I don't think now is the time to change
that (barring catastrophic bugs).
PR c++/99153
gcc/cp/
* decl.c (duplicate_decls): Move DECL_MODULE_IMPORT_P propagation
to common-path.
* module.cc (set_defining_module): Add assert.
gcc/testsuite/
* g++.dg/modules/pr99153_a.H: New.
* g++.dg/modules/pr99153_b.H: New.
-rw-r--r-- | gcc/cp/decl.c | 26 | ||||
-rw-r--r-- | gcc/cp/module.cc | 1 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/modules/pr99153_a.H | 11 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/modules/pr99153_b.H | 15 |
4 files changed, 40 insertions, 13 deletions
diff --git a/gcc/cp/decl.c b/gcc/cp/decl.c index 6f3414f..7fa8f52 100644 --- a/gcc/cp/decl.c +++ b/gcc/cp/decl.c @@ -2879,19 +2879,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) (char *) newdecl + sizeof (struct tree_common), sizeof (struct tree_decl_common) - sizeof (struct tree_common)); - if (DECL_LANG_SPECIFIC (olddecl) && DECL_TEMPLATE_INFO (olddecl)) - { - /* Repropagate the module information to the template. */ - tree tmpl = DECL_TI_TEMPLATE (olddecl); - - if (DECL_TEMPLATE_RESULT (tmpl) == olddecl) - { - DECL_MODULE_PURVIEW_P (tmpl) = DECL_MODULE_PURVIEW_P (olddecl); - gcc_checking_assert (!DECL_MODULE_IMPORT_P (olddecl)); - DECL_MODULE_IMPORT_P (tmpl) = false; - } - } - switch (TREE_CODE (newdecl)) { case LABEL_DECL: @@ -2925,6 +2912,19 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden) } } + if (DECL_LANG_SPECIFIC (olddecl) && DECL_TEMPLATE_INFO (olddecl)) + { + /* Repropagate the module information to the template. */ + tree tmpl = DECL_TI_TEMPLATE (olddecl); + + if (DECL_TEMPLATE_RESULT (tmpl) == olddecl) + { + DECL_MODULE_PURVIEW_P (tmpl) = DECL_MODULE_PURVIEW_P (olddecl); + gcc_checking_assert (!DECL_MODULE_IMPORT_P (olddecl)); + DECL_MODULE_IMPORT_P (tmpl) = false; + } + } + if (VAR_OR_FUNCTION_DECL_P (newdecl)) { if (DECL_EXTERNAL (olddecl) diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 3d17b8d..7a40be3 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -18516,6 +18516,7 @@ set_defining_module (tree decl) gcc_checking_assert (!use_tpl); /* Get to the TEMPLATE_DECL. */ decl = TI_TEMPLATE (ti); + gcc_checking_assert (!DECL_MODULE_IMPORT_P (decl)); } /* Record it on the class_members list. */ diff --git a/gcc/testsuite/g++.dg/modules/pr99153_a.H b/gcc/testsuite/g++.dg/modules/pr99153_a.H new file mode 100644 index 0000000..3eaa76b --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/pr99153_a.H @@ -0,0 +1,11 @@ +// { dg-additional-options -fmodule-header } +// { dg-module-cmi {} } + +template<typename _T1> +struct pair +{ + inline void Frob (); +}; + +template<typename _T2> +inline void Widget (); diff --git a/gcc/testsuite/g++.dg/modules/pr99153_b.H b/gcc/testsuite/g++.dg/modules/pr99153_b.H new file mode 100644 index 0000000..5699378 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/pr99153_b.H @@ -0,0 +1,15 @@ +// PR 99153 Mismatched flags on template and result +// { dg-additional-options -fmodule-header } +// { dg-module-cmi {} } + +import "pr99153_a.H"; + +template<class _T1> +inline void pair<_T1>::Frob() +{ } + + +template<typename _T2> +inline void Widget () +{ +} |