home *** CD-ROM | disk | FTP | other *** search
/ Education Sampler 1992 [NeXTSTEP] / Education_1992_Sampler.iso / NeXT / GnuSource / cc-61.0.1 / cc / cplus-pt.c < prev    next >
C/C++ Source or Header  |  1991-06-03  |  20KB  |  735 lines

  1. /* Handle parameterized types (templates) for GNU C++.
  2.    Written by Ken Raeburn of Watchmaker Computing.
  3.    Copyright (C) 1991 Free Software Foundation, Inc.
  4.  
  5. This file is part of GNU CC.
  6.  
  7. GNU CC is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2, or (at your option)
  10. any later version.
  11.  
  12. GNU CC is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GNU CC; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. #include <stdio.h>
  22. #include <assert.h>
  23. #include "obstack.h"
  24.  
  25. #include "config.h"
  26. #include "tree.h"
  27. #include "cplus-tree.h"
  28. #include "cplus-decl.h"
  29. #include "cplus-tab.h"
  30.  
  31. extern struct obstack permanent_obstack;
  32. extern tree grokdeclarator ();
  33.  
  34. /* Someday, if/when our source language includes templates (yeah, right!),
  35.    make a class of "template_info" objects, and a class template for
  36.    general symbol table manipulation.  */
  37. struct template_info {
  38.   struct template_info *next;
  39.   tree parm_vec;
  40.   char *text;
  41.   int length;
  42.   char *filename;
  43.   int lineno;
  44. };
  45. static struct template_info *templates;
  46. static struct template_info *current_template_info;
  47.  
  48. extern int lineno;
  49. extern char *input_filename;
  50.  
  51. #define obstack_chunk_alloc xmalloc
  52. #define obstack_chunk_free free
  53.  
  54. extern int xmalloc ();
  55. extern void free ();
  56.  
  57. void overload_template_name ();
  58.  
  59. /* We've got a template header coming up; set obstacks up to save the
  60.    nodes created permanently.  (There might be cases with nested templates
  61.    where we don't have to do this, but they aren't implemented, and it
  62.    probably wouldn't be worth the effort.)  */
  63. void
  64. begin_template_parm_list ()
  65. {
  66.   pushlevel (0);
  67.   push_obstacks (&permanent_obstack, &permanent_obstack);
  68. }
  69.  
  70. /* The end of a template parameter list has been reached.  Process the
  71.    tree list into a parameter vector, converting each parameter into a more
  72.    useful form.  Type parameters are saved as IDENTIFIER_NODEs, and others
  73.    as PARM_DECLs.
  74.  
  75.    For the moment, dump out a brief description and tell the user we aren't
  76.    doing anything useful with it.  */
  77.  
  78. tree
  79. end_template_parm_list (parms)
  80.      tree parms;
  81. {
  82.   int nparms = 0;
  83.   tree saved_parmlist;
  84.   tree parm;
  85.   for (parm = parms; parm; parm = TREE_CHAIN (parm))
  86.     nparms++;
  87.   saved_parmlist = make_tree_vec (nparms);
  88.  
  89.   for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++)
  90.     {
  91.       tree p = parm;
  92.       assert (TREE_CODE (p) == TREE_LIST);
  93.       p = TREE_PURPOSE (p);
  94.       if (TREE_CODE (p) == IDENTIFIER_NODE)
  95.     {
  96.       /* We've got "class X"; extract the identifier name.  */
  97.       /* TREE_VALUE (parm) is the base class, if any; ignore it for
  98.          now.  */
  99.     }
  100.       else
  101.     {
  102.       assert (TREE_CODE (p) == TREE_LIST);
  103.       p = TREE_VALUE (p);
  104.       /* PARM is a variable declaration.  Its TREE_VALUE contains the
  105.          identifier, with indirection and function calls and such wrapped
  106.          around it, and its TREE_PURPOSE contains the base type.  Call
  107.          grokdeclarator to rearrange it into a proper VAR_DECL.  */
  108.       p = grokdeclarator (TREE_VALUE (parm), TREE_PURPOSE (parm),
  109.                   NORMAL, 0, NULL_TREE);
  110.       /* A template parameter is not modifiable.  */
  111.       TREE_READONLY (p) = 1;
  112.     }
  113.       TREE_VEC_ELT (saved_parmlist,  nparms) = p;
  114.     }
  115.  
  116.   return saved_parmlist;
  117. }
  118.  
  119. /* Process information from new template parameter NEXT and append it to the
  120.    LIST being built.  The rules for use of a template parameter type name
  121.    by later parameters are not well-defined for us just yet.  However, the
  122.    only way to avoid having to parse expressions of unknown complexity (and
  123.    with tokens of unknown types) is to disallow it completely.  So for now,
  124.    that is what is assumed.  */
  125. tree
  126. process_template_parm (list, next)
  127.      tree list, next;
  128. {
  129.   tree parm;
  130.   int is_type;
  131.  
  132.   parm = next;
  133.   assert (TREE_CODE (parm) == TREE_LIST);
  134.   is_type = TREE_CODE (TREE_PURPOSE (parm)) == IDENTIFIER_NODE;
  135.   if (is_type)
  136.     {
  137.       /* is a type */
  138.     }
  139.   else
  140.     {
  141.       parm = TREE_PURPOSE (parm);
  142.       assert (TREE_CODE (parm) == TREE_LIST);
  143.       parm = TREE_VALUE (parm);
  144.       /* is a const-param */
  145.       parm = grokdeclarator (TREE_VALUE (next), TREE_PURPOSE (next),
  146.                  NORMAL, 0, NULL_TREE);
  147.       /* A template parameter is not modifiable.  */
  148.       TREE_READONLY (parm) = 1;
  149.     }
  150.   return chainon (list, next);
  151. }
  152.  
  153. /* end_template_decl is called after a template declaration is seen.  */
  154. /* D1 is template header; D2 is class_head_sans_basetype.  */
  155. void
  156. end_template_decl (d1, d2)
  157.      tree d1, d2;
  158. {
  159.   tree decl;
  160.   struct template_info *tmpl;
  161.  
  162.   tmpl = (struct template_info *) obstack_alloc (&permanent_obstack,
  163.                          sizeof (struct template_info));
  164.   tmpl->text = 0;
  165.   tmpl->length = 0;
  166. /*  tmpl->is_class = 1; /* XXX */
  167. /*  tmpl->name = 0; /* XXX */
  168.   templates = tmpl;
  169.   current_template_info = tmpl;
  170.   decl = make_node (TEMPLATE_DECL);
  171.   DECL_NAME (decl) = d2;
  172.   DECL_LANG_SPECIFIC (decl) = (struct lang_decl *) current_template_info;
  173.   DECL_ARGUMENTS (decl) = d1;
  174.   poplevel (0, 0, 0);
  175.   pushdecl (decl);
  176.   pop_obstacks ();
  177. }
  178.  
  179.  
  180. /* Convert all template arguments to their appropriate types, and return
  181.    a vector containing the resulting values.  If any error occurs, return
  182.    error_mark_node.  */
  183. static tree
  184. coerce_template_parms (parms, arglist)
  185.      tree parms, arglist;
  186. {
  187.   int nparms, i, lost = 0;
  188.   tree vec;
  189.  
  190.   nparms = list_length (arglist);
  191.   if (nparms != TREE_VEC_LENGTH (parms))
  192.     {
  193.       error ("incorrect number of parameters (%d, should be %d) in template expansion",
  194.          nparms, TREE_VEC_LENGTH (parms));
  195.       return error_mark_node;
  196.     }
  197.  
  198.   vec = make_tree_vec (nparms);
  199.   for (i = 0; i < nparms; i++)
  200.     {
  201.       tree arg = arglist;
  202.       tree parm = TREE_VEC_ELT (parms, i);
  203.       tree val;
  204.       int is_type, requires_type;
  205.  
  206.       if (arg == error_mark_node)
  207.     {
  208.     lose:
  209.       TREE_VEC_ELT (vec, i) = error_mark_node;
  210.       lost++;
  211.       continue;
  212.     }
  213.       arglist = TREE_CHAIN (arglist);
  214.       arg = TREE_VALUE (arg);
  215.       is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';
  216.       requires_type = TREE_CODE (parm) == IDENTIFIER_NODE;
  217.       if (is_type != requires_type)
  218.     {
  219.       error ("type/value mismatch in template parameter list");
  220.       goto lose;
  221.     }
  222.       if (is_type)
  223.     {
  224.       val = groktypename (arg);
  225.     }
  226.       else
  227.     {
  228.       val = digest_init (TREE_TYPE (parm), arg, (tree *) 0);
  229.     }
  230.       if (val == error_mark_node)
  231.     lost++;
  232.       TREE_VEC_ELT (vec, i) = val;
  233.     }
  234.   if (lost)
  235.     return error_mark_node;
  236.   return vec;
  237. }
  238.  
  239. /* Given class template name and parameter list, produce a user-friendly name
  240.    for the instantiation.  Note that this name isn't necessarily valid as
  241.    input to the compiler, because ">" characters may be adjacent.  */
  242.  
  243. static char *
  244. mangle_class_name_for_template (name, parms, arglist)
  245.      char *name;
  246.      tree parms, arglist;
  247. {
  248.   extern char *build_overload_name (/* parm, text, text_end */);
  249.   static char buf[BUFSIZ];
  250.   int i, nparms;
  251.   char *bufp = buf, ibuf[40];
  252.   int icat_tmp;
  253. #define buflen    sizeof(buf)
  254. #define check    if (bufp >= buf+buflen-1) goto too_long
  255. #define ccat(c) *bufp++=(c); check
  256. #define advance    bufp+=strlen(bufp); check
  257. #define cat(s)    strncpy(bufp, s, buf+buflen-bufp-1); advance
  258. #define icat(n)    sprintf(ibuf,"%d",(n)); cat(ibuf)
  259. #define xcat(n)    sprintf(ibuf,"%ux",n); cat(ibuf)
  260.  
  261.   strcpy (bufp, name);
  262.   advance;
  263.   ccat ('<');
  264.   nparms = TREE_VEC_LENGTH (parms);
  265.   assert (nparms == TREE_VEC_LENGTH (arglist));
  266.   for (i = 0; i < nparms; i++)
  267.     {
  268.       tree parm = TREE_VEC_ELT (parms, i), arg = TREE_VEC_ELT (arglist, i);
  269.  
  270.       if (i)
  271.     ccat (',');
  272.  
  273.       switch (TREE_CODE (parm))
  274.     {
  275.     case IDENTIFIER_NODE:
  276.       {
  277.         /* parm is a type */
  278.         extern char * type_as_string ();
  279.         char *typename;
  280.  
  281.         if (TYPE_NAME (arg)
  282.         && DECL_NAME (TYPE_NAME (arg))
  283.         && IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (arg))))
  284.           typename = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (arg)));
  285.         else
  286.           typename = type_as_string (arg);
  287.         cat (typename);
  288.         break;
  289.       }
  290.     case PARM_DECL:
  291.       {
  292.         /* Should do conversions as for "const" initializers.  */
  293.         tree type = TREE_TYPE (parm);
  294.         tree id = DECL_NAME (parm);
  295.  
  296.         if (TREE_CODE (arg) == TREE_LIST)
  297.           {
  298.         /* New list cell was built because old chain link was in
  299.            use.  */
  300.         assert (TREE_PURPOSE (arg) == NULL_TREE);
  301.         arg = TREE_VALUE (arg);
  302.           }
  303.  
  304.         switch (TREE_CODE (type))
  305.           {
  306.           case INTEGER_TYPE:
  307.         if (TREE_CODE (arg) == INTEGER_CST)
  308.           {
  309.             if (TREE_INT_CST_HIGH (arg) != (((int)TREE_INT_CST_LOW (arg)) >> (HOST_BITS_PER_INT - 1)))
  310.               {
  311.             tree val = arg;
  312.             if (TREE_INT_CST_HIGH (val) < 0)
  313.               {
  314.                 ccat ('-');
  315.                 val = build_int_2 (~TREE_INT_CST_LOW (val),
  316.                            -TREE_INT_CST_HIGH (val));
  317.               }
  318.             /* Would "%x%0*x" or "%x%*0x" get zero-padding on all
  319.                systems?  Shouldn't hard-code "8" here.  */
  320.             sprintf (ibuf, "%x%08x", TREE_INT_CST_HIGH (val),
  321.                  TREE_INT_CST_LOW (val));
  322.             cat (ibuf);
  323.               }
  324.             else
  325.               icat (TREE_INT_CST_LOW (arg));
  326.           }
  327.         else
  328.           {
  329.             error ("invalid integer constant for template parameter");
  330.             cat ("*error*");
  331.           }
  332.         break;
  333.           default:
  334.         abort ();
  335.           }
  336.       }
  337.       break;
  338.     default:
  339.       abort ();
  340.     }
  341.     }
  342.   ccat ('>');
  343.   return buf;
  344.  
  345.  too_long:
  346.   fatal ("out of (preallocated) string space creating template instantiation name");
  347. }
  348.  
  349. /* Given an IDENTIFIER_NODE (type TEMPLATE_DECL) and a chain of
  350.    parameters, find the desired type.
  351.  
  352.    D1 is the PTYPENAME terminal, and ARGLIST is the list of arguments.
  353.    Since ARGLIST is build on the decl_obstack, we must copy it here
  354.    to keep it from being reclaimed when the decl storage is reclaimed.  */
  355. tree
  356. lookup_template_class (d1, arglist)
  357.      tree d1, arglist;
  358. {
  359.   tree template, parmlist;
  360.   char *mangled_name;
  361.   tree id;
  362.  
  363.   assert (TREE_CODE (d1) == IDENTIFIER_NODE);
  364.   template = IDENTIFIER_GLOBAL_VALUE (d1); /* XXX */
  365.   assert (template != NULL_TREE);
  366.   assert (TREE_CODE (template) == TEMPLATE_DECL);
  367.   parmlist = DECL_ARGUMENTS (template);
  368.  
  369.   arglist = coerce_template_parms (parmlist, arglist);
  370.   if (arglist == error_mark_node)
  371.     return arglist;
  372.  
  373.   mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (d1),
  374.                          parmlist, arglist);
  375.   id = get_identifier (mangled_name);
  376.   if (!IDENTIFIER_TEMPLATE (id))
  377.     {
  378.       arglist = copy_to_permanent (arglist);
  379.       IDENTIFIER_TEMPLATE (id) = perm_tree_cons (template, arglist, NULL_TREE);
  380.     }
  381.   return id;
  382. }
  383.  
  384. void
  385. push_template_decls (template, class_level)
  386.      tree template;
  387.      int class_level;
  388. {
  389.   tree parmlist, arglist;
  390.   int i, nparms;
  391.  
  392.   assert (template != 0);
  393.   assert (TREE_CODE (template) == TREE_LIST);
  394.   arglist = TREE_VALUE (template);
  395.   if (arglist == error_mark_node)
  396.     return;
  397.   assert (TREE_CODE (arglist) == TREE_VEC);
  398.   template = TREE_PURPOSE (template);
  399.   assert (TREE_CODE (template) == TEMPLATE_DECL);
  400.   parmlist = DECL_ARGUMENTS (template);
  401.   assert (TREE_CODE (parmlist) == TREE_VEC);
  402.   nparms = TREE_VEC_LENGTH (parmlist);
  403.  
  404.   assert (DECL_NAME (template) != 0);
  405.  
  406.   for (i = 0; i < nparms; i++)
  407.     {
  408.       int requires_type, is_type;
  409.       tree parm = TREE_VEC_ELT (parmlist, i);
  410.       tree arg = TREE_VEC_ELT (arglist, i);
  411.       tree decl = 0;
  412.  
  413.       requires_type = TREE_CODE (parm) == IDENTIFIER_NODE;
  414.       is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';
  415.       if (is_type)
  416.     {
  417.       /* add typename to namespace */
  418.       if (!requires_type)
  419.         {
  420.           error ("template use error: type provided where value needed");
  421.           continue;
  422.         }
  423.       decl = arg;
  424.       assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 't');
  425.       decl = build_decl (TYPE_DECL, parm, decl);
  426.     }
  427.       else
  428.     {
  429.       /* add const decl to namespace */
  430.       tree val;
  431.       if (requires_type)
  432.         {
  433.           error ("template use error: value provided where type needed");
  434.           continue;
  435.         }
  436. #if 0
  437.       try to coerce value to proper type;
  438.       if (failed)
  439.         goto oops;
  440.       if (not constant)
  441.         goto oops;
  442.       pushdecl ();
  443. #else
  444.       val = digest_init (TREE_TYPE (parm), arg, (tree *) 0);
  445.       if (val != error_mark_node)
  446.         {
  447.           decl = build_decl (VAR_DECL, DECL_NAME (parm), TREE_TYPE (parm));
  448.           DECL_INITIAL (decl) = val;
  449.           TREE_READONLY (decl) = 1;
  450.         }
  451. #endif
  452.     }
  453.       if (decl != 0)
  454.     {
  455.       layout_decl (decl, 0);
  456.       if (class_level)
  457.         pushdecl_class_level (decl);
  458.       else
  459.         pushdecl (decl);
  460.     }
  461.     }
  462. }
  463.  
  464. void
  465. pop_template_decls (template, class_level)
  466.      tree template;
  467.      int class_level;
  468. {
  469.   tree parmlist, arglist;
  470.   int i, nparms;
  471.  
  472.   assert (template != 0);
  473.   assert (TREE_CODE (template) == TREE_LIST);
  474.   arglist = TREE_VALUE (template);
  475.   assert (TREE_CODE (arglist) == TREE_VEC);
  476.   template = TREE_PURPOSE (template);
  477.   assert (TREE_CODE (template) == TEMPLATE_DECL);
  478.   parmlist = DECL_ARGUMENTS (template);
  479.   assert (TREE_CODE (parmlist) == TREE_VEC);
  480.   nparms = TREE_VEC_LENGTH (parmlist);
  481.  
  482.   assert (DECL_NAME (template) != 0);
  483.  
  484.   for (i = 0; i < nparms; i++)
  485.     {
  486.       int requires_type, is_type;
  487.       tree parm = TREE_VEC_ELT (parmlist, i);
  488.       tree arg = TREE_VEC_ELT (arglist, i);
  489.  
  490.       requires_type = TREE_CODE (parm) == IDENTIFIER_NODE;
  491.       is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't';
  492.       if (is_type)
  493.     {
  494.       /* add typename to namespace */
  495.       tree decl;
  496.       if (!requires_type)
  497.         {
  498.           error ("template use error: type provided where value needed");
  499.           continue;
  500.         }
  501.       if (class_level)
  502.         {
  503.           tree t = IDENTIFIER_CLASS_VALUE (parm);
  504.           assert (t != 0);
  505.           assert (TREE_CODE_CLASS (TREE_CODE (t)) == 'd');
  506.           IDENTIFIER_CLASS_VALUE (parm) = NULL_TREE;
  507.         }
  508.       else
  509.         {
  510.           tree t = IDENTIFIER_LOCAL_VALUE (parm);
  511.           assert (t != 0);
  512.           assert (TREE_CODE_CLASS (TREE_CODE (t)) == 'd');
  513.           /* This isn't right, but this should get popped off.  */
  514.           IDENTIFIER_LOCAL_VALUE (parm) = NULL_TREE;
  515.         }
  516.       adjust_type_value (parm);
  517.     }
  518.     }
  519. }
  520.  
  521. /* Should be defined in cplus-tab.h.  */
  522. extern int yychar;
  523.  
  524. void
  525. instantiate_template (class)
  526.      tree class;
  527. {
  528.   struct template_info *template_info;
  529.   tree template, t1, t2;
  530.  
  531.   assert (TREE_CODE (class) == IDENTIFIER_NODE);
  532.   template = IDENTIFIER_TEMPLATE (class);
  533.  
  534.   if (TREE_TYPE (class))
  535.     return;
  536.  
  537. #if 0
  538.   fprintf (stderr, "  [class %s]  ", IDENTIFIER_POINTER (class));
  539. #endif
  540.   push_to_top_level ();
  541.   pushlevel (0);
  542.   push_template_decls (template, 0);
  543.   template = TREE_PURPOSE (template);
  544.   assert (TREE_CODE (template) == TEMPLATE_DECL);
  545.   set_current_level_tags_transparency (1);
  546.   template_info = (struct template_info *) DECL_LANG_SPECIFIC (template);
  547.   feed_input (template_info->text, template_info->length, (struct obstack *)0);
  548.   input_filename = template_info->filename;
  549.   lineno = template_info->lineno;
  550.   yychar = PRE_PARSED_CLASS_DECL;
  551.   overload_template_name (class);
  552.   yylval.ttype = build_tree_list (class_type_node, class);
  553.  oops:
  554.   return;
  555. }
  556.  
  557. void
  558. undo_template_name_overload (id)
  559.      tree id;
  560. {
  561.   tree template;
  562.  
  563.   template = IDENTIFIER_TEMPLATE (id);
  564.   if (!template)
  565.     return;
  566.   assert (TREE_CODE (template) == TREE_LIST);
  567.   template = TREE_PURPOSE (template);
  568.   assert (template != NULL_TREE);
  569.   template = DECL_NAME (template);
  570.   assert (template != NULL_TREE);
  571.   poplevel (0, 0, 0);
  572.   IDENTIFIER_LOCAL_VALUE (template) = NULL_TREE;
  573.   SET_IDENTIFIER_TYPE_VALUE (template, NULL_TREE);
  574. }
  575.  
  576. void
  577. overload_template_name (id)
  578.      tree id;
  579. {
  580.   tree template, t, decl;
  581.   assert (id != 0);
  582.   assert (TREE_CODE (id) == IDENTIFIER_NODE);
  583.   template = IDENTIFIER_TEMPLATE (id);
  584.   if (!template)
  585.     return;
  586.   template = TREE_PURPOSE (template);
  587.   assert (template != NULL_TREE);
  588.   template = DECL_NAME (template);
  589.   assert (template != NULL_TREE);
  590.   /* Push a level, so we don't overwrite the template decl.  */
  591.   pushlevel (1);
  592.   t = xref_tag (class_type_node, id, NULL_TREE);
  593.   assert (TREE_CODE (t) == RECORD_TYPE);
  594.   decl = build_decl (TYPE_DECL, template, t);
  595.   pushdecl (decl);
  596.   IDENTIFIER_LOCAL_VALUE (template) = decl;
  597.   SET_IDENTIFIER_TYPE_VALUE (template, t);
  598. }
  599.  
  600. /* T1 is PRE_PARSED_CLASS_DECL; T3 is result of XREF_TAG lookup.  */
  601. void
  602. end_template_instantiation (t1, t3)
  603.      tree t1, t3;
  604. {
  605.   extern struct pending_input *to_be_restored;
  606.   tree t, decl;
  607.  
  608. #if 0
  609.   fprintf (stderr, "  [END class %s]  ", IDENTIFIER_POINTER (TREE_VALUE (t1)));
  610. #endif
  611.  
  612.   /* Restore the old parser input state.  */
  613.   if (yychar == -2 /* YYEMPTY */)
  614.     yychar = yylex ();
  615.   if (yychar != END_OF_SAVED_INPUT)
  616.     error ("parse error at end of class template");
  617.   else
  618.     {
  619.       restore_pending_input (to_be_restored);
  620.       to_be_restored = 0;
  621.     }
  622.  
  623.   /* Our declarations didn't get stored in the global slot, since
  624.      there was a (supposedly tags-transparent) scope in between.  */
  625.   t = IDENTIFIER_TYPE_VALUE (TREE_VALUE (t1));
  626.   assert (t != NULL_TREE && TREE_CODE_CLASS (TREE_CODE (t)) == 't');
  627.   decl = IDENTIFIER_GLOBAL_VALUE (TREE_VALUE (t1));
  628.   assert (decl != 0);
  629.   assert (TREE_CODE (decl) == TYPE_DECL);
  630.  
  631.   undo_template_name_overload (TREE_VALUE (t1));
  632.   pop_template_decls (IDENTIFIER_TEMPLATE (TREE_VALUE (t1)), 0);
  633.   /* PRE_PARSED_CLASS_DECL pushes a level */
  634.   poplevel (0, 0, 0);
  635.   pop_from_top_level ();
  636.  
  637.   /* This will fix up the type-value field.  */
  638.   pushdecl_top_level (decl);
  639. }
  640.  
  641. extern struct obstack permanent_obstack;
  642.  
  643.  
  644. reinit_parse_for_template (yychar, d1, d2)
  645.      int yychar;
  646.      tree d1, d2;
  647. {
  648.   current_template_info->filename = input_filename;
  649.   current_template_info->lineno = lineno;
  650.   reinit_parse_for_block (yychar, &permanent_obstack, 1);
  651.   current_template_info->text = obstack_base (&permanent_obstack);
  652.   current_template_info->length = obstack_object_size (&permanent_obstack);
  653.   obstack_finish (&permanent_obstack);
  654. }
  655.  
  656. #if 0
  657. /* Type unification.
  658.  
  659.    We have a function template signature with one or more references to
  660.    template parameters, and a parameter list we wish to fit to this
  661.    template.  If possible, produce a list of parameters for the template
  662.    which will cause it to fit the supplied parameter list.
  663.  
  664.    Return zero for success, 2 for an incomplete match that doesn't resolve
  665.    all the types, and 1 for complete failure.  An error message will be
  666.    printed only for an incomplete match.
  667.  
  668.    TPARMS[NTPARMS] is an array of template parameter types;
  669.    TARGS[NTPARMS] is the array of template parameter values.  PARMS is
  670.    the function template's signature (using TEMPLATE_PARM_IDX nodes),
  671.    and ARGS is the argument list we're trying to match against it.  */
  672.  
  673. static int unify1 ();
  674.  
  675. int
  676. type_unification (tparms, targs, ntparms, parms, args)
  677.      tree *tparms, *targs, parms, args;
  678. {
  679.   tree parm, arg;
  680.   int i;
  681.  
  682.   parm = parms.first;
  683.   arg = args.first;
  684.   while (parm && arg)
  685.     {
  686.       switch (unify (tparms, targs, ntparms, parm, arg)) {
  687.       case 0:
  688.     break;
  689.       case 1:
  690.     return 2;
  691.       }
  692.       next parm;
  693.       next arg;
  694.     }
  695.   if (parm || arg)
  696.     return 1;
  697.   for (i = 0; i < ntparms; i++)
  698.     if (!targs[i])
  699.       {
  700.     error ("incomplete type unification");
  701.     return 2;
  702.       }
  703.   return 0;
  704. }
  705.  
  706. static int
  707. unify1 (tparms, targs, ntparms, parm, arg)
  708.      tree *tparms, *targs, parm, arg;
  709. {
  710.   if (parm == arg)
  711.     return 0;
  712.  
  713.   switch (TREE_CODE (parm)) {
  714.   case TEMPLATE_PARM_IDX:
  715.     int idx = TREE_INT_CST_LOW (parm);
  716.     if (targs[idx] == arg)
  717.       return 0;
  718.     else if (targs[idx])
  719.       return 1;
  720.     else if (typeof arg != tparms[idx])
  721.       return 1;
  722.  
  723.     targs[idx] = arg;
  724.     return 0;
  725.  
  726.   default:
  727.     /* Do I do strict matching or promotions?  */
  728.     abort ();
  729.   }
  730.  
  731.   /* No simple match; recurse.  */
  732.   abort ();
  733. }
  734. #endif
  735.