When a class template is explicitly instantiated, its member should be too.
authorMatt Austern <austern@apple.com>
Wed, 2 Jun 2004 21:12:54 +0000 (21:12 +0000)
committerMatt Austern <austern@gcc.gnu.org>
Wed, 2 Jun 2004 21:12:54 +0000 (21:12 +0000)
* cp-tree.h (instantiate_decl): new boolean parameter,
undefined_ok. Current behavior is equivalent to its being 0.
* decl2.c (mark_used): Add new argument when calling instantiate_decl
* pt.c (mark_decl_instantiated): Unconditionally make
instantiations explicit unconditionally
(do_decl_instantiation): Don't call SET_DECL_EXPLICIT_INSTANTIATION,
since mark_decl_instantiated now does it.
(instantiate_class_member): New.  Instantiate a member of an
explicitly instantiated class template.
(do_type_instantiation): Explicitly instantiate members of an
explicitly instantiated class template.
(instantiate_decl): if undefined_ok is nonzero, and if we're
trying to explicitly instantiated a template with no definition,
change it to an implicit instantiation.
(instantiate_pending_templates): Add new argument to instantiate_decl.
* tree.c (cp_cannot_inline_tree_fn): Likewise.

From-SVN: r82585

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl2.c
gcc/cp/pt.c
gcc/cp/tree.c

index 636a33c..4eb93dc 100644 (file)
@@ -1,3 +1,22 @@
+2004-06-02  Matt Austern  <austern@apple.com>
+
+       * cp-tree.h (instantiate_decl): new boolean parameter,
+       undefined_ok. Current behavior is equivalent to its being 0.
+       * decl2.c (mark_used): Add new argument when calling instantiate_decl
+       * pt.c (mark_decl_instantiated): Unconditionally make
+       instantiations explicit unconditionally
+       (do_decl_instantiation): Don't call SET_DECL_EXPLICIT_INSTANTIATION,
+       since mark_decl_instantiated now does it.
+       (instantiate_class_member): New.  Instantiate a member of an
+       explicitly instantiated class template.
+       (do_type_instantiation): Explicitly instantiate members of an
+       explicitly instantiated class template.
+       (instantiate_decl): if undefined_ok is nonzero, and if we're
+       trying to explicitly instantiated a template with no definition,
+       change it to an implicit instantiation.
+       (instantiate_pending_templates): Add new argument to instantiate_decl.
+       * tree.c (cp_cannot_inline_tree_fn): Likewise.
+       
 2004-06-02  Andrew Pinski  <pinskia@physics.uc.edu>
 
        * cp-tree.h: Fix typo.
index 50e9fe8..3db4ab6 100644 (file)
@@ -3889,7 +3889,7 @@ extern int more_specialized                       (tree, tree, int, 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);
+extern tree instantiate_decl                   (tree, int, int);
 extern int push_tinst_level                    (tree);
 extern void pop_tinst_level                    (void);
 extern int more_specialized_class              (tree, tree, tree);
index 0b93a58..c5c4a55 100644 (file)
@@ -3069,7 +3069,7 @@ mark_used (tree decl)
                  information.  */
               || cp_function_chain->can_throw);
 
-      instantiate_decl (decl, defer);
+      instantiate_decl (decl, defer, /*undefined_ok=*/0);
     }
 }
 
index 824e8bf..7d915dc 100644 (file)
@@ -10131,13 +10131,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict)
 void
 mark_decl_instantiated (tree result, int extern_p)
 {
-  /* We used to set this unconditionally; we moved that to
-     do_decl_instantiation so it wouldn't get set on members of
-     explicit class template instantiations.  But we still need to set
-     it here for the 'extern template' case in order to suppress
-     implicit instantiations.  */
-  if (extern_p)
-    SET_DECL_EXPLICIT_INSTANTIATION (result);
+  SET_DECL_EXPLICIT_INSTANTIATION (result);
 
   /* If this entity has already been written out, it's too late to
      make any modifications.  */
@@ -10641,11 +10635,10 @@ do_decl_instantiation (tree decl, tree storage)
     error ("storage class `%D' applied to template instantiation",
              storage);
 
-  SET_DECL_EXPLICIT_INSTANTIATION (result);
   mark_decl_instantiated (result, extern_p);
   repo_template_instantiated (result, extern_p);
   if (! extern_p)
-    instantiate_decl (result, /*defer_ok=*/1);
+    instantiate_decl (result, /*defer_ok=*/1, /*undefined_ok=*/0);
 }
 
 void
@@ -10674,6 +10667,18 @@ bt_instantiate_type_proc (binding_entry entry, void *data)
     do_type_instantiation (TYPE_MAIN_DECL (entry->type), storage, 0);
 }
 
