re PR c++/22263 (explicit instantiation fails to emit symbols defined later)
authorMark Mitchell <mark@codesourcery.com>
Mon, 18 Jul 2005 15:44:36 +0000 (15:44 +0000)
committerMark Mitchell <mmitchel@gcc.gnu.org>
Mon, 18 Jul 2005 15:44:36 +0000 (15:44 +0000)
PR c++/22263
* cp-tree.h (instantiate_decl): Change prototype.
* decl2.c (mark_used): Adjust accordingly.
* pt.c (do_decl_instantiation): Likewise.
(instantiate_class_member): Likewise.
(instantiate_decl): Rename undefined_ok as expl_inst_class_mem_p.
Clear DECL_INTERFACE_KNOWN for an explicitly instantiated template
that has no definition available.
(instantiate_pending_templates): Adjust call to instantiate_decl.

PR c++/22263
* g++.dg/template/explicit7.C: New test.

From-SVN: r102133

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/pt.c
gcc/testsuite/ChangeLog
gcc/testsuite/g++.dg/template/explicit7.C [new file with mode: 0644]

index 4c048cf4bd83111b4a77a08a8b31b3c7afd6f945..b30aabc1f9a7b4d8daf6f7a00f4187a20f33bbb6 100644 (file)
@@ -1,3 +1,15 @@
+2005-07-18  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/22263
+       * cp-tree.h (instantiate_decl): Change prototype.
+       * decl2.c (mark_used): Adjust accordingly.
+       * pt.c (do_decl_instantiation): Likewise.
+       (instantiate_class_member): Likewise.
+       (instantiate_decl): Rename undefined_ok as expl_inst_class_mem_p.
+       Clear DECL_INTERFACE_KNOWN for an explicitly instantiated template
+       that has no definition available.
+       (instantiate_pending_templates): Adjust call to instantiate_decl.
+
 2005-07-17  Mark Mitchell  <mark@codesourcery.com>
 
        PR c++/22139
index 2d5e5f1f41d518413c8029ac5fa40afc08b4fcdb..d9d053d6dfb0397b5904835156d3a71317fbbecf 100644 (file)
@@ -3997,7 +3997,7 @@ extern int more_specialized_fn                    (tree, tree, int);
 extern void mark_class_instantiated            (tree, int);
 extern void do_decl_instantiation              (tree, tree);
 extern void do_type_instantiation              (tree, tree, tsubst_flags_t);
-extern tree instantiate_decl                   (tree, int, int);
+extern tree instantiate_decl                   (tree, int, bool);
 extern int push_tinst_level                    (tree);
 extern void pop_tinst_level                    (void);
 extern int more_specialized_class              (tree, tree, tree);
index 22166e8b398234271953983eea8b7b40c253e937..5afcd896cc14a080cc6906e28bf2312f64151d6d 100644 (file)
@@ -3278,7 +3278,8 @@ mark_used (tree decl)
        times.  Maintaining a stack of active functions is expensive,
        and the inliner knows to instantiate any functions it might
        need.  */
-    instantiate_decl (decl, /*defer_ok=*/true, /*undefined_ok=*/0);
+    instantiate_decl (decl, /*defer_ok=*/true, 
+                     /*expl_inst_class_mem_p=*/false);
 }
 
 #include "gt-cp-decl2.h"
index bbf3bf9bb34eefd9d52136b01cb953d5c20ef0ec..619cdc117524c7e3157637aeb5d9f5645cfe1260 100644 (file)
@@ -11010,7 +11010,8 @@ do_decl_instantiation (tree decl, tree storage)
 
   mark_decl_instantiated (result, extern_p);
   if (! extern_p)
-    instantiate_decl (result, /*defer_ok=*/1, /*undefined_ok=*/0);
+    instantiate_decl (result, /*defer_ok=*/1, 
+                     /*expl_inst_class_mem_p=*/false);
 }
 
 void
