|
|
1.1 ! root 1: /*ident "@(#)ctrans:src/norm.c 1.6.4.23" */ ! 2: /************************************************************************ ! 3: ! 4: C++ source for cfront, the C++ compiler front-end ! 5: written in the computer science research center of Bell Labs ! 6: ! 7: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 8: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 9: ! 10: norm.c: ! 11: ! 12: "normalization" handles problems which could have been handled ! 13: by the syntax analyser; but has not been done. The idea is ! 14: to simplify the grammar and the actions accociated with it, ! 15: and to get a more robust error handling ! 16: ! 17: ****************************************************************************/ ! 18: ! 19: #include "cfront.h" ! 20: #include "template.h" ! 21: #include "size.h" ! 22: ! 23: void syn_init() ! 24: { ! 25: any_type = new basetype(ANY,0); ! 26: PERM(any_type); any_type->defined = DEFINED ; ! 27: dummy = new expr(DUMMY,0,0); ! 28: PERM(dummy); ! 29: dummy->tp = any_type; ! 30: zero = new expr(ZERO,0,0); ! 31: PERM(zero); ! 32: } ! 33: ! 34: int stcount; ! 35: ! 36: char* make_name(TOK c) ! 37: { ! 38: char* s = new char[8]; // as it happens: fits in two words ! 39: ! 40: if (15000 <= ++stcount) error('i',"too many generatedNs"); ! 41: ! 42: s[0] = '_'; // __ prefix belongs to the implementation ! 43: s[1] = '_'; ! 44: s[2] = c; ! 45: int count = stcount; ! 46: int i = 3; ! 47: if (10000 <= count) { ! 48: s[i++] = '0' + count/10000; ! 49: count %= 10000; ! 50: } ! 51: if (1000 <= count) { ! 52: s[i++] = '0' + count/1000; ! 53: count %= 1000; ! 54: } ! 55: else if (3<i) s[i++] = '0'; ! 56: ! 57: if (100 <= count) { ! 58: s[i++] = '0' + count/100; ! 59: count %= 100; ! 60: } ! 61: else if (3<i) s[i++] = '0'; ! 62: ! 63: if (10 <= count) { ! 64: s[i++] = '0' + count/10; ! 65: count %= 10; ! 66: } ! 67: else if (3<i) s[i++] = '0'; ! 68: ! 69: s[i++] = '0' + count; ! 70: s[i] = 0; ! 71: //if (s[7]!=0) error('d',"impossible make_name"); ! 72: return s; ! 73: } ! 74: ! 75: Pbase basetype::type_adj(TOK t) ! 76: { ! 77: //error('d',"bastype::type_adj(%k)",t); ! 78: switch (base) { ! 79: case COBJ: ! 80: case EOBJ: ! 81: { Pbase bt = new basetype(0,0); ! 82: *bt = *this; ! 83: DEL(this); ! 84: this = bt; ! 85: } ! 86: } ! 87: ! 88: if (b_xname) { ! 89: if (base) ! 90: error("badBT:%n%k",b_xname,t); ! 91: else { ! 92: base = TYPE; ! 93: b_name = b_xname; ! 94: } ! 95: b_xname = 0; ! 96: } ! 97: ! 98: switch (t) { ! 99: case TYPEDEF: b_typedef = 1; break; ! 100: case INLINE: b_inline = 1; break; ! 101: case VIRTUAL: b_virtual = 1; break; ! 102: case CONST: if (b_const) error('w',"two const declarators"); ! 103: b_const = 1; break; ! 104: case UNSIGNED: b_unsigned = 1; break; ! 105: case SHORT: b_short = 1; break; ! 106: case LONG: if (b_long) error('w',"two long declarators"); ! 107: if (base == DOUBLE) ! 108: base = LDOUBLE; ! 109: else ! 110: b_long = 1; ! 111: break; ! 112: case FRIEND: ! 113: case OVERLOAD: ! 114: case EXTERN: ! 115: case STATIC: ! 116: case AUTO: ! 117: case REGISTER: ! 118: if (b_sto) ! 119: error("badBT:%k%k",b_sto,t); ! 120: else ! 121: b_sto = t; ! 122: break; ! 123: case DOUBLE: ! 124: if (b_long) { ! 125: t = LDOUBLE; ! 126: b_long = 0; ! 127: } ! 128: // no break ! 129: case VOID: ! 130: case CHAR: ! 131: case INT: ! 132: case FLOAT: ! 133: if (base) ! 134: error("badBT:%k%k",base,t); ! 135: else ! 136: base = t; ! 137: break; ! 138: case SIGNED: ! 139: case VOLATILE: ! 140: error('w',"\"%k\" not implemented (ignored)",t); ! 141: break; ! 142: default: ! 143: error('i',"BT::type_adj(%k)",t); ! 144: } ! 145: return this; ! 146: } ! 147: ! 148: extern int in_arg_list; ! 149: ! 150: Pbase basetype::name_adj(Pname n) ! 151: { ! 152: //error('d',"name_adj(%n)",n); ! 153: if (b_xname) { ! 154: if (base) ! 155: error("badBT:%n%n",b_xname,n); ! 156: else { ! 157: base = TYPE; ! 158: b_name = b_xname; ! 159: } ! 160: b_xname = 0; ! 161: } ! 162: ! 163: if ( base==0 ! 164: && n->base == TNAME ! 165: && ( n->tp->base!=COBJ || in_arg_list )) { ! 166: base = TYPE; ! 167: b_name = n; ! 168: } ! 169: else ! 170: b_xname = n; ! 171: ! 172: return this; ! 173: } ! 174: ! 175: TOK type_set( Pbase b ) { ! 176: TOK t = 0; ! 177: ! 178: if ( b->b_long ) t = LONG; ! 179: else if ( b->b_short ) t = SHORT; ! 180: else if ( b->b_unsigned ) t = UNSIGNED; ! 181: else if ( b->b_inline ) t = INLINE; ! 182: else if ( b->b_virtual ) t = VIRTUAL; ! 183: else if ( b->b_sto == OVERLOAD ) t = OVERLOAD; ! 184: return t; ! 185: } ! 186: ! 187: int declTag = 1; ! 188: ! 189: Pbase basetype::base_adj(Pbase b) ! 190: { ! 191: Pname bn = b->b_name; ! 192: ! 193: switch (base) { ! 194: case COBJ: ! 195: case EOBJ: ! 196: error("NX after%k%n",base,b_name); ! 197: return this; ! 198: } ! 199: ! 200: TOK t; ! 201: if (base) { ! 202: if (b_name) ! 203: error("badBT:%k%n%k%n",base,b_name,b->base,bn); ! 204: else ! 205: error("badBT:%k%k%n",base,b->base,bn); ! 206: } ! 207: else if ( t = type_set(this)) { ! 208: if (b_name) ! 209: error("badBT:%k%n%k%n",t,b_name,b->base,bn); ! 210: else { ! 211: if ( declTag++ ) error("badBT:%k%k%n",t,b->base,bn); ! 212: base=b->base; b_name = bn; ! 213: // error('d',"base_adj: t: %k", t ); ! 214: } ! 215: } ! 216: else { ! 217: base = b->base; ! 218: b_name = bn; ! 219: b_table = b->b_table; ! 220: } ! 221: return this; ! 222: } ! 223: ! 224: Pbase basetype::check(Pname n) ! 225: /* ! 226: "n" is the first name to be declared using "this" ! 227: check the consistency of "this" ! 228: and use "b_xname" for "n->string" if possible and needed ! 229: */ ! 230: { ! 231: b_inline = 0; ! 232: b_virtual = 0; ! 233: //error('d',"basetype::check(%n) base %k b_xname %n",n,base,b_xname); ! 234: ! 235: if (b_xname && (n->tp || n->string)) { ! 236: if (base) ! 237: error("badBT:%k%n",base,b_xname); ! 238: else { ! 239: base = TYPE; ! 240: b_name = b_xname; ! 241: } ! 242: b_xname = 0; ! 243: } ! 244: ! 245: if (b_xname) { ! 246: if (n->string) ! 247: error("twoNs inD:%n%n",b_xname,n); ! 248: else { ! 249: n->string = b_xname->string; ! 250: b_xname->hide(); ! 251: } ! 252: b_xname = 0; ! 253: } ! 254: ! 255: if (ccl==0 ! 256: && n ! 257: && n->n_oper==TNAME ! 258: && n->n_qualifier==0 ! 259: && n->string) { // hide type name ! 260: Pname nx = ktbl->look(n->string,0); ! 261: if (nx) nx->hide(); ! 262: } ! 263: ! 264: int defa = 0; ! 265: switch (base) { ! 266: case 0: ! 267: defa = 1; ! 268: base = INT; ! 269: break; ! 270: case EOBJ: ! 271: case COBJ: ! 272: if (b_name->base == TNAME) error('i',"TN%n inCO %p",b_name,this); ! 273: } ! 274: ! 275: if (b_long || b_short) { ! 276: TOK sl = (b_short) ? SHORT : LONG; ! 277: if (b_long && b_short) error("badBT:long short%k%n",base,n); ! 278: if (base != INT) ! 279: error("badBT:%k%k%n",sl,base,n); ! 280: else ! 281: base = sl; ! 282: b_short = b_long = 0; ! 283: } ! 284: ! 285: if (b_typedef && b_sto) error("badBT:Tdef%k%n",b_sto,n); ! 286: b_typedef = b_sto = 0; ! 287: ! 288: if (b_linkage) { ! 289: if (1 <= bl_level) error("local linkage directive"); ! 290: /* ! 291: Pfct f = Pfct(n->tp); ! 292: while (f && f->base==PTR) f = Pfct(Pptr(f)->typ); ! 293: ! 294: if (f && f->base==FCT) { ! 295: extern linkage; ! 296: set_linkage(b_linkage); ! 297: if (linkage) ! 298: f->f_signature = ""; ! 299: else ! 300: f->sign(); ! 301: set_linkage(0); ! 302: } ! 303: */ ! 304: } ! 305: ! 306: if (Pfctvec_type == 0) return this; ! 307: ! 308: if (b_const) { ! 309: if (b_unsigned) { ! 310: switch (base) { ! 311: default: ! 312: error("badBT: unsigned const %k%n",base,n); ! 313: b_unsigned = 0; ! 314: case LONG: ! 315: case SHORT: ! 316: case INT: ! 317: case CHAR: ! 318: return this; ! 319: } ! 320: } ! 321: return this; ! 322: } ! 323: else if (b_unsigned) { ! 324: switch (base) { ! 325: case LONG: ! 326: delete this; ! 327: return ulong_type; ! 328: case SHORT: ! 329: delete this; ! 330: return ushort_type; ! 331: case INT: ! 332: delete this; ! 333: return uint_type; ! 334: case CHAR: ! 335: delete this; ! 336: return uchar_type; ! 337: default: ! 338: error("badBT: unsigned%k%n",base,n); ! 339: b_unsigned = 0; ! 340: return this; ! 341: } ! 342: } ! 343: else { ! 344: switch (base) { ! 345: case LONG: ! 346: delete this; ! 347: return long_type; ! 348: case SHORT: ! 349: delete this; ! 350: return short_type; ! 351: case INT: ! 352: if (this==int_type || this==defa_type) return this; ! 353: // if (this != int_type) ! 354: delete this; ! 355: if (defa) return defa_type; ! 356: return int_type; ! 357: case CHAR: ! 358: delete this; ! 359: return char_type; ! 360: case VOID: ! 361: delete this; ! 362: return void_type; ! 363: case TYPE: ! 364: /* use a single base saved in the keyword */ ! 365: if (b_name->n_qualifier) { ! 366: Pbase rv = Pbase(b_name->n_qualifier); ! 367: delete this; ! 368: return rv; ! 369: } ! 370: else { ! 371: PERM(this); ! 372: b_name->n_qualifier = (Pname)this; ! 373: return this; ! 374: } ! 375: default: ! 376: return this; ! 377: } ! 378: } ! 379: } ! 380: ! 381: Pname basetype::aggr() ! 382: /* ! 383: "type SM" seen e.g. struct s {}; ! 384: class x; ! 385: enum e; ! 386: int tname; ! 387: friend cname; ! 388: friend class x; ! 389: int; ! 390: ! 391: typedef int i; // where i is tname ! 392: ! 393: convert ! 394: union { ... }; ! 395: into ! 396: union name { ... } name ; ! 397: */ ! 398: { ! 399: if (b_xname) { ! 400: if (base) { ! 401: Pname n = new name(b_xname->string); ! 402: b_xname->hide(); ! 403: b_xname = 0; ! 404: return n->normalize(this,0,0); ! 405: } ! 406: else { ! 407: base = TYPE; ! 408: b_name = b_xname; ! 409: b_xname = 0; ! 410: } ! 411: } ! 412: ! 413: switch (base) { ! 414: case COBJ: ! 415: { Pclass cl = Pclass(b_name->tp); ! 416: char* s = cl->string; ! 417: if (b_name->base == TNAME) error('i',"TN%n inCO",b_name); ! 418: if (b_const) error("const%k%n",cl->csu,b_name); ! 419: ! 420: if (cl->c_body == 2) { /* body seen */ ! 421: if (s[0]=='_' ! 422: && s[1]=='_' ! 423: && s[2]=='C') { ! 424: char* ss = new char[8]; // max size of generated name is 7 chars, see make_name() ! 425: Pname obj = new name(ss); ! 426: strcpy(ss,s); ! 427: if (cl->csu == UNION) { ! 428: ss[2] = 'O'; ! 429: cl->csu = ANON; ! 430: return obj->normalize(this,0,0); ! 431: } ! 432: error('w',"unusable%k ignored",cl->csu); ! 433: } ! 434: cl->c_body = 1; ! 435: return b_name; ! 436: } ! 437: else { /* really a typedef for cfront only: class x; */ ! 438: if (b_sto == FRIEND) goto frr; ! 439: if (ansi_opt) printf("struct %s;\n",s); ! 440: return 0; ! 441: } ! 442: } ! 443: ! 444: case EOBJ: ! 445: { Penum en = Penum(b_name->tp); ! 446: if (b_name->base == TNAME) error('i',"TN%n in enumO",b_name); ! 447: if (b_const) error("const enum%n",b_name); ! 448: if (en->e_body == 2) { ! 449: en->e_body = 1; ! 450: return b_name; ! 451: } ! 452: else { ! 453: error("forward declaration of enum%n", b_name); ! 454: en->e_type = int_type; ! 455: } ! 456: //if (b_sto == FRIEND) goto frr; ! 457: return 0; ! 458: } ! 459: ! 460: case 0: ! 461: { Pname n = new name(make_name('D')); ! 462: n->tp = defa_type; ! 463: error("NX inDL"); ! 464: return n; ! 465: } ! 466: default: ! 467: if (b_typedef) error('w',"illegalTdef ignored"); ! 468: ! 469: if (b_sto == FRIEND && b_name ) { ! 470: frr: ! 471: Pname fr = ktbl->look(b_name->string,0); ! 472: if (fr == 0) error('i',"cannot find friend%n",b_name); ! 473: Pname n = new name(b_name->string); ! 474: n->n_sto = FRIEND; ! 475: //If it is a parametrized type name, use the ! 476: // sepcific instantiation type, and not the general ! 477: // type. ! 478: if ((fr->tp->base == COBJ) && ! 479: (Pclass(Pbase(fr->tp)->b_name->tp)->class_base == ! 480: template_class)) ! 481: { ! 482: if (base == COBJ) n->tp = this ; ! 483: else if ((base == TYPE) && ! 484: (Pbase(this)->b_name->base == TNAME) && ! 485: (Pbase(this)->b_name->tp->base == COBJ)) ! 486: n->tp = Pbase(this)->b_name->tp ; ! 487: else error('i', "basetype wasn't a COBJ") ; ! 488: }else n->tp = fr->tp; ! 489: return n; ! 490: } ! 491: else { ! 492: Pname n = new name(make_name('D')); ! 493: n->tp = this; ! 494: error('w',"NX inDL"); ! 495: return n; ! 496: } ! 497: } ! 498: } ! 499: ! 500: // local class ! 501: extern void local_restore(); ! 502: extern Plist local_blk; ! 503: void local_name() ! 504: { /* need to provide an additional temporary name ! 505: * to handle case of ! 506: * f() { ! 507: * { class x{...}; } ! 508: * { class x{...}; } ! 509: * } ! 510: * generate name after closing } of block ! 511: * to distinquish between separate blocks at same lexical level ! 512: */ ! 513: for (Plist l=local_blk; l; l=l->l) { ! 514: Pname n = l->f; ! 515: if ( n->tp == 0 ) error( 'i', "no tp yet: #0 local_name" ); ! 516: if ( Pbase(n->tp)->b_name == 0 ) error( 'i', "no tp yet: #1 local_name" ); ! 517: Pname bn = Pbase(n->tp)->b_name; ! 518: if ( bn->tp == 0 ) error( 'i', "no tp yet#2: local_name" ); ! 519: Pclass cl = Pclass(bn->tp); ! 520: cl->lcl = make_name( 'L' ); ! 521: // error( 'd', "local_name(): %n bn: %n: cl : %s nof: %d", n, bn, cl->string, cc->nof ); ! 522: } ! 523: } ! 524: ! 525: // local class ! 526: void local_restore() ! 527: { ! 528: for (Plist l=local_tn; l; l=l->l) { ! 529: Pname n = l->f; ! 530: n->n_key = (n->lex_level==0)?0:(n->lex_level && n->lex_level<=bl_level) ? LOCAL : HIDDEN; ! 531: // error( 'd', "local_restore(): %n n_key: %d", n, n->n_key ); ! 532: } ! 533: } ! 534: ! 535: // local class ! 536: void local_hide( Pname n ) ! 537: { ! 538: if ( n->base != TNAME ) return; ! 539: if ( n->n_key == 0 ) ! 540: { ! 541: local_tn = new name_list( n, local_tn ); ! 542: n->n_key = HIDDEN; ! 543: // error( 'd', "local_hide(): %n n_key: %d", n, n->n_key ); ! 544: } ! 545: } ! 546: ! 547: extern int defer_check = 0; ! 548: extern Ptype in_typedef; ! 549: extern Pname in_tag; ! 550: extern Pname statStat = 0; ! 551: ! 552: void name::hide() ! 553: /* ! 554: hide "this": that is, "this" should not be a keyword in this scope ! 555: */ ! 556: { ! 557: if (base != TNAME) return; ! 558: if (n_key == 0) { ! 559: if (lex_level == bl_level && in_arg_list == 0) { ! 560: if (tp->base != COBJ) { ! 561: if ( !in_typedef ) ! 562: error("%nredefined: typedef and identifier", this); ! 563: else if ( in_typedef->base ! 564: && tp->base != type_set(Pbase(in_typedef)) ! 565: && in_typedef->check(tp,0) ) { ! 566: if ( defer_check == 0 ) ! 567: error("%nredefined: previous: %t now: %t", this, tp, in_typedef); ! 568: } ! 569: } ! 570: else { ! 571: if ( in_typedef && ! 572: in_typedef->base && ! 573: in_typedef->check(tp, 0) && ! 574: defer_check == 0 ) { ! 575: error( "%nredefined: previous: %t now: %t", this, tp, in_typedef); ! 576: } ! 577: else { ! 578: Pname nn = Pbase(tp)->b_name; ! 579: Pclass cl = Pclass( nn->tp ); ! 580: if ( cl->has_ctor() ) ! 581: error( "%nredefined: both aCN with constructor and an identifier", this ); ! 582: } ! 583: } ! 584: ! 585: } ! 586: // error( 'd', "%n::hide", this ); ! 587: modified_tn = new name_list(this,modified_tn); ! 588: n_key = HIDDEN; ! 589: } ! 590: } ! 591: ! 592: Pname Ntncheck; // ensure TNAMES hidden within class scopes ! 593: void set_scope(Pname tn) ! 594: /* enter the scope of class tn after seeing "tn::f" */ ! 595: { ! 596: ! 597: // error( 'd', "set_scope: %n", tn ); ! 598: ! 599: Pbase b = Pbase(tn->tp); ! 600: if (b->b_name==0 || b->b_name->tp->base!=CLASS ) return; ! 601: ! 602: Pclass cl = Pclass(b->b_name->tp); ! 603: ! 604: if ( !Ntncheck || strcmp( tn->string, Ntncheck->string )) { ! 605: int i = 1; ! 606: Plist ll = 0; ! 607: Pname n = 0; ! 608: if (b->parametrized_class()) { ! 609: for (Pname nn = cl->mem_list ; nn ; nn = nn->n_list) ! 610: switch (nn->base) { ! 611: case PUBLIC: case PRIVATE: case PROTECTED: ! 612: continue ; ! 613: default: ! 614: if (nn->tp->base == CLASS) continue; ! 615: if (nn->tp->base == ENUM) continue; ! 616: if ((nn->base == NAME) && ! 617: ((nn->n_oper == TNAME) && (nn->tp->base == FCT)) || ! 618: (nn->n_oper == CTOR) || ! 619: (nn->n_oper == DTOR)) ! 620: continue ; ! 621: n = ktbl->look( nn->string, 0 ); ! 622: if (n) ll = new name_list( n, ll ); ! 623: } ! 624: }else ! 625: for (Pname nn=cl->memtbl->get_mem(i); nn; nn=cl->memtbl->get_mem(++i) ) { ! 626: // error( 'd', "set scope: nn: %n %k", nn, nn->tp->base ); ! 627: if (nn->tp->base == CLASS) continue; ! 628: if (nn->tp->base == ENUM) continue; ! 629: if (nn->base == TNAME) continue; ! 630: n = ktbl->look( nn->string, 0 ); ! 631: // if ( n ) error( 'd', "set scope: n: %n key: %d", n, n->n_key ); ! 632: if (n) ll = new name_list( n, ll ); ! 633: } ! 634: ! 635: if ( ll ) cl->tn_list = ll; ! 636: Ntncheck = tn; ! 637: } ! 638: ! 639: for (Plist l=cl->tn_list; l; l=l->l) { ! 640: Pname n = l->f; ! 641: n->n_key = (n->lex_level) ? 0 : HIDDEN; ! 642: // error( 'd', "set scope: tn_list, n: %n n_key: %d n_lex_level: %d", n, n->n_key, n->lex_level ); ! 643: modified_tn = new name_list(n,modified_tn); ! 644: } ! 645: } ! 646: ! 647: void restore() ! 648: { ! 649: for (Plist l=modified_tn; l; l=l->l) { ! 650: Pname n = l->f; ! 651: // error('d',"restore: n %n %t %d bl_level: %d", n, n->tp, n->lex_level, bl_level ); ! 652: n->n_key = (n->lex_level==0 || (n->lex_level && n->lex_level<=bl_level)) ? 0 : HIDDEN; ! 653: if ( n->lex_level == 0 ! 654: && (n->tp->base == COBJ || n->tp->base == EOBJ)) { ! 655: Pname nn = gtbl->look( n->string, 0 ); ! 656: if ( nn ) n->n_key = HIDDEN; ! 657: } ! 658: } ! 659: } ! 660: ! 661: ! 662: // save and restore typenames around a function member declaration. This code ! 663: // fixes a bug where the declaration of a member function with a formal ! 664: // argument name that is the same as an outer type name blocks visibility to ! 665: // the name for the remainder of the class. Note that this fix does not deal ! 666: // correctly with nested class declarations, when the function member contains ! 667: // a class declaration which in turn contains a function declaration. I'm not ! 668: // sure whether such a construct is legal, or even useful, so am avoiding a ! 669: // more convoluted fix. ! 670: static Plist fn_modified_tn = 0 ; ! 671: ! 672: void note_fn_modified_tn() { ! 673: fn_modified_tn = modified_tn ; ! 674: } ! 675: ! 676: ! 677: // restore the tnames that were modified during the processing of the function ! 678: // argument list within a class member. ! 679: void restore_fn_modified_tn(Pname n) { ! 680: ! 681: if ((n->base == NAME) && n->tp && (n->tp->base == FCT)) { ! 682: for (Plist l=modified_tn; l; l=l->l) ! 683: if (l == fn_modified_tn) { ! 684: modified_tn = fn_modified_tn ; ! 685: return ; ! 686: }else{ ! 687: Pname n = l->f ; ! 688: // code below courtesy of name::restore above ! 689: n->n_key = (n->lex_level==0 || ! 690: (n->lex_level && n->lex_level<=bl_level)) ? 0 : HIDDEN; ! 691: if ( n->lex_level == 0 ! 692: && (n->tp->base == COBJ || n->tp->base == EOBJ)) { ! 693: Pname nn = gtbl->look( n->string, 0 ); ! 694: if ( nn ) n->n_key = HIDDEN; ! 695: } ! 696: } ! 697: } ! 698: fn_modified_tn = modified_tn ; ! 699: } ! 700: ! 701: ! 702: ! 703: ! 704: Pbase start_cl(TOK t, Pname c, Pbcl b) ! 705: { ! 706: int mk_local = 0; ! 707: if (c == 0) ! 708: { ! 709: extern int in_class_decl; ! 710: c = new name(make_name('C')); ! 711: c->lex_level -= in_class_decl + 1; ! 712: if ( in_typedef && c->lex_level ) ! 713: mk_local = 1; ! 714: else c->lex_level = 0; ! 715: } ! 716: ! 717: for ( Pclass tc = ccl; tc; tc = tc->in_class ) ! 718: if ( tc->lex_level == c->lex_level && ! 719: strcmp( tc->string, c->string) == 0) { ! 720: error( "C %s redefined", c->string ); ! 721: c->tp = any_type; ! 722: return Pbase(any_type); ! 723: } ! 724: ! 725: Pname n = c->tname(t); /* t ignored */ ! 726: ! 727: if (templp->in_progress && (c->lex_level == 0)) ! 728: // bring the template in scope ! 729: templp->introduce_class_templ(n) ; ! 730: ! 731: // typedef struct {} x; ! 732: if ( mk_local ) { ! 733: n->n_key = LOCAL; ! 734: extern Plist local_blk, local_class; // place in cfront.h ! 735: local_class = new name_list( n, local_class ); ! 736: local_blk = new name_list( n, local_blk ); ! 737: modified_tn = modified_tn->l; ! 738: } ! 739: ! 740: n->where = curloc; ! 741: Pbase bt = Pbase(n->tp); /* COBJ */ ! 742: if (bt->base != COBJ) { ! 743: error("twoDs of%n:%t andC",n,bt); ! 744: error('i', "can't recover from previous errors"); ! 745: } ! 746: Pclass occl = ccl; ! 747: ccl = Pclass(bt->b_name->tp); /* CLASS */ ! 748: if (ccl->defined) ccl->defined |= IN_ERROR; ! 749: ccl->defined |= DEF_SEEN; ! 750: if (ccl->in_class = occl) { ! 751: occl->tn_list = modified_tn; // save mod-list ! 752: modified_tn = 0; ! 753: } ! 754: ! 755: Ntncheck = 0; // zero it out with each new class declaration ! 756: ccl->string = n->string; ! 757: ccl->csu = t; ! 758: if (b) { // list of base classes ! 759: for (Pbcl bx, bb=b, l=0; bb; bb = bx) { ! 760: bx = bb->next; ! 761: bb->next = 0; ! 762: ! 763: if (l == 0) l = bb; ! 764: else { // append and check for duplicates ! 765: for (Pbcl ll = l;;) { ! 766: if (bb->bclass && ll->bclass==bb->bclass) { ! 767: error("%s has %s asB twice",ccl->string,bb->bclass->string); ! 768: break; ! 769: } ! 770: ! 771: if (ll->next) ! 772: ll = ll->next; ! 773: else { ! 774: bb->next = l; ! 775: l = bb; ! 776: break; ! 777: } ! 778: } ! 779: } ! 780: } ! 781: ccl->baselist = l; ! 782: } ! 783: return bt; ! 784: } ! 785: ! 786: void end_cl() ! 787: { ! 788: Pclass occl = ccl->in_class; ! 789: Plist ol = occl ? occl->tn_list : 0; // saved modified name list ! 790: ccl->c_body = 2; ! 791: ! 792: if (modified_tn) { // export nested class names to outer scope: ! 793: Plist local = 0; ! 794: for (Plist l=modified_tn, nl=0; l; l=nl) { ! 795: nl = l->l; ! 796: Pname n = l->f; ! 797: if (ktbl->look(n->string,0)) { ! 798: // add it to enclosing class's modified name list ! 799: l->l = ol; ! 800: ol = l; ! 801: } ! 802: else { // retain it in this class's modified name list ! 803: l->l = local; ! 804: local = l; ! 805: } ! 806: } ! 807: if (ccl->tn_list = modified_tn = local) restore(); ! 808: } ! 809: modified_tn = ol; // restore mod-list (possibly modified) ! 810: ccl = occl; ! 811: } ! 812: ! 813: extern int in_class_decl; ! 814: Pbase end_enum(Pname n, Pname b) ! 815: { ! 816: if (n == 0) n = new name(make_name('E')); ! 817: n = n->tname(ENUM); ! 818: Pbase bt = (Pbase)n->tp; ! 819: if (bt->base != EOBJ) { ! 820: error("twoDs of%n:%t and enum",n,bt); ! 821: error('i', "can't recover from previous errors"); ! 822: } ! 823: Penum en = (Penum)bt->b_name->tp; ! 824: en->e_body = 2; ! 825: en->mem = name_unlist((class nlist *)b); ! 826: if (en->defined) { ! 827: if ( in_class_decl ) ! 828: error("%nredefined, enum tag not local to class", n); ! 829: en->defined |= IN_ERROR; ! 830: } ! 831: en->defined |= DEF_SEEN; ! 832: return bt; ! 833: } ! 834: ! 835: Pname name::tdef() ! 836: /* ! 837: typedef "this" ! 838: */ ! 839: { ! 840: // error('d', "%n->tdef() %t", this, tp ); ! 841: int anon_cl = 0; ! 842: if (n_qualifier) { ! 843: error("QdN in typedef",this); ! 844: n_qualifier = 0; ! 845: } ! 846: ! 847: lex_level = bl_level - in_class_decl; ! 848: Pname n = ktbl->insert(this,0); ! 849: if (tp == 0) error('i',"Tdef%n tp==0",this); ! 850: n->base = base = TNAME; ! 851: PERM(n); ! 852: PERM(tp); ! 853: ! 854: if (tp->base == COBJ || tp->base == EOBJ ) ! 855: { // typedef struct/enum { } s; => struct/enum s {}; ! 856: Pname b = Pbase(tp)->b_name; ! 857: if (b->string[0] == '_' && b->string[1] == '_' ) ! 858: switch ( tp->base ) { ! 859: case COBJ: { ! 860: if (b->string[2] == 'C') { ! 861: Pclass cl = Pclass(b->tp); ! 862: b->string = n->string; ! 863: cl->string = n->string; ! 864: cl->strlen = strlen(cl->string); ! 865: if ( lex_level ) { ! 866: anon_cl = 1; ! 867: n->n_key = LOCAL; ! 868: } ! 869: } ! 870: break; ! 871: } ! 872: case EOBJ: { ! 873: if (b->string[2] == 'E') { ! 874: Penum en = Penum(b->tp); ! 875: b->string = n->string; ! 876: en->string = n->string; ! 877: en->strlen = strlen(en->string); ! 878: } ! 879: } ! 880: } ! 881: } ! 882: ! 883: if ( anon_cl == 0 ) ! 884: modified_tn = new name_list(n,modified_tn); ! 885: return n; ! 886: } ! 887: ! 888: Pname name::tname(TOK csu) ! 889: /* ! 890: "csu" "this" seen, return typedef'd name for "this" ! 891: return (TNAME,x) ! 892: x: (COBJ,y) ! 893: y: (NAME,z) ! 894: z: (CLASS,ae); ! 895: */ ! 896: { ! 897: switch (base) { ! 898: case TNAME: ! 899: return this; ! 900: case NAME: ! 901: { Pname tn = ktbl->insert(this,0); ! 902: // error('d',"tname %n",this); ! 903: Pname on = new name; ! 904: tn->base = TNAME; ! 905: tn->lex_level = lex_level; ! 906: modified_tn = new name_list(tn,modified_tn); ! 907: tn->n_list = n_list = 0; ! 908: string = tn->string; ! 909: *on = *this; ! 910: switch (csu) { ! 911: case ENUM: ! 912: tn->tp = new basetype(EOBJ,on); ! 913: on->tp = new enumdef(0); ! 914: Penum(on->tp)->string = tn->string; ! 915: break; ! 916: default: ! 917: on->tp = new classdef(csu); ! 918: Pclass(on->tp)->string = tn->string; ! 919: Pclass(on->tp)->lex_level = lex_level; ! 920: tn->tp = new basetype(COBJ,on); ! 921: Pbase(tn->tp)->b_table = Pclass(on->tp)->memtbl; ! 922: } ! 923: PERM(tn); ! 924: PERM(tn->tp); ! 925: PERM(on); ! 926: PERM(on->tp); ! 927: return tn; ! 928: } ! 929: default: ! 930: error('i',"tname(%s %d %k)",string,this,base); ! 931: } ! 932: } ! 933: ! 934: int co_hack; ! 935: Pname name::normalize(Pbase b, Pblock bl, bit Cast) ! 936: /* ! 937: if (bl) : a function definition (check that it really is a type ! 938: ! 939: if (Cast) : no name string ! 940: ! 941: for each name on the name list ! 942: invert the declarator list(s) and attatch basetype ! 943: watch out for class object initializers ! 944: ! 945: convert ! 946: struct s { int a; } a; ! 947: into ! 948: struct s { int a; }; struct s a; ! 949: */ ! 950: { ! 951: Pname n; ! 952: Pname nn; ! 953: TOK stc; ! 954: bit tpdf; ! 955: bit inli; ! 956: bit virt; ! 957: char * lnkg; ! 958: // error('d',"%n::normalize b %k",this,b->base); ! 959: if (b) { ! 960: stc = b->b_sto; ! 961: tpdf = b->b_typedef; ! 962: inli = b->b_inline; ! 963: virt = b->b_virtual; ! 964: lnkg = b->b_linkage; ! 965: } ! 966: else { ! 967: stc = 0; ! 968: tpdf = 0; ! 969: inli = 0; ! 970: virt = 0; ! 971: lnkg = 0; ! 972: } ! 973: ! 974: if (inli && stc==EXTERN) { ! 975: error("both extern and inline"); ! 976: inli = 0; ! 977: } ! 978: ! 979: if (stc==FRIEND && tp==0) { ! 980: /* friend x; ! 981: must be handled during syntax analysis to cope with ! 982: class x { friend y; y* p; }; ! 983: "y" is not local to "x": ! 984: class x { friend y; ... }; y* p; ! 985: is legal ! 986: ! 987: examples: ! 988: ! 989: typedef void SIG_TYP(int); ! 990: class x { ! 991: friend class y; ! 992: friend z; ! 993: friend x; // dumb ! 994: friend int i; // error ! 995: friend SIG_TYP sigFunc; // subtle ! 996: friend int f(); ! 997: friend g(int); ! 998: }; ! 999: */ ! 1000: if (b && (b->base || b->b_name || b->b_xname)) goto ccc; ! 1001: ! 1002: if (n_list) { ! 1003: error("L of friends"); ! 1004: n_list = 0; ! 1005: } ! 1006: ! 1007: if (!Cast) { ! 1008: Pname nn = gtbl->look( string, 0 ); ! 1009: if ( nn ) { ! 1010: if (nn->tp->base == FCT) ! 1011: error("friendF must include signature:%n", this ); ! 1012: else ! 1013: error("illegal friend declaration:%n", this ); ! 1014: } ! 1015: } ! 1016: ! 1017: //error( 'd', "%n ll: %d", ccl, ccl->lex_level ); ! 1018: lex_level = ccl->lex_level; ! 1019: Pname nx = tname(CLASS); ! 1020: modified_tn = modified_tn->l; /* global */ ! 1021: n_sto = FRIEND; ! 1022: tp = nx->tp; ! 1023: return this; ! 1024: } ! 1025: ccc: ! 1026: if (tp // FUDGE: fix the bad grammar ! 1027: && tp->base==FCT ! 1028: && (n_oper==TNAME || Pfct(tp)->returns)) { ! 1029: Pfct f = Pfct(tp); ! 1030: Pfct f2 = Pfct(f->returns); ! 1031: ! 1032: if (f2) { ! 1033: Ptype pt; ! 1034: Ptype t = f2; ! 1035: lxlx: ! 1036: switch (t->base) { ! 1037: case PTR: // x(* p)(args) ? ! 1038: case VEC: // x(* p[10])(args) ? ! 1039: if (pt = Pptr(t)->typ) { ! 1040: if (pt->base == TYPE) { ! 1041: Pptr(t)->typ = 0; ! 1042: b = Pbase(pt); ! 1043: // stc = b->b_sto; ! 1044: // tpdf = b->b_typedef; ! 1045: // inli = b->b_inline; ! 1046: // virt = b->b_virtual; ! 1047: } ! 1048: else { ! 1049: t = pt; ! 1050: goto lxlx; ! 1051: } ! 1052: } ! 1053: goto zse1; ! 1054: case FCT: ! 1055: {// Pexpr e = f2->argtype; ! 1056: Pexpr e = Pfct(f)->argtype; ! 1057: if (e && e->base==ELIST) { // get the real name; fix its type ! 1058: if (e->e2 || e->e1->base!=DEREF) goto zse1; ! 1059: Pexpr ee = e->e1; ! 1060: Ptype t = 0; ! 1061: Ptype tpx; ! 1062: ldld: ! 1063: switch (ee->base) { ! 1064: case DEREF: ! 1065: { Ptype tt = (ee->e2) ? Ptype(new vec(0,ee->e2)) : Ptype (new ptr(PTR,0)); ! 1066: if (t) ! 1067: Pptr(t)->typ = tt; ! 1068: else ! 1069: tpx = tt; ! 1070: t = tt; ! 1071: ee = ee->e1; ! 1072: goto ldld; ! 1073: } ! 1074: case NAME: ! 1075: { Pname rn = Pname(ee); ! 1076: b = new basetype(TYPE,ktbl->look(string,0)); ! 1077: f->returns = tpx; ! 1078: n_oper = 0; ! 1079: string = rn->string; ! 1080: base = NAME; ! 1081: } ! 1082: } ! 1083: } ! 1084: } ! 1085: } ! 1086: } ! 1087: } ! 1088: ! 1089: zse1: ! 1090: if (b == 0) { ! 1091: error("BTX for %s",string); ! 1092: b = Pbase(defa_type); ! 1093: } ! 1094: ! 1095: if (Cast) string = ""; ! 1096: b = b->check(this); ! 1097: ! 1098: switch (b->base) { // separate class definitions ! 1099: // from object and function type declarations ! 1100: case COBJ: ! 1101: nn = b->b_name; ! 1102: ! 1103: if (Pclass(nn->tp)->c_body==2) { /* first occurrence */ ! 1104: if (tp && tp->base==FCT && co_hack == 0) { ! 1105: error(&this->where,"%k%n defined as returnT for%n (did you forget a ';' after '}' ?)",Pclass(nn->tp)->csu,nn,this); ! 1106: nn = this; ! 1107: break; ! 1108: } ! 1109: nn->n_list = this; ! 1110: Pclass(nn->tp)->c_body = 1; /* other occurences */ ! 1111: } ! 1112: else ! 1113: nn = this; ! 1114: break; ! 1115: case EOBJ: ! 1116: nn = b->b_name; ! 1117: if (Penum(nn->tp)->e_body==2) { ! 1118: if (tp && tp->base==FCT) { ! 1119: error(&this->where,"enum%n defined as returnT for%n (did you forget a ';'?)",nn,this); ! 1120: nn = this; ! 1121: break; ! 1122: } ! 1123: nn->n_list = this; ! 1124: Penum(nn->tp)->e_body = 1; ! 1125: } ! 1126: else { ! 1127: Penum en = Penum(nn->tp); ! 1128: if ( en->defined == 0 ) ! 1129: error( "forward declaration of enum%n", nn ); ! 1130: en->e_type = int_type; ! 1131: nn = this; ! 1132: } ! 1133: break; ! 1134: default: ! 1135: nn = this; ! 1136: } ! 1137: ! 1138: Pname nx; ! 1139: for (n=this; n; n=nx) { ! 1140: Ptype t = n->tp; ! 1141: nx = n->n_list; ! 1142: n->n_sto = stc; ! 1143: ! 1144: if (n->base == TNAME) error('i',"redefinition ofTN%n",n); ! 1145: ! 1146: if (t == 0) { ! 1147: if (bl == 0) ! 1148: n->tp = t = b; ! 1149: else { ! 1150: error("body of nonF%n",n); ! 1151: t = new fct(defa_type,0,0); ! 1152: } ! 1153: } ! 1154: ! 1155: switch (t->base) { ! 1156: case PTR: ! 1157: case RPTR: ! 1158: n->tp = Pptr(t)->normalize(b); ! 1159: break; ! 1160: case VEC: ! 1161: n->tp = Pvec(t)->normalize(b); ! 1162: break; ! 1163: case FCT: ! 1164: n->tp = Pfct(t)->normalize(b); ! 1165: break; ! 1166: case FIELD: ! 1167: if (n->string == 0) n->string = make_name('F'); ! 1168: n->tp = t; ! 1169: Pbase tb = b; ! 1170: // error('d', "field t %k tb %k", t->base, tb->base ); ! 1171: flatten: ! 1172: switch (tb->base) { ! 1173: case TYPE: /* chase typedefs */ ! 1174: tb = (Pbase)tb->b_name->tp; ! 1175: goto flatten; ! 1176: case CHAR: ! 1177: case SHORT: ! 1178: case EOBJ: ! 1179: case INT: ! 1180: // typedef const unsigned cu_int; ! 1181: // struct x { x(); cu_int b1: 2; } ! 1182: ! 1183: Pbase(t)->b_fieldtype = (b->b_unsigned||tb->b_unsigned) ? uint_type : int_type; ! 1184: // goto iii; ! 1185: // case CHAR: ! 1186: // Pbase(t)->b_fieldtype = (b->b_unsigned) ? uchar_type : char_type; ! 1187: // goto iii; ! 1188: // case SHORT: ! 1189: // Pbase(t)->b_fieldtype = (b->b_unsigned) ? ushort_type : short_type; ! 1190: // goto iii; ! 1191: // iii: ! 1192: Pbase(t)->b_unsigned = b->b_unsigned?b->b_unsigned:tb->b_unsigned; ! 1193: Pbase(t)->b_const = b->b_const?b->b_const:tb->b_const; ! 1194: break; ! 1195: default: ! 1196: error("non-int field"); ! 1197: n->tp = defa_type; ! 1198: } ! 1199: break; ! 1200: } ! 1201: ! 1202: Pfct f = Pfct(n->tp); ! 1203: ! 1204: if (f->base != FCT) { ! 1205: if (bl) { ! 1206: error("body for nonF%n",n); ! 1207: n->tp = f = new fct(defa_type,0,0); ! 1208: continue; ! 1209: } ! 1210: if (inli) error("inline nonF%n",n); ! 1211: if (virt) error("virtual nonF%n",n); ! 1212: ! 1213: if (tpdf) { ! 1214: if (n->n_initializer) { ! 1215: error("Ir forTdefN%n",n); ! 1216: n->n_initializer = 0; ! 1217: } ! 1218: n->tdef(); ! 1219: } ! 1220: continue; ! 1221: } ! 1222: ! 1223: if (lnkg) { ! 1224: extern linkage; ! 1225: set_linkage(lnkg); ! 1226: if (linkage) ! 1227: f->f_signature = ""; ! 1228: else ! 1229: f->sign(); ! 1230: set_linkage(0); ! 1231: } ! 1232: ! 1233: f->f_inline = inli; ! 1234: extern int vcounter; ! 1235: f->f_virtual = virt?(vcounter++,VTOK):0; ! 1236: ! 1237: if (tpdf) { ! 1238: if (f->body = bl) error("Tdef%n { ... }",n); ! 1239: if (n->n_qualifier) { ! 1240: // typedef T x::f(args); ! 1241: // a pointer to member fucntion: ! 1242: // equivalent to typedef T x::(f)(args); ! 1243: f->memof = Pclass(Pbase(n->n_qualifier->tp)->b_name->tp); ! 1244: n->n_qualifier = 0; ! 1245: } ! 1246: n->tdef(); ! 1247: continue; ! 1248: } ! 1249: ! 1250: if (f->body = bl) continue; ! 1251: ! 1252: /* ! 1253: Check function declarations. ! 1254: Look for class object instansiations ! 1255: The real ambiguity: ; class x fo(); ! 1256: is interpreted as an extern function ! 1257: declaration NOT a class object with an ! 1258: empty initializer ! 1259: */ ! 1260: { Pname cn = f->returns->is_cl_obj(); ! 1261: Ptype template_formal_type ; ! 1262: ! 1263: bit clob = (cn || cl_obj_vec); ! 1264: if (f->argtype) { ! 1265: /* check argument/initializer list */ ! 1266: Pname nn; ! 1267: ! 1268: for (nn=f->argtype; nn; nn=nn->n_list) { ! 1269: if (nn->base != NAME) { ! 1270: if (!clob) { ! 1271: if ((f->returns->base == TYPE) && ! 1272: (Pbase(f->returns)->b_name->n_template_arg == template_type_formal)) ! 1273: { ! 1274: // T x(var) ; wher T is a template formal ! 1275: // it could be a class when ! 1276: // instantiated, wait until then to ! 1277: // issue an error messsage. ! 1278: template_formal_type = f->returns ; ! 1279: Pbase(f->returns)->b_name->n_template_formal_must_be_class = 1 ; ! 1280: goto is_obj ; ! 1281: } ! 1282: ! 1283: error("ATX for%n",n); ! 1284: goto zzz; ! 1285: } ! 1286: goto is_obj; ! 1287: } ! 1288: /* ! 1289: if (nn->string) { ! 1290: error("AN%n inD of%n",nn,n); ! 1291: nn->string = 0; ! 1292: } ! 1293: */ ! 1294: if (nn->tp) goto ok; ! 1295: } ! 1296: if (!clob) { ! 1297: error("FALX"); ! 1298: goto zzz; ! 1299: } ! 1300: is_obj: ! 1301: /* it was an initializer: expand to constructor */ ! 1302: n->tp = f->returns; ! 1303: if (f->argtype->base != ELIST) f->f_args = f->argtype = (Pname)new expr(ELIST,(Pexpr)f->argtype,0); ! 1304: n->n_initializer = new texpr(VALUE, ! 1305: (cn ? cn->tp : ! 1306: template_formal_type) ! 1307: ,(Pexpr)f->argtype); ! 1308: goto ok; ! 1309: zzz: ! 1310: if (f->argtype) { ! 1311: DEL(f->argtype); ! 1312: f->argtype = 0; ! 1313: f->nargs = 0; ! 1314: f->nargs_known = 1; ! 1315: } ! 1316: } ! 1317: else { /* T a(); => function declaration */ ! 1318: /* ! 1319: if (clob) { ! 1320: DEL(n->tp); ! 1321: n->tp = f->returns; ! 1322: } ! 1323: */ ! 1324: } ! 1325: ok: ! 1326: ; ! 1327: } ! 1328: } ! 1329: return nn; ! 1330: } ! 1331: ! 1332: Ptype vec::normalize(Ptype vecof) ! 1333: { ! 1334: Ptype t = typ; ! 1335: typ = vecof; ! 1336: if (t == 0) return this; ! 1337: ! 1338: xx: ! 1339: switch (t->base) { ! 1340: case TYPE: t = Pbase(t)->b_name->tp; ! 1341: goto xx; ! 1342: case PTR: ! 1343: case RPTR: return Pptr(t)->normalize(this); ! 1344: case VEC: return Pvec(t)->normalize(this); ! 1345: case FCT: return Pfct(t)->normalize(this); ! 1346: default: error('i',"bad arrayT(%d)",t->base); ! 1347: } ! 1348: ! 1349: } ! 1350: ! 1351: Ptype ptr::normalize(Ptype ptrto) ! 1352: { ! 1353: // if (this == 0) error('i',"0->ptr.normalize()"); ! 1354: Ptype t = typ; ! 1355: typ = ptrto; ! 1356: ! 1357: int bc = 0; ! 1358: while (ptrto->base == TYPE) { ! 1359: bc += Pbase(ptrto)->b_const; ! 1360: ptrto = Pbase(ptrto)->b_name->tp; ! 1361: } ! 1362: ! 1363: switch (ptrto->base) { ! 1364: case FCT: ! 1365: if (memof) ! 1366: if (Pfct(ptrto)->memof) { ! 1367: if (memof != Pfct(ptrto)->memof) error("P toMF mismatch: %s and %s",memof->string, Pfct(ptrto)->memof->string); ! 1368: } ! 1369: else ! 1370: Pfct(ptrto)->memof = memof; ! 1371: else ! 1372: memof = Pfct(ptrto)->memof; ! 1373: break; ! 1374: case RPTR: ! 1375: switch (base) { ! 1376: case PTR: error("P toR"); break; ! 1377: case RPTR: error("R toR"); break; ! 1378: } ! 1379: } ! 1380: ! 1381: if (t == 0) { ! 1382: Pbase b = Pbase(ptrto); ! 1383: if (Pfctvec_type ! 1384: && rdo==0 ! 1385: && b->b_unsigned==0 ! 1386: && b->b_const==0 ! 1387: && bc == 0 ! 1388: && memof==0 ! 1389: && base==PTR) { ! 1390: switch (b->base) { ! 1391: case INT: delete this; return Pint_type; ! 1392: case CHAR: delete this; return Pchar_type; ! 1393: case VOID: delete this; return Pvoid_type; ! 1394: } ! 1395: } ! 1396: if (base==RPTR && b->base==VOID) error("void& is not a validT"); ! 1397: return this; ! 1398: } ! 1399: ! 1400: xx: ! 1401: switch (t->base) { ! 1402: case TYPE: t = Pbase(t)->b_name->tp; ! 1403: goto xx; ! 1404: case PTR: ! 1405: case RPTR: return Pptr(t)->normalize(this); ! 1406: case VEC: if (base == RPTR) error("array ofRs"); ! 1407: return Pvec(t)->normalize(this); ! 1408: case FCT: return Pfct(t)->normalize(this); ! 1409: default: error('i',"badPT(%k)",t->base); ! 1410: } ! 1411: } ! 1412: ! 1413: Ptype fct::normalize(Ptype ret) ! 1414: /* ! 1415: normalize return type ! 1416: */ ! 1417: { ! 1418: register Ptype t = returns; ! 1419: returns = ret; ! 1420: ! 1421: if (argtype && argtype->base==NAME && argtype->n_qualifier) { ! 1422: error("syntax: ANX"); ! 1423: argtype = 0; ! 1424: nargs = 0; ! 1425: nargs_known = 0; ! 1426: } ! 1427: ! 1428: if (t == 0) return this; ! 1429: xx: ! 1430: switch (t->base) { ! 1431: case PTR: ! 1432: case RPTR: return Pptr(t)->normalize(this); ! 1433: case VEC: error("array ofFs"); ! 1434: return Pvec(t)->normalize(this); ! 1435: case FCT: return Pfct(t)->normalize(this); ! 1436: case TYPE: t = Pbase(t)->b_name->tp; goto xx; ! 1437: default: error('i',"badFT:%k",t->base); ! 1438: } ! 1439: ! 1440: } ! 1441: ! 1442: ! 1443: void fct::argdcl(Pname dcl, Pname fn) ! 1444: /* ! 1445: sort out the argument types for old syntax: ! 1446: f(a,b) int a; char b; { ... } ! 1447: beware of ! 1448: f(a) struct s { int a; }; struct s a; ! 1449: */ ! 1450: { ! 1451: Pname n; ! 1452: /*fprintf(stderr,"%d argtype %d %d dcl %d %d\n",this, argtype, argtype?argtype->base:0, dcl, dcl?dcl->base:0); fflush(stderr);*/ ! 1453: switch (base) { ! 1454: case FCT: break; ! 1455: case ANY: return; ! 1456: default: error('i',"fct::argdcl(%d)",base); ! 1457: } ! 1458: ! 1459: if (argtype) { ! 1460: switch (argtype->base) { ! 1461: case NAME: ! 1462: if (dcl) error("badF definition syntax"); ! 1463: for (n=argtype; n; n=n->n_list) { ! 1464: if (n->string == 0) n->string = make_name('A'); ! 1465: } ! 1466: return; ! 1467: case ELIST: // expression list: f(a,b,c) int a; ... { ... } ! 1468: // scan the elist and build a NAME list ! 1469: { ! 1470: Pname tail = 0; ! 1471: n = 0; ! 1472: ! 1473: error(strict_opt?0:'w',&fn->where,"old style definition of%n",fn); ! 1474: ! 1475: for (Pexpr e=Pexpr(argtype); e; e=e->e2) { ! 1476: Pexpr id = e->e1; ! 1477: if (id->base != NAME) { ! 1478: error("NX inAL"); ! 1479: argtype = 0; ! 1480: dcl = 0; ! 1481: break; ! 1482: } ! 1483: Pname nn = new name(id->string); ! 1484: if (n) ! 1485: tail = tail->n_list = nn; ! 1486: else ! 1487: tail = n = nn; ! 1488: } ! 1489: f_args = argtype = n; ! 1490: break; ! 1491: } ! 1492: default: ! 1493: error("ALX(%d)",argtype->base); ! 1494: argtype = 0; ! 1495: dcl = 0; ! 1496: } ! 1497: } ! 1498: else { ! 1499: nargs_known = 1; ! 1500: nargs = 0; ! 1501: if (dcl) error("ADL forFWoutAs"); ! 1502: return; ! 1503: } ! 1504: ! 1505: // nargs_known = 0; ! 1506: ! 1507: if (dcl) { ! 1508: Pname d; ! 1509: Pname dx; ! 1510: /* for each argument name see if its type is specified ! 1511: in the declaration list otherwise give it the default type ! 1512: */ ! 1513: ! 1514: for (n=argtype; n; n=n->n_list) { ! 1515: char* s = n->string; ! 1516: if (s == 0) { ! 1517: error("AN missing inF definition"); ! 1518: n->string = s = make_name('A'); ! 1519: } ! 1520: else if (n->tp) error("twoTs forA %s",n->string); ! 1521: ! 1522: for (d=dcl; d; d=d->n_list) { ! 1523: if (strcmp(s,d->string) == 0) { ! 1524: if (d->tp->base == VOID) { ! 1525: error("voidA%n",d); ! 1526: d->tp = any_type; ! 1527: } ! 1528: n->tp = d->tp; ! 1529: n->n_sto = d->n_sto; ! 1530: d->tp = 0; // now merged into argtype ! 1531: goto xx; ! 1532: } ! 1533: } ! 1534: n->tp = defa_type; ! 1535: xx:; ! 1536: if (n->tp == 0) error('i',"noT for %s",n->string); ! 1537: } ! 1538: ! 1539: /* now scan the declaration list for "unused declarations" ! 1540: and delete it ! 1541: */ ! 1542: for (d=dcl; d; d=dx) { ! 1543: dx = d->n_list; ! 1544: if (d->tp) { /* not merged with argtype list */ ! 1545: /*if (d->base == TNAME) ??? */ ! 1546: switch (d->tp->base) { ! 1547: case CLASS: ! 1548: case ENUM: ! 1549: /* WARNING: this will reverse the order of ! 1550: class and enum declarations ! 1551: */ ! 1552: d->n_list = argtype; ! 1553: f_args = argtype = d; ! 1554: break; ! 1555: default: ! 1556: error("%n inADL not inAL",d); ! 1557: } ! 1558: } ! 1559: } ! 1560: } ! 1561: ! 1562: /* add default argument types if necessary */ ! 1563: for (n=argtype; n; n=n->n_list) { ! 1564: if (n->tp == 0) n->tp = defa_type; ! 1565: nargs++; ! 1566: } ! 1567: } ! 1568: ! 1569: Pname cl_obj_vec; /* set if is_cl_obj() found a array of class objects */ ! 1570: Pname eobj; /* set if is_cl_obj() found an enum */ ! 1571: ! 1572: Pname type::is_cl_obj() ! 1573: /* ! 1574: returns this->b_name if this is a class object ! 1575: returns 0 and sets cl_obj_vec to this->b_name ! 1576: if this is a array of class objects ! 1577: returns 0 and sets eobj to this->b_name ! 1578: if this is an enum object ! 1579: else returns 0 ! 1580: */ ! 1581: { ! 1582: bit v = 0; ! 1583: register Ptype t = this; ! 1584: ! 1585: if (t == 0) return 0; ! 1586: eobj = 0; ! 1587: cl_obj_vec = 0; ! 1588: xx: ! 1589: switch (t->base) { ! 1590: case TYPE: ! 1591: t = Pbase(t)->b_name->tp; ! 1592: goto xx; ! 1593: ! 1594: case COBJ: ! 1595: if (v) { ! 1596: cl_obj_vec = Pbase(t)->b_name; ! 1597: return 0; ! 1598: } ! 1599: else ! 1600: return Pbase(t)->b_name; ! 1601: ! 1602: case VEC: ! 1603: t = Pvec(t)->typ; ! 1604: v=1; ! 1605: goto xx; ! 1606: ! 1607: case EOBJ: ! 1608: eobj = Pbase(t)->b_name; ! 1609: default: ! 1610: return 0; ! 1611: } ! 1612: } ! 1613: ! 1614: /* ODI notes - ! 1615: ! 1616: template class changes ! 1617: */ ! 1618: ! 1619:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.