c++: cross-header-unit template definitions [PR 99153]

Message ID 5631a031-e519-bfb4-a6cf-30b2ece000e3@acm.org
State New
Headers show
Series
  • c++: cross-header-unit template definitions [PR 99153]
Related show

Commit Message

Nathan Sidwell Feb. 22, 2021, 2:49 p.m.
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

Patch

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