]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c++: cross-header-unit template definitions [PR 99153]
authorNathan Sidwell <nathan@acm.org>
Mon, 22 Feb 2021 14:43:32 +0000 (06:43 -0800)
committerNathan Sidwell <nathan@acm.org>
Mon, 22 Feb 2021 14:52:19 +0000 (06:52 -0800)
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.

gcc/cp/decl.c
gcc/cp/module.cc
gcc/testsuite/g++.dg/modules/pr99153_a.H [new file with mode: 0644]
gcc/testsuite/g++.dg/modules/pr99153_b.H [new file with mode: 0644]

index 6f3414f058eb8b6a28fdb8a0134332de975bc2b0..7fa8f52d6677a91b31ac584548e2e4a33c47c180 100644 (file)
@@ -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)
index 3d17b8ddcdb8b7a1ec4eaf6fc31fa222aa793c92..7a40be3db353ce2bb78d9da5c8d32cf789b316ad 100644 (file)
@@ -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 (file)
index 0000000..3eaa76b
--- /dev/null
@@ -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 (file)
index 0000000..5699378
--- /dev/null
@@ -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 () 
+{
+}