87th Cygnus<->FSF quick merge
authorJason Merrill <jason@yorick.cygnus.com>
Tue, 13 Aug 1996 15:39:22 +0000 (15:39 +0000)
committerMike Stump <mrs@gcc.gnu.org>
Tue, 13 Aug 1996 15:39:22 +0000 (15:39 +0000)
From-SVN: r12630

gcc/cp/ChangeLog
gcc/cp/call.c
gcc/cp/cp-tree.h
gcc/cp/decl.c
gcc/cp/decl2.c
gcc/cp/errfn.c
gcc/cp/parse.y
gcc/cp/pt.c
gcc/cp/tree.c
gcc/cp/typeck.c

index f65965add97c51ff3d420ff081c9e3a5479d3207..cf363840de5fc51f5755f87f12712dcfe230ccfc 100644 (file)
@@ -1,3 +1,49 @@
+Mon Aug 12 00:09:18 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * pt.c (end_template_decl): If we don't actually have parms, return.
+       * parse.y (template_header): Accept 'template <>'.
+
+       * errfn.c: Allow 5 args.
+
+Sun Aug 11 15:20:58 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * tree.c (make_temp_vec): New fn.
+       * pt.c (push_template_decl): Handle partial specs.
+       (instantiate_class_template): Ditto.
+       (more_specialized): Use get_bindings.
+       (more_specialized_class): New fn.
+       (get_class_bindings): New fn.
+       (most_specialized_class): New fn.
+       (do_function_instantiation): List candidates for ambiguous case.
+       * decl.c (duplicate_decls): Lose reference to DECL_TEMPLATE_MEMBERS.
+       (shadow_tag): Call push_template_decl for partial specializations.
+       * parse.y: Ditto.
+       * cp-tree.h (DECL_TEMPLATE_SPECIALIZATIONS): Replaces
+       DECL_TEMPLATE_MEMBERS.
+       * call.c (print_z_candidates): Reduce duplication.
+
+Fri Aug  9 14:36:08 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * decl2.c (lang_decode_option): Allow -fansi-overloading.
+
+Thu Aug  8 17:04:18 1996  Jason Merrill  <jason@yorick.cygnus.com>
+
+       * pt.c (get_bindings): New fn.
+       (most_specialized): Ditto.
+       (do_function_instantiation): Use them.
+       (add_maybe_template): New fn.
+       * cp-tree.h (DECL_MAYBE_TEMPLATE): New macro.
+       * call.c (build_new_op): Handle guiding decls.
+       (build_new_function_call): Ditto.
+       * decl2.c (finish_file): Ditto.
+
+       * decl2.c (mark_used): Do synthesis here.
+       * call.c (build_method_call): Not here.
+       (build_over_call): Or here.
+       * typeck.c (build_function_call_real): Or here.
+       * tree.c (bot_manip): Call mark_used on functions used in default
+       args.
+
 Thu Aug  8 17:48:16 1996  Michael Meissner  <meissner@tiktok.cygnus.com>
 
        * decl2.c (import_export_vtable): Delete code that disabled vtable
index b81f35f21b3ffc333989a75ec3929060c49cd997..8bc96d1ac66d8b60c37456baffb38c03029e648a 100644 (file)
@@ -2468,12 +2468,6 @@ build_method_call (instance, name, parms, basetype_path, flags)
   function = DECL_MAIN_VARIANT (function);
   mark_used (function);
 
-  /* Is it a synthesized method that needs to be synthesized?  */
-  if (DECL_ARTIFICIAL (function) && ! DECL_INITIAL (function)
-      /* Kludge: don't synthesize for default args.  */
-      && current_function_decl)
-    synthesize_method (function);
-
   if (pedantic && DECL_THIS_INLINE (function) && ! DECL_ARTIFICIAL (function)
       && ! DECL_INITIAL (function) && ! DECL_PENDING_INLINE_INFO (function)
       && ! (DECL_TEMPLATE_INFO (function)
@@ -4157,48 +4151,27 @@ static void
 print_z_candidates (candidates)
      struct z_candidate *candidates;
 {
-  if (! candidates)
-    return;
-
-  if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE)
-    {
-      if (candidates->fn == ansi_opname [COND_EXPR])
-       cp_error ("candidates are: %D(%T, %T, %T) <builtin>", candidates->fn,
-                 TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)),
-                 TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)),
-                 TREE_TYPE (TREE_VEC_ELT (candidates->convs, 2)));
-      else if (TREE_VEC_LENGTH (candidates->convs) == 2)
-       cp_error ("candidates are: %D(%T, %T) <builtin>", candidates->fn,
-                 TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)),
-                 TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)));
-      else
-       cp_error ("candidates are: %D(%T) <builtin>", candidates->fn,
-                 TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)));
-    }
-  else
-    cp_error_at ("candidates are: %D", candidates->fn);
-  candidates = candidates->next;
-
+  char *str = "candidates are:";
   for (; candidates; candidates = candidates->next)
     {
       if (TREE_CODE (candidates->fn) == IDENTIFIER_NODE)
        {
          if (candidates->fn == ansi_opname [COND_EXPR])
-           cp_error ("                %D(%T, %T, %T) <builtin>",
-                     candidates->fn,
+           cp_error ("%s %D(%T, %T, %T) <builtin>", str, candidates->fn,
                      TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)),
                      TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)),
                      TREE_TYPE (TREE_VEC_ELT (candidates->convs, 2)));
          else if (TREE_VEC_LENGTH (candidates->convs) == 2)
