OSDN Git Service

1999-02-19 Mark Mitchell <mark@markmitchell.com>
authormmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 21 Feb 1999 16:38:23 +0000 (16:38 +0000)
committermmitchel <mmitchel@138bc75d-0d04-0410-961f-82ee72b054a4>
Sun, 21 Feb 1999 16:38:23 +0000 (16:38 +0000)
* cp-tree.h (CLASSTYPE_METHOD_VEC): Adjust comment.
(fn_type_unification): Adjust prototype.
(lookup_fnfields_1): Declare.
* call.c (add_template_candidate_real): Adjust call to
fn_type_unification.
* class.c (add_method): Don't allow duplicate declarations of
constructors or destructors.
(resolve_address_of_overloaded_function): Remove unused variable.
Adjust call to fn_type_unification.
* decl.c (grokfndecl): Be more robust in the face of illegal
specializations.
* decl2.c (check_classfn): Remove hokey handling of member
templates.
* pt.c (determine_specialization): Improve comments.  Adjust to
handle template argument deduction as per the standard.
(check_explicit_specialization): Fix comment spacing.  Handle
type-conversion operators correctly.  Improve error-recovery.
(fn_type_unification): Remove EXTRA_FN_ARG parameter.
(get_bindings_real): Simplify handling of static members.
* search.c (lookup_fnfields_1): Make it have external linkage.
* typeck.c (compparms): Fix comment.
(build_unary_op): Don't try to figure out which template
specialization is being referred to when when the address-of
operator is used with a template function.

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

18 files changed:
gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/class.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/pt.c
gcc/cp/search.c
gcc/cp/typeck.c
gcc/testsuite/g++.old-deja/g++.other/redecl2.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/explicit1.C
gcc/testsuite/g++.old-deja/g++.pt/explicit2.C
gcc/testsuite/g++.old-deja/g++.pt/explicit26.C
gcc/testsuite/g++.old-deja/g++.pt/explicit27.C
gcc/testsuite/g++.old-deja/g++.pt/explicit28.C
gcc/testsuite/g++.old-deja/g++.pt/explicit30.C
gcc/testsuite/g++.old-deja/g++.pt/spec29.C [new file with mode: 0644]
gcc/testsuite/g++.old-deja/g++.pt/spec30.C [new file with mode: 0644]

index 38b713d..3a8d0db 100644 (file)
@@ -1,3 +1,30 @@
+1999-02-19  Mark Mitchell  <mark@markmitchell.com>
+
+       * cp-tree.h (CLASSTYPE_METHOD_VEC): Adjust comment.
+       (fn_type_unification): Adjust prototype.
+       (lookup_fnfields_1): Declare.
+       * call.c (add_template_candidate_real): Adjust call to
+       fn_type_unification.
+       * class.c (add_method): Don't allow duplicate declarations of
+       constructors or destructors.
+       (resolve_address_of_overloaded_function): Remove unused variable.
+       Adjust call to fn_type_unification.
+       * decl.c (grokfndecl): Be more robust in the face of illegal
+       specializations.
+       * decl2.c (check_classfn): Remove hokey handling of member
+       templates.
+       * pt.c (determine_specialization): Improve comments.  Adjust to
+       handle template argument deduction as per the standard.
+       (check_explicit_specialization): Fix comment spacing.  Handle
+       type-conversion operators correctly.  Improve error-recovery.
+       (fn_type_unification): Remove EXTRA_FN_ARG parameter.
+       (get_bindings_real): Simplify handling of static members.
+       * search.c (lookup_fnfields_1): Make it have external linkage.
+       * typeck.c (compparms): Fix comment.
+       (build_unary_op): Don't try to figure out which template
+       specialization is being referred to when when the address-of
+       operator is used with a template function.
+       
 Thu Feb 18 23:40:01 1999  Kaveh R. Ghazi  <ghazi@caip.rutgers.edu>
 
        * cp-tree.h (lvalue_or_else): Qualify a char* with the `const'
index 83e1d69..1e43233 100644 (file)
@@ -1948,7 +1948,7 @@ add_template_candidate_real (candidates, tmpl, explicit_targs,
   tree fn;
 
   i = fn_type_unification (tmpl, explicit_targs, targs, arglist,
-                          return_type, strict, NULL_TREE);
+                          return_type, strict);
 
   if (i != 0)
     return candidates;
index afcc89a..d2eaa97 100644 (file)
@@ -1136,6 +1136,7 @@ add_method (type, fields, method)
   else 
     {
       int len;
+      int slot;
       tree method_vec;
 
       if (!CLASSTYPE_METHOD_VEC (type))
@@ -1157,27 +1158,20 @@ add_method (type, fields, method)
       len = TREE_VEC_LENGTH (method_vec);
 
       if (DECL_NAME (method) == constructor_name (type))
-       {
-         /* A new constructor or destructor.  Constructors go in 
-            slot 0; destructors go in slot 1.  */
-         int slot 
-           = DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (method)) ? 1 : 0;
-
-         TREE_VEC_ELT (method_vec, slot)
-           = build_overload (method, TREE_VEC_ELT (method_vec, slot));
-       }
+       /* A new constructor or destructor.  Constructors go in 
+          slot 0; destructors go in slot 1.  */
+       slot = DESTRUCTOR_NAME_P (DECL_ASSEMBLER_NAME (method)) ? 1 : 0;
       else
        {
-         int i;
-
          /* See if we already have an entry with this name.  */
-         for (i = 2; i < len; ++i)
-           if (!TREE_VEC_ELT (method_vec, i)
-               || (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, i))) 
+         for (slot = 2; slot < len; ++slot)
+           if (!TREE_VEC_ELT (method_vec, slot)
+               || (DECL_NAME (OVL_CURRENT (TREE_VEC_ELT (method_vec, 
+                                                         slot))) 
                    == DECL_NAME (method)))
              break;
                
-         if (i == len)
+         if (slot == len)
            {
              /* We need a bigger method vector.  */
              tree new_vec = make_method_vec (2 * len);
@@ -1188,76 +1182,8 @@ add_method (type, fields, method)
              len = 2 * len;
              method_vec = CLASSTYPE_METHOD_VEC (type) = new_vec;
            }
-         else if (template_class_depth (type))
-           /* TYPE is a template class.  Don't issue any errors now;
-              wait until instantiation time to complain.  */
-             ;
-         else
-           {
-             tree fns;
-
-             /* Check to see if we've already got this method.  */
-             for (fns = TREE_VEC_ELT (method_vec, i);
-                  fns;
-                  fns = OVL_NEXT (fns))
-               {
-                 tree fn = OVL_CURRENT (fns);
-                
-                 if (TREE_CODE (fn) != TREE_CODE (method))
-                   continue;
-
-                 if (TREE_CODE (method) != TEMPLATE_DECL)
-                   {
-                     /* [over.load] Member function declarations with the
-                        same name and the same parameter types cannot be
-                        overloaded if any of them is a static member
-                        function declaration.  */
-                     if (DECL_STATIC_FUNCTION_P (fn)
-                         != DECL_STATIC_FUNCTION_P (method))
-                       {
-                         tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn));
-                         tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (method));
-
-                         if (! DECL_STATIC_FUNCTION_P (fn))
-                           parms1 = TREE_CHAIN (parms1);
-                         else
-                           parms2 = TREE_CHAIN (parms2);
-
-                         if (compparms (parms1, parms2))
-                           cp_error ("`%#D' and `%#D' cannot be overloaded",
-                                     fn, method);
-                       }
-
-                     /* Since this is an ordinary function in a
-                        non-template class, it's mangled name can be
-                        used as a unique identifier.  This technique
-                        is only an optimization; we would get the
-                        same results if we just used decls_match
-                        here.  */
-                     if (DECL_ASSEMBLER_NAME (fn) 
-                         != DECL_ASSEMBLER_NAME (method))
-                       continue;
-                   }
-                 else if (!decls_match (fn, method))
-                   continue;
-
-                 /* There has already been a declaration of this
-                    method or member template.  */
-                 cp_error_at ("`%D' has already been declared in `%T'", 
-                              method, type);
-
-                 /* We don't call duplicate_decls here to merege the
-                    declarations because that will confuse things if
-                    the methods have inline definitions In
-                    particular, we will crash while processing the
-                    definitions.  */
-                 return;
-               }
-           }
 
