OSDN Git Service

* cp-tree.h (DECL_TEMPLATE_INSTANTIATED): New macro.
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 16 Nov 1998 08:34:38 +0000 (08:34 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Mon, 16 Nov 1998 08:34:38 +0000 (08:34 +0000)
* decl.c (duplicate_decls): Remove special-case code to deal with
template friends, and just do the obvious thing.
* pt.c (register_specialization): Tweak for clarity, and also to
clear DECL_INITIAL for an instantiation before it is merged with a
specialization.
(check_explicit_specialization): Fix indentation.
(tsubst_friend_function): Handle both definitions in friend
declaration and outside friend declarations.
(tsubst_decl): Don't clear DECL_INITIAL for an instantiation.
(regenerate_decl_from_template): Tweak accordingly.
(instantiate_decl): Likewise.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@23674 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/cp/ChangeLog
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/pt.c
gcc/testsuite/g++.old-deja/g++.pt/friend36.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/ttp53.C

index 86503ae..bbd8664 100644 (file)
@@ -1,3 +1,18 @@
+1998-11-16  Mark Mitchell  <mark@markmitchell.com>
+
+       * cp-tree.h (DECL_TEMPLATE_INSTANTIATED): New macro.
+       * decl.c (duplicate_decls): Remove special-case code to deal with
+       template friends, and just do the obvious thing.
+       * pt.c (register_specialization): Tweak for clarity, and also to
+       clear DECL_INITIAL for an instantiation before it is merged with a
+       specialization.
+       (check_explicit_specialization): Fix indentation.
+       (tsubst_friend_function): Handle both definitions in friend
+       declaration and outside friend declarations.
+       (tsubst_decl): Don't clear DECL_INITIAL for an instantiation.
+       (regenerate_decl_from_template): Tweak accordingly.
+       (instantiate_decl): Likewise.
+       
 1998-11-16  Jason Merrill  <jason@yorick.cygnus.com>
 
        * decl.c (cplus_expand_expr_stmt): Promote warning about naked
index a6e2e2d..8cf5594 100644 (file)
@@ -65,6 +65,7 @@ Boston, MA 02111-1307, USA.  */
    Usage of DECL_LANG_FLAG_?:
    0: DECL_ERROR_REPORTED (in VAR_DECL).
    1: C_TYPEDEF_EXPLICITLY_SIGNED (in TYPE_DECL).
+      DECL_TEMPLATE_INSTANTIATED (in a VAR_DECL or a FUNCTION_DECL)
    2: DECL_THIS_EXTERN (in VAR_DECL or FUNCTION_DECL).
    3: DECL_IN_AGGR_P.
    4: DECL_MAYBE_TEMPLATE.
@@ -1812,6 +1813,12 @@ extern int flag_new_for_scope;
 
 /* This function may be a guiding decl for a template.  */
 #define DECL_MAYBE_TEMPLATE(NODE) DECL_LANG_FLAG_4 (NODE)
+
+/* Nonzero if this VAR_DECL or FUNCTION_DECL has already been
+   instantiated, i.e. its definition has been generated from the
+   pattern given in the the template.  */
+#define DECL_TEMPLATE_INSTANTIATED(NODE) DECL_LANG_FLAG_1(NODE)
+
 /* We know what we're doing with this decl now.  */
 #define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE)
 
index 33c4449..a9779f9 100644 (file)
@@ -2989,9 +2989,6 @@ duplicate_decls (newdecl, olddecl)
                             DECL_TEMPLATE_RESULT (olddecl)))
        cp_error ("invalid redeclaration of %D", newdecl);
       TREE_TYPE (olddecl) = TREE_TYPE (DECL_TEMPLATE_RESULT (olddecl));
-      DECL_TEMPLATE_PARMS (olddecl) = DECL_TEMPLATE_PARMS (newdecl);
-      if (DECL_TEMPLATE_INFO (newdecl))
-       DECL_TEMPLATE_INFO (olddecl) = DECL_TEMPLATE_INFO (newdecl);
       DECL_TEMPLATE_SPECIALIZATIONS (olddecl) 
        = chainon (DECL_TEMPLATE_SPECIALIZATIONS (olddecl),
                   DECL_TEMPLATE_SPECIALIZATIONS (newdecl));