-           cp_error ("                %D(%T, %T) <builtin>", candidates->fn,
+           cp_error ("%s %D(%T, %T) <builtin>", str, candidates->fn,
                      TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)),
                      TREE_TYPE (TREE_VEC_ELT (candidates->convs, 1)));
          else
-           cp_error ("                %D(%T) <builtin>", candidates->fn,
+           cp_error ("%s %D(%T) <builtin>", str, candidates->fn,
                      TREE_TYPE (TREE_VEC_ELT (candidates->convs, 0)));
        }
       else
-       cp_error_at ("                %D", candidates->fn);
+       cp_error_at ("%s %+D", str, candidates->fn);
+      str = "               "; 
     }
 }
 
@@ -4334,6 +4307,7 @@ build_new_function_call (fn, args, obj)
   if (obj == NULL_TREE && TREE_CODE (fn) == TREE_LIST)
     {
       tree t;
+      tree templates = NULL_TREE;
 
       for (t = args; t; t = TREE_CHAIN (t))
        if (TREE_VALUE (t) == error_mark_node)
@@ -4342,8 +4316,11 @@ build_new_function_call (fn, args, obj)
       for (t = TREE_VALUE (fn); t; t = DECL_CHAIN (t))
        {
          if (TREE_CODE (t) == TEMPLATE_DECL)
-           candidates = add_template_candidate
-             (candidates, t, args, LOOKUP_NORMAL);
+           {
+             templates = decl_tree_cons (NULL_TREE, t, templates);
+             candidates = add_template_candidate
+               (candidates, t, args, LOOKUP_NORMAL);
+           }
          else
            candidates = add_function_candidate
              (candidates, t, args, LOOKUP_NORMAL);
@@ -4369,6 +4346,12 @@ build_new_function_call (fn, args, obj)
          return error_mark_node;
        }
 
+      /* Pedantically, it is ill-formed to define a function that could
+        also be a template instantiation, but we won't implement that
+        until things settle down.  */
+      if (templates && ! cand->template && ! DECL_INITIAL (cand->fn))
+       add_maybe_template (cand->fn, templates);
+
       return build_over_call (cand->fn, cand->convs, args, LOOKUP_NORMAL);
     }
 
@@ -4482,6 +4465,7 @@ build_new_op (code, flags, arg1, arg2, arg3)
   struct z_candidate *candidates = 0, *cand;
   tree fns, mem_arglist, arglist, fnname, *p;
   enum tree_code code2 = NOP_EXPR;
+  tree templates = NULL_TREE;
 
   if (arg1 == error_mark_node)
     return error_mark_node;
@@ -4602,7 +4586,11 @@ build_new_op (code, flags, arg1, arg2, arg3)
   for (; fns; fns = DECL_CHAIN (fns))
     {
       if (TREE_CODE (fns) == TEMPLATE_DECL)
-       candidates = add_template_candidate (candidates, fns, arglist, flags);
+       {
+         templates = decl_tree_cons (NULL_TREE, fns, templates);
+         candidates = add_template_candidate
+           (candidates, fns, arglist, flags);
+       }
       else
        candidates = add_function_candidate (candidates, fns, arglist, flags);
     }
@@ -4715,6 +4703,13 @@ build_new_op (code, flags, arg1, arg2, arg3)
       if (DECL_FUNCTION_MEMBER_P (cand->fn))
        enforce_access (cand->basetype_path, cand->fn);
 