-         if (TREE_VEC_ELT (method_vec, i))
-           /* We found a match.  */;
-         else if (DECL_CONV_FN_P (method))
+         if (DECL_CONV_FN_P (method) && !TREE_VEC_ELT (method_vec, slot))
            {
              /* Type conversion operators have to come before
                 ordinary methods; add_conversions depends on this to
@@ -1265,42 +1191,107 @@ add_method (type, fields, method)
                 necessary, we slide some of the vector elements up.
                 In theory, this makes this algorithm O(N^2) but we
                 don't expect many conversion operators.  */
-             for (i = 2; i < len; ++i)
+             for (slot = 2; slot < len; ++slot)
                {
-                 tree fn = TREE_VEC_ELT (method_vec, i);
-
+                 tree fn = TREE_VEC_ELT (method_vec, slot);
+  
                  if (!fn)
                    /* There are no more entries in the vector, so we
                       can insert the new conversion operator here.  */
                    break;
-                 
-                 if (! DECL_CONV_FN_P (OVL_CURRENT (fn)))
-                   /* We can insert the new function right at the Ith
-                      position.  */
+                 
+                 if (!DECL_CONV_FN_P (OVL_CURRENT (fn)))
+                   /* We can insert the new function right at the
+                      SLOTth position.  */
                    break;
                }
-
-             if (!TREE_VEC_ELT (method_vec, i))
+  
+             if (!TREE_VEC_ELT (method_vec, slot))
                /* There is nothing in the Ith slot, so we can avoid
                   moving anything.  */
                ; 
              else
                {
                  /* We know the last slot in the vector is empty
-                    because we know that at this point there's room for
-                    a new function.  */
-                 bcopy ((PTR) &TREE_VEC_ELT (method_vec, i),
-                        (PTR) &TREE_VEC_ELT (method_vec, i + 1),
-                        (len - i - 1) * sizeof (tree));
-                 TREE_VEC_ELT (method_vec, i) = NULL_TREE;
+                    because we know that at this point there's room
+                    for a new function.  */
+                 bcopy ((PTR) &TREE_VEC_ELT (method_vec, slot),
+                        (PTR) &TREE_VEC_ELT (method_vec, slot + 1),
+                        (len - slot - 1) * sizeof (tree));
+                 TREE_VEC_ELT (method_vec, slot) = NULL_TREE;
                }
            }
-
-         /* Actually insert the new method.  */
-         TREE_VEC_ELT (method_vec, i) 
-           = build_overload (method, TREE_VEC_ELT (method_vec, i));
        }
       