+/* Called from do_type_instantiation to instantiate a member
+   (a member function or a static member variable) of an
+   explicitly instantiated class template. */
+static void
+instantiate_class_member (tree decl, int extern_p)
+{
+  mark_decl_instantiated (decl, extern_p);
+  repo_template_instantiated (decl, extern_p);
+  if (! extern_p)
+    instantiate_decl (decl, /*defer_ok=*/1, /* undefined_ok=*/1);
+}
+
 /* Perform an explicit instantiation of template class T.  STORAGE, if
    non-null, is the RID for extern, inline or static.  COMPLAIN is
    nonzero if this is called from the parser, zero if called recursively,
@@ -10773,7 +10778,6 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
 
   {
     tree tmp;
-    int explicitly_instantiate_members = 0;
 
     /* In contrast to implicit instantiation, where only the
        declarations, and not the definitions, of members are
@@ -10789,50 +10793,18 @@ do_type_instantiation (tree t, tree storage, tsubst_flags_t complain)
        Of course, we can't instantiate member template classes, since
        we don't have any arguments for them.  Note that the standard
        is unclear on whether the instantiation of the members are
-       *explicit* instantiations or not.  We choose to be generous,
-       and not set DECL_EXPLICIT_INSTANTIATION.  Therefore, we allow
-       the explicit instantiation of a class where some of the members
-       have no definition in the current translation unit.  Exception:
-       on some targets (e.g. Darwin), weak symbols do not get put in 
-       a static archive's TOC.  The problematic case is if we're doing
-       a non-extern explicit instantiation of an extern template: we
-       have to put member functions in the TOC in that case, or we'll
-       get unresolved symbols at link time.  */
-
-    explicitly_instantiate_members =
-      TARGET_EXPLICIT_INSTANTIATIONS_ONE_ONLY
-      && previous_instantiation_extern_p && ! extern_p
-      && ! TYPE_FOR_JAVA (t);
+       *explicit* instantiations or not.  However, the most natural
+       interpretation is that it should be an explicit instantiation. */
 
     if (! static_p)
       for (tmp = TYPE_METHODS (t); tmp; tmp = TREE_CHAIN (tmp))
        if (TREE_CODE (tmp) == FUNCTION_DECL
            && DECL_TEMPLATE_INSTANTIATION (tmp))
-         {
-           if (explicitly_instantiate_members)
-             do_decl_instantiation (tmp, NULL_TREE);
-           else
-             {
-               mark_decl_instantiated (tmp, extern_p);
-               repo_template_instantiated (tmp, extern_p);
-               if (! extern_p)
-                 instantiate_decl (tmp, /*defer_ok=*/1);
-             }
-         }
+         instantiate_class_member (tmp, extern_p);
 
     for (tmp = TYPE_FIELDS (t); tmp; tmp = TREE_CHAIN (tmp))
       if (TREE_CODE (tmp) == VAR_DECL && DECL_TEMPLATE_INSTANTIATION (tmp))
-       {
-         if (explicitly_instantiate_members)
-           do_decl_instantiation (tmp, NULL_TREE);
-         else
-           {
-             mark_decl_instantiated (tmp, extern_p);
-             repo_template_instantiated (tmp, extern_p);
-             if (! extern_p)
-               instantiate_decl (tmp, /*defer_ok=*/1);
-           }
-       }
+       instantiate_class_member (tmp, extern_p);
 
     if (CLASSTYPE_NESTED_UTDS (t))
       binding_table_foreach (CLASSTYPE_NESTED_UTDS (t),
@@ -10995,10 +10967,16 @@ template_for_substitution (tree decl)
 
 /* Produce the definition of D, a _DECL generated from a template.  If
    DEFER_OK is nonzero, then we don't have to actually do the
-   instantiation now; we just have to do it sometime.  */
+   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. */
+
 
 tree
-instantiate_decl (tree d, int defer_ok)
+instantiate_decl (tree d, int defer_ok, int undefined_ok)
 {
   tree tmpl = DECL_TI_TEMPLATE (d);
   tree gen_args;
@@ -11105,6 +11083,9 @@ instantiate_decl (tree d, int defer_ok)
        import_export_decl (d);
     }
 
+  if (! pattern_defined && DECL_EXPLICIT_INSTANTIATION (d) && undefined_ok)
+    SET_DECL_IMPLICIT_INSTANTIATION (d);
+
   if (!defer_ok)
     {
       /* Recheck the substitutions to obtain any warning messages
@@ -11340,7 +11321,7 @@ instantiate_pending_templates (void)
                         fn;
                         fn = TREE_CHAIN (fn))
                      if (! DECL_ARTIFICIAL (fn))
-                       instantiate_decl (fn, /*defer_ok=*/0);
+                       instantiate_decl (fn, /*defer_ok=*/0, /*undefined_ok=*/0);
                  if (COMPLETE_TYPE_P (instantiation))
                    {
                      instantiated_something = 1;
@@ -11364,7 +11345,8 @@ instantiate_pending_templates (void)
                  && !DECL_TEMPLATE_INSTANTIATED (instantiation))
                {
                  instantiation = instantiate_decl (instantiation,
-                                                   /*defer_ok=*/0);
+                                                   /*defer_ok=*/0,
+                                                   /*undefined_ok=*/0);
                  if (DECL_TEMPLATE_INSTANTIATED (instantiation))
                    {
                      instantiated_something = 1;
index 365e075..81db7ca 100644 (file)
@@ -2057,7 +2057,7 @@ cp_cannot_inline_tree_fn (tree* fnp)
                        (template_for_substitution (fn))))
        return 1;
 
-      fn = *fnp = instantiate_decl (fn, /*defer_ok=*/0);
+      fn = *fnp = instantiate_decl (fn, /*defer_ok=*/0, /*undefined_ok=*/0);
 
       if (TI_PENDING_TEMPLATE_FLAG (DECL_TEMPLATE_INFO (fn)))
        return 1;