+      /* Pedantically, it is ill-formed to define a function that could
+        also be a template instantiation, but we won't implement that
+        until things settle down.  */
+      if (templates && ! cand->template && ! DECL_INITIAL (cand->fn)
+         && TREE_CODE (TREE_TYPE (cand->fn)) != METHOD_TYPE)
+       add_maybe_template (cand->fn, templates);
+
       return build_over_call
        (cand->fn, cand->convs,
         TREE_CODE (TREE_TYPE (cand->fn)) == METHOD_TYPE
@@ -4999,12 +4994,6 @@ build_over_call (fn, convs, args, flags)
   converted_args = nreverse (converted_args);
 
   mark_used (fn);
-  /* Is it a synthesized method that needs to be synthesized?  */
-  if (DECL_ARTIFICIAL (fn) && ! DECL_INITIAL (fn)
-      && DECL_CLASS_CONTEXT (fn)
-      /* Kludge: don't synthesize for default args.  */
-      && current_function_decl)
-    synthesize_method (fn);
 
   if (pedantic && DECL_THIS_INLINE (fn) && ! DECL_ARTIFICIAL (fn)
       && ! DECL_INITIAL (fn) && ! DECL_PENDING_INLINE_INFO (fn)
index 19d98689091839a1521a02db5d13d5fedfed9fad..8b9c6ba662bfd9b21ab2eccfe4fce7a0f7828f4e 100644 (file)
@@ -1135,7 +1135,7 @@ struct lang_decl
 #if 0                          /* UNUSED */
 /* Nonzero in IDENTIFIER_NODE means that this name is overloaded, and
    should be looked up in a non-standard way.  */
-#define DECL_OVERLOADED(NODE) (DECL_LANG_FLAG_4 (NODE))
+#define DECL_OVERLOADED(NODE) (FOO)
 #endif
 
 /* Nonzero if this (non-TYPE)_DECL has its virtual attribute set.
@@ -1331,7 +1331,7 @@ extern int flag_new_for_scope;
 /* Accessor macros for C++ template decl nodes.  */
 #define DECL_TEMPLATE_PARMS(NODE)       DECL_ARGUMENTS(NODE)
 /* For class templates.  */
-#define DECL_TEMPLATE_MEMBERS(NODE)     DECL_SIZE(NODE)
+#define DECL_TEMPLATE_SPECIALIZATIONS(NODE)     DECL_SIZE(NODE)
 /* For function, method, class-data templates.  */
 #define DECL_TEMPLATE_RESULT(NODE)      DECL_RESULT(NODE)
 #define DECL_TEMPLATE_INSTANTIATIONS(NODE) DECL_VINDEX(NODE)
@@ -1380,6 +1380,8 @@ extern int flag_new_for_scope;
 #define SET_CLASSTYPE_EXPLICIT_INSTANTIATION(NODE) \
   (CLASSTYPE_USE_TEMPLATE(NODE) = 3)
 
+/* This function may be a guiding decl for a template.  */
+#define DECL_MAYBE_TEMPLATE(NODE) DECL_LANG_FLAG_4 (NODE)
 /* We know what we're doing with this decl now.  */
 #define DECL_INTERFACE_KNOWN(NODE) DECL_LANG_FLAG_5 (NODE)
 
@@ -2308,6 +2310,7 @@ extern tree instantiate_decl                      PROTO((tree));
 extern tree classtype_mangled_name             PROTO((tree));
 extern tree lookup_nested_type_by_name         PROTO((tree, tree));
 extern tree do_poplevel                                PROTO((void));
+extern tree *get_bindings                      PROTO((tree, tree));
 
 /* in search.c */
 extern void push_memoized_context              PROTO((tree, int));
index 98d3f14f8eca38f4c9e9dd4d920338b4a0f70877..3486634591da5b282709cc063f2d0a59ec082bcb 100644 (file)
@@ -2869,7 +2869,6 @@ duplicate_decls (newdecl, olddecl)
 
   if (TREE_CODE (newdecl) == TEMPLATE_DECL)
     {
-      DECL_TEMPLATE_MEMBERS (newdecl) = DECL_TEMPLATE_MEMBERS (olddecl);
       DECL_TEMPLATE_INSTANTIATIONS (newdecl)
        = DECL_TEMPLATE_INSTANTIATIONS (olddecl);
       if (DECL_CHAIN (newdecl) == NULL_TREE)
@@ -5646,7 +5645,11 @@ shadow_tag (declspecs)
            {
              if (CLASSTYPE_IMPLICIT_INSTANTIATION (value)
                  && TYPE_SIZE (value) == NULL_TREE)
-               SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (value);
+               {
+                 SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (value);
+                 if (current_template_parms)
+                   push_template_decl (TYPE_MAIN_DECL (value));
+               }
              else if (CLASSTYPE_TEMPLATE_INSTANTIATION (value))
                cp_error ("specialization after instantiation of `%T'", value);
            }
index b4de01b9e3de6f0d11263002f9d099c4260b20ab..b5a0529fc007b5f336dd90e16dee473e5d8abf4d 100644 (file)
@@ -498,11 +498,6 @@ lang_decode_option (p)
          flag_alt_external_templates = 0;
          found = 1;
        }
-      else if (!strcmp (p, "ansi-overloading"))
-       {
-         warning ("-fansi-overloading is no longer meaningful");
-         found = 1;
-       }
       else if (!strcmp (p, "repo"))
        {
          flag_use_repository = 1;
@@ -2876,6 +2871,7 @@ build_cleanup (decl)
 
 extern int parse_time, varconst_time;
 extern tree pending_templates;
+extern tree maybe_templates;
 
 #define TIMEVAR(VAR, BODY)    \
 do { int otime = get_run_time (); BODY; VAR += get_run_time () - otime; } while (0)
@@ -2952,6 +2948,20 @@ finish_file ()
        instantiate_decl (decl);
     }
 
+  for (fnname = maybe_templates; fnname; fnname = TREE_CHAIN (fnname))
+    {
+      tree *args, fn, decl = TREE_VALUE (fnname);
+
+      if (DECL_INITIAL (decl))
+       continue;
+
+      fn = TREE_PURPOSE (fnname);
+      args = get_bindings (fn, decl);
+      fn = instantiate_template (fn, args);
+      free (args);
+      instantiate_decl (fn);
+    }
+
   /* Push into C language context, because that's all
      we'll need here.  */
   push_lang_context (lang_name_c);
@@ -3848,6 +3858,12 @@ mark_used (decl)
   if (current_template_parms)
     return;
   assemble_external (decl);
+  /* Is it a synthesized method that needs to be synthesized?  */
+  if (TREE_CODE (decl) == FUNCTION_DECL && DECL_CLASS_CONTEXT (decl)
+      && DECL_ARTIFICIAL (decl) && ! DECL_INITIAL (decl)
+      /* Kludge: don't synthesize for default args.  */
+      && current_function_decl)
+    synthesize_method (decl);
   if (DECL_LANG_SPECIFIC (decl) && DECL_TEMPLATE_INFO (decl))
     instantiate_decl (decl);
 }
index 4da07fa40dca022f2665ee4fb363481377417ffc..b5ab8f7b676123ab7599f21bf610374647c39b53 100644 (file)
@@ -44,11 +44,12 @@ extern int   cp_line_of PROTO((tree));
 
 #define STRDUP(f) (ap = (char *) alloca (strlen (f) +1), strcpy (ap, (f)), ap)
 
-#define NARGS 4
-#define arglist a1, a2, a3, a4
-#define arglist_dcl HOST_WIDE_INT a1, a2, a3, a4;
-#define ARGSINIT args[0] = a1; args[1] = a2; args[2] = a3; args[3] = a4;
-#define ARGSLIST args[0], args[1], args[2], args[3]
+#define NARGS 5
+#define arglist a1, a2, a3, a4, a5
+#define arglist_dcl HOST_WIDE_INT a1, a2, a3, a4, a5;
+#define ARGSINIT \
+  args[0] = a1; args[1] = a2; args[2] = a3; args[3] = a4; args[4] = a5;
+#define ARGSLIST args[0], args[1], args[2], args[3], args[4]
 
 static void
 cp_thing (errfn, atarg1, format, arglist)
index eedfd11bca003293739099ec832c645387a6fda0..06c4d82a0ab0e41966237d0bfc22125b0211c73b 100644 (file)
@@ -418,6 +418,8 @@ template_header:
                { begin_template_parm_list (); }
          template_parm_list '>'
                { $$ = end_template_parm_list ($4); }
+       | TEMPLATE '<' '>'
+               { $$ = NULL_TREE; }
        ;
 
 template_parm_list:
@@ -2321,7 +2323,11 @@ named_class_head:
                        {
                          if (CLASSTYPE_IMPLICIT_INSTANTIATION ($$)
                              && TYPE_SIZE ($$) == NULL_TREE)
-                           SET_CLASSTYPE_TEMPLATE_SPECIALIZATION ($$);
+                           {
+                             SET_CLASSTYPE_TEMPLATE_SPECIALIZATION ($$);
+                             if (current_template_parms)
+                               push_template_decl (TYPE_MAIN_DECL ($$));
+                           }
                          else if (CLASSTYPE_TEMPLATE_INSTANTIATION ($$))
                            cp_error ("specialization after instantiation of `%T'", $$);
                        }
@@ -2525,7 +2531,11 @@ left_curly: '{'
                    {
                      if (CLASSTYPE_IMPLICIT_INSTANTIATION (t)
                          && TYPE_SIZE (t) == NULL_TREE)
-                       SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t);
+                       {
+                         SET_CLASSTYPE_TEMPLATE_SPECIALIZATION (t);
+                         if (current_template_parms)
+                           push_template_decl (TYPE_MAIN_DECL (t));
+                       }
                      else if (CLASSTYPE_TEMPLATE_INSTANTIATION (t))
                        cp_error ("specialization after instantiation of `%T'", t);
                    }