+      if (template_class_depth (type))
+       /* TYPE is a template class.  Don't issue any errors now; wait
+          until instantiation time to complain.  */
+         ;
+      else
+       {
+         tree fns;
+
+         /* Check to see if we've already got this method.  */
+         for (fns = TREE_VEC_ELT (method_vec, slot);
+              fns;
+              fns = OVL_NEXT (fns))
+           {
+             tree fn = OVL_CURRENT (fns);
+                
+             if (TREE_CODE (fn) != TREE_CODE (method))
+               continue;
+
+             if (TREE_CODE (method) != TEMPLATE_DECL)
+               {
+                 /* [over.load] Member function declarations with the
+                    same name and the same parameter types cannot be
+                    overloaded if any of them is a static member
+                    function declaration.  */
+                 if (DECL_STATIC_FUNCTION_P (fn)
+                     != DECL_STATIC_FUNCTION_P (method))
+                   {
+                     tree parms1 = TYPE_ARG_TYPES (TREE_TYPE (fn));
+                     tree parms2 = TYPE_ARG_TYPES (TREE_TYPE (method));
+
+                     if (! DECL_STATIC_FUNCTION_P (fn))
+                       parms1 = TREE_CHAIN (parms1);
+                     else
+                       parms2 = TREE_CHAIN (parms2);
+
+                     if (compparms (parms1, parms2))
+                       cp_error ("`%#D' and `%#D' cannot be overloaded",
+                                 fn, method);
+                   }
+
+                 /* Since this is an ordinary function in a
+                    non-template class, it's mangled name can be used
+                    as a unique identifier.  This technique is only
+                    an optimization; we would get the same results if
+                    we just used decls_match here.  */
+                 if (DECL_ASSEMBLER_NAME (fn) 
+                     != DECL_ASSEMBLER_NAME (method))
+                   continue;
+               }
+             else if (!decls_match (fn, method))
+               continue;
+
+             /* There has already been a declaration of this method
+                or member template.  */
+             cp_error_at ("`%D' has already been declared in `%T'", 
+                          method, type);
+
+             /* We don't call duplicate_decls here to merge the
+                declarations because that will confuse things if the
+                methods have inline definitions In particular, we
+                will crash while processing the definitions.  */
+             return;
+           }
+       }
+
+      /* Actually insert the new method.  */
+      TREE_VEC_ELT (method_vec, slot) 
+       = build_overload (method, TREE_VEC_ELT (method_vec, slot));
+
       if (TYPE_BINFO_BASETYPES (type) && CLASSTYPE_BASELINK_VEC (type))
        {
          /* ??? May be better to know whether these can be extended?  */
@@ -5115,7 +5106,6 @@ resolve_address_of_overloaded_function (target_type,
       for (fns = overload; fns; fns = OVL_CHAIN (fns))
        {
          tree fn = OVL_FUNCTION (fns);
-         tree fn_arg_types;
          tree instantiation;
          tree instantiation_type;
          tree targs;
@@ -5134,7 +5124,7 @@ resolve_address_of_overloaded_function (target_type,
          targs = make_scratch_vec (DECL_NTPARMS (fn));
          if (fn_type_unification (fn, explicit_targs, targs,
                                   target_arg_types, NULL_TREE,
-                                  DEDUCE_EXACT, NULL_TREE) != 0)
+                                  DEDUCE_EXACT) != 0)
            /* Argument deduction failed.  */
            continue;
 
index d91149c..861f395 100644 (file)
@@ -887,11 +887,11 @@ struct lang_type
 #define TYPE_USES_VIRTUAL_BASECLASSES(NODE) (TREE_LANG_FLAG_3(NODE))
 
 /* Vector member functions defined in this class.  Each element is
-   either a FUNCTION_DECL, a TEMPLATE_DECL, or an OVERLOAD.  The first
+   either a FUNCTION_DECL, a TEMPLATE_DECL, or an OVERLOAD.  All
+   functions with the same name end up in the same slot.  The first
    two elements are for constructors, and destructors, respectively.
-   Any user-defined conversion operators follow these.  These are
-   followed by ordinary member functions.  There may be empty entries
-   at the end of the vector.  */
+   These are followed by ordinary member functions.  There may be
+   empty entries at the end of the vector.  */
 #define CLASSTYPE_METHOD_VEC(NODE) (TYPE_LANG_SPECIFIC(NODE)->methods)
 
 /* The first type conversion operator in the class (the others can be
@@ -3068,7 +3068,7 @@ extern int uses_template_parms                    PROTO((tree));
 extern tree instantiate_class_template         PROTO((tree));
 extern tree instantiate_template               PROTO((tree, tree));
 extern void overload_template_name             PROTO((tree));
-extern int fn_type_unification                  PROTO((tree, tree, tree, tree, tree, unification_kind_t, tree));
+extern int fn_type_unification                  PROTO((tree, tree, tree, tree, tree, unification_kind_t));
 struct tinst_level *tinst_for_decl             PROTO((void));
 extern void mark_decl_instantiated             PROTO((tree, int));
 extern int more_specialized                    PROTO((tree, tree, tree));
@@ -3126,6 +3126,7 @@ extern int get_base_distance                      PROTO((tree, tree, int, tree *));
 extern tree compute_access                     PROTO((tree, tree));
 extern tree lookup_field                       PROTO((tree, tree, int, int));
 extern tree lookup_nested_field                        PROTO((tree, int));
+extern int lookup_fnfields_1                    PROTO((tree, tree));
 extern tree lookup_fnfields                    PROTO((tree, tree, int));
 extern tree lookup_member                      PROTO((tree, tree, int, int));
 extern tree lookup_nested_tag                  PROTO((tree, tree));
index c5ffd2b..95bd6f9 100644 (file)
@@ -8599,8 +8599,11 @@ grokfndecl (ctype, type, declarator, orig_declarator, virtualp, flags, quals,
            cp_error ("definition of implicitly-declared `%D'", tmp);
          if (tmp)
            {
+             /* Attempt to merge the declarations.  This can fail, in
+                the case of some illegal specialization declarations.  */
              if (!duplicate_decls (decl, tmp))
-               my_friendly_abort (892);
+               cp_error ("no `%#D' member function declared in class `%T'",
+                         decl, ctype);
              return tmp;
            }
        }