@@ -11047,7 +11048,8 @@ instantiate_class_member (tree decl, int extern_p)
 {
   mark_decl_instantiated (decl, extern_p);
   if (! extern_p)
-    instantiate_decl (decl, /*defer_ok=*/1, /* undefined_ok=*/1);
+    instantiate_decl (decl, /*defer_ok=*/1, 
+                     /*expl_inst_class_mem_p=*/true);
 }
 
 /* Perform an explicit instantiation of template class T.  STORAGE, if
@@ -11343,14 +11345,12 @@ template_for_substitution (tree decl)
    DEFER_OK is nonzero, then we don't have to actually do the
    instantiation now; we just have to do it sometime.  Normally it is
    an error if this is an explicit instantiation but D is undefined.
-   If UNDEFINED_OK is nonzero, then instead we treat it as an implicit
-   instantiation.  UNDEFINED_OK is nonzero only if we are being used
-   to instantiate the members of an explicitly instantiated class
-   template.  */
-
+   EXPL_INST_CLASS_MEM_P is true iff D is a member of an
+   explicitly instantiated class template.  */
 
 tree
-instantiate_decl (tree d, int defer_ok, int undefined_ok)
+instantiate_decl (tree d, int defer_ok, 
+                 bool expl_inst_class_mem_p)
 {
   tree tmpl = DECL_TI_TEMPLATE (d);
   tree gen_args;
@@ -11439,9 +11439,14 @@ instantiate_decl (tree d, int defer_ok, int undefined_ok)
 
   input_location = DECL_SOURCE_LOCATION (d);
 
-  if (! pattern_defined && DECL_EXPLICIT_INSTANTIATION (d) && undefined_ok)
+  /* If D is a member of an explicitly instantiated class template,
+     and no definition is available, treat it like an implicit
+     instantiation.  */ 
+  if (!pattern_defined && expl_inst_class_mem_p 
+      && DECL_EXPLICIT_INSTANTIATION (d)) 
     {
       DECL_NOT_REALLY_EXTERN (d) = 0;
+      DECL_INTERFACE_KNOWN (d) = 0;
       SET_DECL_IMPLICIT_INSTANTIATION (d);
     }
 
@@ -11678,8 +11683,9 @@ instantiate_pending_templates (int retries)
                         fn;
                         fn = TREE_CHAIN (fn))
                      if (! DECL_ARTIFICIAL (fn))
-                       instantiate_decl (fn, /*defer_ok=*/0,
-                                         /*undefined_ok=*/0);
+                       instantiate_decl (fn, 
+                                         /*defer_ok=*/0,
+                                         /*expl_inst_class_mem_p=*/false);
                  if (COMPLETE_TYPE_P (instantiation))
                    reconsider = 1;
                }
@@ -11699,9 +11705,10 @@ instantiate_pending_templates (int retries)
              if (!DECL_TEMPLATE_SPECIALIZATION (instantiation)
                  && !DECL_TEMPLATE_INSTANTIATED (instantiation))
                {
-                 instantiation = instantiate_decl (instantiation,
-                                                   /*defer_ok=*/0,
-                                                   /*undefined_ok=*/0);
+                 instantiation 
+                   = instantiate_decl (instantiation,
+                                       /*defer_ok=*/0,
+                                       /*expl_inst_class_mem_p=*/false);
                  if (DECL_TEMPLATE_INSTANTIATED (instantiation))
                    reconsider = 1;
                }
index 80b9604ecbf3f1693399fed0a1fef13b65ebfa46..88228523684e679e74289f0e44678c0ee718131e 100644 (file)
@@ -1,3 +1,8 @@
+2005-07-18  Mark Mitchell  <mark@codesourcery.com>
+
+       PR c++/22263
+       * g++.dg/template/explicit7.C: New test.
+
 2005-07-17  Jerry DeLisle  <jvdelisle@verizon.net>
     * gfortran.fortran-torture/execute/nan_inf_fmt.f90: Change case of field
     width of 8 to +Inf and -Inf.
diff --git a/gcc/testsuite/g++.dg/template/explicit7.C b/gcc/testsuite/g++.dg/template/explicit7.C
new file mode 100644 (file)
index 0000000..7424677
--- /dev/null
@@ -0,0 +1,13 @@
+// PR c++/22263
+// { dg-do link }
+
+template <class T> struct S { T foo (); T bar (); };
+template <class T> T S<T>::foo () { return bar (); }
+template struct S<int>;
+template <class T> T S<T>::bar () { return T (); }
+
+#if !__GXX_WEAK__
+template int S<int>::bar ();
+#endif
+
+int main () { return S<int>().foo (); }