@@ -3123,11 +3120,7 @@ duplicate_decls (newdecl, olddecl)
       DECL_IN_AGGR_P (newdecl) = DECL_IN_AGGR_P (olddecl);
       DECL_ACCESS (newdecl) = DECL_ACCESS (olddecl);
       DECL_NONCONVERTING_P (newdecl) = DECL_NONCONVERTING_P (olddecl);
-      if (DECL_TEMPLATE_INFO (newdecl) == NULL_TREE)
-       {
-         DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
-         DECL_USE_TEMPLATE (newdecl) = DECL_USE_TEMPLATE (olddecl);
-       }
+      DECL_TEMPLATE_INFO (newdecl) = DECL_TEMPLATE_INFO (olddecl);
       olddecl_friend = DECL_FRIEND_P (olddecl);
     }
 
index fb5bb54..655a72b 100644 (file)
@@ -831,15 +831,22 @@ register_specialization (spec, tmpl, args)
 
                       We transform the existing DECL in place so that
                       any pointers to it become pointers to the
-                      updated declaration.  */
-                   duplicate_decls (spec, TREE_VALUE (s));
-                   return TREE_VALUE (s);
+                      updated declaration.  
+
+                      If there was a definition for the template, but
+                      not for the specialization, we want this to
+                      look as if there is no definition, and vice
+                      versa.  */
+                   DECL_INITIAL (fn) = NULL_TREE;
+                   duplicate_decls (spec, fn);
+
+                   return fn;
                  }
              }
            else if (DECL_TEMPLATE_SPECIALIZATION (fn))
              {
-               duplicate_decls (spec, TREE_VALUE (s));
-               return TREE_VALUE (s);
+               duplicate_decls (spec, fn);
+               return fn;
              }
          }
       }
@@ -1369,7 +1376,7 @@ check_explicit_specialization (declarator, decl, template_count, flags)
            /* This is not really a declaration of a specialization.
               It's just the name of an instantiation.  But, it's not
               a request for an instantiation, either.  */
-             SET_DECL_IMPLICIT_INSTANTIATION (decl);
+           SET_DECL_IMPLICIT_INSTANTIATION (decl);
 
          /* Register this specialization so that we can find it
             again.  */
