|
|
1.1 ! root 1: /* ident "@(#)ctrans:src/template.c 1.3" */ ! 2: /******************************************************************* ! 3: * template.c ! 4: * ! 5: * This file contains most of the implementation for a subset of ! 6: * parametrized types as defined by the 1989 Stroustrup JOOP paper. ! 7: * The subset chosen here was the subset relevant to the ! 8: * implementation of aggregates in ObjectStore. ! 9: * ! 10: * The following is a list of features supported by the ! 11: * implementation. The list of features parallels the ! 12: * description of templates in the JOOP paper. ! 13: * ! 14: * a) Class templates supported. ! 15: * ! 16: * b) Member function templates supported. ! 17: * Type-specific member functions as described at the ! 18: * end of the "Outline of an implementation" section ! 19: * are also supported. ! 20: * ! 21: * Non-member function templates are not supported. ! 22: * ! 23: * c) Template arguments may be of type "type" or ! 24: * simple integral, real, double and pointer types ! 25: * that are compile-time constants. ! 26: * ! 27: * Default arguments are not suported. ! 28: * ! 29: * ! 30: * Restrictions: ! 31: * ! 32: * a) template definitions may not be nested. ! 33: * ! 34: * b) enums, or class definitions may not be ! 35: * nested within a template class definition. ! 36: * ! 37: * This file also supports an internal template facility ! 38: * to facilitate the implementation of ObjectStore data ! 39: * model features. The internal template facility is ! 40: * only used by compiler implementors, and is not user visible. ! 41: * ! 42: ************************************************************/ ! 43: ! 44: ! 45: /*********************************************************** ! 46: * ! 47: * TBD ! 48: * ! 49: * 1) Error recovery, a never ending task, could stand improvement. ! 50: * ! 51: * 2) The template copying process could probably be speeded up ! 52: * substantially, by only placing "graph-like" nodes in the hash ! 53: * table. The current implementation plays it safe, and places ! 54: * all nodes in the hash table. ! 55: * ! 56: * 3) Clean up $name processing, it needs to be remodularized ! 57: * so that class templates and tree templates share the code. ! 58: * ! 59: * 4) Permit parametrized name default names within member ! 60: * functions. ! 61: * ! 62: ****************************************************************/ ! 63: ! 64: #include "tree_copy.h" ! 65: #include "cfront.h" ! 66: #include <string.h> ! 67: #include "tree_dump.h" ! 68: #include "template.h" ! 69: #include <stdlib.h> ! 70: #include <ctype.h> ! 71: #include "hash.h" ! 72: ! 73: extern int bound ; // is not mentioned in the header file ! 74: ! 75: const int max_string_size = 1024 ; ! 76: ! 77: const int default_copy_hash_size = 1000 ; ! 78: ! 79: // Save and restore global state around a template instantiation ! 80: void state::save() { ! 81: ! 82: Cdcl = ::Cdcl ; ! 83: Cstmt = ::Cstmt ; ! 84: curloc = ::curloc ; ! 85: ! 86: curr_file = ::curr_file ; ! 87: curr_expr = ::curr_expr ; ! 88: curr_icall = ::curr_icall ; ! 89: curr_loop = ::curr_loop; ! 90: curr_block = ::curr_block; ! 91: curr_switch = ::curr_switch; ! 92: ! 93: bound = ::bound ; ! 94: inline_restr = ::inline_restr ; ! 95: last_line = ::last_line ; ! 96: ! 97: no_of_badcall = ::no_of_badcall; ! 98: no_of_undcl = ::no_of_undcl ; ! 99: ! 100: badcall = ::badcall ; ! 101: undcl = ::undcl ; ! 102: } ; ! 103: ! 104: ! 105: void state::restore() { ! 106: ::Cdcl = Cdcl ; ! 107: ::Cstmt = Cstmt ; ! 108: ::curloc = curloc ; ! 109: ! 110: ::curr_file = curr_file ; ! 111: ::curr_expr = curr_expr ; ! 112: ::curr_icall = curr_icall ; ! 113: ::curr_loop = curr_loop; ! 114: ::curr_block = curr_block; ! 115: ::curr_switch = curr_switch; ! 116: ! 117: ::bound = bound ; ! 118: ::inline_restr = inline_restr ; ! 119: ::last_line = last_line ; ! 120: ! 121: ::no_of_badcall = no_of_badcall; ! 122: ::no_of_undcl = no_of_undcl ; ! 123: ! 124: ::badcall = badcall ; ! 125: ::undcl = undcl ; ! 126: } ; ! 127: ! 128: ! 129: void state::init() { ! 130: ::bound = 0 ; ! 131: ::inline_restr = 0 ; ! 132: ::no_of_badcall = ::no_of_undcl = 0 ; ! 133: ::undcl = ::badcall = NULL ; ! 134: // lastline needs to be initialized probaly via a call to putline ! 135: ! 136: } ! 137: ! 138: ! 139: bit basetype::parametrized_class() ! 140: { return ((base == COBJ) && ! 141: Ptclass(Pbase(this)->b_name->tp)->class_base == uninstantiated_template_class) ; ! 142: } ! 143: ! 144: class_type_enum get_class_base (Pbase b) { ! 145: if (b->base != COBJ) error('i', "badA top ::get_class_type") ; ! 146: return Ptclass(Pbase(b)->b_name->tp)->class_base ; ! 147: } ! 148: ! 149: Ptclass get_template_class (Pbase b) { ! 150: class_type_enum t = get_class_base(b) ; ! 151: ! 152: if (! ((t == instantiated_template_class) || ! 153: (t == uninstantiated_template_class))) ! 154: error ('i', "C is not aYC") ; ! 155: ! 156: return Ptclass(Pbase(b)->b_name->tp) ; ! 157: } ! 158: ! 159: ! 160: Ptempl_inst get_templ_inst(Pbase b) { ! 161: ! 162: return (get_template_class(b))->inst ; ! 163: } ! 164: ! 165: ! 166: bit classdef::parametrized_class() ! 167: { return (class_base == uninstantiated_template_class) ; ! 168: } ! 169: ! 170: // Predicate to determine whether two classes are indeed the same. cfront ! 171: // normally relies on pointer identity, however this test is insufficient when ! 172: // parametrized class instantiationa are involved, since there are potentially ! 173: // many instances of a COBJ and CLASS for a given instantiation. ! 174: bit classdef::same_class(Pclass pc) ! 175: { ! 176: if (this == pc) return true ; ! 177: ! 178: // An intermediate test to compensate for the fact that instantiations do ! 179: // not cause a copy of the syntax tree to be generated. This kludge should ! 180: // not be necessary once the template implementation is complete, and tree ! 181: // copying is implemented. ! 182: // Later, Sam: tree copying is now implemented, i need to remove the ! 183: // following two statements and rerun the test suite. ! 184: ! 185: if ((this->class_base == template_class) && ! 186: (pc->class_base == instantiated_template_class) && ! 187: (Ptclass(pc)->inst->def_basetype()->b_name->tp == this)) ! 188: return true ; ! 189: // The inverse symmetric test ! 190: if ((pc->class_base == template_class) && ! 191: (this->class_base == instantiated_template_class) && ! 192: (Ptclass(this)->inst->def_basetype()->b_name->tp == pc)) ! 193: return true ; ! 194: ! 195: // Check whether the templates were determined to be identical after ! 196: // instantiation. ! 197: if ((pc->class_base == instantiated_template_class) && ! 198: (this->class_base == instantiated_template_class) && ! 199: (Ptclass(this)->inst->same(Ptclass(pc)->inst))) ! 200: return true ; ! 201: return false ; ! 202: } ! 203: ! 204: // determine whether two instantiations are identical; the test asumes that ! 205: // the templates have been instantiated. ! 206: bool templ_inst::same(Ptempl_inst t) ! 207: { ! 208: return ((forward && (forward == t->forward)) || ! 209: (forward == t) || (t->forward == this)) ? true : false ; ! 210: } ! 211: ! 212: ! 213: /* Template parsing support */ ! 214: ! 215: // The canonical template compilation instance. ! 216: ! 217: templ_compilation *templp ; ! 218: ! 219: templ_compilation::templ_compilation() ! 220: { templates = new table(128, NULL, NULL) ; ! 221: any_type = new basetype(ANY, NULL); ! 222: PERM(any_type) ; ! 223: } ! 224: ! 225: ! 226: // determine whether the string corresponds to a tree formal parameter ! 227: Pname templ_compilation::tree_parameter(char *s) { ! 228: for (Plist formal = params ; formal ; formal = formal->l) ! 229: if (strcmp(formal->f->string, s) == 0) { ! 230: formal->f->n_used++ ; ! 231: return formal->f ; ! 232: } ! 233: return 0 ; ! 234: } ! 235: ! 236: ! 237: // Determine whether the name refers to the canonical template class during ! 238: // syntax analysis. ! 239: Ptempl templ_compilation::is_template(Pname p) { ! 240: if (p->tp && (p->tp->base == COBJ) && ! 241: (get_class_base(Pbase(p->tp)) == template_class)) ! 242: { Pname n = templates->look(p->string, 0) ; ! 243: return (n ? Ptempl(n->tp) : 0) ; ! 244: } ! 245: return 0 ; ! 246: } ! 247: ! 248: ! 249: // determine whether the string names a template ! 250: Ptempl templ_compilation::is_template(char *s) { ! 251: Pname n = templates->look(s,0) ; ! 252: return (n ? Ptempl(n->tp) : 0) ; ! 253: } ! 254: ! 255: ! 256: // Set up the environment for parsing a template. This involves setting up a ! 257: // new nesting level into which the "type type" parameters of the template can ! 258: // be entered, so that the lexer can find them as TNAMES. The scope is ! 259: // deallocated by end(). ! 260: void templ_compilation::start() ! 261: { templp->in_progress = true ; ! 262: // Reinitialize the state. ! 263: params = param_end = NULL ; owner = NULL ; ! 264: modified_tn = 0 ; // Initialize it here, since ::collect adds new types ! 265: } ! 266: ! 267: ! 268: ! 269: // Collect each parameter as it is parsed, and add it to the list of parms. ! 270: // Validate each parameter to make sure that it is one of the acceptable ! 271: // types. ! 272: void templ_compilation::collect(TOK parm_type, Pname n) ! 273: { ! 274: switch (parm_type) { ! 275: case CLASS: ! 276: // A "type type" parameter, give it the "ANY" type normally used as a ! 277: // wildcard match internally by the compiler in cases of error. ! 278: n->tp = new basetype(ANY, 0); ! 279: n = n->tdef() ; // Set it up to be a typedef. ! 280: n->lex_level = bl_level + 1 ; // Inner scope, so restore() can hack it ! 281: n->n_template_arg = template_type_formal ; ! 282: PERM(n) ; PERM(n->tp) ; ! 283: break ; ! 284: case STATEMENT: ! 285: case EXPRESSION: ! 286: // the argument is a post-syntax expression tree ! 287: n->n_template_arg = ! 288: ((parm_type == EXPRESSION) ? ! 289: template_expr_tree_formal : template_stmt_tree_formal) ; ! 290: // canonical any_type is ok here ! 291: n->tp = any_type ; ! 292: PERM(n) ; ! 293: break ; ! 294: default: ! 295: error("theZT for%n must be CLASS, not %k", n,parm_type); ! 296: } ! 297: append_parameter(n) ; ! 298: } ! 299: ! 300: // append the "non-type" parameter to the end of the list ! 301: void templ_compilation::append_parameter(Pname n) ! 302: { ! 303: if (params){ ! 304: param_end->l = new name_list(n, NULL) ; ! 305: param_end = param_end->l ; ! 306: }else params = param_end = new name_list(n, NULL) ; ! 307: PERM(n) ; PERM(n->tp) ; ! 308: } ! 309: ! 310: ! 311: // collect non "type type" parameters. The tp field of the name ! 312: // indicates the type of the formal parameter. ! 313: void templ_compilation::collect(Pname n) ! 314: { ! 315: // The grammar alone should be sufficient to protect against undesirable ! 316: // types. Any additional checks go here. ! 317: n->n_template_arg = template_expr_formal ; ! 318: append_parameter(n) ; ! 319: } ! 320: ! 321: ! 322: ! 323: // validate the type for a non-type formal, and make it a const. ! 324: static void check_non_type_formal(Pname n) { ! 325: ! 326: switch (n->tp->base) { ! 327: case ZTYPE: ! 328: case CHAR: ! 329: case SHORT: ! 330: case INT: ! 331: case LONG: ! 332: case FLOAT: ! 333: case DOUBLE: ! 334: case FIELD: ! 335: case EOBJ: ! 336: case COBJ: ! 337: case TYPE: ! 338: case ANY: ! 339: { // a basetype node ! 340: TOK bad_base = 0 ; ! 341: ! 342: if (Pbase(n->tp)->b_volatile) ! 343: bad_base = VOLATILE ; ! 344: if (Pbase(n->tp)->b_typedef) ! 345: bad_base = TYPEDEF ; ! 346: if (Pbase(n->tp)->b_inline) ! 347: bad_base = INLINE ; ! 348: if (Pbase(n->tp)->b_virtual) ! 349: bad_base = VIRTUAL ; ! 350: if (bad_base) ! 351: error ("bad %k declarator forY formal %n", bad_base,n); ! 352: ! 353: Pbase b = new basetype(0, 0) ; ! 354: *b= *Pbase(n->tp) ; ! 355: b->b_const = 1 ; ! 356: n->tp = b ; ! 357: break ; ! 358: } ! 359: case PTR: ! 360: { Pptr b = new ptr(0,0) ; ! 361: *b = *Pptr(n->tp) ; ! 362: ! 363: b->rdo = 1; ! 364: n->tp = b ; ! 365: break ; ! 366: } ! 367: case RPTR: ! 368: case VEC: ! 369: break; // constant by definition ! 370: default: ! 371: error ("badZT %t for formalZ %n", n->tp, n); ! 372: } ! 373: return ; ! 374: } ! 375: ! 376: ! 377: ! 378: // The template parameters if any, have been parsed. Member function templates ! 379: // may choose to default their template arguments to the class arguments, if ! 380: // so, make the defaulting happen. ! 381: void templ_compilation::enter_parameters() ! 382: { ! 383: for (Plist list = params ; list ; list = list->l) { ! 384: Pname n = list->f ; ! 385: switch(n->n_template_arg) { ! 386: case template_type_formal: ! 387: // Set them up for restoration ! 388: modified_tn = new name_list(n,modified_tn); ! 389: // Bring the names out of hiding ! 390: n->n_key = 0 ; ! 391: break ; ! 392: case template_expr_formal: ! 393: check_non_type_formal(n) ; ! 394: n->tp->dcl(gtbl) ; ! 395: break ; ! 396: case template_expr_tree_formal: ! 397: case template_stmt_tree_formal: ! 398: // simply note it, the guts of the processing takes place when the ! 399: // copy of the syntax tree is generated. ! 400: break ; ! 401: default: ! 402: error ('i', "badY formal" ) ; ! 403: } ! 404: } ! 405: // Save away the list of modified_tn, since the body processing will clobber ! 406: // it. ! 407: param_tn = modified_tn ; ! 408: modified_tn = 0 ; ! 409: } ! 410: ! 411: ! 412: ! 413: // Resolve the forward declaration of a template to its true definition. The ! 414: // template and class type data structures must be reused, since there may be ! 415: // outstanding references to them. ! 416: void templ::resolve_forward_decl(Plist params, Pclass c) { ! 417: check_formals(params) ; ! 418: formals = params ; ! 419: defined = true ; ! 420: definition_number = ++ definition_tick ; ! 421: members = c->mem_list ; ! 422: } ! 423: ! 424: void templ::instantiate_forward_decl() { ! 425: for (Ptempl_inst i = insts ; i ; i = i->next) ! 426: if (Ptclass(Pbase(i->tname->tp)->b_name->tp)->class_base == ! 427: instantiated_template_class && ! 428: ! i->forward) ! 429: { // reinstantiate it ! 430: i->instantiate(true) ; ! 431: } ! 432: } ! 433: ! 434: ! 435: ! 436: // verify thet the qualifier used to declare the member function matches the ! 437: // template arguments in name, ie. ! 438: // template <class P, class Q, ..> c<P,Q,..>::member_function() {} ! 439: // match it's Ps and Qs. ! 440: bool templ_inst::check_qualifier(Plist formals) ! 441: { ! 442: Pexpr actual = actuals ; ! 443: for (Plist formal = formals ; formal && actual ; formal = formal->l, ! 444: actual = actual->e2) ! 445: ! 446: switch (formal->f->n_template_arg) { ! 447: ! 448: case template_type_formal: ! 449: { Pbase b = Pbase(actual->e1->tp) ; ! 450: ! 451: if (! ((b->base == TYPE) && ! 452: (b->b_name->base == TNAME) && ! 453: (strcmp (Pname(b->b_name)->string, formal->f->string) == 0))) ! 454: return false ; ! 455: break ; ! 456: } ! 457: ! 458: case template_expr_formal: ! 459: if (! ((actual->e1->base == NAME) && ! 460: (strcmp(Pname(actual->e1)->string, formal->f->string) == 0))) ! 461: return false ; ! 462: break ; ! 463: ! 464: case template_expr_tree_formal: ! 465: case template_stmt_tree_formal: ! 466: default: ! 467: error ('i',"badY formal") ; ! 468: } ! 469: ! 470: return true ; ! 471: } ! 472: ! 473: ! 474: // make the class template visible when compiling the template class ! 475: // defintion, so that it can be refernced while compiling the class body. ! 476: void templ_compilation::introduce_class_templ(Pname namep) ! 477: { ! 478: owner = is_template(namep) ; ! 479: // create a template definition if one did not already exist, due to a ! 480: // forward declaration ! 481: if (!owner){ ! 482: owner = new templ(params, namep) ; ! 483: Pname lookup_name = templp->templates->insert(new name(namep->string), 0); ! 484: lookup_name->tp = Ptype(owner) ; // lie, to permit use of the table ! 485: } ! 486: } ! 487: ! 488: ! 489: // The body of the template has been parsed. Finish the definition of the ! 490: // template class. ! 491: void templ_compilation::end(Pname p) ! 492: { ! 493: bool forward_definition = false ; ! 494: // Restore the name environment to the state before the template parameters ! 495: // were processed. ! 496: modified_tn = param_tn ; ! 497: restore() ; ! 498: modified_tn = 0 ; ! 499: ! 500: if (curr_tree_template) { ! 501: // create an expression template ! 502: new tree_template(curr_tree_template, ! 503: p->string, params, p->n_initializer, templ_refs) ; ! 504: }else { ! 505: if (!p->tp) { ! 506: error ("aC, orMF definition wasX") ; ! 507: return ; ! 508: } ! 509: switch(p->tp->base){ ! 510: ! 511: case CLASS: ! 512: // Create the template type to represent the parsed template, and enter it ! 513: // into the global table. This is achieved simply by modifying the TNAME ! 514: // that was entered into ktbl to represent the class definition. ! 515: Pname namep = ktbl->look(p->string, 0) ; ! 516: ! 517: // check for nested definitions, they aren't supported currently. 2.1 is ! 518: // a good time to start supporting them, since they are nested for real. ! 519: for (Pname nn = Pclass(p->tp)->mem_list ; nn ; nn = nn->n_list) ! 520: switch (nn->base) { ! 521: case NAME: ! 522: switch(nn->tp->base) { ! 523: case CLASS: ! 524: error("CD %s not permitted within a ZizedC", nn->string) ; ! 525: break ; ! 526: case ENUM: ! 527: error("enumD %s not permitted within a ZizedC", nn->string) ; ! 528: break ; ! 529: } ! 530: break ; ! 531: ! 532: case TNAME: ! 533: error("typedef %s not permitted within a ZizedC", nn->string) ; ! 534: break ; ! 535: } ! 536: ! 537: owner = is_template(namep); ! 538: if (owner) { ! 539: Pclass c = Pclass(owner->basetype()->b_name->tp) ; ! 540: // ignore it, if it is a forward declaration following a real ! 541: // definition ! 542: if (owner->defined && (Pclass(p->tp)->mem_list != owner->members)) ! 543: error("YC %s multiply defined", p->string) ; ! 544: ! 545: forward_definition=bool((c->defined & DEF_SEEN) && (!owner->defined)); ! 546: if (forward_definition) owner->resolve_forward_decl(params, c) ; ! 547: }else ! 548: // a forward declaration ! 549: introduce_class_templ(namep) ; ! 550: ! 551: if (templ_refs) owner->templ_refs = templ_refs ; ! 552: break ; ! 553: ! 554: case FCT: ! 555: { Pname qual = p->n_qualifier ; ! 556: // the function must belong to a declared template class ! 557: if (! qual) { ! 558: error('s', "onlyYMFs may beZized currently") ; ! 559: return ; ! 560: } ! 561: if (qual->tp && (qual->tp->base == COBJ)) ! 562: switch (get_class_base(Pbase(qual->tp))) { ! 563: case uninstantiated_template_class: ! 564: owner = Ptclass(Pbase(qual->tp)->b_name->tp)->inst->def ; ! 565: // verify that the formals specified, match the template formals ! 566: // in name, note that the length was already matched when the ! 567: // instantiation was generated. ! 568: if (!get_template_class ! 569: (Pbase(qual->tp))->inst->check_qualifier(params)) ! 570: error ("QrZs must match theY formals") ; ! 571: break ; ! 572: case template_class: ! 573: // the template reference was without any of the formals ! 574: owner = is_template(qual) ; ! 575: if (! owner->has_tree_expr_formals()) ! 576: error('w',"Qr %n for %n must specifyYZs", qual, p) ; ! 577: break ; ! 578: default: ! 579: error ("Qr %n for %n wasn't aYC", qual, p) ; ! 580: return ; ! 581: } ! 582: Pfunt ft= owner->collect_function_member(p) ; ! 583: if (! Pfct(p->tp)->body) ! 584: error ("theYFM %n must have a body", p) ; ! 585: ft->templ_refs = templ_refs ; ! 586: ft->formals = params ; ! 587: owner->check_formals(params) ; ! 588: break ; ! 589: } ! 590: default: error ("C, or MF definitionX.") ; ! 591: } ! 592: } ! 593: // Note the template references from this definition ! 594: ! 595: clear_ref_templ() ; ! 596: param_end = params = 0; // Indicates the end of template processing. ! 597: curr_tree_template = 0 ; ! 598: ! 599: if (forward_definition) owner->instantiate_forward_decl() ; ! 600: owner = 0 ; ! 601: } ! 602: ! 603: ! 604: ! 605: ! 606: // Clear the list of templates referenced during the syntax analysis of a top ! 607: // level definition. Note that since this list is produced during syntax ! 608: // analysis, it does not recognize instantiations that may actualy turn out to ! 609: // be identical at instantiation after the substitution of actual parameters. ! 610: // Thus, the list may be longer than it would be after actual argument ! 611: // substitution. ! 612: void templ_compilation::clear_ref_templ() { ! 613: for (Pcons p = templ_refs ; p ; p = p->cdr) ! 614: Ptempl_inst(p->car)->refp = false ; ! 615: templ_refs = 0 ; last_cons = 0 ; ! 616: } ! 617: ! 618: ! 619: // Instantiate templates that were referenced by a non-template definition, ! 620: // after syntax analysis has been completed on it. ! 621: void templ_compilation::instantiate_ref_templ() { ! 622: for (Pcons p = templ_refs ; p ; p = p->cdr) ! 623: Ptempl_inst(p->car)->instantiate() ; ! 624: clear_ref_templ() ; ! 625: } ! 626: ! 627: ! 628: ! 629: ! 630: // Compile all template member body instantiations. Set in motion the ! 631: // compilation of the graph of instantiation bodies. Note that compilation of ! 632: // a body may in turn initiate the instantiation of templates that had not ! 633: // previously been instantiated. ! 634: void templ_compilation::end_of_compilation() { ! 635: bool change = false ; ! 636: do { ! 637: change = false ; ! 638: for (Ptempl p = list ; p ; p = p->next) ! 639: change = ( change | p->instantiate_bodies() ? true : false); ! 640: } while (change) ; ! 641: } ! 642: ! 643: ! 644: // A predicate to validate that a tname without template parameters is legit ! 645: // in the scope, ie. that it does not need actual template arguments. ! 646: // Currently, a tname without parameters is ok within the class definition, ! 647: // but parameters are required within the member definition. They should not ! 648: // be required within the member function either to be consonance with their ! 649: // use in the class definition. ! 650: Pname templ_compilation::check_tname(Pname p) { ! 651: Ptempl t = is_template(p) ; ! 652: ! 653: if (p->n_template_arg) p->n_used++ ; ! 654: if (!t) return p ; ! 655: if (in_progress && ((owner && (owner->namep == p)) || ! 656: (!owner && t->basetype()->b_name->tp == ccl))) ! 657: return p ; ! 658: error ("%n needs Y instantiationAs.", p) ; ! 659: return p ; ! 660: } ! 661: ! 662: ! 663: // This function determine when the parameters specified to a template are ! 664: // redundant, and really refer to the current template class. Thus, ! 665: // ! 666: // template c<class p1, class p2> c<p1,p2>::foo { ... } ; ! 667: // has the redundant template specification c<p1, p2> and can simply be a ! 668: // reference to a "c" instead, ! 669: bool templ_compilation::current_template(Pname p, Pexpr actuals) { ! 670: if (in_progress && ! 671: ((owner && (owner->namep == p)) || ! 672: (!owner && ((p->tp->base == COBJ) && ! 673: (Pbase(p->tp)->b_name->tp == ccl))))) ! 674: { // Check whether the formal and actual types are identical ! 675: Pexpr actual = actuals; ! 676: for (Plist formal = params ; formal && actual ; formal = formal->l, ! 677: actual = actual->e2) ! 678: if ((formal->f->tp == actual->e1->tp) || ! 679: ((actual->e1->tp && (actual->e1->tp->base == TYPE)) && ! 680: (Pbase(actual->e1->tp)->b_name->tp == formal->f->tp))) ! 681: continue ; ! 682: else break ; ! 683: if (!formal && !actual) return true ; ! 684: } ! 685: return false ; ! 686: } ! 687: ! 688: ! 689: ! 690: // Add a new member function to the list of functions for the template class. ! 691: Pfunt templ::collect_function_member(Pname fname) { ! 692: PERM(fname) ; PERM(fname->tp) ; PERM(Pfct(fname->tp)->body) ; ! 693: return new function_template (*this, templp->params, fname) ; ! 694: } ! 695: ! 696: ! 697: // Check the formals specified for a member function or a forward definition ! 698: // of a class, against the formals for the class. ! 699: void basic_template::check_formals(Plist f2) { ! 700: ! 701: for (Plist f1 = formals; f1 && f2 ; f1 = f1->l, f2 = f2->l) ! 702: if (f1->f->base != f2->f->base) ! 703: switch (f1->f->n_template_arg) { ! 704: case template_type_formal: ! 705: error ("Y formalZ mismatch,\ ! 706: %n must be a type formal parameter.", f2->f) ; ! 707: break ; ! 708: case template_expr_formal: ! 709: error ("formalZ mismatch, %n must be aZ ofT %t", ! 710: f2->f, f2->f->tp) ; ! 711: break ; ! 712: case template_expr_tree_formal: ! 713: case template_stmt_tree_formal: ! 714: error ("formalZ mismatch, %n must be anE formalZ", ! 715: f2->f) ; ! 716: break ; ! 717: default: ! 718: error ("formalZ mismatch betweenC formal: %n andM formal: %n", f1->f, f2->f) ; ! 719: }else if (f1->f->n_template_arg == template_expr_formal) { ! 720: // the types should be identical ! 721: if (f1->f->tp->check(f2->f->tp, 0) == 1) ! 722: error ("type mismatch betweenM formal %n, andC formal %n", f2->f, f1->f) ; ! 723: } ! 724: if (f1) ! 725: error ("insufficient formalZs,CZ parameter %n onwards are missing", f1->f) ; ! 726: if (f2) ! 727: error ("excess formalZs,Z %n onwards not defined forC", f2->f) ; ! 728: ! 729: } ! 730: ! 731: // predicate to determine whether the template has expression tree formals ! 732: bool templ::has_tree_expr_formals() { ! 733: ! 734: for (Plist formal= formals; formal ; formal = formal->l) ! 735: if (formal->f->n_template_arg == template_expr_tree_formal) ! 736: return true ; ! 737: ! 738: return false ; ! 739: } ! 740: ! 741: ! 742: // Check that those formals that require class actual arguments, due to their ! 743: // use in member function bodies get them. ! 744: bool basic_template::check_constraints(Pexpr actual) ! 745: ! 746: { ! 747: bool ret = true ; ! 748: ! 749: for (Plist formal = formals ; formal && actual ; formal = formal->l, ! 750: actual = actual->e2) ! 751: if ((formal->f->n_template_arg == template_type_formal) && ! 752: formal->f->n_template_formal_must_be_class) { ! 753: ! 754: Pname n = Pname(actual->e1) ; ! 755: ! 756: if (n && n->tp && n->tp->is_cl_obj()) ! 757: continue ; ! 758: error("expected aCT actual, not %t, for the \"TT\" formal %s", ! 759: n->tp, formal->f->string); ! 760: ret = false ; ! 761: } ! 762: return ret ; ! 763: } ! 764: ! 765: ! 766: // Check actual template arguments, against the formals. ! 767: bool templ::check_actual_args(Pexpr actual) ! 768: { ! 769: for (Plist formal = formals ; formal && actual ; formal = formal->l, ! 770: actual = actual->e2) ! 771: switch (formal->f->n_template_arg) { ! 772: case template_type_formal: ! 773: { ! 774: // A "type type" parameter, any actual type that was accepted by the ! 775: // parse is acceptable here, just make sure that it is indeed a type. ! 776: // If it was parsed as a type, the grammar should have created a name ! 777: // node, and attached the type to it, having marked the name as a ! 778: // template_actual_arg_dummy. ! 779: ! 780: Pname n = Pname(actual->e1) ; ! 781: ! 782: if (!((n->base == NAME) && ! 783: (n->n_template_arg == template_actual_arg_dummy))) { ! 784: error ("Y %s A mismatch, the Y formal:%n\ ! 785: required aT actualZ.", namep->string, formal->f) ; ! 786: // recover from the error with a safe expression ! 787: n = new name("") ; ! 788: n->tp = any_type ; ! 789: actual->e1 = n ; ! 790: } ! 791: if ((formal->f->n_template_formal_must_be_class) && ! 792: !(n->tp && n->tp->is_cl_obj())) ! 793: error("expected aCT actual, not %t, for the \"TT\" formal %s", ! 794: n->tp, formal->f->string) ; ! 795: break ; ! 796: } ! 797: case template_expr_formal: ! 798: // checking can only be done at instantiation, so postpone it ! 799: break ; ! 800: case template_expr_tree_formal: ! 801: case template_stmt_tree_formal: ! 802: // anything is acceptable, it is a case of "implementor beware". Any ! 803: // illegalities will only be detected when dcl processing takes place. ! 804: break ; ! 805: default: ! 806: error ('i',"badY formal") ; ! 807: } ! 808: // If we provide for optionals, this is where the processing should get done. ! 809: if (formal) ! 810: error ("too fewAs supplied forY %s", namep->string) ; ! 811: if (actual && actual->e1) { ! 812: error ("too manyAs supplied forY %s", namep->string) ; ! 813: } ! 814: return bool(~(formal || actual)) ; ! 815: } ! 816: ! 817: ! 818: ! 819: ! 820: // Append to the list of references. ! 821: void templ_compilation::append_ref(Ptempl_inst ref) ! 822: { cons *p = new cons(ref,0) ; ! 823: if (last_cons) ! 824: last_cons->cdr = p ; ! 825: else templ_refs = p ; ! 826: last_cons = p ; ! 827: } ; ! 828: ! 829: ! 830: // Note the reference by a definition to the template, so that the template ! 831: // can be instantiated before the definition is processed. ! 832: Ptempl_inst templ_inst::note_ref() ! 833: { if ((! refp)) { ! 834: refp = true ; ! 835: templp->append_ref(this) ; ! 836: } ! 837: return this ; ! 838: } ! 839: ! 840: ! 841: ! 842: // Get an instantiation for the template with the given set of actuals. If one ! 843: // exists, return it, otherwise create a new one. ! 844: Ptempl_inst templ::get_inst(Pexpr actuals, Ptempl_inst exclude) ! 845: { Ptempl_inst inst = get_match(actuals, exclude, false) ; ! 846: ! 847: return (inst ? inst : new templ_inst(actuals, this))->note_ref() ; ! 848: } ! 849: ! 850: ! 851: // Find an instantiation that has the same set of actuals, exclude the ! 852: // instantaition passed in from the set of candidates ! 853: Ptempl_inst templ::get_match(Pexpr actuals, ! 854: Ptempl_inst exclude, // don't match this one ! 855: // Only instantiated templates match ! 856: bool match_instantiated_only) ! 857: { ! 858: for (Ptempl_inst p = insts ; p ; p = p->next) ! 859: if ((p != exclude) && ! 860: (p->actuals_match(actuals)) && ! 861: (match_instantiated_only ? ! 862: (Pclass(Pbase(p->tname->tp)->b_name->tp)->class_base == ! 863: instantiated_template_class) ! 864: : true)) ! 865: return (p->forward ? p->forward : p) ; ! 866: return NULL ; ! 867: } ! 868: ! 869: ! 870: // provides the basetype created for a given set of actuals. ! 871: Pbase templ::inst_basetype(Pexpr actuals) ! 872: { ! 873: return (check_actual_args(actuals) ? ! 874: Pbase(get_inst(actuals)->tname->tp) : basep) ; ! 875: } ! 876: ! 877: ! 878: // Validate that the name denotes a parametrized type, and prodouce a TNAME ! 879: // for the instantiation. ! 880: Pname parametrized_typename (Pname p, Pexpr actuals) ! 881: { ! 882: Ptempl t = templp->is_template(p) ; ! 883: // A template instantiation with redundant actuals identical to the formals ! 884: // of the current template ! 885: if (templp->current_template(p, actuals)) return p ; ! 886: if (t) { ! 887: Pname tname = t->typename(actuals) ; ! 888: return (tname ? tname : p) ; ! 889: } ! 890: error ("%n hasTAs but is not aZizedC", p) ; ! 891: return p ; ! 892: } ! 893: ! 894: ! 895: Pbase parametrized_basetype (Pname p, Pexpr actuals) ! 896: { Ptempl t = templp->is_template(p) ; ! 897: // A template instantiation with redundant actuals identical to the formals ! 898: // of the current template ! 899: if (templp->current_template(p, actuals)) return Pbase(p->tp) ; ! 900: if (t) return t->inst_basetype(actuals) ; ! 901: error ("%n is not aZizedC", p) ; ! 902: return new basetype(TYPE, p); ! 903: } ! 904: ! 905: ! 906: // Similar primitive for obtaining the typename associated with an ! 907: // instantiation. ! 908: Pname templ::typename(Pexpr actuals) ! 909: { ! 910: return (check_actual_args(actuals) ? get_inst(actuals)->tname : 0) ; ! 911: } ! 912: ! 913: // predicate to get past all the type nodes ! 914: static Ptype real_type (Ptype t) ! 915: { ! 916: while (t->base == TYPE) t = Pbase(t)->b_name->tp ; ! 917: return t ; ! 918: } ! 919: ! 920: static int expr_match(Pexpr a1, Pexpr a2) ; ! 921: ! 922: // Check whether the actuals provided match the actuals for this instantiation. ! 923: // The actuals match the formals, iff they are the same type or parametrized ! 924: // type. ! 925: bool templ_inst::actuals_match(Pexpr check_actuals) ! 926: { Pexpr ae1, ae2 ; // the cons cells ! 927: Plist formal = def->formals ; ! 928: ! 929: // The lists should be the same length, since check_actuals will have taken ! 930: // appropriate action. ! 931: for (ae1=actuals, ae2=check_actuals ; formal && ae1 && ae2 ; ! 932: ae1=ae1->e2, ae2=ae2->e2, formal = formal->l) ! 933: ! 934: switch (formal->f->n_template_arg) { ! 935: ! 936: case template_type_formal: ! 937: { Ptype t1 = ae1->e1->tp, t2 = ae2->e1->tp ; ! 938: if (t1->check(t2,255) == 1) ! 939: return false ; ! 940: break ; ! 941: } ! 942: case template_expr_formal: ! 943: if (! expr_match(ae1->e1, ae2->e1)) return false ; ! 944: break ; ! 945: ! 946: case template_expr_tree_formal: ! 947: case template_stmt_tree_formal: ! 948: // these are internal instantiations and consequently never match ! 949: return false ; ! 950: ! 951: default: ! 952: error ('i', "bad template formal") ; ! 953: } ! 954: return true ; ! 955: } ! 956: ! 957: ! 958: extern char emode ; ! 959: ! 960: ! 961: // This set of overloaded fuctions are used to accumulate name strings ! 962: void stradd(char *&target, char *source) { ! 963: while (*target++ = *source++) ; ! 964: target-- ; ! 965: } ! 966: ! 967: void stradd(char *&p, long i) { ! 968: if (!emode) { ! 969: *p++ = 'L' ; ! 970: } ! 971: char s[16] ; ! 972: ! 973: sprintf(s,"%ld", i) ; ! 974: stradd(p,s) ; ! 975: } ! 976: ! 977: void stradd(char *&p, Pname n) { ! 978: if (!emode){ ! 979: char s[256] ; ! 980: ! 981: sprintf(s,"%d", strlen(n->string)) ; ! 982: stradd(p,s) ; ! 983: } ! 984: stradd(p, n->string) ; ! 985: } ! 986: ! 987: ! 988: ! 989: // produce a unique string suitable for use within a name; if in emode ie. ! 990: // printing in the context of an error, print a pretty name instead. ! 991: char * mangled_expr(char *p, Pexpr e, bool mangle_for_address = false) ! 992: { ! 993: static int mangle_address = 0 ; ! 994: if (e == 0) return p; ! 995: ! 996: switch (e->base) { ! 997: case ADDROF: ! 998: case G_ADDROF: ! 999: // unary using e2 ! 1000: // rely on the ! 1001: mangle_address++ ; ! 1002: p = mangled_expr(p, e->e2) ; ! 1003: mangle_address -- ; ! 1004: break ; ! 1005: ! 1006: case NAME: ! 1007: if (mangle_address || mangle_for_address) ! 1008: stradd(p, Pname(e)) ; ! 1009: else if (Pname(e)->n_evaluated) ! 1010: stradd(p, Pname(e)->n_val) ; ! 1011: else if (Pname(e)->n_initializer) ! 1012: p = mangled_expr(p, Pname(e)->n_initializer, mangle_for_address) ; ! 1013: else error ('i', "couldn't mangle %n", e) ; ! 1014: break ; ! 1015: ! 1016: case IVAL: ! 1017: stradd(p, ((ival *)e)->i1) ; ! 1018: break ; ! 1019: ! 1020: case CAST: ! 1021: { // an IVAL hiding below the cast ? ! 1022: if (e->e1->base == IVAL) ! 1023: stradd(p, ((ival *)e->e1)->i1) ; ! 1024: else error ('i', "unexpected cast") ; ! 1025: break ; ! 1026: } ! 1027: case ICON: ! 1028: case CCON: ! 1029: case FCON: ! 1030: *p++ = 'L' ; ! 1031: strcpy(p, e->string) ; ! 1032: // Sam: there needs to be a better encoding scheme, but it can wait. ! 1033: if (!emode) ! 1034: while (*p) ! 1035: if (! (isalnum(*p))) ! 1036: switch(*p) { ! 1037: case '+': ! 1038: *p++ = 'p' ; ! 1039: break ; ! 1040: ! 1041: case '-': ! 1042: *p++ = 'm' ; ! 1043: break ; ! 1044: ! 1045: case '.': ! 1046: *p++ = 'D' ; ! 1047: break ; ! 1048: ! 1049: case 'e': ! 1050: *p++ = 'E' ; ! 1051: break ; ! 1052: ! 1053: default: ! 1054: error ('i', "bad character in constant") ; ! 1055: break ; ! 1056: } else p++ ; ! 1057: break ; ! 1058: ! 1059: case ZERO: ! 1060: *p++ = '0' ; ! 1061: break ; ! 1062: ! 1063: default: ! 1064: error ('i', "can't mangle %k", e->base) ; ! 1065: } ! 1066: return p ; ! 1067: } ! 1068: ! 1069: // this function is invoked once at the top level ! 1070: char *mangled_expr(char *p, Pname n) { ! 1071: if (n->n_evaluated) { ! 1072: stradd(p, n->n_val) ; ! 1073: return p ; ! 1074: } ! 1075: return mangled_expr(p, n->n_initializer, ! 1076: (real_type(n->tp)->base == PTR ? true : false)) ; ! 1077: } ! 1078: ! 1079: // Generate a template instantiation name suitable for printing when it is ! 1080: // presented to the user. ! 1081: void templ_inst::print_pretty_name() ! 1082: { ! 1083: extern char emode ; ! 1084: ! 1085: fprintf(out_file, " %s<", (def->namep ? def->namep->string : "?")) ; ! 1086: Plist formal = inst_formals ; ! 1087: emode ++ ; // so that dcl_print generates c++ rather than c names ! 1088: ! 1089: for (Pexpr ae1=actuals; formal && ae1 ; ae1=ae1->e2, formal = formal->l) { ! 1090: switch (formal->f->n_template_arg) { ! 1091: case template_type_formal: ! 1092: ae1->e1->tp->dcl_print(0) ; ! 1093: break ; ! 1094: case template_expr_formal: ! 1095: { char buff[256] ; ! 1096: ! 1097: mangled_expr(buff, ae1->e1) ; ! 1098: fprintf(out_file, "%s", buff) ; ! 1099: break ; ! 1100: } ! 1101: case template_expr_tree_formal: ! 1102: case template_stmt_tree_formal: ! 1103: // doesn't participate in the name generation ! 1104: break ; ! 1105: default: ! 1106: error ('i', "unexpected formal") ; ! 1107: } ! 1108: ! 1109: // this comma is unfortunately misplaced, since it follows a space printed ! 1110: // out by dcl_print ! 1111: if (formal->l) fprintf(out_file, ", ") ; ! 1112: } ! 1113: fprintf(out_file, ">") ; ! 1114: emode -- ; ! 1115: } ! 1116: ! 1117: ! 1118: ! 1119: // there are different representations for ICON based upon whether it has been ! 1120: // evaluated. ! 1121: int check_for_const(Pexpr a1, Pexpr a2) { ! 1122: Neval = 0 ; ! 1123: if ((a1->base == NAME) && ! 1124: ((a2->base == ICON) || (a2->base == IVAL) || (a2->base == ZERO))) ! 1125: { Pname n = Pname(a1) ; ! 1126: return (n->n_evaluated && (n->n_val == a2->eval())) ; ! 1127: }else if (((a1->base == ICON) || (a1->base == IVAL) || (a1->base == ZERO)) ! 1128: && (a2->base == NAME)) ! 1129: { Pname n = Pname(a2) ; ! 1130: return (n->n_evaluated && (n->n_val == a1->eval())) ; ! 1131: } ! 1132: return false ; ! 1133: } ! 1134: ! 1135: ! 1136: // get past the template parameter names to get the the real expression ! 1137: static Pexpr real_expression(Pexpr e) ! 1138: { ! 1139: while (e && (e->base == NAME) && ! 1140: (Pname(e)->n_template_arg == template_expr_formal) && ! 1141: (! Pname(e)->n_evaluated) && Pname(e)->n_initializer) ! 1142: e = Pname(e)->n_initializer ; ! 1143: return e ; ! 1144: } ! 1145: ! 1146: ! 1147: // determine whether two expressions supplied as actual arguments to ! 1148: // a "template_expr_formal" formal argument match. ! 1149: static int expr_match(Pexpr a1, Pexpr a2) ! 1150: { ! 1151: static int addr_of = 0 ; ! 1152: ! 1153: a1 = (addr_of ? a1 : real_expression(a1)) ; ! 1154: a2 = (addr_of ? a2 : real_expression(a2)) ; ! 1155: ! 1156: if (a1 == a2) return true; ! 1157: ! 1158: // ! 1159: if (a1->base != a2->base) return check_for_const(a1, a2) ; ! 1160: ! 1161: switch (a1->base) { ! 1162: case QUEST: ! 1163: // a ternary operator ! 1164: return ( expr_match(a1->cond, a2->cond) && ! 1165: expr_match(a1->e1, a2->e1) && ! 1166: expr_match(a1->e2, a2->e2)) ; ! 1167: ! 1168: case PLUS: case MINUS: case MUL: case DIV: case MOD: ! 1169: case ER: case OR: case ANDAND: case OROR: ! 1170: case LS: case RS: ! 1171: case EQ: case NE: case LT: case LE: case GT: case GE: ! 1172: // binary operator ! 1173: return (expr_match(a1->e1, a2->e1) && ! 1174: expr_match(a1->e2, a2->e2)) ; ! 1175: case UMINUS: case UPLUS: ! 1176: case NOT: case COMPL: ! 1177: return (expr_match(a1->e2, a2->e2)) ; ! 1178: case ADDROF: ! 1179: { ! 1180: // unary using e2 ! 1181: addr_of ++ ; ! 1182: int result = (expr_match(a1->e2, a2->e2)) ; ! 1183: addr_of -- ; ! 1184: return result ; ! 1185: } ! 1186: case CAST: ! 1187: return (expr_match(a1->e1, a2->e1)) ; ! 1188: case NAME: ! 1189: if (! addr_of) { ! 1190: Pname n1 = Pname(a1), n2 = Pname(a2) ; ! 1191: ! 1192: if ((n1->n_evaluated) && n2->n_evaluated && (n1->n_val == n2->n_val)) ! 1193: return true ; ! 1194: if (n1->n_initializer && (! n2->n_initializer)) ! 1195: return check_for_const(n2, n1->n_initializer) ; ! 1196: if (n2->n_initializer && (! n1->n_initializer)) ! 1197: return check_for_const(n1, n2->n_initializer) ; ! 1198: if (n1->n_initializer && n2->n_initializer) ! 1199: return expr_match(n1->n_initializer, n2->n_initializer) ; ! 1200: } ! 1201: return false ; ! 1202: case DOT: ! 1203: return (expr_match(a1->e1, a2->e1)) ; ! 1204: case REF: ! 1205: return (expr_match(a1->e1, a2->e1)) ; ! 1206: case IVAL: ! 1207: return (ival *)a1->i1 == (ival *)a2->i1 ; ! 1208: case ICON: ! 1209: case CCON: ! 1210: case FCON: ! 1211: case STRING: ! 1212: return (strcmp (a1->string, a2->string) == 0) ; ! 1213: case ZERO: ! 1214: return true ; ! 1215: case SIZEOF: ! 1216: { long l1 = a1->eval(), l2 = a2->eval() ; ! 1217: return (l1 == l2) ; ! 1218: } ! 1219: } ! 1220: return false ; ! 1221: } ! 1222: ! 1223: ! 1224: static char * non_type_argument_signature(Pexpr e, char *p) { ! 1225: p = e->tp->signature(p) ; ! 1226: return mangled_expr(p, e) ; ! 1227: } ! 1228: ! 1229: ! 1230: ! 1231: // generate array suffix information for an array signature. cfront does not ! 1232: // normally generate this as part of the type signature, since it only deals ! 1233: // with argument signatures, and arrays can't be arguments. ! 1234: static void add_array_type_suffix(char *&s, Ptype t) { ! 1235: t = real_type(t) ; ! 1236: if (t->base == VEC) { ! 1237: Pvec v = Pvec(t); ! 1238: int dim; ! 1239: char a[32] ; ! 1240: Neval = 0 ; ! 1241: if(v->dim == 0) ! 1242: dim = v->size / v->typ->tsizeof(); ! 1243: else dim = (int)v->dim->eval(); ! 1244: sprintf(a, "A%d", dim) ; ! 1245: stradd(s,a) ; ! 1246: add_array_type_suffix(s, Pvec(t)->typ); ! 1247: } ! 1248: } ! 1249: ! 1250: ! 1251: ! 1252: // Generate a mangled template instantiation name. The syntax of as template ! 1253: // mangled class name is of the form: ! 1254: // original_name__<argument type signatures>__unique_id ! 1255: // Each non-type argument is replaced by a unique id. ! 1256: char *templ_inst::mangled_name(char *ip) ! 1257: { static tree_formal_id = 0 ; ! 1258: ! 1259: char *start = ip ; ! 1260: ip = start ; ! 1261: strcpy(ip, (def->namep ? def->namep->string : "?")) ; ! 1262: ip= start + strlen(start) ; ! 1263: stradd(ip, "__pt__") ; ! 1264: ! 1265: { ! 1266: char a [max_string_size], *p = a ; ! 1267: ! 1268: Plist formal = inst_formals ; ! 1269: ! 1270: for (Pexpr ae1=actuals ; ae1 ; ae1=ae1->e2, formal = formal->l) ! 1271: switch (formal->f->n_template_arg) { ! 1272: case template_expr_formal: ! 1273: *p++ = 'X' ; ! 1274: // the formal must have been bound ! 1275: p = non_type_argument_signature(formal->f, p) ; ! 1276: break ; ! 1277: ! 1278: case template_type_formal: ! 1279: p = ae1->e1->tp->signature(p) ; ! 1280: add_array_type_suffix(p,ae1->e1->tp) ; ! 1281: break ; ! 1282: ! 1283: case template_expr_tree_formal: ! 1284: case template_stmt_tree_formal: ! 1285: *p++ = 'Y' ; ! 1286: stradd(p, tree_formal_id++) ; ! 1287: break ; ! 1288: ! 1289: default: ! 1290: error ("bad template formal:%d", formal->f->base) ; ! 1291: break ; ! 1292: } ! 1293: ! 1294: *p = 0 ; ! 1295: sprintf(ip, "%d_", strlen(a)+1) ; ! 1296: ip = start + strlen(start) ; ! 1297: strcpy(ip,a) ; ! 1298: } ! 1299: ! 1300: return start ; ! 1301: } ! 1302: ! 1303: ! 1304: ! 1305: // The C compiler barfs when it is passed on through C++ as an automatic ! 1306: // variable ! 1307: const char leader[]= "\t" ; ! 1308: ! 1309: // Explain the location of an instantiation in greater detail, since it may be ! 1310: // far removed from it's textual definition. ! 1311: void templ_inst::print_error_loc() { ! 1312: if (! head) return ; // No active instantiations ! 1313: ! 1314: extern void print_loc() ; ! 1315: state current_state ; ! 1316: char buffer[max_string_size] ; ! 1317: ! 1318: for (int i = 0 ; i < max_string_size; i++) buffer[i] = 0 ; ! 1319: ! 1320: current_state.save() ; ! 1321: fprintf (out_file, "%sanomaly detected during the instantiation of", ! 1322: leader) ; ! 1323: print_pretty_name() ; ! 1324: fprintf(out_file, "\n") ; ! 1325: if (!head->next_active) { ! 1326: // A more compact message for a single level of instantiation ! 1327: context.restore() ; ! 1328: fprintf (out_file, leader) ; ! 1329: print_loc() ; ! 1330: fprintf (out_file, "was the site of the instantiation\n") ; ! 1331: }else { ! 1332: // The instantiation chain is longer than one ! 1333: fprintf (out_file, "%sthe instantiation path was:\n", leader) ; ! 1334: for (Ptempl_inst p = head ; p ; p = p->next_active) { ! 1335: p->context.restore() ; ! 1336: print_loc() ; ! 1337: fprintf (out_file, " template:") ; ! 1338: p->print_pretty_name() ; ! 1339: fprintf(out_file, "\n") ; ! 1340: } ! 1341: } ! 1342: current_state.restore() ; ! 1343: } ! 1344: ! 1345: ! 1346: ! 1347: // Generate a class name for the instantiated class. It is constructed in a ! 1348: // manner similar to the names used in the construction of overloaded functions ! 1349: char *templ_inst::instantiation_string() { ! 1350: char inst_name[max_string_size] ; ! 1351: for (int i = 0 ; i < max_string_size; i++) inst_name[i] = 0 ; ! 1352: mangled_name(inst_name) ; ! 1353: return strdup(inst_name) ; ! 1354: } ! 1355: ! 1356: ! 1357: ! 1358: // Change the names for the class, constructors, and destructors to reflect ! 1359: // the new class instantiation name. ! 1360: void classdef::modify_inst_names(char *s) ! 1361: { ! 1362: char *old = string ; ! 1363: string = s ; // Change the class name ! 1364: // Change the constructor names ! 1365: for (Pname p=mem_list; p; p=p->n_list) ! 1366: if (p->tp && (p->tp->base==FCT) && (!strcmp(old, p->string))) ! 1367: p->string = s ; ! 1368: } ! 1369: ! 1370: // Get past the fake template argument name typename types ! 1371: Ptype non_template_arg_type(Pbase t) { ! 1372: if ((t->base == TYPE) && ! 1373: (t->b_name->n_template_arg == template_type_formal)) ! 1374: return non_template_arg_type(Pbase(t->b_name->tp)) ; ! 1375: else return t ; ! 1376: } ! 1377: ! 1378: // follow the chain until we hit a non ! 1379: void non_template_arg_non_type(Pname n) { ! 1380: Pexpr i = n->n_initializer; ! 1381: while (i && ! 1382: (i->base == NAME) && ! 1383: (Pname(i)->n_template_arg == template_expr_formal)) ! 1384: { ! 1385: if (Pname(i)->n_initializer) { ! 1386: n->n_initializer = Pname(i)->n_initializer ; ! 1387: i = n->n_initializer ; ! 1388: continue ; ! 1389: } ! 1390: if (Pname(i)->n_evaluated) { ! 1391: n->n_evaluated = 1 ; ! 1392: n->n_val = Pname(i)->n_val ; ! 1393: return ; ! 1394: } ! 1395: } ! 1396: return ; ! 1397: } ! 1398: ! 1399: ! 1400: ! 1401: // Now that the actuals are truly resolved, ie. semantics is complete, and the ! 1402: // template is about to be instantiated. ! 1403: void forward_template_arg_types(Plist formal, Pexpr actuals) ! 1404: { ! 1405: for (Pexpr actual = actuals ; formal && actual ; ! 1406: formal = formal->l, actual = actual->e2) ! 1407: switch(formal->f->n_template_arg){ ! 1408: case template_type_formal: ! 1409: actual->e1->tp = non_template_arg_type(Pbase(actual->e1->tp)) ; ! 1410: break ; ! 1411: case template_expr_formal: ! 1412: break ; ! 1413: case template_expr_tree_formal: ! 1414: case template_stmt_tree_formal: ! 1415: break ; ! 1416: default: ! 1417: error ('i', "bad template formal") ; ! 1418: } ! 1419: } ! 1420: ! 1421: // determine whether the expression supplied as an actual argument to ! 1422: // atemplate formal of type "template_expr_formal" is suitable. We are nore ! 1423: // restrictive than we need to be, simply so that the debugger can have an ! 1424: // easier time. All expressions must be of the form constant integer ! 1425: // expression, a float or double literal, or the address of a variable, or an ! 1426: // array, or function ! 1427: static int suitable_const_expr(Pname n) ! 1428: { ! 1429: if (n->n_evaluated) return 1 ; ! 1430: ! 1431: if (!n->n_initializer) return 0 ; ! 1432: ! 1433: switch (n->n_initializer->base) { ! 1434: ! 1435: case CAST: ! 1436: { // if it is a cast of an integer value, it's fine. ! 1437: if (n->n_initializer->e1->base == IVAL) ! 1438: return 1 ; ! 1439: else return 0 ; ! 1440: } ! 1441: ! 1442: case FCON: ! 1443: case ZERO: ! 1444: return 1 ; ! 1445: ! 1446: case ADDROF: ! 1447: case G_ADDROF: ! 1448: { ! 1449: Pname an = Pname(n->n_initializer->e2) ; ! 1450: if (an->base != NAME) return 0 ; ! 1451: if (an->n_stclass == STATIC) return 1 ; ! 1452: return 0 ; ! 1453: } ! 1454: case NAME: ! 1455: { ! 1456: Pname an = Pname(n->n_initializer) ; ! 1457: if ((an->n_stclass == STATIC) && ! 1458: (an->tp->base == VEC)) ! 1459: // assumes that decl processing won, so that the formal could only ! 1460: // have been apointer ! 1461: return 1 ; ! 1462: return 0 ; ! 1463: } ! 1464: default: ! 1465: return 0 ; ! 1466: } ! 1467: } ! 1468: ! 1469: ! 1470: ! 1471: static bool is_stmt_node(Pnode p) { ! 1472: if (!p) return false ; ! 1473: switch(p->base) { ! 1474: case BREAK: case CONTINUE: case DEFAULT: ! 1475: case SM: case WHILE: case DO: case SWITCH: case RETURN: case CASE: ! 1476: case FOR: ! 1477: case IF: ! 1478: case BLOCK: ! 1479: case PAIR: // ? ! 1480: return true ; ! 1481: } ! 1482: return false ; ! 1483: } ! 1484: ! 1485: ! 1486: ! 1487: static void bind_tree_expr_formal(Pname f, Pexpr actual) ! 1488: { ! 1489: if (actual->e1->base == TNAME) ! 1490: error ('i', "a TNAME is not a valid argument for the formal %n", ! 1491: f) ; ! 1492: if (is_stmt_node(actual->e1)) { ! 1493: error ("an expression node was expected for the expression formal parameter %n", f) ; ! 1494: actual->e1 = zero ; ! 1495: } ! 1496: // bind the formal to the expression, it will be accessed from here by ! 1497: // the hook function during the copy ! 1498: f->n_initializer = actual->e1 ; ! 1499: } ! 1500: ! 1501: ! 1502: ! 1503: // Bind the formals to the types passed in as the actuals, for the ! 1504: // instantiation, bind the non-type names to their expressions. ! 1505: void templ_inst::bind_formals() ! 1506: { Pexpr actual ; ! 1507: Plist formal ; ! 1508: ! 1509: for (formal = inst_formals, actual = actuals ; ! 1510: formal && actual ; formal = formal->l, actual = actual->e2) ! 1511: switch (formal->f->n_template_arg) { ! 1512: case template_type_formal: ! 1513: { ! 1514: formal->f->tp = non_template_arg_type(Pbase(actual->e1->tp)) ; ! 1515: PERM(formal->f->tp) ; ! 1516: break ; ! 1517: } ! 1518: ! 1519: case template_expr_formal: ! 1520: { ! 1521: actual->e1 = actual->e1->typ(gtbl); ! 1522: if (formal->f->tp->check(actual->e1->tp,ASSIGN) == 1) ! 1523: error("template argument mismatch, expected %t for formal %n, not %t", ! 1524: formal->f->tp, formal->f, actual->e1->tp) ; ! 1525: // hide the global name around decl processing of the formal name ! 1526: Pname g = gtbl->look (formal->f->string, 0) ; ! 1527: if (g) g->n_key = HIDDEN ; ! 1528: // bind the non type arguments to their expressions ! 1529: // parameters that are bound at syntax analysis, these parameters are ! 1530: // bound during dcl processing, so ensure that they can be found. ! 1531: formal->f->n_initializer = actual->e1 ; ! 1532: formal->f->simpl() ; ! 1533: formal->f = formal->f->dcl(gtbl, STATIC) ; ! 1534: formal->f->n_key = HIDDEN ; ! 1535: ! 1536: PERM(formal->f) ; ! 1537: non_template_arg_non_type(formal->f) ; ! 1538: if (!suitable_const_expr(formal->f)) ! 1539: error("template argument for formal:%s, is not a suitable constant.", ! 1540: formal->f->string) ; ! 1541: if (g) g->n_key = 0 ; ! 1542: break ; ! 1543: } ! 1544: ! 1545: case template_expr_tree_formal: ! 1546: { ! 1547: bind_tree_expr_formal(formal->f, actual) ; ! 1548: break ; ! 1549: } ! 1550: case template_stmt_tree_formal: ! 1551: { ! 1552: error("a statement tree may not be specified for a class template") ; ! 1553: break ; ! 1554: } ! 1555: ! 1556: default: ! 1557: error ('i', "bad template formal") ; ! 1558: } ! 1559: ! 1560: // now that the formals are bound, compute the instantiation string ! 1561: char *inst_name = instantiation_string() ; ! 1562: tname->string = instantiation_string() ; ! 1563: ! 1564: for (formal = inst_formals; formal ; formal = formal->l) ! 1565: if (formal->f->n_template_arg_string) ! 1566: error('i', "attempt to bind a template parameter multiple times") ; ! 1567: else ! 1568: formal->f->n_template_arg_string = ! 1569: strcat(strcpy(calloc(strlen(formal->f->string)+strlen(inst_name)+1,1), ! 1570: formal->f->string), inst_name) ; ! 1571: } ! 1572: ! 1573: ! 1574: // Expose the non-type parameter names so that they are visible during decl ! 1575: // processing. Conflicting global names are hidden, so that they are not ! 1576: // found. ! 1577: void templ_inst::expose_parameter_names() { ! 1578: ! 1579: if (hidden_globals) ! 1580: error ('i', "an expose without a hide of global names") ; ! 1581: ! 1582: for (Plist formal = inst_formals ; formal ; formal = formal->l) ! 1583: if (formal->f->n_template_arg == template_expr_formal) { ! 1584: // Hide any visible globals ! 1585: Pname gname = gtbl->look(formal->f->string, 0) ; ! 1586: if (gname) { ! 1587: // an existing global name, hide it ! 1588: gname->n_key = HIDDEN ; ! 1589: // note them for future restoration ! 1590: hidden_globals = new name_list(gname,hidden_globals); ! 1591: } ! 1592: formal->f->n_key = 0 ; // bring it out of hiding ! 1593: if (formal->f != gtbl->look(formal->f->string,0)) ! 1594: error('i', "parameter could not be located in the global table") ; ! 1595: } ! 1596: } ! 1597: ! 1598: ! 1599: // Hide the non-type parameter names after an instantiation, and restore any ! 1600: // globals that may have been hidden during the process. ! 1601: void templ_inst::hide_parameter_names() { ! 1602: ! 1603: for (Plist formal = inst_formals ; formal ; formal = formal->l) ! 1604: if (formal->f->n_template_arg == template_expr_formal) { ! 1605: formal->f->n_key = HIDDEN ; ! 1606: } ! 1607: for (; hidden_globals; hidden_globals= hidden_globals->l) ! 1608: hidden_globals->f->n_key= 0 ; ! 1609: hidden_globals = 0 ; ! 1610: } ! 1611: ! 1612: ! 1613: ! 1614: // Primitives for saving and restoring the compilation state around a template ! 1615: // instantiation. It also maintains the stack of template instantiations. ! 1616: void templ_inst::save_state(Pname p) { ! 1617: if (next_active) error ('i', "circular instantiation of a template") ; ! 1618: context.save() ; ! 1619: if (templ_inst::head) ! 1620: templ_inst::head->hide_parameter_names() ; ! 1621: next_active = templ_inst::head ; templ_inst::head = this ; ! 1622: context.init() ; ! 1623: Cdcl = p ; Cstmt = NULL ; ! 1624: curr_file = (Cdcl) ? Cdcl->where.file : 0; ! 1625: expose_parameter_names() ; ! 1626: } ! 1627: ! 1628: ! 1629: void templ_inst::restore_state() { ! 1630: context.restore() ; ! 1631: hide_parameter_names() ; ! 1632: templ_inst::head = next_active ; next_active = NULL ; ! 1633: if (templ_inst::head) ! 1634: templ_inst::head->expose_parameter_names() ; ! 1635: } ! 1636: ! 1637: ! 1638: // Copy over the class definition subtree starting from COBJ down to the ! 1639: // CLASSDEF node. This minimal subtree has to exist during syntax analysis, ! 1640: // and already contains pointers into it. ! 1641: void templ_inst::kludge_copy(Pbase pbc) ! 1642: { ! 1643: // copy just the COBJ ->b_name NAME ->tp CLASS path for now, note that the ! 1644: // preceding path of the tree is pre-allocated, since syntax analysis needs ! 1645: // to generate pointers to these objects. ! 1646: Pbase pb = Pbase(tname->tp) ; ! 1647: Pname save_b_name = pb->b_name ; ! 1648: Ptype save_tp = pb->b_name->tp ; ! 1649: ! 1650: if ((pb->base != COBJ) || (pbc->base != COBJ)) ! 1651: error ('i', "cobj nodes were expected here") ; ! 1652: ! 1653: *pb = *pbc ; ! 1654: pb->b_name = save_b_name ; ! 1655: *pb->b_name = *pbc->b_name ; ! 1656: pb->b_name->tp = save_tp ; ! 1657: *Pclass(pb->b_name->tp) = *Pclass(pbc->b_name->tp) ; ! 1658: Pclass(pb->b_name->tp)->class_base = instantiated_template_class ; ! 1659: ! 1660: } ! 1661: ! 1662: ! 1663: // these statics probably belong in templ_inst and shouldn't be dangling ! 1664: // around ! 1665: ! 1666: static Pbase cobj_node ; ! 1667: static Pname cname_node ; ! 1668: static Pclass class_node ; ! 1669: ! 1670: static void syntax_tree_copy_hook(void *, ! 1671: Pnode &, ! 1672: node_class, ! 1673: tree_node_action &action, ! 1674: int& never_see_again) ! 1675: { ! 1676: never_see_again = 1; ! 1677: action = tna_continue; ! 1678: return; ! 1679: } ! 1680: ! 1681: ! 1682: // create a copy of the expression tree ! 1683: static Pnode copy_syntax_tree(Pnode n, int no_types = 0) { ! 1684: pointer_hash cht(default_copy_hash_size) ; ! 1685: ! 1686: tree_copy_info info ; ! 1687: ! 1688: if(no_types) info.node_hook = syntax_tree_copy_hook; ! 1689: ! 1690: copy_tree (n, info, &cht); ! 1691: ! 1692: return n ; ! 1693: } ! 1694: ! 1695: ! 1696: ! 1697: // hook to perform the copying of the pre-allocated class subtree ! 1698: bool templ_inst::copy_hook(Pnode &node) ! 1699: { ! 1700: switch (node->base) { ! 1701: case COBJ: ! 1702: if (node == cobj_node) return false ; ! 1703: ! 1704: if (node == def->namep->tp) { ! 1705: *cobj_node = *Pbase(node) ; ! 1706: node = cobj_node ; ! 1707: } ! 1708: break ; ! 1709: case NAME: ! 1710: if (node == cname_node) return false ; ! 1711: if (node == sta_name) return false ; ! 1712: ! 1713: if (node == Pbase(def->namep->tp)->b_name) { ! 1714: *cname_node= *Pname(node) ; ! 1715: node = cname_node ; ! 1716: }else { // check for tree expression formals ! 1717: char *s = Pname(node)->string ; ! 1718: Pname f = 0 ; ! 1719: if (s && (*s == '$') && (f = get_parameter(s+1))) ! 1720: { ! 1721: if(Pname(node)->n_list) ! 1722: error ('i', "n_list set in tree template formal."); ! 1723: node = copy_syntax_tree(Pname(f)->n_initializer) ; ! 1724: return false ; ! 1725: } ! 1726: } ! 1727: break ; ! 1728: case CLASS: ! 1729: if (node == class_node) return false ; ! 1730: ! 1731: if (node == Pbase(def->namep->tp)->b_name->tp) { ! 1732: *class_node = *Pclass(node) ; ! 1733: node = class_node ; ! 1734: } ! 1735: break ; ! 1736: } ! 1737: return true ; ! 1738: } ! 1739: ! 1740: ! 1741: /* ! 1742: ! 1743: This hook function used during a class copy. ! 1744: ! 1745: */ ! 1746: static void copy_hook(void /* Ptempl_inst */ *p, Pnode &node, ! 1747: node_class, tree_node_action &action, ! 1748: int& never_see_again) ! 1749: { ! 1750: action = (Ptempl_inst(p)->copy_hook(node) ? tna_continue : tna_stop ) ; ! 1751: never_see_again = (action != tna_stop); ! 1752: return ; ! 1753: } ! 1754: ! 1755: ! 1756: ! 1757: void establish_class_subtree_correspondence(pointer_hash &h, Pname key_tname, ! 1758: Pname value_tname) ! 1759: { ! 1760: h[int(key_tname)] = int(value_tname) ; ! 1761: h[int(key_tname->tp)] = int(value_tname->tp) ; ! 1762: h[int(Pbase(key_tname->tp)->b_name)] = ! 1763: int(Pbase(value_tname->tp)->b_name) ; ! 1764: h[int(Pbase(key_tname->tp)->b_name->tp)] = ! 1765: int(Pbase(value_tname->tp)->b_name->tp) ; ! 1766: } ! 1767: ! 1768: ! 1769: ! 1770: ! 1771: Pcons make_ref_copy(pointer_hash &h, tree_copy_info &info, Pcons old_templ_refs) ! 1772: { ! 1773: cons dummy(0,0), *last = &dummy ; ! 1774: ! 1775: for (Pcons pc = old_templ_refs ; pc ; pc = pc->cdr) { ! 1776: ! 1777: Ptempl_inst t = Ptempl_inst(pc->car) ; ! 1778: // +**** this doesn't work without class instances of new and delete ! 1779: // +**** dtor places this onto free_list: ugh ! 1780: // +**** want to restore this once new/delete isntances are restored ! 1781: // expr dummy(ELIST, 0, 0) ; ! 1782: // elist list(&dummy) ; ! 1783: Pexpr dummy = new expr(ELIST, 0, 0); ! 1784: elist list(dummy); ! 1785: ! 1786: // copy the trees corresponding to the actuals ! 1787: for (Pexpr actual = t->actuals ; actual ; actual = actual->e2) { ! 1788: Pnode root = actual->e1 ; ! 1789: copy_tree (root, info, &h); ! 1790: // make sure that references to enclosing formals are resolved ! 1791: root = Pexpr(root)->typ(gtbl); ! 1792: list.add(new expr(ELIST, Pexpr(root), 0)) ; ! 1793: } ! 1794: Pexpr new_actuals = list.head->e2 ; ! 1795: ! 1796: // get one if it exists, create one otherwise. ! 1797: Ptempl_inst treal = t->def->get_inst(new_actuals, t) ; ! 1798: Pname new_tname = treal->tname ; ! 1799: ! 1800: last = last->cdr = new cons(treal,0); ! 1801: ! 1802: establish_class_subtree_correspondence(h, t->tname, new_tname) ; ! 1803: } ! 1804: ! 1805: return dummy.cdr ; ! 1806: } ! 1807: ! 1808: ! 1809: ! 1810: ! 1811: /* ! 1812: Remap the template references from within the body of the template. This ! 1813: action is similar to the normal tree copy operation; it would normally have ! 1814: been done during the syntax phase, that produced the tree, but since there ! 1815: isn't one, for the instantiated body, it must be done here. ! 1816: ! 1817: */ ! 1818: Pcons templ_inst::ref_copy(pointer_hash &h, tree_copy_info &info, Pcons old_templ_refs) ! 1819: { ! 1820: expose_parameter_names() ; ! 1821: Pcons new_refs = make_ref_copy(h,info,old_templ_refs) ; ! 1822: hide_parameter_names() ; ! 1823: return new_refs ; ! 1824: } ! 1825: ! 1826: static bool is_forward_instantiation(Pbase b_base, Pbase f_base) ! 1827: { ! 1828: return bool(b_base->b_name->tp->defined && f_base->b_name->tp->defined) ; ! 1829: } ! 1830: ! 1831: ! 1832: /***************************************************************************** ! 1833: * * ! 1834: * If the template instantiation is found to be unique after the decl * ! 1835: * processing of the actuals, create a copy of the post syntax graph for the * ! 1836: * class. The edges of the graph are determined by "type nodes" that have * ! 1837: * already been defined, and TNAME nodes that are in the global keyword * ! 1838: * table. Special care is also taken to avoid copying nodes whose identity * ! 1839: * must be maintained, since cfront uses them for fast type checks, these * ! 1840: * nodes always have the "defined" flag turned on and so are never copied. * ! 1841: * * ! 1842: * Copying of the pre-allocated class sub-tree for the template: COBJ * ! 1843: * ->b_name NAME ->tp CLASS * ! 1844: * * ! 1845: * is handled by the class_copy hook above, that is invoked during the course * ! 1846: * of the copy. * ! 1847: * * ! 1848: * * ! 1849: * Template references from within the class need special handling, since * ! 1850: * each instantiation of the class, results in a potentially new template * ! 1851: * instantiation. * ! 1852: * * ! 1853: *****************************************************************************/ ! 1854: Ptempl_inst templ_inst::class_copy(Pcons &templ_refs, bool recopy) ! 1855: { ! 1856: bool forward = false ; // a forward class is instantiated twice ! 1857: ! 1858: // associate the formals with their types, and their expressions ! 1859: if (recopy) { ! 1860: // remove the class def node from the table, so that it's attributes are ! 1861: // copied. ! 1862: corr->del(int(Pbase(def->namep->tp)->b_name->tp)) ; ! 1863: corr->del(int(Pbase(def->namep->tp)->b_name)) ; ! 1864: corr->del(int(def->namep->tp)) ; ! 1865: ! 1866: corr->del(int(tname->tp)) ; ! 1867: corr->del(int(Pbase(tname->tp)->b_name)) ; ! 1868: corr->del(int(Pbase(tname->tp)->b_name->tp)) ; ! 1869: }else corr = new pointer_hash(default_copy_hash_size) ; ! 1870: ! 1871: { // copy the formals & install them in the correspondence table ! 1872: name_list dummy_formal(0,0) ; ! 1873: Plist last = &dummy_formal ; ! 1874: ! 1875: for (Plist formal = def->formals ; formal ; formal = formal->l) { ! 1876: Pname copy_name = new name("") ; ! 1877: *copy_name = *formal->f ; ! 1878: copy_name->n_tbl_list = 0 ; ! 1879: last = last->l = new name_list(copy_name, 0) ; ! 1880: (*corr)[int(formal->f)] = (int)copy_name ; ! 1881: } ! 1882: inst_formals = dummy_formal.l ; ! 1883: } ! 1884: ! 1885: bind_formals() ; ! 1886: if ( ! recopy && ktbl->look(tname->string, 0)) { ! 1887: // formal binding may result in detecting identical instantiations ! 1888: Ptempl_inst ti = def->get_match(actuals, this, true) ; ! 1889: if (ti) return ti ; ! 1890: error('i', "Generated template instantiation name %swas not unique", ! 1891: tname->string) ; ! 1892: } ! 1893: ! 1894: { ! 1895: tree_copy_info info ; ! 1896: info.node_hook = ::copy_hook ; ! 1897: info.hook_info = this ; ! 1898: ! 1899: (*corr)[int(def->namep)] = int(tname) ; // make the tnames correspond ! 1900: ! 1901: templ_refs = ref_copy(*corr, info, templ_refs) ; ! 1902: Pnode root = def->basep ; // start the copy at the cobj node ! 1903: ! 1904: // deal with these nodes differently during the copy, ie. the nodes ! 1905: // themselves are not copied, but their attributes are. ! 1906: cobj_node = (Pbase)tname->tp ; ! 1907: cname_node = Pbase( tname->tp)->b_name ; ! 1908: class_node = Pclass(Pbase( tname->tp)->b_name->tp) ; ! 1909: ! 1910: copy_tree (root, info, corr); ! 1911: ! 1912: { // dump the tree if the flag is set ! 1913: extern int dump_tree ; ! 1914: extern dcn_arg dump_tree_arg; ! 1915: ! 1916: if (dump_tree) display_cfront_node (dump_tree_arg, root); ! 1917: } ! 1918: } ! 1919: // Perform name modifications for the class, so that it is an ! 1920: // instantiation-specific name. ! 1921: cname_node->string = tname->string ; ! 1922: if (!recopy) ! 1923: namep = ktbl->insert(tname, 0) ; ! 1924: else class_node->defined &= ~(DEFINED|SIMPLIFIED) ; ! 1925: namep->tp = cobj_node; ! 1926: ! 1927: class_node->modify_inst_names(cname_node->string) ; ! 1928: return 0 ; ! 1929: } ! 1930: ! 1931: ! 1932: /* ! 1933: This hook function is responsible for the replacement of references to ! 1934: expression when copying function bodies ! 1935: */ ! 1936: static void function_copy_hook(void *current_templ_inst, ! 1937: Pnode &node, ! 1938: node_class, ! 1939: tree_node_action &action, ! 1940: int& never_see_again) ! 1941: { ! 1942: never_see_again = 1; ! 1943: ! 1944: switch (node->base) { ! 1945: case SM_PARAM: ! 1946: error ('i', "statement parameters not permitted for member functions") ; ! 1947: break ; ! 1948: ! 1949: case NAME: ! 1950: { ! 1951: if(node == sta_name) { ! 1952: action = tna_stop; ! 1953: return; ! 1954: } ! 1955: char *s = Pname(node)->string ; ! 1956: Pname f = 0 ; ! 1957: if (s && (*s == '$') && ! 1958: (f = Ptempl_inst(current_templ_inst)->get_parameter(s+1))) { ! 1959: if(Pname(node)->n_list) ! 1960: error ('i', "n_list set in tree template formal."); ! 1961: node = copy_syntax_tree(Pname(f)->n_initializer) ; ! 1962: action = tna_stop ; ! 1963: never_see_again = 0; ! 1964: }else action = tna_continue ; ! 1965: return ; ! 1966: } ! 1967: default: ! 1968: action = tna_continue ; ! 1969: return ; ! 1970: } ! 1971: } ! 1972: ! 1973: ! 1974: ! 1975: /* ! 1976: ! 1977: Create a copy of a function member, as part of the instantiation of a function ! 1978: body. The correspondence table is first initialized with the contents of the ! 1979: correspondence table used to instantiate the class. Copying is initiated ! 1980: in this context. ! 1981: ! 1982: */ ! 1983: ! 1984: Pname templ_inst::function_copy(Pfunt fnt, Pcons &templ_refs) ! 1985: { ! 1986: pointer_hash fcorr(*corr) ; // initialize it with the old hash table ! 1987: ! 1988: { ! 1989: tree_copy_info info ; ! 1990: Pnode root = fnt->fn ; ! 1991: ! 1992: // establish a correspondence between the formals used for the class ! 1993: // template, andthe formals used for the function template, all references ! 1994: // to the function template formals will be replaced by references to the ! 1995: // instantiated class template formals after the copy has been completed. ! 1996: ! 1997: for (Plist fformal = fnt->formals, cformal = inst_formals ; ! 1998: fformal ; fformal = fformal->l, cformal = cformal->l) ! 1999: { ! 2000: fcorr[int(fformal->f)] = int(cformal->f) ; ! 2001: if (fcorr[int(fformal->f)] != int(cformal->f)) ! 2002: error ('i', "hash table bug") ; ! 2003: } ! 2004: ! 2005: info.node_hook = ::function_copy_hook ; ! 2006: info.hook_info = this ; ! 2007: ! 2008: templ_refs = ref_copy(fcorr, info, templ_refs) ; ! 2009: if (fcorr[int(def->namep)] != int(tname)) ! 2010: error ('i', "template to instantiation typename correspondence is missing") ; ! 2011: ! 2012: copy_tree (root, info, &fcorr); ! 2013: ! 2014: { // dump the tree if the flag is set ! 2015: extern int dump_tree ; ! 2016: extern dcn_arg dump_tree_arg; ! 2017: ! 2018: if (dump_tree) ! 2019: display_cfront_node (dump_tree_arg, root); ! 2020: } ! 2021: return Pname(root) ; ! 2022: } ! 2023: } ! 2024: ! 2025: ! 2026: /***************************************************************************** ! 2027: * * ! 2028: * A matching template was found at instantiation time, which was not * ! 2029: * detected at syntax analysis time. This can happen, when an instantiation * ! 2030: * has as its arguments not real types but template arguments, so that * ! 2031: * matches cannot be detected until the templates are bound. Note that it is * ! 2032: * also possible to match a template that is in the process of being * ! 2033: * instantiated further up the instantiation call chain. In such cases, the * ! 2034: * kludge_copy operation will copy over an incomplete class subtree, which * ! 2035: * will be recopied with the completed one after the instantiation is * ! 2036: * completed, in templ_inst::instantiate. * ! 2037: * * ! 2038: *****************************************************************************/ ! 2039: void templ_inst::instantiate_match(Ptempl_inst match) ! 2040: { Pbase pb = Pbase(match->tname->tp) ; ! 2041: kludge_copy(pb) ; ! 2042: forward = match ; // Note the fact that this template was matched ! 2043: } ! 2044: ! 2045: ! 2046: Pclass current_instantiation = 0 ; ! 2047: ! 2048: // Do the class declaration instantiation. ! 2049: void templ_inst::instantiate(bool reinstantiate) ! 2050: { ! 2051: Pcons templ_refs = def->templ_refs ; ! 2052: if (! reinstantiate) { ! 2053: switch (Ptclass(Pbase(tname->tp)->b_name->tp)->class_base) { ! 2054: case instantiated_template_class: ! 2055: return ; ! 2056: case uninstantiated_template_class: ! 2057: break ; ! 2058: case vanilla_class: ! 2059: case template_class: // the canonical template class ! 2060: default: ! 2061: error ('i', "attempt to instantiate a non-template class") ; ! 2062: } ! 2063: status = class_instantiated ; ! 2064: // Check whether, the template has already been instantiated, if so use it. ! 2065: forward_template_arg_types(def->formals, actuals) ; ! 2066: Ptempl_inst match = def->get_match(actuals, this, true) ; ! 2067: ! 2068: if (match || (match = class_copy(templ_refs, false))){ ! 2069: instantiate_match(match) ; ! 2070: return ; ! 2071: } ! 2072: }else class_copy(templ_refs, true) ; ! 2073: ! 2074: Pbase pb = Pbase(tname->tp) ; ! 2075: ! 2076: // Save the state around decl processing ! 2077: { save_state(def->namep) ; ! 2078: ! 2079: if (def->open_instantiations++ > 1) { ! 2080: error ("an infinite instantiation sequence was initiated") ; ! 2081: def->open_instantiations-- ; ! 2082: return ; ! 2083: } ! 2084: // Mark the class as instantiated so that there are no circular ! 2085: // instantiations. ! 2086: Pclass(pb->b_name->tp)->class_base = instantiated_template_class ; ! 2087: ! 2088: // if it is a forward reference, rely on the usual compilation to ! 2089: // provide an error message, if indeed it is an error, and not a ! 2090: // benign forward reference such as: friend class foo<X,Y> ! 2091: ! 2092: if (def->basep->b_name->tp->defined) { ! 2093: ! 2094: // Put out the typedefs for the template parameters do this before the ! 2095: // call to name::dcl below, since dcl processing will emit c declarations ! 2096: // that make use of the type ! 2097: for (Plist formal = inst_formals; formal ; formal = formal->l) ! 2098: switch(formal->f->n_template_arg) { ! 2099: case template_expr_tree_formal: ! 2100: case template_stmt_tree_formal: ! 2101: break ; ! 2102: default: ! 2103: formal->f->dcl_print(0) ; ! 2104: } ! 2105: // Instantiate the parametrized types referenced by this template ! 2106: for (Pcons pc = templ_refs ; pc ; pc = pc->cdr) ! 2107: Ptempl_inst(pc->car)->instantiate() ; ! 2108: ! 2109: if (!((pb->b_name->dcl(gtbl, EXTERN) == 0 ) || error_count)) { ! 2110: pb->b_name->simpl() ; ! 2111: ! 2112: if (pb->b_name->tp->base != CLASS) ! 2113: error('i', "a classdef was expected in templ_inst::instantiate") ; ! 2114: ! 2115: current_instantiation = Pclass(pb->b_name->tp) ; ! 2116: pb->b_name->dcl_print(0) ; ! 2117: if (! (pb->b_name->tp->defined & DEFINED)) ! 2118: error ('i', "dcl class is not yet defined") ; ! 2119: current_instantiation = 0 ; ! 2120: } ! 2121: } ! 2122: ! 2123: // bash every template instantiation class that has been forwarded to ! 2124: // it, with the decl processed version. ! 2125: for (Ptempl_inst clone = def->insts ; clone ; clone = clone->next) ! 2126: if (clone != this) { ! 2127: if (clone->forward == this) ! 2128: clone->kludge_copy(Pbase(tname->tp)) ; ! 2129: else { ! 2130: // resolve references to forward declarations ! 2131: if (this == def->get_match(clone->actuals, clone, true)) { ! 2132: clone->kludge_copy(Pbase(tname->tp)) ; ! 2133: clone->forward = this ; ! 2134: } ! 2135: } ! 2136: } ! 2137: Pclass result = Pclass(pb->b_name->tp); ! 2138: ! 2139: // dcl_print the member functions, so that they can be referenced ! 2140: int i = 0 ; ! 2141: for (Pname fn= Pclass(pb->b_name->tp)->memtbl->get_mem(i=1); fn; ! 2142: fn=Pclass(pb->b_name->tp)->memtbl->get_mem(++i)) ! 2143: if ((fn->base == NAME) && (fn->tp->base == FCT)) ! 2144: fn->dcl_print(0) ; ! 2145: ! 2146: restore_state() ; ! 2147: def->open_instantiations-- ; ! 2148: } ! 2149: } ! 2150: ! 2151: /* Template Constructors */ ! 2152: ! 2153: ! 2154: templ::templ(Plist parms, Pname p) { ! 2155: namep = p ; ! 2156: formals = parms ; ! 2157: ! 2158: if (!formals) error ("a parametrized type must have parameters !") ; ! 2159: ! 2160: basep = Pbase(namep->tp) ; ! 2161: ! 2162: Pclass(basep->b_name->tp)->class_base = template_class ; ! 2163: defined = ((basep->b_name->tp->defined & DEF_SEEN) ? true : false) ; ! 2164: if (defined) ! 2165: members = Pclass(basep->b_name->tp)->mem_list ; ! 2166: ! 2167: PERM(namep) ; PERM(namep->tp) ; ! 2168: // Chain on to the list of templates for the compilation. ! 2169: next = templp->list ; ! 2170: templp->list = this ; ! 2171: } ! 2172: ! 2173: ! 2174: templ_inst::templ_inst (Pexpr act, Ptempl owner) ! 2175: { ! 2176: // Set up the basetype for the class, so that nodes that need to point to it ! 2177: // during syntax processing can do so. Theese objects are merely ! 2178: // place-holders during syntax analysis, and are actually filled in during ! 2179: // the copy phase of instantiation. ! 2180: Pclass c ; ! 2181: ! 2182: def = owner ; ! 2183: tname = new name(def->namep->string) ; ! 2184: tname->base = TNAME ; ! 2185: tname->tp = new basetype(COBJ, new name(def->namep->string)) ; ! 2186: Pbase(tname->tp)->b_name->tp = c = new templ_classdef(this) ; ! 2187: PERM(tname) ; PERM(tname->tp) ; PERM(Pbase(tname->tp)->b_name) ; ! 2188: PERM(Pbase(tname->tp)->b_name->tp) ; ! 2189: ! 2190: // initialize the member list so that set_scope can do the right thing ! 2191: c->mem_list = Pclass(def->basetype()->b_name->tp)->mem_list ; ! 2192: ! 2193: actuals = act ; ! 2194: next = owner->insts ; ! 2195: owner->insts = this ; ! 2196: } ! 2197: ! 2198: ! 2199: templ_classdef::templ_classdef(Ptempl_inst i): classdef(CLASS) { ! 2200: inst = i ; ! 2201: class_base = uninstantiated_template_class ; ! 2202: string = unparametrized_tname()->string ; ! 2203: } ! 2204: ! 2205: ! 2206: // Create a new function template. ! 2207: function_template::function_template (templ &owner, Plist params, Pname n) ! 2208: { ! 2209: definition_number = ++definition_tick ; ! 2210: ! 2211: if (owner.fns_end) ! 2212: owner.fns_end->next = this ; ! 2213: else owner.fns = this ; ! 2214: owner.fns_end = this ; ! 2215: formals = params ; ! 2216: fn = n ; ! 2217: PERM(n) ; PERM(n->tp) ; ! 2218: } ! 2219: ! 2220: ! 2221: // create the tree template ! 2222: tree_template::tree_template(TOK tree_kind, char *s, Plist params, Pnode tree, ! 2223: Pcons references) ! 2224: { ! 2225: string = s ; ! 2226: formals = params; ! 2227: e = tree ; ! 2228: if (!e) ! 2229: error('w', "the internal template %s does not have an associated body", s); ! 2230: templ_refs = references ; ! 2231: kind = tree_kind ; ! 2232: ! 2233: // add the expression template too the list of known templates ! 2234: if (get(s)) { ! 2235: error ("duplicate definition of the internal template %s", s) ; ! 2236: return ; ! 2237: } ! 2238: // link it in ! 2239: next = templ_compilation::tree_templates ; ! 2240: templ_compilation::tree_templates = this ; ! 2241: ! 2242: // check that formals weren't misspelt ! 2243: for (Plist formal = formals ; formal ; formal = formal->l) ! 2244: if (! formal->f->n_used) ! 2245: error('w', "the formal parameter %n was not referenced within the template body",formal->f) ; ! 2246: } ! 2247: ! 2248: ! 2249: // lookup an internal expression template ! 2250: Ptreet tree_template::get(char *s) { ! 2251: for (Ptreet o = templ_compilation::tree_templates ; o ; o = o->next) ! 2252: if (strcmp(o->string, s) == 0) return o ; ! 2253: return 0 ; ! 2254: } ! 2255: ! 2256: ! 2257: Pname tree_template::get_parameter(char *s) { ! 2258: for (Plist formal = formals ; formal ; formal = formal->l) { ! 2259: if (strcmp(formal->f->string, s)== 0) ! 2260: return formal->f ; ! 2261: } ! 2262: return 0 ; ! 2263: } ! 2264: ! 2265: ! 2266: ! 2267: // Sam: some remodularization seems to be in order here, so that this method ! 2268: // can be shared ! 2269: Pname templ_inst::get_parameter(char *s) { ! 2270: for (Plist formal = inst_formals ; formal ; formal = formal->l) { ! 2271: if (strcmp(formal->f->string, s)== 0) ! 2272: return formal->f ; ! 2273: } ! 2274: return 0 ; ! 2275: } ! 2276: ! 2277: Pexpr tree_template::expand(Pexpr) ! 2278: { ! 2279: error('i', "no support for tree templates") ; ! 2280: return 0 ; ! 2281: } ! 2282: ! 2283: ! 2284: // Instantiate each function member body. It assumes that the class ! 2285: // declaration has been instantiated. The return value indicates whether an ! 2286: // instantiation of bodies actually took place. This function is only invoked ! 2287: // at the end of a file compilation, after all source text has been processed. ! 2288: bool templ::instantiate_bodies(){ ! 2289: bool change = false ; ! 2290: // Perform the instantiation of the member function bodies. ! 2291: if (!fns) return change ; ! 2292: ! 2293: for (Ptempl_inst inst = insts ; inst ; inst = inst->next) ! 2294: if (!inst->forward && (inst->status == class_instantiated)) { ! 2295: // Set up the environment for the declaration, and subsequent compilation ! 2296: // of the function bodies. ! 2297: inst->status = body_instantiated ; change = true ; ! 2298: ! 2299: { Pclass ic = inst->get_class() ; int i ; ! 2300: // note all the overriding definitions explicitly provided by the user ! 2301: for (Pname fn= ic->memtbl->get_mem(i=1); fn; fn=ic->memtbl->get_mem(++i)) ! 2302: if ((fn->base == NAME) && (fn->tp->base == FCT) && Pfct(fn->tp)->body) ! 2303: fn->n_redefined = 1 ; ! 2304: } ! 2305: ! 2306: for (Pfunt fnt = fns; fnt ; fnt = fnt->next) { ! 2307: Pcons templ_ref_copy = fnt->templ_refs ; ! 2308: Pname fn = inst->function_copy(fnt, templ_ref_copy) ; ! 2309: ! 2310: // Change the qualifier to be the name of the instantiated, rather than ! 2311: // the parametrized class name ! 2312: fn->n_qualifier = inst->namep ; ! 2313: if (fn->n_oper != TYPE ) // cond contains type information ! 2314: fn->n_table = 0; ! 2315: fn->n_tbl_list = 0 ; ! 2316: ! 2317: // Note that the formals were bound to the actuals when the class decl ! 2318: // was instantiated, so the binding is not redone. ! 2319: ! 2320: // Modify constructor and destructor names. ! 2321: if (!strcmp(fn->string, namep->string)) ! 2322: fn->string = inst->namep->string ; ! 2323: { inst->save_state(fn) ; ! 2324: // Instantiate the parametrized types referenced by this template ! 2325: for (Pcons pc = templ_ref_copy ; pc ; pc = pc->cdr) ! 2326: Ptempl_inst(pc->car)->instantiate() ; ! 2327: ! 2328: // ensure that "type type" formals constrained to be class definitions are ! 2329: if (!fnt->check_constraints(inst->actuals))continue ; ! 2330: ! 2331: if ( ((fn = fn->dcl(gtbl, EXTERN)) == 0) || error_count) { ! 2332: inst->restore_state() ; ! 2333: continue ; ! 2334: } ! 2335: fn->simpl() ; ! 2336: fn->dcl_print(0) ; ! 2337: inst->restore_state() ; ! 2338: } ! 2339: } ! 2340: } ! 2341: return change ; ! 2342: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.