index 40a4582332e49962c56507c02e2d5dbbde029623..bb037060577a9c517e77d43fbdbc92d532ba1ab5 100644 (file)
@@ -53,6 +53,9 @@ HOST_WIDE_INT processing_template_decl;
 tree pending_templates;
 static tree *template_tail = &pending_templates;
 
+tree maybe_templates;
+static tree *maybe_template_tail = &maybe_templates;
+
 int minimal_parse_mode;
 
 #define obstack_chunk_alloc xmalloc
@@ -65,6 +68,9 @@ void pop_template_decls ();
 tree classtype_mangled_name ();
 static char * mangle_class_name_for_template ();
 tree tsubst_expr_values ();
+tree most_specialized_class PROTO((tree, tree));
+tree get_class_bindings PROTO((tree, tree, tree));
+tree make_temp_vec PROTO((int));
 
 /* We've got a template header coming up; push to a new level for storing
    the parms.  */
@@ -181,6 +187,9 @@ end_template_parm_list (parms)
 void
 end_template_decl ()
 {
+  if (! current_template_parms)
+    return;
+
   /* This matches the pushlevel in begin_template_parm_list.  */
   poplevel (0, 0, 0);
 
@@ -229,6 +238,30 @@ push_template_decl (decl)
   args = nreverse (args);
   args = TREE_VALUE (args);
 
+  /* Partial specialization.  */
+  if (TREE_CODE (decl) == TYPE_DECL
+      && CLASSTYPE_TEMPLATE_SPECIALIZATION (TREE_TYPE (decl)))
+    {
+      tree type = TREE_TYPE (decl);
+      tree maintmpl = CLASSTYPE_TI_TEMPLATE (type);
+      tree mainargs = CLASSTYPE_TI_ARGS (type);
+      tree spec = DECL_TEMPLATE_SPECIALIZATIONS (maintmpl);
+
+      for (; spec; spec = TREE_CHAIN (spec))
+       {
+         /* purpose: args to main template
+            value: spec template */
+         if (comp_template_args (TREE_PURPOSE (spec), mainargs))
+           return;
+       }
+
+      DECL_TEMPLATE_SPECIALIZATIONS (maintmpl) = perm_tree_cons
+       (mainargs, TREE_VALUE (current_template_parms),
+        DECL_TEMPLATE_SPECIALIZATIONS (maintmpl));
+      TREE_TYPE (DECL_TEMPLATE_SPECIALIZATIONS (maintmpl)) = type;
+      return;
+    }
+
   if (! ctx || TYPE_BEING_DEFINED (ctx))
     {
       tmpl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (decl), NULL_TREE);
@@ -237,6 +270,9 @@ push_template_decl (decl)
     }
   else
     {
+      if (CLASSTYPE_TEMPLATE_INSTANTIATION (ctx))
+       cp_error ("must specialize `%#T' before defining member `%#D'",
+                 ctx, decl);
       if (TREE_CODE (decl) == TYPE_DECL)
        tmpl = CLASSTYPE_TI_TEMPLATE (TREE_TYPE (decl));
       else if (! DECL_TEMPLATE_INFO (decl))
@@ -1004,11 +1040,36 @@ instantiate_class_template (type)
   template = TI_TEMPLATE (template_info);
   my_friendly_assert (TREE_CODE (template) == TEMPLATE_DECL, 279);
   args = TI_ARGS (template_info);
-  pattern = TREE_TYPE (template);
+
+  t = most_specialized_class
+    (DECL_TEMPLATE_SPECIALIZATIONS (template), args);
+
+  if (t == error_mark_node)
+    {
+      char *str = "candidates are:";
+      cp_error ("ambiguous class template instantiation for `%#T'", type);
+      for (t = DECL_TEMPLATE_SPECIALIZATIONS (template); t; t = TREE_CHAIN (t))
+       {
+         if (get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args))
+           {
+             cp_error_at ("%s %+#T", str, TREE_TYPE (t));
+             str = "               ";
+           }
+       }
+      TYPE_BEING_DEFINED (type) = 1;
+      return;
+    }
+  else if (t)
+    pattern = TREE_TYPE (t);
+  else
+    pattern = TREE_TYPE (template);
 
   if (TYPE_SIZE (pattern) == NULL_TREE)
     return type;
 