@@ -4247,16 +4254,30 @@ tsubst_friend_function (decl, args)
   if (DECL_NAMESPACE_SCOPE_P (new_friend))
     {
       tree old_decl;
-      tree new_friend_args;
-
+      tree new_friend_template_info;
+      tree new_friend_result_template_info;
+      int  new_friend_is_defn;
+
+      /* We must save some information from NEW_FRIEND before calling
+        duplicate decls since that function will free NEW_FRIEND if
+        possible.  */
+      new_friend_template_info = DECL_TEMPLATE_INFO (new_friend);
       if (TREE_CODE (new_friend) == TEMPLATE_DECL)
-       /* This declaration is a `primary' template.  */
-       DECL_PRIMARY_TEMPLATE (new_friend) = new_friend;
+       {
+         /* This declaration is a `primary' template.  */
+         DECL_PRIMARY_TEMPLATE (new_friend) = new_friend;
+         
+         new_friend_is_defn 
+           = DECL_INITIAL (DECL_RESULT (new_friend)) != NULL_TREE;
+         new_friend_result_template_info
+           = DECL_TEMPLATE_INFO (DECL_RESULT (new_friend));
+       }
+      else
+       {
+         new_friend_is_defn = DECL_INITIAL (new_friend) != NULL_TREE;
+         new_friend_result_template_info = NULL_TREE;
+       }
 
-      /* We must save the DECL_TI_ARGS for NEW_FRIEND here because
-        pushdecl may call duplicate_decls which will free NEW_FRIEND
-        if possible.  */
-      new_friend_args = DECL_TI_ARGS (new_friend);
       old_decl = pushdecl_namespace_level (new_friend);
 
       if (old_decl != new_friend)
@@ -4295,36 +4316,55 @@ tsubst_friend_function (decl, args)
             when `C<int>' is instantiated.  Now, `f(int)' is defined
             in the class.  */
 
-         if (TREE_CODE (old_decl) != TEMPLATE_DECL)
-           /* duplicate_decls will take care of this case.  */
+         if (!new_friend_is_defn)
+           /* On the other hand, if the in-class declaration does
+              *not* provide a definition, then we don't want to alter
+              existing definitions.  We can just leave everything
+              alone.  */
            ;
-         else 
+         else
            {
-             tree t;
-
-             for (t = DECL_TEMPLATE_SPECIALIZATIONS (old_decl); 
-                  t != NULL_TREE;
-                  t = TREE_CHAIN (t))
+             /* Overwrite whatever template info was there before, if
+                any, with the new template information pertaining to
+                the declaration.  */
+             DECL_TEMPLATE_INFO (old_decl) = new_friend_template_info;
+
+             if (TREE_CODE (old_decl) != TEMPLATE_DECL)
+               /* duplicate_decls will take care of this case.  */
+               ;
+             else 
                {
-                 tree spec = TREE_VALUE (t);
+                 tree t;
+                 tree new_friend_args;
+
+                 DECL_TEMPLATE_INFO (DECL_RESULT (old_decl)) 
+                   = new_friend_result_template_info;
+                   
+                 new_friend_args = TI_ARGS (new_friend_template_info);
+                 for (t = DECL_TEMPLATE_SPECIALIZATIONS (old_decl); 
+                      t != NULL_TREE;
+                      t = TREE_CHAIN (t))
+                   {
+                     tree spec = TREE_VALUE (t);
                  
-                 DECL_TI_ARGS (spec) 
-                   = add_outermost_template_args (new_friend_args,
-                                                  DECL_TI_ARGS (spec));
-                 DECL_TI_ARGS (spec)
-                   = copy_to_permanent (DECL_TI_ARGS (spec));
-               }
-
-             /* Now, since specializations are always supposed to
-                hang off of the most general template, we must move
-                them.  */
-             t = most_general_template (old_decl);
-             if (t != old_decl)
-               {
-                 DECL_TEMPLATE_SPECIALIZATIONS (t)
-                   = chainon (DECL_TEMPLATE_SPECIALIZATIONS (t),
-                              DECL_TEMPLATE_SPECIALIZATIONS (old_decl));
-                 DECL_TEMPLATE_SPECIALIZATIONS (old_decl) = NULL_TREE;
+                     DECL_TI_ARGS (spec) 
+                       = add_outermost_template_args (new_friend_args,
+                                                      DECL_TI_ARGS (spec));
+                     DECL_TI_ARGS (spec)
+                       = copy_to_permanent (DECL_TI_ARGS (spec));
+                   }
+
+                 /* Now, since specializations are always supposed to
+                    hang off of the most general template, we must move
+                    them.  */
+                 t = most_general_template (old_decl);
+                 if (t != old_decl)
+                   {
+                     DECL_TEMPLATE_SPECIALIZATIONS (t)
+                       = chainon (DECL_TEMPLATE_SPECIALIZATIONS (t),
+                                  DECL_TEMPLATE_SPECIALIZATIONS (old_decl));
+                     DECL_TEMPLATE_SPECIALIZATIONS (old_decl) = NULL_TREE;
+                   }
                }
            }
 
@@ -5312,7 +5352,6 @@ tsubst_decl (t, args, type, in_decl)
        DECL_ARGUMENTS (r) = tsubst (DECL_ARGUMENTS (t), args, t);
        DECL_MAIN_VARIANT (r) = r;
        DECL_RESULT (r) = NULL_TREE;
-       DECL_INITIAL (r) = NULL_TREE;
 
        TREE_STATIC (r) = 0;
        TREE_PUBLIC (r) = TREE_PUBLIC (t);
@@ -8285,9 +8324,13 @@ regenerate_decl_from_template (decl, tmpl)
     }
 
   if (TREE_CODE (decl) == FUNCTION_DECL)
