|
|
1.1 ! root 1: /* Handle parameterized types (templates) for GNU C++. ! 2: Written by Ken Raeburn of Watchmaker Computing. ! 3: Copyright (C) 1992 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: /* Known bugs or deficiencies include: ! 22: * templates for class static data don't work (methods only) ! 23: * duplicated method templates can crash the compiler ! 24: * interface/impl data is taken from file defining the template ! 25: * all methods must be provided in header files; can't use a source ! 26: file that contains only the method templates and "just win" ! 27: * method templates must be seen before the expansion of the ! 28: class template is done ! 29: */ ! 30: ! 31: #include "config.h" ! 32: #include <stdio.h> ! 33: #include <assert.h> ! 34: #include "obstack.h" ! 35: ! 36: #include "tree.h" ! 37: #include "cp-tree.h" ! 38: #include "cp-decl.h" ! 39: #include "cp-parse.h" ! 40: ! 41: extern struct obstack permanent_obstack; ! 42: extern tree grokdeclarator (); ! 43: ! 44: extern int lineno; ! 45: extern char *input_filename; ! 46: struct pending_inline *pending_template_expansions; ! 47: ! 48: int processing_template_decl; ! 49: int processing_template_defn; ! 50: ! 51: #define obstack_chunk_alloc xmalloc ! 52: #define obstack_chunk_free free ! 53: ! 54: extern int xmalloc (); ! 55: extern void free (); ! 56: ! 57: static int unify (); ! 58: ! 59: void overload_template_name (), pop_template_decls (); ! 60: ! 61: /* We've got a template header coming up; set obstacks up to save the ! 62: nodes created permanently. (There might be cases with nested templates ! 63: where we don't have to do this, but they aren't implemented, and it ! 64: probably wouldn't be worth the effort.) */ ! 65: void ! 66: begin_template_parm_list () ! 67: { ! 68: pushlevel (0); ! 69: push_obstacks (&permanent_obstack, &permanent_obstack); ! 70: } ! 71: ! 72: /* Process information from new template parameter NEXT and append it to the ! 73: LIST being built. The rules for use of a template parameter type name ! 74: by later parameters are not well-defined for us just yet. However, the ! 75: only way to avoid having to parse expressions of unknown complexity (and ! 76: with tokens of unknown types) is to disallow it completely. So for now, ! 77: that is what is assumed. */ ! 78: tree ! 79: process_template_parm (list, next) ! 80: tree list, next; ! 81: { ! 82: tree parm; ! 83: int is_type; ! 84: parm = next; ! 85: assert (TREE_CODE (parm) == TREE_LIST); ! 86: is_type = TREE_CODE (TREE_PURPOSE (parm)) == IDENTIFIER_NODE; ! 87: if (!is_type) ! 88: { ! 89: parm = TREE_PURPOSE (parm); ! 90: assert (TREE_CODE (parm) == TREE_LIST); ! 91: parm = TREE_VALUE (parm); ! 92: /* is a const-param */ ! 93: parm = grokdeclarator (TREE_VALUE (next), TREE_PURPOSE (next), ! 94: NORMAL, 0, NULL_TREE); ! 95: /* A template parameter is not modifiable. */ ! 96: TREE_READONLY (parm) = 1; ! 97: if (TREE_CODE (TREE_TYPE (parm)) == RECORD_TYPE ! 98: || TREE_CODE (TREE_TYPE (parm)) == UNION_TYPE) ! 99: { ! 100: sorry ("aggregate template parameter types"); ! 101: TREE_TYPE (parm) = void_type_node; ! 102: } ! 103: } ! 104: return chainon (list, parm); ! 105: } ! 106: ! 107: /* The end of a template parameter list has been reached. Process the ! 108: tree list into a parameter vector, converting each parameter into a more ! 109: useful form. Type parameters are saved as IDENTIFIER_NODEs, and others ! 110: as PARM_DECLs. */ ! 111: ! 112: tree ! 113: end_template_parm_list (parms) ! 114: tree parms; ! 115: { ! 116: int nparms = 0; ! 117: tree saved_parmlist; ! 118: tree parm; ! 119: for (parm = parms; parm; parm = TREE_CHAIN (parm)) ! 120: nparms++; ! 121: saved_parmlist = make_tree_vec (nparms); ! 122: ! 123: pushlevel (0); ! 124: ! 125: for (parm = parms, nparms = 0; parm; parm = TREE_CHAIN (parm), nparms++) ! 126: { ! 127: tree p = parm, decl; ! 128: if (TREE_CODE (p) == TREE_LIST) ! 129: { ! 130: tree t; ! 131: p = TREE_PURPOSE (p); ! 132: assert (TREE_CODE (p) == IDENTIFIER_NODE); ! 133: t = make_node (TEMPLATE_TYPE_PARM); ! 134: TEMPLATE_TYPE_SET_INFO (t, saved_parmlist, nparms); ! 135: decl = build_lang_decl (TYPE_DECL, p, t); ! 136: TYPE_NAME (t) = decl; ! 137: } ! 138: else ! 139: { ! 140: tree tinfo = make_node (TEMPLATE_CONST_PARM); ! 141: assert (TREE_PERMANENT (tinfo)); ! 142: if (!TREE_PERMANENT (p)) ! 143: { ! 144: tree old_p = p; ! 145: TREE_PERMANENT (old_p) = 1; ! 146: p = copy_node (p); ! 147: TREE_PERMANENT (old_p) = 0; ! 148: } ! 149: TEMPLATE_CONST_SET_INFO (tinfo, saved_parmlist, nparms); ! 150: TREE_TYPE (tinfo) = TREE_TYPE (p); ! 151: decl = build_decl (CONST_DECL, DECL_NAME (p), TREE_TYPE (p)); ! 152: DECL_INITIAL (decl) = tinfo; ! 153: } ! 154: TREE_VEC_ELT (saved_parmlist, nparms) = p; ! 155: pushdecl (decl); ! 156: } ! 157: set_current_level_tags_transparency (1); ! 158: processing_template_decl++; ! 159: return saved_parmlist; ! 160: } ! 161: ! 162: /* end_template_decl is called after a template declaration is seen. ! 163: D1 is template header; D2 is class_head_sans_basetype or a ! 164: TEMPLATE_DECL with its DECL_RESULT field set. */ ! 165: void ! 166: end_template_decl (d1, d2, is_class) ! 167: tree d1, d2, is_class; ! 168: { ! 169: tree decl; ! 170: struct template_info *tmpl; ! 171: ! 172: tmpl = (struct template_info *) obstack_alloc (&permanent_obstack, ! 173: sizeof (struct template_info)); ! 174: tmpl->text = 0; ! 175: tmpl->length = 0; ! 176: tmpl->aggr = is_class; ! 177: ! 178: /* cloned from reinit_parse_for_template */ ! 179: tmpl->filename = input_filename; ! 180: tmpl->lineno = lineno; ! 181: tmpl->parm_vec = d1; /* [eichin:19911015.2306EST] */ ! 182: ! 183: #ifdef DEBUG_CP_BINDING_LEVELS ! 184: indent_to (stderr, debug_bindings_indentation); ! 185: fprintf (stderr, "end_template_decl"); ! 186: debug_bindings_indentation += 4; ! 187: #endif ! 188: ! 189: if (d2 == NULL_TREE || d2 == error_mark_node) ! 190: { ! 191: decl = 0; ! 192: goto lose; ! 193: } ! 194: ! 195: if (is_class) ! 196: { ! 197: decl = build_lang_decl (TEMPLATE_DECL, d2, NULL_TREE); ! 198: } ! 199: else ! 200: { ! 201: if (TREE_CODE (d2) == TEMPLATE_DECL) ! 202: decl = d2; ! 203: else ! 204: { ! 205: /* Class destructor templates and operator templates are ! 206: slipping past as non-template nodes. Process them here, since ! 207: I haven't figured out where to catch them earlier. I could ! 208: go do that, but it's a choice between getting that done and ! 209: staying only N months behind schedule. Sorry.... */ ! 210: enum tree_code code; ! 211: assert (TREE_CODE (d2) == CALL_EXPR); ! 212: code = TREE_CODE (TREE_OPERAND (d2, 0)); ! 213: assert (code == BIT_NOT_EXPR ! 214: || code == OP_IDENTIFIER ! 215: || code == SCOPE_REF); ! 216: d2 = grokdeclarator (d2, NULL_TREE, MEMFUNCDEF, 0, NULL_TREE); ! 217: decl = build_lang_decl (TEMPLATE_DECL, DECL_NAME (d2), ! 218: TREE_TYPE (d2)); ! 219: DECL_TEMPLATE_RESULT (decl) = d2; ! 220: DECL_CONTEXT (decl) = DECL_CONTEXT (d2); ! 221: DECL_CLASS_CONTEXT (decl) = DECL_CLASS_CONTEXT (d2); ! 222: DECL_NAME (decl) = DECL_NAME (d2); ! 223: TREE_TYPE (decl) = TREE_TYPE (d2); ! 224: TREE_PUBLIC (decl) = TREE_PUBLIC (d2) = 0; ! 225: TREE_EXTERNAL (decl) = (TREE_EXTERNAL (d2) ! 226: && !(DECL_CLASS_CONTEXT (d2) ! 227: && !DECL_EXTERNAL (d2))); ! 228: } ! 229: ! 230: /* All routines creating TEMPLATE_DECL nodes should now be using ! 231: build_lang_decl, which will have set this up already. */ ! 232: assert (DECL_LANG_SPECIFIC (decl) != 0); ! 233: ! 234: /* @@ Somewhere, permanent allocation isn't being used. */ ! 235: if (! DECL_TEMPLATE_IS_CLASS (decl) ! 236: && TREE_CODE (DECL_TEMPLATE_RESULT (decl)) == FUNCTION_DECL) ! 237: { ! 238: tree result = DECL_TEMPLATE_RESULT (decl); ! 239: /* Will do nothing if allocation was already permanent. */ ! 240: DECL_ARGUMENTS (result) = copy_to_permanent (DECL_ARGUMENTS (result)); ! 241: } ! 242: ! 243: /* If this is for a method, there's an extra binding level here. */ ! 244: if (! DECL_TEMPLATE_IS_CLASS (decl) ! 245: && DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE) ! 246: { ! 247: /* @@ Find out where this should be getting set! */ ! 248: tree r = DECL_TEMPLATE_RESULT (decl); ! 249: if (DECL_CLASS_CONTEXT (r) == NULL_TREE) ! 250: DECL_CLASS_CONTEXT (r) = DECL_CONTEXT (r); ! 251: } ! 252: } ! 253: DECL_TEMPLATE_INFO (decl) = tmpl; ! 254: DECL_TEMPLATE_PARMS (decl) = d1; ! 255: lose: ! 256: if (decl) ! 257: { ! 258: /* If context of decl is non-null (i.e., method template), add it ! 259: to the appropriate class template, and pop the binding levels. */ ! 260: if (! DECL_TEMPLATE_IS_CLASS (decl) ! 261: && DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)) != NULL_TREE) ! 262: { ! 263: tree ctx = DECL_CONTEXT (DECL_TEMPLATE_RESULT (decl)); ! 264: tree tmpl; ! 265: assert (TREE_CODE (ctx) == UNINSTANTIATED_P_TYPE); ! 266: tmpl = UPT_TEMPLATE (ctx); ! 267: DECL_TEMPLATE_MEMBERS (tmpl) = ! 268: perm_tree_cons (DECL_NAME (decl), decl, ! 269: DECL_TEMPLATE_MEMBERS (tmpl)); ! 270: poplevel (0, 0, 0); ! 271: poplevel (0, 0, 0); ! 272: } ! 273: /* Otherwise, go back to top level first, and push the template decl ! 274: again there. */ ! 275: else ! 276: { ! 277: poplevel (0, 0, 0); ! 278: poplevel (0, 0, 0); ! 279: if (TREE_TYPE (decl) ! 280: && IDENTIFIER_GLOBAL_VALUE (DECL_NAME (decl)) != NULL_TREE) ! 281: push_overloaded_decl (decl, 0); ! 282: else ! 283: pushdecl (decl); ! 284: } ! 285: } ! 286: #if 0 /* It happens sometimes, with syntactic or semantic errors. ! 287: ! 288: One specific case: ! 289: template <class A, int X, int Y> class Foo { ... }; ! 290: template <class A, int X, int y> Foo<X,Y>::method (Foo& x) { ... } ! 291: Note the missing "A" in the class containing "method". */ ! 292: assert (global_bindings_p ()); ! 293: #else ! 294: while (! global_bindings_p ()) ! 295: poplevel (0, 0, 0); ! 296: #endif ! 297: pop_obstacks (); ! 298: processing_template_decl--; ! 299: (void) get_pending_sizes (); ! 300: #ifdef DEBUG_CP_BINDING_LEVELS ! 301: debug_bindings_indentation -= 4; ! 302: #endif ! 303: } ! 304: ! 305: ! 306: /* Convert all template arguments to their appropriate types, and return ! 307: a vector containing the resulting values. If any error occurs, return ! 308: error_mark_node. */ ! 309: static tree ! 310: coerce_template_parms (parms, arglist) ! 311: tree parms, arglist; ! 312: { ! 313: int nparms, i, lost = 0; ! 314: tree vec; ! 315: ! 316: if (TREE_CODE (arglist) == TREE_VEC) ! 317: nparms = TREE_VEC_LENGTH (arglist); ! 318: else ! 319: nparms = list_length (arglist); ! 320: if (nparms != TREE_VEC_LENGTH (parms)) ! 321: { ! 322: error ("incorrect number of parameters (%d, should be %d) in template expansion", ! 323: nparms, TREE_VEC_LENGTH (parms)); ! 324: return error_mark_node; ! 325: } ! 326: ! 327: if (TREE_CODE (arglist) == TREE_VEC) ! 328: vec = copy_node (arglist); ! 329: else ! 330: { ! 331: vec = make_tree_vec (nparms); ! 332: for (i = 0; i < nparms; i++) ! 333: { ! 334: tree arg = arglist; ! 335: arglist = TREE_CHAIN (arglist); ! 336: if (arg == error_mark_node) ! 337: lost++; ! 338: else ! 339: arg = TREE_VALUE (arg); ! 340: TREE_VEC_ELT (vec, i) = arg; ! 341: } ! 342: } ! 343: for (i = 0; i < nparms; i++) ! 344: { ! 345: tree arg = TREE_VEC_ELT (vec, i); ! 346: tree parm = TREE_VEC_ELT (parms, i); ! 347: tree val; ! 348: int is_type, requires_type; ! 349: ! 350: is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't'; ! 351: requires_type = TREE_CODE (parm) == IDENTIFIER_NODE; ! 352: if (is_type != requires_type) ! 353: { ! 354: error ("type/value mismatch in template parameter list"); ! 355: lost++; ! 356: TREE_VEC_ELT (vec, i) = error_mark_node; ! 357: continue; ! 358: } ! 359: if (is_type) ! 360: { ! 361: val = groktypename (arg); ! 362: } ! 363: else ! 364: { ! 365: val = digest_init (TREE_TYPE (parm), arg, (tree *) 0); ! 366: } ! 367: if (val == error_mark_node) ! 368: lost++; ! 369: TREE_VEC_ELT (vec, i) = val; ! 370: } ! 371: if (lost) ! 372: return error_mark_node; ! 373: return vec; ! 374: } ! 375: ! 376: /* Given class template name and parameter list, produce a user-friendly name ! 377: for the instantiation. Note that this name isn't necessarily valid as ! 378: input to the compiler, because ">" characters may be adjacent. */ ! 379: static char * ! 380: mangle_class_name_for_template (name, parms, arglist) ! 381: char *name; ! 382: tree parms, arglist; ! 383: { ! 384: static struct obstack scratch_obstack; ! 385: static char *scratch_firstobj; ! 386: int i, nparms; ! 387: char ibuf[100]; ! 388: ! 389: if (!scratch_firstobj) ! 390: { ! 391: gcc_obstack_init (&scratch_obstack); ! 392: scratch_firstobj = obstack_alloc (&scratch_obstack, 1); ! 393: } ! 394: else ! 395: obstack_free (&scratch_obstack, scratch_firstobj); ! 396: ! 397: #if 0 ! 398: #define buflen sizeof(buf) ! 399: #define check if (bufp >= buf+buflen-1) goto too_long ! 400: #define ccat(c) *bufp++=(c); check ! 401: #define advance bufp+=strlen(bufp); check ! 402: #define cat(s) strncpy(bufp, s, buf+buflen-bufp-1); advance ! 403: #else ! 404: #define check ! 405: #define ccat(c) obstack_1grow (&scratch_obstack, (c)); ! 406: #define advance ! 407: #define cat(s) obstack_grow (&scratch_obstack, (s), strlen (s)) ! 408: #endif ! 409: #define icat(n) sprintf(ibuf,"%d",(n)); cat(ibuf) ! 410: #define xcat(n) sprintf(ibuf,"%ux",n); cat(ibuf) ! 411: ! 412: cat (name); ! 413: ccat ('<'); ! 414: nparms = TREE_VEC_LENGTH (parms); ! 415: assert (nparms == TREE_VEC_LENGTH (arglist)); ! 416: for (i = 0; i < nparms; i++) ! 417: { ! 418: tree parm = TREE_VEC_ELT (parms, i), arg = TREE_VEC_ELT (arglist, i); ! 419: tree type, id; ! 420: ! 421: if (i) ! 422: ccat (','); ! 423: ! 424: if (TREE_CODE (parm) == IDENTIFIER_NODE) ! 425: { ! 426: /* parm is a type */ ! 427: extern char * type_as_string (); ! 428: char *typename; ! 429: ! 430: if (TYPE_NAME (arg) ! 431: && (TREE_CODE (arg) == RECORD_TYPE ! 432: || TREE_CODE (arg) == UNION_TYPE ! 433: || TREE_CODE (arg) == ENUMERAL_TYPE) ! 434: && DECL_NAME (TYPE_NAME (arg)) ! 435: && IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (arg)))) ! 436: typename = IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (arg))); ! 437: else ! 438: typename = type_as_string ((char *) 0, arg); ! 439: cat (typename); ! 440: continue; ! 441: } ! 442: else ! 443: assert (TREE_CODE (parm) == PARM_DECL); ! 444: ! 445: /* Should do conversions as for "const" initializers. */ ! 446: type = TREE_TYPE (parm); ! 447: id = DECL_NAME (parm); ! 448: ! 449: if (TREE_CODE (arg) == TREE_LIST) ! 450: { ! 451: /* New list cell was built because old chain link was in ! 452: use. */ ! 453: assert (TREE_PURPOSE (arg) == NULL_TREE); ! 454: arg = TREE_VALUE (arg); ! 455: } ! 456: ! 457: switch (TREE_CODE (type)) ! 458: { ! 459: case INTEGER_TYPE: ! 460: case ENUMERAL_TYPE: ! 461: if (TREE_CODE (arg) == INTEGER_CST) ! 462: { ! 463: if (TREE_INT_CST_HIGH (arg) != (((int)TREE_INT_CST_LOW (arg)) >> (HOST_BITS_PER_INT - 1))) ! 464: { ! 465: tree val = arg; ! 466: if (TREE_INT_CST_HIGH (val) < 0) ! 467: { ! 468: ccat ('-'); ! 469: val = build_int_2 (~TREE_INT_CST_LOW (val), ! 470: -TREE_INT_CST_HIGH (val)); ! 471: } ! 472: /* Would "%x%0*x" or "%x%*0x" get zero-padding on all ! 473: systems? */ ! 474: { ! 475: static char format[10]; /* "%x%09999x\0" */ ! 476: if (!format[0]) ! 477: sprintf (format, "%%x%%0%dx", HOST_BITS_PER_INT / 4); ! 478: sprintf (ibuf, format, TREE_INT_CST_HIGH (val), ! 479: TREE_INT_CST_LOW (val)); ! 480: cat (ibuf); ! 481: } ! 482: } ! 483: else ! 484: icat (TREE_INT_CST_LOW (arg)); ! 485: } ! 486: else ! 487: { ! 488: error ("invalid integer constant for template parameter"); ! 489: cat ("*error*"); ! 490: } ! 491: break; ! 492: #ifndef REAL_IS_NOT_DOUBLE ! 493: case REAL_TYPE: ! 494: sprintf (ibuf, "%e", TREE_REAL_CST (arg)); ! 495: cat (ibuf); ! 496: break; ! 497: #endif ! 498: case POINTER_TYPE: ! 499: if (TREE_CODE (arg) != ADDR_EXPR) ! 500: { ! 501: error ("invalid pointer constant for template parameter"); ! 502: cat ("*error*"); ! 503: break; ! 504: } ! 505: ccat ('&'); ! 506: arg = TREE_OPERAND (arg, 0); ! 507: if (TREE_CODE (arg) == FUNCTION_DECL) ! 508: cat (fndecl_as_string (0, arg, 0)); ! 509: else ! 510: { ! 511: assert (TREE_CODE_CLASS (TREE_CODE (arg)) == 'd'); ! 512: cat (IDENTIFIER_POINTER (DECL_NAME (arg))); ! 513: } ! 514: break; ! 515: default: ! 516: sorry ("encoding %s as template parm", ! 517: tree_code_name [(int) TREE_CODE (type)]); ! 518: abort (); ! 519: } ! 520: } ! 521: { ! 522: char *bufp = obstack_next_free (&scratch_obstack); ! 523: int offset = 0; ! 524: while (bufp[offset - 1] == ' ') ! 525: offset--; ! 526: obstack_blank_fast (&scratch_obstack, offset); ! 527: } ! 528: ccat ('>'); ! 529: ccat ('\0'); ! 530: return (char *) obstack_base (&scratch_obstack); ! 531: ! 532: too_long: ! 533: fatal ("out of (preallocated) string space creating template instantiation name"); ! 534: /* NOTREACHED */ ! 535: return NULL; ! 536: } ! 537: ! 538: /* Given an IDENTIFIER_NODE (type TEMPLATE_DECL) and a chain of ! 539: parameters, find the desired type. ! 540: ! 541: D1 is the PTYPENAME terminal, and ARGLIST is the list of arguments. ! 542: Since ARGLIST is build on the decl_obstack, we must copy it here ! 543: to keep it from being reclaimed when the decl storage is reclaimed. */ ! 544: tree ! 545: lookup_template_class (d1, arglist) ! 546: tree d1, arglist; ! 547: { ! 548: tree template, parmlist; ! 549: char *mangled_name; ! 550: tree id; ! 551: ! 552: assert (TREE_CODE (d1) == IDENTIFIER_NODE); ! 553: template = IDENTIFIER_GLOBAL_VALUE (d1); /* XXX */ ! 554: assert (TREE_CODE (template) == TEMPLATE_DECL); ! 555: parmlist = DECL_TEMPLATE_PARMS (template); ! 556: ! 557: arglist = coerce_template_parms (parmlist, arglist); ! 558: if (arglist == error_mark_node) ! 559: return error_mark_node; ! 560: if (uses_template_parms (arglist)) ! 561: { ! 562: tree t = make_lang_type (UNINSTANTIATED_P_TYPE); ! 563: tree d; ! 564: id = make_anon_name (); ! 565: d = build_lang_decl (TYPE_DECL, id, t); ! 566: TYPE_NAME (t) = d; ! 567: TYPE_VALUES (t) = build_tree_list (template, arglist); ! 568: pushdecl_top_level (d); ! 569: } ! 570: else ! 571: { ! 572: mangled_name = mangle_class_name_for_template (IDENTIFIER_POINTER (d1), ! 573: parmlist, arglist); ! 574: id = get_identifier (mangled_name); ! 575: } ! 576: if (!IDENTIFIER_TEMPLATE (id)) ! 577: { ! 578: arglist = copy_to_permanent (arglist); ! 579: IDENTIFIER_TEMPLATE (id) = perm_tree_cons (template, arglist, NULL_TREE); ! 580: } ! 581: return id; ! 582: } ! 583: ! 584: void ! 585: push_template_decls (parmlist, arglist, class_level) ! 586: tree parmlist, arglist; ! 587: int class_level; ! 588: { ! 589: int i, nparms; ! 590: ! 591: #ifdef DEBUG_CP_BINDING_LEVELS ! 592: indent_to (stderr, debug_bindings_indentation); ! 593: fprintf (stderr, "push_template_decls"); ! 594: debug_bindings_indentation += 4; ! 595: #endif ! 596: ! 597: /* Don't want to push values into global context. */ ! 598: if (!class_level) ! 599: pushlevel (0); ! 600: nparms = TREE_VEC_LENGTH (parmlist); ! 601: ! 602: for (i = 0; i < nparms; i++) ! 603: { ! 604: int requires_type, is_type; ! 605: tree parm = TREE_VEC_ELT (parmlist, i); ! 606: tree arg = TREE_VEC_ELT (arglist, i); ! 607: tree decl = 0; ! 608: ! 609: requires_type = TREE_CODE (parm) == IDENTIFIER_NODE; ! 610: is_type = TREE_CODE_CLASS (TREE_CODE (arg)) == 't'; ! 611: if (is_type) ! 612: { ! 613: /* add typename to namespace */ ! 614: if (!requires_type) ! 615: { ! 616: error ("template use error: type provided where value needed"); ! 617: continue; ! 618: } ! 619: decl = arg; ! 620: assert (TREE_CODE_CLASS (TREE_CODE (decl)) == 't'); ! 621: decl = build_lang_decl (TYPE_DECL, parm, decl); ! 622: } ! 623: else ! 624: { ! 625: /* add const decl to namespace */ ! 626: tree val; ! 627: if (requires_type) ! 628: { ! 629: error ("template use error: value provided where type needed"); ! 630: continue; ! 631: } ! 632: val = digest_init (TREE_TYPE (parm), arg, (tree *) 0); ! 633: if (val != error_mark_node) ! 634: { ! 635: decl = build_decl (VAR_DECL, DECL_NAME (parm), TREE_TYPE (parm)); ! 636: DECL_INITIAL (decl) = val; ! 637: TREE_READONLY (decl) = 1; ! 638: } ! 639: } ! 640: if (decl != 0) ! 641: { ! 642: layout_decl (decl, 0); ! 643: if (class_level) ! 644: pushdecl_class_level (decl); ! 645: else ! 646: pushdecl (decl); ! 647: } ! 648: } ! 649: if (!class_level) ! 650: set_current_level_tags_transparency (1); ! 651: #ifdef DEBUG_CP_BINDING_LEVELS ! 652: debug_bindings_indentation -= 4; ! 653: #endif ! 654: } ! 655: ! 656: void ! 657: pop_template_decls (parmlist, arglist, class_level) ! 658: tree parmlist, arglist; ! 659: int class_level; ! 660: { ! 661: #ifdef DEBUG_CP_BINDING_LEVELS ! 662: indent_to (stderr, debug_bindings_indentation); ! 663: fprintf (stderr, "pop_template_decls"); ! 664: debug_bindings_indentation += 4; ! 665: #endif ! 666: ! 667: if (!class_level) ! 668: poplevel (0, 0, 0); ! 669: ! 670: #ifdef DEBUG_CP_BINDING_LEVELS ! 671: debug_bindings_indentation -= 4; ! 672: #endif ! 673: } ! 674: ! 675: /* Should be defined in cp-parse.h. */ ! 676: extern int yychar; ! 677: ! 678: int ! 679: uses_template_parms (t) ! 680: tree t; ! 681: { ! 682: if (!t) ! 683: return 0; ! 684: switch (TREE_CODE (t)) ! 685: { ! 686: case INDIRECT_REF: ! 687: case COMPONENT_REF: ! 688: /* We assume that the object must be instantiated in order to build ! 689: the COMPONENT_REF, so we test only whether the type of the ! 690: COMPONENT_REF uses template parms. */ ! 691: return uses_template_parms (TREE_TYPE (t)); ! 692: ! 693: case IDENTIFIER_NODE: ! 694: if (!IDENTIFIER_TEMPLATE (t)) ! 695: return 0; ! 696: return uses_template_parms (TREE_VALUE (IDENTIFIER_TEMPLATE (t))); ! 697: ! 698: /* aggregates of tree nodes */ ! 699: case TREE_VEC: ! 700: { ! 701: int i = TREE_VEC_LENGTH (t); ! 702: while (i--) ! 703: if (uses_template_parms (TREE_VEC_ELT (t, i))) ! 704: return 1; ! 705: return 0; ! 706: } ! 707: case TREE_LIST: ! 708: if (uses_template_parms (TREE_PURPOSE (t)) ! 709: || uses_template_parms (TREE_VALUE (t))) ! 710: return 1; ! 711: return uses_template_parms (TREE_CHAIN (t)); ! 712: ! 713: /* constructed type nodes */ ! 714: case POINTER_TYPE: ! 715: case REFERENCE_TYPE: ! 716: return uses_template_parms (TREE_TYPE (t)); ! 717: case RECORD_TYPE: ! 718: case UNION_TYPE: ! 719: if (!TYPE_NAME (t)) ! 720: return 0; ! 721: if (!DECL_NAME (TYPE_NAME (t))) ! 722: return 0; ! 723: return uses_template_parms (DECL_NAME (TYPE_NAME (t))); ! 724: case FUNCTION_TYPE: ! 725: if (uses_template_parms (TYPE_ARG_TYPES (t))) ! 726: return 1; ! 727: return uses_template_parms (TREE_TYPE (t)); ! 728: case ARRAY_TYPE: ! 729: if (uses_template_parms (TYPE_DOMAIN (t))) ! 730: return 1; ! 731: return uses_template_parms (TREE_TYPE (t)); ! 732: case OFFSET_TYPE: ! 733: if (uses_template_parms (TYPE_OFFSET_BASETYPE (t))) ! 734: return 1; ! 735: return uses_template_parms (TREE_TYPE (t)); ! 736: case METHOD_TYPE: ! 737: if (uses_template_parms (TYPE_OFFSET_BASETYPE (t))) ! 738: return 1; ! 739: if (uses_template_parms (TYPE_ARG_TYPES (t))) ! 740: return 1; ! 741: return uses_template_parms (TREE_TYPE (t)); ! 742: ! 743: /* decl nodes */ ! 744: case TYPE_DECL: ! 745: return uses_template_parms (DECL_NAME (t)); ! 746: case FUNCTION_DECL: ! 747: if (uses_template_parms (TREE_TYPE (t))) ! 748: return 1; ! 749: /* fall through */ ! 750: case VAR_DECL: ! 751: case PARM_DECL: ! 752: /* ??? What about FIELD_DECLs? */ ! 753: /* The type of a decl can't use template parms if the name of the ! 754: variable doesn't, because it's impossible to resolve them. So ! 755: ignore the type field for now. */ ! 756: if (DECL_CONTEXT (t) && uses_template_parms (DECL_CONTEXT (t))) ! 757: return 1; ! 758: if (uses_template_parms (TREE_TYPE (t))) ! 759: { ! 760: error ("template parms used where they can't be resolved"); ! 761: } ! 762: return 0; ! 763: ! 764: case CALL_EXPR: ! 765: return uses_template_parms (TREE_TYPE (t)); ! 766: case ADDR_EXPR: ! 767: return uses_template_parms (TREE_OPERAND (t, 0)); ! 768: ! 769: /* template parm nodes */ ! 770: case TEMPLATE_TYPE_PARM: ! 771: case TEMPLATE_CONST_PARM: ! 772: return 1; ! 773: ! 774: /* simple type nodes */ ! 775: case INTEGER_TYPE: ! 776: if (uses_template_parms (TYPE_MIN_VALUE (t))) ! 777: return 1; ! 778: return uses_template_parms (TYPE_MAX_VALUE (t)); ! 779: ! 780: case REAL_TYPE: ! 781: case VOID_TYPE: ! 782: case ENUMERAL_TYPE: ! 783: return 0; ! 784: ! 785: /* constants */ ! 786: case INTEGER_CST: ! 787: case REAL_CST: ! 788: case STRING_CST: ! 789: return 0; ! 790: ! 791: case ERROR_MARK: ! 792: /* Non-error_mark_node ERROR_MARKs are bad things. */ ! 793: assert (t == error_mark_node); ! 794: /* NOTREACHED */ ! 795: return 0; ! 796: ! 797: case UNINSTANTIATED_P_TYPE: ! 798: return 1; ! 799: ! 800: default: ! 801: switch (TREE_CODE_CLASS (TREE_CODE (t))) ! 802: { ! 803: case '1': ! 804: case '2': ! 805: case '3': ! 806: case '<': ! 807: { ! 808: int i; ! 809: for (i = tree_code_length[(int) TREE_CODE (t)]; --i >= 0;) ! 810: if (uses_template_parms (TREE_OPERAND (t, i))) ! 811: return 1; ! 812: return 0; ! 813: } ! 814: default: ! 815: break; ! 816: } ! 817: sorry ("testing %s for template parms", ! 818: tree_code_name [(int) TREE_CODE (t)]); ! 819: abort (); ! 820: /* NOTREACHED */ ! 821: return 0; ! 822: } ! 823: } ! 824: ! 825: void ! 826: instantiate_member_templates (arg) ! 827: tree arg; ! 828: { ! 829: tree t; ! 830: tree classname = TREE_VALUE (arg); ! 831: tree id = classname; ! 832: tree members = DECL_TEMPLATE_MEMBERS (TREE_PURPOSE (IDENTIFIER_TEMPLATE (id))); ! 833: ! 834: for (t = members; t; t = TREE_CHAIN (t)) ! 835: { ! 836: tree parmvec, type, classparms, tdecl, t2; ! 837: int nparms, xxx, i; ! 838: ! 839: assert (TREE_VALUE (t) != NULL_TREE); ! 840: assert (TREE_CODE (TREE_VALUE (t)) == TEMPLATE_DECL); ! 841: /* @@ Should verify that class parm list is a list of ! 842: distinct template parameters, and covers all the template ! 843: parameters. */ ! 844: tdecl = TREE_VALUE (t); ! 845: type = DECL_CONTEXT (DECL_TEMPLATE_RESULT (tdecl)); ! 846: classparms = UPT_PARMS (type); ! 847: nparms = TREE_VEC_LENGTH (classparms); ! 848: parmvec = make_tree_vec (nparms); ! 849: for (i = 0; i < nparms; i++) ! 850: TREE_VEC_ELT (parmvec, i) = NULL_TREE; ! 851: switch (unify (DECL_TEMPLATE_PARMS (tdecl), ! 852: &TREE_VEC_ELT (parmvec, 0), nparms, ! 853: type, IDENTIFIER_TYPE_VALUE (classname), ! 854: &xxx)) ! 855: { ! 856: case 0: ! 857: /* Success -- well, no inconsistency, at least. */ ! 858: for (i = 0; i < nparms; i++) ! 859: if (TREE_VEC_ELT (parmvec, i) == NULL_TREE) ! 860: goto failure; ! 861: t2 = instantiate_template (tdecl, ! 862: &TREE_VEC_ELT (parmvec, 0)); ! 863: type = IDENTIFIER_TYPE_VALUE (id); ! 864: #if 0 ! 865: print_node_brief (stderr, "producing ", t2, 0); ! 866: print_node_brief (stderr, "\n\tfrom template ", tdecl, 0); ! 867: fprintf (stderr, "\n"); ! 868: #endif ! 869: assert (type != 0); ! 870: if (CLASSTYPE_INTERFACE_UNKNOWN (type)) ! 871: { ! 872: TREE_EXTERNAL (t2) = 0; ! 873: TREE_PUBLIC (t2) = 0; ! 874: } ! 875: else ! 876: { ! 877: TREE_EXTERNAL (t2) = CLASSTYPE_INTERFACE_ONLY (type); ! 878: TREE_PUBLIC (t2) = ! CLASSTYPE_INTERFACE_ONLY (type); ! 879: } ! 880: break; ! 881: case 1: ! 882: /* Failure. */ ! 883: failure: ! 884: error ("type unification error instantiating %s::%s", ! 885: IDENTIFIER_POINTER (classname), ! 886: IDENTIFIER_POINTER (DECL_NAME (tdecl))); ! 887: continue /* loop of members */; ! 888: default: ! 889: /* Eek, a bug. */ ! 890: abort (); ! 891: } ! 892: } ! 893: } ! 894: ! 895: tree ! 896: instantiate_class_template (classname, setup_parse) ! 897: tree classname; ! 898: int setup_parse; ! 899: { ! 900: struct template_info *template_info; ! 901: tree template, t1; ! 902: ! 903: if (classname == error_mark_node) ! 904: return error_mark_node; ! 905: ! 906: assert (TREE_CODE (classname) == IDENTIFIER_NODE); ! 907: template = IDENTIFIER_TEMPLATE (classname); ! 908: ! 909: if (IDENTIFIER_HAS_TYPE_VALUE (classname)) ! 910: { ! 911: tree type = IDENTIFIER_TYPE_VALUE (classname); ! 912: if (TREE_CODE (type) == UNINSTANTIATED_P_TYPE) ! 913: return type; ! 914: if (TYPE_BEING_DEFINED (type) ! 915: || TYPE_SIZE (type) ! 916: || CLASSTYPE_USE_TEMPLATE (type) != 0) ! 917: return type; ! 918: } ! 919: if (uses_template_parms (classname)) ! 920: { ! 921: if (!TREE_TYPE (classname)) ! 922: { ! 923: tree t = make_lang_type (RECORD_TYPE); ! 924: tree d = build_lang_decl (TYPE_DECL, classname, t); ! 925: DECL_NAME (d) = classname; ! 926: TYPE_NAME (t) = d; ! 927: pushdecl (d); ! 928: } ! 929: return NULL_TREE; ! 930: } ! 931: ! 932: t1 = TREE_PURPOSE (template); ! 933: assert (TREE_CODE (t1) == TEMPLATE_DECL); ! 934: ! 935: if (DECL_TEMPLATE_INFO (t1)->text == 0) ! 936: { ! 937: error ("template `%s' declared but not defined", ! 938: IDENTIFIER_POINTER (DECL_NAME (t1))); ! 939: return error_mark_node; ! 940: } ! 941: ! 942: #ifdef DEBUG_CP_BINDING_LEVELS ! 943: indent_to (stderr, debug_bindings_indentation); ! 944: fprintf (stderr, "instantiate_class_template"); ! 945: debug_bindings_indentation += 4; ! 946: #endif ! 947: ! 948: if (setup_parse) ! 949: { ! 950: push_to_top_level (); ! 951: push_template_decls (DECL_TEMPLATE_PARMS (TREE_PURPOSE (template)), ! 952: TREE_VALUE (template), 0); ! 953: set_current_level_tags_transparency (1); ! 954: template_info = DECL_TEMPLATE_INFO (t1); ! 955: feed_input (template_info->text, template_info->length, (struct obstack *)0); ! 956: lineno = template_info->lineno; ! 957: input_filename = template_info->filename; ! 958: /* Get interface/implementation back in sync. */ ! 959: extract_interface_info (); ! 960: overload_template_name (classname, 0); ! 961: yychar = PRE_PARSED_CLASS_DECL; ! 962: yylval.ttype = build_tree_list (class_type_node, classname); ! 963: processing_template_defn++; ! 964: } ! 965: else ! 966: { ! 967: tree t, decl, id, tmpl; ! 968: ! 969: push_to_top_level (); ! 970: push_template_decls (DECL_TEMPLATE_PARMS (TREE_PURPOSE (template)), ! 971: TREE_VALUE (template), 0); ! 972: set_current_level_tags_transparency (1); ! 973: template_info = DECL_TEMPLATE_INFO (t1); ! 974: id = classname; ! 975: tmpl = TREE_PURPOSE (IDENTIFIER_TEMPLATE (id)); ! 976: t = xref_tag (DECL_TEMPLATE_INFO (tmpl)->aggr, id, NULL_TREE); ! 977: assert (TREE_CODE (t) == RECORD_TYPE); ! 978: #if 1 ! 979: lineno = template_info->lineno; ! 980: input_filename = template_info->filename; ! 981: /* Get interface/implementation back in sync. */ ! 982: extract_interface_info (); ! 983: #endif ! 984: ! 985: /* Now, put a copy of the decl in global scope, to avoid ! 986: * recursive expansion. */ ! 987: decl = IDENTIFIER_LOCAL_VALUE (id); ! 988: if (!decl) ! 989: decl = IDENTIFIER_CLASS_VALUE (id); ! 990: if (decl) ! 991: { ! 992: assert (TREE_CODE (decl) == TYPE_DECL); ! 993: pushdecl_top_level (copy_node (decl)); ! 994: } ! 995: pop_from_top_level (); ! 996: } ! 997: ! 998: #ifdef DEBUG_CP_BINDING_LEVELS ! 999: debug_bindings_indentation -= 4; ! 1000: #endif ! 1001: ! 1002: return NULL_TREE; ! 1003: } ! 1004: ! 1005: static tree ! 1006: tsubst (t, args, nargs) ! 1007: tree t, *args; ! 1008: { ! 1009: tree type; ! 1010: if (t == NULL_TREE) ! 1011: return t; ! 1012: type = TREE_TYPE (t); ! 1013: if (type ! 1014: && type != integer_type_node ! 1015: && type != void_type_node ! 1016: && type != char_type_node) ! 1017: type = build_type_variant (tsubst (type, args, nargs), ! 1018: TYPE_READONLY (type), ! 1019: TYPE_VOLATILE (type)); ! 1020: if (type != TREE_TYPE (t)) ! 1021: layout_type (t); ! 1022: switch (TREE_CODE (t)) ! 1023: { ! 1024: case ERROR_MARK: ! 1025: case IDENTIFIER_NODE: ! 1026: case OP_IDENTIFIER: ! 1027: case VOID_TYPE: ! 1028: case REAL_TYPE: ! 1029: case ENUMERAL_TYPE: ! 1030: case INTEGER_CST: ! 1031: case REAL_CST: ! 1032: case STRING_CST: ! 1033: case RECORD_TYPE: ! 1034: case UNION_TYPE: ! 1035: return t; ! 1036: ! 1037: case INTEGER_TYPE: ! 1038: if (t == integer_type_node) ! 1039: return t; ! 1040: ! 1041: if (TREE_CODE (TYPE_MIN_VALUE (t)) == INTEGER_CST ! 1042: && TREE_CODE (TYPE_MAX_VALUE (t)) == INTEGER_CST) ! 1043: return t; ! 1044: return build_index_2_type (tsubst (TYPE_MIN_VALUE (t), args, nargs), ! 1045: tsubst (TYPE_MAX_VALUE (t), args, nargs)); ! 1046: ! 1047: case TEMPLATE_TYPE_PARM: ! 1048: return build_type_variant (args[TEMPLATE_TYPE_IDX (t)], ! 1049: TYPE_READONLY (t), ! 1050: TYPE_VOLATILE (t)); ! 1051: ! 1052: case TEMPLATE_CONST_PARM: ! 1053: return args[TEMPLATE_CONST_IDX (t)]; ! 1054: ! 1055: case FUNCTION_DECL: ! 1056: { ! 1057: tree r; ! 1058: tree fnargs, result; ! 1059: ! 1060: if (type == TREE_TYPE (t) ! 1061: && DECL_CONTEXT (t) == NULL_TREE) ! 1062: return t; ! 1063: fnargs = tsubst (DECL_ARGUMENTS (t), args, nargs); ! 1064: result = tsubst (DECL_RESULT (t), args, nargs); ! 1065: if (DECL_CONTEXT (t)) ! 1066: { ! 1067: /* Look it up in that class, and return the decl node there, ! 1068: instead of creating a new one. */ ! 1069: tree ctx = tsubst (DECL_CONTEXT (t), args, nargs); ! 1070: tree methods = CLASSTYPE_METHOD_VEC (ctx); ! 1071: tree name = DECL_NAME (t); ! 1072: tree method; ! 1073: int n_methods = TREE_VEC_LENGTH (methods); ! 1074: int i, found = 0; ! 1075: ! 1076: r = NULL_TREE; ! 1077: ! 1078: if (DECL_CONTEXT (t) ! 1079: && constructor_name (DECL_CONTEXT (t)) == DECL_NAME (t)) ! 1080: name = constructor_name (ctx); ! 1081: #if 0 ! 1082: fprintf (stderr, "\nfor function %s in class %s:\n", ! 1083: IDENTIFIER_POINTER (name), ! 1084: IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (ctx)))); ! 1085: #endif ! 1086: for (i = 0; i < n_methods; i++) ! 1087: { ! 1088: method = TREE_VEC_ELT (methods, i); ! 1089: if (method == NULL_TREE || DECL_NAME (method) != name) ! 1090: continue; ! 1091: for (; method; method = TREE_CHAIN (method)) ! 1092: { ! 1093: assert (TREE_CODE (method) == FUNCTION_DECL); ! 1094: if (TREE_TYPE (method) != type) ! 1095: { ! 1096: found = 1; ! 1097: continue; ! 1098: } ! 1099: #if 0 ! 1100: fprintf (stderr, "\tfound %s\n\n", ! 1101: IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (method))); ! 1102: #endif ! 1103: ! 1104: if (! TREE_PERMANENT (DECL_ARGUMENTS (method))) ! 1105: /* @@ Is this early enough? Might we want to do ! 1106: this instead while processing the expansion? */ ! 1107: DECL_ARGUMENTS (method) ! 1108: = tsubst (DECL_ARGUMENTS (t), args, nargs); ! 1109: r = method; ! 1110: break; ! 1111: } ! 1112: } ! 1113: if (r == NULL_TREE) ! 1114: { ! 1115: error (found ! 1116: ? "template for method `%s' doesn't match any in class `%s'" ! 1117: : "method `%s' not found in class `%s'", ! 1118: IDENTIFIER_POINTER (name), ! 1119: IDENTIFIER_POINTER (DECL_NAME (TYPE_NAME (ctx)))); ! 1120: return error_mark_node; ! 1121: } ! 1122: } ! 1123: else ! 1124: { ! 1125: r = DECL_NAME (t); ! 1126: r = build_decl_overload (IDENTIFIER_POINTER (r), ! 1127: TYPE_VALUES (type), ! 1128: DECL_CONTEXT (t) != NULL_TREE); ! 1129: r = build_lang_decl (FUNCTION_DECL, r, type); ! 1130: } ! 1131: TREE_PUBLIC (r) = TREE_PUBLIC (t); ! 1132: TREE_EXTERNAL (r) = TREE_EXTERNAL (t); ! 1133: TREE_STATIC (r) = TREE_STATIC (t); ! 1134: TREE_INLINE (r) = TREE_INLINE (t); ! 1135: DECL_SOURCE_FILE (r) = DECL_SOURCE_FILE (t); ! 1136: DECL_SOURCE_LINE (r) = DECL_SOURCE_LINE (t); ! 1137: DECL_CLASS_CONTEXT (r) = tsubst (DECL_CLASS_CONTEXT (t), args, nargs); ! 1138: make_decl_rtl (r, 0, 1); ! 1139: DECL_ARGUMENTS (r) = fnargs; ! 1140: DECL_RESULT (r) = result; ! 1141: if (DECL_CONTEXT (t) == NULL_TREE) ! 1142: push_overloaded_decl_top_level (r, 0); ! 1143: return r; ! 1144: } ! 1145: ! 1146: case PARM_DECL: ! 1147: { ! 1148: tree r; ! 1149: r = build_decl (PARM_DECL, DECL_NAME (t), type); ! 1150: DECL_INITIAL (r) = TREE_TYPE (r); ! 1151: if (TREE_CHAIN (t)) ! 1152: TREE_CHAIN (r) = tsubst (TREE_CHAIN (t), args, nargs); ! 1153: return r; ! 1154: } ! 1155: ! 1156: case TREE_LIST: ! 1157: { ! 1158: tree purpose, value, chain, result; ! 1159: int via_public, via_virtual; ! 1160: ! 1161: if (t == void_list_node) ! 1162: return t; ! 1163: ! 1164: via_public = TREE_VIA_PUBLIC (t); ! 1165: via_virtual = TREE_VIA_VIRTUAL (t); ! 1166: ! 1167: purpose = TREE_PURPOSE (t); ! 1168: if (purpose) ! 1169: purpose = tsubst (purpose, args, nargs); ! 1170: value = TREE_VALUE (t); ! 1171: if (value) ! 1172: value = tsubst (value, args, nargs); ! 1173: chain = TREE_CHAIN (t); ! 1174: if (chain ! 1175: && chain != void_type_node) ! 1176: chain = tsubst (chain, args, nargs); ! 1177: if (purpose == TREE_PURPOSE (t) ! 1178: && value == TREE_VALUE (t) ! 1179: && chain == TREE_CHAIN (t)) ! 1180: return t; ! 1181: result = hash_tree_cons (via_public, via_virtual, ! 1182: purpose, value, chain); ! 1183: TREE_PARMLIST (result) = TREE_PARMLIST (t); ! 1184: return result; ! 1185: } ! 1186: case TREE_VEC: ! 1187: { ! 1188: int len = TREE_VEC_LENGTH (t), need_new = 0, i; ! 1189: tree *elts = (tree *) alloca (len * sizeof (tree)); ! 1190: bzero (elts, len * sizeof (tree)); ! 1191: ! 1192: for (i = 0; i < len; i++) ! 1193: { ! 1194: elts[i] = tsubst (TREE_VEC_ELT (t, i), args, nargs); ! 1195: if (elts[i] != TREE_VEC_ELT (t, i)) ! 1196: need_new = 1; ! 1197: } ! 1198: ! 1199: if (!need_new) ! 1200: return t; ! 1201: ! 1202: t = make_tree_vec (len); ! 1203: for (i = 0; i < len; i++) ! 1204: TREE_VEC_ELT (t, i) = elts[i]; ! 1205: return t; ! 1206: } ! 1207: case POINTER_TYPE: ! 1208: case REFERENCE_TYPE: ! 1209: { ! 1210: tree r; ! 1211: enum tree_code code; ! 1212: if (type == TREE_TYPE (t)) ! 1213: return t; ! 1214: ! 1215: code = TREE_CODE (t); ! 1216: if (code == POINTER_TYPE) ! 1217: r = build_pointer_type (type); ! 1218: else ! 1219: r = build_reference_type (type); ! 1220: r = build_type_variant (r, TYPE_READONLY (t), TYPE_VOLATILE (t)); ! 1221: /* Will this ever be needed for TYPE_..._TO values? */ ! 1222: layout_type (r); ! 1223: return r; ! 1224: } ! 1225: case FUNCTION_TYPE: ! 1226: case METHOD_TYPE: ! 1227: { ! 1228: tree values = TYPE_VALUES (t); /* same as TYPE_ARG_TYPES */ ! 1229: tree context = TYPE_CONTEXT (t); ! 1230: tree new_value; ! 1231: ! 1232: /* Don't bother recursing if we know it won't change anything. */ ! 1233: if (! (values == void_type_node ! 1234: || values == integer_type_node)) ! 1235: values = tsubst (values, args, nargs); ! 1236: if (context) ! 1237: context = tsubst (context, args, nargs); ! 1238: /* Could also optimize cases where return value and ! 1239: values have common elements (e.g., T min(const &T, const T&). */ ! 1240: ! 1241: /* If the above parameters haven't changed, just return the type. */ ! 1242: if (type == TREE_TYPE (t) ! 1243: && values == TYPE_VALUES (t) ! 1244: && context == TYPE_CONTEXT (t)) ! 1245: return t; ! 1246: ! 1247: /* Construct a new type node and return it. */ ! 1248: if (TREE_CODE (t) == FUNCTION_TYPE ! 1249: && context == NULL_TREE) ! 1250: { ! 1251: new_value = build_function_type (type, values); ! 1252: } ! 1253: else if (context == NULL_TREE) ! 1254: { ! 1255: tree base = tsubst (TYPE_METHOD_BASETYPE (t), args, nargs); ! 1256: new_value = build_cplus_method_type (base, type, ! 1257: TREE_CHAIN (values)); ! 1258: } ! 1259: else ! 1260: { ! 1261: new_value = make_node (TREE_CODE (t)); ! 1262: TREE_TYPE (new_value) = type; ! 1263: TYPE_CONTEXT (new_value) = context; ! 1264: TYPE_VALUES (new_value) = values; ! 1265: TYPE_SIZE (new_value) = TYPE_SIZE (t); ! 1266: TYPE_ALIGN (new_value) = TYPE_ALIGN (t); ! 1267: TYPE_MODE (new_value) = TYPE_MODE (t); ! 1268: if (TYPE_METHOD_BASETYPE (t)) ! 1269: TYPE_METHOD_BASETYPE (new_value) = tsubst (TYPE_METHOD_BASETYPE (t), ! 1270: args, nargs); ! 1271: /* Need to generate hash value. */ ! 1272: abort (); ! 1273: } ! 1274: new_value = build_type_variant (new_value, ! 1275: TYPE_READONLY (new_value), ! 1276: TYPE_VOLATILE (new_value)); ! 1277: return new_value; ! 1278: } ! 1279: case ARRAY_TYPE: ! 1280: { ! 1281: tree domain = tsubst (TYPE_DOMAIN (t), args, nargs); ! 1282: tree r; ! 1283: if (type == TREE_TYPE (t) && domain == TYPE_DOMAIN (t)) ! 1284: return t; ! 1285: r = build_cplus_array_type (type, domain); ! 1286: return r; ! 1287: } ! 1288: ! 1289: case UNINSTANTIATED_P_TYPE: ! 1290: { ! 1291: int nparms = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (UPT_TEMPLATE (t))); ! 1292: tree argvec = make_tree_vec (nparms); ! 1293: tree parmvec = UPT_PARMS (t); ! 1294: int i; ! 1295: tree id; ! 1296: for (i = 0; i < nparms; i++) ! 1297: TREE_VEC_ELT (argvec, i) = tsubst (TREE_VEC_ELT (parmvec, i), ! 1298: args, nargs); ! 1299: id = lookup_template_class (DECL_NAME (UPT_TEMPLATE (t)), argvec); ! 1300: if (! IDENTIFIER_HAS_TYPE_VALUE (id)) { ! 1301: instantiate_class_template(id, 0); ! 1302: /* set up pending_classes */ ! 1303: add_pending_template (id); ! 1304: ! 1305: TYPE_MAIN_VARIANT (IDENTIFIER_TYPE_VALUE (id)) = ! 1306: IDENTIFIER_TYPE_VALUE (id); ! 1307: } ! 1308: return IDENTIFIER_TYPE_VALUE (id); ! 1309: } ! 1310: ! 1311: case MINUS_EXPR: ! 1312: case PLUS_EXPR: ! 1313: return fold (build (TREE_CODE (t), TREE_TYPE (t), ! 1314: tsubst (TREE_OPERAND (t, 0), args, nargs), ! 1315: tsubst (TREE_OPERAND (t, 1), args, nargs))); ! 1316: ! 1317: case NEGATE_EXPR: ! 1318: case NOP_EXPR: ! 1319: return fold (build1 (TREE_CODE (t), TREE_TYPE (t), ! 1320: tsubst (TREE_OPERAND (t, 0), args, nargs))); ! 1321: ! 1322: default: ! 1323: sorry ("use of `%s' in function template", ! 1324: tree_code_name [(int) TREE_CODE (t)]); ! 1325: return error_mark_node; ! 1326: } ! 1327: } ! 1328: ! 1329: tree ! 1330: instantiate_template (tmpl, targ_ptr) ! 1331: tree tmpl, *targ_ptr; ! 1332: { ! 1333: tree targs, fndecl; ! 1334: int i, len; ! 1335: struct pending_inline *p; ! 1336: struct template_info *t; ! 1337: struct obstack *old_fmp_obstack; ! 1338: extern struct obstack *function_maybepermanent_obstack; ! 1339: ! 1340: push_obstacks (&permanent_obstack, &permanent_obstack); ! 1341: old_fmp_obstack = function_maybepermanent_obstack; ! 1342: function_maybepermanent_obstack = &permanent_obstack; ! 1343: ! 1344: assert (TREE_CODE (tmpl) == TEMPLATE_DECL); ! 1345: len = TREE_VEC_LENGTH (DECL_TEMPLATE_PARMS (tmpl)); ! 1346: ! 1347: for (fndecl = DECL_TEMPLATE_INSTANTIATIONS (tmpl); ! 1348: fndecl; fndecl = TREE_CHAIN (fndecl)) ! 1349: { ! 1350: tree *t1 = &TREE_VEC_ELT (TREE_PURPOSE (fndecl), 0); ! 1351: for (i = len - 1; i >= 0; i--) ! 1352: if (t1[i] != targ_ptr[i]) ! 1353: goto no_match; ! 1354: ! 1355: /* Here, we have a match. */ ! 1356: fndecl = TREE_VALUE (fndecl); ! 1357: function_maybepermanent_obstack = old_fmp_obstack; ! 1358: pop_obstacks (); ! 1359: return fndecl; ! 1360: ! 1361: no_match: ! 1362: ; ! 1363: } ! 1364: ! 1365: targs = make_tree_vec (len); ! 1366: i = len; ! 1367: while (i--) ! 1368: TREE_VEC_ELT (targs, i) = targ_ptr[i]; ! 1369: ! 1370: /* substitute template parameters */ ! 1371: fndecl = tsubst (DECL_RESULT (tmpl), targ_ptr, ! 1372: TREE_VEC_LENGTH (targs)); ! 1373: p = (struct pending_inline *) permalloc (sizeof (struct pending_inline)); ! 1374: t = DECL_TEMPLATE_INFO (tmpl); ! 1375: p->parm_vec = t->parm_vec; ! 1376: p->bindings = targs; ! 1377: p->can_free = 0; ! 1378: p->deja_vu = 0; ! 1379: p->lineno = t->lineno; ! 1380: p->filename = t->filename; ! 1381: p->buf = t->text; ! 1382: p->len = t->length; ! 1383: p->fndecl = fndecl; ! 1384: ! 1385: DECL_TEMPLATE_INSTANTIATIONS (tmpl) = ! 1386: tree_cons (targs, fndecl, DECL_TEMPLATE_INSTANTIATIONS (tmpl)); ! 1387: ! 1388: function_maybepermanent_obstack = old_fmp_obstack; ! 1389: pop_obstacks (); ! 1390: ! 1391: if (fndecl == error_mark_node) ! 1392: { ! 1393: /* do nothing */ ! 1394: } ! 1395: else if (TREE_INLINE (fndecl)) ! 1396: { ! 1397: DECL_PENDING_INLINE_INFO (fndecl) = p; ! 1398: p->next = pending_inlines; ! 1399: pending_inlines = p; ! 1400: } ! 1401: else ! 1402: { ! 1403: p->next = pending_template_expansions; ! 1404: pending_template_expansions = p; ! 1405: } ! 1406: return fndecl; ! 1407: } ! 1408: ! 1409: void ! 1410: undo_template_name_overload (id, classlevel) ! 1411: tree id; ! 1412: int classlevel; ! 1413: { ! 1414: tree template; ! 1415: ! 1416: template = IDENTIFIER_TEMPLATE (id); ! 1417: if (!template) ! 1418: return; ! 1419: ! 1420: #ifdef DEBUG_CP_BINDING_LEVELS ! 1421: indent_to (stderr, debug_bindings_indentation); ! 1422: fprintf (stderr, "undo_template_name_overload"); ! 1423: debug_bindings_indentation += 4; ! 1424: #endif ! 1425: ! 1426: poplevel (0,0,0); ! 1427: if (!classlevel) ! 1428: poplevel (0, 0, 0); ! 1429: #ifdef DEBUG_CP_BINDING_LEVELS ! 1430: debug_bindings_indentation -= 4; ! 1431: #endif ! 1432: } ! 1433: ! 1434: void ! 1435: overload_template_name (id, classlevel) ! 1436: tree id; ! 1437: int classlevel; ! 1438: { ! 1439: tree template, t, decl; ! 1440: struct template_info *tinfo; ! 1441: ! 1442: assert (TREE_CODE (id) == IDENTIFIER_NODE); ! 1443: template = IDENTIFIER_TEMPLATE (id); ! 1444: if (!template) ! 1445: return; ! 1446: ! 1447: #ifdef DEBUG_CP_BINDING_LEVELS ! 1448: indent_to (stderr, debug_bindings_indentation); ! 1449: fprintf (stderr, "overload_template_name(%d)", classlevel); ! 1450: debug_bindings_indentation += 4; ! 1451: #endif ! 1452: template = TREE_PURPOSE (template); ! 1453: tinfo = DECL_TEMPLATE_INFO (template); ! 1454: template = DECL_NAME (template); ! 1455: assert (template != NULL_TREE); ! 1456: ! 1457: if (!classlevel) ! 1458: pushlevel (1); ! 1459: ! 1460: t = xref_tag (tinfo->aggr, id, NULL_TREE); ! 1461: assert (TREE_CODE (t) == RECORD_TYPE ! 1462: || TREE_CODE (t) == UNINSTANTIATED_P_TYPE); ! 1463: ! 1464: decl = build_decl (TYPE_DECL, template, t); ! 1465: ! 1466: #if 0 /* fix this later */ ! 1467: /* We don't want to call here if the work has already been done. */ ! 1468: t = (classlevel ! 1469: ? IDENTIFIER_CLASS_VALUE (template) ! 1470: : IDENTIFIER_LOCAL_VALUE (template)); ! 1471: if (t ! 1472: && TREE_CODE (t) == TYPE_DECL ! 1473: && TREE_TYPE (t) == t) ! 1474: abort (); ! 1475: #endif ! 1476: ! 1477: if (classlevel) ! 1478: pushdecl_class_level (decl); ! 1479: else ! 1480: { ! 1481: pushdecl (decl); ! 1482: /* @@ Is this necessary now? */ ! 1483: IDENTIFIER_LOCAL_VALUE (template) = decl; ! 1484: } ! 1485: pushlevel(1); ! 1486: ! 1487: #ifdef DEBUG_CP_BINDING_LEVELS ! 1488: debug_bindings_indentation -= 4; ! 1489: #endif ! 1490: } ! 1491: ! 1492: /* T1 is PRE_PARSED_CLASS_DECL; T3 is result of XREF_TAG lookup. */ ! 1493: void ! 1494: end_template_instantiation (t1, t3) ! 1495: tree t1, t3; ! 1496: { ! 1497: extern struct pending_input *to_be_restored; ! 1498: tree t, decl; ! 1499: ! 1500: #ifdef DEBUG_CP_BINDING_LEVELS ! 1501: indent_to (stderr, debug_bindings_indentation); ! 1502: fprintf (stderr, "end_template_instantiation"); ! 1503: debug_bindings_indentation += 4; ! 1504: #endif ! 1505: ! 1506: processing_template_defn--; ! 1507: ! 1508: /* Restore the old parser input state. */ ! 1509: if (yychar == -2 /* YYEMPTY */) ! 1510: yychar = yylex (); ! 1511: if (yychar != END_OF_SAVED_INPUT) ! 1512: error ("parse error at end of class template"); ! 1513: else ! 1514: { ! 1515: restore_pending_input (to_be_restored); ! 1516: to_be_restored = 0; ! 1517: } ! 1518: ! 1519: /* Our declarations didn't get stored in the global slot, since ! 1520: there was a (supposedly tags-transparent) scope in between. */ ! 1521: t = IDENTIFIER_TYPE_VALUE (TREE_VALUE (t1)); ! 1522: assert (t != NULL_TREE && TREE_CODE_CLASS (TREE_CODE (t)) == 't'); ! 1523: CLASSTYPE_USE_TEMPLATE (t) = 2; ! 1524: decl = IDENTIFIER_GLOBAL_VALUE (TREE_VALUE (t1)); ! 1525: assert (TREE_CODE (decl) == TYPE_DECL); ! 1526: ! 1527: undo_template_name_overload (TREE_VALUE (t1), 0); ! 1528: t = IDENTIFIER_TEMPLATE (TREE_VALUE (t1)); ! 1529: pop_template_decls (DECL_TEMPLATE_PARMS (TREE_PURPOSE (t)), TREE_VALUE (t), ! 1530: 0); ! 1531: pop_from_top_level (); ! 1532: ! 1533: /* This will fix up the type-value field. */ ! 1534: pushdecl_top_level (decl); ! 1535: ! 1536: /* Restore interface/implementation settings. */ ! 1537: extract_interface_info (); ! 1538: ! 1539: #ifdef DEBUG_CP_BINDING_LEVELS ! 1540: debug_bindings_indentation -= 4; ! 1541: #endif ! 1542: } ! 1543: ! 1544: /* Store away the text of an inline template function. No rtl is ! 1545: generated for this function until it is actually needed. */ ! 1546: ! 1547: void ! 1548: reinit_parse_for_template (yychar, d1, d2) ! 1549: int yychar; ! 1550: tree d1, d2; ! 1551: { ! 1552: struct template_info *template_info; ! 1553: ! 1554: if (d2 == NULL_TREE || d2 == error_mark_node) ! 1555: { ! 1556: lose: ! 1557: /* @@ Should use temp obstack, and discard results. */ ! 1558: reinit_parse_for_block (yychar, &permanent_obstack, 1); ! 1559: return; ! 1560: } ! 1561: ! 1562: if (TREE_CODE (d2) == IDENTIFIER_NODE) ! 1563: d2 = IDENTIFIER_GLOBAL_VALUE (d2); ! 1564: if (!d2) ! 1565: goto lose; ! 1566: template_info = DECL_TEMPLATE_INFO (d2); ! 1567: if (!template_info) ! 1568: { ! 1569: template_info = (struct template_info *) permalloc (sizeof (struct template_info)); ! 1570: bzero (template_info, sizeof (struct template_info)); ! 1571: DECL_TEMPLATE_INFO (d2) = template_info; ! 1572: } ! 1573: template_info->filename = input_filename; ! 1574: template_info->lineno = lineno; ! 1575: reinit_parse_for_block (yychar, &permanent_obstack, 1); ! 1576: template_info->text = obstack_base (&permanent_obstack); ! 1577: template_info->length = obstack_object_size (&permanent_obstack); ! 1578: obstack_finish (&permanent_obstack); ! 1579: template_info->parm_vec = d1; ! 1580: } ! 1581: ! 1582: /* Type unification. ! 1583: ! 1584: We have a function template signature with one or more references to ! 1585: template parameters, and a parameter list we wish to fit to this ! 1586: template. If possible, produce a list of parameters for the template ! 1587: which will cause it to fit the supplied parameter list. ! 1588: ! 1589: Return zero for success, 2 for an incomplete match that doesn't resolve ! 1590: all the types, and 1 for complete failure. An error message will be ! 1591: printed only for an incomplete match. ! 1592: ! 1593: TPARMS[NTPARMS] is an array of template parameter types; ! 1594: TARGS[NTPARMS] is the array of template parameter values. PARMS is ! 1595: the function template's signature (using TEMPLATE_PARM_IDX nodes), ! 1596: and ARGS is the argument list we're trying to match against it. */ ! 1597: ! 1598: int ! 1599: type_unification (tparms, targs, parms, args, nsubsts) ! 1600: tree tparms, *targs, parms, args; ! 1601: int *nsubsts; ! 1602: { ! 1603: tree parm, arg; ! 1604: int i; ! 1605: int ntparms = TREE_VEC_LENGTH (tparms); ! 1606: ! 1607: assert (TREE_CODE (tparms) == TREE_VEC); ! 1608: assert (TREE_CODE (parms) == TREE_LIST); ! 1609: assert (TREE_CODE (args) == TREE_LIST); ! 1610: assert (ntparms > 0); ! 1611: ! 1612: bzero (targs, sizeof (tree) * ntparms); ! 1613: ! 1614: while (parms ! 1615: && parms != void_list_node ! 1616: && args) ! 1617: { ! 1618: parm = TREE_VALUE (parms); ! 1619: parms = TREE_CHAIN (parms); ! 1620: arg = TREE_VALUE (args); ! 1621: args = TREE_CHAIN (args); ! 1622: ! 1623: if (arg == error_mark_node) ! 1624: return 1; ! 1625: #if 0 ! 1626: if (TREE_CODE (arg) == VAR_DECL) ! 1627: arg = TREE_TYPE (arg); ! 1628: else if (TREE_CODE_CLASS (TREE_CODE (arg)) == 'e') ! 1629: arg = TREE_TYPE (arg); ! 1630: #else ! 1631: assert (TREE_TYPE (arg) != NULL_TREE); ! 1632: arg = TREE_TYPE (arg); ! 1633: #endif ! 1634: ! 1635: switch (unify (tparms, targs, ntparms, parm, arg, nsubsts)) ! 1636: { ! 1637: case 0: ! 1638: break; ! 1639: case 1: ! 1640: return 1; ! 1641: } ! 1642: } ! 1643: /* Fail if we've reached the end of the parm list, and more args ! 1644: are present, and the parm list isn't variadic. */ ! 1645: if (args && parms == void_list_node) ! 1646: return 1; ! 1647: /* Fail if parms are left and they don't have default values. */ ! 1648: if (parms ! 1649: && parms != void_list_node ! 1650: && TREE_PURPOSE (parms) == NULL_TREE) ! 1651: return 1; ! 1652: for (i = 0; i < ntparms; i++) ! 1653: if (!targs[i]) ! 1654: { ! 1655: error ("incomplete type unification"); ! 1656: return 2; ! 1657: } ! 1658: return 0; ! 1659: } ! 1660: ! 1661: /* Tail recursion is your friend. */ ! 1662: static int ! 1663: unify (tparms, targs, ntparms, parm, arg, nsubsts) ! 1664: tree tparms, *targs, parm, arg; ! 1665: int *nsubsts; ! 1666: { ! 1667: int idx; ! 1668: ! 1669: /* I don't think this will do the right thing with respect to types. ! 1670: But the only case I've seen it in so far has been array bounds, where ! 1671: signedness is the only information lost, and I think that will be ! 1672: okay. */ ! 1673: while (TREE_CODE (parm) == NOP_EXPR) ! 1674: parm = TREE_OPERAND (parm, 0); ! 1675: ! 1676: if (arg == error_mark_node) ! 1677: return 1; ! 1678: if (arg == parm) ! 1679: return 0; ! 1680: ! 1681: switch (TREE_CODE (parm)) ! 1682: { ! 1683: case TEMPLATE_TYPE_PARM: ! 1684: (*nsubsts)++; ! 1685: if (TEMPLATE_TYPE_TPARMLIST (parm) != tparms) ! 1686: { ! 1687: error ("mixed template headers?!"); ! 1688: abort (); ! 1689: return 1; ! 1690: } ! 1691: idx = TEMPLATE_TYPE_IDX (parm); ! 1692: /* Simple cases: Value already set, does match or doesn't. */ ! 1693: if (targs[idx] == arg) ! 1694: return 0; ! 1695: else if (targs[idx]) ! 1696: return 1; ! 1697: /* Check for mixed types and values. */ ! 1698: if (TREE_CODE (TREE_VEC_ELT (tparms, idx)) != IDENTIFIER_NODE) ! 1699: return 1; ! 1700: targs[idx] = arg; ! 1701: return 0; ! 1702: case TEMPLATE_CONST_PARM: ! 1703: (*nsubsts)++; ! 1704: idx = TEMPLATE_CONST_IDX (parm); ! 1705: if (targs[idx] == arg) ! 1706: return 0; ! 1707: else if (targs[idx]) ! 1708: { ! 1709: abort(); ! 1710: return 1; ! 1711: } ! 1712: /* else if (typeof arg != tparms[idx]) ! 1713: return 1;*/ ! 1714: ! 1715: targs[idx] = copy_to_permanent (arg); ! 1716: return 0; ! 1717: ! 1718: case POINTER_TYPE: ! 1719: if (TREE_CODE (arg) != POINTER_TYPE) ! 1720: return 1; ! 1721: return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg), ! 1722: nsubsts); ! 1723: ! 1724: case REFERENCE_TYPE: ! 1725: return unify (tparms, targs, ntparms, TREE_TYPE (parm), arg, nsubsts); ! 1726: ! 1727: case ARRAY_TYPE: ! 1728: if (TREE_CODE (arg) != ARRAY_TYPE) ! 1729: return 1; ! 1730: if (unify (tparms, targs, ntparms, TYPE_DOMAIN (parm), TYPE_DOMAIN (arg), ! 1731: nsubsts) != 0) ! 1732: return 1; ! 1733: return unify (tparms, targs, ntparms, TREE_TYPE (parm), TREE_TYPE (arg), ! 1734: nsubsts); ! 1735: ! 1736: case REAL_TYPE: ! 1737: case INTEGER_TYPE: ! 1738: if (TREE_CODE (parm) == INTEGER_TYPE && TREE_CODE (arg) == INTEGER_TYPE) ! 1739: { ! 1740: if (TYPE_MIN_VALUE (parm) && TYPE_MIN_VALUE (arg) ! 1741: && unify (tparms, targs, ntparms, ! 1742: TYPE_MIN_VALUE (parm), TYPE_MIN_VALUE (arg), nsubsts)) ! 1743: return 1; ! 1744: if (TYPE_MAX_VALUE (parm) && TYPE_MAX_VALUE (arg) ! 1745: && unify (tparms, targs, ntparms, ! 1746: TYPE_MAX_VALUE (parm), TYPE_MAX_VALUE (arg), nsubsts)) ! 1747: return 1; ! 1748: } ! 1749: /* As far as unification is concerned, this wins. Later checks ! 1750: will invalidate it if necessary. */ ! 1751: return 0; ! 1752: ! 1753: /* Types INTEGER_CST and MINUS_EXPR can come from array bounds. */ ! 1754: case INTEGER_CST: ! 1755: if (TREE_CODE (arg) != INTEGER_CST) ! 1756: return 1; ! 1757: return !tree_int_cst_equal (parm, arg); ! 1758: ! 1759: case MINUS_EXPR: ! 1760: { ! 1761: tree t1, t2; ! 1762: t1 = TREE_OPERAND (parm, 0); ! 1763: t2 = TREE_OPERAND (parm, 1); ! 1764: if (TREE_CODE (t1) != TEMPLATE_CONST_PARM) ! 1765: return 1; ! 1766: return unify (tparms, targs, ntparms, t1, ! 1767: fold (build (PLUS_EXPR, integer_type_node, arg, t2)), ! 1768: nsubsts); ! 1769: } ! 1770: ! 1771: case TREE_VEC: ! 1772: { ! 1773: int i; ! 1774: if (TREE_CODE (arg) != TREE_VEC) ! 1775: return 1; ! 1776: if (TREE_VEC_LENGTH (parm) != TREE_VEC_LENGTH (arg)) ! 1777: return 1; ! 1778: for (i = TREE_VEC_LENGTH (parm) - 1; i >= 0; i--) ! 1779: if (unify (tparms, targs, ntparms, ! 1780: TREE_VEC_ELT (parm, i), TREE_VEC_ELT (arg, i), ! 1781: nsubsts)) ! 1782: return 1; ! 1783: return 0; ! 1784: } ! 1785: ! 1786: case UNINSTANTIATED_P_TYPE: ! 1787: { ! 1788: tree a = IDENTIFIER_TEMPLATE (DECL_NAME (TYPE_NAME (arg))); ! 1789: if (UPT_TEMPLATE (parm) != TREE_PURPOSE (a)) ! 1790: /* different templates */ ! 1791: return 1; ! 1792: return unify (tparms, targs, ntparms, UPT_PARMS (parm), TREE_VALUE (a), ! 1793: nsubsts); ! 1794: } ! 1795: ! 1796: default: ! 1797: sorry ("use of `%s' in template type unification", ! 1798: tree_code_name [(int) TREE_CODE (parm)]); ! 1799: return 1; ! 1800: } ! 1801: } ! 1802: ! 1803: ! 1804: #undef DEBUG ! 1805: ! 1806: int ! 1807: do_pending_expansions () ! 1808: { ! 1809: struct pending_inline *i, *new_list = 0; ! 1810: ! 1811: if (!pending_template_expansions) ! 1812: return 0; ! 1813: ! 1814: #ifdef DEBUG ! 1815: fprintf (stderr, "\n\n\t\t IN DO_PENDING_EXPANSIONS\n\n"); ! 1816: #endif ! 1817: ! 1818: i = pending_template_expansions; ! 1819: while (i) ! 1820: { ! 1821: tree context; ! 1822: ! 1823: struct pending_inline *next = i->next; ! 1824: tree t = i->fndecl; ! 1825: ! 1826: int decision = 0; ! 1827: #define DECIDE(N) if(1){decision=(N); goto decided;}else ! 1828: ! 1829: assert (TREE_CODE (t) == FUNCTION_DECL || TREE_CODE (t) == VAR_DECL); ! 1830: if (TREE_ASM_WRITTEN (t)) ! 1831: DECIDE (0); ! 1832: /* If it's a method, let the class type decide it. ! 1833: @@ What if the method template is in a separate file? ! 1834: Maybe both file contexts should be taken into account? */ ! 1835: context = DECL_CONTEXT (t); ! 1836: if (context) ! 1837: { ! 1838: /* If `unknown', we might want a static copy. ! 1839: If `implementation', we want a global one. ! 1840: If `interface', ext ref. */ ! 1841: if (!CLASSTYPE_INTERFACE_UNKNOWN (context)) ! 1842: DECIDE (!CLASSTYPE_INTERFACE_ONLY (context)); ! 1843: #if 0 /* This doesn't get us stuff needed only by the file initializer. */ ! 1844: DECIDE (TREE_USED (t)); ! 1845: #else /* This compiles too much stuff, but that's probably better in ! 1846: most cases than never compiling the stuff we need. */ ! 1847: DECIDE (1); ! 1848: #endif ! 1849: } ! 1850: /* else maybe call extract_interface_info? */ ! 1851: if (TREE_USED (t)) /* is this right? */ ! 1852: DECIDE (1); ! 1853: ! 1854: decided: ! 1855: #ifdef DEBUG ! 1856: print_node_brief (stderr, decision ? "yes: " : "no: ", t, 0); ! 1857: fprintf (stderr, "\t%s\n", ! 1858: (DECL_ASSEMBLER_NAME (t) ! 1859: ? IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (t)) ! 1860: : "")); ! 1861: #endif ! 1862: if (decision == 1) ! 1863: { ! 1864: i->next = pending_inlines; ! 1865: pending_inlines = i; ! 1866: } ! 1867: else ! 1868: { ! 1869: i->next = new_list; ! 1870: new_list = i; ! 1871: } ! 1872: i = next; ! 1873: } ! 1874: pending_template_expansions = new_list; ! 1875: if (!pending_inlines) ! 1876: return 0; ! 1877: do_pending_inlines (); ! 1878: return 1; ! 1879: } ! 1880: ! 1881: struct pending_template { ! 1882: struct pending_template *next; ! 1883: tree id; ! 1884: }; ! 1885: ! 1886: ! 1887: struct pending_template* pending_templates; ! 1888: ! 1889: void ! 1890: do_pending_templates () ! 1891: { ! 1892: struct pending_template* t; ! 1893: ! 1894: for ( t = pending_templates; t; t = t->next) ! 1895: { ! 1896: instantiate_class_template (t->id, 1); ! 1897: } ! 1898: ! 1899: for ( t = pending_templates; t; t = pending_templates) ! 1900: { ! 1901: pending_templates = t->next; ! 1902: free(t); ! 1903: } ! 1904: } ! 1905: ! 1906: int ! 1907: add_pending_template (pt) ! 1908: tree pt; ! 1909: { ! 1910: struct pending_template *p; ! 1911: ! 1912: p = (struct pending_template *) malloc (sizeof (struct pending_template)); ! 1913: p->next = pending_templates; ! 1914: pending_templates = p; ! 1915: p->id = pt; ! 1916: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.