+  if (t)
+    args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), args);
+
   TYPE_BEING_DEFINED (type) = 1;
 
   if (! push_tinst_level (type))
@@ -2785,34 +2846,207 @@ int
 more_specialized (pat1, pat2)
      tree pat1, pat2;
 {
-  int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (pat1));
-  tree *targs = (tree *) malloc (sizeof (tree) * ntparms);
-  int i, dummy = 0, winner = 0;
+  tree *targs;
+  int winner = 0;
 
-  i = type_unification (DECL_TEMPLATE_PARMS (pat1), targs,
-                       TYPE_ARG_TYPES (TREE_TYPE (pat1)),
-                       TYPE_ARG_TYPES (TREE_TYPE (pat2)),
-                       &dummy, 0, 1);
+  targs = get_bindings (pat1, pat2);
+  if (targs)
+    {
+      free (targs);
+      --winner;
+    }
 
-  free (targs);
-  if (i == 0)
-    --winner;
+  targs = get_bindings (pat2, pat1);
+  if (targs)
+    {
+      free (targs);
+      ++winner;
+    }
 
-  ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (pat2));
-  targs = (tree *) malloc (sizeof (tree) * ntparms);
+  return winner;
+}
 
-  i = type_unification (DECL_TEMPLATE_PARMS (pat2), targs,
-                       TYPE_ARG_TYPES (TREE_TYPE (pat2)),
-                       TYPE_ARG_TYPES (TREE_TYPE (pat1)),
-                       &dummy, 0, 1);
+/* Given two class template specialization list nodes PAT1 and PAT2, return:
 
-  free (targs);
-  if (i == 0)
+   1 if PAT1 is more specialized than PAT2 as described in [temp.class.order].
+   -1 if PAT2 is more specialized than PAT1.
+   0 if neither is more specialized.  */
+   
+int
+more_specialized_class (pat1, pat2)
+     tree pat1, pat2;
+{
+  tree targs;
+  int winner = 0;
+
+  targs = get_class_bindings
+    (TREE_VALUE (pat1), TREE_PURPOSE (pat1), TREE_PURPOSE (pat2));
+  if (targs)
+    --winner;
+
+  targs = get_class_bindings
+    (TREE_VALUE (pat2), TREE_PURPOSE (pat2), TREE_PURPOSE (pat1));
+  if (targs)
     ++winner;
 
   return winner;
 }