-    /* Convince duplicate_decls to use the DECL_ARGUMENTS from the
-       new decl.  */ 
-    DECL_INITIAL (new_decl) = error_mark_node;
+    {
+      /* Convince duplicate_decls to use the DECL_ARGUMENTS from the
+        new decl.  */ 
+      DECL_INITIAL (new_decl) = error_mark_node;
+      /* And don't complain about a duplicate definition.  */
+      DECL_INITIAL (decl) = NULL_TREE;
+    }
 
   /* The immediate parent of the new template is still whatever it was
      before, even though tsubst sets DECL_TI_TEMPLATE up as the most
@@ -8303,9 +8346,6 @@ regenerate_decl_from_template (decl, tmpl)
   /* Call duplicate decls to merge the old and new declarations.  */
   duplicate_decls (new_decl, decl);
 
-  if (TREE_CODE (decl) == FUNCTION_DECL)
-    DECL_INITIAL (new_decl) = NULL_TREE;
-
   /* Now, re-register the specialization.  */
   register_specialization (decl, gen_tmpl, args);
 }
@@ -8332,8 +8372,7 @@ instantiate_decl (d)
   my_friendly_assert (TREE_CODE (d) == FUNCTION_DECL
                      || TREE_CODE (d) == VAR_DECL, 0);
 
-  if ((TREE_CODE (d) == FUNCTION_DECL && DECL_INITIAL (d))
-      || (TREE_CODE (d) == VAR_DECL && !DECL_IN_AGGR_P (d)))
+  if (DECL_TEMPLATE_INSTANTIATED (d))
     /* D has already been instantiated.  It might seem reasonable to
        check whether or not D is an explict instantiation, and, if so,
        stop here.  But when an explicit instantiation is deferred
@@ -8398,9 +8437,6 @@ instantiate_decl (d)
         cannot restructure the loop to just keep going until we find
         a template with a definition, since that might go too far if
         a specialization was declared, but not defined.  */
-      my_friendly_assert (!(TREE_CODE (d) == FUNCTION_DECL
-                           && DECL_INITIAL (DECL_TEMPLATE_RESULT (td))),
-                         0);
       my_friendly_assert (!(TREE_CODE (d) == VAR_DECL
                            && !DECL_IN_AGGR_P (DECL_TEMPLATE_RESULT (td))), 
                          0); 
@@ -8483,6 +8519,7 @@ instantiate_decl (d)
     }
 
   regenerate_decl_from_template (d, td);
+  DECL_TEMPLATE_INSTANTIATED (d) = 1;
 
   /* We already set the file and line above.  Reset them now in case
      they changed as a result of calling regenerate_decl_from_template.  */
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/friend36.C b/gcc/testsuite/g++.old-deja/g++.pt/friend36.C
new file mode 100644 (file)
index 0000000..4a9042a
--- /dev/null
@@ -0,0 +1,12 @@
+// Build don't link:
+
+template <class T>
+void f(T) {} // ERROR - previously defined here
+
+template <class U>
+struct S {
+  template <class T>
+  friend void f(T) {} // ERROR - redeclaration
+};
+
+S<int> si;
index 694635d..e5e87b4 100644 (file)
@@ -13,7 +13,7 @@ class H{
 public:
 #endif
   template<template<class, class> class Caster, typename Source>
-  static H<Type> cast(const H<Source>& s); // gets bogus error - candidate - XFAIL *-*-*
+  static H<Type> cast(const H<Source>& s);
 
 #ifndef OK
   template <typename Target, typename Source>
@@ -26,10 +26,10 @@ template <class, class> class caster;
 
 template <typename Target, typename Source>
 H<Target> foo(const H<Source>& s){
-  return H<Target>::template cast<caster, Source>(s); // gets bogus error - no match - XFAIL *-*-*
+  return H<Target>::template cast<caster, Source>(s);
 }
 
 int main(){
   H<int> i;
-  foo<const int>(i); // gets bogus error - instantiated from here - XFAIL *-*-*
+  foo<const int>(i);
 }