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.
--
Nathan Sidwell
diff --git c/gcc/cp/decl.c w/gcc/cp/decl.c
index 6f3414f058e..7fa8f52d667 100644
--- c/gcc/cp/decl.c
+++ w/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 c/gcc/cp/module.cc w/gcc/cp/module.cc
index 3d17b8ddcdb..7a40be3db35 100644
--- c/gcc/cp/module.cc
+++ w/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 c/gcc/testsuite/g++.dg/modules/pr99153_a.H w/gcc/testsuite/g++.dg/modules/pr99153_a.H
new file mode 100644
index 00000000000..3eaa76bdc32
--- /dev/null
+++ w/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 c/gcc/testsuite/g++.dg/modules/pr99153_b.H w/gcc/testsuite/g++.dg/modules/pr99153_b.H
new file mode 100644
index 00000000000..5699378d317
--- /dev/null
+++ w/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 ()
+{
+}