index 2608343..70120de 100644 (file)
@@ -1309,8 +1309,21 @@ check_classfn (ctype, function)
   tree method_vec = CLASSTYPE_METHOD_VEC (complete_type (ctype));
   tree *methods = 0;
   tree *end = 0;
-  tree templates = NULL_TREE;
-
+  
+  if (DECL_USE_TEMPLATE (function)
+      && is_member_template (DECL_TI_TEMPLATE (function)))
+    /* Since this is a specialization of a member template,
+       we're not going to find the declaration in the class.
+       For example, in:
+       
+         struct S { template <typename T> void f(T); };
+         template <> void S::f(int);
+       
+       we're not going to find `S::f(int)', but there's no
+       reason we should, either.  We let our callers know we didn't
+       find the method, but we don't complain.  */
+    return NULL_TREE;
+      
   if (method_vec != 0)
     {
       methods = &TREE_VEC_ELT (method_vec, 0);
@@ -1375,36 +1388,13 @@ check_classfn (ctype, function)
                              || (DECL_TI_TEMPLATE (function) 
                                  == DECL_TI_TEMPLATE (fndecl))))
                        return fndecl;
-
-                     if (is_member_template (fndecl))
-                       /* This function might be an instantiation
-                          or specialization of fndecl.  */
-                       templates = 
-                         scratch_tree_cons (NULL_TREE, fndecl, templates);
                    }
                }
              break;            /* loser */
            }
-         else if (TREE_CODE (OVL_CURRENT (fndecl)) == TEMPLATE_DECL 
-                  && DECL_CONV_FN_P (OVL_CURRENT (fndecl))
-                  && DECL_CONV_FN_P (function))
-           /* The method in the class is a member template
-              conversion operator.  We are declaring another
-              conversion operator.  It is possible that even though
-              the names don't match, there is some specialization
-              occurring.  */
-           templates = 
-             scratch_tree_cons (NULL_TREE, fndecl, templates);
        }
     }
 