-  
+
+/* Return the template arguments that will produce the function signature
+   DECL from the function template FN.  */
+
+tree *
+get_bindings (fn, decl)
+     tree fn, decl;
+{
+  int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (fn));
+  tree *targs = (tree *) malloc (sizeof (tree) * ntparms);
+  int i, dummy = 0;
+  i = type_unification (DECL_TEMPLATE_PARMS (fn), targs,
+                       TYPE_ARG_TYPES (TREE_TYPE (fn)),
+                       TYPE_ARG_TYPES (TREE_TYPE (decl)),
+                       &dummy, 0, 1);
+  if (i == 0)
+    return targs;
+  free (targs);
+  return 0;
+}
+
+tree
+get_class_bindings (tparms, parms, args)
+     tree tparms, parms, args;
+{
+  int i, dummy, ntparms = TREE_VEC_LENGTH (tparms);
+  tree vec = make_temp_vec (ntparms);
+
+  for (i = 0; i < TREE_VEC_LENGTH (parms); ++i)
+    {
+      switch (unify (tparms, &TREE_VEC_ELT (vec, 0), ntparms,
+                    TREE_VEC_ELT (parms, i), TREE_VEC_ELT (args, i),
+                    &dummy, 1))
+       {
+       case 0:
+         break;
+       case 1:
+         return NULL_TREE;
+       }
+    }
+
+  for (i =  0; i < ntparms; ++i)
+    if (! TREE_VEC_ELT (vec, i))
+      return NULL_TREE;
+
+  return vec;
+}
+
+/* Return the most specialized of the list of templates in FNS that can
+   produce an instantiation matching DECL.  */
+
+tree
+most_specialized (fns, decl)
+     tree fns, decl;
+{
+  tree fn, champ, *args, *p;
+  int fate;
+
+  for (p = &fns; *p; )
+    {
+      args = get_bindings (TREE_VALUE (*p), decl);
+      if (args)
+       {
+         free (args);
+         p = &TREE_CHAIN (*p);
+       }
+      else
+       *p = TREE_CHAIN (*p);
+    }
+
+  if (! fns)
+    return NULL_TREE;
+
+  fn = fns;
+  champ = TREE_VALUE (fn);
+  fn = TREE_CHAIN (fn);
+  for (; fn; fn = TREE_CHAIN (fn))
+    {
+      fate = more_specialized (champ, TREE_VALUE (fn));
+      if (fate == 1)
+       ;
+      else
+       {
+         if (fate == 0)
+           {
+             fn = TREE_CHAIN (fn);
+             if (! fn)
+               return error_mark_node;
+           }
+         champ = TREE_VALUE (fn);
+       }
+    }
+
+  for (fn = fns; fn && TREE_VALUE (fn) != champ; fn = TREE_CHAIN (fn))
+    {
+      fate = more_specialized (champ, TREE_VALUE (fn));
+      if (fate != 1)
+       return error_mark_node;
+    }
+
+  return champ;
+}
+
+/* Return the most specialized of the class template specializations in
+   SPECS that can produce an instantiation matching ARGS.  */
+
+tree
+most_specialized_class (specs, mainargs)
+     tree specs, mainargs;
+{
+  tree list = NULL_TREE, t, args, champ;
+  int fate;
+
+  for (t = specs; t; t = TREE_CHAIN (t))
+    {
+      args = get_class_bindings (TREE_VALUE (t), TREE_PURPOSE (t), mainargs);
+      if (args)
+       {
+         list = decl_tree_cons (TREE_PURPOSE (t), TREE_VALUE (t), list);
+         TREE_TYPE (list) = TREE_TYPE (t);
+       }
+    }
+
+  if (! list)
+    return NULL_TREE;
+
+  t = list;
+  champ = t;
+  t = TREE_CHAIN (t);
+  for (; t; t = TREE_CHAIN (t))
+    {
+      fate = more_specialized_class (champ, t);
+      if (fate == 1)
+       ;
+      else
+       {
+         if (fate == 0)
+           {
+             t = TREE_CHAIN (t);
+             if (! t)
+               return error_mark_node;
+           }
+         champ = t;
+       }
+    }
+
+  for (t = list; t && t != champ; t = TREE_CHAIN (t))
+    {
+      fate = more_specialized (champ, t);
+      if (fate != 1)
+       return error_mark_node;
+    }
+
+  return champ;
+}
+
 /* called from the parser.  */
 
 void