-  if (templates)
-    /* This function might be an instantiation or a specialization.
-       We should verify that this is possible.  For now, we simply
-       return NULL_TREE, which lets the caller know that this function
-       is new, but we don't print an error message.  */
-    return NULL_TREE;
-
   if (methods != end && *methods)
     {
       tree fndecl = *methods;
index 49d948c..905bdf6 100644 (file)
@@ -906,13 +906,19 @@ print_candidates (fns)
 
 /* Returns the template (one of the functions given by TEMPLATE_ID)
    which can be specialized to match the indicated DECL with the
-   explicit template args given in TEMPLATE_ID.  If
-   NEED_MEMBER_TEMPLATE is true the function is a specialization of a
-   member template.  The template args (those explicitly specified and
-   those deduced) are output in a newly created vector *TARGS_OUT.  If
-   it is impossible to determine the result, an error message is
-   issued, unless COMPLAIN is 0.  The DECL may be NULL_TREE if none is
-   available.  */
+   explicit template args given in TEMPLATE_ID.  The DECL may be
+   NULL_TREE if none is available.  In that case, the functions in
+   TEMPLATE_ID are non-members.
+
+   If NEED_MEMBER_TEMPLATE is non-zero the function is known to be a
+   specialization of a member template.
+
+   The template args (those explicitly specified and those deduced)
+   are output in a newly created vector *TARGS_OUT.
+
+   If it is impossible to determine the result, an error message is
+   issued, unless COMPLAIN is 0.  In any case, error_mark_node is
+   returned to indicate failure.  */
 
 tree
 determine_specialization (template_id, decl, targs_out, 
@@ -924,9 +930,12 @@ determine_specialization (template_id, decl, targs_out,
      int need_member_template;
      int complain;
 {
-  tree fns, targs_in;
-  tree templates = NULL_TREE;
   tree fn;
+  tree fns;
+  tree targs;
+  tree explicit_targs;
+  tree candidates = NULL_TREE;
+  tree templates = NULL_TREE;
 
   *targs_out = NULL_TREE;
 
@@ -934,7 +943,7 @@ determine_specialization (template_id, decl, targs_out,
     return error_mark_node;
 
   fns = TREE_OPERAND (template_id, 0);
-  targs_in = TREE_OPERAND (template_id, 1);
+  explicit_targs = TREE_OPERAND (template_id, 1);
 
   if (fns == error_mark_node)
     return error_mark_node;
@@ -948,25 +957,58 @@ determine_specialization (template_id, decl, targs_out,
       tree tmpl;
 
       fn = OVL_CURRENT (fns);
-      if (!need_member_template 
-         && TREE_CODE (fn) == FUNCTION_DECL 
-         && DECL_FUNCTION_MEMBER_P (fn)
-         && DECL_USE_TEMPLATE (fn)
-         && DECL_TI_TEMPLATE (fn))
-       /* We can get here when processing something like:
-            template <class T> class X { void f(); }
-            template <> void X<int>::f() {}
-          We're specializing a member function, but not a member
-          template.  */
-       tmpl = DECL_TI_TEMPLATE (fn);
-      else if (TREE_CODE (fn) != TEMPLATE_DECL
-              || (need_member_template && !is_member_template (fn)))
+
+      if (TREE_CODE (fn) == TEMPLATE_DECL)
+       /* DECL might be a specialization of FN.  */
+       tmpl = fn;
+      else if (need_member_template)
+       /* FN is an ordinary member function, and we need a
+          specialization of a member template.  */
+       continue;
+      else if (TREE_CODE (fn) != FUNCTION_DECL)
+       /* We can get IDENTIFIER_NODEs here in certain erroneous
+          cases.  */
+       continue;
+      else if (!DECL_FUNCTION_MEMBER_P (fn))
+       /* This is just an ordinary non-member function.  Nothing can
+          be a specialization of that.  */
+       continue;
+      else if (!decl)
+       /* When there's no DECL to match, we know we're looking for
+          non-members.  */
        continue;
       else
-       tmpl = fn;
+       {
+         tree decl_arg_types;
 
-      if (list_length (targs_in) > DECL_NTPARMS (tmpl))
-       continue;
+         /* This is an ordinary member function.  However, since
+            we're here, we can assume it's enclosing class is a
+            template class.  For example,
+            
+              template <typename T> struct S { void f(); };
+              template <> void S<int>::f() {}
+
+            Here, S<int>::f is a non-template, but S<int> is a
+            template class.  If FN has the same type as DECL, we
+            might be in business.  */
+         if (!same_type_p (TREE_TYPE (TREE_TYPE (decl)),
+                           TREE_TYPE (TREE_TYPE (fn))))
+           /* The return types differ.  */
+           continue;
+
+         /* Adjust the type of DECL in case FN is a static member.  */
+         decl_arg_types = TYPE_ARG_TYPES (TREE_TYPE (decl));
+         if (DECL_STATIC_FUNCTION_P (fn) 
+             && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
+           decl_arg_types = TREE_CHAIN (decl_arg_types);
+
+         if (compparms (TYPE_ARG_TYPES (TREE_TYPE (fn)), 
+                        decl_arg_types))
+           /* They match!  */
+           candidates = tree_cons (NULL_TREE, fn, candidates);
+
+         continue;
+       }
 
       if (decl == NULL_TREE)
        {
@@ -974,70 +1016,107 @@ determine_specialization (template_id, decl, targs_out,
             make sense and there aren't any undeducible parms.  It's OK if
             not all the parms are specified; they might be deduced
             later. */
-         tree targs = get_bindings_overload (tmpl, DECL_RESULT (tmpl),
-                                             targs_in);
-
-         if (targs) 
-           /* Unification was successful.  */
-           templates = scratch_tree_cons (targs, tmpl, templates);
+         targs = get_bindings_overload (tmpl, DECL_RESULT (tmpl),
+                                        explicit_targs);
+         if (uses_template_parms (targs))
+           /* We couldn't deduce all the arguments.  */
+           continue;
        }
       else
-       templates = scratch_tree_cons (NULL_TREE, tmpl, templates);
-    }
-  
-  if (decl != NULL_TREE)
-    {
-      tree tmpl = most_specialized (templates, decl, targs_in);
-      tree inner_args;
-      tree tmpl_args;
+       /* See whether this function might be a specialization of this
+          template.  */
+       targs = get_bindings (tmpl, decl, explicit_targs);
 
-      if (tmpl == error_mark_node) 
-       goto ambiguous;
-      else if (tmpl == NULL_TREE)
-       goto no_match;
+      if (!targs)
+       /* Wwe cannot deduce template arguments that when used to
+          specialize TMPL will produce DECL.  */
+       continue;
 
-      inner_args = get_bindings (tmpl, decl, targs_in);
-      tmpl_args = DECL_TI_ARGS (DECL_RESULT (tmpl));
-      if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (tmpl_args))
-       {
-         *targs_out = copy_node (tmpl_args);
-         SET_TMPL_ARGS_LEVEL (*targs_out, 
-                              TMPL_ARGS_DEPTH (*targs_out),
-                              inner_args);
-       }
-      else
-       *targs_out = inner_args;
-      
-      return tmpl;
+      /* Save this template, and the arguments deduced.  */
+      templates = scratch_tree_cons (targs, tmpl, templates);
     }
 
-  if (templates == NULL_TREE)
+  if (decl && templates && TREE_CHAIN (templates))
+    {
+      /* We have:
+        
+          [temp.expl.spec]
+
+          It is possible for a specialization with a given function
+          signature to be instantiated from more than one function
+          template.  In such cases, explicit specification of the
+          template arguments must be used to uniquely identify the
+          function template specialization being specialized.
+
+        Note that here, there's no suggestion that we're supposed to
+        determine which of the candidate templates is most
+        specialized.  However, we, also have:
+
+          [temp.func.order]
+
+          Partial ordering of overloaded function template
+          declarations is used in the following contexts to select
+          the function template to which a function template
+          specialization refers: 
+
+           -- when an explicit specialization refers to a function
+             template. 
+
+        So, we do use the partial ordering rules, at least for now.
+        This extension can only serve to make illegal programs legal,
+        so it's safe.  And, there is strong anecdotal evidence that
+        the committee intended the partial ordering rules to apply;
+        the EDG front-end has that behavior, and John Spicer claims
+        that the committee simply forgot to delete the wording in
+        [temp.expl.spec].  */
+     tree tmpl = most_specialized (templates, decl, explicit_targs);
+     if (tmpl && tmpl != error_mark_node)
+       {
+        targs = get_bindings (tmpl, decl, explicit_targs);
+        templates = scratch_tree_cons (targs, tmpl, NULL_TREE);
+       }
+    }
+
+  if (templates == NULL_TREE && candidates == NULL_TREE)
     {
-    no_match:
       if (complain)
-       {
-         cp_error_at ("template-id `%D' for `%+D' does not match any template declaration",
-                      template_id, decl);
-         return error_mark_node;
-       }
-      return NULL_TREE;
+       cp_error_at ("template-id `%D' for `%+D' does not match any template declaration",
+                    template_id, decl);
+      return error_mark_node;
     }
-  else if (TREE_CHAIN (templates) != NULL_TREE
-          || uses_template_parms (TREE_PURPOSE (templates)))
+  else if ((templates && TREE_CHAIN (templates))
+          || (candidates && TREE_CHAIN (candidates)))
     {
-    ambiguous:
       if (complain)
        {
          cp_error_at ("ambiguous template specialization `%D' for `%+D'",
                       template_id, decl);
-         print_candidates (templates);
-         return error_mark_node;
+         chainon (candidates, templates);
+         print_candidates (candidates);
        }
-      return NULL_TREE;
+      return error_mark_node;
     }
 
   /* We have one, and exactly one, match. */
-  *targs_out = TREE_PURPOSE (templates);
+  if (candidates)
+    {
+      /* It was a specialization of an ordinary member function in a
+        template class.  */
+      *targs_out = copy_node (DECL_TI_ARGS (TREE_VALUE (candidates)));
+      return DECL_TI_TEMPLATE (TREE_VALUE (candidates));
+    }
+
+  /* It was a specialization of a template.  */
+  targs = DECL_TI_ARGS (DECL_RESULT (TREE_VALUE (templates)));
+  if (TMPL_ARGS_HAVE_MULTIPLE_LEVELS (targs))
+    {
+      *targs_out = copy_node (targs);
+      SET_TMPL_ARGS_LEVEL (*targs_out, 
+                          TMPL_ARGS_DEPTH (*targs_out),
+                          TREE_PURPOSE (templates));
+    }
+  else
+    *targs_out = TREE_PURPOSE (templates);
   return TREE_VALUE (templates);
 }
       
@@ -1047,7 +1126,9 @@ determine_specialization (template_id, decl, targs_out,
    instantiation at this point.
 
    Returns DECL, or an equivalent declaration that should be used
-   instead. 
+   instead if all goes well.  Issues an error message if something is
+   amiss.  Returns error_mark_node if the error is not easily
+   recoverable.
    
    FLAGS is a bitmask consisting of the following flags: 
 
@@ -1101,10 +1182,9 @@ check_explicit_specialization (declarator, decl, template_count, flags)
          /* There were more template headers than qualifying template
             classes.  */
          if (template_header_count - template_count > 1)
-           /* There shouldn't be that many template parameter
-                  lists.  There can be at most one parameter list for
-                  every qualifying class, plus one for the function
-                  itself.  */
+           /* There shouldn't be that many template parameter lists.
+              There can be at most one parameter list for every
+              qualifying class, plus one for the function itself.  */
            cp_error ("too many template parameter lists in declaration of `%D'", decl);
 
          SET_DECL_TEMPLATE_SPECIALIZATION (decl);
@@ -1284,8 +1364,9 @@ check_explicit_specialization (declarator, decl, template_count, flags)
          /* Find the list of functions in ctype that have the same
             name as the declared function.  */
          tree name = TREE_OPERAND (declarator, 0);
-         tree fns;
-         
+         tree fns = NULL_TREE;
+         int idx;
+
          if (name == constructor_name (ctype) 
              || name == constructor_name_full (ctype))
            {
@@ -1303,21 +1384,52 @@ check_explicit_specialization (declarator, decl, template_count, flags)
 
                     Similar language is found in [temp.explicit].  */
                  cp_error ("specialization of implicitly-declared special member function");
-
-                 return decl;
+                 return error_mark_node;
                }
 
              name = is_constructor ? ctor_identifier : dtor_identifier;
            }
 
-         fns = lookup_fnfields (TYPE_BINFO (ctype), name, 1);
-         
+         if (!IDENTIFIER_TYPENAME_P (name))
+           {
+             idx = lookup_fnfields_1 (ctype, name);
+             if (idx >= 0)
+               fns = TREE_VEC_ELT (CLASSTYPE_METHOD_VEC (ctype), idx);
+           }
+         else
+           {
+             tree methods;
+
+             /* For a type-conversion operator, we cannot do a
+                name-based lookup.  We might be looking for `operator
+                int' which will be a specialization of `operator T'.
+                So, we find *all* the conversion operators, and then
+                select from them.  */
+             fns = NULL_TREE;
+
+             methods = CLASSTYPE_METHOD_VEC (ctype);
+             if (methods)
+               for (idx = 2; idx < TREE_VEC_LENGTH (methods); ++idx) 
+                 {
+                   tree ovl = TREE_VEC_ELT (methods, idx);
+
+                   if (!ovl || !DECL_CONV_FN_P (OVL_CURRENT (ovl)))
+                     /* There are no more conversion functions.  */
+                     break;
+
+                   /* Glue all these conversion functions together
+                      with those we already have.  */
+                   for (; ovl; ovl = OVL_NEXT (ovl))
+                     fns = ovl_cons (OVL_CURRENT (ovl), fns);
+                 }
+           }
+             
          if (fns == NULL_TREE) 
            {
              cp_error ("no member function `%s' declared in `%T'",
                        IDENTIFIER_POINTER (name),
                        ctype);
-             return decl;
+             return error_mark_node;
            }
          else
            TREE_OPERAND (declarator, 0) = fns;
@@ -1336,7 +1448,11 @@ check_explicit_specialization (declarator, decl, template_count, flags)
                                       member_specialization,
                                       1);
            
-      if (tmpl && tmpl != error_mark_node)
+      if (!tmpl || tmpl == error_mark_node)
+       /* We couldn't figure out what this declaration was
+          specializing.  */
+       return error_mark_node;
+      else
        {
          gen_tmpl = most_general_template (tmpl);
 
@@ -1390,8 +1506,6 @@ check_explicit_specialization (declarator, decl, template_count, flags)
          /* Register this specialization so that we can find it
             again.  */
          decl = register_specialization (decl, gen_tmpl, targs);
-
-         return decl;
        }
     }
   
@@ -7123,17 +7237,13 @@ overload_template_name (type)
      [temp.expl.spec], or when taking the address of a function
      template, as in [temp.deduct.funcaddr]. 
 
-   The EXTRA_FN_ARG, if any, is the type of an additional
-   parameter to be added to the beginning of FN's parameter list.  
-
    The other arguments are as for type_unification.  */
 
 int
 fn_type_unification (fn, explicit_targs, targs, args, return_type,
-                    strict, extra_fn_arg)
+                    strict)
      tree fn, explicit_targs, targs, args, return_type;
      unification_kind_t strict;
-     tree extra_fn_arg;
 {
   tree parms;
   tree fntype;
@@ -7174,11 +7284,6 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type,
       if (fntype == error_mark_node)
        return 1;
 
-      extra_fn_arg = tsubst (extra_fn_arg, converted_args,
-                            /*complain=*/0, NULL_TREE);
-      if (extra_fn_arg == error_mark_node)
-       return 1;
-
       /* Place the explicitly specified arguments in TARGS.  */
       for (i = 0; i < TREE_VEC_LENGTH (targs); i++)
        TREE_VEC_ELT (targs, i) = TREE_VEC_ELT (converted_args, i);
@@ -7195,9 +7300,6 @@ fn_type_unification (fn, explicit_targs, targs, args, return_type,
       args = scratch_tree_cons (NULL_TREE, return_type, args);
     }
 
-  if (extra_fn_arg != NULL_TREE)
-    parms = scratch_tree_cons (NULL_TREE, extra_fn_arg, parms);
-
   /* We allow incomplete unification without an error message here
      because the standard doesn't seem to explicitly prohibit it.  Our
      callers must be ready to deal with unification failures in any
@@ -8355,9 +8457,8 @@ get_bindings_real (fn, decl, explicit_args, check_rettype)
 {
   int ntparms = DECL_NTPARMS (fn);
   tree targs = make_scratch_vec (ntparms);
-  tree decl_arg_types;
-  tree extra_fn_arg = NULL_TREE;
   tree decl_type;
+  tree decl_arg_types;
   int i;
 
   /* Substitute the explicit template arguments into the type of DECL.
@@ -8389,32 +8490,17 @@ get_bindings_real (fn, decl, explicit_args, check_rettype)
        return NULL_TREE;
     }
 
+  /* If FN is a static member function, adjust the type of DECL
+     appropriately.  */
   decl_arg_types = TYPE_ARG_TYPES (decl_type);
-
   if (DECL_STATIC_FUNCTION_P (fn) 
       && DECL_NONSTATIC_MEMBER_FUNCTION_P (decl))
-    {
-      /* Sometimes we are trying to figure out what's being
-        specialized by a declaration that looks like a method, and it
-        turns out to be a static member function.  */
-      if (CLASSTYPE_TEMPLATE_INFO (DECL_REAL_CONTEXT (fn))
-         && !is_member_template (fn))
-       /* The natural thing to do here seems to be to remove the
-          spurious `this' parameter from the DECL, but that prevents
-          unification from making use of the class type.  So,
-          instead, we have fn_type_unification add to the parameters
-          for FN.  */
-       extra_fn_arg = build_pointer_type (DECL_REAL_CONTEXT (fn));
-      else
-       /* In this case, though, adding the extra_fn_arg can confuse
-          things, so we remove from decl_arg_types instead.  */
-       decl_arg_types = TREE_CHAIN (decl_arg_types);
-    }
+    decl_arg_types = TREE_CHAIN (decl_arg_types);
 
   i = fn_type_unification (fn, explicit_args, targs, 
-                          decl_arg_types, TREE_TYPE (decl_type),
-                          DEDUCE_EXACT,
-                          extra_fn_arg);
+                          decl_arg_types,
+                          TREE_TYPE (decl_type),
+                          DEDUCE_EXACT);
 
   if (i != 0)
     return NULL_TREE;
index 1edfdf8..33842c6 100644 (file)
@@ -81,7 +81,6 @@ static tree get_vbase_1 PROTO((tree, tree, unsigned int *));
 static tree convert_pointer_to_vbase PROTO((tree, tree));
 static tree lookup_field_1 PROTO((tree, tree));
 static tree convert_pointer_to_single_level PROTO((tree, tree));
-static int lookup_fnfields_1 PROTO((tree, tree));
 static int lookup_fnfields_here PROTO((tree, tree));
 static int is_subobject_of_p PROTO((tree, tree));
 static int hides PROTO((tree, tree));
@@ -1284,7 +1283,7 @@ lookup_nested_field (name, complain)
 /* TYPE is a class type. Return the index of the fields within
    the method vector with name NAME, or -1 is no such field exists.  */
 
-static int
+int
 lookup_fnfields_1 (type, name)
      tree type, name;
 {
index 58c19a4..83d13f1 100644 (file)
@@ -1185,15 +1185,12 @@ common_base_type (tt1, tt2)
 \f
 /* Subroutines of `comptypes'.  */
 
-/* Return 1 if two parameter type lists PARMS1 and PARMS2
-   are equivalent in the sense that functions with those parameter types
-   can have equivalent types.
-   If either list is empty, we win.
-   Otherwise, the two lists must be equivalent, element by element.
+/* Return 1 if two parameter type lists PARMS1 and PARMS2 are
+   equivalent in the sense that functions with those parameter types
+   can have equivalent types.  The two lists must be equivalent,
+   element by element.
 
-   C++: See comment above about TYPE1, TYPE2.
-
-   STRICT is no longer used.  */
+   C++: See comment above about TYPE1, TYPE2.  */
 
 int
 compparms (parms1, parms2)
@@ -4559,30 +4556,7 @@ build_unary_op (code, xarg, noconvert)
          return build1 (ADDR_EXPR, unknown_type_node, arg);
        }
 
-      if (TREE_CODE (arg) == TEMPLATE_ID_EXPR)
-       {
-         tree targs;
-         tree fn;
-         
-         /* We don't require a match here; it's possible that the
-            context (like a cast to a particular type) will resolve
-            the particular choice of template.  */
-         fn = determine_specialization (arg,
-                                        NULL_TREE,
-                                        &targs, 
-                                        0, 
-                                        0);
-
-         if (fn)
-           {
-             fn = instantiate_template (fn, targs);
-             mark_addressable (fn);
-             return build_unary_op (ADDR_EXPR, fn, 0);
-           }
-
-         return build1 (ADDR_EXPR, unknown_type_node, arg);
-       }
-      else if (type_unknown_p (arg))
+      if (type_unknown_p (arg))
        return build1 (ADDR_EXPR, unknown_type_node, arg);
 
       /* Handle complex lvalues (when permitted)
diff --git a/gcc/testsuite/g++.old-deja/g++.other/redecl2.C b/gcc/testsuite/g++.old-deja/g++.other/redecl2.C
new file mode 100644 (file)
index 0000000..7dcdeb4
--- /dev/null
@@ -0,0 +1,9 @@
+// Build don't link:
+
+struct S {
+  S(int);
+  S(int); // ERROR - already declared
+
+  ~S();
+  ~S(); // ERROR - already declared
+};
index 0daf54f..d218474 100644 (file)
@@ -5,5 +5,5 @@ void foo(T t) {}
 
 void bar()
 {
-  &foo<double>;
+  (void (*)(double)) &foo<double>;
 }
index 4d88c39..7388031 100644 (file)
@@ -5,5 +5,5 @@ void foo(T t) {}
 
 void bar()
 {
-  (void (*)(int)) &foo<double>;
+  (void (*)(int)) (void (*)(double)) &foo<double>;
 }
index eba8d79..7d16162 100644 (file)
@@ -8,5 +8,5 @@ int foo(int i) { return 0; }
 
 int main()
 {
-  &foo<int>;
+  (int (*)(int)) &foo<int>;
 }
index 4a5adb5..a8d8221 100644 (file)
@@ -8,5 +8,5 @@ void foo(int i) {}
 
 int main()
 {
-  &foo<int>;
+  (void (*)(int)) &foo<int>;
 }
index b842b89..0133f16 100644 (file)
@@ -8,5 +8,5 @@ int foo(int i) { return 0; }
 
 int main()
 {
-  return (*&foo<int>)(3);
+  return (*((int (*)(int)) &foo<int>))(3);
 }
index 5a69713..468dd79 100644 (file)
@@ -7,5 +7,5 @@ void foo(T, T*);
 void bar()
 {
   double d;
-  (*((void (*)(int, double*)) &foo<int>))(3, &d);
+  (*((void (*)(int, double*)) (void (*)(int, int*)) &foo<int>))(3, &d);
 }
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec29.C b/gcc/testsuite/g++.old-deja/g++.pt/spec29.C
new file mode 100644 (file)
index 0000000..9f27a8e
--- /dev/null
@@ -0,0 +1,31 @@
+char c;
+
+struct S {
+  template <typename T>
+  operator T*();
+
+  template <typename T>
+  operator T();
+};
+
+template <>
+S::operator int()
+{
+  return 2;
+}
+
+template <>
+S::operator char*()
+{
+  return &c;
+}
+
+int main()
+{
+  S s;
+  int i = s;
+  char* cp = s;
+
+  if (i != 2 || cp != &c)
+    return 1;
+}
diff --git a/gcc/testsuite/g++.old-deja/g++.pt/spec30.C b/gcc/testsuite/g++.old-deja/g++.pt/spec30.C
new file mode 100644 (file)
index 0000000..5d36e25
--- /dev/null
@@ -0,0 +1,41 @@
+#include <cstddef>
+
+template <class T>     
+struct S {
+  void *operator new (size_t);
+  void *operator new (size_t, int);
+  void operator delete (void*);
+};
+
+static void* s[2];
+
+template <>
+void* S<int>::operator new (size_t b) 
+{ 
+  s[0] = ::operator new(b);
+  return s[0];
+}
+
+template <>
+void* S<int>::operator new (size_t b, int)
+{
+  s[1] = ::operator new(b);
+  return s[1];
+}
+
+template <>
+void S<int>::operator delete (void*) 
+{
+}
+
+int main()
+{
+  S<int>* s1 = new S<int>;
+  S<int>* s2 = new(3) S<int>;
+
+  if (s1 != s[0] || s2 != s[1])
+    return 1;
+
+  delete s1;
+  delete s2;
+}