@@ -2844,6 +3078,7 @@ do_function_instantiation (declspecs, declarator, storage)
     }
   else if (name = DECL_NAME (decl), fn = IDENTIFIER_GLOBAL_VALUE (name), fn)
     {
+      tree templates = NULL_TREE;
       for (fn = get_first_fn (fn); fn; fn = DECL_CHAIN (fn))
        if (decls_match (fn, decl)
            && DECL_DEFER_OUTPUT (fn))
@@ -2852,31 +3087,30 @@ do_function_instantiation (declspecs, declarator, storage)
            break;
          }
        else if (TREE_CODE (fn) == TEMPLATE_DECL)
-         {
-           int ntparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (fn));
-           tree *targs = (tree *) malloc (sizeof (tree) * ntparms);
-           int i, dummy = 0;
-           i = type_unification (DECL_TEMPLATE_PARMS (fn), targs,
-                                 TYPE_ARG_TYPES (TREE_TYPE (fn)),
-                                 TYPE_ARG_TYPES (TREE_TYPE (decl)),
-                                 &dummy, 0, 1);
-           if (i == 0)
-             {
-               if (result)
-                 {
-                   int win = more_specialized (DECL_TI_TEMPLATE (result), fn);
-
-                   if (win == 0)
-                     cp_error ("ambiguous template instantiation for `%D' requested", decl);
-                   else if (win == -1)
-                     result = instantiate_template (fn, targs);
-                   /* else keep current winner */
-                 }
-               else
-                 result = instantiate_template (fn, targs);
-             }
-           free (targs);
-         }
+         templates = decl_tree_cons (NULL_TREE, fn, templates);
+
+      if (! result)
+       {
+         tree *args;
+         result = most_specialized (templates, decl);
+         if (result == error_mark_node)
+           {
+             char *str = "candidates are:";
+             cp_error ("ambiguous template instantiation for `%D' requested", decl);
+             for (fn = templates; fn; fn = TREE_CHAIN (fn))
+               {
+                 cp_error_at ("%s %+#D", str, TREE_VALUE (fn));
+                 str = "               ";
+               }
+             return;
+           }
+         else if (result)
+           {
+             args = get_bindings (result, decl);
+             result = instantiate_template (result, args);
+             free (args);
+           }
+       }
     }
   if (! result)
     {
@@ -3195,3 +3429,31 @@ add_tree (t)
 {
   last_tree = TREE_CHAIN (last_tree) = t;
 }
+
+/* D is an undefined function declaration in the presence of templates with
+   the same name, listed in FNS.  If one of them can produce D as an
+   instantiation, remember this so we can instantiate it at EOF if D has
+   not been defined by that time.  */
+
+void
+add_maybe_template (d, fns)
+     tree d, fns;
+{
+  tree t;
+
+  if (DECL_MAYBE_TEMPLATE (d))
+    return;
+
+  t = most_specialized (fns, d);
+  if (! t)
+    return;
+  if (t == error_mark_node)
+    {
+      cp_error ("ambiguous template instantiation for `%D'", d);
+      return;
+    }
+
+  *maybe_template_tail = perm_tree_cons (t, d, NULL_TREE);
+  maybe_template_tail = &TREE_CHAIN (*maybe_template_tail);
+  DECL_MAYBE_TEMPLATE (d) = 1;
+}
index 6a4263fbe40e3e45c2534b99933b8d1743ec9b6e..4551177ab3c230350cde454a8d04b0a9d784c5f7 100644 (file)
@@ -1772,8 +1772,21 @@ bot_manip (t)
   if (TREE_CODE (t) != TREE_LIST && ! TREE_SIDE_EFFECTS (t))
     return t;
   else if (TREE_CODE (t) == TARGET_EXPR)
-    return build_cplus_new (TREE_TYPE (t),
-                           break_out_target_exprs (TREE_OPERAND (t, 1)));
+    {
+      if (TREE_CODE (TREE_OPERAND (t, 1)) == NEW_EXPR)
+       {
+         mark_used (TREE_OPERAND (TREE_OPERAND (TREE_OPERAND (t, 1), 0), 0));
+         return build_cplus_new
+           (TREE_TYPE (t), break_out_target_exprs (TREE_OPERAND (t, 1)));
+       }
+      t = copy_node (t);
+      TREE_OPERAND (t, 0) = build (VAR_DECL, TREE_TYPE (t));
+      layout_decl (TREE_OPERAND (t, 0), 0);
+      return t;
+    }
+  else if (TREE_CODE (t) == CALL_EXPR)
+    mark_used (TREE_OPERAND (TREE_OPERAND (t, 0), 0));
+
   return NULL_TREE;
 }
   
@@ -2078,3 +2091,17 @@ cp_tree_equal (t1, t2)
 
   return -1;
 }
+
+/* Similar to make_tree_vec, but build on a temporary obstack.  */
+
+tree
+make_temp_vec (len)
+     int len;
+{
+  register tree node;
+  push_obstacks_nochange ();
+  resume_temporary_allocation ();
+  node = make_tree_vec (len);
+  pop_obstacks ();
+  return node;
+}
index a43443bd7fe370f13ab17e12e2bc954aeb970e6a..f2f069bbc45aa7f4d3cf496df31911bdb6ef83d6 100644 (file)
@@ -2545,15 +2545,7 @@ build_function_call_real (function, params, require_complete, flags)
         needs to be separately compiled).  */
 
       if (DECL_INLINE (function))
-       {
-         /* Is it a synthesized method that needs to be synthesized?  */
-         if (DECL_ARTIFICIAL (function) && ! DECL_INITIAL (function)
-             /* Kludge: don't synthesize for default args.  */
-             && current_function_decl)
-           synthesize_method (function);
-
-         function = inline_conversion (function);
-       }
+       function = inline_conversion (function);
       else
        function = build_addr_func (function);
     }