|
|
1.1 ! root 1: 0707071010112043441004440001630000160000010075200466055374000001000000013411alloc.c /*ident "@(#)ctrans:src/alloc.c 1.4" */ ! 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: alloc.c: ! 11: ! 12: *****************************************************************************/ ! 13: #include "cfront.h" ! 14: #include "size.h" ! 15: #include "sysent.h" ! 16: ! 17: const int NBITE = (CHUNK-8)/sizeof(name)-1; ! 18: const int EBITE = (CHUNK-8)/sizeof(expr)-1; ! 19: const int SBITE = (CHUNK-8)/sizeof(stmt)-1; ! 20: const int TBITE = (CHUNK-8)/sizeof(table)-1; ! 21: const int VBITE = (CHUNK-8)/sizeof(vec)-1; ! 22: const int FBITE = (CHUNK-8)/sizeof(fct)-1; ! 23: const int PBITE = (CHUNK-8)/sizeof(ptr)-1; ! 24: ! 25: #define mzero(p,l) memset(p,0,l) ! 26: ! 27: void* chunk(int i) // get memory that is not to be freed ! 28: { ! 29: register char* cp = malloc(i*CHUNK-8); ! 30: if (cp == 0) { // no space ! 31: free((char*)gtbl); // get space for error message ! 32: error('i',"free store exhausted"); ! 33: } ! 34: return cp; ! 35: } ! 36: ! 37: #ifdef __HAVE_SIZE_T ! 38: #include <new.h> ! 39: #define NEW_SIZE size_t ! 40: #else ! 41: #define NEW_SIZE long ! 42: #endif ! 43: ! 44: void* operator new(NEW_SIZE sz) // get memory that might be freed ! 45: { ! 46: char* p = calloc((unsigned)sz,1); ! 47: ! 48: //fprintf(stderr,"alloc(%d)->%d\n",sz,p); ! 49: ! 50: if (p == 0) { // no space ! 51: free((char*)gtbl); // get space for error message ! 52: error('i',"free store exhausted"); ! 53: } ! 54: return p; ! 55: } ! 56: ! 57: void operator delete (void* p) ! 58: { ! 59: if (p == 0) return; ! 60: ! 61: //fprintf(stderr,"free(%d) %d\n",p,((int*)p)[-1]-(int)p-1+sizeof(int*)); ! 62: ! 63: free((char*)p); ! 64: } ! 65: ! 66: // class new and delete operators ! 67: ! 68: void* ! 69: expr::operator new(size_t sz) ! 70: { ! 71: register Pexpr p; ! 72: ! 73: if ( (p=expr_free) == 0 ) { ! 74: register Pexpr q = (Pexpr) chunk(1); ! 75: for (p=expr_free=&q[EBITE-1]; q<p; p--) { ! 76: p->e1 = p-1; ! 77: DB(p->node::allocated=0); ! 78: } ! 79: (p+1)->e1 = 0; ! 80: DB(p->node::allocated=0); ! 81: } ! 82: else ! 83: expr_free = p->e1; ! 84: ! 85: mzero(p,sz); ! 86: return p; ! 87: } ! 88: ! 89: void ! 90: expr::operator delete(void* vp, size_t) ! 91: { ! 92: Pexpr p = (Pexpr)vp; ! 93: ! 94: DB( if(!p->node::allocated) error('i',"deleting unallocated expr:%k! -- id==%d",p->base,p->node::id); ! 95: p->node::allocated = 0; ! 96: ); ! 97: p->e1 = expr_free; ! 98: expr_free = p; ! 99: vp = 0; ! 100: } ! 101: ! 102: void* ! 103: stmt::operator new(size_t sz) ! 104: { ! 105: register Pstmt p; ! 106: if ( (p=stmt_free) == 0 ) { ! 107: register Pstmt q = (Pstmt) chunk(1); ! 108: for (p=stmt_free=&q[SBITE-1]; q<p; p--) { ! 109: p->s_list = p-1; ! 110: DB(p->node::allocated=0); ! 111: } ! 112: (p+1)->s_list = 0; ! 113: DB(p->node::allocated=0); ! 114: } ! 115: else ! 116: stmt_free = p->s_list; ! 117: ! 118: mzero(p,sz); ! 119: return p; ! 120: } ! 121: ! 122: void ! 123: stmt::operator delete(void* vp,size_t) ! 124: { ! 125: Pstmt p = (Pstmt)vp; ! 126: DB( if(!p->node::allocated) error('i',"deleting unallocated stmt:%k! -- id==%d",p->base,p->node::id); ! 127: p->node::allocated = 0; ! 128: ); ! 129: p->s_list = stmt_free; ! 130: stmt_free = p; ! 131: vp = 0; ! 132: } ! 133: ! 134: void* ! 135: name::operator new(size_t sz) ! 136: { ! 137: register Pname p; ! 138: ! 139: if ( (p=name_free) == 0 ) { ! 140: register Pname q = (Pname) chunk(1); ! 141: for (p=name_free=&q[NBITE-1]; q<p; p--) { ! 142: p->n_tbl_list = p-1; ! 143: DB(p->node::allocated=0); ! 144: } ! 145: (p+1)->n_tbl_list = 0; ! 146: DB(p->node::allocated=0); ! 147: } ! 148: else ! 149: name_free = p->n_tbl_list; ! 150: ! 151: mzero(p,sz); ! 152: return p; ! 153: } ! 154: ! 155: void ! 156: name::operator delete(void* vp,size_t) ! 157: { ! 158: Pname p = (Pname)vp; ! 159: DB( if(!p->node::allocated) error('i',"deleting unallocated name %s! -- id==%d",p->string?p->string:"???",p->node::id); ! 160: p->node::allocated = 0; ! 161: ); ! 162: p->n_tbl_list = name_free; ! 163: name_free = p; ! 164: vp = 0; ! 165: } ! 166: ! 167: void* ! 168: table::operator new(size_t sz) ! 169: { ! 170: register Ptable p; ! 171: ! 172: if ( (p=table_free) == 0 ) { ! 173: register Ptable q = (Ptable) chunk(1); ! 174: for (p=table_free=&q[TBITE-1]; q<p; p--) { ! 175: p->next = p-1; ! 176: DB(p->node::allocated=0); ! 177: } ! 178: (p+1)->next = 0; ! 179: DB(p->node::allocated=0); ! 180: } ! 181: else ! 182: table_free = p->next; ! 183: ! 184: mzero(p, sz); ! 185: return p; ! 186: } ! 187: ! 188: void ! 189: table::operator delete(void* vp,size_t) ! 190: { ! 191: Ptable p = (Ptable)vp; ! 192: DB( if(!p->node::allocated) error('i',"deleting unallocated table %d! -- id==%d",p->base,p->node::id); ! 193: p->node::allocated = 0; ! 194: ); ! 195: p->next = table_free; ! 196: table_free = p; ! 197: vp = 0; ! 198: } ! 199: ! 200: void* ! 201: vec::operator new(size_t sz) ! 202: { ! 203: register Pvec p; ! 204: ! 205: if ( (p=vec_free) == 0 ) { ! 206: register Pvec q = (Pvec) chunk(1); ! 207: for (p=vec_free=&q[VBITE-1]; q<p; p--) { ! 208: p->tlist = p-1; ! 209: DB(p->node::allocated=0); ! 210: } ! 211: (p+1)->tlist = 0; ! 212: DB(p->node::allocated=0); ! 213: } ! 214: else ! 215: vec_free = (Pvec) p->tlist; ! 216: ! 217: mzero(p, sz); ! 218: return p; ! 219: } ! 220: ! 221: void ! 222: vec::operator delete(void* vp,size_t) ! 223: { ! 224: Pvec p = (Pvec)vp; ! 225: DB( if(!p->node::allocated) error('i',"deleting unallocated vec %d! -- id==%d",p->base,p->node::id); ! 226: p->node::allocated = 0; ! 227: ); ! 228: p->tlist = vec_free; ! 229: vec_free = p; ! 230: vp = 0; ! 231: } ! 232: ! 233: void* ! 234: fct::operator new(size_t sz) ! 235: { ! 236: register Pfct p; ! 237: ! 238: if ( (p=fct_free) == 0 ) { ! 239: register Pfct q = (Pfct) chunk(1); ! 240: for (p=fct_free=&q[FBITE-1]; q<p; p--) { ! 241: p->tlist = p-1; ! 242: DB(p->node::allocated=0); ! 243: } ! 244: (p+1)->tlist = 0; ! 245: DB(p->node::allocated=0); ! 246: } ! 247: else ! 248: fct_free = (Pfct) p->tlist; ! 249: ! 250: mzero(p, sz); ! 251: return p; ! 252: } ! 253: ! 254: void ! 255: fct::operator delete(void* vp,size_t) ! 256: { ! 257: Pfct p = (Pfct)vp; ! 258: DB( if(!p->node::allocated) error('i',"deleting unallocated fct %d! -- id==%d",p->base,p->node::id); ! 259: p->node::allocated = 0; ! 260: ); ! 261: p->tlist = fct_free; ! 262: fct_free = p; ! 263: vp = 0; ! 264: } ! 265: ! 266: void* ! 267: ptr::operator new(size_t sz) ! 268: { ! 269: register Pptr p; ! 270: ! 271: //error('d',"ptr new"); ! 272: if ( (p=ptr_free) == 0 ) { ! 273: register Pptr q = (Pptr) chunk(1); ! 274: for (p=ptr_free=&q[PBITE-1]; q<p; p--) { ! 275: p->tlist = p-1; ! 276: DB(p->node::allocated=0); ! 277: } ! 278: (p+1)->tlist = 0; ! 279: DB(p->node::allocated=0); ! 280: } ! 281: else ! 282: ptr_free = (Pptr) p->tlist; ! 283: ! 284: mzero(p, sz); ! 285: return p; ! 286: } ! 287: ! 288: void ! 289: ptr::operator delete(void* vp,size_t) ! 290: { ! 291: Pptr p = (Pptr)vp; ! 292: DB( if(!p->node::allocated) error('i',"deleting unallocated ptr %d! -- id==%d",p->base,p->node::id); ! 293: p->node::allocated = 0; ! 294: ); ! 295: p->tlist = ptr_free; ! 296: ptr_free = p; ! 297: vp = 0; ! 298: } ! 299: 0707071010112043451004440001630000160000010070500466055374500001100000070343cfront.h /*ident "@(#)ctrans:src/cfront.h 1.12" */ ! 300: /*********************************************************************** ! 301: ! 302: C++ source for cfront, the C++ compiler front-end ! 303: written in the computer science research center of Bell Labs ! 304: ! 305: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 306: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 307: ! 308: When reading cfront code please remember that C++ was not available ! 309: when it was originally written. Out of necessity cfront is written ! 310: in a style that takes advantage of only few of C++'s features. ! 311: ! 312: WARNING: This program relies on non-initialized class members being ZERO. ! 313: This will be true as long as they are allocated using the "new" operator ! 314: from alloc.c ! 315: ! 316: cfront.h: ! 317: ! 318: Here is all the class definitions for cfront, and most of the externs ! 319: ! 320: ***********************************************************************/ ! 321: ! 322: #ifndef _CFRONT_H ! 323: #define _CFRONT_H ! 324: ! 325: #include "token.h" ! 326: #include "typedef.h" ! 327: ! 328: #ifndef GRAM ! 329: extern char* prog_name; // compiler name and version ! 330: extern int inline_restr; // inline expansion restrictions ! 331: #endif ! 332: ! 333: extern TOK tlex(); ! 334: extern Pname syn(); ! 335: ! 336: extern void ext(int); ! 337: ! 338: extern char* make_name(TOK); ! 339: extern void make_dummy(); ! 340: extern Pname dummy_fct; ! 341: extern Pname really_dominate(Pname, Pname, bit); ! 342: extern int exact1(Pname, Ptype); ! 343: ! 344: extern int friend_check(Pclass start,Pclass stop, Pfct f); ! 345: ! 346: struct loc // a source file location ! 347: { ! 348: short file; // index into file_name[], or zero ! 349: short line; ! 350: #ifndef GRAM ! 351: void put(FILE*); ! 352: void putline(); ! 353: #endif ! 354: }; ! 355: ! 356: extern Loc curloc; ! 357: extern int curr_file; ! 358: extern char* src_file_name; ! 359: extern loc noloc; // dummy null location ! 360: extern bit binary_val; ! 361: extern bit stmtno; ! 362: ! 363: struct ea { // fudge portable printf-like formatting for error() ! 364: union { ! 365: void* p; ! 366: long i; ! 367: }; ! 368: ! 369: ea(const void* pp) { p = pp; } ! 370: ea(long ii) { i = ii; } ! 371: ea() {} ! 372: }; ! 373: ! 374: extern ea* ea0; ! 375: ! 376: overload error; ! 377: int error(const char*); ! 378: int error(const char*, const ea&, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0); ! 379: int error(int, const char*); ! 380: int error(int, const char*, const ea&, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0); ! 381: int error(loc*, const char*, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0); ! 382: int error(int, loc*, const char*, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0, const ea& = *ea0); ! 383: extern char emode; ! 384: ! 385: extern int error_count; ! 386: extern int vtbl_opt; ! 387: extern int debug_opt; ! 388: extern int warning_opt; ! 389: extern int ansi_opt; ! 390: extern int strict_opt; ! 391: extern FILE* out_file; ! 392: extern FILE* in_file; ! 393: extern char scan_started; ! 394: ! 395: extern int bl_level; ! 396: extern Ptable ktbl; // keywords and typedef names ! 397: extern Ptable gtbl; // global names ! 398: extern Ptable ptbl; ! 399: extern Ptable lcl_tbl; ! 400: extern char* oper_name(TOK); ! 401: extern Pname def_name; ! 402: extern Pname pdef_name; ! 403: extern Pclass ccl; ! 404: extern Pbase defa_type; ! 405: extern Pbase moe_type; ! 406: extern Pbase mptr_type; ! 407: ! 408: #ifndef GRAM ! 409: extern Pstmt Cstmt; // current statement, or 0 ! 410: extern Pname Cdcl; // name currently being declared, or 0 ! 411: ! 412: extern Pbase any_type; ! 413: extern int largest_int; ! 414: #endif ! 415: ! 416: extern Pbase int_type; ! 417: extern Pbase char_type; ! 418: extern Pbase short_type; ! 419: extern Pbase long_type; ! 420: extern Pbase uint_type; ! 421: extern Pbase float_type; ! 422: extern Pbase double_type; ! 423: extern Pbase ldouble_type; ! 424: extern Pbase void_type; ! 425: ! 426: #ifndef GRAM ! 427: extern Pbase uchar_type; ! 428: extern Pbase ushort_type; ! 429: extern Pbase ulong_type; ! 430: extern Ptype Pchar_type; ! 431: extern Ptype Pint_type; ! 432: extern Ptype Pvptr_type; ! 433: extern Ptype Pfctvec_type; ! 434: extern Ptype Pvoid_type; ! 435: extern Pbase zero_type; ! 436: extern Ptype size_t_type; ! 437: ! 438: extern int byte_offset; ! 439: extern int bit_offset; ! 440: extern int max_align; ! 441: extern int const_save; ! 442: extern int const_ptr; ! 443: extern int cm_const_save; ! 444: extern bit const_problem; ! 445: #endif ! 446: ! 447: extern Pexpr dummy; /* the empty expression */ ! 448: extern Pexpr zero; ! 449: extern Pexpr one; ! 450: extern Pname sta_name; /* qualifier for unary :: */ ! 451: ! 452: #define DEL(p) if (p && (p->permanent==0)) p->del() ! 453: #define PERM(p) p->permanent=1 ! 454: #define UNPERM(p) p->permanent=0 ! 455: ! 456: struct node { ! 457: TOK base; ! 458: bit permanent; ! 459: bit baseclass; // base classes have NAME in their base ... ! 460: #ifdef DBG ! 461: bit displayed; // avoid infinite recursion in display functions ! 462: bit allocated; // set when not on free list ! 463: long id; ! 464: #endif ! 465: }; ! 466: #ifdef DBG ! 467: extern long node_id; ! 468: extern int Adebug; ! 469: #define DBID() { node::id = ++::node_id; node::allocated=1; displayed=0; \ ! 470: if(Adebug>=1)fprintf(stderr,"\n*** allocated %d base %d\n",id,base); } ! 471: #else ! 472: #define DBID() /**/ ! 473: #endif ! 474: ! 475: struct table : node { ! 476: /* a table is a node only to give it a "base" for debugging */ ! 477: bit init_stat; /* ==0 if block(s) of table not simplified, ! 478: ==1 if simplified but had no initializers, ! 479: ==2 if simplified and had initializers. ! 480: */ ! 481: short size; ! 482: short hashsize; ! 483: short free_slot; /* next free slot in entries */ ! 484: Pname* entries; ! 485: short* hashtbl; ! 486: Pstmt real_block; /* the last block the user wrote, ! 487: not one of the ones cfront created ! 488: */ ! 489: Ptable next; /* table for enclosing scope */ ! 490: Pname t_name; /* name of the table */ ! 491: ! 492: static Ptable table_free; ! 493: void* operator new(size_t); ! 494: void operator delete(void*,size_t); ! 495: ! 496: table(short, Ptable, Pname); ! 497: ~table(); ! 498: ! 499: Pname look(char*, TOK); ! 500: Pname insert(Pname, TOK); ! 501: #ifndef GRAM ! 502: void grow(int); ! 503: void set_name(Pname n) { t_name = n; }; ! 504: Pname get_mem(int); ! 505: int max() { return free_slot-1; }; ! 506: void dcl_print(TOK,TOK); ! 507: #endif ! 508: void del(); ! 509: }; ! 510: ! 511: #ifndef GRAM ! 512: extern bit Nold; ! 513: extern bit vec_const, fct_const; ! 514: #endif ! 515: ! 516: extern void restore(); ! 517: extern void set_scope(Pname); ! 518: extern Plist modified_tn; ! 519: ! 520: // local class ! 521: extern Plist local_tn; ! 522: extern Plist local_blk; ! 523: extern Plist local_class; ! 524: extern void local_hide( Pname ); ! 525: extern char *make_local_name(Pclass, int=0); ! 526: ! 527: // nested type ! 528: extern Plist nested_tn; ! 529: extern Plist nested_type; ! 530: extern Pname curr_scope; ! 531: extern Pname curr_fct; ! 532: extern void nested_hide(Pname); ! 533: extern int is_empty(Pclass,bit=0); ! 534: ! 535: extern Pbase start_cl(TOK, Pname, Pbcl); ! 536: extern void end_cl(); ! 537: extern Pbase end_enum(Pname, nlist*); ! 538: ! 539: /************ types : basic types, aggregates, declarators ************/ ! 540: ! 541: #ifndef GRAM ! 542: extern bit new_type; ! 543: extern Pname cl_obj_vec; ! 544: extern Pname eobj; ! 545: #endif ! 546: ! 547: ! 548: #define DEFINED 01 /* definition fed through ?::dcl() */ ! 549: #define SIMPLIFIED 02 /* in ?::simpl() */ ! 550: #define DEF_SEEN 04 /* definition seen, but not processed */ ! 551: #define REF_SEEN 010 /* reference seen (classdef) */ ! 552: /* used for class members in norm.c */ ! 553: #define IN_ERROR 010 ! 554: ! 555: struct type : node { ! 556: bit defined; /* flags DEF_SEEN, DEFINED, SIMPLIFIED, IN_ERROR ! 557: not used systematically yet ! 558: */ ! 559: bit lex_level; ! 560: Pclass in_class; // nested type ! 561: Pname in_fct; // local type ! 562: char *lcl; ! 563: char *nested_sig; ! 564: char *signature(char*); ! 565: Ptype tlist; ! 566: bit check(Ptype, TOK); ! 567: #ifndef GRAM ! 568: void print(); ! 569: void dcl_print(Pname); ! 570: void base_print(); ! 571: ! 572: Pname is_cl_obj(); /* sets cl_obj_vec */ ! 573: Pptr is_ref(); ! 574: Pptr is_ptr(); ! 575: Pptr is_ptr_or_ref(); ! 576: bit is_unsigned(); ! 577: void dcl(Ptable); ! 578: int tsizeof(int = 0); ! 579: bit tconst(); ! 580: TOK set_const(bit); ! 581: int align(); ! 582: TOK kind(TOK,TOK); ! 583: TOK integral(TOK oo) { return kind(oo,'I'); }; ! 584: TOK numeric(TOK oo) { return kind(oo,'N'); }; ! 585: TOK num_ptr(TOK oo) { return kind(oo,'P'); }; ! 586: bit vec_type(); ! 587: Ptype deref(); ! 588: inline Pptr addrof(); ! 589: Pfct memptr(); ! 590: #endif ! 591: void del(); ! 592: }; ! 593: ! 594: struct enumdef : type { /* ENUM */ ! 595: bit e_body; ! 596: short no_of_enumerators; ! 597: unsigned char strlen; // strlen(string) ! 598: char* string; // name of enum ! 599: Pname mem; ! 600: Pbase e_type; // type representing the enum ! 601: enumdef(Pname n) { base=ENUM; mem=n; }; ! 602: #ifndef GRAM ! 603: void print(); ! 604: void dcl_print(Pname); ! 605: void dcl(Pname, Ptable); ! 606: void simpl(); ! 607: #endif ! 608: }; ! 609: ! 610: struct velem { ! 611: Pname n; ! 612: int offset; ! 613: }; ! 614: ! 615: struct virt : node { ! 616: Pvirt next; ! 617: int n_init; ! 618: velem* virt_init; // vector of vtbl initializers (zero-terminated) ! 619: Pclass vclass; // for class vclass ! 620: char* string; ! 621: bit is_vbase; // vtable for virtual base ! 622: bit printed; ! 623: virt(Pclass cl, velem* v, char* s, bit flag, int ni) {base = XVIRT; vclass=cl; virt_init=v; string=s; is_vbase=flag; next=0; n_init = ni;} ! 624: }; ! 625: ! 626: enum { C_VPTR=1, C_XREF=2, C_ASS=4, C_VBASE=8 }; ! 627: ! 628: // An enumeration of the types of classes for Objectstore ! 629: enum class_type_enum { vanilla_class, // A regular class ! 630: template_class, ! 631: instantiated_template_class, ! 632: uninstantiated_template_class, ! 633: relationship_class, ! 634: defining_class ! 635: }; ! 636: class type_extension; ! 637: ! 638: struct classdef : type { /* CLASS */ ! 639: class_type_enum class_base; // An extension of "base" to further define ! 640: // the real subtype of the class ! 641: bit c_body; /* print definition only once */ ! 642: TOK csu; /* CLASS, STRUCT, UNION, or ANON */ ! 643: bit obj_align; ! 644: bit c_xref; ! 645: // 1 set: has vptr(s) ! 646: // 2 set: X(X&) exists ! 647: // 4 set: operator=(X&) exists ! 648: // 8 set: has vbaseptr(s) ! 649: ! 650: bit virt_count; // number of virtual functions ! 651: // starting at max base class virt_count in ! 652: bit virt_merge; // set when no virtual functions, but ! 653: // need to merge virtual base classes ! 654: bit c_abstract; // abstract class: don't instantiate ! 655: bit has_vvtab; // set if class has vtable from virtual base ! 656: unsigned char strlen; // strlen(string) ! 657: Pbcl baselist; // list of base classes ! 658: char* string; /* name of class */ ! 659: Pname mem_list; ! 660: Ptable memtbl; ! 661: int obj_size; ! 662: int real_size; /* obj_size - alignment waste */ ! 663: Plist friend_list; ! 664: Pname pubdef; ! 665: Plist tn_list; // list of member names hiding type names ! 666: Plist nest_list; // list of nested types ! 667: Ptype this_type; ! 668: Pvirt virt_list; // vtbl initializers ! 669: Pname c_ctor; // constuctor: ! 670: // possibly overloaded, possibly inherited ! 671: Pname c_dtor; // destructor ! 672: Pname c_itor; /* constructor X(X&) */ ! 673: Pname conv; /* operator T() chain */ ! 674: struct toknode *c_funqf, *c_funqr; // token Q for parsing function defs after class def ! 675: ! 676: classdef(TOK); ! 677: ~classdef(); ! 678: TOK is_simple() { return (csu==CLASS)?0:csu; }; ! 679: #ifndef GRAM ! 680: void print(); ! 681: void dcl_print(Pname); ! 682: void simpl(); ! 683: ! 684: void print_members(); ! 685: void dcl(Pname, Ptable); ! 686: ! 687: // bit has_friend(Pname); ! 688: bit has_friend(Pclass); ! 689: bit has_friend(Pfct); ! 690: ! 691: bit has_base(Pclass cl); ! 692: bit baseof(Pname); ! 693: bit baseof(Pclass); ! 694: Pclass is_base(char*); ! 695: ! 696: Pname has_oper(TOK); ! 697: Pname has_ctor() { return c_ctor; } ! 698: Pname has_dtor() { return c_dtor; } ! 699: Pname has_itor() { return c_itor; } ! 700: Pname has_ictor(); ! 701: Pname make_itor(int); ! 702: Pexpr find_name(char*, Pclass, int=0); ! 703: int do_virtuals(Pvirt, char*, int, bit); ! 704: int all_virt(Pclass, char*, int, bit); ! 705: void add_vtbl(velem*, char*, bit, int); ! 706: void print_all_vtbls(Pclass); ! 707: void print_vtbl(Pvirt); ! 708: void really_print(Pvirt); ! 709: int check_dup(Pclass, TOK); ! 710: int has_allocated_base(Pclass); ! 711: char *has_allocated_base(char*); ! 712: int get_offset(char*); ! 713: Pbcl get_base(char*); ! 714: Pexpr get_vptr_exp(char*); ! 715: Pexpr find_in_base(char*, Pclass); ! 716: void modify_inst_names(char *s); // Adjust ctor names for instantiation ! 717: bit parametrized_class(); ! 718: bit same_class(Pclass p); ! 719: #endif ! 720: }; ! 721: ! 722: #ifndef GRAM ! 723: ! 724: class clist { ! 725: Pclass cl; ! 726: clist* next; ! 727: public: ! 728: clist(Pclass c, clist* n) { cl=c; next=n; } ! 729: int onlist(Pclass); ! 730: void clear(); ! 731: }; ! 732: ! 733: extern clist * vcllist; ! 734: ! 735: struct vl { ! 736: struct vl* next; ! 737: Pvirt vt; ! 738: classdef* cl; ! 739: ! 740: vl(classdef* c, Pvirt v, struct vl* n) ! 741: { cl = c; vt = v; next = n; } ! 742: }; ! 743: ! 744: extern vl* vlist; ! 745: ! 746: extern int nin; ! 747: extern int Nvis; ! 748: extern int Noffset; ! 749: extern TOK Nvirt; ! 750: extern Pexpr Nptr; ! 751: extern Pbcl Nvbc_alloc; ! 752: extern char *Nalloc_base; ! 753: extern Pexpr rptr(Ptype,Pexpr,int); ! 754: extern Pexpr vbase_args(Pfct, Pname); ! 755: extern Pexpr cdvec(Pname,Pexpr,Pclass,Pname,int,Pexpr,Pexpr=0); ! 756: ! 757: extern Pexpr find(char*, Pclass, int); ! 758: extern Pexpr find_name(Pname, Pclass, Ptable, int, Pname); ! 759: extern Pname find_virtual(Pclass,Pname); ! 760: extern Pname vfct(Pclass, char*); ! 761: extern int Vcheckerror; ! 762: extern int ignore_const; ! 763: ! 764: extern int mex; ! 765: extern Pclass mec; ! 766: extern Pclass tcl; ! 767: #endif ! 768: ! 769: struct basetype : type ! 770: /* ZTYPE CHAR SHORT INT LONG FLOAT DOUBLE ! 771: FIELD EOBJ COBJ TYPE ANY ! 772: */ ! 773: /* used for gathering all the attributes ! 774: for a list of declarators ! 775: ! 776: ZTYPE is the (generic) type of ZERO ! 777: ANY is the generic type of an undeclared name ! 778: */ ! 779: { ! 780: bit b_unsigned; ! 781: bit b_signed; ! 782: bit b_volatile; ! 783: bit b_const; ! 784: bit b_typedef; ! 785: bit b_inline; ! 786: bit b_virtual; ! 787: bit b_short; ! 788: bit b_long; ! 789: bit b_bits; /* number of bits in field */ ! 790: bit b_offset; // bit offset of field ! 791: TOK b_sto; /* AUTO STATIC EXTERN REGISTER 0 */ ! 792: Pname b_name; /* name of non-basic type */ ! 793: Ptable b_table; /* memtbl for b_name, or 0 */ ! 794: Pname b_xname; /* extra name */ ! 795: union { ! 796: Ptype b_fieldtype; ! 797: char* b_linkage; ! 798: }; ! 799: ! 800: basetype(TOK, Pname); ! 801: ! 802: Pbase type_adj(TOK); ! 803: Pbase base_adj(Pbase); ! 804: Pbase name_adj(Pname); ! 805: Pname aggr(); ! 806: Pbase check(Pname); ! 807: #ifndef GRAM ! 808: void dcl_print(); ! 809: Pbase arit_conv(Pbase); ! 810: bit parametrized_class(); ! 811: #endif ! 812: int discriminator(int); // union discriminator fcn ! 813: }; ! 814: ! 815: enum Linkage { linkage_default, linkage_C, linkage_Cplusplus }; ! 816: extern Linkage linkage; ! 817: void set_linkage(char*); ! 818: ! 819: struct fct : type // FCT ! 820: { ! 821: TOK nargs; ! 822: TOK nargs_known; // 0 if unknown, 1 if known, or ELLIPSIS ! 823: bit last_stmt; ! 824: bit f_vdef; // 1 if this is the first virtual definition ! 825: // of this function ! 826: bit f_inline; // 1 if inline, 2 if being expanded, else 0 ! 827: bit f_const; // one if member function that may be called for ! 828: // a const object, else 0 ! 829: bit f_static; // 1 if static member function, else 0 ! 830: short f_virtual; // index in virtual table, or 0 meaning non-virtual ! 831: short f_imeasure; // some measure of the size of an inline function ! 832: Ptype returns; ! 833: Pname argtype; ! 834: Ptype s_returns; ! 835: Pname f_this; ! 836: Pclass memof; // member of class memof ! 837: Pblock body; ! 838: Pname f_init; // base and member initializers ! 839: Pexpr f_expr; // body expanded into an expression ! 840: Pexpr last_expanded; ! 841: Pname f_result; // extra second argument of type X& ! 842: Pname f_args; // argument list including args added by cfront ! 843: Linkage f_linkage; ! 844: char* f_signature; // character encoding of function type ! 845: Plist local_class; // list of local classes ! 846: static Pfct fct_free; ! 847: void* operator new(size_t); ! 848: void operator delete(void*,size_t); ! 849: ! 850: fct(Ptype, Pname, TOK); ! 851: void argdcl(Pname,Pname); ! 852: #ifndef GRAM ! 853: Ptype normalize(Ptype); ! 854: void dcl_print(); ! 855: void dcl(Pname); ! 856: Pexpr base_init(Pclass, Pexpr, Ptable, int); ! 857: Pexpr mem_init(Pname, Pexpr, Ptable); ! 858: void init_bases(Pclass, Pexpr); ! 859: bit declared() { return nargs_known; }; ! 860: void simpl(); ! 861: int ctor_simpl(Pclass, Pexpr); ! 862: Pstmt dtor_simpl(Pclass, Pexpr); ! 863: Pexpr expand(Pname,Ptable,Pexpr); ! 864: void sign(); ! 865: #endif ! 866: int discriminator(int); // union discriminator fcn ! 867: }; ! 868: ! 869: struct name_list : node { ! 870: Pname f; ! 871: Plist l; ! 872: name_list(Pname ff, Plist ll) { base = XNLIST; f=ff; l=ll; }; ! 873: }; ! 874: ! 875: #ifndef GRAM ! 876: struct gen : type { // OVERLOAD ! 877: Plist fct_list; ! 878: ! 879: gen() { base = OVERLOAD; } ! 880: Pname add(Pname); ! 881: Pname find(Pfct, bit); ! 882: Pname match(Pname, Pfct, bit); ! 883: }; ! 884: #endif ! 885: ! 886: struct pvtyp : type { ! 887: Ptype typ; ! 888: }; ! 889: ! 890: struct vec : pvtyp // VEC ! 891: // typ [ dim ] ! 892: { ! 893: Pexpr dim; ! 894: int size; ! 895: ! 896: static Pvec vec_free; ! 897: void* operator new(size_t); ! 898: void operator delete(void*,size_t); ! 899: ! 900: vec(Ptype t, Pexpr e) { base=VEC; typ=t; dim=e; DBID(); } ! 901: #ifndef GRAM ! 902: Ptype normalize(Ptype); ! 903: #endif ! 904: }; ! 905: ! 906: struct ptr : pvtyp // PTR, RPTR i.e. reference ! 907: { ! 908: Pclass memof; // pointer to member of memof: memof::* ! 909: bit rdo; // "*const" ! 910: ! 911: static Pptr ptr_free; ! 912: void* operator new(size_t); ! 913: void operator delete(void*,size_t); ! 914: ! 915: ptr(TOK b, Ptype t) { base=b; typ=t; DBID(); } ! 916: #ifndef GRAM ! 917: Ptype normalize(Ptype); ! 918: #endif ! 919: }; ! 920: ! 921: #ifndef GRAM ! 922: inline Pptr type::addrof() { return new ptr(PTR,this); } ! 923: ! 924: extern bit vrp_equiv; ! 925: #endif ! 926: ! 927: ! 928: /****************************** constants ********************************/ ! 929: ! 930: /* STRING ZERO ICON FCON CCON ID */ ! 931: /* IVAL FVAL LVAL */ ! 932: ! 933: /***************************** expressions ********************************/ ! 934: ! 935: #ifndef GRAM ! 936: extern Pexpr next_elem(); ! 937: extern void new_list(Pexpr); ! 938: extern void list_check(Pname, Ptype, Pexpr, Ptable=0); ! 939: extern Pexpr ref_init(Pptr,Pexpr,Ptable); ! 940: extern Pexpr class_init(Pexpr,Ptype,Pexpr,Ptable); ! 941: extern Pexpr check_cond(Pexpr, TOK, Ptable); ! 942: extern Pexpr ptof(Pfct,Pexpr,Ptable); ! 943: extern void dosimpl(Pexpr, Pname); ! 944: extern int ref_initializer; ! 945: extern int ntok; ! 946: ! 947: extern void ptbl_init(int); ! 948: extern void ptbl_add_pair(char*,char*); ! 949: extern char *ptbl_lookup(char*); ! 950: extern char *st_name(char*); ! 951: #endif ! 952: ! 953: struct expr : node /* PLUS, MINUS, etc. */ ! 954: /* IMPORTANT: all expressions are of sizeof(expr) */ ! 955: /* DEREF => *e1 (e2==0) OR e1[e2] ! 956: UMINUS => -e2 ! 957: INCR (e1==0) => ++e2 ! 958: INCR (e2==0) => e1++ ! 959: CM => e1 , e2 ! 960: ILIST => LC e1 RC (an initializer list) ! 961: a Pexpr may denote a name ! 962: */ ! 963: { ! 964: union { ! 965: Ptype tp; ! 966: char *string4; ! 967: }; ! 968: union { ! 969: Pexpr e1; ! 970: long i1; ! 971: char* string; ! 972: }; ! 973: union { ! 974: Pexpr e2; ! 975: int i2; ! 976: char* string2; ! 977: Pexpr n_initializer; ! 978: Ptype tpdef; // local and nested typedef info ! 979: }; ! 980: union { /* used by the derived classes */ ! 981: Ptype tp2; ! 982: Pname fct_name; ! 983: Pexpr cond; ! 984: Pexpr mem; ! 985: Ptype as_type; ! 986: Ptable n_table; ! 987: Pin il; ! 988: Pname query_this; ! 989: }; ! 990: ! 991: static Pexpr expr_free; ! 992: void* operator new(size_t); ! 993: void operator delete(void*,size_t); ! 994: expr(TOK, Pexpr, Pexpr); ! 995: void del(); ! 996: #ifndef GRAM ! 997: void print(); ! 998: Pexpr typ0(Ptable); ! 999: Pexpr typ(Ptable); ! 1000: long eval(); ! 1001: unsigned long ueval(long,long); ! 1002: int lval(TOK); ! 1003: Ptype call_fct(Ptable); ! 1004: Pexpr address(); ! 1005: Pexpr contents(); ! 1006: void simpl(); ! 1007: Pexpr expand(); ! 1008: bit not_simple(); ! 1009: Pexpr try_to_overload(Ptable); ! 1010: Pexpr docast(Ptable); ! 1011: Pexpr dovalue(Ptable); ! 1012: Pexpr donew(Ptable); ! 1013: void simpl_new(); ! 1014: void simpl_delete(); ! 1015: #endif ! 1016: int discriminator(int); // union discriminator fcn ! 1017: }; ! 1018: ! 1019: struct texpr : expr { // CAST NEW VALUE (also ICALL) ! 1020: texpr(TOK bb, Ptype tt, Pexpr ee) : expr (bb,ee,0) { tp2=tt; } ! 1021: }; ! 1022: ! 1023: struct cast : expr { // CAST ! 1024: cast(Ptype tt, Pexpr ee) : expr (CAST,ee,0) { tp=tp2=tt; } ! 1025: }; ! 1026: ! 1027: struct ival : expr { // IVAL ! 1028: ival(long ii) : expr (IVAL,0,0) { i1 = ii;} ! 1029: }; ! 1030: ! 1031: struct call : expr { // CALL ! 1032: call(Pexpr aa, Pexpr bb) : expr (CALL,aa,bb) { } ! 1033: #ifndef GRAM ! 1034: void simpl(); ! 1035: Pexpr expand(Ptable); ! 1036: #endif ! 1037: }; ! 1038: ! 1039: struct qexpr : expr { // QUEST cond ? e1 : e2 ! 1040: qexpr(Pexpr ee, Pexpr ee1, Pexpr ee2) : expr (QUEST,ee1,ee2) { cond=ee; } ! 1041: }; ! 1042: ! 1043: struct ref : expr { // REF DOT e1->mem OR e1.mem ! 1044: ref(TOK ba, Pexpr a, Pexpr b) : expr (ba,a,0) { mem=b; } ! 1045: }; ! 1046: ! 1047: struct mdot : expr { // MDOT a.b ! 1048: mdot(char* a, Pexpr b) : expr (MDOT,0,0) { string2=a; mem=b; } ! 1049: }; ! 1050: ! 1051: struct text_expr : expr { // TEXT (vtbl_name) ! 1052: text_expr(char* a, char* b) : expr (TEXT,0,0) ! 1053: { string=a; string2=b; } ! 1054: }; ! 1055: char* vtbl_name(char*,char*); ! 1056: /************************* names (are expressions) ****************************/ ! 1057: ! 1058: struct basecl : node { // NAME => base class ! 1059: // VIRTUAL => virtual base class ! 1060: TOK ppp; // private / public / protected ! 1061: bit allocated; // allocated virtual base ! 1062: bit promoted; // non-explicit, promoted virtual base ! 1063: Pclass bclass; ! 1064: Pexpr init; // base class initializers for ctors ! 1065: int ptr_offset; // pointer's relative position in derived class ! 1066: int obj_offset; // object's relative position in derived class ! 1067: Pname* virt_init; // vector of vtbl table initializers ! 1068: basecl* next; ! 1069: ! 1070: basecl(Pclass cl, basecl* n) { baseclass=1; bclass=cl; next=n; promoted=0; init=0;} ! 1071: }; ! 1072: ! 1073: enum template_formal_types { ! 1074: template_type_formal =1 , template_expr_formal, ! 1075: template_stmt_tree_formal, template_expr_tree_formal, ! 1076: template_actual_arg_dummy // used during the parse ! 1077: }; ! 1078: extern TOK ppbase; ! 1079: ! 1080: struct name : expr { // NAME TNAME and the keywords in the ktbl ! 1081: TOK n_oper; // name of operator or 0 ! 1082: TOK n_sto; // EXTERN STATIC AUTO REGISTER ENUM 0 ! 1083: TOK n_stclass; // STATIC AUTO REGISTER 0 ! 1084: TOK n_scope; // EXTERN STATIC FCT ARG PUBLIC 0 ! 1085: TOK n_key; /* for names in table: class */ ! 1086: bit n_evaluated; // 0 or n_val holds the value ! 1087: bit n_xref; // argument of type X(X&) ! 1088: unsigned char lex_level; ! 1089: TOK n_protect; // PROTECTED (<=>n_scope==0) or 0 ! 1090: bit n_dcl_printed; // 1: declaration printed ! 1091: // 2: definition printed ! 1092: // 0: declaration not printed ! 1093: ! 1094: // if this is set it implies that n_template_arg == template_type_formal ! 1095: char n_template_arg; // One of template_formal_types for template arguments ! 1096: bit n_template_formal_must_be_class ; ! 1097: bit n_redefined ; // set only for PT function names where an explict ! 1098: // definition was provided. ! 1099: char *n_anon; // nested anonymous unions ! 1100: short n_union; // 0, or union index ! 1101: short n_addr_taken; ! 1102: short n_used; ! 1103: short n_assigned_to; ! 1104: Loc where; ! 1105: int n_offset; // byte offset in frame or struct ! 1106: Pname n_list; ! 1107: Pname n_tbl_list; ! 1108: char *n_gen_fct_name; // used to be punned with n_tbl_list. ! 1109: char *n_template_arg_string ; // the mangled string name ! 1110: union { ! 1111: /* ! 1112: * n_qualifier: name of containing class ! 1113: * n_realscope: for labels (always entered in function table) ! 1114: * the table for the actual scope in which label occurred. ! 1115: * syn_class: lex table only ! 1116: */ ! 1117: Pname n_qualifier; ! 1118: Ptable n_realscope; ! 1119: int syn_class; ! 1120: }; ! 1121: ! 1122: /* n_val: the value of n_initializer; also the argument ! 1123: * number for inline arguments (when base == ANAME) */ ! 1124: long n_val; ! 1125: static Pname name_free; ! 1126: void* operator new(size_t); ! 1127: void operator delete(void*,size_t); ! 1128: name(char* =0); ! 1129: ! 1130: ! 1131: Pname normalize(Pbase, Pblock, bit); ! 1132: Pname tdef(); ! 1133: Pname tname(TOK); ! 1134: void hide(); ! 1135: void unhide() { n_key=0; n_list=0; }; ! 1136: #ifndef GRAM ! 1137: Pname dcl(Ptable,TOK); ! 1138: int no_of_names(); ! 1139: void use() { n_used++; }; ! 1140: void assign(); ! 1141: void take_addr(); ! 1142: void check_oper(Pname); ! 1143: void simpl(); ! 1144: void print(); ! 1145: void dcl_print(TOK); ! 1146: void field_align(); ! 1147: Pname dofct(Ptable,TOK); ! 1148: #endif ! 1149: void del(); ! 1150: int discriminator(int); // union discriminator fcn ! 1151: }; ! 1152: ! 1153: extern int friend_in_class; ! 1154: extern int in_class_dcl; ! 1155: ! 1156: // from parser ! 1157: extern int in_class_decl; ! 1158: extern int parsing_class_members; ! 1159: extern int in_mem_fct; ! 1160: extern int in_arg_list; ! 1161: extern Ptype in_typedef; ! 1162: extern int defer_check; // redefinition typedef check delay ! 1163: extern int declTag; // !1: inline, virtual mod permitted ! 1164: extern Pname in_tag; ! 1165: extern Pname statStat; ! 1166: extern int DECL_TYPE; ! 1167: ! 1168: /******************** statements *********************************/ ! 1169: ! 1170: struct stmt : node { /* BREAK CONTINUE DEFAULT */ ! 1171: /* IMPORTANT: all statement nodes have sizeof(stmt) */ ! 1172: Pstmt s; ! 1173: Pstmt s_list; ! 1174: Loc where; ! 1175: union { ! 1176: Pname d; // goto/block -- destination ! 1177: Pexpr e2; // for iteration ! 1178: Pstmt has_default; // switch statement default ! 1179: int case_value; ! 1180: Ptype ret_tp; // pair ! 1181: }; ! 1182: union { ! 1183: Pexpr e; ! 1184: bit own_tbl; ! 1185: Pstmt s2; ! 1186: }; ! 1187: Ptable memtbl; ! 1188: union { ! 1189: Pstmt for_init; ! 1190: Pstmt else_stmt; ! 1191: Pstmt case_list; ! 1192: Loc where2; // location of } at end of block ! 1193: }; ! 1194: ! 1195: static Pstmt stmt_free; ! 1196: void* operator new(size_t); ! 1197: void operator delete(void*,size_t); ! 1198: stmt(TOK, loc, Pstmt); ! 1199: void del(); ! 1200: #ifndef GRAM ! 1201: void print(); ! 1202: void dcl(); ! 1203: void dcl1(Pstmt&); ! 1204: void reached(); ! 1205: Pstmt simpl(); ! 1206: Pstmt expand(); ! 1207: Pstmt copy(); ! 1208: #endif ! 1209: int discriminator(int); // union discriminator fcn ! 1210: }; ! 1211: ! 1212: #ifndef GRAM ! 1213: extern char* Neval; ! 1214: extern Ptable scope; ! 1215: extern Ptable expand_tbl; ! 1216: extern Pname expand_fn; ! 1217: #endif ! 1218: ! 1219: struct estmt : stmt /* SM WHILE DO SWITCH RETURN CASE */ ! 1220: /* SM (e!=0) => e; ! 1221: in particular assignments and function calls ! 1222: SM (e==0) => ; (the null statement) ! 1223: CASE => case e : s ; ! 1224: SM_PARAM => e is the template_statement_tree_formal name ! 1225: */ ! 1226: { ! 1227: estmt(TOK t, loc ll, Pexpr ee, Pstmt ss) : stmt (t,ll,ss) { e=ee; } ! 1228: }; ! 1229: ! 1230: struct ifstmt : stmt /* IF */ ! 1231: // else_stme==0 => if (e) s ! 1232: // else_stmt!=0 => if (e) s else else_stmt ! 1233: { ! 1234: ifstmt(loc ll, Pexpr ee, Pstmt ss1, Pstmt ss2) ! 1235: : stmt (IF,ll,ss1) { e=ee; else_stmt=ss2; }; ! 1236: }; ! 1237: ! 1238: struct lstmt : stmt /* LABEL GOTO */ ! 1239: /* ! 1240: d : s ! 1241: goto d ! 1242: */ ! 1243: { ! 1244: lstmt(TOK bb, loc ll, Pname nn, Pstmt ss) : stmt (bb,ll,ss) { d=nn; } ! 1245: }; ! 1246: ! 1247: struct forstmt : stmt { // FOR ! 1248: forstmt(loc ll, Pstmt fss, Pexpr ee1, Pexpr ee2, Pstmt ss) ! 1249: : stmt (FOR,ll,ss) { for_init=fss; e=ee1; e2=ee2; } ! 1250: }; ! 1251: ! 1252: struct block : stmt { // BLOCK { d s } ! 1253: block(loc ll, Pname nn, Pstmt ss, loc rr = noloc ) : stmt (BLOCK,ll,ss) ! 1254: { d=nn; where2=rr; } ! 1255: #ifndef GRAM ! 1256: void dcl(Ptable); ! 1257: Pstmt simpl(); ! 1258: #endif ! 1259: }; ! 1260: ! 1261: #ifndef GRAM ! 1262: struct pair : public stmt { // PAIR ! 1263: pair(loc ll, Pstmt a, Pstmt b) : stmt (PAIR,ll,a) { s2 = b; } ! 1264: }; ! 1265: #endif ! 1266: ! 1267: struct nlist { ! 1268: Pname head; ! 1269: Pname tail; ! 1270: nlist(Pname); ! 1271: void add(Pname n) { tail->n_list = n; tail = n; }; ! 1272: void add_list(Pname); ! 1273: }; ! 1274: ! 1275: extern Pname name_unlist(nlist*); ! 1276: ! 1277: struct slist { ! 1278: Pstmt head; ! 1279: Pstmt tail; ! 1280: slist(Pstmt s) { /*Nl++;*/ head = tail = s; }; ! 1281: void add(Pstmt s) { tail->s_list = s; tail = s; }; ! 1282: }; ! 1283: ! 1284: extern Pstmt stmt_unlist(slist*); ! 1285: ! 1286: struct elist { ! 1287: Pexpr head; ! 1288: Pexpr tail; ! 1289: elist(Pexpr e) { /*Nl++;*/ head = tail = e; }; ! 1290: void add(Pexpr e) { tail->e2 = e; tail = e; }; ! 1291: }; ! 1292: ! 1293: extern Pexpr expr_unlist(elist*); ! 1294: ! 1295: #ifndef GRAM ! 1296: extern class dcl_context * cc; ! 1297: ! 1298: struct dcl_context { ! 1299: Pname c_this; /* current fct's "this" */ ! 1300: Ptype tot; /* type of "this" or 0 */ ! 1301: Pname not; /* name of "this"'s class or 0 */ ! 1302: Pclass cot; /* the definition of "this"'s class */ ! 1303: Ptable ftbl; /* current fct's symbol table */ ! 1304: Pname nof; /* current fct's name */ ! 1305: ! 1306: void stack() { cc++; *cc = *(cc-1); }; ! 1307: void unstack() { cc--; }; ! 1308: }; ! 1309: ! 1310: #define MAXCONT 20 ! 1311: extern dcl_context ccvec[MAXCONT]; ! 1312: #endif ! 1313: ! 1314: extern void yyerror(char*); ! 1315: ! 1316: ! 1317: #ifndef GRAM ! 1318: extern char* line_format; ! 1319: ! 1320: extern Plist stat_mem_list; ! 1321: extern Plist isf_list; ! 1322: extern Pstmt st_ilist; ! 1323: extern Pstmt st_dlist; ! 1324: extern Ptable sti_tbl; ! 1325: extern Ptable std_tbl; ! 1326: extern int need_sti( Pexpr e, Ptable tbl = 0, bit is_static_ok = 0 ); ! 1327: Pexpr try_to_coerce(Ptype, Pexpr, char*, Ptable); ! 1328: extern bit can_coerce(Ptype, Ptype); ! 1329: extern Ptype np_promote(TOK, TOK, TOK, Ptype, Ptype, TOK); ! 1330: extern bit enum_promote; ! 1331: extern int suppress_error; ! 1332: extern void delete_local(); ! 1333: ! 1334: extern int over_call(Pname, Pexpr); ! 1335: extern Pname overFound; ! 1336: extern Pname Nover; ! 1337: extern Pname Ncoerce; ! 1338: extern Nover_coerce; ! 1339: struct ia : node { ! 1340: Pname local; // local variable for argument ! 1341: Pexpr arg; // actual arguments for call ! 1342: Ptype tp; // type of formal argument ! 1343: ia() { base = XIA; }; ! 1344: }; ! 1345: ! 1346: struct iline : node { ! 1347: Pname fct_name; /* fct called */ ! 1348: Pin i_next; ! 1349: Ptable i_table; ! 1350: int i_slots; // no of arg slots pointer to by i_args ! 1351: ia* i_args; ! 1352: iline() { base = XILINE; }; ! 1353: }; ! 1354: ! 1355: extern Pexpr curr_expr; ! 1356: extern Pin curr_icall; ! 1357: #define FUDGE111 11111 ! 1358: #define VTOK 22222 ! 1359: #define ITOR 77 ! 1360: ! 1361: extern Pstmt curr_loop; ! 1362: extern Pblock curr_block; ! 1363: extern Pstmt curr_switch; ! 1364: extern loc last_line; // last #line + number of '\n's output since ! 1365: extern int last_ll; // 0 or line of current stmt/dcl being printed ! 1366: extern FILE* out_file; // output file descriptor ! 1367: extern bit Cast; ! 1368: extern loc no_where; ! 1369: ! 1370: extern no_of_undcl; ! 1371: extern no_of_badcall; ! 1372: extern Pname undcl, badcall; ! 1373: ! 1374: extern long str_to_long(const char*); ! 1375: extern int c_strlen(const char* s); ! 1376: #endif ! 1377: ! 1378: #ifndef GRAM ! 1379: extern Pname vec_new_fct; ! 1380: extern Pname new_fct; ! 1381: extern Pname del_fct; ! 1382: extern Pname vec_del_fct; ! 1383: ! 1384: extern int Nstd; // standard coercion used (derived* =>base* or int=>long or ...) ! 1385: ! 1386: extern int stcount; // number of names generated using make_name() ! 1387: ! 1388: Pexpr replace_temp(Pexpr,Pexpr); ! 1389: void make_res(Pfct); ! 1390: ! 1391: extern int Pchecked; ! 1392: Pexpr ptr_init(Pptr,Pexpr,Ptable); ! 1393: Pexpr call_ctor(Ptable, Pexpr p, Pexpr ctor, Pexpr args, int d = REF, Pexpr vb_args = 0); ! 1394: Pexpr call_dtor(Pexpr p, Pexpr dtor, Pexpr arg = 0, int d = DOT, Pexpr vb_args = 0); ! 1395: void check_visibility(Pname, Pname, Pclass, Ptable, Pname); ! 1396: ! 1397: int make_assignment(Pname); ! 1398: ! 1399: extern Pname make_tmp(char, Ptype, Ptable); ! 1400: Pexpr init_tmp(Pname, Pexpr, Ptable); ! 1401: ! 1402: extern int is_unique_base(Pclass, char*, int, int = 0); ! 1403: extern Pexpr rptr(Ptype, Pexpr, int); ! 1404: ! 1405: extern int read_align(char*); ! 1406: extern void new_init(); ! 1407: ! 1408: extern void Eprint(Pexpr); ! 1409: extern Pexpr cast_cptr(Pclass ccl, Pexpr ee, Ptable tbl, int real_cast); ! 1410: extern Pexpr mptr_assign(Pexpr,Pexpr); ! 1411: extern Pclass Mptr; ! 1412: ! 1413: #endif ! 1414: ! 1415: extern bit fake_sizeof; // suppress error message for ``int v[];'' ! 1416: ! 1417: extern TOK lalex(); ! 1418: ! 1419: ! 1420: #ifdef DBG ! 1421: extern void display_expr( Pexpr, char* = 0, int = 0 ); ! 1422: extern void display_stmt( Pstmt, char* = 0, int = 0 ); ! 1423: extern void display_type( Ptype ); ! 1424: extern void display_namelist( Plist, char* = 0, int = 0 ); ! 1425: ! 1426: extern fprintf(const FILE*, const char* ...); ! 1427: extern void process_debug_flags( char* ); ! 1428: #define DB(a) if(scan_started){a;} ! 1429: extern int Adebug; // allocation (ctor/del) debugging ! 1430: extern int Ddebug; // dcl debugging ! 1431: extern int Edebug; // expr debugging ! 1432: extern int Ldebug; // lex/lalex debugging ! 1433: extern int Mdebug; // trace function matching ! 1434: extern int Ndebug; // norm debugging ! 1435: extern int Pdebug; // print debugging ! 1436: extern int Rdebug; // run() debugging ! 1437: extern int Sdebug; // simpl debugging ! 1438: extern int Tdebug; // typ debugging ! 1439: #define Ydebug yydebug ! 1440: extern int Ydebug; // yacc debugging ! 1441: ! 1442: #else ! 1443: ! 1444: #define DB(a) /**/ ! 1445: ! 1446: #endif ! 1447: ! 1448: #endif ! 1449: /* end */ ! 1450: 0707071010112043661004440001630000160000010071100466055375100000600000112027dcl.c /*ident "@(#)ctrans:src/dcl.c 1.5" */ ! 1451: /************************************************************************** ! 1452: ! 1453: C++ source for cfront, the C++ compiler front-end ! 1454: written in the computer science research center of Bell Labs ! 1455: ! 1456: Copyright (c) 1984 AT&T, Inc. All rights Reserved ! 1457: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 1458: ! 1459: dcl.c: ! 1460: ! 1461: ``declare'' all names, that is insert them in the appropriate symbol tables. ! 1462: ! 1463: Calculate the size for all objects (incl. stack frames), ! 1464: and find store the offsets for all members (incl. auto variables). ! 1465: "size.h" holds the constants needed for calculating sizes. ! 1466: ! 1467: Note that (due to errors) functions may nest ! 1468: ! 1469: *****************************************************************************/ ! 1470: ! 1471: ! 1472: #include "cfront.h" ! 1473: #include "size.h" ! 1474: ! 1475: class dcl_context ccvec[MAXCONT], * cc = ccvec; ! 1476: int byte_offset; ! 1477: int bit_offset; ! 1478: int max_align; ! 1479: int friend_in_class; ! 1480: static Pstmt itail; ! 1481: ! 1482: Pname dclass(Pname, Ptable); ! 1483: Pname denum(Pname, Ptable); ! 1484: void merge_init(Pname, Pfct, Pfct); ! 1485: ! 1486: void dosimpl(Pexpr e, Pname n) ! 1487: { ! 1488: //error('d',"dosimpl %k %n",e?e->base:0,n); ! 1489: if (n==0) { ! 1490: if (dummy_fct == 0) make_dummy(); ! 1491: n = dummy_fct; ! 1492: } ! 1493: Pname cf = curr_fct; ! 1494: curr_fct = n; ! 1495: e->simpl(); ! 1496: curr_fct = cf; ! 1497: } ! 1498: ! 1499: static Pexpr co_array_init(Pname n, Ptable tbl) ! 1500: /* ! 1501: handle simple arrays only. To be done well list_check() must ! 1502: be rewritten to handle dynamic initialization. ! 1503: */ ! 1504: { ! 1505: // error('d',"Ir forCO%n\[\]",n); ! 1506: Pexpr init = n->n_initializer; ! 1507: ! 1508: if (init->base != ILIST) { ! 1509: error("badIr for array ofCOs %n",n); ! 1510: return 0; ! 1511: } ! 1512: ! 1513: Pexpr el = 0; ! 1514: Pvec v = Pvec(n->tp); ! 1515: while (v->base==TYPE) v = Pvec(Pbase(v)->b_name->tp); ! 1516: Pname cn = v->typ->is_cl_obj(); ! 1517: Pclass cl = cn ? Pclass(cn->tp) : 0; ! 1518: //error('d',"v %t cl %d %t",v,cl,cl); ! 1519: int i = v->size; ! 1520: ! 1521: int count = 0; ! 1522: Pexpr il2; ! 1523: for (Pexpr il = init->e1; il; il = il2) { ! 1524: // generate n[0].cl(initializer), ! 1525: // ... ! 1526: // n[max].cl(initializer), ! 1527: Pexpr e = il->e1; ! 1528: il2 = il->e2; ! 1529: il->e2 = 0; ! 1530: if (e == dummy) break; ! 1531: //error('d',"il %k e %k",il->base,e?e->base:0); ! 1532: if (e->base == VALUE) { ! 1533: switch (e->tp2->base) { ! 1534: case CLASS: ! 1535: if (Pclass(e->tp2)!=cl) e = new texpr(VALUE,cl,il); ! 1536: break; ! 1537: default: ! 1538: Pname n2 = e->tp2->is_cl_obj(); ! 1539: if (n2==0 || Pclass(n2->tp)!=cl) e = new texpr(VALUE,cl,il); ! 1540: } ! 1541: } ! 1542: else ! 1543: e = new texpr(VALUE,cl,il); ! 1544: e->e2 = new expr(DEREF,n,new ival(count++)); ! 1545: e = e->typ(tbl); ! 1546: dosimpl(e,cc->nof); ! 1547: // e->simpl(); ! 1548: if (sti_tbl == tbl) { ! 1549: Pstmt ist = new estmt(SM,no_where,e,0); ! 1550: if (st_ilist == 0) ! 1551: st_ilist = ist; ! 1552: else ! 1553: itail->s_list = ist; ! 1554: itail = ist; ! 1555: } ! 1556: else { ! 1557: el = el ? new expr(G_CM,el,e) : e; ! 1558: } ! 1559: } ! 1560: ! 1561: if (i==0) ! 1562: v->size = count; ! 1563: else if (i==count) ! 1564: ; ! 1565: else if (i<count) { ! 1566: error("too manyIrs for%n (%d)",n, count); ! 1567: return 0; ! 1568: } ! 1569: else { ! 1570: // error('d',"too fewIrs for%n (%d)",n, count); ! 1571: if (cl->has_ictor()) ! 1572: error('s',"too fewIrs for%n",n); ! 1573: else error( "too fewIrs for%n (C %srequires a defaultK)", n, cl->string ); ! 1574: return 0; ! 1575: } ! 1576: return el; ! 1577: } ! 1578: ! 1579: int need_sti(Pexpr e, Ptable tbl, bit accept_name) ! 1580: /* ! 1581: check if non-static variables or operations are used ! 1582: INCOMPLETE ! 1583: */ ! 1584: { ! 1585: if (e == 0) return 0; ! 1586: // error('d',"need_sti: %d - %d %k %t",tbl?1:0,accept_name,e->base,e->tp); ! 1587: ! 1588: switch (e->base) { ! 1589: case QUEST: ! 1590: if (need_sti(e->cond,tbl,0) && tbl==0) return 1; ! 1591: case PLUS: ! 1592: case MINUS: ! 1593: case MUL: ! 1594: case DIV: ! 1595: case MOD: ! 1596: case ER: ! 1597: case OR: ! 1598: case ANDAND: ! 1599: case OROR: ! 1600: case LS: ! 1601: case RS: ! 1602: case EQ: ! 1603: case NE: ! 1604: case LT: ! 1605: case LE: ! 1606: case GT: ! 1607: case GE: ! 1608: case INCR: ! 1609: case DECR: ! 1610: case ASSIGN: ! 1611: if (need_sti(e->e1,tbl,accept_name) && tbl==0) return 1; ! 1612: // no break; ! 1613: ! 1614: case UMINUS: ! 1615: case UPLUS: ! 1616: case NOT: ! 1617: case COMPL: ! 1618: if (need_sti(e->e2,tbl,accept_name) && tbl==0) return 1; ! 1619: // no break ! 1620: ! 1621: case SIZEOF: ! 1622: default: ! 1623: ! 1624: return 0; ! 1625: ! 1626: case CAST: ! 1627: ! 1628: return need_sti(e->e1,tbl,accept_name); ! 1629: ! 1630: case ADDROF: ! 1631: { ! 1632: int i = need_sti(e->e2,tbl,1); ! 1633: return i; ! 1634: } ! 1635: ! 1636: case NAME: ! 1637: if (accept_name && Pname(e)->n_stclass==STATIC) return 0; ! 1638: ! 1639: // if ((Pname(e)->n_stclass==AUTO || Pname(e)->n_stclass==REGISTER) ! 1640: // && strncmp(Pname(e)->string,"__Q",3) != 0 ) { ! 1641: // error("localN%n inIr for static",e); ! 1642: // return 0; ! 1643: // } ! 1644: ! 1645: if (e->tp->tconst()) { ! 1646: if (vec_const || fct_const) return 0; ! 1647: Neval = 0; ! 1648: e->eval(); ! 1649: if (Neval == 0) return 0; ! 1650: } ! 1651: return 1; ! 1652: ! 1653: case DEREF: ! 1654: case REF: ! 1655: case DOT: ! 1656: if (accept_name||(e->tp && e->tp->base==VEC)) { ! 1657: int x1 = need_sti(e->e1,tbl,e->base == DOT); ! 1658: int x2 = need_sti(e->e2,tbl,0); ! 1659: return x1 || x2; ! 1660: } ! 1661: // no break ! 1662: ! 1663: case ELIST: ! 1664: // case ILIST: ! 1665: case G_CM: ! 1666: case CM: ! 1667: if (e->base==CM) { ! 1668: if (need_sti(e->e1,tbl,0) || need_sti(e->e2,tbl,0)) ! 1669: return 1; ! 1670: else ! 1671: return 0; ! 1672: } ! 1673: case CALL: ! 1674: case G_CALL: ! 1675: case NEW: ! 1676: case GNEW: ! 1677: case 0: // hack for `new type (expr)' ! 1678: if (tbl) { ! 1679: need_sti(e->e1,tbl,accept_name); ! 1680: need_sti(e->e2,tbl,accept_name); ! 1681: if ( e->tp && e->tp->base == VEC && ! 1682: e->base == NEW || e->base == GNEW ) ! 1683: // preserve ICON,STRING,CCON,FCON ! 1684: need_sti(Pvec(e->tp)->dim,tbl); ! 1685: } ! 1686: else if (e->base == 0) ! 1687: return 0; ! 1688: // no break ! 1689: case ICALL: ! 1690: return 1; ! 1691: case ICON: ! 1692: case STRING: ! 1693: case CCON: ! 1694: case FCON: ! 1695: //error('d',"save %k tbl %d",e->base,tbl); ! 1696: if (tbl) { ! 1697: char* p = new char[strlen(e->string)+1]; ! 1698: strcpy(p,e->string); ! 1699: e->string = p; ! 1700: } ! 1701: return 0; ! 1702: } ! 1703: } ! 1704: ! 1705: static void check_def_name( Pname nn, int scope ) ! 1706: { ! 1707: // error('d', "check_def_name: nn: %n n_sto: %k scope: %k", nn,nn->n_sto,scope ); ! 1708: if ( def_name==0 && pdef_name==0 && friend_in_class == 0 && ! 1709: scope == EXTERN && nn->n_scope != STATIC && ! 1710: nn->n_oper != NEW && nn->n_oper != DELETE ) { ! 1711: Pfct f = Pfct(nn->tp); ! 1712: if (f->body && ! 1713: f->f_inline == 0 && ! 1714: f->f_imeasure == 0) { ! 1715: // error('d', "check_def_name: do it: %n", nn ); ! 1716: pdef_name = def_name = nn; ! 1717: ptbl_init(0); ! 1718: def_name = 0; ! 1719: } ! 1720: } ! 1721: } ! 1722: ! 1723: int stat_init = 0; // in an expression initializing a local static ! 1724: Pname name::dcl(Ptable tbl, TOK scope) ! 1725: /* ! 1726: enter a copy of this name into symbol table "tbl"; ! 1727: - create local symbol tables as needed ! 1728: ! 1729: "scope" gives the scope in which the declaration was found ! 1730: - EXTERN, FCT, ARG, PUBLIC, or 0 ! 1731: Compare "scope" with the specified storage class "n_sto" ! 1732: - AUTO, STATIC, REGISTER, EXTERN, OVERLOAD, FRIEND, or 0 ! 1733: ! 1734: After name::dcl() ! 1735: n_stclass == 0 class or enum member ! 1736: REGISTER auto variables declared register ! 1737: AUTO auto variables not registers ! 1738: STATIC statically allocated object ! 1739: n_scope == 0 private class member ! 1740: PUBLIC public class member ! 1741: EXTERN name valid in this and other files ! 1742: STATIC name valid for this file only ! 1743: FCT name local to a function ! 1744: ARG name of a function argument ! 1745: ARGT name of a type defined in an ! 1746: argument list ! 1747: ARGS temporary class object with dtor in ! 1748: initialization of a local static ! 1749: ! 1750: ! 1751: typecheck function bodies; ! 1752: typecheck initializers; ! 1753: ! 1754: note that functions (error recovery) and classes (legal) nest ! 1755: ! 1756: The return value is used to chain symbol table entries, but cannot ! 1757: be used for printout because it denotes the sum of all type information ! 1758: for the name ! 1759: ! 1760: names of typenames are marked with n_oper==TNAME ! 1761: ! 1762: WARNING: The handling of scope and storage class is cursed! ! 1763: */ ! 1764: { ! 1765: Pname nn; ! 1766: Ptype nnt = 0; ! 1767: Pname odcl = Cdcl; ! 1768: int sti_vb = 0; // set if initialize with virtual base class ! 1769: ! 1770: // if (this == 0) error('i',"0->N::dcl()"); ! 1771: // if (tbl == 0) error('i',"%n->N::dcl(tbl=0,%k)",this,scope); ! 1772: // if (tbl->base != TABLE) error('i',"%n->N::dcl(tbl=%d,%k)",this,tbl->base,scope); ! 1773: // if (tp == 0) error('i',"N::dcl(%n,%k)T missing",this,scope); ! 1774: ! 1775: Cdcl = this; ! 1776: Ptype tx = tp; ! 1777: ! 1778: DB( if(Ddebug>=1) error('d',"dcl %n %t",this,tx); ); ! 1779: // error('d',"dcl %n %t cc->cot: %d",this,tx,cc?cc->cot:0); ! 1780: while (tx->base == TYPE) tx = Pbase(tx)->b_name->tp; ! 1781: ! 1782: switch (base) { ! 1783: case TNAME: ! 1784: nn = tbl->look(string,0); ! 1785: tp->dcl(tbl); ! 1786: if (nn && nn->lex_level == lex_level) { ! 1787: //error('d', "dcl: cot: %s ccl: %s", cc->cot?cc->cot->string:"notset", ccl?ccl->string:"notset"); ! 1788: ! 1789: if ( tp->check(nn->tp,0) ) ! 1790: error("%n declared as %t and %t",nn,nn->tp,tp); ! 1791: else if ( nn->base == NAME && cc->cot == 0 && ! 1792: (tp->base != COBJ || tp->base != EOBJ)) ! 1793: error("%n declared as identifier and typedef", nn ); ! 1794: Cdcl = odcl; ! 1795: return 0; ! 1796: ! 1797: } ! 1798: PERM(tp); ! 1799: nn = new name(string); ! 1800: nn->base = TNAME; ! 1801: nn->tp = tp; ! 1802: Pname tn = tbl->insert(nn,0); ! 1803: if (n_key == NESTED) { ! 1804: tn->n_key = NESTED; ! 1805: tn->tpdef = tpdef; ! 1806: } ! 1807: delete nn; ! 1808: Cdcl = odcl; ! 1809: return this; ! 1810: ! 1811: case NAME: ! 1812: switch (n_oper) { ! 1813: case COMPL: ! 1814: if (tp->base != FCT) { ! 1815: error("~%s notF",string); ! 1816: n_oper = 0; ! 1817: } ! 1818: break; ! 1819: case TNAME: ! 1820: if (tp->base != FCT) n_oper = 0; ! 1821: break; ! 1822: } ! 1823: break; ! 1824: default: ! 1825: error('i',"NX in N::dcl()"); ! 1826: } ! 1827: ! 1828: if (n_qualifier) { ! 1829: // c::f() ! 1830: // class function, ! 1831: // friend declaration, or ! 1832: // static member initializer ! 1833: Pname cn = n_qualifier; ! 1834: ! 1835: switch (cn->base) { ! 1836: case TNAME: ! 1837: break; ! 1838: case NAME: ! 1839: cn = gtbl->look(cn->string,0); ! 1840: if (cn && cn->base==TNAME) break; ! 1841: default: ! 1842: error("badQr%n for%n",n_qualifier,this); ! 1843: Cdcl = odcl; ! 1844: return 0; ! 1845: } ! 1846: ! 1847: while (cn->tp->base == TYPE) cn->tp = Pbase(cn->tp)->b_name->tp; ! 1848: // error('d',"actualQr%n %t",cn,cn->tp); ! 1849: if (cn->tp->base != COBJ) { ! 1850: error(&where,"Qr%nnot aCN",n_qualifier); ! 1851: Cdcl = odcl; ! 1852: return 0; ! 1853: } ! 1854: ! 1855: cn = Pbase(cn->tp)->b_name; ! 1856: if (n_oper) check_oper(cn); ! 1857: ! 1858: Pclass cl = Pclass(cn->tp); ! 1859: if (cl == cc->cot) { ! 1860: n_qualifier = 0; ! 1861: goto xdr; ! 1862: } ! 1863: else if ((cl->defined&(DEFINED|SIMPLIFIED)) == 0) { ! 1864: error("C%nU",cn); ! 1865: Cdcl = odcl; ! 1866: return 0; ! 1867: } ! 1868: else if (cl->c_body==1) //III ! 1869: cl->dcl_print(0); ! 1870: ! 1871: Ptable etbl = cl->memtbl; ! 1872: Pname x = etbl->look(string,0); ! 1873: if (x==0 || x->n_table!=etbl) { ! 1874: error("%n is not aM of%n",this,cn); ! 1875: Cdcl = odcl; ! 1876: return 0; ! 1877: } ! 1878: ! 1879: if (tp->base == FCT) { //III ! 1880: // if (friend_in_class==0 && Pfct(tp)->body==0) { // c::f(); needed for friend ! 1881: if (friend_in_class==0 ! 1882: && n_sto!=FRIEND ! 1883: && Pfct(tp)->body==0) { // c::f(); needed for friend ! 1884: error("QdN%n inFD",x); ! 1885: Cdcl = odcl; ! 1886: return 0; ! 1887: } ! 1888: ! 1889: if (Pfct(tp)->body==0) { ! 1890: Pfct(tp)->memof = cl; ! 1891: int xx; ! 1892: if (x->tp->base==OVERLOAD) ! 1893: xx = Pgen(x->tp)->find(Pfct(tp),0)==0; ! 1894: else ! 1895: xx = x->tp->check(tp,0); ! 1896: ! 1897: if (xx) { ! 1898: error("%n is not aM of%n",this,cn); ! 1899: Cdcl = odcl; ! 1900: return 0; ! 1901: } ! 1902: } ! 1903: } ! 1904: else { ! 1905: if (x->n_stclass != STATIC) { // e.g. int c::i = 7 ! 1906: error("D of non staticCM %n",this); ! 1907: Cdcl = odcl; ! 1908: return 0; ! 1909: } ! 1910: if (n_sto) error("staticCM declared%k",n_sto); ! 1911: tbl = etbl; ! 1912: } ! 1913: } ! 1914: xdr: ! 1915: if (n_oper ! 1916: && tp->base!=FCT ! 1917: && n_sto!=OVERLOAD) error("operator%k not aF",n_oper); ! 1918: ! 1919: ! 1920: /* if a storage class was specified ! 1921: check that it is legal in the scope ! 1922: else ! 1923: provide default storage class ! 1924: some details must be left until the type of the object is known ! 1925: */ ! 1926: ! 1927: n_stclass = n_sto; ! 1928: n_scope = scope; /* default scope & storage class */ ! 1929: ! 1930: switch (n_sto) { ! 1931: default: ! 1932: error('i',"unX %k",n_sto); ! 1933: case FRIEND: ! 1934: { ! 1935: Pclass cl = cc->cot; ! 1936: ! 1937: switch (scope) { ! 1938: case 0: ! 1939: case PUBLIC: ! 1940: break; ! 1941: default: ! 1942: error("friend%n not inCD(%k)",this,scope); ! 1943: base = 0; ! 1944: Cdcl = odcl; ! 1945: return 0; ! 1946: } ! 1947: ! 1948: switch (n_oper) { ! 1949: case 0: ! 1950: case NEW: ! 1951: case DELETE: ! 1952: case CTOR: ! 1953: case DTOR: ! 1954: case TYPE: ! 1955: n_sto = 0; ! 1956: break; ! 1957: default: ! 1958: n_sto = OVERLOAD; ! 1959: } ! 1960: ! 1961: switch (tx->base) { ! 1962: case COBJ: ! 1963: nn = Pbase(tx)->b_name; ! 1964: break; ! 1965: case CLASS: ! 1966: nn = this; ! 1967: break; ! 1968: case FCT: ! 1969: cc->stack(); ! 1970: cc->not = 0; ! 1971: cc->tot = 0; ! 1972: cc->cot = 0; ! 1973: friend_in_class++; ! 1974: // n_sto = EXTERN; ! 1975: n_sto = 0; ! 1976: nn = dcl(gtbl,EXTERN); ! 1977: if (nn == 0) { ! 1978: Cdcl = odcl; ! 1979: return 0; ! 1980: } ! 1981: friend_in_class--; ! 1982: cc->unstack(); ! 1983: if (nn->tp->base == OVERLOAD) nn = Pgen(nn->tp)->find(Pfct(tx),1); ! 1984: break; ! 1985: default: ! 1986: error("badT%tof friend%n",tp,this); ! 1987: Cdcl = odcl; ! 1988: return 0; ! 1989: } ! 1990: PERM(nn); ! 1991: cl->friend_list = new name_list(nn,cl->friend_list); ! 1992: Cdcl = odcl; ! 1993: return nn; ! 1994: } ! 1995: case OVERLOAD: ! 1996: if (strict_opt||warning_opt) ! 1997: error(strict_opt?0:'w',"`overload' used (anachronism)"); ! 1998: n_sto = 0; ! 1999: // ignore overload! ! 2000: switch (tp->base) { ! 2001: case FCT: ! 2002: break; ! 2003: default: ! 2004: base = 0; ! 2005: Cdcl = odcl; ! 2006: return this; ! 2007: } ! 2008: break; ! 2009: case REGISTER: ! 2010: if (tp->base == FCT) { ! 2011: error('w',"%n: register (ignored)",this); ! 2012: goto ddd; ! 2013: } ! 2014: case AUTO: ! 2015: switch (scope) { ! 2016: case 0: ! 2017: case PUBLIC: ! 2018: case EXTERN: ! 2019: error("%k not inF",n_sto); ! 2020: goto ddd; ! 2021: } ! 2022: if (n_sto==AUTO) n_sto = 0; // always redundant ! 2023: break; ! 2024: case EXTERN: ! 2025: switch (scope) { ! 2026: case ARG: ! 2027: //error("externA"); ! 2028: goto ddd; ! 2029: case 0: ! 2030: case PUBLIC: ! 2031: /* extern is provided as a default for functions without body */ ! 2032: if (tp->base != FCT) error("externM%n",this); ! 2033: goto ddd; ! 2034: case FCT: ! 2035: { ! 2036: Pname nn = gtbl->look( string, 0 ); ! 2037: tp->dcl(tbl); ! 2038: if ( nn && tp->base != FCT && ! 2039: tp->check(nn->tp,0)) ! 2040: { ! 2041: error("twoDs of%n;Ts:%t and%t",this,nn->tp,tp); ! 2042: Cdcl = odcl; ! 2043: return 0; ! 2044: } ! 2045: } ! 2046: } ! 2047: n_stclass = STATIC; ! 2048: n_scope = EXTERN; /* avoid FCT scoped externs to allow better checking */ ! 2049: break; ! 2050: case STATIC: ! 2051: switch (scope) { ! 2052: case ARG: ! 2053: //error("static used forA%n",this); ! 2054: goto ddd; ! 2055: case 0: ! 2056: case PUBLIC: ! 2057: n_stclass = STATIC; ! 2058: n_scope = scope; ! 2059: break; ! 2060: default: ! 2061: n_scope = STATIC; ! 2062: } ! 2063: break; ! 2064: case 0: ! 2065: ddd: ! 2066: switch (scope) { /* default storage classes */ ! 2067: case EXTERN: ! 2068: n_scope = EXTERN; ! 2069: n_stclass = STATIC; ! 2070: break; ! 2071: case FCT: ! 2072: if (tp->base == FCT) { ! 2073: n_stclass = STATIC; ! 2074: n_scope = EXTERN; ! 2075: } ! 2076: else ! 2077: n_stclass = AUTO; ! 2078: break; ! 2079: case ARG: ! 2080: n_stclass = AUTO; ! 2081: break; ! 2082: case 0: ! 2083: case PUBLIC: ! 2084: n_stclass = 0; ! 2085: break; ! 2086: } ! 2087: } ! 2088: ! 2089: ! 2090: /* ! 2091: now insert the name into the appropriate symbol table, ! 2092: and compare types with previous declarations of that name ! 2093: ! 2094: do type dependent adjustments of the scope ! 2095: */ ! 2096: //error('d',"sw %d",tx->base); ! 2097: static int warn_ldouble=0; ! 2098: ! 2099: switch (tx->base) { ! 2100: case ASM: ! 2101: { Pbase b = Pbase(tp); ! 2102: Pname n = tbl->insert(this,0); ! 2103: n->assign(); ! 2104: n->use(); ! 2105: char* s = (char*) b->b_name; // save asm string. Shoddy ! 2106: int ll = strlen(s); ! 2107: char* s2 = new char[ll+1]; ! 2108: strcpy(s2,s); ! 2109: b->b_name = Pname(s2); ! 2110: Cdcl = odcl; ! 2111: return this; ! 2112: } ! 2113: ! 2114: case CLASS: ! 2115: tp = tx; ! 2116: nn = dclass(this,tbl); ! 2117: Cdcl = odcl; ! 2118: return nn; ! 2119: ! 2120: case ENUM: ! 2121: tp = tx; ! 2122: nn = denum(this,tbl); ! 2123: Cdcl = odcl; ! 2124: return nn; ! 2125: ! 2126: case FCT: ! 2127: tp = tx; ! 2128: nn = dofct(tbl,scope); ! 2129: if (nn == 0) { ! 2130: Cdcl = odcl; ! 2131: return 0; ! 2132: } ! 2133: ! 2134: // error('d', "%s n_oper: %k, scope: %k", string, n_oper, scope ); ! 2135: if (pdef_name == 0) check_def_name(nn, scope); ! 2136: break; ! 2137: ! 2138: case FIELD: ! 2139: switch (n_stclass) { ! 2140: case 0: ! 2141: case PUBLIC: ! 2142: break; ! 2143: default: ! 2144: error("%k field",n_stclass); ! 2145: n_stclass = 0; ! 2146: } ! 2147: ! 2148: if (cc->not==0 || cc->cot->csu==UNION || cc->cot->csu==ANON) { ! 2149: error(cc->not?"field in union":"field not inC"); ! 2150: PERM(tp); ! 2151: Cdcl = odcl; ! 2152: return this; ! 2153: } ! 2154: ! 2155: if (string) { ! 2156: nn = tbl->insert(this,0); ! 2157: n_table = nn->n_table; ! 2158: if (Nold) error("twoDs of field%n",this); ! 2159: } ! 2160: ! 2161: tp->dcl(tbl); ! 2162: field_align(); ! 2163: break; ! 2164: ! 2165: case COBJ: ! 2166: { Pclass cl = Pclass(Pbase(tx)->b_name->tp); ! 2167: //error('d',&where,"dcl %n; tx->base == cobj",this); ! 2168: if (cl->lex_level > lex_level) ! 2169: error("C%t is not visible in this scope",cl); ! 2170: ! 2171: if (cl->csu == ANON) { // export member names to enclosing scope ! 2172: if (tbl==gtbl && n_sto!=STATIC) error("extern anonymous union (declare as static)"); ! 2173: char* p = cl->string; ! 2174: while (*p++ != 'C'); /* sneaky */ ! 2175: int uindex = (int)str_to_long(p); ! 2176: ! 2177: // error('d', "%n->dcl() n_scope: %k n_protect: %k", this, n_scope, n_protect ); ! 2178: // cannot cope with use counts for ANONs: ! 2179: Pbase(tp)->b_name->n_used = 1; ! 2180: Pbase(tp)->b_name->n_assigned_to = 1; ! 2181: ! 2182: Ptable mtbl = cl->memtbl; ! 2183: int i, err_msg = 0; ! 2184: for (Pname nn=mtbl->get_mem(i=1); nn; nn=mtbl->get_mem(++i)) { ! 2185: if (nn->tp->base == FCT) { ! 2186: error("FM%n for anonymous union",nn); ! 2187: break; ! 2188: } ! 2189: Ptable tb = nn->n_table; ! 2190: nn->n_table = 0; ! 2191: nn->n_scope = n_protect?n_protect:n_scope; ! 2192: Pname n = tbl->insert(nn,0); ! 2193: if (Nold) { ! 2194: error("twoDs of%n (one in anonymous union)",nn); ! 2195: break; ! 2196: } ! 2197: ! 2198: Pclass tc; ! 2199: if (tc = cl->in_class) ! 2200: --n->lex_level; ! 2201: if ( tc && tc->csu == ANON) { ! 2202: //error('d', "tc->csu anon %k %s", tc->csu, string ); ! 2203: if ( n->n_anon ) { ! 2204: if ( !err_msg ) ! 2205: error('s', "anonymous unions nested deeper than 2 levels" ); ! 2206: err_msg = 1; ! 2207: } ! 2208: n->n_anon = string; ! 2209: } ! 2210: ! 2211: n->n_union = uindex; ! 2212: nn->n_table = tb; ! 2213: } ! 2214: } ! 2215: if (cl->c_abstract) error("D ofO of abstractC%t",cl); ! 2216: goto cde; ! 2217: } ! 2218: ! 2219: case VOID: ! 2220: if (n_scope != ARG) { ! 2221: error("badBT:%k%n",tx->base,this); ! 2222: Cdcl = odcl; ! 2223: return 0; ! 2224: } ! 2225: break; ! 2226: ! 2227: case LDOUBLE: ! 2228: if (warn_ldouble==0 && ansi_opt==0) { ! 2229: ++warn_ldouble; ! 2230: error('w',"long double supported under ``+a1'' option only, generating ``double%n''", this); ! 2231: } ! 2232: goto cde; ! 2233: ! 2234: case PTR: ! 2235: case VEC: ! 2236: case RPTR: ! 2237: tp->dcl(tbl); ! 2238: ! 2239: default: ! 2240: cde: ! 2241: //error('d',"cde: %n %t",this,tp); ! 2242: nn = tbl->insert(this,0); ! 2243: n_table = nn->n_table; ! 2244: ! 2245: if (Nold) { ! 2246: ! 2247: if ( nn->base == PUBLIC ) { // X::i ! 2248: error("twoDs ofCM%n", nn); ! 2249: Cdcl = odcl; ! 2250: return 0; ! 2251: } ! 2252: ! 2253: if (nn->tp->base == ANY) goto zzz; ! 2254: ! 2255: if (tp->check(nn->tp,0)) { ! 2256: error("twoDs of%n;Ts:%t and%t",this,nn->tp,tp); ! 2257: Cdcl = odcl; ! 2258: return 0; ! 2259: } ! 2260: //error('d',"%n: %k %k scope %k",this,n_sto,nn->n_sto,nn->n_scope); ! 2261: if (n_sto && n_sto!=nn->n_scope) { ! 2262: if (n_sto==EXTERN && nn->n_scope==STATIC) { ! 2263: error('w',"%n declared extern after being declared static",this); ! 2264: goto ext_fudge; ! 2265: } ! 2266: else ! 2267: error("%n declared as both%k and%k",this,n_sto,(nn->n_sto)?nn->n_sto:(scope==FCT?AUTO:EXTERN)); ! 2268: } ! 2269: else if (nn->n_scope==STATIC && n_scope==EXTERN) { ! 2270: error('w',"static%n followed by definition",this); ! 2271: ext_fudge: ! 2272: if (n_initializer) { ! 2273: // error('d',"static%n redefined (WIr)",this); ! 2274: n_initializer = 0; ! 2275: } ! 2276: n_sto = EXTERN; ! 2277: } ! 2278: else if (nn->n_sto==STATIC && n_sto==STATIC ) ! 2279: error("static%n declared twice",this); ! 2280: else { ! 2281: if (n_sto==0 ! 2282: && nn->n_sto==EXTERN ! 2283: && n_initializer ! 2284: && tp->tconst()) ! 2285: n_sto = EXTERN; ! 2286: n_scope = nn->n_scope; ! 2287: ! 2288: switch (scope) { ! 2289: case FCT: ! 2290: if (n_sto != EXTERN) { ! 2291: error("twoDs of%n",this); ! 2292: Cdcl = odcl; ! 2293: return 0; ! 2294: } ! 2295: break; ! 2296: case ARG: ! 2297: error("twoAs%n",this); ! 2298: Cdcl = odcl; ! 2299: return 0; ! 2300: case 0: ! 2301: case PUBLIC: ! 2302: error("twoDs ofM%n",this); ! 2303: Cdcl = odcl; ! 2304: return 0; ! 2305: case EXTERN: ! 2306: if (n_sto==0) { ! 2307: switch(nn->n_sto) { ! 2308: case 0: ! 2309: error("two definitions of%n",this); ! 2310: Cdcl = odcl; ! 2311: return 0; ! 2312: case EXTERN: ! 2313: if(nn->n_initializer) { ! 2314: error("two definitions of%n",this); ! 2315: Cdcl = odcl; ! 2316: } ! 2317: else ! 2318: nn->n_sto=0; ! 2319: break; ! 2320: } ! 2321: } ! 2322: else if(n_sto==EXTERN && n_initializer) { ! 2323: switch(nn->n_sto) { ! 2324: case 0: ! 2325: error("two definitions of%n",this); ! 2326: Cdcl = odcl; ! 2327: return 0; ! 2328: case EXTERN: ! 2329: nn->n_sto=0; ! 2330: break; ! 2331: } ! 2332: } ! 2333: break; ! 2334: } ! 2335: } ! 2336: n_scope = nn->n_scope; ! 2337: /* n_val */ ! 2338: if (n_initializer) { ! 2339: if (nn->n_initializer || nn->n_val) error("twoIrs for%n",this); ! 2340: nn->n_initializer = n_initializer; ! 2341: } ! 2342: if (tp->base == VEC) { ! 2343: // handle: extern v[]; v[200]; ! 2344: // and extern u[10]; u[11]; ! 2345: ! 2346: Ptype ntp = nn->tp; ! 2347: while (ntp->base == TYPE) ntp = Pbase(ntp)->b_name->tp; ! 2348: if (Pvec(ntp)->dim == 0) Pvec(ntp)->dim = Pvec(tp)->dim; ! 2349: if (Pvec(ntp)->size) { ! 2350: if (Pvec(tp)->size ! 2351: && Pvec(ntp)->size!=Pvec(tp)->size) ! 2352: error("bad array size for%n: %d %dX",this,Pvec(tp)->size,Pvec(ntp)->size); ! 2353: } ! 2354: else ! 2355: Pvec(ntp)->size = Pvec(tp)->size; ! 2356: } ! 2357: } ! 2358: else { ! 2359: //error('d',"%n %t scope %d sto %k",this,tp,scope,n_sto); ! 2360: if (scope!=ARG ! 2361: && n_sto!=EXTERN ! 2362: && (!((scope==0 || scope==PUBLIC) && n_sto==STATIC)) // static member ! 2363: && n_initializer==0 ! 2364: && tp->base==VEC ! 2365: && Pvec(tp)->size==0) ! 2366: error(&where,"dimension missing for array%n",this); ! 2367: ! 2368: if (scope==EXTERN ! 2369: && n_sto==0 ! 2370: && tp->tconst() ! 2371: && vec_const==0 ! 2372: && fct_const==0) ! 2373: nn->n_sto = n_sto = STATIC; ! 2374: } ! 2375: ! 2376: zzz: ! 2377: if (base != TNAME) { ! 2378: Ptype t = nn->tp; ! 2379: ! 2380: if (t->base == TYPE) { ! 2381: Ptype tt = Pbase(t)->b_name->tp; ! 2382: if (tt->base == FCT) nn->tp = t = tt; ! 2383: } ! 2384: ! 2385: switch (t->base) { ! 2386: case FCT: ! 2387: case OVERLOAD: ! 2388: break; ! 2389: default: ! 2390: fake_sizeof = 1; ! 2391: switch (nn->n_stclass) { ! 2392: default: ! 2393: if (nn->n_scope != ARG) { ! 2394: int x = t->align(); ! 2395: int y = t->tsizeof(); ! 2396: ! 2397: if (max_align < x) max_align = x; ! 2398: ! 2399: while (0 < bit_offset) { ! 2400: byte_offset++; ! 2401: bit_offset -= BI_IN_BYTE; ! 2402: } ! 2403: bit_offset = 0; ! 2404: ! 2405: if (byte_offset && 1<x) byte_offset = ((byte_offset-1)/x)*x+x; ! 2406: nn->n_offset = byte_offset; ! 2407: byte_offset += y; ! 2408: } ! 2409: break; ! 2410: case STATIC: ! 2411: if (n_sto != EXTERN ! 2412: && nn->n_scope ! 2413: && nn->n_scope!=PUBLIC) ! 2414: t->tsizeof(); // check that size is known ! 2415: } ! 2416: fake_sizeof = 0; ! 2417: } ! 2418: } ! 2419: ! 2420: { Ptype t = nn->tp; ! 2421: int const_old = const_save; ! 2422: bit vec_seen = 0; ! 2423: Pexpr init = n_initializer; ! 2424: ! 2425: lll: ! 2426: // error('d',"lll %n %t init %d %k",this,t,init,init?init->base:0); ! 2427: switch (t->base) { ! 2428: case COBJ: ! 2429: { Pname cn = Pbase(t)->b_name; ! 2430: Pclass cl = (Pclass)cn->tp; ! 2431: Pname ctor = cl->has_ctor(); ! 2432: Pname dtor = cl->has_dtor(); ! 2433: int stct = 0; ! 2434: //error('d',"obj %n; class '%s'; ctor '%s'; dtor '%s'",nn,cn->string,ctor?ctor->string:"???",dtor?dtor->string:"???"); ! 2435: if (dtor) { ! 2436: Pstmt dls; ! 2437: ! 2438: // if dtor is not public check scope of class object ! 2439: ! 2440: //error('d',"dcl %n has dtor",nn); ! 2441: if (dtor->n_scope != PUBLIC) { ! 2442: //error('d',"dcl %n->n_scope: %d fct %n",nn,nn->n_scope,cc->nof); ! 2443: switch (nn->n_scope) { ! 2444: case ARG: ! 2445: case 0: ! 2446: case PUBLIC: ! 2447: break; ! 2448: default: ! 2449: check_visibility( dtor, 0, cl, tbl, cc->nof ); ! 2450: } ! 2451: // if (nn->n_scope == FCT) ! 2452: // check_visibility( dtor, 0, cl, tbl, cc->nof ); ! 2453: // else if ( nn->n_sto != EXTERN ) ! 2454: // error("%k%n cannot access%n: %sM",nn->n_scope,nn,dtor,dtor->n_protect?"protected":"private"); ! 2455: } ! 2456: ! 2457: switch ( nn->n_scope ) { ! 2458: case 0: ! 2459: case PUBLIC: ! 2460: if (n_stclass==STATIC) { //III ! 2461: Pclass cl = Pclass(nn->n_table->t_name->tp); ! 2462: if (cl->defined&DEFINED) goto dtdt; ! 2463: } ! 2464: break; ! 2465: case EXTERN: ! 2466: if (n_sto==EXTERN) break; ! 2467: ! 2468: case STATIC: ! 2469: { Pexpr c; ! 2470: dtdt: ! 2471: // local static class objects have destructors set up in simpl2.c ! 2472: // special case: temporary class object generated in init expression ! 2473: if (stat_init && scope == ARGS ) { ! 2474: nn->n_scope = ARGS; ! 2475: goto ggg; ! 2476: } ! 2477: ! 2478: if ( nn->lex_level ! 2479: && nn->n_sto == STATIC ) { ! 2480: if (ctor==0) ! 2481: error('s',"local static%n has%n but noK(add%n::%n())", nn, dtor, cn, cn ); ! 2482: goto static_init; ! 2483: } ! 2484: ! 2485: Ptable otbl = tbl; ! 2486: // to collect temporaries generated ! 2487: // in static destructors where we ! 2488: // can find them again (in std_tbl) ! 2489: if (std_tbl == 0) std_tbl = new table(8,gtbl,0); ! 2490: tbl = std_tbl; ! 2491: if (vec_seen) { ! 2492: c = cdvec(vec_del_fct,nn,cl,dtor,0,zero); ! 2493: } else { // nn->cl::~cl(0); ! 2494: c = call_dtor(nn,dtor,0,DOT,one); ! 2495: } ! 2496: c->tp = any_type; // avoid another check ! 2497: dls = new estmt(SM,nn->where,c,0); ! 2498: ! 2499: // destructors for statics are executed in reverse order ! 2500: if (st_dlist) dls->s_list = st_dlist; ! 2501: st_dlist = dls; ! 2502: tbl = otbl; ! 2503: } // case STATIC ! 2504: } // switch nn->n_scope ! 2505: } // if dtor ! 2506: ! 2507: // local static class objects must defer setting up static dtor ! 2508: static_init: ! 2509: if (ctor) { ! 2510: // error('d',"ctor %n scope %k",ctor,nn->n_scope); ! 2511: Pexpr oo = nn; ! 2512: for (int vi=vec_seen; vi; vi--) oo = oo->contents(); ! 2513: int sti = 0; ! 2514: switch (nn->n_scope) { ! 2515: case EXTERN: ! 2516: if (init==0 && n_sto==EXTERN) goto ggg; ! 2517: case STATIC: ! 2518: if (tbl == gtbl) ! 2519: sti = 1; ! 2520: else ! 2521: stct = 1; ! 2522: default: ! 2523: if (vec_seen && init) { ! 2524: if (1<vec_seen) { ! 2525: /* ????? ! 2526: if (init->base != ILIST) ! 2527: error("badIr forO ofC %t withK%n",cl,this); ! 2528: else ! 2529: */ ! 2530: error('s',"Ir for multi-dimensional array%n ofOsofC %t withK",this,cl); ! 2531: } ! 2532: else { ! 2533: if (sti) { ! 2534: if (sti_tbl==0) sti_tbl = new table(8,gtbl,0); ! 2535: const_save = 1; ! 2536: (void) co_array_init(nn,sti_tbl); ! 2537: const_save = 0; ! 2538: n_initializer = init = 0; ! 2539: } ! 2540: else { ! 2541: n_initializer = init = co_array_init(nn,tbl); ! 2542: if (stct) ! 2543: nn->n_initializer = n_initializer = init = new expr( STAT_INIT, init, 0 ); ! 2544: } ! 2545: } ! 2546: goto ggg; ! 2547: } ! 2548: break; ! 2549: case PUBLIC: ! 2550: case 0: ! 2551: if (n_stclass==STATIC) { //III ! 2552: Pclass cl = Pclass(nn->n_table->t_name->tp); ! 2553: if (cl->defined&DEFINED) { ! 2554: sti = 1; ! 2555: break; ! 2556: } ! 2557: } ! 2558: { ! 2559: Pname c; ! 2560: if (vec_seen) { ! 2561: c = cl->has_ictor(); ! 2562: if (c == 0) ! 2563: error("array ofC%n that does not have aK taking noAs",cn); ! 2564: else if (Pfct(c->tp)->nargs) ! 2565: error("defaultAs forK for array ofC%n",cn); ! 2566: } ! 2567: } ! 2568: // no break ! 2569: case ARG: ! 2570: goto ggg; ! 2571: } ! 2572: ! 2573: const_save = 1; ! 2574: nn->assign(); ! 2575: Ptable otbl = tbl; ! 2576: if (sti) { // to collect temporaries generated ! 2577: // in static initializers where we ! 2578: // can find them again (in sti_tbl) ! 2579: if (sti_tbl == 0) sti_tbl = new table(8,gtbl,0); ! 2580: tbl = sti_tbl; ! 2581: if (n_sto == EXTERN) nn->n_sto = n_sto = 0; ! 2582: } ! 2583: ! 2584: if (init) { ! 2585: // error('d',"init %k",init->base); ! 2586: if (init->base==VALUE) { ! 2587: switch (init->tp2->base) { ! 2588: case CLASS: ! 2589: // error('d',"class %t %t",Pclass(init->tp2),cl); ! 2590: if (Pclass(init->tp2)!=cl) goto inin; ! 2591: break; ! 2592: default: ! 2593: Pname n2 = init->tp2->is_cl_obj(); ! 2594: // error('d',"default %t %t",n2->tp,cl); ! 2595: if (n2==0 || Pclass(n2->tp)!=cl) goto inin; ! 2596: } ! 2597: ! 2598: Pexpr ee = init->e1; ! 2599: // error('d',"init->e1 %k",ee->base); ! 2600: if (ee && vec_seen==0) ! 2601: switch (ee->base) { ! 2602: case CALL: // T a = f(); ! 2603: init = ee; ! 2604: goto inin; ! 2605: case ELIST: // T a(f()); ! 2606: if (ee->e1->base==CALL ! 2607: && ee->e2 == 0) { ! 2608: init = ee->e1; ! 2609: goto inin; ! 2610: } ! 2611: } // end switch ! 2612: ! 2613: init->e2 = oo; ! 2614: init = init->typ(tbl); ! 2615: ! 2616: if (init->base == G_CM) // beware of type conversion operators ! 2617: switch (init->tp2->base) { ! 2618: case CLASS: ! 2619: if (Pclass(init->tp2)!=cl) goto inin; ! 2620: break; ! 2621: default: ! 2622: Pname n2 = init->tp2->is_cl_obj(); ! 2623: if (n2==0 || Pclass(n2->tp)!=cl) goto inin; ! 2624: } ! 2625: } ! 2626: else { ! 2627: inin: ! 2628: // error('d',"inin %k",init->base); ! 2629: init = init->typ(tbl); ! 2630: //error('d', "inin: init->typ: %d %k n->tp %t init->tp %t",init->base,init->base,nn->tp,init->tp); ! 2631: if (init->base==G_CM ! 2632: && nn->tp->check(init->tp,0)==0) ! 2633: (void) replace_temp(init,nn->address()); ! 2634: else ! 2635: init = class_init(nn,nn->tp,init,tbl); ! 2636: } ! 2637: } ! 2638: else if (vec_seen == 0) { ! 2639: //error('d',"make value"); ! 2640: init = new texpr(VALUE,cl,0); ! 2641: init->e2 = oo; ! 2642: init = init->typ(tbl); ! 2643: } ! 2644: ! 2645: Pname c; ! 2646: if (vec_seen) { ! 2647: c = cl->has_ictor(); ! 2648: if (c == 0) ! 2649: error("array ofC%n that does not have aK taking noAs",cn); ! 2650: else if (Pfct(c->tp)->nargs) ! 2651: error("defaultAs forK for array ofC%n",cn); ! 2652: } ! 2653: ! 2654: // error( 'd', "stct: %d init: %d", stct, init ); ! 2655: if (stct) { ! 2656: if (tbl!=gtbl && nn->n_sto==EXTERN) { ! 2657: error(&where,"Id local extern%n",this); ! 2658: init = 0; ! 2659: } ! 2660: else if (init) ! 2661: init->base = STAT_INIT; ! 2662: else { ! 2663: if (tp->base == VEC && Pvec(tp)->size ) { ! 2664: Pexpr ilist = 0; ! 2665: for (int i=Pvec(tp)->size; i>0; i--) { ! 2666: Pexpr e = new texpr(VALUE,cl,0); ! 2667: ilist = new expr(ELIST, e, ilist); ! 2668: } ! 2669: nn->n_initializer=new expr(ILIST,ilist,0); ! 2670: init = co_array_init(nn,tbl); ! 2671: nn->n_initializer = n_initializer = init = new expr( STAT_INIT, init, 0 ); ! 2672: } ! 2673: else ! 2674: error('s',"local staticC%n (%t)",this, tp); ! 2675: } ! 2676: } ! 2677: ! 2678: // error('d', "%n->sti: %d vec_seen: %d n_stclass: %k", this, sti, vec_seen, n_stclass ); ! 2679: if (sti) { ! 2680: if (vec_seen) { // _vec_new(vec,noe,sz,ctor); ! 2681: // error('d', "%n->dcl: n_stclass: %k ", this, n_stclass ); ! 2682: if ( n_stclass == STATIC && n_initializer ) { ! 2683: const_save = 1; ! 2684: (void) co_array_init(nn,sti_tbl); ! 2685: const_save = 0; ! 2686: n_initializer = init = 0; ! 2687: goto ggg; ! 2688: } ! 2689: ! 2690: init = cdvec(vec_new_fct,nn,cl,c,-1,0); ! 2691: init->tp = any_type; ! 2692: } ! 2693: else { ! 2694: switch (init->base) { ! 2695: case DEREF: // *constructor? ! 2696: if (init->e1->base == G_CALL) { ! 2697: Pname fn = init->e1->fct_name; ! 2698: if (fn==0 || fn->n_oper!=CTOR) goto as; ! 2699: init = init->e1; ! 2700: break; ! 2701: } ! 2702: goto as; ! 2703: case G_CM: ! 2704: init = init->e1; ! 2705: // suppress further type checking ! 2706: if (init->tp == 0) init->tp= any_type; ! 2707: break; ! 2708: case ASSIGN: ! 2709: if (init->e1 == nn) break; // simple assignment ! 2710: as: ! 2711: default: ! 2712: init = new expr(ASSIGN,nn,init); ! 2713: } ! 2714: } ! 2715: Pstmt ist = new estmt(SM,nn->where,init,0); ! 2716: // constructors for statics are executed in order ! 2717: if (st_ilist == 0) ! 2718: st_ilist = ist; ! 2719: else ! 2720: itail->s_list = ist; ! 2721: itail = ist; ! 2722: init = 0; // suppress further processing ! 2723: } // if (sti) ! 2724: nn->n_initializer = n_initializer = init; ! 2725: const_save = const_old; ! 2726: tbl = otbl; ! 2727: } ! 2728: else if (init == 0) // no initializer ! 2729: goto str; ! 2730: else if (cl->is_simple() ! 2731: // && cl->csu!=UNION // accept ANSIism ! 2732: && cl->csu!=ANON ! 2733: ) { // struct ! 2734: init = init->typ(tbl); ! 2735: if (nn->tp->check(init->tp,0)==0 ! 2736: && init->base==G_CM) ! 2737: (void) replace_temp(init,nn->address()); ! 2738: else { ! 2739: if (ansi_opt==0 ! 2740: && init->base==ILIST ! 2741: && cl->csu==UNION) ! 2742: error('s',"initialization of union withIL"); ! 2743: goto str; ! 2744: } ! 2745: } ! 2746: else if (init->base == ILIST) { // class or union ! 2747: error("cannotI%nWIrL",nn); ! 2748: } ! 2749: else { // bitwise copy ok? ! 2750: // possible to get here? ! 2751: init = init->typ(tbl); ! 2752: //error('d',"init22 %t %t",nn->tp,init->tp); ! 2753: if (nn->tp->check(init->tp,0)==0) { ! 2754: if (init->base==G_CM) ! 2755: (void) replace_temp(init,nn->address()); ! 2756: else ! 2757: goto str; ! 2758: } ! 2759: goto str; ! 2760: // else ! 2761: // error("cannotI%n:%k %s has noK",nn,cl->csu,cl->string); ! 2762: } ! 2763: break; ! 2764: } ! 2765: case VEC: ! 2766: t = Pvec(t)->typ; ! 2767: vec_seen++; ! 2768: goto lll; ! 2769: case TYPE: ! 2770: if (init==0 && Pbase(t)->b_const) { ! 2771: switch (n_scope) { ! 2772: case ARG: ! 2773: break; ! 2774: case 0: ! 2775: case PUBLIC: ! 2776: if ( cc->cot ) break; ! 2777: default: { ! 2778: Pname n = t->is_cl_obj(); ! 2779: Pclass cl; ! 2780: if ( n ) cl = Pclass( n->tp ); ! 2781: ! 2782: if (n_sto!=EXTERN && ! 2783: (n==0 || (cl->has_ctor()==0 && is_empty(cl,1)==0))) ! 2784: error("uninitialized const%n",this); ! 2785: } ! 2786: } ! 2787: } ! 2788: t = Pbase(t)->b_name->tp; ! 2789: goto lll; ! 2790: case RPTR: ! 2791: if (init) { ! 2792: if (nn->n_scope == ARG) break; ! 2793: if (Pptr(nn->tp)->memof) error("R toCM%n ofT%t illegal",nn,nn->tp); ! 2794: ref_initializer++; ! 2795: init = init->typ(tbl); ! 2796: ref_initializer--; ! 2797: Nvirt = 0; // set within ref_init() call ! 2798: const_ptr = Pbase(Pptr(t)->typ)->tconst(); ! 2799: ! 2800: if (n_sto==STATIC ! 2801: && init->lval(0)==0 ! 2802: && fct_const==0) ! 2803: error("Ir for staticR%n not an lvalue",this); ! 2804: else ! 2805: nn->n_initializer = n_initializer = init = ref_init(Pptr(t),init,tbl); ! 2806: ! 2807: const_ptr = 0; ! 2808: if (Nvirt == VIRTUAL) sti_vb = 1; ! 2809: nn->assign(); ! 2810: ! 2811: if (init->base==ILIST && init->e2==0) { ! 2812: new_list(init); ! 2813: list_check(nn,nn->tp,0,tbl); ! 2814: if (next_elem()) error(&where,"IrL too long"); ! 2815: } ! 2816: ! 2817: } ! 2818: else { ! 2819: switch (nn->n_scope) { ! 2820: default: ! 2821: if (n_sto == EXTERN) break; ! 2822: error("uninitializedR%n",this); ! 2823: case ARG: ! 2824: break; ! 2825: case PUBLIC: ! 2826: case 0: ! 2827: //III if (n_sto == STATIC) error("a staticM%n cannot be aR",this); ! 2828: // error('d', "%n->dcl cot: %s", this, cc->cot?cc->cot->string:"notset"); ! 2829: if ( cc->cot == 0 ) ! 2830: error("uninitializedR%n",this); ! 2831: break; ! 2832: } ! 2833: } ! 2834: goto stgg; ! 2835: default: ! 2836: str: ! 2837: // error('d',"str %n %t %k %t",this,tp,init?init->base:0,init?init->tp:0); ! 2838: if (init == 0) { ! 2839: switch (n_scope) { ! 2840: case ARG: ! 2841: break; ! 2842: case 0: ! 2843: case PUBLIC: ! 2844: if ( cc->cot ) break; ! 2845: default: ! 2846: if (n_sto!=EXTERN && t->tconst()) error("uninitialized const%n",this); ! 2847: } ! 2848: ! 2849: break; ! 2850: } ! 2851: ! 2852: const_save = const_save ! 2853: || n_scope==ARG ! 2854: || (t->tconst() && vec_const==0); ! 2855: ! 2856: if ( tp->base == PTR ) { ! 2857: if ( cc && cc->nof ! 2858: && Pfct(cc->nof->tp)->f_const ) ! 2859: cm_const_save = Pbase(Pptr(tp)->typ)->b_const; ! 2860: const_ptr = Pbase(Pptr(tp)->typ)->b_const; ! 2861: } ! 2862: ! 2863: if (n_sto==STATIC) stat_init++; ! 2864: nn->n_initializer = n_initializer = init = init->typ(tbl); ! 2865: if (n_sto==STATIC) stat_init--; ! 2866: ! 2867: cm_const_save = 0; ! 2868: const_ptr = 0; ! 2869: ! 2870: if (const_save) PERM(init); ! 2871: nn->assign(); ! 2872: const_save = const_old; ! 2873: //error('d',"init2 %k %t",init->base,init->tp); ! 2874: switch (init->base) { ! 2875: case ILIST: ! 2876: if (init->e2) goto dfdf;//break; // pointer to member ! 2877: new_list(init); ! 2878: list_check(nn,nn->tp,0,tbl); ! 2879: if (next_elem()) error(&where,"IrL too long"); ! 2880: break; ! 2881: case STRING: ! 2882: { Ptype v = nn->tp; ! 2883: while (v->base == TYPE) v = Pbase(v)->b_name->tp; ! 2884: if (v->base==VEC) { ! 2885: Ptype vv = Pvec(v)->typ; ! 2886: while(vv->base==TYPE) vv = Pbase(vv)->b_name->tp; ! 2887: if(vv->base==CHAR) { ! 2888: int sz = Pvec(v)->size; ! 2889: int isz = Pvec(init->tp)->size; ! 2890: if (sz == 0) ! 2891: Pvec(v)->size = isz; ! 2892: else if (sz < isz) ! 2893: error(&where,"Ir too long (%d characters) for%n[%d]",isz,nn,sz); ! 2894: break; ! 2895: } ! 2896: } ! 2897: // no break ! 2898: } ! 2899: default: ! 2900: dfdf: ! 2901: { Ptype nt = nn->tp; ! 2902: int ntc = Pbase(nt)->b_const; ! 2903: ! 2904: if (vec_seen) { ! 2905: error("badIr for array%n",nn); ! 2906: break; ! 2907: } ! 2908: tlx: ! 2909: switch (nt->base) { ! 2910: case TYPE: ! 2911: nt = Pbase(nt)->b_name->tp; ! 2912: ntc |= Pbase(nt)->b_const; ! 2913: goto tlx; ! 2914: case INT: ! 2915: case CHAR: ! 2916: case SHORT: ! 2917: case EOBJ: ! 2918: // if (init->base==ICON && init->tp==long_type) ! 2919: // error('w',"longIr constant for%k%n",nn->tp->base,nn); ! 2920: { Ptype t = init->tp; ! 2921: csi: ! 2922: switch (t->base) { ! 2923: case TYPE: ! 2924: t = Pbase(t)->b_name->tp; goto csi; ! 2925: case LONG: ! 2926: case FLOAT: ! 2927: case DOUBLE: ! 2928: case LDOUBLE: ! 2929: error('w',"%tIdW %t",nt,init->tp); ! 2930: } ! 2931: } ! 2932: // no break ! 2933: case LONG: ! 2934: if (Pbase(nt)->b_unsigned ! 2935: && init->base==UMINUS ! 2936: && init->e2->base==ICON) ! 2937: error('w',"negativeIr for unsigned%n",nn); ! 2938: if (ntc && scope!=ARG) { ! 2939: long i; ! 2940: Neval = 0; ! 2941: i = init->eval(); ! 2942: if (Neval == 0) { ! 2943: DEL(init); ! 2944: nn->n_evaluated = n_evaluated = 1; ! 2945: nn->n_val = n_val = i; ! 2946: DEL(init); ! 2947: nn->n_initializer = n_initializer = 0; ! 2948: } ! 2949: } ! 2950: break; ! 2951: case PTR: ! 2952: Nvirt = 0; ! 2953: nn->n_initializer = n_initializer = init = ptr_init(Pptr(nt),init,tbl); ! 2954: //display_expr(init,string); ! 2955: if (Nvirt == VIRTUAL) sti_vb = 1; ! 2956: if (Pchecked) goto stgg; ! 2957: } ! 2958: ! 2959: { Pexpr x = try_to_coerce(nt,init,"initializer",tbl); ! 2960: if (x) { ! 2961: nn->n_initializer = n_initializer = init = x; ! 2962: goto stgg; ! 2963: } ! 2964: } ! 2965: //error('d',"check %t %t %k",nt,init->tp,init->base); ! 2966: // if (nt->check(init->tp,ASSIGN)) { ! 2967: Pname c1 = nt->is_cl_obj(); ! 2968: Pname c2 = init->tp->is_cl_obj(); ! 2969: if (c1 ! 2970: && c2 ! 2971: && Pclass(c2->tp)->has_base(Pclass(c1->tp))) { ! 2972: init = new texpr(CAST,new ptr(PTR,nt),init->address()); ! 2973: init = init->typ(tbl); ! 2974: nn->n_initializer = n_initializer = init = init->contents(); ! 2975: goto stgg; ! 2976: } ! 2977: ! 2978: if (nt->check(init->tp,ASSIGN)) { ! 2979: error("badIrT%t for%n (%tX)",init->tp,this,nn->tp); ! 2980: break; ! 2981: } ! 2982: } ! 2983: ! 2984: stgg: ! 2985: // error('d',"stgg %n init %k %t Nvirt: %k",this,init?init->base:0,init?init->tp:0, Nvirt); ! 2986: if (init && n_stclass==STATIC && (sti_vb || need_sti(init))) { ! 2987: /* check if non-static variables are used */ ! 2988: int local = (0<lex_level); ! 2989: // error('d',"init %n %t local %d",nn,init->tp,local); ! 2990: if (local==0) need_sti(init,tbl); // save consts ! 2991: ! 2992: Pptr r = nn->tp->is_ref(); //III ! 2993: ! 2994: if (r) init = init->address(); ! 2995: init = new expr(ASSIGN,nn,init); ! 2996: // error('d',"init r %t: nn %n %t init %t",r,nn,nn->tp,init->tp); ! 2997: if (r) ! 2998: init->tp = nn->tp; ! 2999: else if (nn->tp!=init->tp) { // static member refs ! 3000: TOK t = nn->tp->set_const(0); //JJJ ! 3001: init = init->typ(tbl); ! 3002: nn->tp->set_const(t); //JJJ ! 3003: } ! 3004: ! 3005: if (local) { ! 3006: if (init->base != ASSIGN) error('s',"Ir for local static too complicated"); ! 3007: if (nn->n_sto == EXTERN) { ! 3008: error(&where,"Id local extern%n",this); ! 3009: init = 0; ! 3010: } ! 3011: else init->base = STAT_INIT; ! 3012: nn->n_initializer = n_initializer = init; ! 3013: ! 3014: } ! 3015: else { ! 3016: Pstmt ist = new estmt(SM,nn->where,init,0); ! 3017: // constructors for statics are executed in order ! 3018: ! 3019: if (st_ilist == 0) ! 3020: st_ilist = ist; ! 3021: else ! 3022: itail->s_list = ist; ! 3023: itail = ist; ! 3024: nn->n_initializer = n_initializer = init = 0; // suppress further processing ! 3025: nn->n_val = n_val = 1; ! 3026: } ! 3027: } ! 3028: ! 3029: ! 3030: } /* switch */ ! 3031: } /* block */ ! 3032: } /* default */ ! 3033: ! 3034: } /* switch */ ! 3035: ggg: ! 3036: //error('d',"ggg"); ! 3037: PERM(nn); ! 3038: switch (n_scope) { ! 3039: case FCT: ! 3040: nn->n_initializer = n_initializer; ! 3041: break; ! 3042: default: ! 3043: { Ptype t = nn->tp; ! 3044: px: ! 3045: PERM(t); ! 3046: switch (t->base) { ! 3047: case PTR: ! 3048: case RPTR: ! 3049: case VEC: t = Pptr(t)->typ; goto px; ! 3050: case TYPE: t = Pbase(t)->b_name->tp; goto px; ! 3051: case FCT: t = Pfct(t)->returns; goto px; /* args? */ ! 3052: } ! 3053: } ! 3054: } ! 3055: ! 3056: Cdcl = odcl; ! 3057: return nn; ! 3058: } ! 3059: 0707071010112043671004440001630000160000010172100466055375400000700000067044dcl2.c /*ident "@(#)ctrans:src/dcl2.c 1.2" */ ! 3060: /************************************************************************** ! 3061: ! 3062: C++ source for cfront, the C++ compiler front-end ! 3063: written in the computer science research center of Bell Labs ! 3064: ! 3065: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 3066: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 3067: ! 3068: dcl2.c: ! 3069: ! 3070: *************************************************************************/ ! 3071: ! 3072: #include "cfront.h" ! 3073: #include "size.h" ! 3074: ! 3075: Pname conv_dominates(Pname on1, Pname on2) ! 3076: /* ! 3077: compare for duplicates and dominance: ! 3078: ! 3079: on1 and on2 are two conversion operator functions ! 3080: return the the one that dominates the other (according to the ! 3081: class hierarchy) otherwise 0 (0 thus indicats ambiguous conversion) ! 3082: */ ! 3083: { ! 3084: Ptype r1 = on1->tp->base==FCT ? Pfct(on1->tp)->returns ! 3085: : Pfct(Pgen(on1->tp)->fct_list->f->tp)->returns; ! 3086: Ptype r2 = on2->tp->base==FCT ? Pfct(on2->tp)->returns ! 3087: : Pfct(Pgen(on2->tp)->fct_list->f->tp)->returns; ! 3088: //error('d',"conv_dominates(%n,%n)",on1,on2); ! 3089: if (r1==r2 || r1->check(r2,0)==0) return on1; ! 3090: Pptr p1 = r1->is_ptr_or_ref(); ! 3091: Pptr p2 = r2->is_ptr_or_ref(); ! 3092: if (p1 && p2) { ! 3093: Pname cn1 = p1->typ->is_cl_obj(); ! 3094: Pname cn2 = p2->typ->is_cl_obj(); ! 3095: if (cn1 && cn2) { ! 3096: // is_cl_obj() returns b_name ! 3097: // Pclass c1 = Pclass(Pbase(cn1->tp)->b_name->tp); ! 3098: // Pclass c2 = Pclass(Pbase(cn2->tp)->b_name->tp); ! 3099: Pclass c1 = Pclass(cn1->tp); ! 3100: Pclass c2 = Pclass(cn2->tp); ! 3101: if (c1 && c2) { ! 3102: //if (c1==c2 || c1->has_base(c2)) ! 3103: if (c1->has_base(c2)) ! 3104: return on1; ! 3105: else if (c2->has_base(c1)) ! 3106: return on2; ! 3107: } ! 3108: } ! 3109: } ! 3110: return 0; ! 3111: } ! 3112: ! 3113: ! 3114: Pstmt curr_loop; ! 3115: Pstmt curr_switch; ! 3116: Pblock curr_block; ! 3117: ! 3118: void stmt::reached() ! 3119: { ! 3120: register Pstmt ss = s_list; ! 3121: ! 3122: if (ss == 0) return; ! 3123: ! 3124: switch (ss->base) { ! 3125: case LABEL: ! 3126: case CASE: ! 3127: case DEFAULT: ! 3128: break; ! 3129: default: ! 3130: error('w',&ss->where,"S after%k not reached",base); ! 3131: for (; ss; ss=ss->s_list) { // delete unreacheable code ! 3132: switch (ss->base) { ! 3133: case LABEL: ! 3134: case CASE: ! 3135: case DEFAULT: // reachable ! 3136: s_list = ss; ! 3137: return; ! 3138: case DCL: // the dcl may be used later ! 3139: // keep to avoid cascading errors ! 3140: case IF: ! 3141: case DO: ! 3142: case WHILE: ! 3143: case SWITCH: ! 3144: case FOR: ! 3145: case BLOCK: // may hide a label ! 3146: s_list = ss; ! 3147: return; ! 3148: } ! 3149: } ! 3150: s_list = 0; ! 3151: } ! 3152: } ! 3153: ! 3154: Pexpr check_cond(Pexpr e, TOK b, Ptable tbl) ! 3155: { ! 3156: //error('d',"check_cond(%k %k) tbl %d",e->base,b,tbl); ! 3157: Pname cn; ! 3158: if (e == dummy) error("empty condition for %k",b); ! 3159: ! 3160: int const_obj = 0; ! 3161: const_obj = e->tp->tconst(); ! 3162: Pexpr ee = e; ! 3163: while (ee && (ee->base==DOT || ee->base==REF)) { ! 3164: Pexpr m = ee->mem; ! 3165: if ( ee->base==REF && m->tp && m->tp->is_ptr()) ! 3166: break; ! 3167: ee = ee->e1; ! 3168: } ! 3169: if (ee) { ! 3170: Ptype ttt = ee->tp; ! 3171: switch (e->base) { ! 3172: case REF: ! 3173: Pptr p = ttt?ttt->is_ptr():0; ! 3174: if (p && p->typ->tconst()) ! 3175: const_obj = 1; ! 3176: break; ! 3177: case DOT: ! 3178: if (ttt && ttt->tconst()) ! 3179: const_obj = 1; ! 3180: } ! 3181: } ! 3182: ! 3183: if (cn = e->tp->is_cl_obj()) { ! 3184: Pclass cl = Pclass(cn->tp); ! 3185: int i = 0; ! 3186: Pname found = 0; ! 3187: for (Pname on = cl->conv; on; on=on->n_list) { ! 3188: Pfct f = on->tp->base == FCT ? Pfct(on->tp) ! 3189: : Pfct(Pgen(on->tp)->fct_list->f->tp); ! 3190: Ptype t = f->returns; ! 3191: xx: ! 3192: switch (t->base) { ! 3193: case TYPE: ! 3194: t = Pbase(t)->b_name->tp; ! 3195: goto xx; ! 3196: case FLOAT: ! 3197: case DOUBLE: ! 3198: case LDOUBLE: ! 3199: case PTR: ! 3200: if (b == DEREF) break; ! 3201: case CHAR: ! 3202: case SHORT: ! 3203: case INT: ! 3204: case LONG: ! 3205: case EOBJ: ! 3206: // if (found==0 || found->tp->check(on->tp,0)) { ! 3207: //error('d',"found %n on %n",found,on); ! 3208: { Pname xx = found; ! 3209: if (found == 0) { ! 3210: i = 1; ! 3211: found = on; ! 3212: } ! 3213: else if ((found = really_dominate(found,on,const_obj)) == 0) { ! 3214: i = 2; ! 3215: found = on; ! 3216: error("two conversions for%nO in%kE: %n and %n",cn,b,xx,on); ! 3217: return e; ! 3218: } ! 3219: } ! 3220: } ! 3221: } ! 3222: //error('d',"i %d",i); ! 3223: switch (i) { ! 3224: case 0: ! 3225: error("%nO in%kE",cn,b); ! 3226: return e; ! 3227: /* ! 3228: case 1: ! 3229: { Pname xx = new name(found->string); ! 3230: Pref r = new ref(DOT,e,xx); ! 3231: Pexpr rr = r->typ(tbl); ! 3232: Pexpr c = new expr(G_CALL,rr,0); ! 3233: ! 3234: if (e->lval(0)) { ! 3235: // Pref r = new ref(DOT,e,found); ! 3236: // r->tp = found->tp; ! 3237: // Pexpr c = new expr(G_CALL,r,0); ! 3238: // c->fct_name = found; ! 3239: return c->typ(tbl); ! 3240: } ! 3241: else { // (temp=init,temp.coerce()) ! 3242: Pname tmp = make_tmp('U',e->tp,tbl); ! 3243: Pexpr ass = init_tmp(tmp,e,tbl); ! 3244: // Pref r = new ref(DOT,tmp,found); ! 3245: // Pexpr rr = r->typ(tbl); ! 3246: // Pexpr c = new expr(G_CALL,rr,0); ! 3247: // c->fct_name = found; ! 3248: ass = new expr(CM,ass,c); ! 3249: return ass->typ(tbl); ! 3250: } ! 3251: } ! 3252: */ ! 3253: case 1: ! 3254: { Pname xx = new name(found->string); ! 3255: Pexpr c; ! 3256: ! 3257: if (e->lval(0)) { ! 3258: Pref r = new ref(DOT,e,xx); ! 3259: Pexpr rr = r->typ(tbl); ! 3260: c = new expr(G_CALL,rr,0); ! 3261: } ! 3262: else { // (temp=init,temp.coerce()) ! 3263: Pname tmp = make_tmp('U',e->tp,tbl); ! 3264: Pexpr ass = init_tmp(tmp,e,tbl); ! 3265: Pref r = new ref(DOT,tmp,xx); ! 3266: Pexpr rr = r->typ(tbl); ! 3267: c = new expr(G_CALL,rr,0); ! 3268: c = new expr(CM,ass,c); ! 3269: } ! 3270: return c->typ(tbl); ! 3271: } ! 3272: // default: ! 3273: // error("%d possible conversions for%nO in%kE",i,cn,b); ! 3274: // return e; ! 3275: } ! 3276: ! 3277: } ! 3278: if (e->tp->memptr()) { ! 3279: e = new mdot("i",e); ! 3280: e->i1 = 9; ! 3281: e = new expr(NE,e,zero); ! 3282: } ! 3283: else if (e->tp->num_ptr(b) == FCT) ! 3284: error("%k(F)",b); ! 3285: return e; ! 3286: } ! 3287: ! 3288: void stmt::dcl() ! 3289: /* ! 3290: typecheck statement "this" in scope "curr_block->tbl" ! 3291: */ ! 3292: { ! 3293: Pstmt ss; ! 3294: Pname n; ! 3295: Pname nn; ! 3296: Pstmt ostmt = Cstmt; ! 3297: DB( if(Ddebug>=1) error('d',&where,"'%k'->stmt::dcl()",base); ); ! 3298: for (ss=this; ss; ss=ss->s_list) { ! 3299: Pstmt old_loop, old_switch; ! 3300: Cstmt = ss; ! 3301: enum_promote = 0; ! 3302: Ptable tbl = curr_block->memtbl; ! 3303: //error('d',"stmt::dcl %k",ss->base); ! 3304: switch (ss->base) { ! 3305: case BREAK: ! 3306: inline_restr |= 16; ! 3307: if (curr_loop==0 && curr_switch==0) ! 3308: error("break not in loop or switch"); ! 3309: ss->reached(); ! 3310: break; ! 3311: ! 3312: case CONTINUE: ! 3313: inline_restr |= 32; ! 3314: if (curr_loop == 0) error("continue not in loop"); ! 3315: ss->reached(); ! 3316: break; ! 3317: ! 3318: case DEFAULT: ! 3319: if (curr_switch == 0) { ! 3320: error("default not in switch"); ! 3321: break; ! 3322: } ! 3323: if (curr_switch->has_default) error("two defaults in switch"); ! 3324: curr_switch->has_default = ss; ! 3325: ss->s->s_list = ss->s_list; ! 3326: ss->s_list = 0; ! 3327: ss->s->dcl(); ! 3328: break; ! 3329: ! 3330: case SM: ! 3331: { if (ss->e ==0) break; ! 3332: TOK b = ss->e->base; ! 3333: switch (b) { ! 3334: case DUMMY: ! 3335: ss->e = 0; ! 3336: break; ! 3337: // check for unused results ! 3338: // don't check operators that are likely ! 3339: // to be overloaded to represent "actions": ! 3340: // ! ~ < <= > >= << >> ! 3341: case EQ: ! 3342: case NE: ! 3343: case PLUS: ! 3344: case MINUS: ! 3345: case REF: ! 3346: case DOT: ! 3347: case MUL: ! 3348: case DIV: ! 3349: case ADDROF: ! 3350: case AND: ! 3351: case OR: ! 3352: case ER: ! 3353: case DEREF: ! 3354: case ANDAND: ! 3355: case OROR: ! 3356: case NAME: ! 3357: case VALUE: ! 3358: if (ss->e->tp) break; // avoid looking at generated code ! 3359: ss->e = ss->e->typ(tbl); ! 3360: if (ss->e->base == CALL) break; ! 3361: if (ss->e->tp->base != VOID) { ! 3362: if ( ss->e->base == DEREF ) ! 3363: error('w',"result of %sE not used",ss->e->e2?"[]":"*"); ! 3364: else ! 3365: error('w',"result of%kE not used",b); ! 3366: if (ss->e->not_simple()==0) ss->e = dummy; ! 3367: } ! 3368: break; ! 3369: default: ! 3370: ss->e = ss->e->typ(tbl); ! 3371: } ! 3372: break; ! 3373: } ! 3374: case RETURN: ! 3375: { Pname fn = cc->nof; ! 3376: Pfct f = Pfct(fn->tp); ! 3377: Ptype rt = f->returns; ! 3378: Pexpr v = ss->e; ! 3379: //error('d',"rt %t",rt); ! 3380: while (rt->base == TYPE) rt = Pbase(rt)->b_name->tp; ! 3381: if (v != dummy) { ! 3382: if (rt->base == RPTR || rt->base == PTR) { ! 3383: const_ptr = Pbase(Pptr(rt)->typ)->tconst(); ! 3384: } ! 3385: if (rt->base == RPTR) { ! 3386: ref_initializer++; ! 3387: v = v->typ(tbl); ! 3388: ref_initializer--; ! 3389: } else ! 3390: v = v->typ(tbl); ! 3391: const_ptr = 0; ! 3392: ! 3393: if (fn->n_oper==CTOR ! 3394: || fn->n_oper==DTOR ! 3395: || (rt->base==VOID && v->tp!=void_type)) { ! 3396: error("unexpected return value"); ! 3397: // refuse to return the value: ! 3398: ss->e = dummy; ! 3399: } ! 3400: else { ! 3401: switch (rt->base) { ! 3402: // case TYPE: laready done above ! 3403: case RPTR: ! 3404: switch (v->base) { ! 3405: case NAME: ! 3406: if (Pname(v)->n_scope==FCT ! 3407: || Pname(v)->n_scope==ARG) ! 3408: error('w',"R to localV returned"); ! 3409: break; ! 3410: case ICON: ! 3411: case CCON: ! 3412: case FCON: ! 3413: case STRING: ! 3414: if (Pptr(rt)->typ->tconst()==0) ! 3415: error('w',"R to literal returned"); ! 3416: } ! 3417: v = ref_init(Pptr(rt),v,tbl); ! 3418: if (v->base==G_CM ! 3419: && v->e2->base==G_ADDROF ! 3420: && v->e2->e2->base==NAME) ! 3421: error('w',"R to temporary returned (return value is not lvalue or of wrongT)"); ! 3422: case ANY: ! 3423: break; ! 3424: case COBJ: ! 3425: if (v->base == DEREF) { ! 3426: Pexpr v1 = v->e1; ! 3427: if (v1->base==CAST) { ! 3428: Pexpr v2 = v1->e1; ! 3429: if (v2->base == G_CM) { // *(T)(e1,e2) => (e1,*(T)e2) ! 3430: Pexpr v3 = v2->e2; ! 3431: v2->e2 = v; ! 3432: v2->tp = v->tp; ! 3433: v = v2; ! 3434: v1->e1 = v3; ! 3435: } ! 3436: } ! 3437: } ! 3438: if (f->f_result) { ! 3439: if (v->base==G_CM && rt->check(v->tp,0/*ASSIGN*/)==0) ! 3440: v = replace_temp(v,f->f_result); ! 3441: else { ! 3442: v = class_init(f->f_result->contents(),rt,v,tbl); ! 3443: Pname rcn = rt->is_cl_obj(); ! 3444: if (Pclass(rcn->tp)->has_itor()==0) { ! 3445: // can happen for virtuals and for user defined conversions ! 3446: v->tp = rt; ! 3447: v = new expr(ASSIGN,f->f_result->contents(),v); ! 3448: v->tp = rt; ! 3449: } ! 3450: } ! 3451: } ! 3452: else ! 3453: v = class_init(0,rt,v,tbl); ! 3454: break; ! 3455: case PTR: ! 3456: { Pexpr x = v; ! 3457: v = ptr_init(Pptr(rt),v,tbl); ! 3458: if (v->base == ADDROF ! 3459: && v->e2->base == NAME ! 3460: && Pname(v->e2)->n_stclass == AUTO) ! 3461: error('w',"P to local variable%n returned",Pname(v->e2)); ! 3462: // if (v==x ||v->e2==x) goto def; ! 3463: if (Pchecked == 0) goto def; ! 3464: goto ret_save; ! 3465: // break; ! 3466: } ! 3467: case INT: ! 3468: case CHAR: ! 3469: case LONG: ! 3470: case SHORT: ! 3471: if (Pbase(rt)->b_unsigned ! 3472: && v->base==UMINUS ! 3473: && v->e2->base==ICON) ! 3474: error('w',"negative returned fromF returning unsigned"); ! 3475: default: ! 3476: def: ! 3477: { ! 3478: Pexpr x = try_to_coerce(rt,v,"return value",tbl); ! 3479: if (x) ! 3480: v = x; ! 3481: else if (rt->check(v->tp,ASSIGN)) ! 3482: error("bad return valueT for%n:%t (%tX)",fn,v->tp,rt); ! 3483: } ! 3484: ! 3485: } ! 3486: ret_save: ! 3487: ss->ret_tp = rt; ! 3488: ss->e = v; ! 3489: } ! 3490: } ! 3491: else { ! 3492: if (rt->base != VOID) error("return valueX"); ! 3493: } ! 3494: ss->reached(); ! 3495: break; ! 3496: } ! 3497: ! 3498: case DO: // in DO the stmt is before the test ! 3499: inline_restr |= 8; ! 3500: old_loop = curr_loop; ! 3501: curr_loop = ss; ! 3502: { Pstmt st = ss->s; ! 3503: while(st && st->base == FOR) st = st->for_init; ! 3504: if (st && st->base == DCL) ! 3505: if (st==ss->s) error("D as onlyS in do-loop"); ! 3506: } ! 3507: ss->s->dcl(); ! 3508: ss->e = ss->e->typ(tbl); ! 3509: ss->e = check_cond(ss->e,DO,tbl); ! 3510: curr_loop = old_loop; ! 3511: break; ! 3512: ! 3513: case WHILE: ! 3514: inline_restr |= 8; ! 3515: old_loop = curr_loop; ! 3516: curr_loop = ss; ! 3517: ss->e = ss->e->typ(tbl); ! 3518: ss->e = check_cond(ss->e,WHILE,tbl); ! 3519: { Pstmt st = ss->s; ! 3520: while(st && st->base == FOR) st = st->for_init; ! 3521: if (st && st->base == DCL) ! 3522: if(st==ss->s) error("D as onlyS in while-loop"); ! 3523: } ! 3524: ss->s->dcl(); ! 3525: curr_loop = old_loop; ! 3526: break; ! 3527: ! 3528: case SWITCH: ! 3529: { int ne = 0; ! 3530: inline_restr |= 4; ! 3531: old_switch = curr_switch; ! 3532: curr_switch = ss; ! 3533: ss->e = ss->e->typ(tbl); ! 3534: ss->e = check_cond(ss->e,SWITCH,tbl); ! 3535: { Pstmt st = ss->s; ! 3536: while(st && st->base == FOR) st = st->for_init; ! 3537: if (st && st->base == DCL) ! 3538: if(st==ss->s) error("D as onlyS in switchS"); ! 3539: } ! 3540: { Ptype tt = ss->e->tp; ! 3541: sii: ! 3542: switch (tt->base) { ! 3543: case TYPE: ! 3544: tt = Pbase(tt)->b_name->tp; goto sii; ! 3545: case EOBJ: ! 3546: ne = Penum(Pbase(tt)->b_name->tp)->no_of_enumerators; ! 3547: case ZTYPE: ! 3548: case ANY: ! 3549: case CHAR: ! 3550: case SHORT: ! 3551: case INT: ! 3552: case LONG: ! 3553: case FIELD: ! 3554: break; ! 3555: default: ! 3556: error("%t switchE",ss->e->tp); ! 3557: } ! 3558: } ! 3559: ss->s->dcl(); ! 3560: if (ne) { /* see if the number of cases is "close to" ! 3561: but not equal to the number of enumerators ! 3562: */ ! 3563: int i = 0; ! 3564: Pstmt cs; ! 3565: for (cs=ss->case_list; cs; cs=cs->case_list) i++; ! 3566: if (i && i!=ne) { ! 3567: if (ne < i) { ! 3568: ee: error('w',"switch (%t)W %d cases (%d enumerators)",ss->e->tp,i,ne); ! 3569: } ! 3570: else { ! 3571: switch (ne-i) { ! 3572: case 1: if (3<ne) goto ee; ! 3573: case 2: if (7<ne) goto ee; ! 3574: case 3: if (23<ne) goto ee; ! 3575: case 4: if (60<ne) goto ee; ! 3576: case 5: if (99<ne) goto ee; ! 3577: } ! 3578: } ! 3579: } ! 3580: } ! 3581: curr_switch = old_switch; ! 3582: break; ! 3583: } ! 3584: case CASE: ! 3585: if (curr_switch == 0) { ! 3586: error("case not in switch"); ! 3587: break; ! 3588: } ! 3589: ss->e = ss->e->typ(tbl); ! 3590: ss->e->tp->num_ptr(CASE); ! 3591: { Ptype tt = ss->e->tp; ! 3592: iii: ! 3593: switch (tt->base) { ! 3594: case TYPE: ! 3595: tt = Pbase(tt)->b_name->tp; goto iii; ! 3596: case ZTYPE: ! 3597: case ANY: ! 3598: case CHAR: ! 3599: case SHORT: ! 3600: case INT: ! 3601: case LONG: ! 3602: case EOBJ: ! 3603: Neval = 0; ! 3604: long i = ss->e->eval(); ! 3605: if (Neval == 0) { ! 3606: Pstmt cs; ! 3607: if (largest_int<i) error("long case value"); ! 3608: for (cs=curr_switch->case_list; cs; cs=cs->case_list) { ! 3609: if (cs->case_value == i) error("case %d used twice in switch",i); ! 3610: } ! 3611: ss->case_value = int(i); ! 3612: ss->case_list = curr_switch->case_list; ! 3613: curr_switch->case_list = ss; ! 3614: } ! 3615: else ! 3616: error("bad case label: %s",Neval); ! 3617: break; ! 3618: default: ! 3619: error("%t caseE",ss->e->tp); ! 3620: } ! 3621: } ! 3622: // if (1) { ! 3623: // Neval = 0; ! 3624: // long i = ss->e->eval(); ! 3625: // if (Neval == 0) { ! 3626: // Pstmt cs; ! 3627: // if (largest_int<i) error("long case value"); ! 3628: // for (cs=curr_switch->case_list; cs; cs=cs->case_list) { ! 3629: // if (cs->case_value == i) error("case %d used twice in switch",i); ! 3630: // } ! 3631: // ss->case_value = int(i); ! 3632: // ss->case_list = curr_switch->case_list; ! 3633: // curr_switch->case_list = ss; ! 3634: // } ! 3635: // else ! 3636: // error("bad case label: %s",Neval); ! 3637: // } ! 3638: if (ss->s->s_list) error('i',"case%k",ss->s->s_list->base); ! 3639: ss->s->s_list = ss->s_list; ! 3640: ss->s_list = 0; ! 3641: ss->s->dcl(); ! 3642: break; ! 3643: ! 3644: case GOTO: ! 3645: inline_restr |= 2; ! 3646: ss->reached(); ! 3647: case LABEL: ! 3648: /* Insert label in function mem table; ! 3649: labels have function scope. ! 3650: */ ! 3651: n = ss->d; ! 3652: nn = cc->ftbl->insert(n,LABEL); ! 3653: ! 3654: /* Set a ptr to the mem table corresponding to the scope ! 3655: in which the label actually occurred. This allows the ! 3656: processing of goto's in the presence of ctors and dtors ! 3657: */ ! 3658: if (ss->base == LABEL) { ! 3659: nn->n_realscope = curr_block->memtbl; ! 3660: inline_restr |= 1; ! 3661: } ! 3662: ! 3663: if (Nold) { ! 3664: if (ss->base == LABEL) { ! 3665: if (nn->n_initializer) error("twoDs of label%n",n); ! 3666: nn->n_initializer = (Pexpr)1; ! 3667: } ! 3668: if (n != nn) ss->d = nn; ! 3669: } ! 3670: else { ! 3671: if (ss->base == LABEL) nn->n_initializer = (Pexpr)1; ! 3672: nn->where = ss->where; ! 3673: } ! 3674: if (ss->base == GOTO) ! 3675: nn->use(); ! 3676: else { ! 3677: if (ss->s->s_list) error('i',"label%k",ss->s->s_list->base); ! 3678: ss->s->s_list = ss->s_list; ! 3679: ss->s_list = 0; ! 3680: nn->assign(); ! 3681: } ! 3682: if (ss->s) ss->s->dcl(); ! 3683: break; ! 3684: ! 3685: case IF: ! 3686: { ! 3687: Pexpr ee = ss->e->typ(tbl); ! 3688: if (ee->base == ASSIGN) { ! 3689: Neval = 0; ! 3690: (void)ee->e2->eval(); ! 3691: if (Neval == 0) ! 3692: error('w',"constant assignment in condition"); ! 3693: } ! 3694: ss->e = ee = check_cond(ee,IF,tbl); ! 3695: ! 3696: if (ss->s->base == DCL) error("D as onlyS after `if'"); ! 3697: ! 3698: // pointer to member returns with a tp set to 0 ! 3699: if ( ee->tp ) switch (ee->tp->base) { ! 3700: case INT: ! 3701: case EOBJ: ! 3702: case ZTYPE: ! 3703: { long i; ! 3704: Neval = 0; ! 3705: i = ee->eval(); ! 3706: ! 3707: if (Neval == 0) { ! 3708: Pstmt sl = ss->s_list; ! 3709: if (i) { ! 3710: DEL(ss->else_stmt); ! 3711: ss->s->dcl(); ! 3712: *ss = *ss->s; ! 3713: } ! 3714: else { ! 3715: DEL(ss->s); ! 3716: if (ss->else_stmt) { ! 3717: ss->else_stmt->dcl(); ! 3718: *ss = *ss->else_stmt; ! 3719: } ! 3720: else { ! 3721: ss->base = SM; ! 3722: ss->e = dummy; ! 3723: ss->s = 0; ! 3724: } ! 3725: } ! 3726: ss->s_list = sl; ! 3727: continue; ! 3728: } ! 3729: } ! 3730: } ! 3731: ss->s->dcl(); ! 3732: if (ss->else_stmt) { ! 3733: if (ss->else_stmt->base == DCL) error("D as onlyS after `else'"); ! 3734: ss->else_stmt->dcl(); ! 3735: } ! 3736: break; ! 3737: } ! 3738: case FOR: ! 3739: inline_restr |= 8; ! 3740: old_loop = curr_loop; ! 3741: curr_loop = ss; ! 3742: if (ss->for_init) { ! 3743: Pstmt fi = ss->for_init; ! 3744: switch (fi->base) { ! 3745: case SM: ! 3746: if (fi->e == dummy) { ! 3747: ss->for_init = 0; ! 3748: break; ! 3749: } ! 3750: fi->dcl(); ! 3751: break; ! 3752: default: ! 3753: // for (stmt; e1; e2) stmt1 stmt2 ! 3754: // => {stmt; for(; e1; e2) stmt1 stmt2} ! 3755: // if stmt != declaration ! 3756: // if stmt == declaration, temporarily ! 3757: // rewrite to avoid symbol table ! 3758: // problems in some contexts. ! 3759: // Then put decl back to avoid ! 3760: // extraneous {}. ! 3761: // Note: to maintain pointers, ss ! 3762: // must not change ! 3763: { Pstmt tmp = new stmt (SM,curloc,0); ! 3764: *tmp = *ss; // tmp = original for ! 3765: tmp->for_init = 0; ! 3766: fi->s_list = tmp; ! 3767: *ss = *fi; ! 3768: curr_loop = old_loop; ! 3769: ss->dcl(); ! 3770: tmp = ss->s_list; ! 3771: if ( ss->base == DCL ! 3772: && tmp->base == FOR // sanity check ! 3773: && tmp->for_init == 0 // sanity check ! 3774: ) { ! 3775: // put DCL back in for init ! 3776: *fi = *ss; ! 3777: *ss = *tmp; ! 3778: ss->for_init = fi; ! 3779: fi->s_list = 0; ! 3780: } else { ! 3781: // non-decl stmt in for init ! 3782: // put stmts in block in case ! 3783: // they follow a condition... ! 3784: // allocate tmp to be sure ! 3785: // fields are initialized ! 3786: *fi = *ss; ! 3787: tmp = new block(ss->where,0,fi); ! 3788: tmp->own_tbl = 0; ! 3789: tmp->memtbl = curr_block->memtbl; ! 3790: tmp->permanent = ss->permanent; ! 3791: *ss = *tmp; ! 3792: tmp->permanent = 0; delete tmp; ! 3793: } ! 3794: // don't repeat stmt::dcl() for ! 3795: // remaining stmts ! 3796: goto done; ! 3797: } ! 3798: } ! 3799: } ! 3800: if (ss->e == dummy) ! 3801: ss->e = 0; ! 3802: else { ! 3803: ss->e = ss->e->typ(tbl); ! 3804: ss->e = check_cond(ss->e,FOR,tbl); ! 3805: } ! 3806: { Pstmt st = ss->s; ! 3807: while(st && st->base == FOR) st = st->for_init; ! 3808: if (st && st->base == DCL) ! 3809: if(st==ss->s) error("D as onlyS in for-loop"); ! 3810: } ! 3811: ss->s->dcl(); ! 3812: ss->e2 = (ss->e2 == dummy) ? 0 : ss->e2->typ(tbl); ! 3813: curr_loop = old_loop; ! 3814: break; ! 3815: ! 3816: case DCL: /* declaration after statement */ ! 3817: { ! 3818: /* collect all the contiguous DCL nodes from the ! 3819: head of the s_list. find the next statement ! 3820: */ ! 3821: int non_trivial = 0; ! 3822: int count = 0; ! 3823: Pname tail = ss->d; ! 3824: for (Pname nn=tail; nn; nn=nn->n_list) { ! 3825: // find tail; ! 3826: // detect non-trivial declarations ! 3827: count++; ! 3828: ! 3829: if (nn->n_list) tail = nn->n_list; ! 3830: Pname n = tbl->look(nn->string,0); ! 3831: ! 3832: if (n && n->n_table==tbl) non_trivial = 2; ! 3833: if (non_trivial == 2) continue; ! 3834: if ((nn->n_sto==STATIC && nn->tp->base!=FCT) ! 3835: || nn->tp->is_ref() ! 3836: || (nn->tp->tconst() && fct_const==0)) { ! 3837: non_trivial = 2; ! 3838: continue; ! 3839: } ! 3840: ! 3841: Pexpr in = nn->n_initializer; ! 3842: if (in) ! 3843: switch (in->base) { ! 3844: case ILIST: ! 3845: case STRING: ! 3846: non_trivial = 2; ! 3847: continue; ! 3848: } ! 3849: non_trivial = 1; ! 3850: Pname cln = nn->tp->is_cl_obj(); ! 3851: if (cln == 0) cln = cl_obj_vec; ! 3852: if (cln == 0) continue; ! 3853: if (Pclass(cln->tp)->has_ctor()) { ! 3854: non_trivial = 2; ! 3855: continue; ! 3856: } ! 3857: if (Pclass(cln->tp)->has_dtor()) non_trivial = 2; ! 3858: } ! 3859: ! 3860: while( ss->s_list && ss->s_list->base==DCL ) { ! 3861: Pstmt sx = ss->s_list; ! 3862: tail = tail->n_list = sx->d; // add to tail ! 3863: for (nn=sx->d; nn; nn=nn->n_list) { ! 3864: // find tail; ! 3865: // detect non-trivial declarations ! 3866: count++; ! 3867: if (nn->n_list) tail = nn->n_list; ! 3868: Pname n = tbl->look(nn->string,0); ! 3869: if (n && n->n_table==tbl) non_trivial = 2; ! 3870: if (non_trivial == 2) continue; ! 3871: if ((nn->n_sto==STATIC && nn->tp->base!=FCT) ! 3872: || nn->tp->is_ref() ! 3873: || (nn->tp->tconst() && fct_const==0)) { ! 3874: non_trivial = 2; ! 3875: continue; ! 3876: } ! 3877: Pexpr in = nn->n_initializer; ! 3878: if (in) ! 3879: switch (in->base) { ! 3880: case ILIST: ! 3881: case STRING: ! 3882: non_trivial = 2; ! 3883: continue; ! 3884: } ! 3885: non_trivial = 1; ! 3886: Pname cln = nn->tp->is_cl_obj(); ! 3887: if (cln == 0) cln = cl_obj_vec; ! 3888: if (cln == 0) continue; ! 3889: if (Pclass(cln->tp)->has_ctor()) { ! 3890: non_trivial = 2; ! 3891: continue; ! 3892: } ! 3893: if (Pclass(cln->tp)->has_dtor()) non_trivial = 2; ! 3894: } ! 3895: ss->s_list = sx->s_list; ! 3896: /* delete sx; */ ! 3897: } ! 3898: ! 3899: Pstmt next_st = ss->s_list; ! 3900: //error('d',"dcl stmt : d %n non_trivial %d curr own_tbl %d inline_restr 0%o",ss->d,non_trivial,curr_block->own_tbl,inline_restr); ! 3901: if (non_trivial==2 // must ! 3902: || (non_trivial==1 // might ! 3903: && ( curr_block->own_tbl==0 // why not? ! 3904: || inline_restr&3 /* label seen */) ! 3905: ) ! 3906: ) { ! 3907: if (curr_switch && non_trivial==2) { ! 3908: Pstmt cs = curr_switch->case_list; ! 3909: Pstmt ds = curr_switch->has_default; ! 3910: Pstmt bl; ! 3911: if (cs == 0) ! 3912: bl = ds; ! 3913: else if (ds == 0) ! 3914: bl = cs; ! 3915: else if (cs->where.line<ds->where.line) ! 3916: bl = ds; ! 3917: else ! 3918: bl = cs; ! 3919: ! 3920: if ((bl==0 || bl->s->base!=BLOCK) && curr_switch->s->memtbl==tbl) ! 3921: error('s',"non trivialD in switchS (try enclosing it in a block)"); ! 3922: } ! 3923: ! 3924: /* Create a new block, ! 3925: put all the declarations at the head, ! 3926: and the remainder of the slist as the ! 3927: statement list of the block. ! 3928: */ ! 3929: //ss->base = BLOCK; //DCL ! 3930: ! 3931: /* check that there are no redefinitions ! 3932: since the last "real" (user-written, ! 3933: non-generated) block ! 3934: */ ! 3935: { Pname lastnn = 0; ! 3936: for( nn=ss->d; nn; nn=nn->n_list ) { ! 3937: Pname n; ! 3938: //n=curr_block->memtbl->look(nn->string,0); ! 3939: //error('d',"checking %n lex_level: %d n: %n n->lex_level: %d",nn,nn->lex_level,n,n?n->lex_level:0); ! 3940: //error('d'," own_tbl: %d curr_block: %d n->n_table: %d",curr_block->own_tbl,curr_block,n->n_table); ! 3941: //error('d'," real_block: %d n's real_block: %d",curr_block->memtbl->real_block,n->n_table->real_block); ! 3942: //if( curr_block->own_tbl ! 3943: if ( (n=curr_block->memtbl->look(nn->string,0)) ! 3944: && n->n_table->real_block==curr_block->memtbl->real_block ! 3945: && n->tp->base!=FCT ! 3946: && n->tp->base!=OVERLOAD ! 3947: && nn->lex_level == n->lex_level ) { ! 3948: error("twoDs of%n",n); ! 3949: if (lastnn==0) ss->d=nn->n_list; ! 3950: else lastnn->n_list=nn->n_list; ! 3951: } else lastnn = nn; ! 3952: } // for nn ! 3953: } ! 3954: ! 3955: /* attach the remainder of the s_list ! 3956: as the statement part of the block. ! 3957: */ ! 3958: ss->s = next_st; ! 3959: ss->s_list = 0; ! 3960: ! 3961: /* create the table in advance, ! 3962: in order to set the real_block ! 3963: ptr to that of the enclosing table ! 3964: */ ! 3965: ss->memtbl = new table(count+4,tbl,0); ! 3966: ss->memtbl->real_block = curr_block->memtbl->real_block; ! 3967: Pblock(ss)->dcl(ss->memtbl); ! 3968: } ! 3969: else { /* to reduce the number of symbol tables, ! 3970: do not make a new block, ! 3971: instead insert names in enclosing block, ! 3972: and make the initializers into expression ! 3973: statements. ! 3974: */ ! 3975: Pstmt sss = ss; ! 3976: { Pname lastnn = 0; ! 3977: for( nn=ss->d; nn; nn=nn->n_list ) { ! 3978: Pname n; ! 3979: //error('d',"nn %n",nn); ! 3980: //if( curr_block->own_tbl ! 3981: if ( (n=curr_block->memtbl->look(nn->string,0)) ! 3982: && n->n_table->real_block==curr_block->memtbl->real_block ! 3983: && n->tp->base!=FCT && n->tp->base!=OVERLOAD ! 3984: && nn->lex_level == n->lex_level ) { ! 3985: error("twoDs of%n",n); ! 3986: n = 0; ! 3987: if (lastnn==0) ss->d=nn->n_list; ! 3988: else lastnn->n_list=nn->n_list; ! 3989: } else { ! 3990: n = nn->dcl(tbl,FCT); ! 3991: lastnn=nn; ! 3992: } ! 3993: ! 3994: if (n == 0) { ! 3995: if (ss) { ! 3996: ss->base = SM; ! 3997: ss->e = 0; ! 3998: } ! 3999: continue; ! 4000: } ! 4001: //error('d',"hoisted %n to outer blk",n); ! 4002: ! 4003: Pexpr in = n->n_initializer; ! 4004: n->n_initializer = 0; ! 4005: ! 4006: if (ss) { ! 4007: sss->base = SM; ! 4008: ss = 0; ! 4009: } ! 4010: else ! 4011: sss = sss->s_list = new estmt(SM,sss->where,0,0); ! 4012: if (in) { ! 4013: switch (in->base) { ! 4014: case G_CALL: /* constructor? */ ! 4015: { ! 4016: Pname fn = in->fct_name; ! 4017: if (fn && fn->n_oper==CTOR) break; ! 4018: } ! 4019: default: ! 4020: in = new expr(ASSIGN,n,in); ! 4021: in->tp = n->tp; ! 4022: } ! 4023: // sss->e = in->typ(tbl); ! 4024: sss->e = in; ! 4025: } ! 4026: else ! 4027: sss->e = dummy; ! 4028: } // for nn ! 4029: } ! 4030: ! 4031: ss = sss; ! 4032: ss->s_list = next_st; ! 4033: } ! 4034: break; ! 4035: } ! 4036: ! 4037: case BLOCK: ! 4038: Pblock(ss)->dcl(tbl); ! 4039: break; ! 4040: ! 4041: case ASM: ! 4042: /* save string */ ! 4043: { ! 4044: char* s = (char*)ss->e; ! 4045: int ll = strlen(s); ! 4046: char* s2 = new char[ll+1]; ! 4047: strcpy(s2,s); ! 4048: ss->e = Pexpr(s2); ! 4049: break; ! 4050: } ! 4051: default: ! 4052: error('i',"badS(%p %d)",ss,ss->base); ! 4053: } ! 4054: } ! 4055: done: ! 4056: Cstmt = ostmt; ! 4057: } ! 4058: ! 4059: void block::dcl(Ptable tbl) ! 4060: /* ! 4061: Note: for a block without declarations memtbl denotes the table ! 4062: for the enclosing scope. ! 4063: A function body has its memtbl created by fct::dcl(). ! 4064: */ ! 4065: { ! 4066: int bit_old = bit_offset; ! 4067: int byte_old = byte_offset; ! 4068: int max_old = max_align; ! 4069: Pblock block_old = curr_block; ! 4070: ! 4071: if (base != BLOCK && base != DCL) error('i',"block::dcl(%d)",base); ! 4072: ! 4073: curr_block = this; ! 4074: //error('d',"%d->block::dcl(%d) base %k",this,tbl,base); ! 4075: //error('d'," memtbl %d own_tbl %d d %n s %k",memtbl,own_tbl,d,s?s->base:0); ! 4076: if (d) { ! 4077: own_tbl = 1; ! 4078: base = BLOCK; ! 4079: if (memtbl == 0) { ! 4080: int nmem = d->no_of_names()+4; ! 4081: memtbl = new table(nmem,tbl,0); ! 4082: memtbl->real_block = this; ! 4083: /* this is a "real" block from the ! 4084: source text, and not one created by DCL's ! 4085: inside a block. */ ! 4086: } ! 4087: else ! 4088: if (memtbl != tbl) error('i',"block::dcl(?)"); ! 4089: ! 4090: Pname nx; ! 4091: for (Pname n=d; n; n=nx) { ! 4092: nx = n->n_list; ! 4093: n->dcl(memtbl,FCT); ! 4094: switch (n->tp->base) { ! 4095: case CLASS: ! 4096: case ANON: ! 4097: case ENUM: ! 4098: break; ! 4099: default: ! 4100: delete n; ! 4101: } ! 4102: } ! 4103: } ! 4104: else if ( base == BLOCK ) { ! 4105: own_tbl = 1; ! 4106: if (memtbl == 0) { ! 4107: int nmem = 4; ! 4108: memtbl = new table(nmem,tbl,0); ! 4109: memtbl->real_block = this; ! 4110: /* this is a "real" block from the ! 4111: source text, and not one created by DCL's ! 4112: inside a block. */ ! 4113: } else ! 4114: if (memtbl != tbl) error('i',"block::dcl(?)"); ! 4115: } else { ! 4116: base = BLOCK; ! 4117: memtbl = tbl; ! 4118: } ! 4119: ! 4120: Pname odcl = Cdcl; ! 4121: if (s) s->dcl(); ! 4122: if (own_tbl) { ! 4123: Pname m; ! 4124: int i; ! 4125: for (m=memtbl->get_mem(i=1); m; m=memtbl->get_mem(++i)) { ! 4126: Ptype t = m->tp; ! 4127: ! 4128: if (in_class_dcl) m->lex_level -= 1; ! 4129: ! 4130: if (t == 0) { ! 4131: if (m->n_assigned_to == 0) ! 4132: error("label %sU",m->string); ! 4133: if (m->n_used == 0) ! 4134: error('w',"label %s not used", m->string); ! 4135: continue; ! 4136: } ! 4137: ll: ! 4138: switch (t->base) { ! 4139: case TYPE: t = Pbase(t)->b_name->tp; goto ll; ! 4140: case CLASS: ! 4141: case ANON: ! 4142: case ENUM: ! 4143: case FCT: ! 4144: //case VEC: ! 4145: continue; ! 4146: } ! 4147: ! 4148: if (m->n_addr_taken == 0) { ! 4149: if (m->n_used) { ! 4150: if (m->n_assigned_to) { ! 4151: } ! 4152: else if ( t->base != VEC ) { ! 4153: switch (m->n_scope) { ! 4154: case FCT: ! 4155: Cdcl = m; ! 4156: if (m->string[0] != '_' && m->string[1] != '_' ) ! 4157: error('w',&m->where,"%n used but not set",m); ! 4158: } ! 4159: } ! 4160: } ! 4161: else { ! 4162: if (m->n_assigned_to) { ! 4163: } ! 4164: else if (m->string[0]!='_' || m->string[1]!='_') { ! 4165: switch (m->n_scope) { ! 4166: case ARG: ! 4167: case FCT: ! 4168: Cdcl = m; ! 4169: error('w',&m->where,"%n not used",m); ! 4170: } ! 4171: } ! 4172: } ! 4173: } ! 4174: } ! 4175: } ! 4176: Cdcl = odcl; ! 4177: ! 4178: d = 0; ! 4179: ! 4180: if (bit_offset) byte_offset += SZ_WORD; ! 4181: bit_offset = bit_old; ! 4182: byte_offset = byte_old; ! 4183: curr_block = block_old; ! 4184: } ! 4185: ! 4186: void name::field_align() ! 4187: /* ! 4188: adjust alignment ! 4189: */ ! 4190: { ! 4191: Pbase fld = (Pbase)tp; ! 4192: int nbits = fld->b_bits; ! 4193: ! 4194: int a = (F_SENSITIVE) ? fld->b_fieldtype->align() : SZ_WORD; ! 4195: if (max_align < a) max_align = a; ! 4196: ! 4197: if (nbits == 0) { // force word alignment ! 4198: int b; ! 4199: if (bit_offset) ! 4200: nbits = BI_IN_WORD - bit_offset; ! 4201: else if (b = byte_offset%SZ_WORD) ! 4202: nbits = b * BI_IN_BYTE; ! 4203: // else ! 4204: // nbits = BI_IN_WORD; ! 4205: if (max_align < SZ_WORD) max_align = SZ_WORD; ! 4206: } ! 4207: else if (bit_offset == 0) { // take care of part of word ! 4208: int b = byte_offset%SZ_WORD; ! 4209: if (b) { ! 4210: byte_offset -= b; ! 4211: bit_offset = b*BI_IN_BYTE; ! 4212: } ! 4213: } ! 4214: //error('d',"byteoff %d bitoff %d bits %d",byte_offset,bit_offset,nbits); ! 4215: int x = (bit_offset += nbits); ! 4216: if (BI_IN_WORD < x) { ! 4217: fld->b_offset = 0; ! 4218: byte_offset += SZ_WORD; ! 4219: bit_offset = nbits; ! 4220: } ! 4221: else { ! 4222: fld->b_offset = bit_offset; ! 4223: if (BI_IN_WORD == x) { ! 4224: bit_offset = 0; ! 4225: byte_offset += SZ_WORD; ! 4226: } ! 4227: else ! 4228: bit_offset = x; ! 4229: } ! 4230: n_offset = byte_offset; ! 4231: } ! 4232: 0707071010112043701004440001630000160000010172500466055376100000700000171674dcl3.c /*ident "@(#)ctrans:src/dcl3.c 1.7" */ ! 4233: /************************************************************************** ! 4234: ! 4235: C++ source for cfront, the C++ compiler front-end ! 4236: written in the computer science research center of Bell Labs ! 4237: ! 4238: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 4239: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 4240: ! 4241: dcl3.c: ! 4242: Routines used by ::dcl fucntions: fct::dcl() etc. ! 4243: ! 4244: *****************************************************************************/ ! 4245: ! 4246: #include "cfront.h" ! 4247: #include "size.h" ! 4248: #include "template.h" ! 4249: ! 4250: static void vbase_pointers(Pname fn, Pclass cl) ! 4251: /* ! 4252: insert argument for virtual base pointers (if any) ! 4253: after f_this and before f_argtype ! 4254: */ ! 4255: { ! 4256: //error('d',"vbase_pointers(%n,%t) %d %k",fn,cl,fn->tp,fn->n_oper); ! 4257: Pfct f = Pfct(fn->tp); ! 4258: if (fn->n_oper == CTOR) { ! 4259: Pname d = 0; ! 4260: for (Pbcl b = cl->baselist; b; b=b->next) { ! 4261: if (b->base != VIRTUAL) continue; ! 4262: Pname a = new name(b->bclass->string); ! 4263: a->tp = b->bclass->this_type; ! 4264: a->n_list = d; ! 4265: a->n_table = f->body ? f->body->memtbl : 0; ! 4266: a->where = fn->where; ! 4267: d = a; ! 4268: } ! 4269: ! 4270: if (d) { ! 4271: for (Pname dd =d;;) { ! 4272: if (d->n_list == 0) { ! 4273: d->n_list = f->f_args->n_list; ! 4274: break; ! 4275: } ! 4276: d = d->n_list; ! 4277: } ! 4278: f->f_args->n_list = dd; ! 4279: } ! 4280: } ! 4281: if (fn->n_oper == DTOR) { // add __free argument ! 4282: //error('d',"add __free to %n",fn); ! 4283: Pname fa = new name; ! 4284: fa->tp = int_type; ! 4285: fa->n_scope = ARG; ! 4286: fa->where = fn->where; ! 4287: ! 4288: Pname a = f->f_args; ! 4289: if (a == 0) ! 4290: f->f_args = fa; ! 4291: else { ! 4292: for(;;a = a->n_list) { ! 4293: // error('d',"a %d %t",a,a->tp); ! 4294: if (a->n_list == 0) { ! 4295: a->n_list = fa; ! 4296: break; ! 4297: } ! 4298: } ! 4299: } ! 4300: } ! 4301: } ! 4302: ! 4303: void make_res(Pfct f) ! 4304: /* ! 4305: returns X where X(X&) has been declared ! 4306: add "_result" argument of type X* ! 4307: */ ! 4308: { ! 4309: Pname cl = f->returns->is_cl_obj(); ! 4310: if (cl==0 || Pclass(cl->tp)->has_itor()==0) return; ! 4311: ! 4312: Pname rv = new name("_result"); ! 4313: rv->tp = f->returns->addrof(); ! 4314: rv->n_scope = FCT; // not a ``real'' argument ! 4315: rv->n_used = 1; ! 4316: rv->n_list = f->argtype; ! 4317: if (f->f_this) ! 4318: f->f_this->n_list = rv; ! 4319: else ! 4320: f->f_args = rv; ! 4321: f->f_result = rv; ! 4322: f->s_returns = void_type; ! 4323: } ! 4324: ! 4325: void name::check_oper(Pname cn) ! 4326: /* ! 4327: check declarations of operators, ctors, dtors ! 4328: */ ! 4329: { ! 4330: // error('d', "%n->check_oper( %n ): n_oper: %k", this, cn, n_oper ); ! 4331: switch (n_oper) { ! 4332: case CALL: ! 4333: case DEREF: ! 4334: case REF: ! 4335: if (cn == 0) error("operator%s must be aM",keys[n_oper]); ! 4336: break; ! 4337: case ASPLUS: ! 4338: case ASMINUS: ! 4339: case ASMUL: ! 4340: case ASDIV: ! 4341: case ASMOD: ! 4342: case ASAND: ! 4343: case ASOR: ! 4344: case ASER: ! 4345: case ASLS: ! 4346: case ASRS: ! 4347: if ( warning_opt ) { ! 4348: if ( cn == 0 || Pfct(tp)->f_static ) ! 4349: error('w', "operator%s should be a non-staticMF",keys[n_oper]); ! 4350: } ! 4351: break; ! 4352: case ASSIGN: ! 4353: if (cn == 0) ! 4354: error(strict_opt?0:'w',"non-member operator%k() (anachronism)",n_oper); ! 4355: break; ! 4356: case NOT: /* unary operators only */ ! 4357: case COMPL: ! 4358: // case INCR: ! 4359: // case DECR: ! 4360: Pfct f = Pfct(tp); ! 4361: if (cn && f->argtype) ! 4362: error("%n::%n takes noA",cn, this); ! 4363: else if (f->nargs == 2) ! 4364: error("%n takes 1A only",this); ! 4365: break; ! 4366: case INCR: ! 4367: case DECR: ! 4368: // check for postscript instance ! 4369: f = Pfct(tp); ! 4370: if (cn) { // member ! 4371: if ( f->argtype && f->nargs == 1 ) { ! 4372: Pname n = f->argtype; ! 4373: if ( n->tp->base != INT ) ! 4374: error("%n must takeA ofT int, not %t",this,n->tp); ! 4375: } ! 4376: } ! 4377: else ! 4378: if (f->nargs == 2) { // non-member ! 4379: Pname n = f->argtype->n_list; ! 4380: if ( n->tp->base != INT ) ! 4381: error("%n must takeA ofT int, not %t",this,n->tp); ! 4382: } ! 4383: break; ! 4384: ! 4385: case 0: ! 4386: case TNAME: /* may be a constructor */ ! 4387: if (cn && ((strcmp(cn->string,string)==0) || ! 4388: ((Pclass(cn->tp)->class_base == ! 4389: instantiated_template_class) && ! 4390: (strcmp(string, ! 4391: Ptclass(cn->tp)->unparametrized_tname()->string) == 0)))) ! 4392: { ! 4393: if (tp->base == FCT) { ! 4394: Pfct f = Pfct(tp); ! 4395: if (f->returns!=defa_type) ! 4396: error("%s::%s()W returnT",string,string); ! 4397: f->returns = void_type; ! 4398: string = "__ct"; ! 4399: n_oper = CTOR; ! 4400: } ! 4401: else ! 4402: error('s',"struct%nM%n",cn,cn); ! 4403: } ! 4404: else ! 4405: n_oper = 0; ! 4406: break; ! 4407: case DTOR: /* must be a destructor */ ! 4408: //error('d',"dtor %s",string); ! 4409: if (cn == 0) { ! 4410: n_oper = 0; ! 4411: error("destructor ~%s() not inC",string); ! 4412: } ! 4413: else ! 4414: if ((strcmp(cn->string,string) == 0) || ! 4415: ((Pclass(cn->tp)->class_base == ! 4416: instantiated_template_class) && ! 4417: (strcmp(string, ! 4418: Ptclass(cn->tp)->unparametrized_tname()->string)==0))) ! 4419: { ! 4420: dto: ! 4421: Pfct f = (Pfct)tp; ! 4422: string = "__dt"; ! 4423: if (tp->base != FCT) { ! 4424: error("%s::~%s notF",cn->string,cn->string); ! 4425: tp = new fct(void_type,0,1); ! 4426: } ! 4427: else if (f->returns!=defa_type/* && f->returns!=void_type*/) { ! 4428: if ( f->returns != void_type || ! 4429: f->body != 0 || friend_in_class == 0 ) ! 4430: error("%s::~%s()W returnT",cn->string,cn->string); ! 4431: } ! 4432: ! 4433: if (f->argtype) { ! 4434: error("%s::~%s()WAs",cn->string,cn->string); ! 4435: f->nargs = 0; ! 4436: f->nargs_known = 1; ! 4437: f->argtype = 0; ! 4438: } ! 4439: f->returns = void_type; ! 4440: } ! 4441: else { ! 4442: if (strcmp(string,"__dt") == 0) goto dto; ! 4443: error("~%s in %s",string,cn->string); ! 4444: n_oper = 0; ! 4445: } ! 4446: break; ! 4447: case TYPE: ! 4448: // cond stores the type of the operator function ! 4449: // error('d',"type %t",cond); ! 4450: if (cn == 0) { ! 4451: // error("operator%t() not aM",Ptype(n_initializer)); ! 4452: error("operator%t() not aM",Ptype(cond)); ! 4453: n_oper = 0; ! 4454: // n_initializer = 0; ! 4455: cond = 0; ! 4456: } ! 4457: else { ! 4458: Pfct f = Pfct(tp); ! 4459: // n_initializer = 0; ! 4460: Ptype tx = Ptype(cond); ! 4461: cond = 0; ! 4462: if (f->base != FCT) error("badT for%n::operator%t()",cn,tx); ! 4463: if (f->returns != defa_type) { ! 4464: // if (f->returns->check(tx,0)) error("bad resultT for%n::operator%t()",cn,tx); ! 4465: error("resultT for%n::operator%t()",cn,tx); ! 4466: DEL(f->returns); ! 4467: } ! 4468: if (f->argtype) { ! 4469: error("%n::operator%t()WAs",cn,tx); ! 4470: f->argtype = 0; ! 4471: } ! 4472: f->returns = tx; ! 4473: Pname nx = tx->is_cl_obj(); ! 4474: if (nx && can_coerce(tx,cn->tp)) error("both %n::%n(%n) and %n::operator%t()",cn,cn,nx,tx); ! 4475: char buf[1024]; ! 4476: char* bb = tx->signature(buf); ! 4477: int l2 = bb-buf; ! 4478: if (1023<l2) error('i',"N::check_oper():N buffer overflow"); ! 4479: char* p = new char[l2+5]; ! 4480: p[0] = '_'; ! 4481: p[1] = '_'; ! 4482: p[2] = 'o'; ! 4483: p[3] = 'p'; ! 4484: strcpy(p+4,buf); ! 4485: string = p; ! 4486: } ! 4487: break; ! 4488: } ! 4489: } ! 4490: ! 4491: Pexpr vbase_args(Pfct a, Pname bn) ! 4492: /* ! 4493: constructor a calls the constructor bn for a base class ! 4494: generate argument list needed for virtual base arguments ! 4495: */ ! 4496: { ! 4497: Pfct b = Pfct(bn->tp); ! 4498: //error('d',"vbase_args%n: %t %k",bn,b,b->base); ! 4499: Pexpr args = 0; ! 4500: Pexpr tail = 0; ! 4501: if (b->base == OVERLOAD) b = Pfct(Pgen(b)->fct_list->f->tp); // doesn't matter which ! 4502: for (Pname d = b->f_args->n_list; d!=b->argtype; d=d->n_list) { ! 4503: for (Pname dd = a->f_args->n_list; dd; dd=dd->n_list) ! 4504: // using strcmp is a trick ! 4505: if (strcmp(dd->string,d->string)==0) break; ! 4506: ! 4507: Pexpr aa = new expr(ELIST,dd,0); ! 4508: if (args == 0) ! 4509: args = aa; ! 4510: else ! 4511: tail->e2 = aa; ! 4512: tail = aa; ! 4513: } ! 4514: return args; ! 4515: } ! 4516: ! 4517: void fct::init_bases(Pclass cl, Pexpr) ! 4518: /* ! 4519: in "cl"'s constructor "this" generate code to initialize base classes ! 4520: and members using the initializers "f->f_init" ! 4521: ! 4522: this->f_init == list of names of classes to be initialized ! 4523: COLON(b) => base class b ! 4524: => constructor call in f_init->n_initializer ! 4525: COLON() => unnamed base class ! 4526: => constructor call in f_init->n_initializer ! 4527: NAME(m) => member m ! 4528: => constructor call in m->n_initializer ! 4529: */ ! 4530: { ! 4531: Ptable ftbl = body->memtbl; ! 4532: DB( if(Ddebug>=1) error('d',"init_bases %t init %d",cl,f_init); ); ! 4533: ! 4534: // explicit initializers ! 4535: if ( cl && cl->csu == UNION && f_init && f_init->n_list ) ! 4536: error(&f_init->where,"multipleIrs in unionK %s:: %s",cl->string,cl->string); ! 4537: for (Pname nx, nn=f_init; nn; delete nn,(nn=nx) ) { ! 4538: Pexpr i = nn->n_initializer; ! 4539: nn->n_initializer = 0; ! 4540: nx = nn->n_list; ! 4541: ! 4542: // error('d',"init_base %s %d",nn->string,i); ! 4543: if (nn->string) { ! 4544: // lookup in case type name hides a "real" member ! 4545: { Pname mmm = cl->memtbl->look(nn->string,0); ! 4546: if ( mmm ) nn->base = mmm->base; ! 4547: } ! 4548: if (nn->base == TNAME) { // base class ! 4549: char *bn; ! 4550: while ( nn->tp && nn->tp->base == TYPE ) ! 4551: nn->tp = Pbase(nn->tp)->b_name->tp; ! 4552: if ( nn->tp && nn->tp->base == COBJ ) ! 4553: bn = Pbase(nn->tp)->b_name->string; ! 4554: else ! 4555: bn = nn->string; ! 4556: for (Pbcl l = cl->baselist; l; l=l->next) { ! 4557: Pclass bcl = l->bclass; ! 4558: if ((strcmp(bcl->string,bn) == 0) || ! 4559: ((bcl->class_base == ! 4560: instantiated_template_class) && ! 4561: ((strcmp(nn->string, ! 4562: Ptclass(bcl)->unparametrized_tname()->string)) == 0))) ! 4563: { ! 4564: ! 4565: // l->init is zeroed out in ctor_simpl ! 4566: // if error_count, simpl() not invoked ! 4567: if (l->init && error_count == 0) ! 4568: error("twoIrs for%t",bcl); ! 4569: else ! 4570: l->init = base_init(bcl,i,ftbl,l->obj_offset); ! 4571: goto con; ! 4572: } ! 4573: } ! 4574: error(&nn->where,"unexpectedAL: noBC%n",nn); ! 4575: con: ! 4576: continue; ! 4577: } ! 4578: else { // member initializer ! 4579: Pname m = cl->memtbl->look(nn->string,0); ! 4580: if (m && m->n_table==cl->memtbl) ! 4581: m->n_initializer = mem_init(m,i,ftbl); ! 4582: else ! 4583: error(&nn->where,"%n not inC %s",nn,cl->string); ! 4584: } ! 4585: } ! 4586: else { // unnamed base class ! 4587: Pbcl l = cl->baselist; ! 4588: if (l == 0) { ! 4589: error("unexpectedAL: noBC called"); ! 4590: continue; ! 4591: } ! 4592: ! 4593: if (l->next) { ! 4594: bit cnt = 0, rvb = 0; // remote virtual base classes ! 4595: for (Pbcl ll = l; ll; ll = ll->next, ++cnt ) ! 4596: if (ll->base==VIRTUAL && ll->promoted) ++rvb; ! 4597: if ( rvb ) ! 4598: error("unnamedBCIr: %dBCes(%d non-explicit virtualBC%s)",cnt,rvb,rvb==1?"":"es"); ! 4599: else error("unnamedBCIr: %dBCes",cnt); ! 4600: continue; ! 4601: } ! 4602: ! 4603: if (l->init) ! 4604: error("twoIrs for%t",l->bclass); ! 4605: else { ! 4606: error(strict_opt?0:'w',&nn->where,"N ofBC%t missing from BCIr (anachronism)",l->bclass); ! 4607: l->init = base_init(l->bclass,i,ftbl,l->obj_offset); ! 4608: } ! 4609: } ! 4610: } // for ! 4611: ! 4612: for (Pbcl l = cl->baselist; l; l=l->next) { ! 4613: // default initialization of base classes ! 4614: Pname ctor; ! 4615: Pclass bcl = l->bclass; ! 4616: if (l->init==0 && (ctor=bcl->has_ctor())) ! 4617: l->init = base_init(bcl,0,ftbl,l->obj_offset); ! 4618: } ! 4619: } ! 4620: ! 4621: int inline_restr; /* report use of constructs that the inline expanded ! 4622: cannot handle here */ ! 4623: ! 4624: void fct::dcl(Pname n) ! 4625: { ! 4626: int nmem = TBLSIZE; ! 4627: Pname a; ! 4628: Pname ll; ! 4629: Ptable ftbl; ! 4630: ! 4631: Pptr cct = 0; ! 4632: int const_old = const_save; ! 4633: ! 4634: int bit_old = bit_offset; ! 4635: int byte_old = byte_offset; ! 4636: int max_old = max_align; ! 4637: ! 4638: if (base != FCT) error('i',"F::dcl(%d)",base); ! 4639: if (body == 0) error('i',"F::dcl(body=%d)",body); ! 4640: if (n==0 || n->base!=NAME) error('i',"F::dcl(N=%d %d)",n,(n)?n->base:0); ! 4641: DB( if(Ddebug>=1) error('d',"fct::dcl(%n) %k %d %t",n,n->n_scope,body->own_tbl,this); ); ! 4642: if (body->own_tbl) return; // done already ! 4643: ! 4644: // if (f_inline==0 ) n->n_dcl_printed = 1; // beware of recursive calls, no decl needed ! 4645: // if (f_inline && debug_opt) n->n_dcl_printed = 2; ! 4646: if (body->memtbl == 0) body->memtbl = new table(nmem+3,gtbl,0); ! 4647: body->own_tbl = 1; ! 4648: ftbl = body->memtbl; ! 4649: ftbl->real_block = body; ! 4650: ! 4651: max_align = 0;//AL_FRAME; ! 4652: bit_offset = 0; ! 4653: ! 4654: cc->stack(); ! 4655: cc->nof = n; ! 4656: cc->ftbl = ftbl; ! 4657: ! 4658: switch (n->n_scope) { ! 4659: case 0: ! 4660: case PUBLIC: ! 4661: { cc->not = n->n_table->t_name; ! 4662: cc->cot = Pclass(cc->not->tp); ! 4663: cc->tot = cc->cot->this_type; ! 4664: // if (f_this==0 || cc->tot==0) error('i',"F::dcl(%n): f_this=%d cc->tot=%d",n,f_this,cc->tot); ! 4665: if (f_this) f_this->n_table = ftbl; // fake for inline printout ! 4666: cc->c_this = f_this; ! 4667: ! 4668: ! 4669: Pclass cl = Pclass(cc->not->tp); ! 4670: ! 4671: if (cl->c_body!=3 ! 4672: || n->n_initializer ! 4673: || n->n_sto==STATIC ! 4674: || f_inline ! 4675: || f_imeasure ! 4676: || f_virtual==0) ! 4677: ; ! 4678: else { // could be the function where we need to ! 4679: // output the vtbl ! 4680: int i; ! 4681: for (Pname nn=cl->memtbl->get_mem(i=1); nn; nn=cl->memtbl->get_mem(++i) ) { ! 4682: Ptype t = nn->tp; ! 4683: if (t) ! 4684: switch (t->base) { ! 4685: case FCT: ! 4686: if (nn == n) goto prnt; ! 4687: if (nn->n_initializer ! 4688: || nn->n_sto==STATIC ! 4689: || Pfct(nn->tp)->f_inline ! 4690: || Pfct(nn->tp)->f_imeasure ! 4691: || Pfct(nn->tp)->f_virtual==0) break; ! 4692: goto zaq; ! 4693: ! 4694: case OVERLOAD: ! 4695: { for (Plist gl=Pgen(t)->fct_list; gl; gl=gl->l) { ! 4696: Pname nn = gl->f; ! 4697: if (nn == n) goto prnt; ! 4698: if (nn->n_initializer ! 4699: || nn->n_sto==STATIC ! 4700: || Pfct(nn->tp)->f_inline ! 4701: || Pfct(nn->tp)->f_imeasure ! 4702: || Pfct(nn->tp)->f_virtual==0) continue; ! 4703: goto zaq; ! 4704: } ! 4705: } ! 4706: } ! 4707: } ! 4708: goto zaq; ! 4709: prnt: ! 4710: cl->print_all_vtbls(cl); ! 4711: goto zaq; ! 4712: } ! 4713: } ! 4714: } ! 4715: zaq: ! 4716: // protect against: class x; x f(); class x { x(x&); .... ! 4717: if (f_result == 0) make_res(this); ! 4718: if (f_result) f_result->n_table = ftbl; // fake for inline printout ! 4719: ! 4720: returns->tsizeof(); // make sure size is known ! 4721: ! 4722: Pname ax; ! 4723: for (a=argtype, ll=0; a; a=ax) { ! 4724: ax = a->n_list; ! 4725: Pname nn = a->dcl(ftbl,ARG); ! 4726: Pname cn = nn->tp->is_cl_obj(); ! 4727: if (cn == 0) cn = cl_obj_vec; ! 4728: if (cn) (void)cn->tp->tsizeof(); // make sure it is printed ! 4729: nn->n_assigned_to = nn->n_used = nn->n_addr_taken = 0; ! 4730: nn->n_list = 0; ! 4731: ! 4732: switch (nn->tp->base) { ! 4733: case CLASS: ! 4734: case ENUM: /* unlink types declared in arg list */ ! 4735: nn->dcl_print(0); ! 4736: break; ! 4737: default: ! 4738: if (ll) ! 4739: ll->n_list = nn; ! 4740: else ! 4741: f_args = argtype = nn; ! 4742: ll = nn; ! 4743: } ! 4744: delete a; ! 4745: } ! 4746: ! 4747: if (f_result) { // link in f_result ! 4748: f_args = f_result; ! 4749: f_result->n_list = argtype; ! 4750: } ! 4751: ! 4752: if (f_this) { // link in f_this ! 4753: f_args = f_this; ! 4754: f_this->n_list = f_result ? f_result : argtype; ! 4755: } ! 4756: ! 4757: if (n->n_oper==CTOR || n->n_oper==DTOR) vbase_pointers(n,cc->cot); ! 4758: ! 4759: if (n->n_oper == CTOR) { ! 4760: const_save = 1; ! 4761: init_bases(cc->cot,f_init); ! 4762: } ! 4763: else if (f_init) ! 4764: error(0,"unexpectedAL: not aK"); ! 4765: ! 4766: PERM(returns); ! 4767: const_save = f_inline&&debug_opt==0; ! 4768: inline_restr = 0; ! 4769: body->dcl(ftbl); ! 4770: ! 4771: defined |= DEFINED; ! 4772: if (f_inline && inline_restr && returns->base!=VOID) { ! 4773: f_inline = 0; ! 4774: char* s = (inline_restr & 32) ? "continue" ! 4775: : (inline_restr & 16) ? "break" ! 4776: : (inline_restr & 8) ? "loop" ! 4777: : (inline_restr & 4) ? "switch" ! 4778: : (inline_restr & 2) ? "goto" ! 4779: : (inline_restr & 1) ? "label" ! 4780: : "" ; ! 4781: if (warning_opt) { ! 4782: error('w', "\"inline\" ignored, %n contains %s",n,s); ! 4783: error('w', "out-of-line copy of %n created",n); ! 4784: } ! 4785: // if (cc->cot) ! 4786: n->simpl(); //BS6 ! 4787: n->dcl_print(0); ! 4788: } ! 4789: const_save = const_old; ! 4790: ! 4791: if (f_inline && debug_opt==0) isf_list = new name_list(n,isf_list); ! 4792: ! 4793: bit_offset = bit_old; ! 4794: byte_offset = byte_old; ! 4795: max_align = max_old; ! 4796: cc->unstack(); ! 4797: ! 4798: //error('d',"fct-> returns %t",returns); ! 4799: } ! 4800: ! 4801: Pexpr fct::base_init(Pclass bcl, Pexpr i, Ptable ftbl, int offset) ! 4802: /* ! 4803: have base class bcl and expr list i ! 4804: return "( *(base*)this ) . ctor( i )" ! 4805: ctor call generated in expr.typ() ! 4806: */ ! 4807: { ! 4808: Ptype ty = bcl->this_type; ! 4809: Pexpr th = rptr(ty,f_this,offset); // base* ! 4810: Pname ctor = bcl->has_ctor(); ! 4811: ! 4812: //error('d',"fct::B_init(C %t, i %d, %d) ctor %n",bcl,i,i?i->tp:0,ctor); ! 4813: ! 4814: Pexpr ii = (i && i->base==ELIST)?i->e1:i; ! 4815: ! 4816: if (ii ! 4817: && ii->base==DEREF ! 4818: && ii->e1->base==CAST ! 4819: && th->base==CAST) th->i2 = ii->e1->i2; ! 4820: ! 4821: if (ctor == 0) { ! 4822: if (i && i->base!=ELIST) i = new expr(ELIST,i,0); ! 4823: ! 4824: Pexpr v = new texpr(VALUE,bcl,i); // ?.base(i) ! 4825: v->e2 = new expr(DEREF,th,0); // (*(base*)this).base(i) ! 4826: v = v->typ(ftbl); // *base(&*(base*)this,i) ! 4827: //error('d',"v %k",v->base); ! 4828: switch (v->base) { ! 4829: case DEREF: ! 4830: return v->e1; // base(&*(base*)this,i) ! 4831: case ASSIGN: // degenerate base(base&): *(base*)this=i ! 4832: th = new texpr(CAST,ty,f_this); ! 4833: v = new expr(CM,v,th); // (*(base*)this=i,(base*)this); ! 4834: return v->typ(ftbl); ! 4835: default: ! 4836: return 0; ! 4837: } ! 4838: } ! 4839: ! 4840: ! 4841: Pname icn; ! 4842: if (i) { ! 4843: ii = ii->typ(ftbl); ! 4844: if (bcl->has_itor()==0 ! 4845: && (icn=ii->tp->is_cl_obj()) ! 4846: && (Pclass(icn->tp)==bcl || Pclass(icn->tp)->has_base(bcl))) { ! 4847: // degenerate base(base&): *(base*)this=i ! 4848: // memberwise copy ! 4849: //error('d',"copy %t",ty); ! 4850: // th = new cast(ty,f_this); ! 4851: // th = th->contents(); ! 4852: th = new texpr(CAST,ty,f_this); ! 4853: th = th->contents(); ! 4854: th = th->typ(ftbl); ! 4855: if (Pclass(icn->tp)!=bcl) { // cast needed ! 4856: Pptr r = new ptr(RPTR,Pptr(ty)->typ); ! 4857: ii = new texpr(CAST,r,ii); ! 4858: ii = ii->typ(ftbl); ! 4859: } ! 4860: ii = new expr(ASSIGN,th,ii); ! 4861: ii->tp = th->tp; ! 4862: // simulate `return this': ! 4863: // *(base*)this=i,(base*)this ! 4864: ii = new expr(CM,ii,new cast(ty,f_this)); ! 4865: ii->tp = th->tp; ! 4866: return ii; ! 4867: // return ii->typ(ftbl); // don't find cl::operator=() ! 4868: } ! 4869: if (i->base == ELIST) i->e1 = ii; ! 4870: } ! 4871: //Pexpr x = call_ctor(ftbl,th,ctor,i,REF,vbase_args(this,ctor)); ! 4872: //error('d',"call %n %t -> %d %k",ctor,ctor->tp,x,x->base); ! 4873: // return x; ! 4874: return call_ctor(ftbl,th,ctor,i,REF,vbase_args(this,ctor)); ! 4875: } ! 4876: ! 4877: ! 4878: Pexpr fct::mem_init(Pname mn, Pexpr i, Ptable ftbl) ! 4879: /* ! 4880: return "member_ctor( m, i )" ! 4881: */ ! 4882: { ! 4883: // a new entry for B::B_pub, in general, has no tp and no ! 4884: // real info: all the tp-> only work on our systems because ! 4885: // 0 pointer dereference isn't system memory. it core dumps ! 4886: // in set_const since no test is made on this == 0. ! 4887: //error('d',"mem_init %n",mn); ! 4888: ! 4889: // if (mn->n_stclass == STATIC) error('s',"MIr for static%n",mn); ! 4890: switch (mn->n_stclass) { ! 4891: case STATIC: ! 4892: error("MIr for static%n",mn); ! 4893: break; ! 4894: case ENUM: ! 4895: error("MIr for enumeration constant%n", mn); ! 4896: break; ! 4897: } ! 4898: ! 4899: Pname member = (mn->base==PUBLIC && mn->n_qualifier) ? mn->n_qualifier : mn; ! 4900: ! 4901: if (i) i = i->typ(ftbl); ! 4902: Pname cn = member->tp->is_cl_obj(); // first find the class name ! 4903: ! 4904: // if (member->n_stclass == STATIC) error('s',"MIr for static%n",member); ! 4905: // if (i) i = i->typ(ftbl); ! 4906: // Pname cn = member->tp->is_cl_obj(); // first find the class name ! 4907: Pref tn = new ref(REF,f_this,member); ! 4908: tn->tp = member->tp; ! 4909: //error('d',"MI for %n %t = %t",member,member->tp,i?i->tp:0); ! 4910: //error('d',"fthis %d %t member %n tp %t",f_this,f_this->tp,member,tn->tp); ! 4911: if (cn) { ! 4912: Pclass mcl = Pclass(cn->tp); // then find the classdef ! 4913: Pname ctor = mcl->has_ctor(); ! 4914: Pname icn; ! 4915: ! 4916: if (i ! 4917: && mcl->has_itor()==0 ! 4918: && (icn=i->tp->is_cl_obj()) ! 4919: && Pclass(icn->tp)==mcl) { // bitwise copy ! 4920: Pexpr init = new expr(ASSIGN,tn,i); ! 4921: init->tp = tn->tp; ! 4922: // return init->typ(ftbl); // don't look for mcl.operator=() ! 4923: member->assign(); ! 4924: return init; ! 4925: } ! 4926: ! 4927: if (ctor) return call_ctor(ftbl,tn,ctor,i,DOT); ! 4928: ! 4929: error("Ir forM%nW noK",member); ! 4930: return 0; ! 4931: } ! 4932: ! 4933: if (cl_obj_vec) { ! 4934: if (i && i->base == ELIST) ! 4935: error("illegalIrL for %t%nWinM initializationL",mn->tp,mn); ! 4936: else error('s',"Ir forCM %t%nWK",mn->tp,mn); ! 4937: return 0; ! 4938: } ! 4939: ! 4940: if (i && i->base == ELIST) { ! 4941: if (i->e2) error("Ir for%n not a simpleE",member); ! 4942: i = i->e1; ! 4943: } ! 4944: ! 4945: if (member->tp->is_ref() && (i == 0)) { ! 4946: error("empty Ir for reference %n", member); ! 4947: return 0 ; ! 4948: } ! 4949: ! 4950: // error( 'd', "fct_mem_init: %n %k", member, member->tp->base ); ! 4951: switch (member->tp->base) { ! 4952: // case RPTR: ! 4953: // if ( i == 0 ) { ! 4954: // error( "empty Ir for reference %n", member ); ! 4955: // return 0; ! 4956: // } ! 4957: // break; ! 4958: case VEC: ! 4959: case FCT: ! 4960: case OVERLOAD: ! 4961: error("Ir for%n ofT %t",member,member->tp); ! 4962: return 0; ! 4963: } ! 4964: ! 4965: //error('d',"tp %t",member->tp); ! 4966: if (member->tp->tconst()) { ! 4967: int save_ignore_const = ignore_const; ! 4968: ignore_const = 1; ! 4969: i = new expr(ASSIGN,tn,i); ! 4970: i = i->typ(ftbl); ! 4971: ignore_const = save_ignore_const; ! 4972: return i; ! 4973: } ! 4974: ! 4975: Pptr pt; ! 4976: if (pt = member->tp->is_ref()) { ! 4977: switch (pt->typ->base) { ! 4978: case FCT: ! 4979: case OVERLOAD: ! 4980: i = ptr_init(pt,i,ftbl); ! 4981: break; ! 4982: default: ! 4983: i = ref_init(pt,i,ftbl); ! 4984: } ! 4985: i = new expr(ASSIGN,tn,i); ! 4986: i->tp = tn->tp; ! 4987: member->assign(); // cannot call typ: would cause dereference ! 4988: return i; ! 4989: } ! 4990: ! 4991: i = new expr(ASSIGN,tn,i); ! 4992: return i->typ(ftbl); // typ performs the type check on the assignment ! 4993: } ! 4994: ! 4995: Pexpr replace_temp(Pexpr e, Pexpr n) ! 4996: /* ! 4997: e is on the form ! 4998: f(&temp,arg) , temp ! 4999: or ! 5000: &temp->ctor(arg) , temp ! 5001: or ! 5002: x->f(&temp,arg) , temp ! 5003: change it to ! 5004: f(n,arg) ! 5005: or ! 5006: n->ctor(arg) ! 5007: */ ! 5008: { ! 5009: Pexpr c = e->e1; // f(&temp,arg) or &temp->ctor(args) ! 5010: Pexpr ff = c->e1; ! 5011: Pexpr a = c->e2; // maybe ELIST(&temp,arg) ! 5012: Pexpr tmp = e->e2; ! 5013: ! 5014: //error('d',"suppress(%d %k) %n",tmp->base,tmp->base,tmp->base==NAME?tmp:0); ! 5015: if (tmp->base==DEREF) tmp = tmp->e1; ! 5016: if (tmp->base==CAST) tmp = tmp->e1; ! 5017: if (tmp->base==ADDROF || tmp->base==G_ADDROF) tmp = tmp->e2; ! 5018: if (tmp->base != NAME) return e; //error('i',"replace %k",tmp->base); ! 5019: tmp->tp = any_type; // temporary not used: suppress it ! 5020: ! 5021: //error('d',"replace_temp(%k %k) c %k ff %k",e->base,n->base,c->base,ff->base); ! 5022: switch (ff->base) { ! 5023: case REF: ! 5024: if (ff->e1->base==G_ADDROF && ff->e1->e2==tmp) ! 5025: a = ff; // &tmp -> f() ! 5026: break; ! 5027: case DOT: ! 5028: if (ff->e1->base==NAME && ff->e1==tmp) { ! 5029: a = ff; // tmp . f() ! 5030: a->base = REF; ! 5031: } ! 5032: break; ! 5033: } ! 5034: a->e1 = n; ! 5035: return c; ! 5036: } ! 5037: ! 5038: Pname classdef::has_ictor() ! 5039: /* ! 5040: does this class have a constructor taking no arguments? ! 5041: */ ! 5042: { ! 5043: Pname c = has_ctor(); ! 5044: if (c == 0) return 0; ! 5045: ! 5046: Pfct f = Pfct(c->tp); ! 5047: ! 5048: switch (f->base) { ! 5049: default: ! 5050: error('i',"%s: badK (%k)",string,c->tp->base); ! 5051: ! 5052: case FCT: ! 5053: switch (f->nargs) { ! 5054: case 0: return c; ! 5055: default: if (f->argtype->n_initializer) return c; ! 5056: } ! 5057: return 0; ! 5058: ! 5059: case OVERLOAD: ! 5060: { for (Plist l=Pgen(f)->fct_list; l; l=l->l) { ! 5061: Pname n = l->f; ! 5062: f = (Pfct)n->tp; ! 5063: switch (f->nargs) { ! 5064: case 0: return n; ! 5065: default: if (f->argtype->n_initializer) return n; ! 5066: } ! 5067: } ! 5068: return 0; ! 5069: } ! 5070: } ! 5071: } ! 5072: ! 5073: int add_first; // fudge, use ctor arg instead ! 5074: Pname gen::add(Pname n) ! 5075: /* ! 5076: add "n" to the tail of "fct_list" ! 5077: (overloaded names are searched in declaration order) ! 5078: ! 5079: detect: multiple identical declarations ! 5080: declaration after use ! 5081: multiple definitions ! 5082: */ ! 5083: { ! 5084: Pfct f = Pfct(n->tp); ! 5085: Pname nx; ! 5086: //error('d',"add(%n) %d",n,add_first); ! 5087: if (f->base != FCT) error("%n: overloaded nonF",n); ! 5088: ! 5089: if ( fct_list && (nx=find(f,1)) ) { ! 5090: //error('d',"found %n %t",nx,nx->tp); ! 5091: Linkage l1 = Pfct(nx->tp)->f_linkage; ! 5092: Linkage l2 = f->f_linkage; ! 5093: if ( l2 != linkage_default && l1 != l2 ) ! 5094: error("inconsistent linkage specifications for%n",n); ! 5095: Nold = 1; ! 5096: } ! 5097: else { ! 5098: if (add_first==0 && f->f_signature==0) f->sign(); ! 5099: //error('d',"signature: %d \"%s\" fct_list %d",f->f_signature,f->f_signature,fct_list); ! 5100: nx = new name; ! 5101: *nx = *n; ! 5102: // nx->n_tbl_list = Pname(n->string); ! 5103: nx->n_gen_fct_name = n->string; ! 5104: PERM(nx); ! 5105: Nold = 0; ! 5106: if (fct_list) { ! 5107: int clink = (f->f_linkage==linkage_C); ! 5108: Plist gl=fct_list; ! 5109: for(;;) { ! 5110: if (clink ! 5111: && Pfct(gl->f->tp)->f_linkage == linkage_C ) { ! 5112: error("two%ns with c linkage",n); ! 5113: if(f->f_signature==0) f->sign(); ! 5114: } ! 5115: if (gl->l) ! 5116: gl = gl->l; ! 5117: else ! 5118: break; ! 5119: } ! 5120: gl->l = new name_list(nx,0); ! 5121: } ! 5122: else ! 5123: fct_list = new name_list(nx,0); ! 5124: nx->n_list = 0; ! 5125: } ! 5126: return nx; ! 5127: } ! 5128: ! 5129: void fct::sign() ! 5130: { ! 5131: switch ( f_linkage ) { ! 5132: case linkage_C: ! 5133: f_signature = ""; ! 5134: return; ! 5135: case linkage_Cplusplus: ! 5136: case linkage_default: ! 5137: break; ! 5138: } ! 5139: char buf[1024]; ! 5140: char* bb = signature(buf); ! 5141: int ll = bb-buf; ! 5142: if (1023 < ll) error('i',"gen::add():N buffer overflow"); ! 5143: char* p = new char[ll+1]; ! 5144: strcpy(p,buf); ! 5145: f_signature = p; ! 5146: //error('d',"fct::sign %s",p); ! 5147: } ! 5148: ! 5149: Pname gen::find(Pfct f, bit warn) ! 5150: { ! 5151: for (Plist gl=fct_list; gl; gl=gl->l) { ! 5152: Pname n = match(gl->f,f,warn); ! 5153: if (n) return n; ! 5154: } ! 5155: return 0; ! 5156: } ! 5157: ! 5158: Pname gen::match(Pname nx, Pfct f, bit warn) ! 5159: { ! 5160: Pfct fx = Pfct(nx->tp); ! 5161: Pname a, ax; ! 5162: int op = 0; // overloading problem: const, ref, vec/ptr, or basetype ! 5163: //error('d',"fx %d %d f %d %d",fx->nargs_known,fx->nargs,f->nargs_known,f->nargs); ! 5164: ! 5165: if (f->nargs_known != fx->nargs_known) return 0; // the bets are off ! 5166: // must rely on checks at ! 5167: // call points ! 5168: if (f->f_const != fx->f_const) return 0; ! 5169: ! 5170: if (fx->nargs != f->nargs ! 5171: && fx->nargs_known==1 ! 5172: && f->nargs_known==1) return 0; // no warning for potential ! 5173: // problems due to default args ! 5174: ! 5175: for (ax=fx->argtype, a=f->argtype; a&&ax; ax=ax->n_list, a=a->n_list) { ! 5176: Ptype at = ax->tp; ! 5177: Ptype atp = a->tp; ! 5178: //error('d',"at %t atp %t",at,atp); ! 5179: if (at->check(atp,OVERLOAD) == 0) { ! 5180: //error('d',"at %t atp %t cp %d vrp %d",at,atp,const_problem,vrp_equiv); ! 5181: continue; ! 5182: } ! 5183: //error('d',"warn %d",warn); ! 5184: if (warn == 0) goto xx; ! 5185: ! 5186: /* ! 5187: warn against: ! 5188: overload f(X&), f(X); error ! 5189: overload f(int), f(const); error ! 5190: overload f(int*), f(int[10]); warn ! 5191: etc. ! 5192: */ ! 5193: ! 5194: //error('d',"vrp_equiv %d const_problem %d",vrp_equiv,const_problem); ! 5195: if (const_problem) { // differ only in X vs const X ! 5196: if (at->is_ptr_or_ref()) return 0; ! 5197: op++; ! 5198: continue; ! 5199: } ! 5200: ! 5201: aaa: ! 5202: switch (atp->base) { ! 5203: case TYPE: ! 5204: atp = Pbase(atp)->b_name->tp; ! 5205: goto aaa; ! 5206: // case EOBJ: ! 5207: // atp = Penum(Pbase(atp)->b_name->tp)->e_type; ! 5208: // goto aaa; ! 5209: case RPTR: // differ only by X vs X& ? ! 5210: if (Pptr(atp)->typ->check(at,0)==0) { ! 5211: op++; ! 5212: continue; ! 5213: } ! 5214: } ! 5215: ! 5216: atl: ! 5217: switch (at->base) { ! 5218: case TYPE: ! 5219: at = Pbase(at)->b_name->tp; ! 5220: goto atl; ! 5221: // case EOBJ: ! 5222: // at = Penum(Pbase(at)->b_name->tp)->e_type; ! 5223: // goto atl; ! 5224: case RPTR: // differ only by X& vs X ? ! 5225: if (Pptr(at)->typ->check(atp,0)==0) { ! 5226: op++; ! 5227: continue; ! 5228: } ! 5229: break; ! 5230: // case CHAR: // differ only by int vs char ? ! 5231: // case SHORT: ! 5232: // case INT: ! 5233: // if (atp->base!=at->base && atp->base==EOBJ) { ! 5234: // op++; ! 5235: // continue; ! 5236: // } ! 5237: // break; ! 5238: } ! 5239: //error('d',"return 0"); ! 5240: //goto xx; ! 5241: // some argument is really different ! 5242: // e.g. f(int), f(char*); ! 5243: return 0; ! 5244: } ! 5245: ! 5246: // arguments checked. Now look at leftover args, return type,etc. ! 5247: ! 5248: // if (warn && a && fx->nargs_known==ELLIPSIS) error('w',"... in%n'sAT hidesATs from the overloading mechanism",nx); ! 5249: ! 5250: if (a || ax) return 0; ! 5251: ! 5252: if (op == 0) { ! 5253: if (warn && fx->returns->check(f->returns,0)) ! 5254: error("two different return valueTs for%n: %t and %t",nx,fx->returns,f->returns); ! 5255: ! 5256: return nx; ! 5257: } ! 5258: xx: ! 5259: if (warn && op) ! 5260: error("the overloading mechanism cannot tell a%t from a%t",fx,f); ! 5261: ! 5262: return 0; ! 5263: } ! 5264: ! 5265: int name::no_of_names() ! 5266: { ! 5267: register int i = 0; ! 5268: register Pname n; ! 5269: for (n=this; n; n=n->n_list) i++; ! 5270: return i; ! 5271: } ! 5272: ! 5273: static Pexpr lvec[20], *lll, *curr_e; ! 5274: static Pexpr last_il = 0; ! 5275: static Pexpr list_back = 0; ! 5276: static Pexpr last_el = 0, *last_lll; ! 5277: ! 5278: void new_list(Pexpr lx) ! 5279: { ! 5280: if (lx->base != ILIST) error('i',"IrLX"); ! 5281: ! 5282: lll = last_lll = lvec; ! 5283: lll++; ! 5284: *lll = last_el = lx->e1; ! 5285: } ! 5286: ! 5287: Pexpr next_elem() ! 5288: { ! 5289: Pexpr e; ! 5290: Pexpr lx; ! 5291: ! 5292: if (lll == lvec) return 0; ! 5293: ! 5294: lx = *lll; ! 5295: ! 5296: if (list_back) { ! 5297: e = list_back; ! 5298: list_back = 0; ! 5299: return e; ! 5300: } ! 5301: ! 5302: if (lx == 0) { /* end of list */ ! 5303: lll--; ! 5304: return 0; ! 5305: } ! 5306: ! 5307: switch (lx->base) { ! 5308: case ELIST: ! 5309: e = lx->e1; ! 5310: curr_e = &lx->e1; ! 5311: last_el = lx; ! 5312: last_lll = lll; ! 5313: *lll = lx->e2; ! 5314: switch (e->base) { ! 5315: case ILIST: ! 5316: lll++; ! 5317: *lll = e->e1; ! 5318: last_il = e; ! 5319: return Pexpr(1); // start of new ILIST ! 5320: case ELIST: ! 5321: error("nestedEL"); ! 5322: return 0; ! 5323: default: ! 5324: { ! 5325: if (need_sti(e)) error('s',"generalIr inIrL"); ! 5326: return e; ! 5327: } ! 5328: } ! 5329: case IVAL: ! 5330: case ZERO: ! 5331: lll--; ! 5332: return 0; ! 5333: default: ! 5334: error('i',"IrL %k",lx->base); ! 5335: } ! 5336: } ! 5337: ! 5338: static Pexpr insert_init(Pexpr newval) { ! 5339: // splice an initializer in front of the next element in the ! 5340: // initializer list. Provides initializers for unnamed bitfields. ! 5341: Pexpr t = new expr(ELIST,last_el->e1,last_el->e2); ! 5342: ! 5343: last_el->e1=newval; ! 5344: last_el->e2=t; ! 5345: lll = last_lll; ! 5346: *lll = last_el; ! 5347: return next_elem(); ! 5348: } ! 5349: ! 5350: void skip_ilist() ! 5351: // skip ilist use to represent pointer to member function literal ! 5352: { ! 5353: Pexpr e = next_elem(); ! 5354: e = next_elem(); ! 5355: } ! 5356: ! 5357: void list_check(Pname nn, Ptype t, Pexpr il, Ptable tbl) ! 5358: /* ! 5359: see if the list "lll" can be assigned to something of type "t" ! 5360: "nn" is the name of the variable for which the assignment is taking place. ! 5361: "il" is the last list element returned by next_elem() ! 5362: */ ! 5363: { ! 5364: Pexpr e; ! 5365: bit lst = 0; ! 5366: int i; ! 5367: Pclass cl; ! 5368: int tdef = 0; ! 5369: ! 5370: //error('d',"list_check%n: %t (%d)",nn,t,il); ! 5371: if (il == Pexpr(1)) { ! 5372: lst = 1; ! 5373: e = il; ! 5374: } ! 5375: else if (il) ! 5376: list_back = il; ! 5377: ! 5378: zzz: ! 5379: switch (t->base) { ! 5380: case TYPE: ! 5381: t = Pbase(t)->b_name->tp; ! 5382: tdef = 1; ! 5383: ! 5384: // did it used to be a VEC before arg_fudge was applied? ! 5385: if (t->base==PTR && Pvec(t)->size) ! 5386: t->base=VEC; ! 5387: goto zzz; ! 5388: ! 5389: case VEC: ! 5390: { Pvec v = Pvec(t); ! 5391: Ptype vt = v->typ; ! 5392: ! 5393: if (v->size) { /* get at most v->size initializers */ ! 5394: if (v->typ->base == CHAR) { ! 5395: e = next_elem(); ! 5396: if (e->base == STRING) { // v[size] = "..." ! 5397: int isz = Pvec(e->tp)->size; ! 5398: if (v->size < isz) error("Ir too long (%d characters) for%n[%d]",isz,nn,v->size); ! 5399: break; ! 5400: } ! 5401: else ! 5402: list_back = e; ! 5403: } ! 5404: for (i=0; i<v->size; i++) { // check next list element type ! 5405: Pfct MP = 0; ! 5406: ee: ! 5407: e = next_elem(); ! 5408: if (e == 0) goto xsw; // too few initializers are ok ! 5409: vtz: ! 5410: //error('d',"vtz: %d",vt->base); ! 5411: switch (vt->base) { ! 5412: case TYPE: ! 5413: vt = Pbase(vt)->b_name->tp; ! 5414: goto vtz; ! 5415: case VEC: ! 5416: case COBJ: ! 5417: list_check(nn,vt,e); ! 5418: break; ! 5419: case PTR: ! 5420: if ((MP = vt->memptr()) && ! 5421: e==Pexpr(1)) { ! 5422: if (vt->check(last_il->tp,ASSIGN)) ! 5423: error("badIrT for%n:%t (%tX)",v,last_il->tp,vt); ! 5424: skip_ilist(); ! 5425: break; ! 5426: } ! 5427: if (MP && e && e->base==ZERO) { ! 5428: *curr_e = new expr(ELIST,zero,zero); ! 5429: *curr_e = new expr(ILIST,*curr_e,zero); ! 5430: (*curr_e)->tp = zero_type; ! 5431: break; ! 5432: } ! 5433: if (MP && e && e->tp->base==OVERLOAD) { ! 5434: Pexpr op = ptof(Pfct(Pptr(vt)->typ),e,tbl); ! 5435: if(op) { ! 5436: *curr_e = op; ! 5437: break; ! 5438: } ! 5439: } ! 5440: // no break ! 5441: default: ! 5442: { ! 5443: if (e == (Pexpr)1) { ! 5444: error("unexpectedIrL"); ! 5445: goto ee; ! 5446: } ! 5447: ! 5448: if (vt->check(e->tp,ASSIGN)) ! 5449: error("badIrT for%n:%t (%tX)",nn,e->tp,vt); ! 5450: ! 5451: Pptr p; ! 5452: if (vt->check(e->tp,0) ! 5453: && (p=vt->is_ptr()) ! 5454: && Ptype(p)!=zero_type ! 5455: && p->typ!=char_type) { ! 5456: Pexpr te = e; ! 5457: Ptype t = p->typ; ! 5458: while ( t->base == TYPE ) t = Pbase(t)->b_name->tp; ! 5459: if ( t->base == COBJ ) ! 5460: te = ptr_init( p, e, tbl ); ! 5461: if ( te == e ) ! 5462: *curr_e = new cast(vt,e); ! 5463: else *curr_e = te; ! 5464: } ! 5465: } ! 5466: } ! 5467: } ! 5468: if ( lst && (e=next_elem()) ) error("end ofIrLX after array"); ! 5469: xsw:; ! 5470: } ! 5471: else { /* determine v->size */ ! 5472: i = 0; ! 5473: (void) v->typ->tsizeof(); ! 5474: xx: ! 5475: while ( e=next_elem() ) { // get another initializer ! 5476: Pfct MP = 0; ! 5477: i++; ! 5478: vtzz: ! 5479: //error('d',"vtzz"); ! 5480: switch (vt->base) { ! 5481: case TYPE: ! 5482: vt = Pbase(vt)->b_name->tp; ! 5483: goto vtzz; ! 5484: case VEC: ! 5485: case COBJ: ! 5486: list_check(nn,vt,e); ! 5487: break; ! 5488: case PTR: ! 5489: if((MP = vt->memptr()) && ! 5490: e==Pexpr(1)) { ! 5491: if (vt->check(last_il->tp,ASSIGN)) ! 5492: error("badIrT for%n:%t (%tX)",v,last_il->tp,vt); ! 5493: skip_ilist(); ! 5494: break; ! 5495: } ! 5496: if (MP && e && e->base==ZERO) { ! 5497: *curr_e = new expr(ELIST,zero,zero); ! 5498: *curr_e = new expr(ILIST,*curr_e,zero); ! 5499: (*curr_e)->tp = zero_type; ! 5500: break; ! 5501: } ! 5502: if (MP && e && e->tp->base==OVERLOAD) { ! 5503: Pexpr op = ptof(Pfct(Pptr(vt)->typ),e,tbl); ! 5504: if(op) { ! 5505: *curr_e = op; ! 5506: break; ! 5507: } ! 5508: } ! 5509: // no break ! 5510: default: ! 5511: { if (e == Pexpr(1)) { ! 5512: error("unexpectedIrL"); ! 5513: goto xx; ! 5514: } ! 5515: ! 5516: if (vt->check(e->tp,ASSIGN)) ! 5517: error("badIrT for%n:%t (%tX)",nn,e->tp,vt); ! 5518: ! 5519: Pptr p; ! 5520: if (vt->check(e->tp,0) ! 5521: && (p=vt->is_ptr()) ! 5522: && Ptype(p)!=zero_type ! 5523: && p->typ!=char_type) { ! 5524: Pexpr te = e; ! 5525: Ptype t = p->typ; ! 5526: while ( t->base == TYPE ) t = Pbase(t)->b_name->tp; ! 5527: if ( t->base == COBJ ) ! 5528: te = ptr_init( p, e, tbl ); ! 5529: if ( te == e ) ! 5530: *curr_e = new cast(vt,e); ! 5531: else *curr_e = te; ! 5532: } ! 5533: } ! 5534: } ! 5535: } ! 5536: if (tdef==0) v->size = i; ! 5537: } ! 5538: break; ! 5539: } ! 5540: ! 5541: case CLASS: ! 5542: cl = Pclass(t); ! 5543: goto ccc; ! 5544: ! 5545: case COBJ: /* initialize members */ ! 5546: cl = Pclass(Pbase(t)->b_name->tp); ! 5547: ccc: ! 5548: if (cl->defined == 0) { ! 5549: lll = lvec; // we are lost: ignore rest of list ! 5550: return; ! 5551: } ! 5552: ! 5553: if (cl->c_body == 1) cl->dcl_print(0); ! 5554: ! 5555: { Ptable tbl = cl->memtbl; ! 5556: Pname m; ! 5557: ! 5558: if (cl->baselist) { ! 5559: if (cl->baselist->next) error("IrL forO ofC with multipleBCs"); ! 5560: list_check(nn,cl->baselist->bclass,0); ! 5561: } ! 5562: ! 5563: for (m=tbl->get_mem(i=1); m; m=tbl->get_mem(++i)) { ! 5564: Ptype mt = m->tp; ! 5565: Pfct MP = 0; ! 5566: switch (mt->base) { ! 5567: case FCT: ! 5568: case OVERLOAD: ! 5569: case CLASS: ! 5570: case ENUM: ! 5571: continue; ! 5572: } ! 5573: if (m->n_stclass == STATIC || ! 5574: m->n_stclass == ENUM ) continue; ! 5575: /* check assignment to next member */ ! 5576: dd: ! 5577: while (mt->base == TYPE) ! 5578: mt = Pbase(mt)->b_name->tp; ! 5579: ! 5580: if ((MP = mt->memptr()) && ! 5581: e==Pexpr(1) && ! 5582: last_il->tp->base == PTR) { ! 5583: if(i==1) lst=0; ! 5584: } ! 5585: else e = next_elem(); ! 5586: ! 5587: if (e == 0) return; //break; ! 5588: ! 5589: if( ! 5590: mt->base == FIELD ! 5591: && ! 5592: m->string[0]=='_' ! 5593: && ! 5594: m->string[1]=='_' ! 5595: && ! 5596: m->string[2]=='F' // unnamed bitfield ! 5597: ) { ! 5598: e = insert_init(zero); ! 5599: } ! 5600: ! 5601: //error('d',"mtz%n: %d",m,mt->base); ! 5602: switch (mt->base) { ! 5603: case CLASS: ! 5604: case ENUM: ! 5605: break; ! 5606: case VEC: ! 5607: case COBJ: ! 5608: list_check(nn,m->tp,e); ! 5609: break; ! 5610: case PTR: ! 5611: if (MP && e==Pexpr(1)) { ! 5612: if (mt->check(last_il->tp,ASSIGN)) ! 5613: error("badIrT for%n:%t (%tX)",m,last_il->tp,mt); ! 5614: skip_ilist(); ! 5615: break; ! 5616: } ! 5617: if (MP && e && e->base==ZERO) { ! 5618: *curr_e = new expr(ELIST,zero,zero); ! 5619: *curr_e = new expr(ILIST,*curr_e,zero); ! 5620: (*curr_e)->tp = zero_type; ! 5621: break; ! 5622: } ! 5623: if (MP && e && e->tp->base==OVERLOAD) { ! 5624: Pexpr op = ptof(Pfct(Pptr(mt)->typ),e,tbl); ! 5625: if(op) { ! 5626: *curr_e = op; ! 5627: break; ! 5628: } ! 5629: } ! 5630: // no break ! 5631: default: ! 5632: { if (e == Pexpr(1)) { ! 5633: error("unexpectedIrL"); ! 5634: goto dd; ! 5635: } ! 5636: ! 5637: if (mt->check(e->tp,ASSIGN)) ! 5638: error("badIrT for%n:%t (%tX)",m,e->tp,m->tp); ! 5639: ! 5640: if(MP && e && e->base==CAST) ! 5641: *curr_e = e->e1; ! 5642: ! 5643: Pptr p; ! 5644: if (mt->check(e->tp,0) ! 5645: && (p=mt->is_ptr()) ! 5646: && Ptype(p)!=zero_type ! 5647: && p->typ!=char_type) ! 5648: *curr_e = new cast(mt,e); ! 5649: } ! 5650: } ! 5651: } ! 5652: if (lst && (e=next_elem()) ) error("end ofIrLX afterCO"); ! 5653: break; ! 5654: } ! 5655: default: ! 5656: e = next_elem(); ! 5657: ! 5658: if (e == 0) { ! 5659: error("noIr forO"); ! 5660: break; ! 5661: } ! 5662: ! 5663: if (e == Pexpr(1)) { ! 5664: error("unexpectedIrL"); ! 5665: break; ! 5666: } ! 5667: //error('d',"t %t e->tp %t",t,e->tp); ! 5668: if (t->check(e->tp,ASSIGN)) error("badIrT for%n:%t (%tX)",nn,e->tp,t); ! 5669: Pptr p; ! 5670: if (t->check(e->tp,0) ! 5671: && (p=t->is_ptr()) ! 5672: && Ptype(p)!=zero_type ! 5673: && p->typ!=char_type) ! 5674: *curr_e = new cast(t,e); ! 5675: if (lst && (e=next_elem()) ) error("end ofIrLX afterO"); ! 5676: break; ! 5677: } ! 5678: } ! 5679: ! 5680: int ! 5681: is_anon(char* string) { ! 5682: // error('d',"is_anon: %s", string ); ! 5683: if ( string == 0 ) ! 5684: return 0; ! 5685: ! 5686: if ( string[0]=='_' && string[1]=='_' && ! 5687: (string[2]=='C' || string[2]=='E')) ! 5688: return 1; ! 5689: return 0; ! 5690: } ! 5691: ! 5692: Pname dclass(Pname n, Ptable tbl) ! 5693: { ! 5694: Pclass cl; ! 5695: Pbase bt; ! 5696: Pname bn; ! 5697: Pname ntbl = tbl->t_name; ! 5698: Ptype ntp = 0; ! 5699: TOK tscope; ! 5700: ! 5701: Pname nx = ktbl->look(n->string,0); // TNAME ! 5702: if (ntbl && ntbl->tp) ntp = ntbl->tp; ! 5703: ! 5704: tscope = ntp&&ntp->base==CLASS?NESTED:(n->lex_level?LOCAL:HIDDEN); ! 5705: ! 5706: DB( if(Ddebug>=1) error( 'd', &n->where, "dclass n %n %d nx %d", n,n->lex_level, nx); ); ! 5707: // error( 'd', &n->where, "dclass n %n ll %d nx %d tbl: %n", n,n->lex_level, nx, tbl->t_name); ! 5708: if (nx == 0 || n->lex_level || ! 5709: ntp && is_anon(n->string) == 0 && ntp->base == CLASS ! 5710: && (ktbl->look(n->string,tscope))) ! 5711: { ! 5712: if ( nx && ntp && ntp->base == CLASS ) { ! 5713: bt = (Pbase)nx->tp; ! 5714: bn = bt->b_name; ! 5715: cl = bn ? (Pclass)bn->tp : 0; ! 5716: if (cl && cl->lcl && ! 5717: strcmp(cl->lcl,"FUDGE007")==0) ! 5718: goto bbb; ! 5719: else { bt=0; bn=0; cl=0; } ! 5720: } ! 5721: ! 5722: int tn = 0; ! 5723: for (nx=ktbl->look(n->string,tscope); nx; nx=nx->n_tbl_list) ! 5724: { ! 5725: if (nx->n_key != tscope) continue; ! 5726: if (tscope==LOCAL && ! 5727: nx->lex_level != n->lex_level ) continue; ! 5728: ! 5729: if (nx->tp->base != COBJ) { ! 5730: tn = 1; ! 5731: continue; ! 5732: } ! 5733: ! 5734: bt = (Pbase)nx->tp; ! 5735: bn = bt->b_name; ! 5736: cl = (Pclass)bn->tp; ! 5737: ! 5738: if (cl == 0) continue; ! 5739: ! 5740: // is this class nested within class table? ! 5741: if (tscope==NESTED && ! 5742: strcmp(ntbl->string,cl->in_class->string)) ! 5743: continue; ! 5744: else ! 5745: if ( tscope==LOCAL && ! 5746: (cl->lcl==0 || strcmp(cl->lcl,Pclass(n->tp)->lcl))) ! 5747: continue; ! 5748: ! 5749: goto bbb; ! 5750: } ! 5751: ! 5752: if (tn) ! 5753: error("%n redefined using Tdef",n); ! 5754: else ! 5755: error('i',"%n is not aCN",n); ! 5756: } ! 5757: else { ! 5758: bt = Pbase(nx->tp); // COBJ ! 5759: if ( bt->base != COBJ ) { ! 5760: error("%n redefined using typedef",n); ! 5761: Pname tn = ktbl->look(n->string,HIDDEN); ! 5762: if ( tn->tp->base == COBJ ) ! 5763: bt = Pbase(tn->tp); ! 5764: else error('i',"%n is not a CN", n ); ! 5765: } ! 5766: bn = bt->b_name; ! 5767: } ! 5768: bbb: ! 5769: bn->where = nx->where; ! 5770: Pname bnn = tbl->insert(bn,CLASS); // copy for member lookup ! 5771: cl = Pclass(bn->tp); ! 5772: ! 5773: if (cl->class_base == template_class) ! 5774: error("C%n defined previously asYC", bn); ! 5775: ! 5776: if (cl->defined&(DEFINED|SIMPLIFIED)) ! 5777: error("C%n defined twice",n); ! 5778: else { ! 5779: if (bn->n_scope == ARG) bn->n_scope = ARGT; ! 5780: cl->dcl(bn,tbl); ! 5781: } ! 5782: n->tp = cl; ! 5783: return bnn; ! 5784: } ! 5785: ! 5786: Pname denum(Pname n, Ptable tbl) ! 5787: { ! 5788: Penum en; ! 5789: Pbase bt; ! 5790: Pname bn; ! 5791: Pname ntbl = tbl->t_name; ! 5792: Ptype ntp = 0; ! 5793: TOK tscope; ! 5794: ! 5795: Pname nx = ktbl->look(n->string,0); // TNAME ! 5796: if (ntbl && ntbl->tp) ntp = ntbl->tp; ! 5797: ! 5798: // note: ***** add for local enumeration declaration ! 5799: // error( 'd', &n->where, "denum n %n ll %d nx %d tbl: %n", n,n->lex_level, nx, tbl->t_name); ! 5800: if (nx == 0 || /* n->lex_level ||*/ ! 5801: ntp && is_anon(n->string)==0 && ntp->base == CLASS ) ! 5802: { ! 5803: int tn = 0; ! 5804: tscope = ntp&&ntp->base==CLASS?NESTED:(/*n->lex_level?LOCAL:*/HIDDEN); ! 5805: for (nx=ktbl->look(n->string,tscope); nx; nx=nx->n_tbl_list) ! 5806: { ! 5807: if (nx->n_key != tscope) continue; ! 5808: // if (tscope==LOCAL && ! 5809: // nx->lex_level != n->lex_level ) continue; ! 5810: ! 5811: bt = (Pbase)nx->tp; ! 5812: bn = bt->b_name; ! 5813: en = (Penum)bn->tp; ! 5814: ! 5815: // is this class nested within class table? ! 5816: if (tscope==NESTED && en->in_class && ! 5817: strcmp(ntbl->string,en->in_class->string)) ! 5818: continue; ! 5819: } ! 5820: } ! 5821: else { ! 5822: bt = (Pbase)nx->tp; ! 5823: bn = bt->b_name; ! 5824: en = (Penum)bn->tp; ! 5825: } ! 5826: ! 5827: Pname bnn = tbl->insert(bn,CLASS); ! 5828: if (en->defined&(DEFINED|SIMPLIFIED)) ! 5829: error("enum%n defined twice",n); ! 5830: else { ! 5831: if (bn->n_scope == ARG) bn->n_scope = ARGT; ! 5832: en->dcl(bn,tbl); ! 5833: } ! 5834: n->tp = en; ! 5835: return bnn; ! 5836: } ! 5837: ! 5838: static int ! 5839: is_probably_temp( char *str ) ! 5840: { ! 5841: // error( 'd', "is_probably_temp( %s )", str ); ! 5842: ! 5843: if ( str[0] != '_' || str[1] != '_' ) ! 5844: return 0; ! 5845: ! 5846: switch (str[2]) { ! 5847: default: ! 5848: return 0; ! 5849: case 'A': case 'C': case 'D': case 'E': case 'F': ! 5850: case 'I': case 'K': case 'L': case 'M': case 'N': ! 5851: case 'Q': case 'R': case 'S': case 'T': case 'U': ! 5852: case 'V': case 'W': case 'X': ! 5853: return 1; ! 5854: } ! 5855: ! 5856: } ! 5857: ! 5858: static void ! 5859: check_for_local( Pexpr ee ) ! 5860: { ! 5861: static Pname n[2] = {0,0}; // try not to flag multiple errors ! 5862: static index = 0; ! 5863: ! 5864: if ( ee==0 ) return; ! 5865: ! 5866: // error('d', "check_for_local( %k ) e1: %d e2: %d", ee->base, ee->e1, ee->e2); ! 5867: ! 5868: switch ( ee->base ) { ! 5869: case NAME: ! 5870: { ! 5871: Pname nn = Pname(ee); ! 5872: if ((nn->n_scope==FCT || nn->n_scope==ARG) ! 5873: && is_probably_temp(nn->string) == 0 ! 5874: && n[0]!=nn && n[1]!=nn) ! 5875: { ! 5876: error("local%n used as defaultA", nn ); ! 5877: n[index] = nn; ! 5878: index = index==0?1:0; ! 5879: } ! 5880: // no break; ! 5881: } ! 5882: case TNAME: case STRING: case IVAL: ! 5883: case ICON: case CCON: case FCON: ! 5884: case ZERO: case DUMMY: case SIZEOF: ! 5885: return; ! 5886: case QUEST: ! 5887: check_for_local( ee->cond ); ! 5888: break; ! 5889: case MDOT: ! 5890: check_for_local( ee->mem ); ! 5891: return; ! 5892: } ! 5893: ! 5894: check_for_local( ee->e1 ); ! 5895: check_for_local( ee->e2 ); ! 5896: } ! 5897: ! 5898: void dargs(Pname, Pfct f, Ptable tbl) ! 5899: { ! 5900: int argnamesize = 0; // if +a1, make sure arg names can be printed ! 5901: int oo = const_save; ! 5902: const_save = 1; ! 5903: if ( ansi_opt ) { ! 5904: Pname th = f->f_this; ! 5905: if ( th && th->string ) argnamesize += strlen(th->string) + 1; ! 5906: th = f->f_result; ! 5907: if ( th && th->string ) argnamesize += strlen(th->string) + 1; ! 5908: } ! 5909: ! 5910: for (Pname a=f->argtype; a; a=a->n_list) { ! 5911: Pexpr init; ! 5912: ! 5913: if (a->tp == 0) { ! 5914: error( "A has noT" ); ! 5915: a->tp = any_type; ! 5916: continue; ! 5917: } ! 5918: if (ansi_opt && a->string) argnamesize += strlen(a->string) + 1; ! 5919: ! 5920: Pname cln = a->tp->is_cl_obj(); ! 5921: //error('d',"dargs %t",a->tp); ! 5922: if (cln && Pclass(cln->tp)->has_itor()) // mark X(X&) arguments ! 5923: a->n_xref = 1; ! 5924: else { ! 5925: Ptype t = a->tp; ! 5926: while (t->base == TYPE) t = Pbase(t)->b_name->tp; ! 5927: if (t->base == FCT) a->tp = new ptr(PTR,a->tp); ! 5928: } ! 5929: ! 5930: // if (init = a->n_initializer) { // default argument ! 5931: if ( a->n_key != NESTED && ! 5932: (init = a->n_initializer)) { // default argument ! 5933: Pptr pt; ! 5934: if (init == dummy) { ! 5935: error("emptyIr"); ! 5936: a->n_initializer = 0; ! 5937: continue; ! 5938: } ! 5939: if (cln) { ! 5940: if (init->base==VALUE) { ! 5941: switch (init->tp2->base) { ! 5942: case CLASS: ! 5943: if (Pclass(init->tp2)!=Pclass(cln->tp)) goto inin2; ! 5944: break; ! 5945: default: ! 5946: Pname n2 = init->tp2->is_cl_obj(); ! 5947: if (n2==0 || Pclass(n2->tp)!=Pclass(cln->tp)) goto inin2; ! 5948: } ! 5949: ! 5950: a->n_initializer = init = 0; ! 5951: error('s',"K as defaultA"); ! 5952: } ! 5953: else { ! 5954: inin2: ! 5955: if (init->base == ILIST) error("list as AIr"); ! 5956: Pexpr i = init->typ(tbl); ! 5957: init = class_init(a,a->tp,i,tbl); ! 5958: if (i!=init && init->base==DEREF) { ! 5959: error('s',"K needed forAIr"); ! 5960: init = 0; ! 5961: } ! 5962: else { ! 5963: dosimpl(init,cc->nof); ! 5964: // init->simpl(); ! 5965: init->permanent = 2; ! 5966: } ! 5967: a->n_initializer = init; ! 5968: } ! 5969: } ! 5970: else if (pt = a->tp->is_ref()) { ! 5971: ref_initializer++; ! 5972: init = init->typ(tbl); ! 5973: ref_initializer--; ! 5974: int tcount = stcount; ! 5975: init = ref_init(pt,init,tbl); ! 5976: if (tcount != stcount) { ! 5977: error('s',"needs temporaryV to evaluateAIr"); ! 5978: init = 0; ! 5979: } ! 5980: else { ! 5981: dosimpl(init,cc->nof); ! 5982: // init->simpl(); ! 5983: init->permanent = 2; ! 5984: } ! 5985: a->n_initializer = init; ! 5986: } ! 5987: else { ! 5988: Pptr p = a->tp->is_ptr(); ! 5989: init = init->typ(tbl); ! 5990: if (p) init = ptr_init(p,init,tbl); ! 5991: ! 5992: if (a->tp->check(init->tp,ARG)) { ! 5993: int i = can_coerce(a->tp,init->tp); ! 5994: ! 5995: switch (i) { ! 5996: case 1: ! 5997: if (Ncoerce) { ! 5998: Pname cn = init->tp->is_cl_obj(); ! 5999: Pname xx = new name(Ncoerce->string); ! 6000: Pref r = new ref(DOT,init,xx); ! 6001: init = new expr(G_CALL,r,0); ! 6002: init = init->typ(tbl); ! 6003: } ! 6004: break; ! 6005: default: ! 6006: error("%d possible conversions for defaultA",i); ! 6007: case 0: ! 6008: error("badIrT%t forA%n (%tX)",init->tp,a,a->tp); ! 6009: DEL(init); ! 6010: a->n_initializer = init = 0; ! 6011: } ! 6012: } ! 6013: ! 6014: if (init) { ! 6015: dosimpl(init,cc->nof); ! 6016: // init->simpl(); ! 6017: init->permanent = 2; ! 6018: a->n_initializer = init; ! 6019: Neval = 0; ! 6020: long i = init->eval(); ! 6021: if (Neval == 0) { ! 6022: a->n_evaluated = 1; ! 6023: a->n_val = i; ! 6024: } ! 6025: } ! 6026: } ! 6027: if ( a->n_initializer ) ! 6028: check_for_local(a->n_initializer); ! 6029: } ! 6030: } ! 6031: if ( ansi_opt && argnamesize ) { ! 6032: char* ps = new char[ argnamesize ]; ! 6033: Pname a = f->f_this; ! 6034: if ( a && a->string ) { ! 6035: int i = strlen(a->string) + 1; ! 6036: if ( (argnamesize -= i) < 0 ) goto bad; ! 6037: strcpy(ps,a->string); ! 6038: a->string = ps; ! 6039: ps += i; ! 6040: } ! 6041: a = f->f_result; ! 6042: if ( a && a->string ) { ! 6043: int i = strlen(a->string) + 1; ! 6044: if ( (argnamesize -= i) < 0 ) goto bad; ! 6045: strcpy(ps,a->string); ! 6046: a->string = ps; ! 6047: ps += i; ! 6048: } ! 6049: for ( a = f->argtype; a; a = a->n_list ) { ! 6050: if ( a->string == 0 ) continue; ! 6051: int i = strlen(a->string) + 1; ! 6052: if ( (argnamesize -= i) < 0 ) goto bad; ! 6053: strcpy(ps,a->string); ! 6054: a->string = ps; ! 6055: ps += i; ! 6056: } ! 6057: if ( argnamesize ) bad:error('i',"bad argN size for%t",f); ! 6058: } ! 6059: const_save = oo; ! 6060: } ! 6061: ! 6062: void merge_init(Pname nn, Pfct f, Pfct nf) ! 6063: { ! 6064: // Pname a1 = f->f_args; if (a1==0) a1 = f->argtype; ! 6065: // Pname a2 = nf->f_args;//nf->argtype; ! 6066: Pname a1 = f->argtype; ! 6067: Pname a2 = nf->argtype; ! 6068: ! 6069: for (; a1; a1=a1->n_list, a2=a2->n_list) { ! 6070: int i1 = a1->n_initializer || a1->n_evaluated; ! 6071: int i2 = a2->n_initializer || a2->n_evaluated; ! 6072: ! 6073: if (i1 && i2) error(&a1->where,"twoIrs for%nA%n",nn,a1); ! 6074: ! 6075: if (i1) { ! 6076: a2->n_initializer = a1->n_initializer; ! 6077: a2->n_evaluated = a1->n_evaluated; ! 6078: a2->n_val = a1->n_val; ! 6079: } ! 6080: if (i2) { ! 6081: a1->n_initializer = a2->n_initializer; ! 6082: a1->n_evaluated = a2->n_evaluated; ! 6083: a1->n_val = a2->n_val; ! 6084: } ! 6085: ! 6086: } ! 6087: } ! 6088: ! 6089: Pexpr try_to_coerce(Ptype rt, Pexpr e, char* s, Ptable tbl) ! 6090: /* ! 6091: ``e'' is of class ``cn'' coerce it to type ``rt'' ! 6092: */ ! 6093: { ! 6094: int i; ! 6095: Pname cn; ! 6096: //error('d',"try_to_coerce(%t, %t, %s, %d)",rt,e->tp,s,tbl); ! 6097: ! 6098: if ((cn=e->tp->is_cl_obj()) && (i=can_coerce(rt,e->tp)) && Ncoerce) { ! 6099: if (1 < i) error("%d possible conversions for %s",i,s); ! 6100: //error('d',"coerce %n",Ncoerce); ! 6101: Pclass cl = Pclass(cn->tp); ! 6102: // Pref r = new ref(DOT,e,Ncoerce); ! 6103: // Pexpr rr = r->typ(tbl); ! 6104: // Pexpr c = new expr(G_CALL,rr,0); ! 6105: // c->fct_name = Ncoerce; ! 6106: Pname xx = new name(Ncoerce->string); ! 6107: Pref r = new ref(DOT,e,xx); ! 6108: Pexpr c = new expr(G_CALL,r,0); ! 6109: // return c->typ(tbl); ! 6110: c = c->typ(tbl); ! 6111: //error('d',"coerce -> %k %t",c->base,c->tp); ! 6112: return c; ! 6113: } ! 6114: //error('d',"coerce ->0"); ! 6115: return 0; ! 6116: } ! 6117: ! 6118: int in_class_dcl; ! 6119: ! 6120: Pname name::dofct(Ptable tbl, TOK scope) ! 6121: { ! 6122: Pfct f = Pfct(tp); ! 6123: Pname class_name; ! 6124: Ptable etbl; ! 6125: in_class_dcl = cc->not!=0; ! 6126: int just_made = 0; ! 6127: // int fvirt = 0; //BSopt ! 6128: DB( if(Ddebug>=1) error('d',"dofct %n %d %t %s",this,tp,tp,tbl==gtbl?"global":""); ); ! 6129: // error( 'd', "%n->dofct(): n_initializer: %d f->f_virtual: %d", this, n_initializer, f->f_virtual); ! 6130: ! 6131: if (f->f_inline) n_sto = STATIC; ! 6132: ! 6133: if (n_stclass) ! 6134: switch (n_stclass) { ! 6135: case EXTERN: ! 6136: case STATIC: ! 6137: case OVERLOAD: ! 6138: break; ! 6139: default: ! 6140: error("%n declared%k",this,n_stclass); ! 6141: n_stclass = EXTERN; ! 6142: } ! 6143: ! 6144: tp->dcl(tbl); // must be done before the type check ! 6145: ! 6146: if (n_qualifier) { // qualified name: c::f() checked above ! 6147: class_name = Pbase(n_qualifier->tp)->b_name; ! 6148: etbl = Pclass(class_name->tp)->memtbl; ! 6149: ! 6150: if (f->f_virtual) { ! 6151: error("virtual specifier illegal outsideCD(%n::%s())",class_name,this->string); ! 6152: f->f_virtual = 0; ! 6153: } ! 6154: ! 6155: ! 6156: if (n_sto ! 6157: && n_sto!=FRIEND // friend X::f(); ! 6158: && f->f_inline==0) { // inline causes n_sto==STATIC ! 6159: error("%k specified for QdN%n",n_sto,this); ! 6160: n_sto = 0; ! 6161: } ! 6162: } ! 6163: else { ! 6164: class_name = cc->not; ! 6165: ! 6166: // beware of local function declarations in member functions ! 6167: if (class_name && tbl!=cc->cot->memtbl) { ! 6168: class_name = 0; ! 6169: in_class_dcl = 0; ! 6170: } ! 6171: ! 6172: if (f->f_static && f->f_virtual) { ! 6173: error("virtual staticM"); ! 6174: f->f_virtual = 0; ! 6175: } ! 6176: ! 6177: if (n_oper) check_oper(class_name); ! 6178: etbl = tbl; ! 6179: } ! 6180: ! 6181: // Pfct(tp)->memof = class_name ? Pclass(class_name->tp) : 0; ! 6182: ! 6183: if (class_name) { ! 6184: Pclass cl; ! 6185: f->memof = cl = Pclass(class_name->tp); ! 6186: if (f->f_virtual==0 && find_virtual(f->memof,this)) ! 6187: f->f_virtual = VTOK; ! 6188: //error('d',"class_name: %s fct: %s virtual: %d", class_name->string, string, f->f_virtual ); ! 6189: ! 6190: if (f->f_static && f->f_virtual) { ! 6191: error("virtual staticM"); ! 6192: f->f_virtual = 0; ! 6193: } ! 6194: ! 6195: if ( cl->csu == UNION && f->f_virtual ) // don't worry about ANON ! 6196: error( "%n: cannot declare a virtualFWin union", this ); ! 6197: } ! 6198: ! 6199: if(f->f_const && f->memof==0) { ! 6200: error("onlyMFs can be constant"); ! 6201: } ! 6202: ! 6203: if (etbl==0 || etbl->base!=TABLE) error('i',"N::dcl: etbl=%d",etbl); ! 6204: ! 6205: switch (n_oper) { ! 6206: case CTOR: ! 6207: if (f->f_virtual) { ! 6208: error("virtualK"); ! 6209: f->f_virtual = 0; ! 6210: } ! 6211: ! 6212: // case DTOR: ! 6213: // f->f_const = 1; ! 6214: break; ! 6215: ! 6216: case REF: ! 6217: if (f->argtype) ! 6218: error("%n takes no argument",this); ! 6219: else if (f->returns->is_ptr() == 0) { ! 6220: Pname cn = f->returns->is_cl_obj(); ! 6221: if (cn==0 && f->returns->base==RPTR) cn = Pptr(f->returns)->typ->is_cl_obj(); ! 6222: if (cn==0 || Pclass(cn->tp)->has_oper(REF)==0) { ! 6223: if ( cn && class_name && // B B::operator->(); ! 6224: strcmp(cn->string, class_name->string)==0 ) ! 6225: error("%s::%n cannot return aR orCO ofC%n",cn->string,this,cn); ! 6226: else error("%n must return aP toCO, aR toCO, or aCO",this); ! 6227: tp = any_type; // suppress further checking ! 6228: } ! 6229: } ! 6230: break; ! 6231: ! 6232: case NEW: // void* operator new(long) ! 6233: if (f->f_virtual) ! 6234: error("virtual%n (operator new() is static)",this); ! 6235: if (class_name) f->f_static = 1; // if member: static by default ! 6236: if (f->nargs_known != 1) ! 6237: error("ATs must be fully specified for%n",this); ! 6238: else if (f->nargs<1) ! 6239: error("%n requires a firstA ofT size_t",this); ! 6240: else if (f->argtype->tp->check(size_t_type,0)) { ! 6241: if (strict_opt==0 ! 6242: && ( f->argtype->tp->check(long_type,0)==0 || ! 6243: f->argtype->tp->check(ulong_type,0)==0)) { ! 6244: error('w',"%n firstA should be size_t (anachronism)",this); ! 6245: f->argtype->tp = size_t_type; ! 6246: if (f->f_signature) f->sign(); ! 6247: } ! 6248: else ! 6249: error("%n requires a firstA ofT size_t",this); ! 6250: } ! 6251: else { ! 6252: Ptype t = f->s_returns ? f->s_returns : f->returns; ! 6253: if (t->check(Pvoid_type,0)) error("bad returnT for %n",this); ! 6254: } ! 6255: break; ! 6256: ! 6257: case DELETE: // void operator delete(void*) or ! 6258: // void operator delete(void*, long) ! 6259: if (f->f_virtual) ! 6260: error("virtual%n (operator delete() is static)",this); ! 6261: if (class_name) f->f_static = 1; // if member: static by default ! 6262: if (f->nargs_known != 1) ! 6263: error("ATs must be fully specified for%n",this); ! 6264: else { ! 6265: Ptype t = f->s_returns ? f->s_returns : f->returns; ! 6266: if (t->base != VOID) ! 6267: error("bad returnT for %n", this); ! 6268: else { ! 6269: switch (f->nargs) { ! 6270: default: ! 6271: error("%n takes 1 or 2As",this); ! 6272: break; ! 6273: case 1: ! 6274: case 2: ! 6275: { Pname a = f->argtype; ! 6276: if (a->tp->check(Pvoid_type,0)) ! 6277: error("%n's 1stA must be a void*",this); ! 6278: else if (a = a->n_list) { ! 6279: if (class_name == 0) ! 6280: error("%n takes only oneA",this); ! 6281: else if (a->tp->check(size_t_type,0)) { ! 6282: if (strict_opt==0 ! 6283: && a->tp->check(long_type,0)==0) { ! 6284: error('w',"%n's 2ndA should be a size_t (anachronism)",this); ! 6285: a->tp = size_t_type; ! 6286: if (f->f_signature) f->sign(); ! 6287: } ! 6288: else ! 6289: error("%n's 2ndA must be a size_t",this); ! 6290: } ! 6291: } ! 6292: } ! 6293: } ! 6294: } ! 6295: } ! 6296: break; ! 6297: ! 6298: case ASSIGN: ! 6299: if (class_name && f->nargs==1) { ! 6300: Ptype t = f->argtype->tp; ! 6301: Pname an = t->is_cl_obj(); // X::operator=(X) ? ! 6302: if (an==0 && (t=t->is_ref())) { // X::operator=(X&) ? ! 6303: t = Pptr(t)->typ; ! 6304: rx1: ! 6305: switch (t->base) { ! 6306: case TYPE: t = Pbase(t)->b_name->tp; goto rx1; ! 6307: case COBJ: an = Pbase(t)->b_name; ! 6308: } ! 6309: } ! 6310: if (an && an==class_name) Pclass(an->tp)->c_xref |= C_ASS; ! 6311: } ! 6312: else if (f->nargs == 2) { ! 6313: Ptype t = f->argtype->tp; ! 6314: Pname an1; ! 6315: if (t=t->is_ref()) { // operator=(X&,?) ? ! 6316: t = Pptr(t)->typ; ! 6317: rx2: ! 6318: switch (t->base) { ! 6319: case TYPE: t = Pbase(t)->b_name->tp; goto rx2; ! 6320: case COBJ: an1 = Pbase(t)->b_name; ! 6321: } ! 6322: } ! 6323: t = f->argtype->n_list->tp; ! 6324: Pname an2 = t->is_cl_obj(); // operator=(X&,X) ? ! 6325: if (an2==0 && (t=t->is_ref())) { // operator=(X&,X&) ? ! 6326: t = Pptr(t)->typ; ! 6327: rx3: ! 6328: switch (t->base) { ! 6329: case TYPE: t = Pbase(t)->b_name->tp; goto rx3; ! 6330: case COBJ: an2 = Pbase(t)->b_name; ! 6331: } ! 6332: } ! 6333: if (an1 && an1==an2) Pclass(an1->tp)->c_xref |= C_ASS; ! 6334: } ! 6335: } ! 6336: ! 6337: switch (scope) { ! 6338: case FCT: ! 6339: case ARG: ! 6340: if (n_sto == STATIC) error("D of staticF in aF"); ! 6341: else { // detect local re-definition ! 6342: Pname nx = gtbl->look(string,0); ! 6343: if (nx) { ! 6344: switch (nx->tp->base) { ! 6345: case FCT: ! 6346: if (tp->check(nx->tp,0)) ! 6347: error('w',"%n has been locally re-declared as%t",this,tp); ! 6348: else { ! 6349: if(Pfct(nx->tp)->f_signature==0) ! 6350: Pfct(nx->tp)->sign(); ! 6351: if (Pfct(tp)->f_signature == 0) ! 6352: Pfct(tp)->sign(); ! 6353: if ( strcmp(Pfct(nx->tp)->f_signature,Pfct(tp)->f_signature)) ! 6354: error('w',"%n of type %t has been locally re-declared with different linkage",this,tp); ! 6355: } ! 6356: break; ! 6357: case OVERLOAD: ! 6358: { Pname ny = Pgen(nx->tp)->find(f,0); ! 6359: if (ny == 0) ! 6360: error('w',"overloadedF%n has been locally declared as%t",this,tp); ! 6361: else { ! 6362: if(Pfct(ny->tp)->f_signature==0) ! 6363: Pfct(ny->tp)->sign(); ! 6364: if (Pfct(tp)->f_signature == 0) ! 6365: Pfct(tp)->sign(); ! 6366: if (strcmp(Pfct(ny->tp)->f_signature,Pfct(tp)->f_signature)) ! 6367: error('w',"overloadedF%n of type %t has been locally re-declared with different linkage",this,tp); ! 6368: } ! 6369: } ! 6370: break; ! 6371: } // switch nx->base ! 6372: } // if nx ! 6373: } // else ! 6374: } // switch scope ! 6375: ! 6376: Pname nn = etbl->insert(this,0); ! 6377: if ( f->body ) nn->where = where; ! 6378: nn->assign(); ! 6379: n_table = etbl; ! 6380: //error('d',"%n->dofct(): n_initializer:%d f->f_virtual:%d",this,n_initializer,f->f_virtual); ! 6381: if (n_initializer) { ! 6382: if (f->f_virtual == 0) error("Ir for non-virtualF%n",this); ! 6383: if (n_initializer != zero) error("virtualFIr must be 0"); ! 6384: } ! 6385: ! 6386: if (Nold) { ! 6387: Pfct nf = Pfct(nn->tp); ! 6388: // error('d',"old %n: %t and %t",nn,nf,tp); ! 6389: int flag = 0; ! 6390: Pname af=0,anf=0; ! 6391: if (nf->base==ANY || f->base==ANY) ! 6392: ; // wild card -- do nothing ! 6393: else ! 6394: if (nf->base == OVERLOAD) { ! 6395: string = nn->string; ! 6396: nn = Pgen(nf)->add(this); ! 6397: ! 6398: if (Nold == 0) { ! 6399: if (f->body && n_qualifier) { ! 6400: error("badAL for%n",this); ! 6401: return 0; ! 6402: } ! 6403: goto thth; ! 6404: } ! 6405: // else { ! 6406: // if (f->body==0 && friend_in_class==0) error('w',"%n redeclared",nn); ! 6407: // } ! 6408: nf = Pfct(nn->tp); ! 6409: if (f->body && nf->body) { ! 6410: // Preserve the original definition ! 6411: // in the case of a PT class; i.e, ! 6412: // the one supplied by the user ! 6413: if (!(class_name && ! 6414: (Pclass(class_name->tp)->class_base == ! 6415: instantiated_template_class) && ! 6416: nn->n_redefined)) ! 6417: { ! 6418: error("two definitions of%n",nn); ! 6419: f->body = 0; ! 6420: } ! 6421: return 0; ! 6422: } ! 6423: if (f->body) goto bdbd; ! 6424: goto stst; ! 6425: } ! 6426: else if (nf->base != FCT) { ! 6427: error("%n declared both as%t and asF",this,nf); ! 6428: f->body = 0; ! 6429: } ! 6430: else { ! 6431: // error('d',"%t->check(%t) -> %d %d",nf,f,nf->check(f,OVERLOAD)); ! 6432: if (nf->check(f,OVERLOAD) || const_problem) { ! 6433: if (f->body && n_qualifier) { ! 6434: error("%nT mismatch: %t and %t",nn,nf,f); ! 6435: return 0; ! 6436: } ! 6437: Pgen g = new gen; ! 6438: add_first = 1; ! 6439: Pname n1 = g->add(nn); ! 6440: add_first = 0; ! 6441: string = nn->string; ! 6442: Pname n2 = g->add(this); ! 6443: nn->tp = g; ! 6444: nn = n2; ! 6445: goto thth; ! 6446: } ! 6447: ! 6448: af = f->argtype; ! 6449: anf = nf->argtype; ! 6450: for (; af && anf; af=af->n_list,anf=anf->n_list) { ! 6451: Ptype at = af->tp; ! 6452: Ptype atp = anf->tp; ! 6453: if(!exact1(af,atp)) break; ! 6454: if(at->base!=PTR || ! 6455: Pptr(at)->rdo == Pptr(atp)->rdo) continue; ! 6456: int k = Pptr(at)->typ->tconst(); ! 6457: int l = Pptr(atp)->typ->tconst(); ! 6458: if(k==l) flag=1; ! 6459: } ! 6460: if ( flag && !af && !anf) { ! 6461: error("the overloading mechanism cannot tell a%t from a%t",nf,f); ! 6462: } ! 6463: ! 6464: if (in_class_dcl) { ! 6465: // error("twoDs of%n",this); ! 6466: // f->body = 0; ! 6467: // return 0; ! 6468: } ! 6469: else if (nf->f_static && f->f_inline==0 && n_sto==STATIC) { ! 6470: //error('d',"MF%n declared static outsideF",this); ! 6471: n_sto = 0; ! 6472: } ! 6473: else if (n_sto && n_sto!=nn->n_scope) { ! 6474: if (n_sto==EXTERN && nn->n_scope==STATIC) ! 6475: error('w',"%n declared extern after being declared static",this); ! 6476: else if (nf->f_inline==0 && f->f_inline==0) { ! 6477: if (nn->tp==new_fct->tp || nn->tp==del_fct->tp) ! 6478: nn->n_sto = n_sto; ! 6479: else ! 6480: error("%n declared as both%k and%k",this,n_sto,(nn->n_sto)?nn->n_sto:EXTERN); ! 6481: } ! 6482: } ! 6483: ! 6484: //error('d',"fct %n: %k %k scope %k",this,n_sto,nn->n_sto,nn->n_scope); ! 6485: //error('d',"link %d lcount %d sig %s",linkage,lcount,nf->f_signature); ! 6486: ! 6487: { ! 6488: Linkage l1 = nf->f_linkage; ! 6489: Linkage l2 = f->f_linkage; ! 6490: if ( l2!=linkage_default && l1!=l2) ! 6491: error("inconsistent linkage specifications for%n",this); ! 6492: } ! 6493: if (nf->body && f->body) { ! 6494: // Preserve the original definition ! 6495: // in the case of a PT class; i.e, ! 6496: // the one supplied by the user ! 6497: if (!(class_name && ! 6498: (Pclass(class_name->tp)->class_base == ! 6499: instantiated_template_class) && ! 6500: nn->n_redefined)) ! 6501: { ! 6502: error("two definitions of%n",this); ! 6503: f->body = 0; ! 6504: } ! 6505: return 0; ! 6506: } ! 6507: ! 6508: if (f->body) goto bdbd; ! 6509: ! 6510: goto stst; ! 6511: ! 6512: bdbd: ! 6513: // error('d',"nn %n init: %d f_virt: %d f->body: %d", nn,nn->n_initializer,nf->f_virtual,f->body); ! 6514: if (f->nargs_known && nf->nargs_known) merge_init(nn,f,nf); ! 6515: f->f_virtual = nf->f_virtual; ! 6516: f->f_this = nf->f_this; ! 6517: f->f_result = nf->f_result; ! 6518: f->s_returns = nf->s_returns; ! 6519: f->f_args = nf->f_args; ! 6520: // f->argtype = nf->argtype; ! 6521: f->f_signature = nf->f_signature; ! 6522: f->f_const = nf->f_const; ! 6523: f->f_static = nf->f_static; ! 6524: nn->tp = f; ! 6525: if (f->f_inline) { ! 6526: if (nf->f_inline==0) { ! 6527: if (nn->n_used && nn->n_sto!=STATIC) ! 6528: error("%n declared with external linkage and called before defined as inline",nn); ! 6529: // else if (nf->memof) ! 6530: // error('w',"%n declared as non-inline but defined as inline",nn); ! 6531: else if (nn->n_used) { ! 6532: nn->take_addr(); // force printout ! 6533: if (warning_opt) error('w',"%n called before defined as inline",nn); ! 6534: } ! 6535: } ! 6536: nf->f_inline = 1; ! 6537: nn->n_sto = STATIC; ! 6538: } ! 6539: else if (nf->f_inline) { ! 6540: // error('w',"%n defined as inline but not declared as inline",this); ! 6541: f->f_inline = 1; ! 6542: } ! 6543: goto stst2; ! 6544: ! 6545: stst: ! 6546: //error('d',"stst"); ! 6547: if (f->nargs_known && nf->nargs_known) merge_init(nn,f,nf); ! 6548: f->f_args = nf->f_args; ! 6549: // f->argtype = nf->argtype; ! 6550: stst2: ! 6551: //error('d',"stst2 %n printed %d",nn,nn->n_dcl_printed); ! 6552: if (f->f_inline) n_sto = STATIC; ! 6553: ! 6554: /* superceded above (line 1978 and following) ! 6555: if (n_sto ! 6556: && nn->n_scope!=n_sto ! 6557: && friend_in_class==0 ! 6558: && f->f_inline==0){ // allow re-def to "static" ! 6559: if (n_sto == STATIC) ! 6560: nn->n_sto = STATIC; ! 6561: else { ! 6562: error("%n both%k and%k",this,n_sto,nn->n_scope); ! 6563: } ! 6564: } ! 6565: */ ! 6566: ! 6567: //// addition for 2.1 ! 6568: ! 6569: if(n_sto == STATIC && nn->n_sto == EXTERN && ! 6570: (!strcmp(string,"__nw") || !strcmp(string,"__dl"))) ! 6571: nn->n_sto = STATIC; ! 6572: ! 6573: //// end of addition ! 6574: ! 6575: n_scope = nn->n_scope; // first specifier wins ! 6576: n_sto = nn->n_sto; ! 6577: } ! 6578: } ! 6579: else { // new function: make f_this for member functions ! 6580: thth: ! 6581: just_made = 1; ! 6582: if (f->f_inline) ! 6583: nn->n_sto = STATIC; ! 6584: else if (class_name==0 && n_sto==0 && f->body==0) ! 6585: nn->n_sto = EXTERN; ! 6586: //error('d',"thth %n %t static %d sto %k",nn,f,f->f_static,nn->n_sto); ! 6587: if (f->f_static) ! 6588: switch (n_oper) { // what about + ?? ! 6589: case CTOR: ! 6590: case DTOR: ! 6591: case TYPE: ! 6592: case CALL: ! 6593: case DEREF: ! 6594: case REF: ! 6595: case ASSIGN: ! 6596: error("%n cannot be a staticMF",nn); ! 6597: f->f_static = 0; ! 6598: } ! 6599: ! 6600: if (class_name ! 6601: && f->f_static==0 // no ``this'' in static members ! 6602: && n_oper!=NEW // X::operator new() static by default ! 6603: && n_oper!=DELETE // X::operator delete() static by default ! 6604: && etbl!=gtbl) { // beware of implicit declaration ! 6605: Pname cn = nn->n_table->t_name; ! 6606: Pname tt = new name("this"); ! 6607: tt->n_scope = ARG; ! 6608: tt->where = no_where; ! 6609: // tt->n_sto = ARG; ! 6610: tt->tp = Pclass(class_name->tp)->this_type; ! 6611: PERM(tt); ! 6612: Pfct(nn->tp)->f_this = f->f_this = Pfct(nn->tp)->f_args = f->f_args = tt; ! 6613: tt->n_list = f->argtype; ! 6614: //error('d',"nn %n tp %t const %d",nn,nn->tp,f->f_const); ! 6615: if (f->f_const /*&& n_oper!=CTOR && n_oper!=DTOR*/) { ! 6616: Pbase x = Pbase(Pptr(tt->tp)->typ); ! 6617: Pbase y = new basetype(COBJ,0); ! 6618: *y = *x; ! 6619: y->b_const = 1; ! 6620: tt->tp = new ptr(PTR,y); ! 6621: Pptr(tt->tp)->rdo = 1; ! 6622: PERM(tt->tp); ! 6623: } ! 6624: } ! 6625: else { ! 6626: Pfct(nn->tp)->f_args = f->f_args = f->f_result?f->f_result:f->argtype; ! 6627: Pfct(nn->tp)->f_signature = f->f_signature; ! 6628: Pfct(nn->tp)->f_const = f->f_const; ! 6629: Pfct(nn->tp)->f_static = f->f_static; ! 6630: } ! 6631: ! 6632: // if C++ linkage encode type in function name ! 6633: if (Pfct(nn->tp)->f_signature==0) Pfct(nn->tp)->sign(); ! 6634: ! 6635: if (f->f_result == 0) { ! 6636: //error('d',"re1 %n %t %d",this,f,f); ! 6637: make_res(f); ! 6638: } ! 6639: else if (f->f_this) ! 6640: f->f_this->n_list = f->f_result; ! 6641: ! 6642: if (nn->n_oper==CTOR || nn->n_oper==DTOR) vbase_pointers(nn,Pclass(class_name->tp)); ! 6643: ! 6644: if (f->f_virtual) { ! 6645: switch (nn->n_scope) { ! 6646: default: ! 6647: error("nonC virtual%n",this); ! 6648: break; ! 6649: case 0: ! 6650: case PUBLIC: ! 6651: // if (fvirt) //BSopt ! 6652: cc->cot->virt_count = 1; ! 6653: Pfct(nn->tp)->f_virtual = f->f_virtual; ! 6654: break; ! 6655: } ! 6656: } ! 6657: } ! 6658: ! 6659: /* an operator must take at least one class object or ! 6660: reference to class object argument ! 6661: */ ! 6662: ! 6663: if (just_made) ! 6664: switch (n_oper) { ! 6665: case CTOR: ! 6666: switch (f->nargs) { // check for X(X) and X(X&) ! 6667: case 0: ! 6668: break; ! 6669: default: // handle X(X&, int i = 0) ! 6670: { Pname n2 = f->argtype->n_list; ! 6671: if (n2->n_initializer==0 && n2->n_evaluated==0) break; ! 6672: } ! 6673: case 1: ! 6674: { ! 6675: Ptype t = f->argtype->tp; ! 6676: clll: ! 6677: switch (t->base) { ! 6678: case TYPE: ! 6679: t = Pbase(t)->b_name->tp; ! 6680: goto clll; ! 6681: case RPTR: /* X(X&) ? */ ! 6682: t = Pptr(t)->typ; ! 6683: cxll: ! 6684: switch (t->base) { ! 6685: case TYPE: ! 6686: t = Pbase(t)->b_name->tp; ! 6687: goto cxll; ! 6688: case COBJ: ! 6689: if (class_name == Pbase(t)->b_name) ! 6690: Pclass(class_name->tp)->c_itor = nn; ! 6691: } ! 6692: break; ! 6693: case COBJ: /* X(X) ? */ ! 6694: if (class_name == Pbase(t)->b_name) { ! 6695: error("badK %s(%s) use %s(%s&)",class_name->string,class_name->string,class_name->string,class_name->string); ! 6696: f->argtype->tp = any_type; ! 6697: } ! 6698: } ! 6699: } ! 6700: } ! 6701: if (Pclass(class_name->tp)->c_ctor == 0) Pclass(class_name->tp)->c_ctor = nn; ! 6702: break; ! 6703: ! 6704: case TYPE: ! 6705: // somewhat simple minded solution to the inheritance of ! 6706: // conversion operator problem ! 6707: nn->n_list = Pclass(class_name->tp)->conv; ! 6708: Pclass(class_name->tp)->conv = nn; ! 6709: break; ! 6710: ! 6711: case DTOR: ! 6712: Pclass(class_name->tp)->c_dtor = nn; ! 6713: break; ! 6714: ! 6715: case NEW: ! 6716: case DELETE: ! 6717: case CALL: ! 6718: case 0: ! 6719: break; ! 6720: ! 6721: default: ! 6722: for (Pname a=f->argtype; a; a=a->n_list) { ! 6723: if ( a->n_initializer ) ! 6724: error( "%n: operatorFs cannot take defaultA", this ); ! 6725: } ! 6726: ! 6727: if (f->nargs_known != 1) { ! 6728: error("ATs must be fully specified for%n",nn); ! 6729: } ! 6730: // this doesn't catch unary operator off by one errors ! 6731: // for simplicity, placed that check in check_oper(), above ! 6732: else if (class_name == 0) { ! 6733: switch (f->nargs) { ! 6734: case 1: ! 6735: case 2: ! 6736: for (a=f->argtype; a; a=a->n_list) { ! 6737: Ptype tx = a->tp; ! 6738: while (tx->base == TYPE) tx = Pbase(tx)->b_name->tp; ! 6739: if (tx->is_ref()) tx = Pptr(tx)->typ; ! 6740: if (tx->is_cl_obj()) goto cok; ! 6741: } ! 6742: error("%n must take at least oneCTA",nn); ! 6743: break; ! 6744: default: ! 6745: error("%n must take 1 or 2As",nn); ! 6746: } ! 6747: } ! 6748: else { ! 6749: switch (f->nargs) { ! 6750: case 0: ! 6751: case 1: ! 6752: break; ! 6753: default: ! 6754: error("%n must take 0 or 1As",nn); ! 6755: } ! 6756: } ! 6757: cok:; ! 6758: } ! 6759: ! 6760: int i = 0; // check that every argument after an argument with ! 6761: // initializer have an initializer ! 6762: for (Pname a = f->f_args/*f->argtype*/; a; a=a->n_list) { ! 6763: if (a->n_initializer) ! 6764: i = 1; ! 6765: else if (i) ! 6766: error("trailingA%n withoutIr",a); ! 6767: } ! 6768: ! 6769: /* ! 6770: the body cannot be checked until the name ! 6771: has been checked and entered into its table ! 6772: */ ! 6773: if (f->body) f->dcl(nn); ! 6774: return nn; ! 6775: } ! 6776: ! 6777: 0707071010112043711004440001630000160000010174600466055376600000700000154273dcl4.c /*ident "@(#)ctrans:src/dcl4.c 1.4" */ ! 6778: /************************************************************************** ! 6779: ! 6780: C++ source for cfront, the C++ compiler front-end ! 6781: written in the computer science research center of Bell Labs ! 6782: ! 6783: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 6784: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 6785: ! 6786: dcl4.c: ! 6787: Declaration of class and enum ! 6788: ! 6789: *************************************************************************/ ! 6790: ! 6791: #include "cfront.h" ! 6792: #include "size.h" ! 6793: #include "template.h" ! 6794: ! 6795: Pname find_vptr(Pclass); ! 6796: void fix_args(Pfct f, Pclass cl) ! 6797: /* ! 6798: This function is used to cope with the case where cl::cl(cl&) is ! 6799: declared AFTER f has been declared ! 6800: set n_xref bit for f ! 6801: */ ! 6802: { ! 6803: for (Pname a = f->argtype; a; a = a->n_list) { ! 6804: Pname n = a->tp->is_cl_obj(); ! 6805: if (n && Pclass(n->tp)==cl) a->n_xref = 1; ! 6806: } ! 6807: } ! 6808: ! 6809: Pname merge_conv(Pname c1, Pname c2) ! 6810: { ! 6811: if (c1 == 0) return c2; ! 6812: if (c2 == 0) return c1; ! 6813: if (c1 == c2) return c1; ! 6814: error('s',"cannot merge lists of conversion functions"); ! 6815: return c1; ! 6816: } ! 6817: ! 6818: static Eppp; ! 6819: ! 6820: char* get_classname(char* s) ! 6821: /* ! 6822: retrieve the outermost class name in a vtable name ! 6823: */ ! 6824: { ! 6825: //error('d',"get_classname(%s)",s); ! 6826: char* s1 = 0; ! 6827: ! 6828: while (*s) { ! 6829: s1 = s; ! 6830: for ( ; s[0] && (s[0] != '_' || s[1] && s[1] != '_'); s++); ! 6831: if (*s) s += 2; // bypass "__" ! 6832: } ! 6833: ! 6834: return s1; ! 6835: } ! 6836: ! 6837: char* drop_classname(char* s) ! 6838: /* ! 6839: retrieve all but the outermost class name in a vtable name ! 6840: */ ! 6841: { ! 6842: //error('d',"drop_classname(%s)",s); ! 6843: char* r = new char[strlen(s)+1]; ! 6844: sprintf(r,s); ! 6845: s = r; ! 6846: ! 6847: char* s1 = s; ! 6848: while (*s) { ! 6849: for ( ; s[0] && (s[0] != '_' || s[1] && s[1] != '_'); s++); ! 6850: if (*s) { ! 6851: s1 = s; ! 6852: s += 2; // bypass "__" ! 6853: } ! 6854: } ! 6855: ! 6856: *s1 = '\0'; ! 6857: ! 6858: return (*r) ? r : 0; ! 6859: } ! 6860: ! 6861: Pbcl classdef::get_base( char *s ) ! 6862: /* ! 6863: Find the base class whose name matches the argument ! 6864: */ ! 6865: { ! 6866: //error('d',"%t::get_base(%s)",this,s); ! 6867: for (Pbcl b = baselist; b; b = b->next) { ! 6868: for ( char *s1 = s, *s2 = b->bclass->string; ! 6869: *s1 && *s2 && *s1 == *s2; ! 6870: s1++, s2++); ! 6871: ! 6872: if (!(*s1 || *s2)) ! 6873: break; ! 6874: } ! 6875: ! 6876: return b; ! 6877: } ! 6878: ! 6879: int classdef::get_offset(char* s) ! 6880: /* ! 6881: Get offset represented by string as viewed from "this" ! 6882: */ ! 6883: { ! 6884: //error('d',"%t::get_offset(%s)",this,s); ! 6885: if (!s) return 0; ! 6886: ! 6887: Pbcl b = get_base(get_classname(s)); ! 6888: ! 6889: return b->obj_offset + b->bclass->get_offset(drop_classname(s)); ! 6890: } ! 6891: ! 6892: char* vtbl_str(char* s1, char* s2) ! 6893: /* ! 6894: combine two pieces of a vtbl name ! 6895: */ ! 6896: { ! 6897: //error('d',"vtbl_str(%s,%s)",s1,s2); ! 6898: char* s3; ! 6899: if (s1) ! 6900: if (s2) { ! 6901: s3 = new char[strlen(s1)+strlen(s2)+3]; ! 6902: sprintf(s3,"%s__%s",s1,s2); ! 6903: return s3; ! 6904: } ! 6905: else ! 6906: return s1; ! 6907: else ! 6908: return s2; ! 6909: } ! 6910: ! 6911: void classdef::add_vtbl(velem* v, char* s, bit virt_flag, int n_init) ! 6912: /* ! 6913: add vtbl to virt_list ! 6914: */ ! 6915: { ! 6916: // error('d',"%t->add_vtbl(%d,%s)",this,v,s); ! 6917: Pvirt vtab = new virt(this, v, s, virt_flag, n_init); ! 6918: ! 6919: if (virt_flag) has_vvtab = 1; ! 6920: ! 6921: if (!virt_list) { ! 6922: virt_list = vtab; ! 6923: return; ! 6924: } ! 6925: ! 6926: // If conficting vtable entries are made because of ! 6927: // a virtual base class, must be considered an error. ! 6928: for (Pvirt vt = virt_list; vt; vt = vt->next ) ! 6929: // if (strcmp(vt->string,s)==0) { ! 6930: if (vt->string && strcmp(vt->string,s)==0) { ! 6931: velem* ivec = vt->virt_init; ! 6932: Pname on = ivec[0].n; ! 6933: Pname nn = v[0].n; ! 6934: Pclass ocl,ncl; ! 6935: for (int i=0; on && nn; i++,on=ivec[i].n,nn=v[i].n) { ! 6936: ocl = Pfct(on->tp)->memof; ! 6937: ncl = Pfct(nn->tp)->memof; ! 6938: if (on != nn) ! 6939: if (!ocl->has_base(ncl)) ! 6940: if (!ncl->has_base(ocl)) ! 6941: break; ! 6942: else { ! 6943: ivec[i].n = nn; ! 6944: ivec[i].offset = v[i].offset; ! 6945: } ! 6946: } ! 6947: if (on || nn) ! 6948: error("virtualB: ambiguous%n and%n", on, nn); ! 6949: return; ! 6950: } ! 6951: ! 6952: vtab->next = virt_list->next; ! 6953: virt_list->next = vtab; ! 6954: } ! 6955: ! 6956: static int Voffset; // cope with offsets of virtuals in deep nests ! 6957: int vcounter; ! 6958: static vmax; ! 6959: const vpChunk = 32; ! 6960: ! 6961: int classdef::do_virtuals(Pvirt vtab, char* str, int leftmost, bit virt_flag) ! 6962: /* ! 6963: make vtbl for b in "this" ! 6964: match up virtuals and assign virtual indices for the base or delegate "bcl" ! 6965: first base class shares ``this'' and vtbl with this class ! 6966: */ ! 6967: { ! 6968: if (vmax<vcounter) vmax = vcounter; ! 6969: int vpsz = (vmax+vcounter)/vpChunk+1; // fragmentation prevention ! 6970: vpsz *= vpChunk; ! 6971: Pname* vp = new Pname[vpsz]; ! 6972: velem* ivec = vtab ? vtab->virt_init : 0; ! 6973: int vo = Voffset; ! 6974: int vc = 0; ! 6975: int changed = 0; ! 6976: ! 6977: // error('d',"%t->do_virtuals(%d,%s) voffset %d",this,vtab,str,Voffset); ! 6978: // error('d',"virt_count %d vpsz %d vcounter %d",virt_count,vpsz,vcounter); ! 6979: ! 6980: if (ivec) { // vtbl replacement for ivec ! 6981: ! 6982: if (vtab->is_vbase) { ! 6983: str = 0; ! 6984: Voffset = get_offset(vtab->string); ! 6985: } ! 6986: else ! 6987: Voffset = Voffset + vtab->vclass->get_offset(vtab->string); ! 6988: Pname vn; ! 6989: for (int i=0; vn=ivec[i].n; i++) { ! 6990: ! 6991: /* go through virtual table's list of virtuals: ! 6992: first see if the function is simply inherited ! 6993: if not, check for a match ! 6994: if not, then add as new ! 6995: */ ! 6996: // Pname vn = ivec[i]; ! 6997: if ( i >= vpsz ) { // resize vp vector ! 6998: int tvpsz = vpsz + vpChunk; ! 6999: Pname *tvp = new Pname[ tvpsz ]; ! 7000: for ( int j = 0; j < i; ++j ) ! 7001: tvp[ j ] = vp[ j ]; ! 7002: delete [vpsz] vp; ! 7003: vp = tvp; ! 7004: //error( 'd',"resizing: i: %d vpsz: %d tvpsz: %d", i, vpsz, tvpsz ); ! 7005: vpsz = tvpsz; ! 7006: } ! 7007: ! 7008: // char* s = Pchar(vn->n_tbl_list); ! 7009: char* s = vn->n_gen_fct_name; ! 7010: Pname n = memtbl->look(s?s:vn->string, 0); ! 7011: ! 7012: // error('d',"vn %n %s n %n %d",vn,s,n,Voffset); ! 7013: // error('d',"n %n %k", n, n?n->base:0 ); ! 7014: if (n == 0 || // FCT + FCT ! 7015: n->base == PUBLIC ) { // base::FCT ! 7016: inher: // inherit ! 7017: // if (vn->n_initializer) error("cannot inherit pure virtualF%n",vn); ! 7018: if (vn->n_initializer) c_abstract = 1; ! 7019: vp[i] = vn; ! 7020: if ( ivec[i].offset && vtab->is_vbase ) ! 7021: vp[i]->n_offset = Voffset - vo; ! 7022: else ! 7023: vp[i]->n_offset = ivec[i].offset; ! 7024: continue; ! 7025: } ! 7026: ! 7027: Pfct f = Pfct(n->tp); ! 7028: // error ('d', "f %d", f ); ! 7029: if (f == 0 ) continue; ! 7030: // error('d',"f %t %d",f,f->f_virtual); ! 7031: ! 7032: if (s && f->base==OVERLOAD) { // OVERLOAD + OVERLOAD ! 7033: // vn is overloaded and s is its name ! 7034: for (Plist gl=Pgen(f)->fct_list; gl; gl=gl->l) ! 7035: if (gl->f == vn) goto inher; ! 7036: } ! 7037: ! 7038: Pfct vnf = Pfct(vn->tp); ! 7039: // re-define? ! 7040: switch (f->base) { ! 7041: default: ! 7042: error('w',&n->where,"%n hides virtual%n",n,vn); ! 7043: vp[i] = vn; // not a new overloaded: inherit ! 7044: if ( ivec[i].offset && vtab->is_vbase ) ! 7045: vp[i]->n_offset = Voffset - vo; ! 7046: else ! 7047: vp[i]->n_offset = ivec[i].offset; ! 7048: break; ! 7049: case FCT: // derived::FCT ! 7050: { ! 7051: if (vnf->check(f,VIRTUAL) == 0) { // derived::FCT match base::FCT ! 7052: // error('d',"vnf1 %t f %t vcheck %d",vnf,f,Vcheckerror); ! 7053: // VTOK: virtual, but no index assigned ! 7054: // you can only inherit an index from your first base ! 7055: if (Vcheckerror) error("bad virtualT match for %n",vn); ! 7056: if (f->f_virtual==VTOK) f->f_virtual = i+1; ! 7057: vp[i] = n; ! 7058: vp[i]->n_offset = Voffset; ! 7059: changed = 1; ! 7060: } ! 7061: else { ! 7062: // error('d',"vnf2 %t f %t vcheck %d",vnf,f,Vcheckerror); ! 7063: if (Vcheckerror) ! 7064: error("bad virtualT match for %n",vn); ! 7065: else ! 7066: switch (f->f_virtual) { ! 7067: case 0: ! 7068: case VTOK: ! 7069: error('w',&n->where,"%n hides virtual%n",n,vn); ! 7070: } ! 7071: vp[i] = vn; // not a new overloaded: inherit ! 7072: if ( ivec[i].offset && vtab->is_vbase ) ! 7073: vp[i]->n_offset = Voffset - vo; ! 7074: else ! 7075: vp[i]->n_offset = ivec[i].offset; ! 7076: } ! 7077: break; ! 7078: } ! 7079: case OVERLOAD: // derived::OVERLOAD ! 7080: { ! 7081: int hit = 0; ! 7082: for (Plist gl=Pgen(f)->fct_list; gl; gl=gl->l) { ! 7083: // try each fct from derived class ! 7084: Pname fn = gl->f; ! 7085: Pfct f = Pfct(fn->tp); ! 7086: ! 7087: if (f->check(vnf,VIRTUAL) == 0) { // derived::FCT ! 7088: if (Vcheckerror) error("bad virtualT match for %n",vn); ! 7089: if (f->f_virtual==VTOK) f->f_virtual = i+1; ! 7090: vp[i] = fn; ! 7091: vp[i]->n_offset = Voffset; ! 7092: changed = 1; ! 7093: goto found; ! 7094: } ! 7095: else { ! 7096: if (Vcheckerror) error("bad virtualT match for %n",vn); ! 7097: } ! 7098: if (Vcheckerror == 0) ! 7099: switch (f->f_virtual) { ! 7100: case 0: ! 7101: case VTOK: ! 7102: hit = 1; ! 7103: } ! 7104: ! 7105: } ! 7106: ! 7107: if (hit) ! 7108: error('w',&n->where,"%n hides virtual%n ofT %t",n,vn,vn->tp); ! 7109: ! 7110: vp[i] = vn; // not a new overloaded: inherit ! 7111: if ( ivec[i].offset && vtab->is_vbase ) ! 7112: vp[i]->n_offset = Voffset - vo; ! 7113: else ! 7114: vp[i]->n_offset = ivec[i].offset; ! 7115: found: ! 7116: break; ! 7117: } ! 7118: } ! 7119: } ! 7120: ! 7121: Voffset = vo; ! 7122: vc = i; ! 7123: } ! 7124: ! 7125: // error( 'd', "do_virtuals: out of loop: vc: %d vpsz: %d changed: %d", vc, vpsz,changed ); ! 7126: ! 7127: if (leftmost) { ! 7128: /* ! 7129: add new virtuals: ! 7130: `VTOK' marks ``new virtual, no index assigned''. ! 7131: You can only be new once (no base or first base). ! 7132: */ ! 7133: int i; ! 7134: for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) { ! 7135: Pfct f = Pfct(nn->tp); ! 7136: ! 7137: if ( vc >= vpsz ) { // resize vp vector ! 7138: int tvpsz = vpsz + vpChunk; ! 7139: Pname *tvp = new Pname[ tvpsz ]; ! 7140: for ( int j = 0; j < vc; ++j ) ! 7141: tvp[ j ] = vp[ j ]; ! 7142: delete [vpsz] vp; ! 7143: vp = tvp; ! 7144: vpsz = tvpsz; ! 7145: } ! 7146: ! 7147: // error('d',"f %n %t",nn,f); ! 7148: if (f) ! 7149: switch (f->base) { ! 7150: case FCT: ! 7151: //error('d',"fv %d",f->f_virtual); ! 7152: if (f->f_virtual == VTOK) { ! 7153: // declared virtual, or ! 7154: // virtual in some base ! 7155: f->f_virtual = ++vc; ! 7156: vp[f->f_virtual-1] = nn; ! 7157: vp[f->f_virtual-1]->n_offset = 0; ! 7158: f->f_vdef = 1; ! 7159: changed = 2; ! 7160: } ! 7161: break; ! 7162: case OVERLOAD: ! 7163: { for (Plist gl=Pgen(f)->fct_list; gl; gl=gl->l) { ! 7164: Pname fn = gl->f; ! 7165: Pfct f = Pfct(fn->tp); ! 7166: ! 7167: ! 7168: if ( vc >= vpsz ) { // resize vp vector ! 7169: int tvpsz = vpsz + vpChunk; ! 7170: Pname *tvp = new Pname[ tvpsz ]; ! 7171: for ( int j = 0; j < vc; ++j ) { ! 7172: tvp[ j ] = vp[ j ]; ! 7173: } ! 7174: delete [vpsz] vp; ! 7175: vp = tvp; ! 7176: vpsz = tvpsz; ! 7177: } ! 7178: ! 7179: ! 7180: if (f->f_virtual == VTOK) { ! 7181: f->f_virtual = ++vc; ! 7182: vp[f->f_virtual-1] = fn; ! 7183: vp[f->f_virtual-1]->n_offset = 0; ! 7184: f->f_vdef = 1; ! 7185: changed = 2; ! 7186: } ! 7187: } ! 7188: break; ! 7189: } ! 7190: } ! 7191: } ! 7192: // error('d',"%s changed %d has_vvtab %d",string,changed,has_vvtab); ! 7193: // error('d',"vc %d vpsz %d",vc,vpsz); ! 7194: virt_count = 0; ! 7195: if (changed) ! 7196: virt_count = vc; ! 7197: else if (has_vvtab) { ! 7198: virt_merge = 1; ! 7199: if (vc && vtab->is_vbase) ! 7200: leftmost = 0; ! 7201: } ! 7202: } ! 7203: ! 7204: // error('d',"vc %d ch %d vp[%d] virt_count %d",vc,changed,vpsz,virt_count); ! 7205: if (changed || !leftmost) { ! 7206: // vc==0 if all explicit virtuals in fact were declared in base ! 7207: velem* v = new velem[vc+1]; ! 7208: ! 7209: for (int i=0; i<vc; i++) { ! 7210: v[i].n = vp[i]; ! 7211: v[i].offset = vp[i]->n_offset; ! 7212: } ! 7213: v[vc].n = 0; ! 7214: ! 7215: if (leftmost) ! 7216: add_vtbl(v,0,0,0); ! 7217: else ! 7218: add_vtbl(v,vtbl_str(vtab->string,str),virt_flag||vtab->is_vbase,vc+1); ! 7219: delete vp; ! 7220: vcounter = 0; ! 7221: return 1; ! 7222: } ! 7223: ! 7224: delete vp; ! 7225: vcounter = 0; ! 7226: return 0; ! 7227: } ! 7228: ! 7229: int classdef::all_virt(Pclass bcl, char* s, int leftmost, bit virt_flag) ! 7230: { ! 7231: int i = 0; ! 7232: if (bcl->virt_count) { ! 7233: for (Pvirt blist = bcl->virt_list; blist; blist = blist->next) { ! 7234: // if (has_base(blist->vclass)) ! 7235: // if (blist->vclass==bcl ! 7236: // // bcl is virtual in both ! 7237: // || ((Nvirt=0,blist->vclass->has_base(bcl)) && Nvirt==VIRTUAL ! 7238: // && (Nvirt=0,has_base(bcl)) && Nvirt==VIRTUAL ! 7239: // ) ! 7240: // ) ! 7241: if (virt_merge && !(virt_flag || blist->is_vbase)) ! 7242: continue; ! 7243: ! 7244: i += do_virtuals(blist, s, leftmost, virt_flag); ! 7245: if (!i && leftmost && !virt_merge) ! 7246: return 0; ! 7247: ! 7248: leftmost = 0; ! 7249: } ! 7250: } ! 7251: ! 7252: // finding virt_list stops recursive step ! 7253: // if vtables found and updated, return number ! 7254: if (i) return i; ! 7255: ! 7256: for (Pbcl b = bcl->baselist; b; b = b->next) { ! 7257: // if (b->base==PTR) continue; ! 7258: if (b->promoted) continue; ! 7259: // error('d',"b %t vl %d bl %d",b->bclass,b->bclass->virt_list,b->bclass->baselist); ! 7260: if (leftmost && b->base == VIRTUAL) { ! 7261: i += do_virtuals(0, 0, 1, 0); ! 7262: if (!i && !virt_merge) ! 7263: return 0; ! 7264: leftmost = 0; ! 7265: } ! 7266: int vo = Voffset; ! 7267: Voffset += b->obj_offset; ! 7268: // error('d',"offset %t %d",b->bclass,Voffset); ! 7269: ! 7270: if (b->base==VIRTUAL) ! 7271: i += all_virt(b->bclass, b->bclass->string, leftmost, 1); ! 7272: else ! 7273: i += all_virt(b->bclass, vtbl_str(b->bclass->string,s), leftmost, virt_flag); ! 7274: if (!i && leftmost && !virt_merge) ! 7275: return 0; ! 7276: ! 7277: Voffset = vo; ! 7278: leftmost = 0; ! 7279: } ! 7280: ! 7281: // if recursion updated vtables, return number ! 7282: if (i) return i; ! 7283: ! 7284: // no vtables updated in recursion ! 7285: // look for new virtuals ! 7286: if (leftmost) ! 7287: return do_virtuals(0, 0, 1, 0); ! 7288: else ! 7289: return 0; ! 7290: } ! 7291: ! 7292: Pexpr copy_obj(Pexpr l, Pexpr r, int sz) ! 7293: /* ! 7294: generate: ! 7295: struct _s { char[sz]; }; ! 7296: *(struct _s*)this->m = *(struct _s*)arg.mem; ! 7297: */ ! 7298: { ! 7299: if ( !sz ) sz = 1; ! 7300: //error('d',"copy(%d)",sz); ! 7301: char* s = make_name('S'); ! 7302: fprintf(out_file,"struct %s { char v[%d]; };\n",s,sz); ! 7303: Pname n = new name(s); ! 7304: Ptype t = new basetype(COBJ,n); ! 7305: t = new ptr(PTR,t); ! 7306: ! 7307: l = new texpr(CAST,t,l);//new cast(t,l); ! 7308: l = l->contents(); ! 7309: ! 7310: r = new texpr(CAST,t,r);//new cast(t,r); ! 7311: r = r->contents(); ! 7312: ! 7313: return new expr(ASSIGN,l,r); ! 7314: } ! 7315: ! 7316: /* ! 7317: Pname make_default_ctor(Pclass cl) ! 7318: { ! 7319: //error('d',"make_ctor %t",cl); ! 7320: Pname cn = ktbl->look(cl->string,0); ! 7321: if (cn) cn = Pbase(cn->tp)->b_name; ! 7322: cc->stack(); ! 7323: cc->not = cn; ! 7324: cc->cot = cl; ! 7325: Pname fn = new name(cl->string); ! 7326: Pfct f = new fct(defa_type,0,1); ! 7327: fn->tp = f; ! 7328: fn->n_oper = TNAME; ! 7329: // fn->n_sto = STATIC; ! 7330: ! 7331: Pfct(f)->f_inline = 1; ! 7332: f->body = new block(curloc,0,0); ! 7333: ! 7334: Pname nn = fn->dcl(cl->memtbl,PUBLIC); ! 7335: delete fn; ! 7336: ! 7337: cc->unstack(); ! 7338: nn->simpl(); ! 7339: if (debug_opt) nn->dcl_print(0); ! 7340: //error('d',"make_ctor->"); ! 7341: return nn; ! 7342: } ! 7343: ! 7344: Pname make_default_dtor(Pclass cl) ! 7345: { ! 7346: //error('d',"make_dtor %t",cl); ! 7347: Pname cn = ktbl->look(cl->string,0); ! 7348: if (cn) cn = Pbase(cn->tp)->b_name; ! 7349: cc->stack(); ! 7350: cc->not = cn; ! 7351: cc->cot = cl; ! 7352: Pname fn = new name(cl->string); ! 7353: Pfct f = new fct(defa_type,0,1); ! 7354: fn->tp = f; ! 7355: fn->n_oper = DTOR; ! 7356: // fn->n_sto = STATIC; ! 7357: ! 7358: Pfct(f)->f_inline = 1; ! 7359: f->body = new block(curloc,0,0); ! 7360: ! 7361: Pname nn = fn->dcl(cl->memtbl,PUBLIC); ! 7362: delete fn; ! 7363: ! 7364: cc->unstack(); ! 7365: nn->simpl(); ! 7366: if (debug_opt) nn->dcl_print(0); ! 7367: //error('d',"make_dtor->"); ! 7368: return nn; ! 7369: } ! 7370: */ ! 7371: ! 7372: Ptype find_arg_type(Pclass cl) ! 7373: // first determine argument type ! 7374: { ! 7375: int i; ! 7376: int mod = 0; ! 7377: for (Pbcl b = cl->baselist; b; b = b->next) { ! 7378: Pclass bcl = b->bclass; ! 7379: switch (b->base) { ! 7380: case VIRTUAL: ! 7381: case NAME: // generate :b(*(b*)&arg) ! 7382: { ! 7383: Pname itor = bcl->has_itor(); ! 7384: if (itor && itor->tp->base==FCT) { ! 7385: Pname a = Pfct(itor->tp)->argtype; ! 7386: Pptr p = a->tp->is_ref(); ! 7387: if (p && p->typ->tconst()==0) { ! 7388: mod = 1; ! 7389: goto ll1; ! 7390: } ! 7391: } ! 7392: } ! 7393: } ! 7394: } ! 7395: ll1: ! 7396: if (mod == 0) { ! 7397: for (Pname m=cl->memtbl->get_mem(i=1); m; m=cl->memtbl->get_mem(++i) ) { ! 7398: Pname cln; ! 7399: // ignore static members ! 7400: if (m->n_evaluated || m->n_stclass==STATIC) continue; ! 7401: ! 7402: if (cln = m->tp->is_cl_obj()) { ! 7403: Pname itor = Pclass(cln->tp)->has_itor(); ! 7404: if (itor && itor->tp->base==FCT) { ! 7405: Pname a = Pfct(itor->tp)->argtype; ! 7406: Pptr p = a->tp->is_ref(); ! 7407: if (p && p->typ->tconst()==0) { ! 7408: mod = 1; ! 7409: goto ll2; ! 7410: } ! 7411: } ! 7412: } ! 7413: } ! 7414: } ! 7415: ll2: ! 7416: //error('d',"mod %d",mod); ! 7417: Pbase bp = new basetype(INT,0); ! 7418: *bp = *Pbase(Pptr(cl->this_type)->typ); ! 7419: if (mod == 0) bp->b_const = 1; ! 7420: return new ptr(RPTR,bp); ! 7421: } ! 7422: ! 7423: Pname classdef::make_itor(int def) ! 7424: /* ! 7425: make cn::cn(const cn&) :bases_and_members_of_cn {} ! 7426: */ ! 7427: { ! 7428: //error('d',"%t->make_itor(%d) %d",this,def,obj_size); ! 7429: Pstmt s; ! 7430: Pname e; ! 7431: int i; ! 7432: Pname arg = new name(make_name('A')); ! 7433: arg->tp = find_arg_type(this); ! 7434: ! 7435: // c_xref = 2; // now it has X(X&) ! 7436: c_xref |= C_XREF; // now it has X(X&) ! 7437: ! 7438: if (def) { ! 7439: // define itor ! 7440: int slow = 0; // slow==0 => copy using vector copy ! 7441: int first = 1; ! 7442: Pexpr es = 0; ! 7443: s = new estmt(SM,no_where,0,0); ! 7444: e = 0; ! 7445: ! 7446: ! 7447: if (warning_opt && 128<obj_size) ! 7448: error('w',"copying a %d byte object (ofC %s)",obj_size,string); ! 7449: ! 7450: if (baselist) slow = 1; ! 7451: ! 7452: //for (Pbcl v = baselist; v; v = v->next) ! 7453: // if (v->base == VIRTUAL) { ! 7454: // slow = 1; ! 7455: // break; ! 7456: // } ! 7457: ! 7458: // initialize bases: ! 7459: if (slow) { ! 7460: for (Pbcl b = baselist; b; b = b->next) { ! 7461: Pclass bcl = b->bclass; ! 7462: Ptype pt = bcl->this_type; ! 7463: //error('d',"base %t %k offset %d ptroffset %d",bcl,b->base,b->obj_offset,b->ptr_offset); ! 7464: switch (b->base) { ! 7465: case VIRTUAL: ! 7466: case NAME: // generate :b(*(b*)&arg) ! 7467: { ! 7468: Pexpr b2 = new name(arg->string); ! 7469: b2 = b2->address(); ! 7470: b2 = new texpr(CAST,pt,b2);//new cast(pt,b2); ! 7471: b2->i2 = 1; ! 7472: b2 = b2->contents(); ! 7473: ! 7474: Pname ee = new name(bcl->string); ! 7475: ee->base = TNAME; ! 7476: ee->n_initializer = b2; ! 7477: if (e) ee->n_list = e; ! 7478: e = ee; ! 7479: break; ! 7480: } ! 7481: } ! 7482: } ! 7483: } ! 7484: ! 7485: // initialize members ! 7486: for (Pname m=memtbl->get_mem(i=1); m; m=memtbl->get_mem(++i) ) { ! 7487: // ignore static members ! 7488: if (m->n_evaluated || m->n_stclass==STATIC) continue; ! 7489: ! 7490: if (strcmp(m->string,"__vptr")==0) { ! 7491: // error('d',"%t vptr: %d",this,first); ! 7492: if (first==0 && m->n_offset) { ! 7493: Pexpr th = new expr(THIS,0,0); ! 7494: Pexpr a = new name(arg->string); ! 7495: a = a->address(); ! 7496: Pexpr ee = copy_obj(th,a,m->n_offset); ! 7497: es = es ? new expr(CM,es,ee) : ee; ! 7498: } ! 7499: slow = 1; ! 7500: first = 0; ! 7501: continue; ! 7502: } ! 7503: Ptype mt = m->tp; ! 7504: tx: ! 7505: switch (mt->base) { ! 7506: case TYPE: ! 7507: mt = Pbase(mt)->b_name->tp; ! 7508: goto tx; ! 7509: case VEC: ! 7510: { Pname cn = Pvec(mt)->typ->is_cl_obj(); ! 7511: //error('d',"vec %n %t xref %d",m,mt,cn?Pclass(cn->tp)->c_xref:0); ! 7512: if (cn && Pclass(cn->tp)->c_xref&(C_XREF|C_VBASE)) { ! 7513: error('s',"copy of %n[], no memberwise copy for%n",cn,cn); ! 7514: slow = 1; // make sure an assignment operator ! 7515: // is generated so that there will ! 7516: // be no more error messages ! 7517: } ! 7518: ! 7519: if (slow && mt->tsizeof()) { ! 7520: /* ! 7521: generate: ! 7522: struct _s { char[sizeof(m)]; }; ! 7523: *(struct _s*)this->m = *(struct _s*)arg.mem; ! 7524: */ ! 7525: Pexpr l = new name(m->string); ! 7526: Pexpr r = new name(m->string); ! 7527: r = new ref(DOT,new name(arg->string),r); ! 7528: Pexpr ee = copy_obj(l,r,mt->tsizeof()); ! 7529: es = es ? new expr(CM,es,ee) : ee; ! 7530: break; ! 7531: } ! 7532: } ! 7533: case FCT: ! 7534: case OVERLOAD: ! 7535: case CLASS: ! 7536: case ENUM: ! 7537: break; ! 7538: case COBJ: ! 7539: { Pclass mcl = Pclass(Pbase(mt)->b_name->tp); ! 7540: if (slow==0 // if slow, previous members have ! 7541: // already been copied ! 7542: && mcl->c_xref&(C_VBASE|C_XREF)) { ! 7543: slow = 1; ! 7544: if (first==0 && m->n_offset) { ! 7545: //AAA copy up to here ! 7546: Pexpr th = new expr(THIS,0,0); ! 7547: Pexpr a = new name(arg->string); ! 7548: a = a->address(); ! 7549: Pexpr ee = copy_obj(th,a,m->n_offset); ! 7550: es = es ? new expr(CM,es,ee) : ee; ! 7551: } ! 7552: } ! 7553: // no break ! 7554: } ! 7555: ! 7556: default: ! 7557: if (slow) { ! 7558: //error('d',"slow %s %s",m->string,arg->string); ! 7559: Pname ee = new name(m->string); ! 7560: ee->n_initializer = new ref(DOT,new name(arg->string),new name(m->string)); ! 7561: if (e) ee->n_list = e; ! 7562: e = ee; ! 7563: } ! 7564: } ! 7565: first = 0; ! 7566: } ! 7567: ! 7568: if (slow == 0) { ! 7569: /* really simple just copy: ! 7570: the only problem was a vptr which can be ! 7571: ignored since X(X&) is going to reset it anyway ! 7572: don't use assignment of this struct to avoid operator= ! 7573: */ ! 7574: Pexpr th = new expr(THIS,0,0); ! 7575: Pexpr a = new name(arg->string); ! 7576: a = a->address(); ! 7577: Pexpr ee = copy_obj(th,a,obj_size); ! 7578: es = es ? new expr(CM,es,ee) : ee; ! 7579: } ! 7580: ! 7581: s->e = es; ! 7582: Pname cn = ktbl->look(string,0); ! 7583: if (cn) cn = Pbase(cn->tp)->b_name; ! 7584: cc->stack(); ! 7585: cc->not = cn; ! 7586: cc->cot = this; ! 7587: } ! 7588: Pname fn = new name(string); ! 7589: Pfct f = new fct(defa_type,arg,1); ! 7590: fn->tp = f; ! 7591: fn->n_oper = TNAME; ! 7592: // fn->n_sto = STATIC; ! 7593: ! 7594: Pfct(f)->f_inline = def?1:ITOR; // ITOR means ``define itor() if used'' ! 7595: if (def) { ! 7596: f->body = new block(curloc,0,s); ! 7597: f->f_init = e; ! 7598: } ! 7599: ! 7600: Pname nn = fn->dcl(memtbl,PUBLIC); ! 7601: delete fn; ! 7602: ! 7603: if (def) { ! 7604: cc->unstack(); ! 7605: nn->simpl(); ! 7606: if (debug_opt) nn->dcl_print(0); ! 7607: } ! 7608: //error('d',"make_itor->"); ! 7609: return nn; ! 7610: } ! 7611: ! 7612: int make_assignment(Pname cn) ! 7613: /* ! 7614: write the function: ! 7615: ! 7616: X& X::operator=(const X&) { assign all bases and members } ! 7617: ! 7618: return 1 is a function is really synthesized ! 7619: */ ! 7620: { ! 7621: Pclass cl = Pclass(cn->tp); ! 7622: Pstmt s = new estmt(SM,no_where,0,0); ! 7623: Pexpr e = 0; ! 7624: Pname arg = new name(make_name('A')); ! 7625: basetype* bp = new basetype(INT,0); ! 7626: *bp = *Pbase(Pptr(cl->this_type)->typ); ! 7627: bp->b_const = 1; ! 7628: // arg->tp = new ptr(RPTR,bp); ! 7629: arg->tp = find_arg_type(cl); ! 7630: //error('d',"make_assignment %t %d",cl,cl->obj_size); ! 7631: // cl->c_xref |= 4; // now it has X::operator=(const X&) ! 7632: ! 7633: if (warning_opt && 128<cl->obj_size) ! 7634: error('w',"copying a %d byte object (ofC %s)", ! 7635: cl->obj_size,cl->string); ! 7636: { ! 7637: int slow = 0; // slow==0 => copy using vector copy ! 7638: int first = 1; // first==1 => first member of (derived) class ! 7639: ! 7640: if (cl->baselist) slow = 1; // be dumb and safe ! 7641: // for (Pbcl v = cl->baselist; v; v = v->next) ! 7642: // if (v->base==VIRTUAL || v->c_xref&(C_VBASE|C_ASS)) { ! 7643: // slow = 1; ! 7644: // break; ! 7645: // } ! 7646: ! 7647: if (slow) { ! 7648: for (Pbcl b = cl->baselist; b; b = b->next) { ! 7649: Pclass bcl = b->bclass; ! 7650: Ptype pt = bcl->this_type; ! 7651: switch (b->base) { ! 7652: case NAME: ! 7653: { // generate: *(bcl*)this = *(bcl*)&arg; ! 7654: //error('d',"base %t",bcl); ! 7655: Pexpr b1 = new expr(THIS,0,0); ! 7656: b1 = new texpr(CAST,pt,b1); ! 7657: b1 = b1->contents(); ! 7658: ! 7659: Pexpr b2 = new name(arg->string); ! 7660: b2 = b2->address(); ! 7661: b2 = new texpr(CAST,pt,b2); ! 7662: b2->i2 = 1; ! 7663: b2 = b2->contents(); ! 7664: ! 7665: Pexpr ee = new expr(ASSIGN,b1,b2); ! 7666: e = e ? new expr(CM,e,ee) : ee; ! 7667: break; ! 7668: } ! 7669: case VIRTUAL: ! 7670: if (warning_opt) ! 7671: error('w',"copying an object ofC%n with a virtualBC",cn); ! 7672: if (b->ptr_offset) { ! 7673: // copy object, but not pointer ! 7674: // generate: *(bcl*)this->Pw = *(bcl*)arg->Pw; ! 7675: ! 7676: // I don't know how to avoid copying the object ! 7677: // once for each pointer ! 7678: ! 7679: Pexpr b1 = new expr(THIS,0,0); ! 7680: b1 = new mdot(bcl->string,b1); ! 7681: b1->i1 = 3; ! 7682: b1->tp = pt; ! 7683: b1 = new expr(DEREF,b1,0);//b1->contents(); ! 7684: ! 7685: Pexpr b2 = new name(arg->string); ! 7686: b2 = b2->address(); ! 7687: b2 = new mdot(bcl->string,b2); ! 7688: b2->i1 = 3; ! 7689: b2->tp = pt; ! 7690: b2 = new expr(DEREF,b2,0);//b2->contents(); ! 7691: ! 7692: Pexpr ee = new expr(ASSIGN,b1,b2); ! 7693: e = e ? new expr(CM,e,ee) : ee; ! 7694: } ! 7695: break; ! 7696: } ! 7697: } ! 7698: } ! 7699: ! 7700: int i; ! 7701: for (Pname m=cl->memtbl->get_mem(i=1); m; m=cl->memtbl->get_mem(++i) ) { ! 7702: // ignore static members ! 7703: if (m->n_evaluated || m->n_stclass==STATIC) continue; ! 7704: ! 7705: if (strcmp(m->string,"__vptr")==0) { // don't copy vptrs ! 7706: // we may be copying ! 7707: // into a base class object ! 7708: if (first==0 && m->n_offset) { ! 7709: // copy up to (but not including) vptr ! 7710: // don't copy if first member ! 7711: Pexpr th = new expr(THIS,0,0); ! 7712: Pexpr a = new name(arg->string); ! 7713: a = a->address(); ! 7714: Pexpr ee = copy_obj(th,a,m->n_offset); ! 7715: e = e ? new expr(CM,e,ee) : ee; ! 7716: } ! 7717: slow = 1; ! 7718: first = 0; ! 7719: continue; ! 7720: } ! 7721: Ptype mt = m->tp; ! 7722: tx: ! 7723: switch (mt->base) { ! 7724: case TYPE: ! 7725: mt = Pbase(mt)->b_name->tp; ! 7726: goto tx; ! 7727: case VEC: ! 7728: { Pname cn = Pvec(mt)->typ->is_cl_obj(); ! 7729: if (cn && Pclass(cn->tp)->c_xref&(C_ASS|C_VBASE)) { ! 7730: error('s',"copy of %n[], no memberwise copy for%n",cn,cn); ! 7731: slow = 1; // make sure an assignment operator ! 7732: // is generated so that there will ! 7733: // be no more error messages ! 7734: } ! 7735: ! 7736: if (slow && mt->tsizeof()) { ! 7737: // protect against sizeof(mt)==0: char[] ! 7738: /* ! 7739: generate: ! 7740: struct _s { char[sizeof(m)]; }; ! 7741: *(struct _s*)this->m = *(struct _s*)arg.mem; ! 7742: */ ! 7743: Pexpr l = new name(m->string); ! 7744: Pexpr r = new name(m->string); ! 7745: r = new ref(DOT,new name(arg->string),r); ! 7746: Pexpr ee = copy_obj(l,r,mt->tsizeof()); ! 7747: e = e ? new expr(CM,e,ee) : ee; ! 7748: break; ! 7749: } ! 7750: } ! 7751: case FCT: ! 7752: case OVERLOAD: ! 7753: case CLASS: ! 7754: case ENUM: ! 7755: break; ! 7756: case RPTR: ! 7757: error("cannot assignC%t:RM%n",cl,m); ! 7758: break; ! 7759: case COBJ: ! 7760: //error('d',"cobj %n %d %d",m,slow,Pclass(Pbase(mt)->b_name->tp)->c_xref); ! 7761: if (slow==0 ! 7762: && Pclass(Pbase(mt)->b_name->tp)->c_xref&(C_VBASE|C_ASS)) { ! 7763: // must use its assignment operation ! 7764: if (first==0 && m->n_offset) { ! 7765: // copy up to this member ! 7766: Pexpr th = new expr(THIS,0,0); ! 7767: Pexpr a = new name(arg->string); ! 7768: a = a->address(); ! 7769: e = copy_obj(th,a,m->n_offset); ! 7770: } ! 7771: slow = 1; ! 7772: } ! 7773: // no break: copy cobj itself ! 7774: default: ! 7775: //error('d',"defa %n %d",m,slow); ! 7776: if (slow) { ! 7777: if (m->tp->tconst()) error("cannot assignC%t: const M%n",cl,m); ! 7778: Pname ms = new name(m->string); ! 7779: Pname as = new name(arg->string); ! 7780: Pexpr ee = new ref(DOT,as,new name(m->string)); ! 7781: ee = new expr(ASSIGN,ms,ee); ! 7782: e = e ? new expr(CM,e,ee) : ee; ! 7783: } ! 7784: } ! 7785: first = 0; ! 7786: } ! 7787: ! 7788: if (slow == 0) { ! 7789: /* really simple just copy: ! 7790: */ ! 7791: //error('d',"slow"); ! 7792: /* ! 7793: Pexpr th = new expr(THIS,0,0); ! 7794: Pexpr a = new name(arg->string); ! 7795: a = a->address(); ! 7796: Pexpr ee = copy_obj(th,a,cl->tsize()); ! 7797: e = e ? new expr(CM,e,ee) : e; ! 7798: */ ! 7799: //error('d',"%n simple assignment",cn); ! 7800: // cl->c_xref ^= C_ASS; // Didn't mean it: No X::operator=(X&) ! 7801: return 0; ! 7802: } ! 7803: ! 7804: } ! 7805: ! 7806: Pexpr rv = new expr(THIS,0,0); ! 7807: rv = new expr(DEREF,rv,0);//b1->contents(); ! 7808: ! 7809: s->e = e ? new expr(CM,e,rv) : e; ! 7810: s->s_list = new estmt(RETURN,no_where,rv,0); ! 7811: ! 7812: cc->stack(); ! 7813: cc->not = cn; ! 7814: cc->cot = cl; ! 7815: ! 7816: cl->c_xref |= C_ASS; // now it has X::operator=(const X&) ! 7817: ! 7818: Pname fn = new name(oper_name(ASSIGN)); ! 7819: Pfct f = new fct(new ptr(RPTR,Pptr(cl->this_type)->typ),arg,1); ! 7820: f->f_inline = 1; ! 7821: fn->tp = f; ! 7822: fn->n_oper = ASSIGN; ! 7823: fn->n_sto = STATIC; ! 7824: Pname nn = fn->dcl(cl->memtbl,PUBLIC); ! 7825: delete fn; ! 7826: Pfct(nn->tp)->body = new block(curloc,0,s); ! 7827: Pfct(nn->tp)->dcl(nn); ! 7828: ! 7829: cc->unstack(); ! 7830: nn->simpl(); ! 7831: //error('d',"make_assign->"); ! 7832: return 1; ! 7833: } ! 7834: ! 7835: void classdef::dcl(Pname cname, Ptable tbl) ! 7836: { ! 7837: int bvirt = 0; ! 7838: int dvirt = 0; ! 7839: int scope = PUBLIC; ! 7840: int protect = 0; ! 7841: int st = 1; // nothing private or protected seen: a struct ! 7842: // int nstd = (in_class && nested_sig)?2:(in_class?1:0); // nested class ! 7843: ! 7844: int byte_old = byte_offset; ! 7845: int bit_old = bit_offset; ! 7846: int max_old = max_align; ! 7847: int boff = 0; ! 7848: ! 7849: int in_union = 0; ! 7850: int usz; ! 7851: int make_ctor = 0; ! 7852: int make_dtor = 0; ! 7853: ! 7854: /* this is the place for paranoia */ ! 7855: if (this == 0) error('i',"0->Cdef::dcl(%p)",tbl); ! 7856: if (base != CLASS) error('i',"Cdef::dcl(%d)",base); ! 7857: if (cname == 0) error('i',"unNdC"); ! 7858: if (cname->tp != this) error('i',"badCdef"); ! 7859: if (tbl == 0) error('i',"Cdef::dcl(%n,0)",cname); ! 7860: if (tbl->base != TABLE) error('i',"Cdef::dcl(%n,tbl=%d)",cname,tbl->base); ! 7861: DB( if(Ddebug>=1) error('d',&cname->where,"classdef::dcl %s tbl %d gtbl %d",string,tbl,gtbl); ); ! 7862: // error('d',&cname->where,"classdef::dcl %s tbl %d gtbl %d",string,tbl,gtbl); ! 7863: ! 7864: switch (csu) { ! 7865: case UNION: ! 7866: in_union = UNION; ! 7867: break; ! 7868: case ANON: ! 7869: in_union = ANON; ! 7870: break; ! 7871: case CLASS: ! 7872: scope = 0; ! 7873: } ! 7874: ! 7875: max_align = AL_STRUCT; ! 7876: ! 7877: if (lex_level) { ! 7878: // error('d',&cname->where,"%t::dcl in_class: %t lex_level %d ",this,in_class, lex_level); ! 7879: if ( in_class ) ! 7880: lex_level = 0; ! 7881: else { ! 7882: in_fct = cc->nof; ! 7883: if ( lcl == 0 ) lcl = make_name( 'L' ); ! 7884: } ! 7885: } ! 7886: ! 7887: if (strlen == 0) strlen = ::strlen(string); ! 7888: if (baselist) { ! 7889: /* ! 7890: check base classes. ! 7891: duplicates were removed in start_cl() in norm.c. ! 7892: remove bad classes. ! 7893: add virtual bases from bases to the list. ! 7894: ! 7895: check against ! 7896: class b : a {} ! 7897: class c : a, b {} // first a inaccessible ! 7898: */ ! 7899: ! 7900: Pbcl ll = 0; ! 7901: Pbcl lll = 0; ! 7902: Pbcl vlist = 0; ! 7903: for (Pbcl lx, l=baselist; l; l=lx) { // remove bad bases ! 7904: Pclass cl = l->bclass; ! 7905: /* restriction lifted: nested and local classes ! 7906: int b_nstd = (cl->in_class && cl->nested_sig) ! 7907: ?2:(cl->in_class?1:0); ! 7908: ! 7909: if (b_nstd) ! 7910: error((b_nstd==2)?0:'w',"%s derived from nestedC %s", string, cl->string); ! 7911: if (cl->lex_level) ! 7912: error('w',"%s derived from localC %s", string, cl->string); ! 7913: */ ! 7914: ! 7915: lx = l->next; ! 7916: ! 7917: //error('d',"base1 %t %k init %d",cl,l->ppp,l->init); ! 7918: // ``class'' => private base ``struct'' => public base ! 7919: if (l->ppp == 0) { ! 7920: l->ppp = csu==CLASS ? PRIVATE : PUBLIC; ! 7921: #ifndef OLD ! 7922: if (l->ppp == PRIVATE) error('w',"B%t private by default: please be explicit ``: private%t",cl,cl); ! 7923: #endif ! 7924: } ! 7925: // if you have a ``class'' as base you cannot remain a ! 7926: // ``mere struct'' ! 7927: if (cl && cl->csu == CLASS) st = 0; ! 7928: ! 7929: if ((cl->defined&(DEFINED|SIMPLIFIED)) == 0) { ! 7930: error("BC %sU",cl->string); ! 7931: continue; ! 7932: } ! 7933: else ! 7934: (void)cl->tsizeof(); // ensure printout ! 7935: ! 7936: if (cl->csu==UNION || cl->csu==ANON) { ! 7937: error("C derived from union"); ! 7938: continue; ! 7939: } ! 7940: ! 7941: if (in_union) { ! 7942: error("derived union"); ! 7943: continue; ! 7944: } ! 7945: ! 7946: if (l->base==VIRTUAL) { ! 7947: // constraint removed ... ! 7948: // if (cl->has_ictor()==0 && cl->has_ctor()) { ! 7949: // error("virtualB%t has no defaultIr",cl); ! 7950: // continue; ! 7951: // } ! 7952: // order of virtual classes doesn't matter ! 7953: l->next = vlist; ! 7954: vlist = l; ! 7955: } ! 7956: else { // keep ordinary base classes in order ! 7957: if (ll == 0) { ! 7958: lll = l; ! 7959: l->next = 0; ! 7960: } ! 7961: else ! 7962: ll->next = l; ! 7963: ll = l; ! 7964: } ! 7965: } ! 7966: if (ll) { ! 7967: ll->next = vlist; // put virtual bases at end ! 7968: baselist = lll; ! 7969: } ! 7970: else ! 7971: baselist = vlist; ! 7972: ! 7973: lll = 0; ! 7974: for (l=baselist; l; l=l->next) { // detect unmanageable duplicates ! 7975: Pclass b = l->bclass; ! 7976: for (ll=baselist; ll; ll=ll->next) ! 7977: if (b!=ll->bclass && ll->bclass->check_dup(b,l->base)) { ! 7978: if (lll) ! 7979: lll->next = l->next; ! 7980: else ! 7981: baselist = l->next; ! 7982: goto mmm; ! 7983: } ! 7984: ! 7985: lll = l; ! 7986: mmm:; ! 7987: } ! 7988: ! 7989: for (l=baselist; l; l=l->next) { // promote virtual bases ! 7990: Pclass b = l->bclass; ! 7991: for (ll=b->baselist; ll; ll=ll->next) { ! 7992: if (ll->base == VIRTUAL) { ! 7993: Pclass v = ll->bclass; ! 7994: for (Pbcl lll=baselist; lll; lll=lll->next) ! 7995: if (lll->bclass == v) goto nnn; ! 7996: // error('w',"%t is virtualB of%t",v,this); ! 7997: baselist = new basecl(v,baselist); ! 7998: baselist->base = VIRTUAL; ! 7999: baselist->promoted = 1; ! 8000: // needs a more complete check of visibility rules ! 8001: //error('d',"promote %t %k",v,ll->ppp); ! 8002: baselist->ppp = ll->ppp; ! 8003: } ! 8004: nnn:; ! 8005: } ! 8006: } ! 8007: ! 8008: ll = 0; ! 8009: lll = 0; ! 8010: l=baselist; ! 8011: baselist = 0; ! 8012: vlist = 0; ! 8013: for (; l; l=lx) { ! 8014: // sort virtual bases so that no virtual base ! 8015: // is ahead of its own virtual base ! 8016: lx = l->next; ! 8017: if (l->base == VIRTUAL) { // add to sorted vlist ! 8018: // each class before its bases ! 8019: if (vlist == 0) { ! 8020: vlist = l; ! 8021: l->next = 0; ! 8022: } ! 8023: else { ! 8024: Pclass lb = l->bclass; ! 8025: Pbcl v_prev = 0; ! 8026: for (Pbcl vx, v = vlist; v; v=vx) { ! 8027: Pclass vb = v->bclass; ! 8028: vx = v->next; ! 8029: ! 8030: if (lb->has_base(vb)) { ! 8031: // put l ahead of v ! 8032: l->next = v; ! 8033: if (v_prev) ! 8034: v_prev->next = l; ! 8035: else ! 8036: vlist = l; ! 8037: break; ! 8038: } ! 8039: if (vx == 0) { ! 8040: // stick l at end ! 8041: v->next = l; ! 8042: l->next = 0; ! 8043: break; ! 8044: } ! 8045: v_prev = v; ! 8046: } ! 8047: } ! 8048: } ! 8049: else { // keep in order ! 8050: if (ll == 0) { ! 8051: lll = l; ! 8052: l->next = 0; ! 8053: } ! 8054: else ! 8055: ll->next = l; ! 8056: ll = l; ! 8057: } ! 8058: } ! 8059: ! 8060: if (ll) { ! 8061: ll->next = vlist; // put virtual bases at end ! 8062: baselist = lll; ! 8063: } ! 8064: else ! 8065: baselist = vlist; ! 8066: ! 8067: for (l=baselist; l; l=l->next) { // allocate base class objects ! 8068: Pclass cl = l->bclass; ! 8069: //error('d',"base %t %k init %d",cl,l->ppp,l->init); ! 8070: if (l->base == VIRTUAL) { // : virtual bclass ! 8071: // pointer and object for virtual base MAY ! 8072: // be allocated at the end - but not here ! 8073: c_xref |= C_VBASE; ! 8074: dvirt += cl->virt_count; ! 8075: } ! 8076: else { // : bclass =>allocate ! 8077: int ba = cl->align(); ! 8078: if (max_align<ba) max_align = ba; ! 8079: ! 8080: if (cl == baselist->bclass) { ! 8081: // pad to ensure alignment: ! 8082: boff = cl->real_size; ! 8083: // not obj_size-real_size, we can ! 8084: // optimize vbase object away ! 8085: int xtra = boff%ba; ! 8086: // align ! 8087: if (xtra) boff += ba-xtra; ! 8088: } ! 8089: else { // let C handle the padding: ! 8090: int xtra = boff%ba; ! 8091: if (xtra) boff += ba-xtra; // align ! 8092: l->obj_offset = boff; ! 8093: // don't use waste ! 8094: boff += cl->obj_size; ! 8095: } ! 8096: bvirt += cl->virt_count; ! 8097: } ! 8098: ! 8099: if (cl->has_vvtab) has_vvtab = 1; ! 8100: c_xref |= cl->c_xref; ! 8101: ! 8102: //error('d',"%t: base %t conv %d base conv %d",this,cl,conv,cl->conv); ! 8103: conv = merge_conv(conv,cl->conv); ! 8104: } ! 8105: } ! 8106: ! 8107: memtbl->set_name(cname); ! 8108: ! 8109: // int nmem = mem_list->no_of_names(); ! 8110: int nmem = 0; ! 8111: int fct_mem = 0; ! 8112: { for (Pname m = mem_list; m; m=m->n_list) { ! 8113: nmem++; ! 8114: if (m->tp && m->tp->base==FCT) fct_mem++; ! 8115: } ! 8116: } ! 8117: if (nmem) memtbl->grow((nmem<=2)?3:nmem); ! 8118: ! 8119: cc->stack(); ! 8120: cc->not = cname; ! 8121: cc->cot = this; ! 8122: ! 8123: byte_offset = usz = boff; ! 8124: bit_offset = 0; ! 8125: ! 8126: int real_virts = 0; ! 8127: Pbase bt = new basetype(COBJ,cname); ! 8128: bt->b_table = memtbl; ! 8129: Ptype cct = bt->addrof(); ! 8130: // for strict opt type of `this': X *const ! 8131: // '2' distinguishes this case from a real constant object ! 8132: if (strict_opt) Pptr(cct)->rdo = 2; ! 8133: this_type = cc->tot = cct; ! 8134: PERM(cct); ! 8135: PERM(bt); ! 8136: ! 8137: for (Pname px, p=mem_list; p; p=px) { ! 8138: /* ! 8139: look at each member; ! 8140: declare it and determine its visibility ! 8141: calculate offsets and sizes ! 8142: */ ! 8143: px = p->n_list; ! 8144: // error( 'd', "p: %n %k n_scope: %d", p, p->base, p->n_scope ); ! 8145: ! 8146: switch (p->base) { ! 8147: case PUBLIC: ! 8148: scope = PUBLIC; ! 8149: protect = 0; ! 8150: goto prpr; ! 8151: ! 8152: case PRIVATE: ! 8153: scope = 0; ! 8154: protect = 0; ! 8155: goto prpr; ! 8156: ! 8157: case PROTECTED: ! 8158: scope = 0; ! 8159: protect = PROTECTED; ! 8160: prpr: ! 8161: if (in_union == ANON) error(&p->where,"%k in anonymous unionD",p->base); ! 8162: continue; ! 8163: ! 8164: case PR: // visibility control: C::M ! 8165: { ! 8166: char* qs = p->n_qualifier->string; ! 8167: char* ms = p->string; ! 8168: TOK ppp = scope?PUBLIC:(protect?PROTECTED:PRIVATE); ! 8169: ! 8170: p->base = NAME; ! 8171: p->n_scope = scope; ! 8172: p->n_protect = protect; ! 8173: ! 8174: if (strcmp(ms,qs) == 0) ms = "__ct"; ! 8175: ! 8176: ppbase = PUBLIC; ! 8177: ! 8178: if (is_base(qs) == 0) { ! 8179: error("%kQr %s not aBC of %s",ppp,qs,string); ! 8180: continue; ! 8181: } ! 8182: ! 8183: mex = 1; ! 8184: tcl = mec = this; ! 8185: c_body = 0; // this search must not be interpreted as a use ! 8186: Pname os = Cdcl; ! 8187: Cdcl = p; ! 8188: Pexpr ee = find_name(ms,0,1); ! 8189: Cdcl = os; ! 8190: c_body = 1; ! 8191: ! 8192: // error('d', "ee: %k ", ee->base ); ! 8193: ! 8194: // while (ee->base == MDOT || ee->base == REF) ! 8195: while (ee && (ee->base == MDOT || ee->base == REF)) ! 8196: ee = ee->mem; ! 8197: Pname mx = Pname(ee); ! 8198: ! 8199: // error('d', "ee: %k mx: %n", ee->base, mx ); ! 8200: ! 8201: if (mx == 0) { ! 8202: error("C %s does not have aM %s",qs,ms); ! 8203: continue; ! 8204: } ! 8205: ! 8206: if (mx->tp->base == OVERLOAD) { ! 8207: error('s',"%k specification of overloaded%n",ppp,mx); ! 8208: continue; ! 8209: } ! 8210: ! 8211: TOK pp = mx->n_scope?PUBLIC:mx->n_protect?PROTECTED:PRIVATE; ! 8212: ! 8213: // error('d',"mx %n pp %k ppp %k",mx,pp,ppp); ! 8214: if (ppp != pp) { ! 8215: error(&p->where,"%kM%n specified%k",pp,mx,ppp); ! 8216: continue; ! 8217: } ! 8218: ! 8219: ! 8220: p->n_qualifier = mx; ! 8221: Pname m = memtbl->insert(p,0); ! 8222: m->base = PUBLIC; ! 8223: if (Nold) error("twoDs ofCM%n",p); ! 8224: continue; ! 8225: } ! 8226: } ! 8227: ! 8228: // error('d',"mem%n tp %d %k scope %d",p,p->tp->base,p->tp->base,scope); ! 8229: ! 8230: if (scope==0) { ! 8231: if (p->n_sto != STATIC) st = 0; ! 8232: } ! 8233: else ! 8234: if ( p->tp->base == TYPE ) { ! 8235: Pname nn = p->tp->is_cl_obj(); ! 8236: if (nn) { ! 8237: // error( 'd', "nn: %n %k tp %t %k", nn, nn->base, nn->tp, nn->tp->base ); ! 8238: if ((Pclass(nn->tp)->csu == CLASS) && (strcmp(this->string,nn->string))) st = 0; ! 8239: } ! 8240: } ! 8241: ! 8242: if (p->tp->base == FCT) { ! 8243: int ff = 0; ! 8244: Pfct f = Pfct(p->tp); ! 8245: Pblock b = f->body; ! 8246: f->body = 0; ! 8247: if (b) ! 8248: f->f_inline = 1; ! 8249: /* restriction lifted: nested classes ! 8250: else ! 8251: if (nstd) ! 8252: error((nstd==2)?0:'w',&p->where,"non-inlineMF%n in nestedC %s",p,string); ! 8253: */ ! 8254: else ! 8255: if (lex_level) ! 8256: error('w',&p->where,"non-inlineMF%n in localC %s",p,string); ! 8257: ! 8258: switch (p->n_sto) { ! 8259: case FRIEND: ! 8260: ff = 1; ! 8261: break; ! 8262: case STATIC: // accept static member functions ! 8263: //error('d',"inline %d",f->f_inline); ! 8264: // if (f->f_inline==0) ! 8265: /* restriction lifted: nested classes ! 8266: if (nstd) ! 8267: error((nstd==2)?0:'w',"staticMF%n in nestedC %s",p,string); ! 8268: else ! 8269: */ ! 8270: if (lex_level) ! 8271: error('w',"staticMF%n in localC %s",p,string); ! 8272: f->f_static = 1; ! 8273: p->n_sto = 0; ! 8274: break; ! 8275: case AUTO: ! 8276: // case STATIC: ! 8277: case REGISTER: ! 8278: case EXTERN: ! 8279: error(&p->where,"M%n cannot be%k",p,p->n_sto); ! 8280: p->n_sto = 0; ! 8281: } ! 8282: ! 8283: if (f->f_virtual) real_virts++; ! 8284: ! 8285: Pname m = p->dcl(memtbl,scope); ! 8286: if (m == 0 || m->tp->base != FCT) continue; ! 8287: if (m->n_initializer) { ! 8288: c_abstract = 1; ! 8289: if (m->n_oper == DTOR) ! 8290: error('w',"please provide an out-of-line definition: %n {}; which is needed by derived classes",m); ! 8291: } ! 8292: if (ff == 0) m->n_protect = protect; ! 8293: if (b) { ! 8294: if (m->tp->defined&DEFINED || Pfct(m->tp)->body ) ! 8295: error(&p->where,"two definitions of%n",m); ! 8296: else ! 8297: Pfct(m->tp)->body = b; ! 8298: // Pfct(m->tp)->f_inline = 1; ! 8299: } ! 8300: if (ff==0 && p->where.line!=m->where.line) ! 8301: error(&p->where,"%n cannot be redeclared inCD",p); ! 8302: } ! 8303: else { ! 8304: Eppp = scope?scope:protect?protect:0; ! 8305: ! 8306: if (p->base == TNAME) { ! 8307: // typedef names are exported to ! 8308: // surrounding non-class scope ! 8309: // NOTE: name should actually be declared in ! 8310: // the innermost block of the current ! 8311: // function, but this info isn't available ! 8312: if ( cc->nof ) { ! 8313: if (p->tp && ! 8314: Pbase(p->tp)->base != COBJ && ! 8315: Pbase(p->tp)->base != EOBJ) { ! 8316: Pname n = cc->ftbl->look(p->string,0); ! 8317: if (n && n->base != TNAME && ! 8318: n->lex_level && ! 8319: n->tp != p->tp ) { ! 8320: error('s',"transitional model of nestedTs within%n (%s asTdef and%t)",cc->nof,p->string,n->tp); ! 8321: error('i', "cannot recover from previous errors" ); ! 8322: } ! 8323: } ! 8324: else p->dcl(cc->ftbl,scope); ! 8325: } ! 8326: else ! 8327: p->dcl(gtbl,scope); ! 8328: ! 8329: // typedefs need to be generated outside class ! 8330: if ( p->tp && Pbase(p->tp)->base != COBJ ) { ! 8331: Pname n = gtbl->look(p->string,0); ! 8332: if ( n && lex_level == 0 && n->base != TNAME ) ! 8333: error(&p->where,"%nredefined: identifier and typedef",p); ! 8334: p->dcl_print(0); ! 8335: } ! 8336: continue; ! 8337: }; ! 8338: ! 8339: if (p->n_initializer) { ! 8340: error(&p->where,"Ir forM%n",p); ! 8341: p->n_initializer = 0; ! 8342: } ! 8343: ! 8344: if (p->tp->base==OVERLOAD) { ! 8345: for (Plist gl=Pgen(p->tp)->fct_list; gl; gl=gl->l) { ! 8346: Pname nn = gl->f; ! 8347: Pfct ff = Pfct(nn->tp); ! 8348: if ( ff->f_virtual ) real_virts++; ! 8349: } ! 8350: } ! 8351: ! 8352: // error('d',"lex_level %d p %n lex %d nested_scope: %k",lex_level,p,p->lex_level, nested_scope); ! 8353: ! 8354: TOK is_friend = p->n_sto; ! 8355: if ( lex_level && p->tp->base == VEC ) lcl_tbl = tbl; ! 8356: if ( protect && p->tp->base == COBJ && ! 8357: Pclass(Pbase(p->tp)->b_name->tp)->csu == ANON ) ! 8358: p->n_protect = protect; ! 8359: Pname m = p->dcl(memtbl,scope); ! 8360: lcl_tbl = 0; ! 8361: Eppp = 0; ! 8362: if (m == 0) continue; ! 8363: ! 8364: m->n_protect = protect; ! 8365: ! 8366: if (m->n_stclass==STATIC) { ! 8367: if (in_union) error("staticM%n in union",m); ! 8368: if ( is_friend != FRIEND ) { ! 8369: /* restriction lifted: nested classes ! 8370: if (nstd) ! 8371: error((nstd==2)?0:'w',"staticM%n in nestedC %s",m,string); ! 8372: else ! 8373: */ ! 8374: if (lex_level) ! 8375: error(strict_opt?0:'w',"staticM%n in localC %s (anachronism)",m,string); ! 8376: } ! 8377: // Ptype t = m->tp; ! 8378: // Pname cn = t->is_cl_obj(); ! 8379: // if ((cn && Pclass(cn->tp)->has_ctor()) ! 8380: // || t->is_ref() ! 8381: // || (t->tconst() && vec_const == 0)) ! 8382: m->n_sto = EXTERN; ! 8383: if (tbl == gtbl) stat_mem_list = new name_list(m,stat_mem_list); ! 8384: if (m->n_initializer) error('s',"staticM%nWIr",m); ! 8385: } ! 8386: ! 8387: if (in_union) { ! 8388: if (usz < byte_offset) usz = byte_offset; ! 8389: byte_offset = 0; ! 8390: if(in_union==ANON) m->n_offset+=byte_old; ! 8391: } ! 8392: } ! 8393: } ! 8394: ! 8395: /* restriction lifted: nested and local classes ! 8396: if (real_virts) { ! 8397: if (nstd) ! 8398: error((nstd==2)?0:'w',"nestedC%s contains%d virtualF",string,real_virts); ! 8399: else ! 8400: if (lex_level) ! 8401: error('w',"localC%s contains%d virtualF",string,real_virts); ! 8402: } ! 8403: */ ! 8404: ! 8405: if (st && csu==CLASS) csu = STRUCT; // nothing private => STRUCT ! 8406: if (st==0 && csu==STRUCT) csu = CLASS; // all is not public => CLASS ! 8407: ! 8408: if (in_union) byte_offset = usz; ! 8409: ! 8410: // now look look at the members ! 8411: ! 8412: Pname ct = has_ctor(); ! 8413: Pname dt = has_dtor(); ! 8414: ! 8415: int i; ! 8416: ! 8417: int omex = mex; mex = 0; ! 8418: Pname on = has_oper(NEW); ! 8419: Pname od = has_oper(DELETE); ! 8420: mex = omex; ! 8421: ! 8422: if (dt && ct==0 && Pfct(dt->tp)->f_virtual == 0 ) error('w',"%s has%n but noK",string,dt); ! 8423: if (on && od==0) error('w',"%s has%n but no operator delete()",string,on); ! 8424: if (od && on==0) error('w',"%s has%n but no operator new()",string,od); ! 8425: ! 8426: if (dt==0 && od && od && od->n_table==memtbl) make_dtor = 1; ! 8427: ! 8428: for (Pname m=memtbl->get_mem(i=1); m; m=memtbl->get_mem(++i) ) { ! 8429: /* ! 8430: The members have been declared. ! 8431: now look at each to see if it needs defining ! 8432: */ ! 8433: Ptype t = m->tp; ! 8434: ! 8435: if (t == 0) continue; // public declarations ! 8436: // error('d', "m %n %d", m, m->n_scope ); ! 8437: ! 8438: switch (t->base) { ! 8439: default: ! 8440: if (ct==0 ! 8441: && m->n_stclass!=ENUM ! 8442: && m->n_stclass!=STATIC) { ! 8443: if (t->is_ref()) error("R%n inC %sWoutK",m,string); ! 8444: if (t->tconst() ! 8445: && vec_const==0 ! 8446: && m->n_evaluated==0) ! 8447: error("const%n inC %sWoutK",m,string); ! 8448: } ! 8449: case VEC: ! 8450: break; ! 8451: case FCT: ! 8452: case OVERLOAD: ! 8453: case CLASS: ! 8454: case ENUM: ! 8455: continue; ! 8456: } ! 8457: ! 8458: Pname cn = t->is_cl_obj(); ! 8459: if (cn == 0) cn = cl_obj_vec; ! 8460: if (cn == 0) continue; ! 8461: ! 8462: Pclass cl = Pclass(cn->tp); ! 8463: c_xref |= cl->c_xref; ! 8464: //error('d',"m %n %t %d",m,cl,cl->c_xref); ! 8465: if (cl->has_ctor()) { ! 8466: if (m->n_stclass == STATIC) ! 8467: ; // error('s',"staticM%n ofC%nWK",m,cn); ! 8468: else if (in_union) { ! 8469: if (strncmp("__C",string,3) == 0) ! 8470: error("M %s ofC%nWK in union",m->string,cn); // tagless union ! 8471: else error("M%n ofC%nWK in union",m,cn); ! 8472: } ! 8473: else if (ct == 0) { ! 8474: // does mctor have a default constructor? ! 8475: if (make_ctor==0 && cl->has_ictor()==0) ! 8476: error("%t needs aK; it has aMWK requiringAs",this); ! 8477: make_ctor = 1; ! 8478: } ! 8479: } ! 8480: ! 8481: if (cl->has_dtor()) { ! 8482: if (m->n_stclass==STATIC) ! 8483: ; // error('s',"staticM%n ofC%nW destructor",m,cn); ! 8484: else if (in_union) { ! 8485: if (strncmp("__C",string,3) == 0) // tagless union ! 8486: error("M %s ofC%nW destructor in union",m->string,cn); ! 8487: else error("M%n ofC%nW destructor in union",m,cn); ! 8488: } ! 8489: else if (dt==0) ! 8490: make_dtor = 1; ! 8491: } ! 8492: } ! 8493: ! 8494: if (has_dtor()==0 && make_dtor==0) { ! 8495: // can dtor be inherited (from single base class)? ! 8496: Pclass bcl = 0; ! 8497: for (Pbcl b = baselist; b; b = b->next) { ! 8498: switch (b->base) { ! 8499: case NAME: ! 8500: if (bcl == 0) { ! 8501: Pname d = b->bclass->has_dtor(); ! 8502: if (d==0) break; ! 8503: if (strict_opt == 0) { ! 8504: if (d->n_scope==PUBLIC ! 8505: && Pfct(d->tp)->f_virtual==0) { ! 8506: bcl = b->bclass; ! 8507: break; ! 8508: } ! 8509: } ! 8510: } ! 8511: // two dtors or non-public dtors force creation ! 8512: make_dtor = 1; ! 8513: goto zbzb; ! 8514: case VIRTUAL: ! 8515: if (b->bclass->has_dtor()) make_dtor = 1; ! 8516: goto zbzb; ! 8517: } ! 8518: } ! 8519: if (bcl) c_dtor = bcl->has_dtor(); ! 8520: zbzb:; ! 8521: } ! 8522: ! 8523: if (make_dtor && dt==0) { // make x::~x() {} ! 8524: ! 8525: // must be done before vtbls are made in case dtor is virtual ! 8526: //error('d',"%t: make_dtor",this); ! 8527: Pname n = new name(string); ! 8528: Pfct f = new fct(defa_type,0,1); ! 8529: f->f_inline = /*IDTOR; */ 1; ! 8530: n->tp = f; ! 8531: n->n_oper = DTOR; ! 8532: dt = n->dcl(memtbl,PUBLIC); ! 8533: delete n; ! 8534: Pfct(dt->tp)->body = /*0; */ new block(curloc,0,0); ! 8535: dt = has_dtor(); ! 8536: } ! 8537: ! 8538: if (virt_count && find_vptr(this)==0) { ! 8539: // we only need a vptr if this class has virtual ! 8540: // functions and none of its first bases have vptrs ! 8541: //error('d',"%s virt_count %d",string,virt_count); ! 8542: Pname vp = new name("__vptr"); ! 8543: vp->tp = Pvptr_type; ! 8544: (void) vp->dcl(memtbl,0); ! 8545: delete vp; ! 8546: c_xref |= C_VPTR; ! 8547: } ! 8548: else { ! 8549: //error("byte_offset %d bit_offset %d bitsinbyte %d",byte_offset,bit_offset,BI_IN_BYTE); ! 8550: //error(" div %d mod %d",bit_offset/BI_IN_BYTE,bit_offset%BI_IN_BYTE); ! 8551: // no more bit fields. absorb bit_offset ! 8552: if (bit_offset) { ! 8553: byte_offset += (bit_offset/BI_IN_BYTE + (bit_offset%BI_IN_BYTE?1:0)); ! 8554: bit_offset = 0; ! 8555: } ! 8556: } ! 8557: //error("byte_offset %d bit_offset %d",byte_offset,bit_offset); ! 8558: ! 8559: for (Pbcl b = baselist; b; b = b->next) { // allocate virtual base pointers ! 8560: if (b->base != VIRTUAL) continue; ! 8561: Pclass bcl = b->bclass; ! 8562: ! 8563: // search non-virtual bases for this virtual base ! 8564: for (Pbcl bb = baselist; bb; bb = bb->next) ! 8565: if (bb->base == NAME) { ! 8566: for (Pbcl l = bb->bclass->baselist; l; l=l->next) ! 8567: if (l->base==VIRTUAL && l->bclass==bcl) goto eee; ! 8568: } ! 8569: { ! 8570: if (obj_align<AL_WPTR) obj_align = AL_WPTR; ! 8571: if (max_align<AL_WPTR) max_align = AL_WPTR; ! 8572: int waste = byte_offset%AL_WPTR; ! 8573: if (waste) byte_offset += AL_WPTR-waste; // align ! 8574: b->ptr_offset = byte_offset+1; // ensure != 0 ! 8575: byte_offset += sizeof(int*); ! 8576: } ! 8577: eee:; ! 8578: } ! 8579: ! 8580: real_size = byte_offset; // the rest may be optimized away ! 8581: ! 8582: for (b = baselist; b; b = b->next) { // allocate virtual class objects ! 8583: if (b->base != VIRTUAL) continue; ! 8584: Pclass bcl = b->bclass; ! 8585: ! 8586: // if necessary ! 8587: if (b->obj_offset = has_allocated_base(bcl)) continue; ! 8588: ! 8589: int ba = bcl->align(); ! 8590: if (obj_align<ba) obj_align = ba; ! 8591: if (max_align<ba) max_align = ba; ! 8592: int waste = byte_offset%ba; ! 8593: if (waste) byte_offset += ba-waste; // align ! 8594: b->obj_offset = byte_offset; // offset in this ! 8595: b->allocated = 1; ! 8596: //error('d',"virtual %t in %t at %d",bcl,this,b->obj_offset); ! 8597: byte_offset += bcl->tsizeof(); ! 8598: } ! 8599: ! 8600: // no more data members. ! 8601: // pad object (so that copying into a base object ! 8602: // doesn't destroy derevid class members): ! 8603: if (byte_offset==0) { // empty struct: waste a member ! 8604: Pname c = new name (make_name('W')); ! 8605: c->tp = char_type; ! 8606: (void) c->dcl(memtbl,0); ! 8607: real_size = byte_offset = 1; ! 8608: } ! 8609: if (byte_offset < SZ_STRUCT) byte_offset = SZ_STRUCT; ! 8610: int waste = byte_offset%max_align; ! 8611: //error('d',"max_align %d waste %d byte_offset %d",max_align,waste,byte_offset); ! 8612: if (waste) byte_offset += max_align-waste; ! 8613: obj_size = byte_offset; ! 8614: obj_align = max_align; ! 8615: ! 8616: // make vtbls ! 8617: // this cannot be done until the bases ! 8618: // have been allocated in this class ! 8619: // so that the offsets (deltas) are known ! 8620: if (all_virt(this,0,1,0)) { ! 8621: if (has_ctor()==0) make_ctor = 1; ! 8622: } ! 8623: else if (has_vvtab) ! 8624: error("virtualB: conflicting vtable initialization"); ! 8625: ! 8626: // error('d',"%t->classdef: virt_count: %d virt_merge: %d",this,virt_count,virt_merge); ! 8627: ! 8628: Pname hito = has_itor(); ! 8629: ! 8630: if (hito) c_xref |= C_XREF; // has user defined X(X&) ! 8631: //error('d',"%t hito %d ctor %d",this,hito,make_ctor); ! 8632: if (hito==0 && c_xref&(C_VPTR|C_VBASE|C_XREF)) { ! 8633: // X(X&) needed if bitwise copy is illegal ! 8634: // or if any constructor is defined ! 8635: ! 8636: hito = make_itor(0); ! 8637: // if the base has B::B(void) ! 8638: // the derived should have D::D(void) ! 8639: if (baselist) { ! 8640: int mc = 1; // can make and ictor ! 8641: for (Pbcl b = baselist; b; b = b->next) { ! 8642: if (b->bclass->has_ctor() ! 8643: && b->bclass->has_ictor()==0) ! 8644: mc = 0; ! 8645: } ! 8646: make_ctor = mc; ! 8647: /* ! 8648: int mc = 1; // can make an ictor ! 8649: for (Pbcl b = baselist; b; b = b->next) { ! 8650: if (b->bclass->has_ctor()) { ! 8651: Pname c = b->bclass->has_ictor(); ! 8652: // no copy constructor? ! 8653: // non-public copy constructor? ! 8654: if (c==0 || c->n_scope==0) mc = 0; ! 8655: } ! 8656: } ! 8657: make_ctor = mc; ! 8658: */ ! 8659: } ! 8660: else ! 8661: make_ctor = 1; ! 8662: } ! 8663: ! 8664: if (c_ctor==0 && make_ctor==0) { // can ctor be inherited (from single base class)? ! 8665: /* ! 8666: int bb = 0; ! 8667: for (Pbcl b = baselist; b; b = b->next) { ! 8668: switch (b->base) { ! 8669: case NAME: ! 8670: { Pname c = b->bclass->has_ctor(); ! 8671: // if (b->bclass->has_ctor() == 0) break; ! 8672: if (c == 0) break; ! 8673: if (c->n_scope==PUBLIC && bb++==0) break; ! 8674: } ! 8675: // no break: two bases: needs ctor ! 8676: case VIRTUAL: ! 8677: make_ctor = 1; // virtual base: need ctor ! 8678: goto zaza; ! 8679: } ! 8680: } ! 8681: */ ! 8682: Pname btor = 0; ! 8683: Pclass bc = 0; ! 8684: for (Pbcl b = baselist; b; b = b->next) { ! 8685: switch (b->base) { ! 8686: case NAME: ! 8687: { Pname c = b->bclass->has_ctor(); ! 8688: if (c == 0) break; ! 8689: if (c->n_scope==PUBLIC && b==baselist) { ! 8690: bc = b->bclass; ! 8691: btor = bc->has_ictor(); ! 8692: break; ! 8693: } ! 8694: } ! 8695: // no break: two bases: needs ctor ! 8696: case VIRTUAL: ! 8697: make_ctor = 1; // virtual base: need ctor ! 8698: goto zaza; ! 8699: } ! 8700: } ! 8701: // c_ctor = btor; ! 8702: //error('d',"btor %n",btor); ! 8703: if (bc) { ! 8704: if (btor) ! 8705: make_ctor = 1; ! 8706: else ! 8707: error("K needed for %s, BC%t hasK",string,bc); ! 8708: } ! 8709: zaza:; ! 8710: } ! 8711: ! 8712: if (make_ctor && ct==0) { // make x::x() {} ! 8713: //error('d',"%t: make_ctor",this); ! 8714: Pname n = new name(string); ! 8715: Pfct f = new fct(defa_type,0,1); ! 8716: f->f_inline = 1; // ICTOR; // ICTOR means ``define ctor() if used'' ! 8717: n->tp = f; ! 8718: n->n_oper = TNAME; ! 8719: ct = n->dcl(memtbl,PUBLIC); ! 8720: delete n; ! 8721: Pfct(ct->tp)->body = /* 0; */ new block(curloc,0,0); ! 8722: } ! 8723: ! 8724: defined |= DEFINED; ! 8725: ! 8726: if (ansi_opt) { ! 8727: char* s = csu==UNION || csu==ANON ? "union" : "struct"; ! 8728: fprintf(out_file,"%s %s;",s,string); ! 8729: } ! 8730: //error('d',"defined %s",string); ! 8731: ! 8732: // fix argument lists for inlines ! 8733: for (p=memtbl->get_mem(i=1); p; p=memtbl->get_mem(++i)) { ! 8734: Pfct f = Pfct(p->tp); ! 8735: if (f==0) continue; // public declarations ! 8736: ! 8737: switch (f->base) { ! 8738: case FCT: ! 8739: /* prohibit something like the following: ! 8740: typedef int t1; ! 8741: class x { ! 8742: typedef int t1; ! 8743: t1 foo(); ! 8744: }; ! 8745: */ ! 8746: if (f->returns->base == TYPE) { ! 8747: Pname nn = Pbase(f->returns)->b_name; ! 8748: while ( nn->tp->base == TYPE ) ! 8749: nn = Pbase(nn->tp)->b_name; ! 8750: if (nn->n_key == NESTED) { ! 8751: Ptype tt; ! 8752: if ( nn->tp->base != EOBJ && ! 8753: nn->tp->base != COBJ ) ! 8754: tt = nn->tpdef; ! 8755: else tt = Pbase(nn->tp)->b_name->tp; ! 8756: if ( tt && tt->nested_sig ) ! 8757: error('w',"nested %s as returnT for non-inlineMF, use %t::%s %n{} in definition (anachronism)",nn->string,tt->in_class,nn->string,p); ! 8758: } ! 8759: } ! 8760: ! 8761: if (hito && f->argtype) fix_args(f,this); ! 8762: if (p->n_oper == CTOR) f->s_returns = this_type; ! 8763: if (f->body) p->n_sto = STATIC; ! 8764: break; ! 8765: case OVERLOAD: ! 8766: { Pgen g = Pgen(f); ! 8767: for (Plist gl=g->fct_list; gl; gl=gl->l) { ! 8768: Pname n = gl->f; ! 8769: Pfct f = Pfct(n->tp); ! 8770: ! 8771: if (hito && f->argtype) fix_args(f,this); ! 8772: if (n->n_oper == CTOR) f->s_returns = this_type; ! 8773: if (f->body) n->n_sto = STATIC; ! 8774: } ! 8775: } ! 8776: } ! 8777: } ! 8778: ! 8779: // define members defined inline ! 8780: for (p=memtbl->get_mem(i=1); p; p=memtbl->get_mem(++i)) { ! 8781: Pfct f = Pfct(p->tp); ! 8782: if (f==0) continue; // public declarations ! 8783: ! 8784: switch (f->base) { ! 8785: case FCT: ! 8786: if (f->body) { ! 8787: f->dcl(p); ! 8788: p->simpl(); ! 8789: } ! 8790: break; ! 8791: case OVERLOAD: ! 8792: { Pgen g = Pgen(f); ! 8793: for (Plist gl=g->fct_list; gl; gl=gl->l) { ! 8794: Pname n = gl->f; ! 8795: Pfct f = Pfct(n->tp); ! 8796: ! 8797: if (f->body) { ! 8798: f->dcl(n); ! 8799: n->simpl(); ! 8800: } ! 8801: } ! 8802: } ! 8803: } ! 8804: } ! 8805: ! 8806: byte_offset = byte_old; ! 8807: bit_offset = bit_old; ! 8808: max_align = max_old; ! 8809: ! 8810: cc->unstack(); // friends are not in class scope ! 8811: ! 8812: // fix arguments lists for friends defined inline ! 8813: for (Plist fl=friend_list; fl; fl=fl->l) { ! 8814: Pname p = fl->f; ! 8815: Pfct f = Pfct(p->tp); ! 8816: ! 8817: switch (f->base) { ! 8818: case FCT: ! 8819: if (hito && f->argtype) fix_args(f,this); ! 8820: if (f->body && ! 8821: (f->defined&(DEFINED|SIMPLIFIED)) == 0) ! 8822: p->n_sto = STATIC; ! 8823: else ! 8824: if (p->n_scope == STATIC) ! 8825: error(strict_opt?0:'w',"static%n declared friend toC%t",p,this); ! 8826: break; ! 8827: case OVERLOAD: ! 8828: { Pgen g = Pgen(f); ! 8829: for (Plist gl=g->fct_list; gl; gl=gl->l) { ! 8830: Pname n = gl->f; ! 8831: Pfct f = Pfct(n->tp); ! 8832: ! 8833: if (hito && f->argtype) fix_args(f,this); ! 8834: if (f->body && ! 8835: (f->defined&(DEFINED|SIMPLIFIED)) == 0) ! 8836: n->n_sto = STATIC; ! 8837: else ! 8838: if (p->n_scope == STATIC) ! 8839: error(strict_opt?0:'w',"static%n declared friend toC%t",p,this); ! 8840: } ! 8841: } ! 8842: } ! 8843: } ! 8844: ! 8845: // define friends defined inline and modify return types if necessary ! 8846: for (fl=friend_list; fl; fl=fl->l) { ! 8847: Pname p = fl->f; ! 8848: Pfct f = Pfct(p->tp); ! 8849: ! 8850: switch (f->base) { ! 8851: case FCT: ! 8852: if (f->body && ! 8853: (f->defined&(DEFINED|SIMPLIFIED)) == 0) { ! 8854: f->dcl(p); ! 8855: p->simpl(); ! 8856: } ! 8857: break; ! 8858: case OVERLOAD: ! 8859: { Pgen g = Pgen(f); ! 8860: for (Plist gl=g->fct_list; gl; gl=gl->l) { ! 8861: Pname n = gl->f; ! 8862: Pfct f = Pfct(n->tp); ! 8863: ! 8864: if (f->body && ! 8865: (f->defined&(DEFINED|SIMPLIFIED)) == 0) { ! 8866: f->dcl(n); ! 8867: n->simpl(); ! 8868: } ! 8869: } ! 8870: } ! 8871: } ! 8872: } ! 8873: ! 8874: if (tbl != gtbl) this->simpl(); ! 8875: ! 8876: if ( statStat && strcmp(statStat->string,string)==0) { ! 8877: //error('d', "classdef::dcl: statstat: %n this %s", statStat, string); ! 8878: statStat->hide(); ! 8879: statStat = 0; ! 8880: } ! 8881: // error('d',"classdef::dcl defined: %d",defined); ! 8882: // catch refs to this class in body of nested class function ! 8883: // (i.e., ref to member of this class...) ! 8884: if ( (defined&REF_SEEN) != 0 ) dcl_print(0); ! 8885: ! 8886: if ( debug_opt ) { ! 8887: for (p=memtbl->get_mem(i=1); p; p=memtbl->get_mem(++i)) { ! 8888: Pfct f = Pfct(p->tp); ! 8889: if (f==0) continue; // public declarations ! 8890: ! 8891: switch (f->base) { ! 8892: case FCT: ! 8893: if (f->body) { ! 8894: if ( c_body == 1 ) dcl_print(0); ! 8895: p->dcl_print(0); ! 8896: } ! 8897: break; ! 8898: case OVERLOAD: ! 8899: { ! 8900: Pgen g = Pgen(f); ! 8901: for (Plist gl=g->fct_list; gl; gl=gl->l) { ! 8902: Pname n = gl->f; ! 8903: Pfct f = Pfct(n->tp); ! 8904: if (f->body) { ! 8905: if ( c_body == 1 ) dcl_print(0); ! 8906: p->dcl_print(0); ! 8907: } ! 8908: } ! 8909: } ! 8910: } ! 8911: } ! 8912: ! 8913: for (fl=friend_list; fl; fl=fl->l) { ! 8914: Pname p = fl->f; ! 8915: Pfct f = Pfct(p->tp); ! 8916: ! 8917: switch (f->base) { ! 8918: case FCT: ! 8919: if (f->body && ! 8920: (f->defined&(DEFINED|SIMPLIFIED)) == 0) ! 8921: p->dcl_print(0); ! 8922: break; ! 8923: case OVERLOAD: ! 8924: { ! 8925: Pgen g = Pgen(f); ! 8926: for (Plist gl=g->fct_list; gl; gl=gl->l) { ! 8927: Pname n = gl->f; ! 8928: Pfct f = Pfct(n->tp); ! 8929: ! 8930: if (f->body && ! 8931: (f->defined&(DEFINED|SIMPLIFIED)) == 0) ! 8932: p->dcl_print(0); ! 8933: } ! 8934: } ! 8935: } ! 8936: } ! 8937: } // end, if (debug_opt) ! 8938: } ! 8939: ! 8940: void enumdef::dcl(Pname n, Ptable tbl) ! 8941: { ! 8942: // if (this == 0) error('i',"0->enumdef::dcl(%p)",tbl); ! 8943: Pname px; ! 8944: Pname p = mem; ! 8945: DB( if(Ddebug>=1) error('d',&n->where,"enumdef(%n,%d)",n,tbl); ); ! 8946: Pbase b = new basetype(EOBJ,n); ! 8947: b->b_const = 1; ! 8948: ! 8949: #define FIRST_ENUM 0 ! 8950: int enum_count = FIRST_ENUM; ! 8951: no_of_enumerators = mem->no_of_names(); ! 8952: int largest = 0; ! 8953: ! 8954: if (p == 0) mem = new name(make_name('e')); ! 8955: ! 8956: for (; p; p=px) { ! 8957: px = p->n_list; ! 8958: // error( 'd', "p %n", p ); ! 8959: if (p->n_initializer) { ! 8960: Pexpr i = p->n_initializer->typ(tbl); ! 8961: Neval = 0; ! 8962: long ii = i->eval(); ! 8963: if (largest_int<ii) error("long enumerator"); ! 8964: enum_count = int(ii); ! 8965: if (Neval) error("%s",Neval); ! 8966: DEL(i); ! 8967: p->n_initializer = 0; ! 8968: } ! 8969: p->n_evaluated = 1; ! 8970: largest |= enum_count; ! 8971: p->n_val = enum_count++; ! 8972: p->tp = b; ! 8973: ! 8974: Pname nn = tbl->insert(p,0); ! 8975: if (Nold) { ! 8976: if (nn->n_stclass == ENUM) { ! 8977: // error( (p->n_val!=nn->n_val)?0:'w',"enumerator%n declared twice",nn); ! 8978: // if (p->n_val!=nn->n_val) ! 8979: error("enumerator%n declared twice",nn); ! 8980: ! 8981: } ! 8982: else ! 8983: error("incompatibleDs of%n",nn); ! 8984: } ! 8985: else { ! 8986: nn->n_stclass = ENUM; // no store will be allocated ! 8987: if (Eppp == PROTECTED) ! 8988: nn->n_protect = PROTECTED; ! 8989: else if (Eppp == PUBLIC) ! 8990: nn->n_scope = PUBLIC; ! 8991: } ! 8992: p->string = nn->string; ! 8993: // delete p; ! 8994: } ! 8995: ! 8996: // mem = 0; ! 8997: ! 8998: // chose a shorter representation for the enum? ! 8999: // if (largest&0133 == largest) ! 9000: // e_type = char_type; ! 9001: // else if largest&077777 == largest) ! 9002: // e_type = short_type; ! 9003: // else ! 9004: e_type = int_type; ! 9005: ! 9006: defined |= DEFINED; ! 9007: } ! 9008: ! 9009: ! 9010: 0707071010112044131004440001630000160000010175600466055377200000600000013077del.c /*ident "@(#)ctrans:src/del.c 1.3" */ ! 9011: /************************************************************ ! 9012: ! 9013: C++ source for cfront, the C++ compiler front-end ! 9014: written in the computer science research center of Bell Labs ! 9015: ! 9016: Copyright (c) 1984 AT&T, Inc. All rights Reserved ! 9017: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 9018: ! 9019: del.c: ! 9020: ! 9021: walk the trees to reclaim storage ! 9022: ! 9023: **************************************************************/ ! 9024: ! 9025: #include "cfront.h" ! 9026: ! 9027: void name::del() ! 9028: { ! 9029: DB( if(Adebug>=1) { ! 9030: fprintf(stderr,"\n*** '%s'->del()",string?string:"???"); ! 9031: display_type(tp); putc(' ',stderr); ! 9032: where.put(stderr); putc('\n',stderr); ! 9033: } ! 9034: if ( base!=NAME && base!=TNAME ) error('i',"name::del() of%k -- id==%ld",base,node::id); ! 9035: ); ! 9036: Pexpr i = n_initializer; ! 9037: ! 9038: // error('d', "\nname::del: %d %s", this, string?string:"no name" ); ! 9039: // NFn++; ! 9040: DEL(tp); ! 9041: if(i && i!=(Pexpr)1) DEL(i); ! 9042: delete this; ! 9043: } ! 9044: ! 9045: void type::del() ! 9046: { ! 9047: DB( if(Adebug>=1) { ! 9048: fprintf(stderr,"\n*** '"); ! 9049: display_type(this); ! 9050: fprintf(stderr," '->del()\n"); ! 9051: } ! 9052: ); ! 9053: //fprintf(stderr,"DEL(type=%d %d)\n",this,base); ! 9054: permanent = 3; /* do not delete twice */ ! 9055: switch (base) { ! 9056: case TNAME: ! 9057: case NAME: ! 9058: error('i',"%d->T::del():N %s %d",this,Pname(this)->string,base); ! 9059: case FCT: ! 9060: { Pfct f = (Pfct) this; ! 9061: DEL(f->returns); ! 9062: delete f; ! 9063: break; ! 9064: } ! 9065: case VEC: ! 9066: { Pvec v = (Pvec) this; ! 9067: DEL(v->dim); ! 9068: DEL(v->typ); ! 9069: delete v; ! 9070: break; ! 9071: } ! 9072: case PTR: ! 9073: case RPTR: ! 9074: { Pptr p = (Pptr) this; ! 9075: DEL(p->typ); ! 9076: delete p; ! 9077: break; ! 9078: } ! 9079: } ! 9080: } ! 9081: ! 9082: void expr::del() ! 9083: { ! 9084: DB( if(Adebug>=1) { ! 9085: fprintf(stderr,"\n*** expr::del(): "); ! 9086: display_expr(this,0,1); ! 9087: if(Adebug>=2) display_expr(this); ! 9088: }); ! 9089: //fprintf(stderr,"DEL(expr=%d: %d %d %d)\n",this,base,e1,e2); fflush(stderr); ! 9090: permanent = 3; ! 9091: switch (base) { ! 9092: case IVAL: ! 9093: if (this == one) return; ! 9094: //case FVAL: ! 9095: case THIS: ! 9096: case ICON: ! 9097: case FCON: ! 9098: case CCON: ! 9099: case STRING: ! 9100: case TEXT: ! 9101: goto dd; ! 9102: case DUMMY: ! 9103: case ZERO: ! 9104: case NAME: ! 9105: return; ! 9106: case CAST: ! 9107: case SIZEOF: ! 9108: case NEW: ! 9109: case GNEW: ! 9110: case VALUE: ! 9111: DEL(tp2); ! 9112: break; ! 9113: case REF: ! 9114: case DOT: ! 9115: DEL(e1); ! 9116: if (e2) DEL(e2); ! 9117: case MDOT: ! 9118: if (mem && mem->base!=NAME) DEL(mem); ! 9119: if ( i1 == 5 ) delete string4; ! 9120: goto dd; ! 9121: case QUEST: ! 9122: DEL(cond); ! 9123: break; ! 9124: case ICALL: ! 9125: delete il->i_args; ! 9126: delete il; ! 9127: goto dd; ! 9128: case ELIST: { // limit recursion ! 9129: Pexpr tp = e2; ! 9130: while ( tp && tp->e2 && tp->e2->base == ELIST ) { ! 9131: Pexpr x = tp; ! 9132: if ( x->permanent ) break; ! 9133: x->permanent = 3; ! 9134: tp = tp->e2; ! 9135: if ( x->e1 ) DEL(x->e1); ! 9136: delete x; ! 9137: } ! 9138: e2 = tp; ! 9139: break; ! 9140: } ! 9141: } ! 9142: ! 9143: DEL(e1); ! 9144: DEL(e2); ! 9145: dd: ! 9146: delete this; ! 9147: } ! 9148: ! 9149: void stmt::del() ! 9150: { ! 9151: DB( if(Adebug>=1) { ! 9152: fprintf(stderr,"\n*** stmt::del(): "); ! 9153: display_stmt(this,0,1); ! 9154: if(Adebug>=2) display_stmt(this); ! 9155: }); ! 9156: //fprintf(stderr,"DEL(stmt %d %s)\n",this,keys[base]); fflush(stderr); ! 9157: permanent = 3; ! 9158: switch (base) { ! 9159: case SM: ! 9160: case WHILE: ! 9161: case DO: ! 9162: case RETURN: ! 9163: case CASE: ! 9164: case SWITCH: ! 9165: DEL(e); ! 9166: break; ! 9167: case PAIR: ! 9168: DEL(s2); ! 9169: break; ! 9170: case BLOCK: ! 9171: DEL(d); ! 9172: DEL(s); ! 9173: if (own_tbl) DEL(memtbl); ! 9174: DEL(s_list); ! 9175: goto dd; ! 9176: case FOR: ! 9177: DEL(e); ! 9178: DEL(e2); ! 9179: DEL(for_init); ! 9180: break; ! 9181: case IF: ! 9182: DEL(e); ! 9183: DEL(else_stmt); ! 9184: break; ! 9185: } ! 9186: ! 9187: DEL(s); ! 9188: DEL(s_list); ! 9189: dd: ! 9190: delete this; ! 9191: } ! 9192: ! 9193: void table::del() ! 9194: { ! 9195: // error('d',"\n*** %d::del() -- '%s'\n",this, t_name?t_name->string:"???"); ! 9196: ! 9197: for (register i=1; i<free_slot; i++) { ! 9198: Pname n = entries[i]; ! 9199: if (n==0) error('i',"table.del(0)"); ! 9200: DB( if(Adebug>=2) { fprintf(stderr," name: '%s'",n->string); ! 9201: display_type(n->tp); putc('\n',stderr); ! 9202: }); ! 9203: ! 9204: // error( 'd',"\ntable::del: %s n_scope: %d, n_stclass: %d", n->string, n->n_scope, n->n_stclass ); ! 9205: ! 9206: if (n->n_stclass == STATIC) continue; ! 9207: switch (n->n_scope) { ! 9208: case ARG: ! 9209: case ARGT: ! 9210: break; ! 9211: default: ! 9212: { char* s = n->string; ! 9213: if (s && (s[0]!='_' || s[1]!='_' || s[2]!='X')) delete s; ! 9214: /* delete n; */ ! 9215: n->del(); ! 9216: } ! 9217: } ! 9218: } ! 9219: //delete entries; ! 9220: //delete hashtbl; ! 9221: delete this; ! 9222: } ! 9223: ! 9224: // local class ! 9225: void delete_local() ! 9226: { ! 9227: DB( if(Adebug>=1) { ! 9228: fprintf( stderr, "delete_local: vlist: %d", vlist ); ! 9229: }); ! 9230: // error( 'd', "delete_local: vlist: %d", vlist ); ! 9231: do { ! 9232: for (vl* v = vlist; v; v = v->next) v->cl->really_print(v->vt); ! 9233: vlist = 0; ! 9234: ! 9235: for (Plist l=isf_list; l; l=l->l) { ! 9236: Pname n = l->f; ! 9237: Pfct f = Pfct(n->tp); ! 9238: // error('d',"isf %n f %d",n,f); ! 9239: if ( f == 0 ) { error('d', "delete_local: f == 0" );break;} ! 9240: if (f->base == OVERLOAD) { ! 9241: n = Pgen(f)->fct_list->f; // first fct ! 9242: f = Pfct(n->tp); ! 9243: } ! 9244: ! 9245: if (debug_opt==0 && n->n_addr_taken) { ! 9246: f->f_inline = 0; ! 9247: if (n->n_dcl_printed<2) { ! 9248: if (warning_opt) ! 9249: error('w',"out-of-line copy of %n created",n); ! 9250: n->dcl_print(0); ! 9251: } ! 9252: } ! 9253: } ! 9254: //isf_list = 0; ! 9255: } while (vlist); ! 9256: ! 9257: for ( Plist l = local_class; l; l = l->l ) ! 9258: { ! 9259: Pname n = l->f; ! 9260: // error( 'd' , "delete_local() %d %n %t", n, n, n->tp ); ! 9261: Pname nn = Pbase(n->tp)->b_name; ! 9262: Pclass cl = Pclass(nn->tp); ! 9263: for (Pname px, p=cl->mem_list; p; p=px) { ! 9264: px = p->n_list; ! 9265: if (p->tp) ! 9266: switch (p->tp->base) { ! 9267: case FCT: ! 9268: { Pfct f = (Pfct)p->tp; ! 9269: if (f->body) { ! 9270: if (f->f_inline==0 ! 9271: && f->f_imeasure==0) { ! 9272: ! 9273: if (ansi_opt && f->f_this) { ! 9274: f->f_this->n_table = 0; ! 9275: for (Pname n=f->f_this->n_list; n; n=n->n_list) ! 9276: n->n_table = 0; ! 9277: } ! 9278: ! 9279: DEL(f->body); ! 9280: f->body = 0; ! 9281: } ! 9282: } ! 9283: } ! 9284: case COBJ: ! 9285: case EOBJ: ! 9286: DEL(p); ! 9287: break; ! 9288: case CLASS: ! 9289: case ENUM: ! 9290: break; ! 9291: default: ! 9292: delete p; ! 9293: } // end switch ! 9294: else delete p; ! 9295: } // end for mem ! 9296: DEL(cl->memtbl); ! 9297: cl->mem_list = 0; ! 9298: cl->permanent = 3; ! 9299: nn->permanent = 0; ! 9300: DEL(nn); ! 9301: n->permanent = 0; ! 9302: extern void table_delete( char*, TOK, int ); ! 9303: table_delete( n->string, LOCAL, n->lex_level ); ! 9304: DEL(n); ! 9305: } ! 9306: } ! 9307: 0707071010112045761004440001630000160000010210600466055414200001200000013534discrim.c /* ident "@(#)ctrans:src/discrim.c 1.2" */ ! 9308: /************ add copyright ********************** ! 9309: * union discriminator functions for nodes in cfront. ! 9310: * all return 0 for none, ! 9311: * -1 for bad union index, -2 for inconsistent ! 9312: * or otherwise messed up nodes ! 9313: */ ! 9314: #include "cfront.h" ! 9315: #define DEFINE_TOKEN_CLASS_TABLE ! 9316: #include "node_classes.h" ! 9317: ! 9318: int basetype::discriminator(int which_union) ! 9319: { ! 9320: switch(which_union) ! 9321: { ! 9322: case 0: ! 9323: switch(base) { ! 9324: case FIELD: return 1; ! 9325: case FCT: return 2; ! 9326: default: return discrim_none_valid; ! 9327: } ! 9328: default: ! 9329: return discrim_bad_index; ! 9330: } ! 9331: } ! 9332: ! 9333: int fct::discriminator(int) ! 9334: { ! 9335: return discrim_bad_index; ! 9336: } ! 9337: ! 9338: int expr::discriminator(int which_union) ! 9339: { ! 9340: switch(which_union) { ! 9341: case 0: ! 9342: return 1; /* tp, never syn_class */ ! 9343: case 1: /* e1, i1, string */ ! 9344: switch(base) { ! 9345: case DEREF: ! 9346: case ICALL: ! 9347: case REF: ! 9348: case DOT: ! 9349: case VALUE: ! 9350: case SIZEOF: ! 9351: case NEW: ! 9352: case GNEW: ! 9353: case DELETE: ! 9354: case CAST: ! 9355: case CALL: ! 9356: case G_CALL: ! 9357: case ASSIGN: ! 9358: case EQ: ! 9359: case NE: ! 9360: case GT: ! 9361: case GE: ! 9362: case LE: ! 9363: case LT: ! 9364: case ELIST: ! 9365: case ILIST: ! 9366: case QUEST: ! 9367: case CM: ! 9368: case G_CM: ! 9369: case PLUS: ! 9370: case MINUS: ! 9371: case MUL: ! 9372: case DIV: ! 9373: case MOD: ! 9374: case LS: ! 9375: case RS: ! 9376: case AND: ! 9377: case OR: ! 9378: case ER: ! 9379: case ANDAND: ! 9380: case OROR: ! 9381: case ASOR: ! 9382: case ASER: ! 9383: case ASAND: ! 9384: case ASPLUS: ! 9385: case ASMINUS: ! 9386: case ASMUL: ! 9387: case ASMOD: ! 9388: case ASDIV: ! 9389: case ASLS: ! 9390: case ASRS: ! 9391: case DECR: ! 9392: case INCR: ! 9393: return 1; ! 9394: case MDOT: ! 9395: case IVAL: ! 9396: return 2; ! 9397: case TNAME: ! 9398: case NAME: ! 9399: case ICON: ! 9400: case FCON: ! 9401: case CCON: ! 9402: case ID: ! 9403: case STRING: ! 9404: case TEXT: ! 9405: return 3; ! 9406: default: return discrim_none_valid; ! 9407: } ! 9408: case 2: /* e2, i2, string2, n_initializer */ ! 9409: /* i2 is a complete mystery. It is set to 1, ! 9410: and never referenced. But I'm not sure that ! 9411: someone somewhere doesn't test one of the other ! 9412: union elements for equal to 1, so therefore this test. */ ! 9413: if(i2 == 1)return 2; ! 9414: switch(base) { ! 9415: case DELETE: ! 9416: case VALUE: ! 9417: case ICALL: ! 9418: case CALL: ! 9419: case G_CALL: ! 9420: case ASSIGN: ! 9421: case EQ: ! 9422: case NE: ! 9423: case GT: ! 9424: case GE: ! 9425: case LE: ! 9426: case LT: ! 9427: case DEREF: ! 9428: case ELIST: ! 9429: case QUEST: ! 9430: case CM: ! 9431: case G_CM: ! 9432: case UMINUS: ! 9433: case NOT: ! 9434: case COMPL: ! 9435: case ADDROF: ! 9436: case G_ADDROF: ! 9437: case PLUS: ! 9438: case MINUS: ! 9439: case MUL: ! 9440: case DIV: ! 9441: case MOD: ! 9442: case LS: ! 9443: case RS: ! 9444: case AND: ! 9445: case OR: ! 9446: case ER: ! 9447: case ANDAND: ! 9448: case OROR: ! 9449: case ASOR: ! 9450: case ASER: ! 9451: case ASAND: ! 9452: case ASPLUS: ! 9453: case ASMINUS: ! 9454: case ASMUL: ! 9455: case ASMOD: ! 9456: case ASDIV: ! 9457: case ASLS: ! 9458: case ASRS: ! 9459: case DECR: ! 9460: case INCR: ! 9461: case NEW: /*- the placement expression list hangs off e2 -*/ ! 9462: return 1; ! 9463: case TEXT: ! 9464: return 3; ! 9465: case NAME: ! 9466: case TNAME: ! 9467: /* The n_initializer field is used for TNAMEs when describing base */ ! 9468: /* class initializations. The TNAME refers to the base class, and */ ! 9469: /* the actuals arguments are hung off the n_initializer list */ ! 9470: return 4; ! 9471: default: return discrim_none_valid; ! 9472: } ! 9473: case 3: /* tp2, fct_name, cond, mem, as_type, n_table, il, query_this */ ! 9474: switch(base) { ! 9475: case VALUE: ! 9476: case SIZEOF: ! 9477: case NEW: ! 9478: case GNEW: ! 9479: case CAST: ! 9480: return 1; ! 9481: case CALL: ! 9482: case G_CALL: ! 9483: return 2; ! 9484: case QUEST: ! 9485: return 3; ! 9486: case REF: ! 9487: case DOT: ! 9488: case MDOT: ! 9489: return 4; ! 9490: case ASOR: ! 9491: case ASER: ! 9492: case ASAND: ! 9493: case ASPLUS: ! 9494: case ASMINUS: ! 9495: case ASMUL: ! 9496: case ASMOD: ! 9497: case ASDIV: ! 9498: case ASLS: ! 9499: case ASRS: ! 9500: case DECR: ! 9501: case INCR: ! 9502: case ASSIGN: ! 9503: return 5; ! 9504: ! 9505: case NAME: ! 9506: case TNAME: ! 9507: if (Pname(this)->n_oper==TYPE && ! 9508: (strcmp(Pname(this)->string, "_type")==0)) { ! 9509: // error('d',"string %s n_oper: %k", string, Pname(this)->n_oper); ! 9510: return 3; ! 9511: } ! 9512: return 6; ! 9513: ! 9514: case ICALL: ! 9515: case ANAME: ! 9516: return 7; ! 9517: ! 9518: default: return discrim_none_valid; ! 9519: } ! 9520: ! 9521: default: ! 9522: return discrim_bad_index; ! 9523: } ! 9524: } ! 9525: ! 9526: int name::discriminator (int which_union) ! 9527: { ! 9528: switch(which_union) { ! 9529: case 0: /* n_qualifier, n_realscope */ ! 9530: if(base == LABEL) return 2; ! 9531: else return 1; ! 9532: default: ! 9533: return discrim_bad_index; ! 9534: } ! 9535: } ! 9536: ! 9537: int stmt::discriminator (int which_union) ! 9538: { ! 9539: switch(which_union) { ! 9540: case 0: /* d, e2, has_default, case_value, ret_tp */ ! 9541: switch(base) { ! 9542: case BLOCK: ! 9543: case GOTO: ! 9544: case LABEL: ! 9545: case DCL: ! 9546: return 1; ! 9547: case FOR: ! 9548: return 2; ! 9549: case SWITCH: ! 9550: return 3; ! 9551: case PAIR: ! 9552: case RETURN: ! 9553: return 4; ! 9554: default: return discrim_none_valid; ! 9555: } ! 9556: case 1: /* e, own_tbl, s2 */ ! 9557: switch(base) { ! 9558: case FOR: ! 9559: case IF: ! 9560: case WHILE: ! 9561: case DO: ! 9562: case RETURN: ! 9563: case SWITCH: ! 9564: case SM: ! 9565: case SM_PARAM: ! 9566: case CASE: ! 9567: return 1; ! 9568: case BLOCK: ! 9569: return 2; ! 9570: case PAIR: ! 9571: return 3; ! 9572: default: ! 9573: return discrim_none_valid; ! 9574: } ! 9575: case 2: /* for_init, else_stmt, case_list */ ! 9576: switch(base) { ! 9577: case FOR: ! 9578: return 1; ! 9579: case IF: ! 9580: return 2; ! 9581: case SWITCH: ! 9582: case CASE: ! 9583: return 3; ! 9584: default: ! 9585: return discrim_none_valid; ! 9586: } ! 9587: default: ! 9588: return discrim_bad_index; ! 9589: } ! 9590: } ! 9591: ! 9592: static node_class token_to_class_map[DUMMY_LAST_NODE]; ! 9593: static char map_initialized; ! 9594: ! 9595: node_class classify_node (Pnode node, int& error) ! 9596: { ! 9597: int ncx; ! 9598: node_class nclass; ! 9599: ! 9600: error = 0; ! 9601: ! 9602: if (! map_initialized) { ! 9603: map_initialized = 1 ; ! 9604: for(ncx = 0; ncx < sizeof (token_classes) / sizeof (token_class); ! 9605: ncx ++) ! 9606: token_to_class_map[token_classes[ncx].token] ! 9607: = token_classes[ncx].nclass; ! 9608: } ! 9609: ! 9610: if (!((node->base > 0) && (node->base < DUMMY_LAST_NODE))) { ! 9611: error = 1; ! 9612: return nc_unused; ! 9613: } ! 9614: ! 9615: nclass = token_to_class_map[node->base]; ! 9616: ! 9617: switch(nclass) { ! 9618: case nc_fct: ! 9619: case nc_name: ! 9620: if(node->baseclass) nclass = nc_baseclass; ! 9621: } ! 9622: ! 9623: return nclass; ! 9624: } ! 9625: ! 9626: node_class classify_node (Pnode node) ! 9627: { ! 9628: int err; ! 9629: node_class nclass = classify_node (node, err); ! 9630: if(err) error ('i', "failed to classify node."); ! 9631: return nclass; ! 9632: } ! 9633: 0707071010112045771004440001630000160000010210700466055414600001200000041601doprint.c /* ident "@(#)ctrans:src/doprint.c 1.2" */ ! 9634: /* ! 9635: ************* obviously, have to do something here!!! ! 9636: ! 9637: * Copyright (c) 1988 Regents of the University of California. ! 9638: * All rights reserved. ! 9639: * ! 9640: * Redistribution and use in source and binary forms are permitted ! 9641: * provided that the above copyright notice and this paragraph are ! 9642: * duplicated in all such forms and that any documentation, ! 9643: * advertising materials, and other materials related to such ! 9644: * distribution and use acknowledge that the software was developed ! 9645: * by the University of California, Berkeley. The name of the ! 9646: * University may not be used to endorse or promote products derived ! 9647: * from this software without specific prior written permission. ! 9648: * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR ! 9649: * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED ! 9650: * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE. ! 9651: */ ! 9652: ! 9653: /* ! 9654: $Header: /usr2/odi/lib.src/RCS/doprint.C,v 1.3 89/09/19 12:00:34 benson Exp $ ! 9655: ! 9656: Copyright (c) 1989 by Object Design, Inc., Burlington, Mass. ! 9657: All rights reserved. ! 9658: ! 9659: */ ! 9660: ! 9661: #include <sys/types.h> ! 9662: #include <stdarg.h> ! 9663: #include <ctype.h> ! 9664: #include <iostream.h> ! 9665: #include <strstream.h> ! 9666: #include <memory.h> ! 9667: #include <math.h> ! 9668: #include <string.h> ! 9669: #include "print_self.h" ! 9670: ! 9671: /* 11-bit exponent (VAX G floating point) is 308 decimal digits */ ! 9672: #define MAXEXP 308 ! 9673: /* 128 bit fraction takes up 39 decimal digits; max reasonable precision */ ! 9674: #define MAXFRACT 39 ! 9675: ! 9676: #define DEFPREC 6 ! 9677: ! 9678: #define BUF (MAXEXP+MAXFRACT+1) /* + decimal point */ ! 9679: ! 9680: #define PUTC(ch) (void) fp.put(ch) ! 9681: ! 9682: #define ARG() \ ! 9683: _ulong = flags&LONGINT ? va_arg(argp, long) : \ ! 9684: flags&SHORTINT ? va_arg(argp, short) : va_arg(argp, int); ! 9685: ! 9686: #define todigit(c) ((c) - '0') ! 9687: #define tochar(n) ((n) + '0') ! 9688: ! 9689: #define LONGINT 0x01 /* long integer */ ! 9690: #define LONGDBL 0x02 /* long double; unimplemented */ ! 9691: #define SHORTINT 0x04 /* short integer */ ! 9692: #define ALT 0x08 /* alternate form */ ! 9693: #define LADJUST 0x10 /* left adjustment */ ! 9694: #define ZEROPAD 0x20 /* zero (as opposed to blank) pad */ ! 9695: #define HEXPREFIX 0x40 /* add 0x or 0X prefix */ ! 9696: ! 9697: ! 9698: static char * exponent(char * p, int exp, u_char fmtch); ! 9699: static char * round(double fract, ! 9700: int * exp, ! 9701: char * start, ! 9702: char * end, ! 9703: char ch, ! 9704: char * signp); ! 9705: ! 9706: ! 9707: ! 9708: static ! 9709: cvt(double number, ! 9710: register int prec, ! 9711: int flags, ! 9712: char * signp, ! 9713: u_char fmtch, ! 9714: char * startp, ! 9715: char * endp) ! 9716: { ! 9717: register char *p, *t; ! 9718: register double fract; ! 9719: int dotrim, expcnt, gformat; ! 9720: double integer, tmp; ! 9721: ! 9722: dotrim = expcnt = gformat = 0; ! 9723: fract = modf(number, &integer); ! 9724: ! 9725: /* get an extra slot for rounding. */ ! 9726: t = ++startp; ! 9727: ! 9728: /* ! 9729: * get integer portion of number; put into the end of the buffer; the ! 9730: * .01 is added for modf(356.0 / 10, &integer) returning .59999999... ! 9731: */ ! 9732: for (p = endp - 1; integer; ++expcnt) { ! 9733: tmp = modf(integer / 10, &integer); ! 9734: *p-- = tochar((int)((tmp + .01) * 10)); ! 9735: } ! 9736: switch(fmtch) { ! 9737: case 'f': ! 9738: /* reverse integer into beginning of buffer */ ! 9739: if (expcnt) ! 9740: for (; ++p < endp; *t++ = *p); ! 9741: else ! 9742: *t++ = '0'; ! 9743: /* ! 9744: * if precision required or alternate flag set, add in a ! 9745: * decimal point. ! 9746: */ ! 9747: if (prec || flags&ALT) ! 9748: *t++ = '.'; ! 9749: /* if requires more precision and some fraction left */ ! 9750: if (fract) { ! 9751: if (prec) ! 9752: do { ! 9753: fract = modf(fract * 10, &tmp); ! 9754: *t++ = tochar((int)tmp); ! 9755: } while (--prec && fract); ! 9756: if (fract) ! 9757: startp = round(fract, (int *)NULL, startp, ! 9758: t - 1, (char)0, signp); ! 9759: } ! 9760: for (; prec--; *t++ = '0'); ! 9761: break; ! 9762: case 'e': ! 9763: case 'E': ! 9764: eformat: if (expcnt) { ! 9765: *t++ = *++p; ! 9766: if (prec || flags&ALT) ! 9767: *t++ = '.'; ! 9768: /* if requires more precision and some integer left */ ! 9769: for (; prec && ++p < endp; --prec) ! 9770: *t++ = *p; ! 9771: /* ! 9772: * if done precision and more of the integer component, ! 9773: * round using it; adjust fract so we don't re-round ! 9774: * later. ! 9775: */ ! 9776: if (!prec && ++p < endp) { ! 9777: fract = 0; ! 9778: startp = round((double)0, &expcnt, startp, ! 9779: t - 1, *p, signp); ! 9780: } ! 9781: /* adjust expcnt for digit in front of decimal */ ! 9782: --expcnt; ! 9783: } ! 9784: /* until first fractional digit, decrement exponent */ ! 9785: else if (fract) { ! 9786: /* adjust expcnt for digit in front of decimal */ ! 9787: for (expcnt = -1;; --expcnt) { ! 9788: fract = modf(fract * 10, &tmp); ! 9789: if (tmp) ! 9790: break; ! 9791: } ! 9792: *t++ = tochar((int)tmp); ! 9793: if (prec || flags&ALT) ! 9794: *t++ = '.'; ! 9795: } ! 9796: else { ! 9797: *t++ = '0'; ! 9798: if (prec || flags&ALT) ! 9799: *t++ = '.'; ! 9800: } ! 9801: /* if requires more precision and some fraction left */ ! 9802: if (fract) { ! 9803: if (prec) ! 9804: do { ! 9805: fract = modf(fract * 10, &tmp); ! 9806: *t++ = tochar((int)tmp); ! 9807: } while (--prec && fract); ! 9808: if (fract) ! 9809: startp = round(fract, &expcnt, startp, ! 9810: t - 1, (char)0, signp); ! 9811: } ! 9812: /* if requires more precision */ ! 9813: for (; prec--; *t++ = '0'); ! 9814: ! 9815: /* unless alternate flag, trim any g/G format trailing 0's */ ! 9816: if (gformat && !(flags&ALT)) { ! 9817: while (t > startp && *--t == '0'); ! 9818: if (*t == '.') ! 9819: --t; ! 9820: ++t; ! 9821: } ! 9822: t = exponent(t, expcnt, fmtch); ! 9823: break; ! 9824: case 'g': ! 9825: case 'G': ! 9826: /* a precision of 0 is treated as a precision of 1. */ ! 9827: if (!prec) ! 9828: ++prec; ! 9829: /* ! 9830: * ``The style used depends on the value converted; style e ! 9831: * will be used only if the exponent resulting from the ! 9832: * conversion is less than -4 or greater than the precision.'' ! 9833: * -- ANSI X3J11 ! 9834: */ ! 9835: if (expcnt > prec || !expcnt && fract && fract < .0001) { ! 9836: /* ! 9837: * g/G format counts "significant digits, not digits of ! 9838: * precision; for the e/E format, this just causes an ! 9839: * off-by-one problem, i.e. g/G considers the digit ! 9840: * before the decimal point significant and e/E doesn't ! 9841: * count it as precision." ! 9842: */ ! 9843: --prec; ! 9844: fmtch -= 2; /* G->E, g->e */ ! 9845: gformat = 1; ! 9846: goto eformat; ! 9847: } ! 9848: /* ! 9849: * reverse integer into beginning of buffer, ! 9850: * note, decrement precision ! 9851: */ ! 9852: if (expcnt) ! 9853: for (; ++p < endp; *t++ = *p, --prec); ! 9854: else ! 9855: *t++ = '0'; ! 9856: /* ! 9857: * if precision required or alternate flag set, add in a ! 9858: * decimal point. If no digits yet, add in leading 0. ! 9859: */ ! 9860: if (prec || flags&ALT) { ! 9861: dotrim = 1; ! 9862: *t++ = '.'; ! 9863: } ! 9864: else ! 9865: dotrim = 0; ! 9866: /* if requires more precision and some fraction left */ ! 9867: if (fract) { ! 9868: if (prec) { ! 9869: do { ! 9870: fract = modf(fract * 10, &tmp); ! 9871: *t++ = tochar((int)tmp); ! 9872: } while(!tmp); ! 9873: while (--prec && fract) { ! 9874: fract = modf(fract * 10, &tmp); ! 9875: *t++ = tochar((int)tmp); ! 9876: } ! 9877: } ! 9878: if (fract) ! 9879: startp = round(fract, (int *)NULL, startp, ! 9880: t - 1, (char)0, signp); ! 9881: } ! 9882: /* alternate format, adds 0's for precision, else trim 0's */ ! 9883: if (flags&ALT) ! 9884: for (; prec--; *t++ = '0'); ! 9885: else if (dotrim) { ! 9886: while (t > startp && *--t == '0'); ! 9887: if (*t != '.') ! 9888: ++t; ! 9889: } ! 9890: } ! 9891: return(t - startp); ! 9892: } ! 9893: ! 9894: static char * round(double fract, ! 9895: int * exp, ! 9896: char * start, ! 9897: char * end, ! 9898: char ch, ! 9899: char * signp) ! 9900: { ! 9901: double tmp; ! 9902: ! 9903: if (fract) ! 9904: (void)modf(fract * 10, &tmp); ! 9905: else ! 9906: tmp = todigit(ch); ! 9907: if (tmp > 4) ! 9908: for (;; --end) { ! 9909: if (*end == '.') ! 9910: --end; ! 9911: if (++*end <= '9') ! 9912: break; ! 9913: *end = '0'; ! 9914: if (end == start) { ! 9915: if (exp) { /* e/E; increment exponent */ ! 9916: *end = '1'; ! 9917: ++*exp; ! 9918: } ! 9919: else { /* f; add extra digit */ ! 9920: *--end = '1'; ! 9921: --start; ! 9922: } ! 9923: break; ! 9924: } ! 9925: } ! 9926: /* ``"%.3f", (double)-0.0004'' gives you a negative 0. */ ! 9927: else if (*signp == '-') ! 9928: for (;; --end) { ! 9929: if (*end == '.') ! 9930: --end; ! 9931: if (*end != '0') ! 9932: break; ! 9933: if (end == start) ! 9934: *signp = 0; ! 9935: } ! 9936: return(start); ! 9937: } ! 9938: ! 9939: static char * exponent(char * p, int exp, u_char fmtch) ! 9940: { ! 9941: register char *t; ! 9942: char expbuf[MAXEXP]; ! 9943: ! 9944: *p++ = fmtch; ! 9945: if (exp < 0) { ! 9946: exp = -exp; ! 9947: *p++ = '-'; ! 9948: } ! 9949: else ! 9950: *p++ = '+'; ! 9951: t = expbuf + MAXEXP; ! 9952: if (exp > 9) { ! 9953: do { ! 9954: *--t = tochar(exp % 10); ! 9955: } while ((exp /= 10) > 9); ! 9956: *--t = tochar(exp); ! 9957: for (; t < expbuf + MAXEXP; *p++ = *t++); ! 9958: } ! 9959: else { ! 9960: *p++ = '0'; ! 9961: *p++ = tochar(exp); ! 9962: } ! 9963: return(p); ! 9964: } ! 9965: ! 9966: int vostream_printf(const char *fmt0, va_list argp, ostream& fp) ! 9967: { ! 9968: register const u_char *fmt; /* format string */ ! 9969: register int ch; /* character from fmt */ ! 9970: register int cnt; /* return value accumulator */ ! 9971: register int n; /* random handy integer */ ! 9972: register char *t; /* buffer pointer */ ! 9973: double _double; /* double precision arguments %[eEfgG] */ ! 9974: u_long _ulong; /* integer arguments %[diouxX] */ ! 9975: int base; /* base for [diouxX] conversion */ ! 9976: int dprec; /* decimal precision in [diouxX] */ ! 9977: int fieldsz; /* field size expanded by sign, etc */ ! 9978: int flags; /* flags as above */ ! 9979: int fpprec; /* `extra' floating precision in [eEfgG] */ ! 9980: int prec; /* precision from format (%.3d), or -1 */ ! 9981: int realsz; /* field size expanded by decimal precision */ ! 9982: int size; /* size of converted field or string */ ! 9983: int width; /* width from format (%8d), or 0 */ ! 9984: char sign; /* sign prefix (' ', '+', '-', or \0) */ ! 9985: char softsign; /* temporary negative sign for floats */ ! 9986: char *digs; /* digits for [diouxX] conversion */ ! 9987: char buf[BUF]; /* space for %c, %[diouxX], %[eEfgG] */ ! 9988: ! 9989: fmt = (const u_char *)fmt0; ! 9990: digs = "0123456789abcdef"; ! 9991: for (cnt = 0;; ++fmt) { ! 9992: for (;(ch = *fmt) && ch != '%'; ++cnt, ++fmt) ! 9993: PUTC(ch); ! 9994: if (!ch)return (cnt); ! 9995: ! 9996: flags = 0; dprec = 0; fpprec = 0; width = 0; ! 9997: prec = -1; ! 9998: sign = '\0'; ! 9999: ! 10000: rflag: switch (*++fmt) { ! 10001: case ' ': ! 10002: /* ! 10003: * ``If the space and + flags both appear, the space ! 10004: * flag will be ignored.'' ! 10005: * -- ANSI X3J11 ! 10006: */ ! 10007: if (!sign) ! 10008: sign = ' '; ! 10009: goto rflag; ! 10010: case '#': ! 10011: flags |= ALT; ! 10012: goto rflag; ! 10013: case '*': ! 10014: /* ! 10015: * ``A negative field width argument is taken as a ! 10016: * - flag followed by a positive field width.'' ! 10017: * -- ANSI X3J11 ! 10018: * They don't exclude field widths read from args. ! 10019: */ ! 10020: if ((width = va_arg(argp, int)) >= 0) ! 10021: goto rflag; ! 10022: width = -width; ! 10023: /* FALLTHROUGH */ ! 10024: case '-': ! 10025: flags |= LADJUST; ! 10026: goto rflag; ! 10027: case '+': ! 10028: sign = '+'; ! 10029: goto rflag; ! 10030: case '.': ! 10031: if (*++fmt == '*') ! 10032: n = va_arg(argp, int); ! 10033: else { ! 10034: n = 0; ! 10035: while (isascii(*fmt) && isdigit(*fmt)) ! 10036: n = 10 * n + todigit(*fmt++); ! 10037: --fmt; ! 10038: } ! 10039: prec = n < 0 ? -1 : n; ! 10040: goto rflag; ! 10041: case '0': ! 10042: /* ! 10043: * ``Note that 0 is taken as a flag, not as the ! 10044: * beginning of a field width.'' ! 10045: * -- ANSI X3J11 ! 10046: */ ! 10047: flags |= ZEROPAD; ! 10048: goto rflag; ! 10049: case '1': case '2': case '3': case '4': ! 10050: case '5': case '6': case '7': case '8': case '9': ! 10051: n = 0; ! 10052: do { ! 10053: n = 10 * n + todigit(*fmt); ! 10054: } while (isascii(*++fmt) && isdigit(*fmt)); ! 10055: width = n; ! 10056: --fmt; ! 10057: goto rflag; ! 10058: case 'L': ! 10059: flags |= LONGDBL; ! 10060: goto rflag; ! 10061: case 'h': ! 10062: flags |= SHORTINT; ! 10063: goto rflag; ! 10064: case 'l': ! 10065: flags |= LONGINT; ! 10066: goto rflag; ! 10067: case 'c': ! 10068: *(t = buf) = va_arg(argp, int); ! 10069: size = 1; ! 10070: sign = '\0'; ! 10071: goto pforw; ! 10072: case 'D': ! 10073: flags |= LONGINT; ! 10074: /*FALLTHROUGH*/ ! 10075: case 'd': ! 10076: case 'i': ! 10077: ARG(); ! 10078: if ((long)_ulong < 0) { ! 10079: _ulong = -_ulong; ! 10080: sign = '-'; ! 10081: } ! 10082: base = 10; ! 10083: goto number; ! 10084: case 'e': ! 10085: case 'E': ! 10086: case 'f': ! 10087: case 'g': ! 10088: case 'G': ! 10089: _double = va_arg(argp, double); ! 10090: /* ! 10091: * don't do unrealistic precision; just pad it with ! 10092: * zeroes later, so buffer size stays rational. ! 10093: */ ! 10094: if (prec > MAXFRACT) { ! 10095: if (*fmt != 'g' && *fmt != 'G' || (flags&ALT)) ! 10096: fpprec = prec - MAXFRACT; ! 10097: prec = MAXFRACT; ! 10098: } ! 10099: else if (prec == -1) ! 10100: prec = DEFPREC; ! 10101: /* ! 10102: * softsign avoids negative 0 if _double is < 0 and ! 10103: * no significant digits will be shown ! 10104: */ ! 10105: if (_double < 0) { ! 10106: softsign = '-'; ! 10107: _double = -_double; ! 10108: } ! 10109: else ! 10110: softsign = 0; ! 10111: /* ! 10112: * cvt may have to round up past the "start" of the ! 10113: * buffer, i.e. ``intf("%.2f", (double)9.999);''; ! 10114: * if the first char isn't NULL, it did. ! 10115: */ ! 10116: *buf = NULL; ! 10117: size = cvt(_double, prec, flags, &softsign, *fmt, buf, ! 10118: buf + sizeof(buf)); ! 10119: if (softsign) ! 10120: sign = '-'; ! 10121: t = *buf ? buf : buf + 1; ! 10122: goto pforw; ! 10123: case 'n': ! 10124: if (flags & LONGINT) ! 10125: *va_arg(argp, long *) = cnt; ! 10126: else if (flags & SHORTINT) ! 10127: *va_arg(argp, short *) = cnt; ! 10128: else ! 10129: *va_arg(argp, int *) = cnt; ! 10130: break; ! 10131: case 'O': ! 10132: flags |= LONGINT; ! 10133: /*FALLTHROUGH*/ ! 10134: case 'o': ! 10135: ARG(); ! 10136: base = 8; ! 10137: goto nosign; ! 10138: case 'T': // Type ! 10139: { ! 10140: streampos cur_pos; ! 10141: streampos new_pos; ! 10142: ! 10143: cur_pos = fp.tellp(); ! 10144: ! 10145: _Print_self * obj = va_arg (argp, _Print_self *); ! 10146: obj->print_self (fp); ! 10147: ! 10148: new_pos = fp.tellp(); ! 10149: ! 10150: cnt += int (new_pos - cur_pos); ! 10151: } ! 10152: break; ! 10153: ! 10154: case 'p': ! 10155: /* ! 10156: * ``The argument shall be a pointer to void. The ! 10157: * value of the pointer is converted to a sequence ! 10158: * of printable characters, in an implementation- ! 10159: * defined manner.'' ! 10160: * -- ANSI X3J11 ! 10161: */ ! 10162: /* NOSTRICT */ ! 10163: _ulong = (u_long)va_arg(argp, void *); ! 10164: base = 16; ! 10165: goto nosign; ! 10166: case 's': ! 10167: if (!(t = va_arg(argp, char *))) ! 10168: t = "(null)"; ! 10169: if (prec >= 0) { ! 10170: /* ! 10171: * can't use strlen; can only look for the ! 10172: * NUL in the first `prec' characters, and ! 10173: * strlen() will go further. ! 10174: */ ! 10175: char *p; ! 10176: ! 10177: if (p = (char *) memchr(t, 0, prec)) { ! 10178: size = p - t; ! 10179: if (size > prec) ! 10180: size = prec; ! 10181: } else ! 10182: size = prec; ! 10183: } else ! 10184: size = strlen(t); ! 10185: sign = '\0'; ! 10186: goto pforw; ! 10187: case 'U': ! 10188: flags |= LONGINT; ! 10189: /*FALLTHROUGH*/ ! 10190: case 'u': ! 10191: ARG(); ! 10192: base = 10; ! 10193: goto nosign; ! 10194: case 'X': ! 10195: digs = "0123456789ABCDEF"; ! 10196: /* FALLTHROUGH */ ! 10197: case 'x': ! 10198: ARG(); ! 10199: base = 16; ! 10200: /* leading 0x/X only if non-zero */ ! 10201: if (flags & ALT && _ulong != 0) ! 10202: flags |= HEXPREFIX; ! 10203: ! 10204: /* unsigned conversions */ ! 10205: nosign: sign = '\0'; ! 10206: /* ! 10207: * ``... diouXx conversions ... if a precision is ! 10208: * specified, the 0 flag will be ignored.'' ! 10209: * -- ANSI X3J11 ! 10210: */ ! 10211: number: if ((dprec = prec) >= 0) ! 10212: flags &= ~ZEROPAD; ! 10213: ! 10214: /* ! 10215: * ``The result of converting a zero value with an ! 10216: * explicit precision of zero is no characters.'' ! 10217: * -- ANSI X3J11 ! 10218: */ ! 10219: t = buf + BUF; ! 10220: if (_ulong != 0 || prec != 0) { ! 10221: do { ! 10222: *--t = digs[_ulong % base]; ! 10223: _ulong /= base; ! 10224: } while (_ulong); ! 10225: digs = "0123456789abcdef"; ! 10226: if (flags & ALT && base == 8 && *t != '0') ! 10227: *--t = '0'; /* octal leading 0 */ ! 10228: } ! 10229: size = buf + BUF - t; ! 10230: ! 10231: pforw: ! 10232: /* ! 10233: * All reasonable formats wind up here. At this point, ! 10234: * `t' points to a string which (if not flags&LADJUST) ! 10235: * should be padded out to `width' places. If ! 10236: * flags&ZEROPAD, it should first be prefixed by any ! 10237: * sign or other prefix; otherwise, it should be blank ! 10238: * padded before the prefix is emitted. After any ! 10239: * left-hand padding and prefixing, emit zeroes ! 10240: * required by a decimal [diouxX] precision, then print ! 10241: * the string proper, then emit zeroes required by any ! 10242: * leftover floating precision; finally, if LADJUST, ! 10243: * pad with blanks. ! 10244: */ ! 10245: ! 10246: /* ! 10247: * compute actual size, so we know how much to pad ! 10248: * fieldsz excludes decimal prec; realsz includes it ! 10249: */ ! 10250: fieldsz = size + fpprec; ! 10251: if (sign) ! 10252: fieldsz++; ! 10253: if (flags & HEXPREFIX) ! 10254: fieldsz += 2; ! 10255: realsz = dprec > fieldsz ? dprec : fieldsz; ! 10256: ! 10257: /* right-adjusting blank padding */ ! 10258: if ((flags & (LADJUST|ZEROPAD)) == 0 && width) ! 10259: for (n = realsz; n < width; n++) ! 10260: PUTC(' '); ! 10261: /* prefix */ ! 10262: if (sign) ! 10263: PUTC(sign); ! 10264: if (flags & HEXPREFIX) { ! 10265: PUTC('0'); ! 10266: PUTC((char)*fmt); ! 10267: } ! 10268: /* right-adjusting zero padding */ ! 10269: if ((flags & (LADJUST|ZEROPAD)) == ZEROPAD) ! 10270: for (n = realsz; n < width; n++) ! 10271: PUTC('0'); ! 10272: /* leading zeroes from decimal precision */ ! 10273: for (n = fieldsz; n < dprec; n++) ! 10274: PUTC('0'); ! 10275: ! 10276: /* the string or number proper */ ! 10277: ! 10278: fp.write(t, size); ! 10279: ! 10280: /* trailing f.p. zeroes */ ! 10281: while (--fpprec >= 0) ! 10282: PUTC('0'); ! 10283: /* left-adjusting padding (always blank) */ ! 10284: if (flags & LADJUST) ! 10285: for (n = realsz; n < width; n++) ! 10286: PUTC(' '); ! 10287: /* finally, adjust cnt */ ! 10288: cnt += width > realsz ? width : realsz; ! 10289: break; ! 10290: case '\0': /* "%?" prints ?, unless ? is NULL */ ! 10291: return (cnt); ! 10292: default: ! 10293: PUTC(*fmt); ! 10294: cnt++; ! 10295: } ! 10296: } ! 10297: /* NOTREACHED */ ! 10298: } ! 10299: ! 10300: int ostream_printf(ostream& stream, const char * format ...) ! 10301: { ! 10302: int ret; ! 10303: ! 10304: va_list args; ! 10305: va_start(args, format); ! 10306: ret = vostream_printf(format, args, stream); ! 10307: va_end(args); ! 10308: return ret; ! 10309: } ! 10310: ! 10311: // There are intended to be more convienient that stirring up ! 10312: // an strstream by hand. ! 10313: ! 10314: int printf_to_string (char * string, int length, const char * format ...) ! 10315: { ! 10316: ostrstream& stream = ostrstream (string, length, (ios::open_mode)ios::app); ! 10317: ! 10318: va_list args; ! 10319: va_start(args, format); ! 10320: ! 10321: vostream_printf (format, args, stream); ! 10322: ! 10323: va_end(args); ! 10324: stream.str(); ! 10325: return stream.pcount(); ! 10326: } ! 10327: ! 10328: // caller of this must free() the string that comes back. ! 10329: ! 10330: char * printf_to_alloc_string (const char * format ...) ! 10331: { ! 10332: ostrstream& stream = ostrstream (); ! 10333: ! 10334: va_list args; ! 10335: va_start(args, format); ! 10336: ! 10337: vostream_printf (format, args, stream); ! 10338: ! 10339: va_end(args); ! 10340: return stream.str(); ! 10341: } ! 10342: 0707071010112044141004440001630000160000010176000466055377500001000000031505error.c /*ident "@(#)ctrans:src/error.c 1.4" */ ! 10343: /************************************************************************** ! 10344: ! 10345: C++ source for cfront, the C++ compiler front-end ! 10346: written in the computer science research center of Bell Labs ! 10347: ! 10348: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 10349: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 10350: ! 10351: error.c : ! 10352: ! 10353: write error messages ! 10354: ! 10355: Until scan_started != 0 no context can be assumed ! 10356: ! 10357: ***************************************************************************/ ! 10358: ! 10359: #ifdef __cplusplus ! 10360: #include <stdlib.h> ! 10361: #endif ! 10362: ! 10363: #include "cfront.h" ! 10364: #include "size.h" ! 10365: #include "template.h" ! 10366: ! 10367: int error_count; ! 10368: static int no_of_warnings; ! 10369: char scan_started; ! 10370: ! 10371: #define ERRTRACE 20 ! 10372: ! 10373: static char* abbrev_tbl[] = { ! 10374: " argument", ! 10375: " base", ! 10376: " class", ! 10377: " declaration", ! 10378: " expression", ! 10379: " function", ! 10380: " global", ! 10381: "H", ! 10382: " initialize", ! 10383: "J", ! 10384: " constructor", // 'K' ! ! 10385: " list", ! 10386: " member", ! 10387: " name", ! 10388: " object", ! 10389: " pointer", ! 10390: " qualifie", ! 10391: " reference", ! 10392: " statement", ! 10393: " type", ! 10394: " undefined", ! 10395: " variable", ! 10396: " with", ! 10397: " expected", // 'X' ! 10398: " template", // 'Y'??? ! 10399: " parameter", // 'Z'??? ! 10400: }; ! 10401: ! 10402: ea* ea0; ! 10403: ! 10404: void error_init() ! 10405: { ! 10406: static char errbuf[BUFSIZ]; ! 10407: setbuf(stderr,errbuf); ! 10408: ea0 = new ea; ! 10409: } ! 10410: ! 10411: #define INTERNAL 127 ! 10412: ! 10413: void ext(int n) ! 10414: { ! 10415: int useit=n; // to avoid n not used warning during build ! 10416: // for testing only ! 10417: // if (n == INTERNAL) ! 10418: // abort(); ! 10419: exit(error_count?error_count:1); ! 10420: } ! 10421: ! 10422: /* static */ ! 10423: void print_loc() ! 10424: { ! 10425: loc* sl = (Cstmt) ? &Cstmt->where : 0; ! 10426: loc* dl = (Cdcl && (Cdcl->base==NAME || Cdcl->base==TNAME)) ? &Cdcl->where : 0; ! 10427: if (sl && dl && sl->file==dl->file) { // Cstmt and Cdcl in same file ! 10428: if (sl->line<=dl->line) { ! 10429: if (curloc.file==dl->file && curloc.line<dl->line) ! 10430: // hack to compensate for YACC's ! 10431: // bad manners in the use of line numbers ! 10432: sl->put(out_file); ! 10433: else ! 10434: dl->put(out_file); ! 10435: } ! 10436: else ! 10437: sl->put(out_file); ! 10438: } ! 10439: else if (sl && sl->file==curr_file) // Cstmt in current file ! 10440: sl->put(out_file); ! 10441: else if (dl && dl->file==curr_file) // Cdcl in current file ! 10442: dl->put(out_file); ! 10443: else ! 10444: curloc.put(out_file); ! 10445: } ! 10446: ! 10447: static void print_context() ! 10448: { ! 10449: putc('\n',out_file); ! 10450: } ! 10451: ! 10452: static char in_error = 0; ! 10453: static loc dummy_loc; ! 10454: ! 10455: void yyerror(char* s) ! 10456: { ! 10457: error(s); ! 10458: } ! 10459: ! 10460: int error(const char* s) ! 10461: { ! 10462: return error(0,s); ! 10463: } ! 10464: ! 10465: int error(int t, const char* s) ! 10466: { ! 10467: return error(t,&dummy_loc,s,*ea0,*ea0,*ea0,*ea0); ! 10468: } ! 10469: ! 10470: int error(const char* s, const ea& a0, const ea& a1, const ea& a2, const ea& a3) ! 10471: { ! 10472: return error(0,&dummy_loc,s,a0,a1,a2,a3); ! 10473: } ! 10474: ! 10475: int error(loc* lc, const char* s, const ea& a0, const ea& a1, const ea& a2, const ea& a3) ! 10476: { ! 10477: return error(0,lc,s,a0,a1,a2,a3); ! 10478: } ! 10479: ! 10480: int error(int t, const char* s, const ea& a0, const ea& a1, const ea& a2, const ea& a3) ! 10481: { ! 10482: return error(t,&dummy_loc,s,a0,a1,a2,a3); ! 10483: } ! 10484: ! 10485: int suppress_error; ! 10486: ! 10487: int error(int t, loc* lc, const char* s, const ea& a0, const ea& a1, const ea& a2, const ea& a3) ! 10488: /* ! 10489: "int" not "void" because of "pch" in lex.c ! 10490: ! 10491: legal error types are: ! 10492: 'w' warning (not counted in error count) ! 10493: 'd' debug ! 10494: 'D' debug -- no prefix ! 10495: 's' "not implemented" message ! 10496: 'l' "compiler limit exceeded" message ! 10497: 0 error ! 10498: 'i' internal error (causes abort) ! 10499: 't' error while printing error message ! 10500: */ ! 10501: { ! 10502: if (suppress_error) return 0; ! 10503: ! 10504: if (in_error++) ! 10505: if (t == 't') ! 10506: t = 'i'; ! 10507: else if (4 < in_error) { ! 10508: fprintf(stderr,"\nOops!, error while handling error\n"); ! 10509: ext(13); ! 10510: } ! 10511: ! 10512: FILE * of = out_file; ! 10513: out_file = stderr; ! 10514: ! 10515: if (!scan_started || t=='t') ! 10516: putch('\n'); ! 10517: else if (lc != &dummy_loc) { ! 10518: if(t != 'D') lc->put(out_file); ! 10519: } else { ! 10520: if(t != 'D') print_loc(); ! 10521: } ! 10522: ! 10523: switch (t) { ! 10524: case 0: ! 10525: putstring("error: "); ! 10526: break; ! 10527: case 'd': ! 10528: putstring("DEBUG: "); ! 10529: case 'D': ! 10530: break; ! 10531: case 'w': ! 10532: no_of_warnings++; ! 10533: putstring("warning: "); ! 10534: break; ! 10535: case 'l': ! 10536: putstring("compiler limit exceeded: "); ! 10537: break; ! 10538: case 's': ! 10539: putstring("sorry, not implemented: "); ! 10540: break; ! 10541: case 'i': ! 10542: if (error_count++) { ! 10543: fprintf(out_file,"sorry, %s cannot recover from earlier errors\n",prog_name); ! 10544: ext(INTERNAL); ! 10545: } ! 10546: else ! 10547: fprintf(out_file,"internal %s error: ",prog_name); ! 10548: } ! 10549: ! 10550: ea argv[4]; ! 10551: ea* a = argv; ! 10552: argv[0] = a0; ! 10553: argv[1] = a1; ! 10554: argv[2] = a2; ! 10555: argv[3] = a3; ! 10556: ! 10557: int c; ! 10558: ! 10559: while (c = *s++) { ! 10560: if ('A'<=c && c<='Z') ! 10561: putstring(abbrev_tbl[c-'A']); ! 10562: else if (c == '%') { ! 10563: switch (c = *s++) { ! 10564: case 'k': // TOK assumed passed as an int ! 10565: { TOK x = TOK(a->i); ! 10566: if (0<x && x<=MAXTOK && keys[x]) ! 10567: fprintf(out_file," %s",keys[x]); ! 10568: else ! 10569: fprintf(out_file," token(%d)",x); ! 10570: break; ! 10571: } ! 10572: case 't': // Ptype ! 10573: { Ptype tt = Ptype(a->p); ! 10574: if (tt == 0) break; ! 10575: ! 10576: putch(' '); ! 10577: ! 10578: int nt = ntok; ! 10579: emode = 1; ! 10580: tt->dcl_print(0); ! 10581: emode = 0; ! 10582: ntok = nt; ! 10583: break; ! 10584: } ! 10585: case 'n': // Pname ! 10586: { Pname nn = Pname(a->p); ! 10587: if (nn && nn->string) { ! 10588: // suppress generated class names: ! 10589: if (nn->string[0]=='_' ! 10590: && nn->string[1]=='_' ! 10591: && nn->string[2]=='C') break; ! 10592: emode = 1; ! 10593: putch(' '); ! 10594: nn->print(); ! 10595: emode = 0; ! 10596: } ! 10597: else ! 10598: putstring(" ?"); ! 10599: break; ! 10600: } ! 10601: case 'p': // pointer ! 10602: { char* f = sizeof(char*)==sizeof(int)?" %d":" %ld"; ! 10603: fprintf(out_file,f,a->p); ! 10604: break; ! 10605: } ! 10606: case 'c': // char assumed passed as an int ! 10607: putch(a->i); ! 10608: break; ! 10609: ! 10610: case 'd': // int ! 10611: fprintf(out_file," %d",a->i); ! 10612: break; ! 10613: ! 10614: case 'o': // int ! 10615: fprintf(out_file," %o",a->i); ! 10616: break; ! 10617: ! 10618: case 's': // char* ! 10619: char *s = ((char *)a->p); ! 10620: if ( s ) putst((char*)a->p); ! 10621: break; ! 10622: } ! 10623: a++; ! 10624: } ! 10625: else ! 10626: putch(c); ! 10627: } ! 10628: ! 10629: /* ! 10630: switch (t) { ! 10631: case 'd': ! 10632: case 't': ! 10633: case 'w': ! 10634: putch('\n'); ! 10635: break; ! 10636: default: ! 10637: */ ! 10638: print_context(); ! 10639: /* ! 10640: } ! 10641: */ ! 10642: ! 10643: templ_inst::head->print_error_loc(); ! 10644: fflush(stderr); ! 10645: if (!scan_started && t!='d' && t!='w') ext(4); ! 10646: ! 10647: // now we may want to carry on ! 10648: out_file = of; ! 10649: switch (t) { ! 10650: case 't': ! 10651: if (--in_error) return 0; ! 10652: case 'i': ! 10653: ext(INTERNAL); ! 10654: case 0: ! 10655: case 'l': ! 10656: case 's': ! 10657: if (MAXERR<++error_count) { ! 10658: fprintf(stderr,"Sorry, too many errors\n"); ! 10659: ext(7); ! 10660: } ! 10661: } ! 10662: ! 10663: in_error = 0; ! 10664: return 0; ! 10665: } ! 10666: ! 10667: ! 10668: ! 10669: #ifdef DBG ! 10670: #define OPEREP(v) ((v)>MAXTOK || (v)<=0 ? 0 : keys[v]) ! 10671: void ! 10672: display_type( Ptype t ) ! 10673: { ! 10674: if ( t ) { putc(' ',stderr); ! 10675: FILE * of = out_file; ! 10676: out_file = stderr; ! 10677: extern int ntok; int nt = ntok; ! 10678: emode=1; (t)->dcl_print(0); emode=0; ! 10679: //fprintf(stderr," <node %d",t->node::id); ! 10680: if(!t->allocated)fprintf(stderr," UNALLOCATED!"); ! 10681: //putc('>',stderr); ! 10682: ntok = nt; ! 10683: out_file = of; ! 10684: } else fprintf(stderr," <null type>"); ! 10685: } ! 10686: #define INDENT(in) { for ( int i = in; i > 0; --i ) fprintf(stderr," "); } ! 10687: static indent = 0; ! 10688: ! 10689: void ! 10690: display_expr( Pexpr ptr, char* label, int oneline ) ! 10691: { ! 10692: INDENT(indent); ! 10693: if ( label ) fprintf(stderr, "%s:", label); ! 10694: if ( ptr == 0 ) { ! 10695: fprintf(stderr, "NULL EXPR\n" ); ! 10696: return; ! 10697: } ! 10698: fprintf(stderr,"%d",ptr->node::id); ! 10699: if(!ptr->allocated)fprintf(stderr," UNALLOCATED!"); ! 10700: putc(':',stderr); ! 10701: char* s = OPEREP(ptr->base); ! 10702: if ( s == 0 ) ! 10703: fprintf(stderr, "token(%d)", ptr->base ); ! 10704: else ! 10705: fprintf(stderr,"%s",s); ! 10706: if ( ptr->displayed ) { // recursion!!! ! 10707: if ( ptr->base == NAME ) ! 10708: fprintf(stderr," '%s'",Pname(ptr)->string); ! 10709: fprintf(stderr," RECURSION!!!\n"); ! 10710: ptr->displayed = 0; ! 10711: return; ! 10712: } ! 10713: ptr->displayed = 1; ! 10714: switch ( ptr->base ) { ! 10715: case QUEST: ! 10716: display_type(ptr->tp); ! 10717: putc('\n',stderr); ! 10718: if ( !oneline ) { ! 10719: ++indent; ! 10720: display_expr( ptr->cond, "cond" ); ! 10721: display_expr( ptr->e1, "e1" ); ! 10722: display_expr( ptr->e2, "e2" ); ! 10723: --indent; ! 10724: } ! 10725: break; ! 10726: case REF: case DOT: ! 10727: display_type(ptr->tp); ! 10728: putc('\n',stderr); ! 10729: if ( !oneline ) { ! 10730: ++indent; ! 10731: display_expr( ptr->e1, "e1" ); ! 10732: display_expr( ptr->mem, "mem" ); ! 10733: --indent; ! 10734: } ! 10735: break; ! 10736: case MDOT: ! 10737: display_type(ptr->tp); ! 10738: fprintf(stderr," string2:'%s'\n",ptr->string2?ptr->string2:""); ! 10739: if ( !oneline ) { ! 10740: ++indent; ! 10741: display_expr( ptr->mem, "mem" ); ! 10742: --indent; ! 10743: } ! 10744: break; ! 10745: case ICALL: ! 10746: fprintf(stderr," fn=='%s'",ptr->il->fct_name->string); ! 10747: display_type(ptr->tp); ! 10748: putc('\n',stderr); ! 10749: if ( !oneline ) { ! 10750: ++indent; ! 10751: for ( int i = 0; i < ptr->il->i_slots; ++i ) { ! 10752: ia *aa = &ptr->il->i_args[i]; ! 10753: INDENT(indent); ! 10754: fprintf(stderr,"arg:'%s'",aa->local&&aa->local->string?aa->local->string:""); ! 10755: display_type(aa->tp); ! 10756: putc('\n',stderr); ! 10757: ++indent; ! 10758: display_expr( aa->arg, "actual" ); ! 10759: --indent; ! 10760: } ! 10761: display_expr( ptr->e1, "e1" ); ! 10762: display_expr( ptr->e2, "e2" ); ! 10763: --indent; ! 10764: } ! 10765: break; ! 10766: case SIZEOF: ! 10767: if ( ptr->tp2 ) { ! 10768: putc('(',stderr); ! 10769: display_type(ptr->tp2); ! 10770: putc(')',stderr); ! 10771: } ! 10772: display_type(ptr->tp); ! 10773: putc('\n',stderr); ! 10774: if ( !oneline ) { ! 10775: if ( ptr->e1 ) { ! 10776: ++indent; ! 10777: display_expr(ptr->e1,"e1"); ! 10778: --indent; ! 10779: } ! 10780: if ( ptr->e2 ) { ! 10781: ++indent; ! 10782: display_expr(ptr->e2,"e2"); ! 10783: --indent; ! 10784: } ! 10785: } ! 10786: break; ! 10787: case ZERO: ! 10788: display_type(ptr->tp); ! 10789: putc('\n',stderr); ! 10790: break; ! 10791: case NAME: case TNAME: case STRING: ! 10792: case ICON: case ID: ! 10793: case FCON: case CCON: ! 10794: case IVAL: ! 10795: fprintf(stderr," '%s'",(ptr->string)?ptr->string:"<0>"); ! 10796: display_type(ptr->tp); ! 10797: if(ptr->string2)fprintf(stderr," string2=='%s'",ptr->string2); ! 10798: if ( ptr->permanent ) fprintf(stderr, " (permanent)"); ! 10799: if ( ptr->base == IVAL ) fprintf(stderr, " i1==%d", ptr->i1); ! 10800: putc('\n',stderr); ! 10801: if ( !oneline && (ptr->base == NAME || ptr->base == TNAME) ) { ! 10802: Pname n = Pname(ptr); ! 10803: ++indent; ! 10804: INDENT(indent); ! 10805: fprintf(stderr, "n_sto==%d", n->n_sto ); ! 10806: fprintf(stderr, " n_stclass==%d",n->n_stclass); ! 10807: fprintf(stderr, " n_scope==%d",n->n_scope); ! 10808: fprintf(stderr, " n_protected==%d\n", n->n_protect ); ! 10809: INDENT(indent); ! 10810: fprintf(stderr, "n_oper=='%s'", (s=OPEREP(n->base))?s:"0"); ! 10811: fprintf(stderr, " n_val==%d", n->n_val ); ! 10812: fprintf(stderr, " n_xref==%d",n->n_xref); ! 10813: fprintf(stderr, " lex_level==%d\n", n->lex_level ); ! 10814: INDENT(indent); ! 10815: fprintf(stderr, "n_used==%d",n->n_used); ! 10816: fprintf(stderr, " n_assigned_to==%d",n->n_assigned_to); ! 10817: fprintf(stderr, " n_addr_taken==%d\n",n->n_addr_taken ); ! 10818: INDENT(indent); ! 10819: fprintf(stderr, "n_union==%d", n->n_union); ! 10820: fprintf(stderr, " n_list=='%s'", n->n_list?n->n_list->string:"<0>" ); ! 10821: fprintf(stderr, " n_qualifier=='%s'", n->n_qualifier?n->n_qualifier->string:"<0>" ); ! 10822: if ( n->n_initializer ) { ! 10823: fprintf(stderr, " n_initializer:\n" ); ! 10824: ++indent; ! 10825: display_expr( n->n_initializer ); ! 10826: --indent; ! 10827: } else fprintf(stderr, " n_initializer==<0>\n"); ! 10828: --indent; ! 10829: } ! 10830: break; ! 10831: case BLOCK: ! 10832: ((Pstmt)ptr)->where.put(stderr); putc(' ',stderr); ! 10833: putc('\n',stderr); ! 10834: break; ! 10835: default: ! 10836: display_type(ptr->tp); ! 10837: putc('\n',stderr); ! 10838: if ( !oneline && ptr->base > 0 ! 10839: && (ptr->base<165 || ptr->base==MEMPTR) ) { ! 10840: ++indent; ! 10841: display_expr( ptr->e1, "e1" ); ! 10842: display_expr( ptr->e2, "e2" ); ! 10843: --indent; ! 10844: } ! 10845: break; ! 10846: } ! 10847: ptr->displayed = 0; ! 10848: return; ! 10849: } ! 10850: void ! 10851: display_stmt( Pstmt ptr, char* label, int oneline ) ! 10852: { ! 10853: INDENT(indent); ! 10854: if ( label ) fprintf(stderr, "%s:", label); ! 10855: if ( ptr == 0 ) { ! 10856: fprintf(stderr, "NULL STMT\n" ); ! 10857: return; ! 10858: } ! 10859: fprintf(stderr,"%d",ptr->node::id); ! 10860: if(!ptr->allocated)fprintf(stderr," UNALLOCATED!"); ! 10861: putc(':',stderr); ! 10862: char* s = OPEREP(ptr->base); ! 10863: if ( s == 0 ) ! 10864: fprintf(stderr, "token(%d)", ptr->base ); ! 10865: else ! 10866: fprintf(stderr,"%s",s); ! 10867: if ( ptr->displayed ) { // recursion!!! ! 10868: if ( ptr->base == NAME ) ! 10869: fprintf(stderr," '%s'",Pname(ptr)->string); ! 10870: fprintf(stderr," RECURSION!!!\n"); ! 10871: ptr->displayed = 0; ! 10872: return; ! 10873: } ! 10874: putc(' ',stderr); ! 10875: ptr->where.put(stderr); ! 10876: if ( oneline ) { putc('\n',stderr); return; } ! 10877: ptr->displayed = 1; ! 10878: switch ( ptr->base ) { ! 10879: case BLOCK: ! 10880: fprintf(stderr," .. "); ! 10881: ptr->where2.put(stderr); ! 10882: putc('\n',stderr); ! 10883: ++indent; ! 10884: { for( Pstmt st = ptr->s; st; st = st->s_list ) ! 10885: display_stmt( ptr->s, "s" ); ! 10886: } ! 10887: --indent; ! 10888: break; ! 10889: case IF: ! 10890: putc('\n',stderr); ! 10891: ++indent; ! 10892: display_expr(ptr->e,"cond"); ! 10893: display_stmt(ptr->s,"if-clause"); ! 10894: --indent; ! 10895: if ( ptr->else_stmt ) { ! 10896: INDENT(indent); ! 10897: fprintf(stderr,"else\n"); ! 10898: ++indent; ! 10899: display_stmt(ptr->else_stmt,"else-clause"); ! 10900: --indent; ! 10901: } ! 10902: break; ! 10903: case DO: ! 10904: putc('\n',stderr); ! 10905: ++indent; ! 10906: display_stmt(ptr->s,"do-stmt"); ! 10907: display_expr(ptr->e,"cond"); ! 10908: --indent; ! 10909: break; ! 10910: case WHILE: ! 10911: putc('\n',stderr); ! 10912: ++indent; ! 10913: display_expr(ptr->e,"cond"); ! 10914: display_stmt(ptr->s,"while-stmt"); ! 10915: --indent; ! 10916: break; ! 10917: case FOR: ! 10918: putc('\n',stderr); ! 10919: ++indent; ! 10920: display_stmt(ptr->for_init,"init"); ! 10921: display_expr(ptr->e,"cond"); ! 10922: display_expr(ptr->e2,"incr"); ! 10923: display_stmt(ptr->s,"stmt"); ! 10924: --indent; ! 10925: break; ! 10926: case RETURN: ! 10927: putc('\n',stderr); ! 10928: ++indent; ! 10929: display_expr(ptr->e,"e"); ! 10930: --indent; ! 10931: break; ! 10932: case SM: ! 10933: putc('\n',stderr); ! 10934: ++indent; ! 10935: display_expr(ptr->e,"e"); ! 10936: --indent; ! 10937: break; ! 10938: default: ! 10939: putc('\n',stderr); ! 10940: break; ! 10941: } ! 10942: ptr->displayed = 0; ! 10943: return; ! 10944: } ! 10945: ! 10946: void ! 10947: display_namelist( Plist nl, char* s, int verbose ) ! 10948: { ! 10949: error('d',"namelist: %s",s?s:""); ! 10950: ++indent; ! 10951: for ( Plist l = nl; l; l = l->l ) { ! 10952: Pname n = l->f; ! 10953: INDENT(indent); ! 10954: fprintf(stderr," %d",n); ! 10955: error('D'," %n %k n_key %d",n,n?n->tp->base:0,n?n->n_key:0); ! 10956: if ( verbose ) { ! 10957: ++indent; ! 10958: display_expr(n); ! 10959: --indent; ! 10960: } ! 10961: } ! 10962: --indent; ! 10963: } ! 10964: #endif ! 10965: 0707071010112044151004440001630000160000010176300466055400100001100000053752expand.c /*ident "@(#)ctrans:src/expand.c 1.3" */ ! 10966: /***************************************************************** ! 10967: ! 10968: C++ source for cfront, the C++ compiler front-end ! 10969: written in the computer science research center of Bell Labs ! 10970: ! 10971: Copyright (c) 1984 AT&T, Inc. All rights Reserved ! 10972: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 10973: ! 10974: expand.c: ! 10975: ! 10976: expand inline functions ! 10977: ! 10978: ******************************************************************/ ! 10979: ! 10980: #include "cfront.h" ! 10981: static Ptable Scope; ! 10982: // extern void display_expr(Pexpr); ! 10983: ! 10984: static char* temp(char* vn, Pname fn) ! 10985: // ! 10986: // make the name of the temporary: __Xvn00xxxxxx ! 10987: // xxxxxx is a representation of fn's address - ! 10988: // anything unique will do. we use radix 32 here ! 10989: // add two bytes to make the name sensitive to the scope ! 10990: // to avoid re-using temps when an inline is expanded in ! 10991: // more than one other inline that is then called in the ! 10992: // same expression ! 10993: // ! 10994: { ! 10995: if (vn[0]!='_' || vn[1]!='_' || vn[2]!='X') { ! 10996: unsigned long a = (unsigned long) fn->tp; ! 10997: ! 10998: // al = the number of radix-32 chars in a ! 10999: unsigned long aa = a; ! 11000: int al = 0; ! 11001: while (aa) { ! 11002: al++; ! 11003: aa >>= 5; ! 11004: } ! 11005: ! 11006: // allocate memory for the result ! 11007: int ll = strlen(vn); ! 11008: char* s = new char[ll+al+8]; ! 11009: register char* p = s; ! 11010: ! 11011: // append _ _ X vn ! 11012: *p++ = '_'; ! 11013: *p++ = '_'; ! 11014: *p++ = 'X'; ! 11015: strcpy(p,vn); ! 11016: p += ll; ! 11017: *p++ = '0'; ! 11018: *p++ = '0'; ! 11019: ! 11020: // append representation of `a' ! 11021: while (a) { ! 11022: *p++ = "abcdefghijklmnopqrstuvwxyz012345"[a&037]; ! 11023: a >>= 5; ! 11024: } ! 11025: ! 11026: // append scope representation and trailing null ! 11027: *p++ = 'a' + ((int(Scope)>>4)&15); ! 11028: *p++ = 'a' + ((int(Scope)>>8)&15); ! 11029: *p = '\0'; ! 11030: //tmp error('d',"temp(%s,%n) -- scope %d -- returning %s",vn,fn,scope,s); ! 11031: return s; ! 11032: } ! 11033: else { ! 11034: //tmp error('d',"temp(%s,%n) -- scope %d -- returning %s",vn,fn,scope,vn); ! 11035: return vn; ! 11036: } ! 11037: ! 11038: } ! 11039: ! 11040: Pname dcl_local(Ptable scope, Pname an, Pname fn) ! 11041: { ! 11042: if (scope == 0 || scope->base == 0) { ! 11043: if (sti_tbl == 0) sti_tbl = new table(8,gtbl,0); ! 11044: scope = sti_tbl; ! 11045: // error('s',"cannot expand inlineF needing temporaryV in nonF context"); ! 11046: // return an; ! 11047: } ! 11048: ! 11049: if (an->n_stclass == STATIC) { ! 11050: if (an->tp->base!=FCT) error('s',&fn->where,"cannot expand inlineF with static%n",an); ! 11051: return an; ! 11052: } ! 11053: ! 11054: Pname cn = fn->n_table->t_name; ! 11055: char* s = temp(an->string,fn); ! 11056: Pname nx = new name(s); ! 11057: Ptype atp = an->tp; ! 11058: //error('d',"dcl_local(%d,%n,%n) -> %s",scope,an,fn,s); ! 11059: while (atp->base == TYPE) atp = Pbase(atp)->b_name->tp; ! 11060: if (atp->base == VEC) { ! 11061: if (an->n_scope == ARG) { ! 11062: Pptr t = new ptr(PTR,Pvec(atp)->typ); ! 11063: nx->tp = t; ! 11064: } ! 11065: else { ! 11066: error('s',&fn->where,"cannot expand inlineF needing temporaryV of vectorT"); ! 11067: return an; ! 11068: } ! 11069: } ! 11070: else ! 11071: nx->tp = atp; ! 11072: PERM(nx->tp); ! 11073: ! 11074: nx->n_used = an->n_used; ! 11075: nx->n_assigned_to = an->n_assigned_to; ! 11076: nx->n_addr_taken = an->n_addr_taken; ! 11077: nx->n_xref = an->n_xref; ! 11078: //error('d',"nx %n %t,",nx,nx->tp); ! 11079: Pname r = scope->look(nx->string,0); ! 11080: if (r) { ! 11081: //error('d',"ll %n %t",ll,ll->tp); ! 11082: if (r->tp->check(nx->tp,0)) ! 11083: error('s',&fn->where,"cannot expand inlineF %n with two local variables with the sameN (%s)",fn,an->string); ! 11084: else ! 11085: r = 0; ! 11086: } ! 11087: if (r==0) { ! 11088: r = scope->insert(nx,0); ! 11089: //error('d',"%d %d %d %d",r->n_stclass,an->n_stclass,r->lex_level,an->lex_level); ! 11090: r->n_stclass = an->n_stclass; ! 11091: r->lex_level = an->lex_level; ! 11092: delete nx; ! 11093: r->where.line = 0; ! 11094: } ! 11095: return r; ! 11096: } ! 11097: ! 11098: int ck_cast(Ptype t1, Ptype t2) ! 11099: /* ! 11100: return a value of type t2 from a function returning a t1 ! 11101: return 1 if cast is needed ! 11102: */ ! 11103: { ! 11104: st: ! 11105: while (t1->base == TYPE) t1 = Pbase(t1)->b_name->tp; ! 11106: while (t2->base == TYPE) t2 = Pbase(t2)->b_name->tp; ! 11107: ! 11108: if (t1 == t2) return 0; ! 11109: ! 11110: if (t1->base != t2->base) return 1; ! 11111: ! 11112: switch (t1->base) { ! 11113: case RPTR: ! 11114: case PTR: ! 11115: { t1 = Pptr(t1)->typ; ! 11116: if (t1->base == VOID) return 1; ! 11117: t2 = Pptr(t2)->typ; ! 11118: goto st; ! 11119: } ! 11120: case CHAR: ! 11121: case SHORT: ! 11122: case INT: ! 11123: case LONG: ! 11124: if (Pbase(t1)->b_unsigned != Pbase(t2)->b_unsigned) return 1; ! 11125: break; ! 11126: case COBJ: ! 11127: { ! 11128: Pname nn = Pbase(t1)->b_name; ! 11129: ! 11130: if (Pclass(nn->tp)->csu==UNION ) return 0; ! 11131: ! 11132: if (t2->base==COBJ && nn->tp==Pbase(t2)->b_name->tp) return 0; ! 11133: ! 11134: return 1; ! 11135: } ! 11136: } ! 11137: ! 11138: return 0; ! 11139: } ! 11140: ! 11141: int makeCM( Ptype t ) ! 11142: /* return 1 if the type is not a primitive type ! 11143: * this will cause the generation of (t,0) ! 11144: * note: ``t'' is guaranteed not to be 0 ! 11145: */ ! 11146: { ! 11147: while ( t->base == TYPE ) ! 11148: t = Pbase(t)->b_name->tp; ! 11149: ! 11150: switch (t->base) { ! 11151: case FLOAT: ! 11152: case DOUBLE: ! 11153: case LDOUBLE: ! 11154: case CHAR: ! 11155: case SHORT: ! 11156: case INT: ! 11157: case LONG: ! 11158: case EOBJ: ! 11159: return 0; ! 11160: default: ! 11161: return 1; ! 11162: } ! 11163: } ! 11164: ! 11165: static ret_seen = 0; ! 11166: ! 11167: Pstmt stmt::expand() ! 11168: /* ! 11169: copy the statements with the formal arguments replaced by ANAMES ! 11170: ! 11171: called once only per inline function ! 11172: expand_tbl!=0 if the function should be transformed into an expression ! 11173: and expand_tbl is the table for local variables ! 11174: */ ! 11175: { ! 11176: if (this == 0) error('i',"0->S::expand() for%n",expand_fn); ! 11177: Pstmt ostmt = Cstmt; ! 11178: if ( where.line ) Cstmt = this; ! 11179: ! 11180: if (memtbl) { /* check for static variables */ ! 11181: register Ptable t = memtbl; ! 11182: register int i; ! 11183: for (register Pname n = t->get_mem(i=1); n; n=t->get_mem(++i)) { ! 11184: if (n->n_stclass == STATIC) { ! 11185: if (n->tp->base == FCT) continue; ! 11186: error('s',"cannot expand inlineF with static%n",n); ! 11187: n->n_stclass = AUTO; ! 11188: } ! 11189: n->where.line = 0; ! 11190: } ! 11191: } ! 11192: ! 11193: if (expand_tbl) { /* make expression */ ! 11194: Pexpr ee; ! 11195: ! 11196: if (memtbl) { // temporaries ! 11197: int i; ! 11198: for (Pname n=memtbl->get_mem(i=1); n; n=memtbl->get_mem(++i)) { ! 11199: //error('d',"block %n %k %d %d",n,base,memtbl->real_block == this,n->lex_level); ! 11200: if (n->base!=NAME || n->tp==any_type) continue; ! 11201: ! 11202: if (base==BLOCK ! 11203: && memtbl->real_block == this ! 11204: && n->lex_level < 2 ! 11205: && (n->string[0]!='_' // promoted from called ! 11206: // inlines ! 11207: || n->string[1]!='_' ! 11208: || ( n->string[2]!='X' ! 11209: && n->string[2]!='K')) ! 11210: ) { ! 11211: //error('d',"not promoting%n",n); ! 11212: continue; ! 11213: } ! 11214: ! 11215: if (memtbl != scope) ! 11216: { ! 11217: Pname nn = dcl_local(scope,n,expand_fn); ! 11218: nn->base = NAME; ! 11219: n->string = nn->string; ! 11220: } ! 11221: else if (n->tp->base!=FCT && n->tp->base!=OVERLOAD){ ! 11222: n->string = temp(n->string, expand_fn); ! 11223: n->where.line = 0; ! 11224: } ! 11225: } ! 11226: } ! 11227: ! 11228: switch (base) { ! 11229: default: ! 11230: error('s',"cannot expand inlineF%n with %kS in inline",expand_fn,base); ! 11231: Cstmt = ostmt; ! 11232: return Pstmt(dummy); ! 11233: ! 11234: case BLOCK: ! 11235: DB(if(Edebug>=2){error('d',"stmt::expand() -- block");display_stmt(this);}); ! 11236: if (s_list) { ! 11237: ee = Pexpr(s_list->expand()); ! 11238: if (s) { ! 11239: ee = new expr(CM, Pexpr(s->expand()), ee); ! 11240: ee->tp = ee->e2->tp; ! 11241: PERM(ee); ! 11242: } ! 11243: Cstmt = ostmt; ! 11244: return Pstmt(ee); ! 11245: } ! 11246: ! 11247: if (s) { ! 11248: Pstmt st = s->expand(); ! 11249: Cstmt = ostmt; ! 11250: return st; ! 11251: } ! 11252: ! 11253: Cstmt = ostmt; ! 11254: return Pstmt(zero); ! 11255: ! 11256: case PAIR: ! 11257: ee = s2 ? Pexpr(s2->expand()) : 0; ! 11258: ee = new expr(CM, s?Pexpr(s->expand()):0, ee); ! 11259: ee->tp = ee->e2->tp; ! 11260: if (s_list) { ! 11261: ee = new expr(CM, ee, Pexpr(s_list->expand())); ! 11262: ee->tp = ee->e2->tp; ! 11263: } ! 11264: PERM(ee); ! 11265: Cstmt = ostmt; ! 11266: return Pstmt(ee); ! 11267: ! 11268: case RETURN: ! 11269: ret_seen = 1; ! 11270: s_list = 0; ! 11271: ! 11272: if (e == 0) ! 11273: ee = zero; ! 11274: else { ! 11275: ee = e->expand(); ! 11276: Ptype tt = Pfct(expand_fn->tp)->returns; ! 11277: if (tt == 0) tt = Pfct(expand_fn->tp)->returns; ! 11278: //error('d',"return::expand() -- ee==%k tt==%t",ee?ee->base:0,tt); ! 11279: //display_expr(ee); ! 11280: if (tt!=ee->tp && ck_cast(tt,ee->tp)) ee = new cast(tt,ee); ! 11281: } ! 11282: ! 11283: Cstmt = ostmt; ! 11284: return Pstmt(ee); ! 11285: ! 11286: case SM: ! 11287: if (e== 0 || e==dummy) ! 11288: ee = zero; ! 11289: else { ! 11290: if (e->base == DEREF) e = e->e1; ! 11291: ee = e->expand(); ! 11292: } ! 11293: // no break; ! 11294: ! 11295: case ASM: ! 11296: if (s_list) { ! 11297: ee = new expr(CM, ee, (Pexpr)s_list->expand()); ! 11298: ee->tp = ee->e2->tp; ! 11299: PERM(ee); ! 11300: } ! 11301: Cstmt = ostmt; ! 11302: return (Pstmt)ee; ! 11303: ! 11304: case IF: ! 11305: { ! 11306: int ors = ret_seen; ! 11307: ret_seen = 0; ! 11308: ee = Pexpr(s->expand()); ! 11309: if(ee->base==ASSIGN && ee->e1->tp && ! 11310: ee->e1->tp->base != PTR) ! 11311: ee = new expr(G_CM,ee,zero); ! 11312: Pexpr qq = new expr(QUEST,ee,zero); ! 11313: int ret1 = ret_seen; ! 11314: ret_seen = 0; ! 11315: ! 11316: qq->cond = e->expand(); ! 11317: qq->e2 = else_stmt ? Pexpr(else_stmt->expand()) : zero; ! 11318: int ret2 = ret_seen; ! 11319: if (ret1+ret2 && s_list) { ! 11320: error('s',"cannot expand inlineF%n with S after \"return\"",expand_fn); ! 11321: ret_seen = 0; ! 11322: } ! 11323: ret_seen += ret1; ! 11324: ret_seen += ret2; ! 11325: ret_seen += ors; ! 11326: ! 11327: // handle ``if (x) class_object_valued_expression;'' ! 11328: ! 11329: Ptype t1 = qq->e1->tp; ! 11330: Ptype t2 = qq->e2->tp; ! 11331: ! 11332: if (t1 && t1->base==FCT) ! 11333: t1 = Pfct(t1)->s_returns ? Pfct(t1)->s_returns : Pfct(t1)->returns; ! 11334: ! 11335: if (t2 && t2->base==FCT) ! 11336: t2 = Pfct(t2)->s_returns ? Pfct(t2)->s_returns : Pfct(t2)->returns; ! 11337: ! 11338: Pname c1 = t1?t1->is_cl_obj():0; ! 11339: Pname c2 = t2?t2->is_cl_obj():0; ! 11340: ! 11341: int z1 = c1 && c1!=c2; ! 11342: int z2 = c2 && c1!=c2; ! 11343: ! 11344: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2); ! 11345: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2); ! 11346: //display_expr(qq); ! 11347: if (c1==0 ! 11348: && c2==0 ! 11349: && t1 ! 11350: && t2 ! 11351: && t2->check(t1,ASSIGN) ! 11352: && t1->check(t2,ASSIGN)) { ! 11353: z1 = makeCM( t1 ); ! 11354: z2 = makeCM( t2 ); ! 11355: if ((z1 && ret1) || (z2 && ret2)) ! 11356: error('s',"cannot expand inlineF with return in ifS"); ! 11357: } ! 11358: ! 11359: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2); ! 11360: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2); ! 11361: //display_expr(qq); ! 11362: if (t1 && z1==0) { ! 11363: // since zero is acceptable to all pointer types ! 11364: // we need only ``fix'' z1 and z2 will take care ! 11365: // of itself ! 11366: z1 = t1->is_ptr_or_ref() ! 11367: && t2 ! 11368: && t2->is_ptr_or_ref() ! 11369: && t1->check(t2,0) ! 11370: && !const_problem; ! 11371: } ! 11372: ! 11373: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2); ! 11374: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2); ! 11375: //display_expr(qq); ! 11376: if (z1) { ! 11377: Pexpr v = (z2==0 && (t2->is_ptr_or_ref())) ? new cast(t2,zero) : zero; ! 11378: qq->e1 = new expr(CM,qq->e1,v); ! 11379: qq->e1->tp = qq->e1->e1->tp; ! 11380: } ! 11381: ! 11382: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2); ! 11383: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2); ! 11384: //display_expr(qq); ! 11385: if (z2) { ! 11386: Pexpr v = (z1==0 && (t1->is_ptr_or_ref())) ? new cast(t1,zero) : zero; ! 11387: qq->e2 = new expr(CM,qq->e2,v); ! 11388: qq->e2->tp = qq->e2->e1->tp; ! 11389: } ! 11390: ! 11391: //error('d',"if()%k%t else%k%t",qq->e1->base,t1,qq->e2->base,t2); ! 11392: //error('d',"c1%n c2%n %d %d",c1,c2,z1,z2); ! 11393: //display_expr(qq); ! 11394: if (s_list) { ! 11395: qq = new expr(CM,qq,Pexpr(s_list->expand())); ! 11396: qq->tp = qq->e2->tp; ! 11397: } ! 11398: else ! 11399: qq->tp = qq->e1->tp; ! 11400: PERM(qq); ! 11401: Cstmt = ostmt; ! 11402: return Pstmt(qq); ! 11403: } ! 11404: } ! 11405: } ! 11406: ! 11407: where.line = 0; ! 11408: ! 11409: switch (base) { ! 11410: default: ! 11411: if (e) e = e->expand(); ! 11412: break; ! 11413: case PAIR: ! 11414: if (s2) s2 = s2->expand(); ! 11415: break; ! 11416: case BLOCK: ! 11417: break; ! 11418: case FOR: ! 11419: if (for_init) for_init = for_init->expand(); ! 11420: if (e2) e2 = e2->expand(); ! 11421: case ASM: ! 11422: break; ! 11423: // case LABEL: ! 11424: // case GOTO: ! 11425: case RETURN: ! 11426: // case BREAK: ! 11427: // case CONTINUE: ! 11428: error('s',"cannot expand inlineF%n with %kS",expand_fn,base); ! 11429: } ! 11430: ! 11431: if (s) s = s->expand(); ! 11432: if (s_list) s_list = s_list->expand(); ! 11433: PERM(this); ! 11434: Cstmt = ostmt; ! 11435: return this; ! 11436: } ! 11437: ! 11438: Pexpr expr::expand() ! 11439: { ! 11440: if (this == 0) error('i',"E::expand(0)"); ! 11441: ! 11442: switch (base) { ! 11443: case NAME: ! 11444: if (expand_tbl && Pname(this)->n_scope==FCT) { ! 11445: Pname n = Pname(this); ! 11446: char* s = n->string; ! 11447: if (s[0]=='_' && s[1]=='_' && s[2]=='X') break; ! 11448: Pname cn = expand_fn->n_table->t_name; ! 11449: // n->string = temp(s,expand_fn->string,(cn)?cn->string:0); ! 11450: n->string = temp(s,expand_fn); ! 11451: } ! 11452: case DUMMY: ! 11453: case ICON: ! 11454: case FCON: ! 11455: case CCON: ! 11456: case IVAL: ! 11457: //case FVAL: ! 11458: //case LVAL: ! 11459: case STRING: ! 11460: case ZERO: ! 11461: case TEXT: ! 11462: case ANAME: ! 11463: case MDOT: ! 11464: break; ! 11465: case ICALL: ! 11466: if (expand_tbl && e1==0) { ! 11467: int ors = ret_seen; ! 11468: ret_seen = 0; ! 11469: Pname fn = il->fct_name; ! 11470: Pfct f = Pfct(fn->tp); ! 11471: if (f->f_expr==0 ! 11472: // f->returns==void_type ! 11473: // && f->s_returns!=int_type ! 11474: // && fn->n_oper!=CTOR ! 11475: ) ! 11476: error('s',&fn->where,"cannot expand value-returning inline%n with call of non-value-returning inline%n",expand_fn,fn); ! 11477: // else ! 11478: // error("inline%n called before defined",fn); ! 11479: ret_seen = ors; ! 11480: } ! 11481: break; ! 11482: case SIZEOF: ! 11483: case CAST: ! 11484: if (tp2) PERM(tp2); ! 11485: goto rrr; ! 11486: case QUEST: ! 11487: cond = cond->expand(); ! 11488: default: ! 11489: if (e2) e2 = e2->expand(); ! 11490: case REF: ! 11491: case DOT: ! 11492: rrr: ! 11493: if (e1) e1 = e1->expand(); ! 11494: break; ! 11495: } ! 11496: ! 11497: switch (base) { ! 11498: case CM: ! 11499: case G_CM: ! 11500: if (tp==0) tp=e2->tp; ! 11501: } ! 11502: ! 11503: PERM(this); ! 11504: return this; ! 11505: } ! 11506: ! 11507: int nin; ! 11508: ! 11509: static int watch_out; ! 11510: bit expr::not_simple() ! 11511: /* ! 11512: is a temporary variable needed to hold the value of this expression ! 11513: as an argument for an inline expansion? ! 11514: return 1; if side effect ! 11515: return 2; if modifies expression ! 11516: */ ! 11517: { ! 11518: int s; ! 11519: //error('d',"not_simple%k",base); ! 11520: switch (base) { ! 11521: default: ! 11522: return 2; ! 11523: case NAME: ! 11524: if (nin==0 && Pname(this)->n_table==gtbl) return 2; // unsafe: aliasing ! 11525: case ZERO: ! 11526: case IVAL: ! 11527: //case FVAL: ! 11528: case ICON: ! 11529: case CCON: ! 11530: case FCON: ! 11531: return 0; ! 11532: case STRING: ! 11533: ::watch_out = 1; ! 11534: return 0; ! 11535: case MDOT: ! 11536: return mem->not_simple(); ! 11537: case SIZEOF: ! 11538: return (e1==0 || e1==dummy) ? 0 : e1->not_simple(); ! 11539: case G_ADDROF: ! 11540: case ADDROF: ! 11541: return e2->not_simple(); ! 11542: case CAST: ! 11543: return e1->not_simple(); ! 11544: case DOT: ! 11545: ::watch_out = 1; ! 11546: return e1->not_simple(); ! 11547: case REF: ! 11548: ::watch_out = 1; ! 11549: return e1->not_simple(); ! 11550: case UMINUS: ! 11551: case NOT: ! 11552: case COMPL: ! 11553: return e2->not_simple(); ! 11554: case DEREF: ! 11555: s = e1->not_simple(); ! 11556: if (1<s) return 2; ! 11557: if (e2==0) return s; ! 11558: return s |= e2->not_simple(); ! 11559: case MUL: ! 11560: case DIV: ! 11561: case MOD: ! 11562: case PLUS: ! 11563: case MINUS: ! 11564: case LS: ! 11565: case RS: ! 11566: case AND: ! 11567: case OR: ! 11568: case ER: ! 11569: case LT: ! 11570: case LE: ! 11571: case GT: ! 11572: case GE: ! 11573: case EQ: ! 11574: case NE: ! 11575: case ANDAND: ! 11576: case OROR: ! 11577: case CM: ! 11578: s = e1->not_simple(); ! 11579: if (1<s) return 2; ! 11580: return s |= e2->not_simple(); ! 11581: case QUEST: ! 11582: s = cond->not_simple(); ! 11583: if (1<s) return 2; ! 11584: s |= e1->not_simple(); ! 11585: if (1<s) return 2; ! 11586: return s |= e2->not_simple(); ! 11587: case ANAME: ! 11588: if (curr_icall) { ! 11589: Pname n = (Pname)this; ! 11590: int argno = int(n->n_val); ! 11591: for (Pin il=curr_icall; il; il=il->i_next) ! 11592: if (n->n_table == il->i_table) goto aok; ! 11593: goto bok; ! 11594: aok: ! 11595: return (il->i_args[argno].local) ? 0 : il->i_args[argno].arg->not_simple(); ! 11596: } ! 11597: bok: error('i',"expand aname%n",this); ! 11598: case G_CM: ! 11599: case VALUE: ! 11600: case NEW: ! 11601: case GNEW: ! 11602: case CALL: ! 11603: case G_CALL: ! 11604: case ICALL: ! 11605: case ASSIGN: ! 11606: case INCR: ! 11607: case DECR: ! 11608: case ASPLUS: ! 11609: case ASMINUS: ! 11610: case ASMUL: ! 11611: case ASDIV: ! 11612: case ASMOD: ! 11613: case ASAND: ! 11614: case ASOR: ! 11615: case ASER: ! 11616: case ASLS: ! 11617: case ASRS: ! 11618: return 2; ! 11619: } ! 11620: } ! 11621: ! 11622: extern void uninline(Pname fn); ! 11623: //extern Pname new_fct; ! 11624: //extern Pname del_fct; ! 11625: extern Pstmt del_list; ! 11626: extern Pstmt break_del_list; ! 11627: extern Pstmt continue_del_list; ! 11628: extern Pname curr_fct; ! 11629: extern Pexpr init_list; ! 11630: ! 11631: extern Pname make_default_ctor(Pclass cl); ! 11632: void expand_itor(Pclass cl) ! 11633: { ! 11634: //error('d',"expand_itor(%t)",cl); ! 11635: Pexpr s2 = curr_expr; ! 11636: Pstmt s5 = del_list; ! 11637: Pstmt s6 = break_del_list; ! 11638: Pstmt s7 = continue_del_list; ! 11639: Pname s8 = curr_fct; ! 11640: Pexpr s9 = init_list; ! 11641: (void) cl->make_itor(1); ! 11642: curr_expr = s2; ! 11643: del_list = s5; ! 11644: break_del_list = s6; ! 11645: continue_del_list = s7; ! 11646: curr_fct = s8; ! 11647: init_list = s9; ! 11648: } ! 11649: /* ! 11650: extern Pname make_default_dtor(Pclass cl); ! 11651: void expand_dtor(Pclass cl) ! 11652: { ! 11653: //error('d',"expand_itor(%t)",cl); ! 11654: Pexpr s2 = curr_expr; ! 11655: Pstmt s5 = del_list; ! 11656: Pstmt s6 = break_del_list; ! 11657: Pstmt s7 = continue_del_list; ! 11658: Pname s8 = curr_fct; ! 11659: Pexpr s9 = init_list; ! 11660: (void) make_default_dtor(cl); ! 11661: curr_expr = s2; ! 11662: del_list = s5; ! 11663: break_del_list = s6; ! 11664: continue_del_list = s7; ! 11665: curr_fct = s8; ! 11666: init_list = s9; ! 11667: } ! 11668: ! 11669: ! 11670: void expand_ictor(Pclass cl) ! 11671: { ! 11672: //error('d',"expand_itor(%t)",cl); ! 11673: Pexpr s2 = curr_expr; ! 11674: Pstmt s5 = del_list; ! 11675: Pstmt s6 = break_del_list; ! 11676: Pstmt s7 = continue_del_list; ! 11677: Pname s8 = curr_fct; ! 11678: Pexpr s9 = init_list; ! 11679: (void) make_default_ctor(cl); ! 11680: curr_expr = s2; ! 11681: del_list = s5; ! 11682: break_del_list = s6; ! 11683: continue_del_list = s7; ! 11684: curr_fct = s8; ! 11685: init_list = s9; ! 11686: } ! 11687: */ ! 11688: Pexpr fct::expand(Pname fn, Ptable scope, Pexpr ll) ! 11689: /* ! 11690: expand call to (previously defined) inline function in "scope" ! 11691: with the argument list "ll" ! 11692: (1) declare variables in "scope" ! 11693: (2) initialize argument variables ! 11694: (3) link to body ! 11695: */ ! 11696: { ! 11697: Scope = scope; ! 11698: //error('d',"expand%s() body %d f_expr %d inline %d",fn->string,body,f_expr,f_inline); ! 11699: if (f_inline == ITOR) { ! 11700: Pexpr s1 = last_expanded; ! 11701: expand_itor(memof); ! 11702: last_expanded = s1; ! 11703: last_stmt = stmtno; ! 11704: this = Pfct(fn->tp); ! 11705: if (f_inline==0 && f_imeasure) { ! 11706: uninline(fn); ! 11707: return 0; ! 11708: } ! 11709: } ! 11710: ! 11711: //error('d',"expand %n body %d f_expr %d defined %d",fn,body,f_expr,defined); ! 11712: //error('d',"inline %d memtbl %d scope %d",f_inline,Pfct(fn->tp)->body->memtbl,scope); ! 11713: //display_stmt(body); ! 11714: if ((body==0 && f_expr==0) // before defined ! 11715: || ((defined&SIMPLIFIED)==0) // before simplified ! 11716: || (Pfct(fn->tp)->body->memtbl==scope) // while defining ! 11717: || (f_inline>1) // recursive call ! 11718: ) { // so don't expand ! 11719: if (warning_opt) error('w',"cannot inline%n in thisE",fn); ! 11720: if (fn->n_addr_taken++==0) fn->dcl_print(0); ! 11721: return 0; ! 11722: } ! 11723: ! 11724: if (fn->n_oper==CTOR) { ! 11725: Pclass cl = Pclass(fn->n_table->t_name->tp); ! 11726: if (cl->c_body == 3) cl->print_all_vtbls(cl); ! 11727: } ! 11728: ! 11729: Pin il = new iline; ! 11730: Pexpr ic = new texpr(ICALL,0,0); ! 11731: int ns = 0; ! 11732: for (Pname an = f_args; an; an=an->n_list) ns++; ! 11733: il->fct_name = fn; ! 11734: il->i_args = new ia[il->i_slots = ns]; ! 11735: ic->il = il; ! 11736: ic->tp = s_returns ? s_returns : returns; ! 11737: // Pname at = (f_this) ? f_this : (f_result) ? f_result : argtype; ! 11738: Pname at = f_args; ! 11739: ! 11740: f_inline++; ! 11741: ! 11742: if (at) il->i_table = at->n_table; ! 11743: int i = 0; ! 11744: int not_simple = 0; /* is a temporary argument needed? */ ! 11745: ! 11746: for (Pname n=at; n; n=n->n_list, i++) { ! 11747: /* check formal/actual argument pairs ! 11748: and generate temporaries as necessary ! 11749: */ ! 11750: ! 11751: if (ll == 0) error('i',"F::expand(%n):AX",fn); ! 11752: Pexpr ee; ! 11753: ! 11754: if (ll->base == ELIST) { ! 11755: ee = ll->e1; ! 11756: ll = ll->e2; ! 11757: } ! 11758: else { ! 11759: ee = ll; ! 11760: ll = 0; ! 11761: } ! 11762: ! 11763: /* could be avoided when expanding into a block */ ! 11764: il->i_args[i].local = 0; ! 11765: int s ; ! 11766: ! 11767: // try to protect agains aliasing through pointers and references ! 11768: for (Pname m=at; m; m=m->n_list) { ! 11769: Pptr p; ! 11770: if (n!=m) { ! 11771: // if ((p=m->tp->is_ptr()) || (p=m->tp->is_ref())) ! 11772: if (p=m->tp->is_ptr_or_ref()) ! 11773: if (p->check(n->tp,0)==0 || p->typ->check(n->tp,0)==0) goto zxc; ! 11774: ! 11775: } ! 11776: } ! 11777: ! 11778: ::watch_out = 0; ! 11779: int notsimple; notsimple = ee->not_simple(); ! 11780: if ( notsimple==0 && ::watch_out && n->n_used > 1 ) goto zxc; ! 11781: if (n->n_assigned_to==FUDGE111 ! 11782: && ee!=zero ! 11783: && notsimple==0) { ! 11784: if (ee && ee->e1 && (ee->e1->base == NAME) && ! 11785: (! strcmp (ee->e1->string,"this"))) goto zxc; ! 11786: } ! 11787: else if (n->n_addr_taken || n->n_assigned_to) ! 11788: goto zxc; ! 11789: else if (s=notsimple) { ! 11790: if (/*n->n_used==0 // n_used not set for ``this'' ! 11791: || */1<s ! 11792: || 1<n->n_used ) { // not safe ! 11793: zxc: ! 11794: if (last_expanded && last_expanded==curr_expr && last_stmt==stmtno) { ! 11795: if (warning_opt) ! 11796: error('w',"%n not inlined, called twice in an expression",fn); ! 11797: f_inline--; ! 11798: delete il->i_args; ! 11799: delete il; ! 11800: if (fn->n_addr_taken++==0) fn->dcl_print(0); ! 11801: return 0; ! 11802: } ! 11803: //error('d',"zxc %n %t ee %d %t",n,n->tp,ee->base,ee->tp); ! 11804: if (ee && ee->tp && (ee->tp->base==EOBJ) && ansi_opt) ! 11805: ; // do nothing ! 11806: else { ! 11807: Pname nn = dcl_local(scope,n,fn); ! 11808: nn->base = NAME; ! 11809: il->i_args[i].local = nn; ! 11810: ++not_simple; ! 11811: // if (nn->tp->is_ref() ! 11812: // && ee->tp ! 11813: // && ee->tp->is_ptr_or_ref()==0) ee = ee->address(); ! 11814: } ! 11815: } ! 11816: } ! 11817: ! 11818: il->i_args[i].arg = ee; ! 11819: il->i_args[i].tp = n->tp; ! 11820: } ! 11821: ! 11822: Ptable tbl = body->memtbl; ! 11823: if (f_expr) { // generate comma expression ! 11824: ! 11825: char loc_var = 0; ! 11826: ! 11827: /* look for local variables needing declaration: */ ! 11828: for (n=tbl->get_mem(i=1); n; n=tbl->get_mem(++i) ) { ! 11829: //error('d',"n %n %d",n,n->base); ! 11830: //error('d',"loc %n %d %d %d",n,n->n_used,n->n_assigned_to,n->n_addr_taken); ! 11831: if (n->base==NAME // don't re-declare the args ! 11832: && (n->tp->base!=FCT && n->tp->base!=OVERLOAD) ! 11833: && (n->n_used || n->n_assigned_to || n->n_addr_taken)) { ! 11834: if (last_expanded && last_expanded==curr_expr && last_stmt == stmtno) { ! 11835: if (warning_opt) error('w',"cannot inline%n in thisE",fn); ! 11836: f_inline--; ! 11837: delete il->i_args; ! 11838: delete il; ! 11839: if (fn->n_addr_taken++==0) fn->dcl_print(0); ! 11840: return 0; ! 11841: } ! 11842: Pname nn = dcl_local(scope,n,fn); ! 11843: nn->base = NAME; ! 11844: n->string = nn->string; ! 11845: ! 11846: loc_var++; ! 11847: } ! 11848: } ! 11849: ! 11850: if (i /*not_simple*/ || loc_var) { ! 11851: if(!curr_expr) curr_expr = dummy; ! 11852: last_expanded = curr_expr; ! 11853: last_stmt = stmtno; ! 11854: } ! 11855: ! 11856: Pexpr ex; ! 11857: if (not_simple) { ! 11858: Pexpr etail = ex = new expr(CM,0,0); ! 11859: for (i=0; i<il->i_slots; i++) { ! 11860: Pname n = il->i_args[i].local; ! 11861: if (n == 0) continue; ! 11862: Pexpr e = il->i_args[i].arg; ! 11863: // if used assign ! 11864: // otherwise (e.g. unused argument) ! 11865: // simply evaluate for sideeffects ! 11866: if (n->n_used ! 11867: || n->n_assigned_to ! 11868: || n->n_addr_taken) { ! 11869: Pexpr mptr_assign(Pexpr n, Pexpr in); ! 11870: Pptr p1 = n->tp->is_ptr(); ! 11871: Pptr p2 = e->tp ? e->tp->is_ptr() : 0; ! 11872: if (p1 && p1->memof && p1!=p2) { ! 11873: switch (e->base) { ! 11874: case CM: ! 11875: case G_CM: ! 11876: e->e2 = mptr_assign(n,e->e2); ! 11877: break; ! 11878: case ICALL: ! 11879: break; ! 11880: default: ! 11881: e = mptr_assign(n,e); ! 11882: } ! 11883: etail->e1 = e; ! 11884: } ! 11885: else ! 11886: etail->e1 = new expr(ASSIGN,n,e); ! 11887: } ! 11888: else ! 11889: etail->e1 = e; ! 11890: if (--not_simple) ! 11891: etail = etail->e2 = new expr(CM,0,0); ! 11892: else ! 11893: break; ! 11894: } ! 11895: etail->e2 = f_expr; ! 11896: } ! 11897: else ! 11898: ex = f_expr; ! 11899: ic->e1 = ex; ! 11900: } ! 11901: else { // generate block: ! 11902: for (n=tbl->get_mem(i=1); n; n=tbl->get_mem(++i) ) { ! 11903: // mangle local names ! 11904: if (n->base==NAME ! 11905: && (n->n_used || n->n_assigned_to || n->n_addr_taken)) { ! 11906: // Pname cn = fn->n_table->t_name; ! 11907: // n->string = temp(n->string,fn->string,(cn)?cn->string:0); ! 11908: n->string = temp(n->string,fn); ! 11909: } ! 11910: } ! 11911: Pstmt ss; ! 11912: if (not_simple) { ! 11913: if(!curr_expr) curr_expr = dummy; ! 11914: last_expanded = curr_expr; ! 11915: last_stmt = stmtno; ! 11916: Pstmt st = new estmt(SM,curloc,0,0); ! 11917: st->where.line = 0; ! 11918: Pstmt stail = st; ! 11919: for (i=0; i<il->i_slots; i++) { ! 11920: Pname n = il->i_args[i].local; ! 11921: if (n == 0) continue; ! 11922: Pexpr e = il->i_args[i].arg; ! 11923: Pptr p1 = n->tp->is_ptr(); ! 11924: Pptr p2 = e->tp->is_ptr(); ! 11925: Pexpr mptr_assign(Pexpr n, Pexpr in); ! 11926: if (p1 && p1->memof && p1!=p2) { ! 11927: switch (e->base) { ! 11928: case CM: ! 11929: case G_CM: ! 11930: e->e2 = mptr_assign(n,e->e2); ! 11931: break; ! 11932: default: ! 11933: e = mptr_assign(n,e); ! 11934: } ! 11935: stail->e = e; ! 11936: } ! 11937: else ! 11938: stail->e = new expr(ASSIGN,n,e); ! 11939: if (--not_simple) { ! 11940: stail = stail->s_list = new estmt(SM,curloc,0,0); ! 11941: stail->where.line = 0; ! 11942: } ! 11943: else ! 11944: break; ! 11945: } ! 11946: stail->s_list = body; ! 11947: ss = new block(curloc,0,st); ! 11948: ss->where.line = 0; ! 11949: } ! 11950: else ! 11951: ss = body; ! 11952: ic->e2 = Pexpr(ss); ! 11953: } ! 11954: ! 11955: f_inline--; ! 11956: //error('d',"expand%n -- returning%k", fn, ic?ic->base:0); ! 11957: //display_expr(ic); ! 11958: return ic; ! 11959: } ! 11960: 0707071010112044261004440001630000160000010177000466055400600000700000116316expr.c /*ident "@(#)ctrans:src/expr.c 1.8" */ ! 11961: /*************************************************************************** ! 11962: ! 11963: C++ source for cfront, the C++ compiler front-end ! 11964: written in the computer science research center of Bell Labs ! 11965: ! 11966: Copyright (c) 1984 AT&T, Inc. All rights Reserved ! 11967: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 11968: ! 11969: expr.c: ! 11970: ! 11971: type check expressions ! 11972: ! 11973: ************************************************************************/ ! 11974: ! 11975: #include "cfront.h" ! 11976: #include "size.h" ! 11977: ! 11978: int const_save; ! 11979: int const_ptr; ! 11980: extern Ptype Pfct_type; ! 11981: ! 11982: Pexpr expr::address() ! 11983: { ! 11984: // error('d',"address %k %d %s",base,base,base==NAME||base==ANAME?string:"?"); ! 11985: // error('d',"address e1 %d %k e2 %d %k", e1, e1?e1->base:0, e2, e2?e2->base:0); ! 11986: switch (base) { ! 11987: case DEREF: ! 11988: if (e2 == 0) return e1; // &*e => e ! 11989: break; ! 11990: case QUEST: // &(a?b:c) => a?&b:&c ! 11991: e1 = e1->address(); ! 11992: // no break; ! 11993: case G_CM: ! 11994: if ( e1 && e1->base == G_CALL && ! 11995: e2 && e2->base == G_ADDROF) ! 11996: return this; ! 11997: case CM: ! 11998: e2 = e2->address(); // &(e1,e2) => (e1,&e2) ! 11999: tp = e2->tp; //LLL ! 12000: return this; ! 12001: case INCR: ! 12002: case DECR: // &(++a) => (++a,&a) ! 12003: if (e1) break; ! 12004: nin++; ! 12005: if (e2->not_simple()) error('s',"& of%k",base); ! 12006: nin--; ! 12007: e1 = new expr(base,0,e2); ! 12008: e2 = e2->address(); ! 12009: base = G_CM; ! 12010: tp = e2->tp; ! 12011: return this; ! 12012: case ASSIGN: // &(a=b) => ((a=b),&a) ! 12013: case ASPLUS: ! 12014: case ASMINUS: ! 12015: case ASMUL: ! 12016: case ASDIV: ! 12017: case ASMOD: ! 12018: case ASAND: ! 12019: case ASOR: ! 12020: case ASER: ! 12021: case ASLS: ! 12022: case ASRS: ! 12023: nin++; ! 12024: if (e1->not_simple()) error('s',"& of%k",base); ! 12025: nin--; ! 12026: Pexpr a = new expr(base,e1,e2); ! 12027: a->tp = a->e1->tp; ! 12028: base = G_CM; ! 12029: e1 = a; ! 12030: e2 = a->e1->address(); ! 12031: tp = e2->tp; ! 12032: return this; ! 12033: ! 12034: case NAME: ! 12035: if (Pname(this)->n_stclass == REGISTER) error("& register%n",Pname(this)); ! 12036: Pname(this)->take_addr(); ! 12037: break; ! 12038: case CALL: ! 12039: case CAST: ! 12040: case NEW: ! 12041: case GNEW: ! 12042: if (tp && tp->is_ptr_or_ref()) { // hack? ! 12043: return this; ! 12044: } ! 12045: break; ! 12046: } ! 12047: ! 12048: register Pexpr ee = new expr(G_ADDROF,0,this); ! 12049: if (tp) { // tp==0 ??? ! 12050: ee->tp = tp->addrof(); ! 12051: ! 12052: switch (tp->base) { ! 12053: case PTR: ! 12054: Pptr(ee->tp)->memof = Pptr(tp)->memof; ! 12055: break; ! 12056: case FCT: ! 12057: if (Pfct(tp)->f_static==0) ! 12058: Pptr(ee->tp)->memof = Pfct(tp)->memof; ! 12059: break; ! 12060: case OVERLOAD: ! 12061: if (Pfct(Pgen(tp)->fct_list->f->tp)->f_static==0) ! 12062: Pptr(ee->tp)->memof = Pfct(Pgen(tp)->fct_list->f->tp)->memof; ! 12063: } ! 12064: } ! 12065: ! 12066: return ee; ! 12067: } ! 12068: ! 12069: Pexpr expr::contents() ! 12070: { ! 12071: //error('d',"deref %k %d %t",base,base,tp); ! 12072: // if (base==ADDROF || base==G_ADDROF) return e2; // *& ! 12073: switch (base) { ! 12074: case ADDROF: ! 12075: case G_ADDROF: ! 12076: return e2; // *& ! 12077: case ELIST: ! 12078: //error('d',"contents of elist"); ! 12079: e1 = e1->contents(); ! 12080: tp = e1->tp; ! 12081: return this; ! 12082: }; ! 12083: ! 12084: register Pexpr ee = new expr(DEREF,this,0); ! 12085: if (tp) { // tp==0 ??? ! 12086: Ptype tt = tp; ! 12087: while (tt->base == TYPE) tt = Pbase(tt)->b_name->tp; ! 12088: ee->tp = Pptr(tt)->typ; ! 12089: Pname cn = ee->tp->is_cl_obj(); ! 12090: if (cn) { ! 12091: Pclass cl = Pclass(cn->tp); ! 12092: if (cl->c_body==1) cl->dcl_print(0); // look for first use of cl ! 12093: } ! 12094: } ! 12095: return ee; ! 12096: } ! 12097: ! 12098: static Pexpr ! 12099: make_postfix( Pexpr op ) ! 12100: { // apply the postfix form of increment/decrement operator ! 12101: Pexpr e = op->e1->base==NAME?op->e1:op->e1->mem; ! 12102: for (Plist fl=Pgen(e->tp)->fct_list;fl; fl=fl->l) { ! 12103: Pname n = fl->f; ! 12104: Pfct f = Pfct(n->tp); ! 12105: if ((f->nargs==1 && f->f_this) || ! 12106: (f->nargs==2 && f->f_this==0)) { ! 12107: ! 12108: if (op->e1->base == NAME) { ! 12109: op->e1 = n; ! 12110: op->e2->e2 = new expr(ELIST,zero,0); ! 12111: } else { ! 12112: op->e1->mem = n; ! 12113: op->e2 = new expr(ELIST,zero,0); ! 12114: } ! 12115: ! 12116: op->fct_name = n; ! 12117: n->dcl_print(0); ! 12118: return op; ! 12119: } ! 12120: } ! 12121: error('w',"no postfix instance of%n, although overloaded",Pname(e)); ! 12122: return op; // as it were ! 12123: } ! 12124: ! 12125: int bound; ! 12126: int chars_in_largest; // no of characters in largest int ! 12127: static Pclass mpglob; ! 12128: ! 12129: Pexpr expr::typ(Ptable tbl) ! 12130: /* ! 12131: find the type of "this" and place it in tp; ! 12132: return the typechecked version of the expression: ! 12133: "tbl" provides the scope for the names in "this" ! 12134: */ ! 12135: { ! 12136: //if (this == 0) error('i',"0->expr::typ"); ! 12137: Pname n; ! 12138: Ptype t = 0; ! 12139: Ptype t1, t2; ! 12140: TOK b = base; ! 12141: TOK r1, r2; ! 12142: #define nppromote(b) t=np_promote(b,r1,r2,t1,t2,1) ! 12143: #define npcheck(b) (void)np_promote(b,r1,r2,t1,t2,0) ! 12144: if (tbl->base != TABLE) error('i',"expr::typ(%d)",tbl->base); ! 12145: ! 12146: DB( if(Tdebug>=1) { ! 12147: error('d',"%d->expr::typ(%d) %k %t",this,tbl,b,tp); ! 12148: display_expr(this); ! 12149: }); ! 12150: // error('d',"%k->typ %n tp: %t", b,b==NAME?this:0,tp); ! 12151: // error('d'," e1 %d %k e1 %d %k",e1,e1?e1->base:0,e2,e2?e2->base:0); ! 12152: ! 12153: if (tp) { ! 12154: switch (b) { ! 12155: case NAME: ! 12156: //?? Pname(this)->use(); ! 12157: break; ! 12158: case MDOT: ! 12159: mem = mem->typ(tbl); ! 12160: } ; ! 12161: // if (b == NAME) Pname(this)->use(); ! 12162: return this; ! 12163: } ! 12164: ! 12165: extern Pname Ntmp; ! 12166: ! 12167: switch (b) { // is it a basic type ! 12168: case MDOT: ! 12169: error('i',"mdot %s",string2); ! 12170: case DUMMY: ! 12171: error("emptyE"); ! 12172: tp = any_type; ! 12173: return this; ! 12174: ! 12175: case ZERO: ! 12176: tp = zero_type; ! 12177: return this; ! 12178: ! 12179: case IVAL: ! 12180: tp = int_type; ! 12181: return this; ! 12182: ! 12183: //case FVAL: ! 12184: // tp = float_type; ! 12185: // return this; ! 12186: ! 12187: case ICON: ! 12188: /* is it long? ! 12189: explicit long? ! 12190: decimal larger than largest signed int ! 12191: octal or hexadecimal larger than largest unsigned int ! 12192: */ ! 12193: { int ll = strlen(string); ! 12194: switch (string[ll-1]) { ! 12195: case 'l': ! 12196: case 'L': ! 12197: switch (string[ll-2]) { ! 12198: case 'u': ! 12199: case 'U': ! 12200: string[ll-2] = 0; ! 12201: tp = ulong_type; ! 12202: goto cast_n_save; ! 12203: } ! 12204: lng: ! 12205: tp = long_type; ! 12206: goto save; ! 12207: case 'u': ! 12208: case 'U': // 1u => unsigned(1) ! 12209: switch (string[ll-2]) { ! 12210: case 'l': ! 12211: case 'L': ! 12212: string[ll-2] = 0; ! 12213: ulng: ! 12214: tp = ulong_type; ! 12215: goto cast_n_save; ! 12216: default: ! 12217: string[ll-1] = 0; ! 12218: uint: ! 12219: tp = uint_type; ! 12220: goto cast_n_save; ! 12221: } ! 12222: } ! 12223: ! 12224: // no suffix - see if we can figure it out ! 12225: if (string[0] == '0') { // assume 8 bits in byte ! 12226: register index = 1; ! 12227: switch (string[1]) { ! 12228: case 'x': ! 12229: case 'X': ! 12230: while(string[++index]=='0') ; ! 12231: ll -= index; ! 12232: int HSZ = SZ_INT+SZ_INT; ! 12233: if(ll < HSZ) goto nrm; ! 12234: if(ll == HSZ) ! 12235: if(string[2]>='8') goto uint; ! 12236: else goto nrm; ! 12237: if(SZ_INT==SZ_LONG) break; ! 12238: HSZ = SZ_LONG+SZ_LONG; ! 12239: if(ll < HSZ) goto lng; ! 12240: if(ll == HSZ) ! 12241: if(string[2]>='8') goto ulng; ! 12242: else goto lng; ! 12243: break; ! 12244: default: // OCTAL ! 12245: register IBITS = BI_IN_BYTE*SZ_INT; ! 12246: while(string[index]=='0') index++; ! 12247: register char x = string[index]; ! 12248: int lbt = x=='1' ? 1 : ! 12249: ( x=='2' || x=='3' ? 2 : 3 ); ! 12250: int nbits = (ll-index-1)*3 + lbt; ! 12251: if(nbits < IBITS) goto nrm; ! 12252: if(nbits == IBITS) goto uint; ! 12253: if(nbits < BI_IN_BYTE*SZ_LONG) goto lng; ! 12254: } ! 12255: goto ulng; ! 12256: } ! 12257: else { // DECIMAL ! 12258: if (ll<chars_in_largest) { ! 12259: nrm: ! 12260: tp = int_type; ! 12261: goto save; ! 12262: } ! 12263: if (ll>chars_in_largest) { ! 12264: if(SZ_INT==SZ_LONG || ll>2*chars_in_largest) ! 12265: goto ulng; ! 12266: goto lng; ! 12267: } ! 12268: // ll == chars_in_largest ! 12269: char* p = string; ! 12270: char* q = LARGEST_INT; ! 12271: do if (*p>*q) { ! 12272: if(SZ_INT==SZ_LONG) goto ulng; ! 12273: goto lng; ! 12274: } while (*p++==*q++ && *p); ! 12275: } ! 12276: ! 12277: goto nrm; ! 12278: } ! 12279: case CCON: ! 12280: tp = c_strlen(string)<5 ? char_type : int_type; // stored as 'a' ! 12281: goto save; ! 12282: ! 12283: case FCON: ! 12284: { int ll = strlen(string); ! 12285: int last = string[ll-1]; ! 12286: tp = double_type; ! 12287: if (last=='F' || last=='f') { ! 12288: tp = float_type; ! 12289: if (!ansi_opt) { ! 12290: string[ll-1] = 0; ! 12291: goto cast_n_save; ! 12292: } ! 12293: } ! 12294: else if (last=='L' || last=='l') { ! 12295: if (ansi_opt == 0) string[ll-1] = 0; ! 12296: tp = ldouble_type; ! 12297: } ! 12298: goto save; ! 12299: } ! 12300: case STRING: // type of "as\tdf" is char[6] ! 12301: // c_strlen counts the terminating '\0' ! 12302: { Pvec v = new vec(char_type,0); ! 12303: v->size = c_strlen(string); ! 12304: tp = v; ! 12305: } ! 12306: save: ! 12307: if (const_save) { // "as\tdf" needs 7 chars for storage ! 12308: char* p = new char[strlen(string)+1]; ! 12309: strcpy(p,string); ! 12310: string = p; ! 12311: } ! 12312: ! 12313: return this; ! 12314: ! 12315: cast_n_save: ! 12316: if (const_save) { // "as\tdf" needs 7 chars for storage ! 12317: char* p = new char[strlen(string)+1]; ! 12318: strcpy(p,string); ! 12319: string = p; ! 12320: } ! 12321: ! 12322: return new cast(tp,this); ! 12323: ! 12324: case THIS: ! 12325: delete this; ! 12326: if (cc->c_this) { ! 12327: cc->c_this->use(); ! 12328: return cc->c_this; ! 12329: } ! 12330: error("``this'' used in nonC context"); ! 12331: n = new name("this"); ! 12332: n->tp = any_type; ! 12333: return tbl->insert(n,0); ! 12334: ! 12335: case NAME: ! 12336: { ! 12337: Pname q = Pname(this)->n_qualifier; // suppress virtual iff x:: ! 12338: Pexpr ee = find_name(Pname(this),cc->cot,tbl,0,cc->nof); ! 12339: if (q && (ee->base==REF || ee->base==DOT)) ! 12340: ee->n_initializer = Pexpr(q); ! 12341: //error('d',"ee %k %t %n",ee->base,ee->tp,ee->base==NAME?ee:ee->base==REF?ee->mem:0); ! 12342: // if (ee->tp->base == RPTR) return ee->contents(); ! 12343: if (ee->tp->is_ref()) return ee->contents(); ! 12344: ! 12345: if (ee->base==NAME && Pname(ee)->n_xref) { ! 12346: // fudge to handle X(X&) args ! 12347: ee = new expr(DEREF,ee,0); ! 12348: ee->tp = ee->e1->tp; // !! ! 12349: } ! 12350: ! 12351: return ee; ! 12352: } ! 12353: ! 12354: case ADDROF: ! 12355: case G_ADDROF: // handle lookup for &s::i ! 12356: mpglob = 0; ! 12357: if (e2->base == NAME) e2 = find_name(Pname(e2),cc->cot,tbl,ADDROF,cc->nof); ! 12358: if (e2->base==NAME && Pname(e2)->n_xref) { ! 12359: // fudge to handle X(X&) args ! 12360: e2 = new expr(DEREF,e2,0); ! 12361: e2->tp = e2->e1->tp; // !! ! 12362: } ! 12363: if (e2->base==DOT) { // &f().x = > &(tmp=f(),&tmp)->x ! 12364: switch (e2->e1->base) { ! 12365: case CALL: ! 12366: case G_CALL: ! 12367: case VALUE: ! 12368: error("& non-lvalue"); ! 12369: } ! 12370: } ! 12371: break; ! 12372: ! 12373: case SIZEOF: ! 12374: if (tp2) { ! 12375: tp2->dcl(tbl); ! 12376: switch (tp2->base) { ! 12377: case VOID: ! 12378: error("sizeof(void)"); ! 12379: break; ! 12380: case CLASS: ! 12381: { ! 12382: Pclass cl = Pclass(tp2); ! 12383: if (cl->c_body==1 ! 12384: && (cl->defined&(DEFINED|SIMPLIFIED)) == 0) ! 12385: error('s',"class defined within sizeof"); ! 12386: } ! 12387: } ! 12388: ! 12389: if (e1 && e1!=dummy) { ! 12390: e1 = e1->typ(tbl); ! 12391: DEL(e1); ! 12392: e1 = dummy; ! 12393: } ! 12394: Pptr r = tp2->is_ref(); ! 12395: if (r) tp2 = r->typ; // sizeof(T&)==sizeof(T) ! 12396: } ! 12397: else if (e1 == dummy) { ! 12398: error("sizeof emptyE"); ! 12399: tp = any_type; ! 12400: return this; ! 12401: } ! 12402: else { ! 12403: e1 = e1->typ(tbl); ! 12404: tp2 = e1->tp; ! 12405: if(tp2->base == VEC) tp2->permanent = 1; ! 12406: if (e1->base==ILIST) // PtoM ! 12407: e1 = dummy; ! 12408: else if (tp2 == char_type) // sizeof ('a') ! 12409: e1 = dummy; ! 12410: } ! 12411: (void) tp2->tsizeof(); ! 12412: tp = size_t_type; ! 12413: return this; ! 12414: ! 12415: case CAST: ! 12416: // return docast(tbl); ! 12417: ! 12418: { Pexpr ee = docast(tbl); ! 12419: return ee->tp->is_ref() ? ee->contents() : ee; ! 12420: } ! 12421: ! 12422: ! 12423: case VALUE: ! 12424: if ( tp2->base == COBJ || tp2->base == EOBJ) { ! 12425: char *s = Pbase(tp2)->b_name->string; ! 12426: //Pname tn = gtbl->look( s, 0 ); ! 12427: //??? non type name apparently takes precedence ! 12428: // Don't use global ftn if it hides local ! 12429: // class ctor. (Note: More info is needed ! 12430: // to detect all cases.) ! 12431: Pname tn = tbl->look( s, 0 ); ! 12432: //error( 'd', "tn: %n %t lex_levels: %d %d", tn, tn?tn->tp:0, tn?tn->lex_level:0, Pbase(tp2)->b_name->lex_level ); ! 12433: if ( tn && tn->n_qualifier == 0 ! 12434: && tn->lex_level == Pbase(tp2)->b_name->lex_level ! 12435: && (tn->tp->base==FCT || tn->tp->base==OVERLOAD)) ! 12436: { ! 12437: Pexpr et = new expr( CALL, tn, e1 ); ! 12438: *this = *et; ! 12439: b = CALL; ! 12440: break; ! 12441: } ! 12442: } ! 12443: return dovalue(tbl); ! 12444: ! 12445: case NEW: ! 12446: case GNEW: ! 12447: return donew(tbl); ! 12448: ! 12449: case DELETE: // delete e1 OR delete[e2] e1 ! 12450: case GDELETE: ! 12451: { int i; ! 12452: if (e1->base == ADDROF) error('w',"delete &E"); ! 12453: e1 = e1->typ(tbl); ! 12454: i = e1->tp->num_ptr(DELETE); ! 12455: if (i != 'P') error("nonP deleted"); ! 12456: if (e2) { ! 12457: e2 = e2->typ(tbl); ! 12458: e2->tp->integral(DELETE); ! 12459: } ! 12460: tp = void_type; ! 12461: return this; ! 12462: } ! 12463: ! 12464: case ILIST: /* an ILIST is pointer to an ELIST */ ! 12465: e1 = e1->typ(tbl); ! 12466: tp = any_type; ! 12467: return this; ! 12468: ! 12469: case ELIST: ! 12470: { Pexpr e; ! 12471: Pexpr ex; ! 12472: ! 12473: if (e1 == dummy && e2==0) { ! 12474: error("emptyIrL"); ! 12475: tp = any_type; ! 12476: return this; ! 12477: } ! 12478: ! 12479: for (e=this; e; e=ex) { ! 12480: Pexpr ee = e->e1; ! 12481: //error('d',"e %d %d ee %d %d",e,e?e->base:0,ee,ee?ee->base:0); ! 12482: if (e->base != ELIST) error('i',"elist%k",e->base); ! 12483: if (ex = e->e2) { /* look ahead for end of list */ ! 12484: if (ee == dummy) error("EX in EL"); ! 12485: if (ex->e1 == dummy && ex->e2 == 0) { ! 12486: /* { ... , } */ ! 12487: DEL(ex); ! 12488: e->e2 = ex = 0; ! 12489: } ! 12490: } ! 12491: e->e1 = ee->typ(tbl); ! 12492: t = e->e1->tp; ! 12493: if (t->base == FCT) { // yuk! ! 12494: ee = new expr(G_ADDROF,0,e->e1); ! 12495: e->e1 = ee->typ(tbl); ! 12496: t = e->e1->tp; ! 12497: } ! 12498: } ! 12499: tp = t; ! 12500: return this; ! 12501: } ! 12502: ! 12503: case DOT: ! 12504: case REF: ! 12505: { if (e2) { // *. or ->* ! 12506: if (b == REF) b = base = REFMUL; ! 12507: break; ! 12508: } ! 12509: ! 12510: Pbase b; ! 12511: ! 12512: e1 = e1->typ(tbl); ! 12513: t = e1->tp; ! 12514: ! 12515: // check that . (->) is applied to class object (pointer) ! 12516: if (base == REF) { ! 12517: xxx: ! 12518: switch (t->base) { ! 12519: case TYPE: ! 12520: t = Pbase(t)->b_name->tp; ! 12521: goto xxx; ! 12522: case COBJ: ! 12523: { Pname n = Pclass(Pbase(t)->b_name->tp)->has_oper(REF); ! 12524: if (n) { ! 12525: n->n_used += 2; ! 12526: e1 = new call(new ref(DOT,e1,n),0); ! 12527: return typ(tbl); ! 12528: } ! 12529: // no break; ! 12530: } ! 12531: default: ! 12532: error("nonP ->%n",mem); ! 12533: t = any_type; ! 12534: // no break; ! 12535: case ANY: ! 12536: goto qqq; ! 12537: case PTR: ! 12538: case VEC: ! 12539: b = Pbase(Pptr(t)->typ); ! 12540: } ! 12541: } ! 12542: else { // base == DOT ! 12543: qqq: ! 12544: switch (t->base) { ! 12545: case TYPE: t = Pbase(t)->b_name->tp; goto qqq; ! 12546: default: error("nonO .%n",mem); t = any_type; ! 12547: case ANY: ! 12548: case COBJ: break; ! 12549: } ! 12550: //error('d',"dot %k",e1->base); ! 12551: switch (e1->base) { ! 12552: case QUEST: ! 12553: case ASSIGN: ! 12554: case INCR: ! 12555: case DECR: ! 12556: case ASPLUS: ! 12557: case ASMINUS: ! 12558: case ASMUL: ! 12559: case ASDIV: ! 12560: case ASMOD: ! 12561: case ASAND: ! 12562: case ASOR: ! 12563: case ASER: ! 12564: case ASLS: ! 12565: case ASRS: ! 12566: case CM: ! 12567: case G_CM: ! 12568: base = REF; ! 12569: e1 = e1->address(); ! 12570: break; ! 12571: case CALL: ! 12572: case G_CALL: ! 12573: //error('d'," f(). %n mem->tp %t",e1->fct_name,mem->tp); ! 12574: #ifdef FDOTRIGHT ! 12575: // this rewrite is only necessary on machines with broken C compilers ! 12576: // there seems to be a lot of those ! 12577: // and for inlines (a,b).c ! 12578: if (e1->fct_name && Pfct(e1->fct_name->tp)->f_inline) ! 12579: #endif ! 12580: { // f(). => (tmp=f(),&tmp)-> ! 12581: Pname tmp = make_tmp('Q',e1->tp,tbl); ! 12582: //error('d',"fdot2 %k",e1->base); ! 12583: e1 = init_tmp(tmp,e1,tbl); ! 12584: Pexpr aa = tmp->address(); ! 12585: e1 = new expr(G_CM,e1,aa); ! 12586: e1->tp = aa->tp; ! 12587: base = REF; ! 12588: break; ! 12589: } ! 12590: } ! 12591: b = Pbase(t); ! 12592: } ! 12593: ! 12594: xxxx: ! 12595: switch (b->base) { ! 12596: case TYPE: ! 12597: b = Pbase(b->b_name->tp); ! 12598: goto xxxx; ! 12599: default: ! 12600: error("(%t) before %k%n (%n not aM)",e1->tp,base,mem,mem); ! 12601: case ANY: ! 12602: tp = any_type; ! 12603: return this; ! 12604: case COBJ: ! 12605: { Pclass cl = Pclass(Pbase(b)->b_name->tp); ! 12606: if (cl->c_body == 1) cl->dcl_print(0); ! 12607: break; ! 12608: } ! 12609: } ! 12610: ! 12611: /* ! 12612: x.m is not a const even if x is a const object, this case is handled ! 12613: by lval() rejecting it ! 12614: */ ! 12615: ! 12616: if (mem->tp) { ! 12617: tp = mem->tp; ! 12618: for (Pexpr ee = mem; ee->base==REF; ee = ee->e1) { ! 12619: if (ee->e1 == cc->c_this) { // this-> => p-> ! 12620: ee->e1 = e1; ! 12621: ee->base = base; ! 12622: return mem->tp->is_ref() ? mem->contents() : mem; ! 12623: } ! 12624: } ! 12625: ! 12626: // return tp->base==RPTR ? contents() : this; ! 12627: return tp->is_ref() ? contents() : this; ! 12628: } ! 12629: ! 12630: ! 12631: Pname q = Pname(mem)->n_qualifier; ! 12632: Pexpr e = find_name(Pname(mem),Pclass(b->b_name->tp),0,base,cc->nof); ! 12633: if (q && (e->base==REF || e->base==DOT)) ! 12634: Pname(e)->n_initializer = Pexpr(q); ! 12635: //error('d',"e %k %t %n",e->base,e->tp,e->base==NAME?e:e->base==REF?e->mem:0); ! 12636: ! 12637: for (Pexpr ee = e; ee->base==REF; ee = ee->e1) { ! 12638: if (ee->e1 == cc->c_this) { // this-> => p-> ! 12639: ee->e1 = e1; ! 12640: ee->base = base; ! 12641: break; ! 12642: } ! 12643: } ! 12644: ! 12645: if (e->base == NAME) { ! 12646: switch (e->tp->base) { ! 12647: case FCT: ! 12648: case OVERLOAD: ! 12649: mem = e; ! 12650: tp = e->tp; ! 12651: e = this; ! 12652: } ! 12653: } ! 12654: ! 12655: // function or static member ! 12656: return e->tp->is_ref() ? e->contents() : e; ! 12657: } ! 12658: ! 12659: //?? case G_CALL: ! 12660: case CALL: /* handle undefined function names */ ! 12661: //error('d',"call %k %t %k",e1->base,e1->tp,e2?e2->base:0); ! 12662: if (e1->base==NAME && e1->tp==0) { ! 12663: Pname q = Pname(e1)->n_qualifier; ! 12664: e1 = find_name(Pname(e1),cc->cot,tbl,CALL,cc->nof); ! 12665: //error('d',"e1 %k %t %n",e1->base,e1->tp,e1->base==NAME?e1:e1->base==REF?e1->mem:0); ! 12666: if (q && (e1->base==REF ||e1->base==DOT)) // suppress virtual call ! 12667: e1->n_initializer = Pexpr(q); ! 12668: } ! 12669: ! 12670: if (e1->base==NAME && Pname(e1)->n_xref) { ! 12671: // fudge to handle X(X&) args ! 12672: e1 = new expr(DEREF,e1,0); ! 12673: e1->tp = e1->e1->tp; // !! ! 12674: } ! 12675: ! 12676: switch (e1->base) { ! 12677: case DOT: ! 12678: /* ! 12679: #ifdef FDOTRIGHT ! 12680: { ! 12681: //error('d',"fdot1 %k",e1->e1->base); ! 12682: switch (e1->e1->base) { ! 12683: case CALL: ! 12684: case G_CALL: // f().g() => (tmp=f(),tmp.g()) ! 12685: { Pexpr ee = e1->e1; ! 12686: Pexpr ex = ee->typ(tbl); ! 12687: Pname tmp = make_tmp('Q',ex->tp,tbl); ! 12688: ex = init_tmp(tmp,ex,tbl); ! 12689: ! 12690: Pexpr ee2 = new expr(base,e1,e2); ! 12691: e1->base = DOT; ! 12692: e1->e1 = tmp; ! 12693: ! 12694: base = G_CM; ! 12695: e1 = ex; ! 12696: e2 = ee2; ! 12697: ! 12698: return typ(tbl); ! 12699: } ! 12700: } ! 12701: break; ! 12702: } ! 12703: #endif ! 12704: */ ! 12705: case REF: // becomes ob.x::~x(0) or ! 12706: if (e2==0 // becomes p->x::~x(0) ! 12707: && Pref(e1)->mem ! 12708: && Pref(e1)->mem->base==NAME ! 12709: && Pname(Pref(e1)->mem)->n_oper==DTOR) { ! 12710: e1 = e1->typ(tbl); ! 12711: Pexpr ee = call_dtor(e1->e1,Pref(e1)->mem,0,e1->base,one); ! 12712: ee->tp = void_type; ! 12713: return ee; ! 12714: } ! 12715: } ! 12716: break; ! 12717: ! 12718: case QUEST: ! 12719: cond = cond->typ(tbl); ! 12720: case ANDAND: ! 12721: case OROR: ! 12722: Ntmp = 0; ! 12723: } ! 12724: ! 12725: if (e1) { ! 12726: e1 = e1->typ(tbl); ! 12727: if (e1->tp->is_ref()) e1 = e1->contents(); ! 12728: t1 = e1->tp; ! 12729: // if (t1->is_cl_obj()) t1->tsizeof(); ! 12730: } ! 12731: else ! 12732: t1 = 0; ! 12733: ! 12734: if (e2) { ! 12735: e2 = e2->typ(tbl); ! 12736: if (e2->tp->is_ref()) e2 = e2->contents(); ! 12737: t2 = e2->tp; ! 12738: // if (t2->is_cl_obj()) t2->tsizeof(); ! 12739: } ! 12740: else ! 12741: t2 = 0; ! 12742: ! 12743: // error('d',"b %k t1 %t t2 %t",b,t1,t2); ! 12744: switch (b) { // filter out non-overloadable operators ! 12745: default: ! 12746: { ! 12747: Pexpr x = try_to_overload(tbl); ! 12748: if (x) { ! 12749: if (b==INCR || b==DECR) { ! 12750: Pexpr fe = x->e1->base==NAME?x->e1:x->e1->mem; ! 12751: // by default, prefix version of operator is chosen ! 12752: // t2 set ==> ++n, t1 set ==> n++ ! 12753: if (fe->tp->base==OVERLOAD && t2==0 && t1) ! 12754: x=make_postfix(x); ! 12755: } ! 12756: return x; ! 12757: } ! 12758: // if (x) return x; ! 12759: // error('d',"e2: %t t2: %t", e2->tp, t2); ! 12760: if (t2 && t1==0 && t2!=e2->tp) t2 = e2->tp; ! 12761: } ! 12762: case DOT: ! 12763: case G_CM: ! 12764: case G_ADDROF: ! 12765: case G_CALL: ! 12766: case QUEST: ! 12767: break; ! 12768: } ! 12769: ! 12770: switch (b) { ! 12771: case QUEST: ! 12772: case ANDAND: ! 12773: case OROR: ! 12774: if (Ntmp) error('s',"temporary ofC%n with destructor needed in%kE",Ntmp,b); ! 12775: } ! 12776: ! 12777: t = (t1==0) ? t2 : (t2==0) ? t1 : 0; ! 12778: // error('d', "expr::typ t %t", t ); ! 12779: // error('d',"b2 %d %k",b,b); ! 12780: switch (b) { /* are the operands of legal types */ ! 12781: case REFMUL: ! 12782: base = REF; ! 12783: // no break; ! 12784: case DOT: ! 12785: { // a .* p => &a MEMPTR p => appropriate indirection ! 12786: // to be considered: what happens if a .* expression ! 12787: // is used except in a call/=? ! 12788: Pexpr a = e1->typ(tbl); ! 12789: Ptype at = a->tp; ! 12790: if (base == DOT) { ! 12791: a = a->address(); ! 12792: at = at->addrof(); // beware of n_xref ! 12793: } ! 12794: ! 12795: while (at->base == TYPE) at = Pbase(at)->b_name->tp; ! 12796: Pname cn = Pptr(at)->typ->is_cl_obj(); ! 12797: Pclass mm = cn ? Pclass(cn->tp) : 0; ! 12798: ! 12799: Pexpr p = e2->typ(tbl); ! 12800: Ptype pt = p->tp; ! 12801: Pname pcn = pt->is_cl_obj(); ! 12802: ! 12803: //error('d',"mm %t pt %t",mm,pt); ! 12804: if (pcn) { ! 12805: Pclass cl = Pclass(pcn->tp); ! 12806: Pname found = 0; ! 12807: for (Pname on=cl->conv; on; on=on->n_list) { ! 12808: Pfct f = Pfct(on->tp); ! 12809: Pptr frt = Pptr(f->returns); ! 12810: while (frt->base == TYPE) frt = Pptr(Pbase(frt)->b_name->tp); ! 12811: if (frt->base!=PTR || Pptr(frt)->memof==0) break; ! 12812: if (Pptr(frt)->memof==mm || mm->has_base(Pptr(frt)->memof)) { ! 12813: if (found) ! 12814: error("two possible conversions forP toM: %n and %n",found,on); ! 12815: else ! 12816: found = on; ! 12817: } ! 12818: } ! 12819: //error('d',"found %n",found); ! 12820: if (found) { ! 12821: p = new ref(DOT,p,found); ! 12822: p = new call(p,0); ! 12823: p = p->typ(tbl); ! 12824: pt = p->tp; ! 12825: } ! 12826: ! 12827: } ! 12828: while (pt->base == TYPE) pt = Pbase(pt)->b_name->tp; ! 12829: if (pt->base!=PTR || Pptr(pt)->memof==0) { ! 12830: error("P toMX in .*E: %t",pt); ! 12831: tp = any_type; ! 12832: base = DUMMY; ! 12833: return this; ! 12834: } ! 12835: Pclass pm = Pptr(pt)->memof; ! 12836: ! 12837: // while (at->base == TYPE) at = Pbase(at)->b_name->tp; ! 12838: // Pname cn = Pptr(at)->typ->is_cl_obj(); ! 12839: // Pclass mm = cn ? Pclass(cn->tp) : 0; ! 12840: //error('d',"mm %t %t %d %d",mm,pm,pm->baseof(mm),mm->has_base(pm)); ! 12841: ! 12842: // if (mm!=pm && pm->baseof(mm)==0 && mm->has_base(pm)==0) { ! 12843: if (mm != pm) { ! 12844: if (mm->has_base(pm) == 0) { ! 12845: error("badOT in .*E: %t (%s*X)",a->tp,pm->string); ! 12846: tp = any_type; ! 12847: //return this; ! 12848: } ! 12849: a = new texpr(CAST,pm->this_type,a); ! 12850: e1 = a = a->typ(tbl); ! 12851: } ! 12852: ! 12853: Ptype tpx = Pptr(pt)->typ; ! 12854: while (tpx->base == TYPE) tpx = Pbase(tpx)->b_name->tp; ! 12855: ! 12856: if (tpx->base == FCT) { // a.*p => (&a MEMPTR p) ! 12857: base = MEMPTR; ! 12858: tp2 = mm; // keep the class for simpl.c ! 12859: e1 = a; ! 12860: e2 = p; ! 12861: } ! 12862: else { // a .* p => *(typeof(p))((char*)&a + (int)p-1) ! 12863: a = new cast(Pchar_type,a); ! 12864: p = new cast(int_type,p); ! 12865: p = new expr(MINUS,p,one); ! 12866: p->tp = int_type; ! 12867: Pexpr pl = new expr(PLUS,a,p); ! 12868: pl->tp = Pchar_type; ! 12869: base = DEREF; ! 12870: pt = new ptr(PTR,tpx); // need a T* not a T C::* ! 12871: Pptr(pt)->rdo = Pptr(tpx)->rdo; ! 12872: mpglob = pm; ! 12873: // PERM(pt); ! 12874: e1 = new cast(pt,pl); ! 12875: e2 = 0; ! 12876: } ! 12877: tp = tpx; ! 12878: return tp->is_ref() ? contents() : this; ! 12879: } ! 12880: ! 12881: case G_CALL: ! 12882: case CALL: ! 12883: tp = call_fct(tbl); /* two calls of use() for e1's names */ ! 12884: if (tp->is_ref()) return contents(); ! 12885: return this; ! 12886: ! 12887: case DEREF: ! 12888: if (e1 == dummy) error("O missing before []\n"); ! 12889: if (e2 == dummy) error("subscriptE missing"); ! 12890: ! 12891: if (t) { /* *t */ ! 12892: while (t->base == TYPE) t = Pbase(t)->b_name->tp; ! 12893: // t->vec_type(); ! 12894: if (t->base==PTR && Pptr(t)->memof) error("P toM dereferenced"); ! 12895: tp = t->deref(); ! 12896: } ! 12897: else { // e1[e2] that is *(e1+e2) ! 12898: //error('d',"deref %t[%t]",t1,t2); ! 12899: if (t1->vec_type()) { // e1[e2] ! 12900: switch (t2->base) { ! 12901: case CHAR: ! 12902: case SHORT: ! 12903: case INT: ! 12904: case LONG: ! 12905: case EOBJ: ! 12906: break; ! 12907: default: ! 12908: { Pname cn = t2->is_cl_obj(); ! 12909: if (cn) // conversion to integral? ! 12910: e2 = check_cond(e2,DEREF,tbl); ! 12911: else ! 12912: t2->integral(DEREF); ! 12913: } ! 12914: } ! 12915: while (t1->base == TYPE) t1 = Pbase(t1)->b_name->tp; ! 12916: if (t1->base==PTR && Pptr(t1)->memof) error("P toM dereferenced"); ! 12917: tp = t1->deref(); ! 12918: (void) tp->tsizeof(); ! 12919: } ! 12920: else if (t2->vec_type()) { // really e2[e1] ! 12921: t1->integral(DEREF); ! 12922: while (t2->base == TYPE) t2 = Pbase(t2)->b_name->tp; ! 12923: if (t2->base==PTR && Pptr(t2)->memof) error("P toM dereferenced"); ! 12924: tp = t2->deref(); ! 12925: (void) tp->tsizeof(); ! 12926: } ! 12927: else { ! 12928: error("[] applied to nonPT:%t[%t]",t1,t2); ! 12929: tp = any_type; ! 12930: } ! 12931: } ! 12932: ! 12933: if (tp->is_ref()) return contents(); ! 12934: ! 12935: return this; ! 12936: ! 12937: case G_ADDROF: ! 12938: case ADDROF: ! 12939: //error('d',"addrof(%d) %k %d",base,e2->base,e2->base); ! 12940: switch (e2->base) { // potential lvalues ! 12941: case G_CM: ! 12942: if (base==ADDROF && e2->e2->base==NAME) { ! 12943: // check for cfront generated result variable ! 12944: char* s = e2->e2->string; ! 12945: if (s[0]=='_' && s[1] && s[1]=='_') { ! 12946: if (s[2] && (s[2]=='R' || s[2]=='V')) { ! 12947: error("address of non-lvalue"); ! 12948: break; ! 12949: } ! 12950: } ! 12951: } ! 12952: case CM: // &(a,b) => (a,&b) ! 12953: { ! 12954: Pexpr ee = e2; ! 12955: ee->tp = 0; ! 12956: ee->e2 = new expr(base,0,ee->e2); ! 12957: delete this; ! 12958: return ee->typ(tbl); ! 12959: } ! 12960: case QUEST: // & (a?b:c) => (a?&b:&c) ! 12961: { ! 12962: Pexpr ee = e2; ! 12963: ee->tp = 0; ! 12964: ee->e1 = new expr(base,0,ee->e1); ! 12965: ee->e2 = new expr(base,0,ee->e2); ! 12966: delete this; ! 12967: return ee->typ(tbl); ! 12968: } ! 12969: case INCR: ! 12970: case DECR: ! 12971: if (e2->e1) break; ! 12972: case ASSIGN: ! 12973: case ASPLUS: ! 12974: case ASMINUS: ! 12975: case ASMUL: ! 12976: case ASDIV: ! 12977: case ASMOD: ! 12978: case ASAND: ! 12979: case ASOR: ! 12980: case ASER: ! 12981: case ASLS: ! 12982: case ASRS: ! 12983: return e2->address(); ! 12984: } ! 12985: ! 12986: if (e2->lval(ADDROF) == 0) { ! 12987: if (error_count) { // error_count == 0 possible ! 12988: // in case of & const ! 12989: tp = any_type; ! 12990: return this; ! 12991: } ! 12992: } ! 12993: ! 12994: tp = t->addrof(); ! 12995: ! 12996: if( base==ADDROF && mpglob) ! 12997: Pptr(tp)->memof = mpglob; ! 12998: ! 12999: if (e2->tp->base == VEC) { ! 13000: if(e2->base != NAME) { ! 13001: base = CAST; ! 13002: tp2 = tp; ! 13003: e1 = e2; ! 13004: e2 = 0; ! 13005: return this; ! 13006: } ! 13007: } ! 13008: ! 13009: // tp = t->addrof(); ! 13010: ! 13011: if (t->base==FCT) ! 13012: Pptr(tp)->memof = Pfct(t)->memof; ! 13013: ! 13014: // if (t->tconst() && vec_const==0 && fct_const==0) Pptr(tp)->rdo = 1; ! 13015: // ??? & (const T) is NOT T*const but const T* ! 13016: ! 13017: switch (e2->base) { ! 13018: case NAME: ! 13019: mname: // check for &s::i ! 13020: { Pname n2 = Pname(e2); ! 13021: Pname cn = (n2->n_table && n2->n_table!=gtbl) ? n2->n_table->t_name : 0; ! 13022: // error('d',"n2 %k cn %n t %t",n2->base,cn,t); ! 13023: if (cn == 0) break; ! 13024: // Pptr(tp)->memof = Pclass(cn->tp); ! 13025: ! 13026: if (t->base==FCT && Pfct(t)->f_this==0) { ! 13027: Pptr(tp)->memof = 0; ! 13028: break; ! 13029: } ! 13030: ! 13031: switch (t->base) { ! 13032: case OVERLOAD: ! 13033: return e2; ! 13034: case FCT: ! 13035: // error('d', "cn->tp: %d, %k", cn->tp, cn->tp->base); ! 13036: Pptr(tp)->memof = Pclass(cn->tp); //SSS ! 13037: ! 13038: if (Pfct(t)->f_virtual) { ! 13039: // { 0,vtbl index,0 } ! 13040: e1 = new ival(Pfct(t)->f_virtual); ! 13041: e1 = new expr(ELIST,zero,e1); ! 13042: e2 = zero; ! 13043: base = ILIST; ! 13044: // tp = int_type; ! 13045: return this; ! 13046: } // use the pointer ! 13047: ! 13048: // { 0,-1,(int(*)())ptr } ! 13049: e1 = new ival(-1); ! 13050: e1 = new expr(ELIST,zero,e1); ! 13051: // e2 is the name ! 13052: e2 = new cast(Pfct_type,e2); ! 13053: base = ILIST; ! 13054: // tp = int_type; ! 13055: return this; ! 13056: ! 13057: // return e2; ! 13058: ! 13059: default: ! 13060: if (n2->n_stclass != STATIC) { // offset + 1 ! 13061: //error('d',"n2 %n %d",n2,n2->n_offset); ! 13062: //error('d',"q %n cn %n",n2->n_qualifier,cn); ! 13063: e1 = new ival(n2->n_offset+1); ! 13064: Pptr(tp)->memof = Pclass(cn->tp); ! 13065: //error('d',"cl %d %s i %d",Pclass(cn->tp),Pclass(cn->tp)?Pclass(cn->tp)->string:"0",n2->n_offset); ! 13066: } ! 13067: else ! 13068: return this; ! 13069: } ! 13070: //error('d',"int_type"); ! 13071: e1->tp = int_type; ! 13072: e2 = 0; ! 13073: tp2 = tp; ! 13074: base = CAST; ! 13075: return this; ! 13076: } ! 13077: case DOT: ! 13078: case REF: ! 13079: { ! 13080: Pname m = Pname(e2->mem); ! 13081: // error( 'd', "e2->mem->base: %k", e2->mem->base ); ! 13082: // Pname m = (e2->mem->base == MDOT) ? Pname(e2->mem->mem) : Pname(e2->mem); ! 13083: while ( m->base == MDOT ) m = Pname(Pexpr(m)->mem); ! 13084: ! 13085: Pfct f = Pfct(m->tp); ! 13086: ! 13087: if (f->base == FCT || f->base == OVERLOAD) { // &p->f ! 13088: Pexpr q = Pname(e2)->n_initializer; // &p->x::f ! 13089: ! 13090: if (q && bound==0 && e2->e1==cc->c_this) { ! 13091: // FUDGE: &this->x::f => &x::f ! 13092: DEL(e2); ! 13093: e2 = m; ! 13094: goto mname; ! 13095: } ! 13096: ! 13097: bound = 1; ! 13098: if(!f->f_static) { ! 13099: error(strict_opt?0:'w', ! 13100: "address of boundF (try using ``%s::*'' forPT and ``&%s::%s'' for address) (anachronism)", ! 13101: m->n_table->t_name->string, ! 13102: m->n_table->t_name->string, ! 13103: m->string ! 13104: ); ! 13105: } ! 13106: ! 13107: if (q || f->f_virtual==0) { ! 13108: // & x.f => & f ! 13109: DEL(e2); ! 13110: e2 = m; ! 13111: } ! 13112: } ! 13113: break; ! 13114: ! 13115: } ! 13116: case MEMPTR: ! 13117: // &(p->*q) ! 13118: error("& .* E"); ! 13119: } ! 13120: ! 13121: return this; ! 13122: ! 13123: case UMINUS: ! 13124: t->numeric(UMINUS); ! 13125: tp = t; ! 13126: return this; ! 13127: ! 13128: case UPLUS: ! 13129: t->num_ptr(UPLUS); ! 13130: tp = t; ! 13131: if (ansi_opt==0) { ! 13132: base = PLUS; ! 13133: e1 = zero; ! 13134: } ! 13135: return this; ! 13136: ! 13137: case NOT: ! 13138: e2 = check_cond(e2,NOT,tbl); ! 13139: tp = int_type; ! 13140: return this; ! 13141: ! 13142: case COMPL: ! 13143: t->integral(COMPL); ! 13144: tp = t; ! 13145: return this; ! 13146: ! 13147: case INCR: ! 13148: case DECR: ! 13149: { ! 13150: // error('d',"incr-decr: e1: %k e2: %k", e1?e1->base:0, e2?e2->base:0); ! 13151: Pexpr e = e1?e1:e2; // e1!=0 ==> e++ or e-- ! 13152: // e1==0 ==> ++e or --e ! 13153: ! 13154: e->lval(b); ! 13155: ! 13156: switch(e->base) { ! 13157: case QUEST: ! 13158: e->tp=0; ! 13159: e->e1 = e1 ? new expr(base,e->e1,0) : new expr(base,0,e->e1); ! 13160: e->e2 = e1 ? new expr(base,e->e2,0) : new expr(base,0,e->e2); ! 13161: delete this; ! 13162: return e->typ(tbl); ! 13163: case CM: ! 13164: case G_CM: ! 13165: e->tp=0; ! 13166: e->e2 = e1 ? new expr(base,e->e2,0) : new expr(base,0,e->e2); ! 13167: delete this; ! 13168: return e->typ(tbl); ! 13169: case INCR: ! 13170: case DECR: ! 13171: if(e->e1) ! 13172: break; ! 13173: nin++; ! 13174: if(e->e2->not_simple()) ! 13175: error('s',"overly complex %k of %k",b,e->base); ! 13176: nin--; ! 13177: e = new expr(G_CM,e,e->e2->typ(tbl)); ! 13178: if (e1) e1=e; else e2=e; ! 13179: // e1?e1:e2 = e; ! 13180: return typ(tbl); ! 13181: case ASSIGN: ! 13182: case ASPLUS: ! 13183: case ASMINUS: ! 13184: case ASMUL: ! 13185: case ASDIV: ! 13186: case ASMOD: ! 13187: case ASAND: ! 13188: case ASOR: ! 13189: case ASER: ! 13190: case ASLS: ! 13191: case ASRS: ! 13192: nin++; ! 13193: if(e->e1->not_simple()) ! 13194: error('s',"overly complex %k of %k",b,e->base); ! 13195: nin--; ! 13196: e = new expr(G_CM,e,e->e1->typ(tbl)); ! 13197: if (e1) e1=e; else e2=e; ! 13198: // e1?e1:e2 = e; ! 13199: return typ(tbl); ! 13200: } ! 13201: } ! 13202: ! 13203: r1 = t->num_ptr(b); ! 13204: if (r1='P' && t->check(Pvoid_type,0)==0) error("%k of void*",b); ! 13205: tp = t; ! 13206: return this; ! 13207: ! 13208: } ! 13209: ! 13210: if (e1==dummy || e2==dummy || e1==0 || e2==0) error("operand missing for%k",b); ! 13211: switch (b) { ! 13212: case MUL: ! 13213: case DIV: ! 13214: r1 = t1->numeric(b); ! 13215: r2 = t2->numeric(b); ! 13216: nppromote(b); ! 13217: break; ! 13218: ! 13219: case PLUS: ! 13220: r2 = t2->num_ptr(PLUS); ! 13221: r1 = t1->num_ptr(PLUS); ! 13222: nppromote(PLUS); ! 13223: goto void_check; ! 13224: ! 13225: case MINUS: ! 13226: r2 = t2->num_ptr(MINUS); ! 13227: r1 = t1->num_ptr(MINUS); ! 13228: if (r2=='P' && r1!='P' && r1!='A') error("nonP - P"); ! 13229: nppromote(MINUS); ! 13230: void_check: ! 13231: if ((r1='P' && t1->check(Pvoid_type,0)==0) ! 13232: || (r2='P' && t2->check(Pvoid_type,0)==0)) ! 13233: error("%k of void*",b); ! 13234: tp = t; ! 13235: break; ! 13236: ! 13237: case LS: ! 13238: case RS: ! 13239: case AND: ! 13240: case OR: ! 13241: case ER: ! 13242: switch (e1->base) { ! 13243: case LT: ! 13244: case LE: ! 13245: case GT: ! 13246: case GE: ! 13247: case EQ: ! 13248: case NE: ! 13249: error('w',"%kE as operand for%k",e1->base,b); ! 13250: } ! 13251: switch (e2->base) { ! 13252: case LT: ! 13253: case LE: ! 13254: case GT: ! 13255: case GE: ! 13256: case EQ: ! 13257: case NE: ! 13258: error('w',"%kE as operand for%k",e2->base,b); ! 13259: } ! 13260: case MOD: ! 13261: r1 = t1->integral(b); ! 13262: r2 = t2->integral(b); ! 13263: nppromote(b); ! 13264: break; ! 13265: ! 13266: case LT: ! 13267: case LE: ! 13268: case GT: ! 13269: case GE: ! 13270: case EQ: ! 13271: case NE: ! 13272: r1 = t1->num_ptr(b); ! 13273: r2 = t2->num_ptr(b); ! 13274: if (r1=='P' && r2=='I') { // allow things like: ! 13275: // if (p==2-2) ! 13276: // YUCK! ! 13277: Neval = 0; ! 13278: long i = e2->eval(); ! 13279: if (Neval==0 && i==0) { ! 13280: DEL(e2); ! 13281: e2 = zero; ! 13282: r2 = 'Z'; ! 13283: } ! 13284: } ! 13285: else if (r2=='P' && r1=='I') { ! 13286: Neval = 0; ! 13287: long i = e1->eval(); ! 13288: if (Neval==0 && i==0) { ! 13289: DEL(e1); ! 13290: e1 = zero; ! 13291: r1 = 'Z'; ! 13292: } ! 13293: } ! 13294: ! 13295: if (b!=EQ && b!=NE) { ! 13296: if (r1=='P' && r2=='Z') error("P%k 0",b); ! 13297: if (r2=='P' && r1=='Z') error("P%k 0",b); ! 13298: } ! 13299: ! 13300: // make sure functions are properly converted to pointers to ! 13301: // functions and make sure overloaded functions are rejected ! 13302: Pexpr ptof(Pfct ef, Pexpr e, Ptable tbl); ! 13303: if (r1 == FCT) e1 = ptof(0,e1,tbl); ! 13304: if (r2 == FCT) e2 = ptof(0,e2,tbl); ! 13305: ! 13306: npcheck(b); ! 13307: ! 13308: if (r1=='P') { // need cast for pointers to virtual and second bases ! 13309: Pptr p1 = t1->is_ptr(); ! 13310: Pptr p2 = t2->is_ptr(); ! 13311: Pname cn = p1?p1->typ->is_cl_obj():0; ! 13312: Pname cn2 = p2?p2->typ->is_cl_obj():0; ! 13313: ! 13314: if (cn && cn2) { ! 13315: Pclass cl = Pclass(cn->tp); ! 13316: Pclass cl2 = Pclass(cn2->tp); ! 13317: ! 13318: if (cl->has_base(cl2)) { ! 13319: e1 = cast_cptr(cl2,e1,tbl,0); ! 13320: e1 = new cast(p2,e1); ! 13321: } ! 13322: else if (cl2->has_base(cl)) { ! 13323: e2 = cast_cptr(cl,e2,tbl,0); ! 13324: e2 = new cast(p1,e2); ! 13325: } ! 13326: } ! 13327: } ! 13328: ! 13329: if (r1=='P' && t1->memptr()) { ! 13330: mpmp: ! 13331: if (r2=='Z') { ! 13332: e2 = zero; ! 13333: e1 = new mdot("i",e1); ! 13334: e1->i1 = 9; ! 13335: } ! 13336: else if (r2=='P' && t2->memptr()) { ! 13337: // ERROR: no check for sideeffects ! 13338: Pexpr i1 = new mdot("i",e1); ! 13339: Pexpr i2; ! 13340: i1->i1 = 9; ! 13341: ! 13342: i2 = e2; ! 13343: while ( i2->base == CAST ) ! 13344: i2 = i2->e1; ! 13345: if ( i2->base == ILIST ) ! 13346: e2 = i2; ! 13347: ! 13348: if (e2->base==ILIST) ! 13349: i2 = e2->e1->e2; ! 13350: else { ! 13351: i2 = new mdot("i",e2); ! 13352: i2->i1 = 9; ! 13353: } ! 13354: ! 13355: Pexpr f1 = new mdot("f",e1); ! 13356: Pexpr f2; ! 13357: f1->i1 = 9; ! 13358: if (e2->base == ILIST) ! 13359: // f2 = new cast(Pfct_type,e2->e2); ! 13360: f2 = e2->e2; ! 13361: else { ! 13362: f2 = new mdot("f",e2); ! 13363: f2->i1 = 9; ! 13364: } ! 13365: ! 13366: Pexpr ei = new expr(base,i1,i2); ! 13367: Pexpr fi = new expr(base,f1,f2); ! 13368: ! 13369: base = ANDAND; ! 13370: e1 = ei; ! 13371: e2 = fi; ! 13372: } else if (r2=='P') { ! 13373: error('s',"%t %k %t",t1,base,t2); ! 13374: } ! 13375: } ! 13376: else if (r2=='P' && t2->memptr()) { ! 13377: Pexpr ee = e1; // swap ! 13378: e1 = e2; ! 13379: e2 = ee; ! 13380: int rr = r1; ! 13381: r1 = r2; ! 13382: r2 = rr; ! 13383: Ptype tt = t1; ! 13384: t1 = t2; ! 13385: t2 = tt; ! 13386: goto mpmp; ! 13387: } ! 13388: t = int_type; ! 13389: break; ! 13390: ! 13391: case ANDAND: ! 13392: case OROR: ! 13393: e1 = check_cond(e1,b,tbl); ! 13394: e2 = check_cond(e2,b,tbl); ! 13395: t = int_type; ! 13396: break; ! 13397: ! 13398: case QUEST: ! 13399: { ! 13400: Pname c1, c2; ! 13401: cond = check_cond(cond,b,tbl); ! 13402: //error('d',"cond %k %t",cond->base,cond->tp); ! 13403: //error('d',"t1 %t t2 %t",t1,t2); ! 13404: ! 13405: // still doesn't do complete checking for possible conversions... ! 13406: ! 13407: bit MPTR = 0; // local hack ! 13408: ! 13409: extern int suppress_error; // global hack ! 13410: suppress_error++; ! 13411: r1 = t1->num_ptr(b); ! 13412: r2 = t2->num_ptr(b); ! 13413: suppress_error--; ! 13414: if (r1=='P' && r2=='P' && t1->memptr() && t2->memptr()) { ! 13415: ! 13416: ++MPTR; // prevent later sorry ! 13417: ! 13418: // watch for casts ! 13419: Pexpr tt = e1; ! 13420: while ( tt->base == CAST ) tt = tt->e1; ! 13421: if ( tt->base == ILIST ) e1 = tt; ! 13422: ! 13423: tt = e2; ! 13424: while ( tt->base == CAST ) tt = tt->e1; ! 13425: if ( tt->base == ILIST ) e2 = tt; ! 13426: ! 13427: // cannot have sides return (expr?{}:{}) ! 13428: // reuse same temp for both sides ?: ! 13429: Pname temp = make_tmp( 'A', mptr_type, tbl ); ! 13430: ! 13431: e1 = mptr_assign( temp, e1 ); ! 13432: e1 = new expr( G_CM, e1, temp ); ! 13433: e1->tp = temp->tp; ! 13434: ! 13435: e2 = mptr_assign( temp, e2 ); ! 13436: e2 = new expr( G_CM, e2, temp ); ! 13437: e2->tp = temp->tp; ! 13438: } ! 13439: ! 13440: if (t1==t2 ! 13441: || ( (c1=t1->is_cl_obj()) ! 13442: && (c2=t2->is_cl_obj()) ! 13443: && (c1->tp==c2->tp) ! 13444: )) ! 13445: t = t1; ! 13446: else { ! 13447: r1 = t1->num_ptr(b); ! 13448: r2 = t2->num_ptr(b); ! 13449: ! 13450: if (r1=='P' && r2=='P') { ! 13451: Pptr p1 = t1->is_ptr(); ! 13452: Pptr p2 = t2->is_ptr(); ! 13453: //error('d',"p1 %t p2 %t",p1,p2); ! 13454: if ((c1 = p1->typ->is_cl_obj()) ! 13455: && (c2 = p2->typ->is_cl_obj())) { ! 13456: Pclass cl1 = Pclass(c1->tp); ! 13457: Pclass cl2 = Pclass(c2->tp); ! 13458: if (cl1==cl2 || cl2->has_base(cl1)) { ! 13459: t = t1; ! 13460: goto caca; ! 13461: } ! 13462: else if (cl1->has_base(cl2)) { ! 13463: t = t2; ! 13464: goto caca; ! 13465: } ! 13466: } ! 13467: } ! 13468: ! 13469: if (r1==FCT && r2==FCT) { // fudge ! 13470: if (t1->check(t2,ASSIGN)) ! 13471: error("badTs in ?:E: %t and %t",t1,t2); ! 13472: else if (Pfct(t1)->memof) error('s',"conditionalE with%t",t1); ! 13473: t = t1; ! 13474: } ! 13475: else ! 13476: nppromote(b); ! 13477: caca: ! 13478: //error('d',"?: t %t t1 %t t2 %t",t,t1,t2); ! 13479: if (t!=t1 && t->check(t1,0)) { ! 13480: PERM(t); ! 13481: e1 = new cast(t,e1); ! 13482: } ! 13483: ! 13484: if (t!=t2 && t->check(t2,0)) { ! 13485: PERM(t); ! 13486: e2 = new cast(t,e2); ! 13487: } ! 13488: ! 13489: Pptr pt = t->is_ptr(); ! 13490: //if (pt && pt->base==PTR && pt->memof) error('s',"conditionalE with%t",t); ! 13491: if (pt && pt->base==PTR && pt->memof && MPTR == 0) error('s',"conditionalE with%t",t); ! 13492: } ! 13493: } ! 13494: break; ! 13495: ! 13496: case ASPLUS: ! 13497: r1 = t1->num_ptr(ASPLUS); ! 13498: r2 = t2->num_ptr(ASPLUS); ! 13499: nppromote(ASPLUS); ! 13500: goto ass; ! 13501: ! 13502: case ASMINUS: ! 13503: r1 = t1->num_ptr(ASMINUS); ! 13504: r2 = t2->num_ptr(ASMINUS); ! 13505: if (r2=='P' && r1!='P' && r1!='A') error("P -= nonP"); ! 13506: nppromote(ASMINUS); ! 13507: goto ass; ! 13508: ! 13509: case ASMUL: ! 13510: case ASDIV: ! 13511: r1 = t1->numeric(b); ! 13512: r2 = t1->numeric(b); ! 13513: nppromote(b); ! 13514: goto ass; ! 13515: ! 13516: case ASMOD: ! 13517: r1 = t1->integral(ASMOD); ! 13518: r2 = t2->integral(ASMOD); ! 13519: nppromote(ASMOD); ! 13520: goto ass; ! 13521: ! 13522: case ASAND: ! 13523: case ASOR: ! 13524: case ASER: ! 13525: case ASLS: ! 13526: case ASRS: ! 13527: r1 = t1->integral(b); ! 13528: r2 = t2->integral(b); ! 13529: npcheck(b); ! 13530: t = int_type; ! 13531: goto ass; ! 13532: ass: ! 13533: if (r1='P' && t1->check(Pvoid_type,0)==0) error("%k of void*",b); ! 13534: tp = t; ! 13535: as_type = t; /* the type of the rhs */ ! 13536: t2 = t; ! 13537: ! 13538: case ASSIGN: ! 13539: //error('d',"assign %k: %t %t %s",b,t1,t2,ignore_const?"ignore const":""); ! 13540: //error('d'," e1 %d %k e1 %d %k",e1,e1->base,e2,e2->base); ! 13541: if (ignore_const) { // handle static initializers ! 13542: // represented as assignments ! 13543: // ignore consts. ! 13544: tp = e1->tp; ! 13545: return this; ! 13546: } ! 13547: ! 13548: switch (e1->base) { ! 13549: case G_CM: ! 13550: case CM: // (a,b)=c => *(a,&b)=c ! 13551: { ! 13552: e1->e2 = new expr(G_ADDROF,0,e1->e2); ! 13553: e1->tp = 0; ! 13554: e1 = new expr(DEREF,e1,0); ! 13555: return typ(tbl); ! 13556: } ! 13557: case QUEST: // (a?b:c)=d => *(a?&b:&c)=c ! 13558: { ! 13559: e1->e1 = new expr(G_ADDROF,0,e1->e1); ! 13560: e1->e2 = new expr(G_ADDROF,0,e1->e2); ! 13561: e1->tp = 0; ! 13562: e1 = new expr(DEREF,e1,0); ! 13563: return typ(tbl); ! 13564: } ! 13565: case ASSIGN: // (a*=b)=c => a*=b,a=c ! 13566: case ASPLUS: ! 13567: case ASMINUS: ! 13568: case ASMUL: ! 13569: case ASDIV: ! 13570: case ASMOD: ! 13571: case ASAND: ! 13572: case ASOR: ! 13573: case ASER: ! 13574: case ASLS: ! 13575: case ASRS: ! 13576: { ! 13577: base = G_CM; ! 13578: nin++; ! 13579: if (e1->e1->not_simple()) error('s',"lvalue %k too complicated",b); ! 13580: nin--; ! 13581: Pexpr aa = new expr(e1->base,e1->e1,e1->e2); ! 13582: Pexpr bb = new expr(b,e1->e1,e2); ! 13583: e1 = aa; ! 13584: e2 = bb; ! 13585: return typ(tbl); ! 13586: } ! 13587: case INCR: ! 13588: case DECR: // ++a=b => ++a,a=b ! 13589: { ! 13590: if(!e1->e2) break ; ! 13591: base = G_CM; ! 13592: nin++; ! 13593: if (e1->e2->not_simple()) error('s',"lvalue %k too complicated",b); ! 13594: nin--; ! 13595: Pexpr aa = new expr(e1->base,0,e1->e2); ! 13596: Pexpr bb = new expr(b,e1->e2,e2); ! 13597: e1 = aa; ! 13598: e2 = bb; ! 13599: return typ(tbl); ! 13600: } ! 13601: case REF: ! 13602: { ! 13603: Pexpr r = e1; ! 13604: // hack to prevent ! 13605: // f().i = j ! 13606: // transformed into ! 13607: // ((t=f()),&t)->i = j ! 13608: if (r->e1->base==G_CM ! 13609: && r->e1->e2->base==G_ADDROF ! 13610: && r->e1->e2->e2->base==NAME) { ! 13611: char* s = r->e1->e2->e2->string; ! 13612: if (s[0]=='_' && s[1]=='_') ! 13613: error("left hand side not lvalue"); ! 13614: } ! 13615: } ! 13616: } ! 13617: ! 13618: if (e1->lval(b) == 0) { ! 13619: tp = any_type; ! 13620: return this; ! 13621: } ! 13622: lkj: ! 13623: switch (t1->base) { ! 13624: case TYPE: ! 13625: t1 = Pbase(t1)->b_name->tp; ! 13626: goto lkj; ! 13627: case INT: ! 13628: case CHAR: ! 13629: case SHORT: ! 13630: // if (e2->base==ICON && e2->tp==long_type) ! 13631: // error('w',"long constant assigned to%k",t1->base); ! 13632: { Ptype t = e2->tp; ! 13633: csi: ! 13634: switch (t->base) { ! 13635: case TYPE: ! 13636: t = Pbase(t)->b_name->tp; goto csi; ! 13637: case LONG: ! 13638: case FLOAT: ! 13639: case DOUBLE: ! 13640: case LDOUBLE: ! 13641: error('w',"%t assigned to %t",e2->tp,t1); ! 13642: } ! 13643: } ! 13644: // no break ! 13645: case LONG: ! 13646: if (b==ASSIGN ! 13647: && Pbase(t1)->b_unsigned ! 13648: && e2->base==UMINUS ! 13649: && e2->e2->base==ICON) ! 13650: error('w',"negative assigned to unsigned"); ! 13651: break; ! 13652: case PTR: ! 13653: if (b == ASSIGN) { ! 13654: //error('d',"ptr t1 %t %d %t",t1,t1->memptr(),t2); ! 13655: //?? if (t1->memptr() && t2->base!=OVERLOAD) break; ! 13656: e2 = ptr_init(Pptr(t1),e2,tbl); ! 13657: t2 = e2->tp; ! 13658: //error('d',"pchecked %d",Pchecked); ! 13659: if (Pchecked) { ! 13660: tp = e1->tp; ! 13661: return this; ! 13662: } ! 13663: } ! 13664: break; ! 13665: case COBJ: ! 13666: { Pname c1 = t1->is_cl_obj(); ! 13667: // test of c1->tp necessary for ``fake classes'' ! 13668: // _Sdd generated for vector assignemnts ! 13669: if (c1 ! 13670: && c1->tp ! 13671: /* && Pclass(c1->tp)->memtbl->look("__as",0)==0*/) { ! 13672: //&& Pclass(c1->tp)->has_oper(ASSIGN)==0) { ! 13673: Pname c2 = t2->is_cl_obj(); ! 13674: // error('d', "expr::typ: c1: %n c2: %n", c1, c2 ); ! 13675: if (c1 != c2) { ! 13676: /* ! 13677: consider: ! 13678: ! 13679: struct A { A(B&); }; ! 13680: struct B : A {}; ! 13681: ! 13682: A aa; ! 13683: B bb; ! 13684: ! 13685: aa = bb; // aa.operator=(A(bb)); ! 13686: // optimize to aa.A(bb) when possible ! 13687: // avoid temporary where aa = *(A*)&bb is legal ! 13688: */ ! 13689: // error('d',"expr::typ c1 %n %d c2 %n %d",c1,c1?c1->tp:0,c2,c2?c2->tp:0); ! 13690: if (c2 ! 13691: && c2->tp ! 13692: && can_coerce(t1,t2)==0 ! 13693: //&& Pclass(c2->tp)->has_base(Pclass(c1->tp)) ! 13694: //&& (1<is_unique_base(Pclass(c2->tp),c1->string,0)) ! 13695: && (vcllist->clear(),vcllist=0,1<is_unique_base(Pclass(c2->tp),c1->string,0)) ! 13696: && Pclass(c1->tp)->c_xref&(C_VBASE|C_VPTR|C_ASS)) { ! 13697: // error('d',"aaa"); ! 13698: if (make_assignment(c1)) return try_to_overload(tbl); ! 13699: } ! 13700: // optimize ! 13701: else { ! 13702: e2 = new expr(ELIST,e2,0); ! 13703: e2 = new texpr(VALUE,t1,e2); ! 13704: if (Pclass(c1->tp)->has_dtor()==0 && ! 13705: Pclass(c1->tp)->has_oper(ASSIGN)==0) { ! 13706: // optimize ! 13707: // error('d',"bbb"); ! 13708: e2->e2 = e1; ! 13709: e2 = e2->typ(tbl); ! 13710: if (e2->base==DEREF && e2->e1->base==G_CALL || ! 13711: e2->base==ASSIGN && e2->e1==e1) { ! 13712: // error('d',"ccc"); ! 13713: *this = *e2; ! 13714: } ! 13715: tp = t1; ! 13716: return this; ! 13717: } ! 13718: return typ(tbl); ! 13719: } ! 13720: } ! 13721: // test of c1->tp necessary for ``fake classes'' ! 13722: // _Sdd generated for vector assignemnts ! 13723: else if (c1->tp && Pclass(c1->tp)->c_xref&(C_VBASE|C_VPTR|C_ASS)) { ! 13724: if (make_assignment(c1)) return try_to_overload(tbl); ! 13725: } ! 13726: } ! 13727: (void) t1->tsizeof(); ! 13728: break; ! 13729: } ! 13730: } ! 13731: ! 13732: //error('d',"check(%t,%t) -> %d",e1->tp,t2,try_to_coerce(t1,e2,"assignment",tbl)); ! 13733: { Pexpr x = try_to_coerce(t1,e2,"assignment",tbl); ! 13734: if (x) ! 13735: e2 = x; ! 13736: else if (e1->tp->check(t2,ASSIGN)) ! 13737: error("bad assignmentT:%t =%t",e1->tp,t2); ! 13738: else if ((t1 = t1->is_ptr()) && t1->memptr()) { ! 13739: if (t2 == zero_type) { ! 13740: Pexpr ee = new expr(ELIST,zero,zero); ! 13741: e2 = new expr(ILIST,ee,zero); ! 13742: } ! 13743: else if (t2->base==PTR && t2->memptr()) { ! 13744: // do nothing: structure assignment ! 13745: } ! 13746: else { ! 13747: Pexpr x = ptr_init(Pptr(t1),e2,tbl); ! 13748: if (x != e2) e2 = x; ! 13749: } ! 13750: } ! 13751: } ! 13752: t = e1->tp; // the type of the lhs ! 13753: break; ! 13754: case CM: ! 13755: case G_CM: ! 13756: t = t2; ! 13757: break; ! 13758: default: ! 13759: error('i',"unknown operator%k",b); ! 13760: } ! 13761: ! 13762: tp = t; ! 13763: return this; ! 13764: } ! 13765: 0707071010112044271004440001630000160000010200100466055401400001000000130600expr2.c /*ident "@(#)ctrans:src/expr2.c 1.5" */ ! 13766: /*************************************************************************** ! 13767: ! 13768: C++ source for cfront, the C++ compiler front-end ! 13769: written in the computer science research center of Bell Labs ! 13770: ! 13771: Copyright (c) 1984 AT&T, Inc. All rights Reserved ! 13772: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 13773: ! 13774: expr2.c: ! 13775: ! 13776: type check expressions ! 13777: ! 13778: ************************************************************************/ ! 13779: ! 13780: #include "cfront.h" ! 13781: #include "size.h" ! 13782: ! 13783: extern Pname conv_dominates(Pname,Pname); ! 13784: static int const_obj1,const_obj2; ! 13785: ! 13786: Pname really_dominate(Pname on1, Pname on2, bit tc) ! 13787: { ! 13788: Pfct f1 = on1->tp->base==FCT ? Pfct(on1->tp) : ! 13789: Pfct(Pgen(on1->tp)->fct_list->f->tp); ! 13790: Pfct f2 = on2->tp->base==FCT ? Pfct(on2->tp) : ! 13791: Pfct(Pgen(on2->tp)->fct_list->f->tp); ! 13792: ! 13793: // const check ! 13794: int c1 = f1->f_const; ! 13795: int c2 = f2->f_const; ! 13796: ! 13797: if(c1 == c2) ; ! 13798: else if(c1 && !c2) return tc ? on1 : on2; ! 13799: else if(c2 && !c1) return tc ? on2 : on1; ! 13800: ! 13801: // hierarchy check ! 13802: Pname on = conv_dominates(on1,on2); ! 13803: if(on) return on; ! 13804: else return 0; ! 13805: } ! 13806: ! 13807: void name::assign() ! 13808: { ! 13809: if (n_assigned_to++ == 0) { ! 13810: switch (n_scope) { ! 13811: case FCT: ! 13812: if (n_used && n_addr_taken==0) { ! 13813: Ptype t = tp; ! 13814: ll: ! 13815: switch (t->base) { ! 13816: case TYPE: ! 13817: t=Pbase(t)->b_name->tp; goto ll; ! 13818: case VEC: ! 13819: break; ! 13820: default: ! 13821: if (curr_loop) ! 13822: error('w',&where,"%n may have been used before set",this); ! 13823: else ! 13824: error('w',&where,"%n used before set",this); ! 13825: } ! 13826: } ! 13827: } ! 13828: } ! 13829: } ! 13830: ! 13831: void name::take_addr() ! 13832: { ! 13833: // error('d', "%n->take_addr tp: %t", this, tp?tp:0 ); ! 13834: // error('d', "%n->take_addr tp: %d %d", this, tp?tp:0, tp?tp->base:0 ); ! 13835: if ( (warning_opt) && (! n_addr_taken) && (tp) && (tp->base==FCT) && Pfct (tp)->f_inline) ! 13836: error('w',"can't take address of inline function %n, %n not inlined", this, this); ! 13837: n_addr_taken++; ! 13838: if ( n_sto == EXTERN && tp ) { ! 13839: Ptype t = tp; ! 13840: while ( t->base == TYPE ) ! 13841: t = Pbase(t)->b_name->tp; ! 13842: switch ( t->base ) { ! 13843: case COBJ: ! 13844: t = Pbase(t)->b_name->tp; // no break ! 13845: case CLASS: { ! 13846: Pclass cl = Pclass(t); ! 13847: if ( cl->c_body == 1 ) ! 13848: cl->dcl_print(0); ! 13849: } ! 13850: } ! 13851: } ! 13852: } ! 13853: ! 13854: int ignore_const; // for use by ref_init ! 13855: static is_dataMemPtr(Pexpr); ! 13856: ! 13857: int expr::lval(TOK oper) ! 13858: { ! 13859: register Pexpr ee = this; ! 13860: register Pname n; ! 13861: int deref = 0; ! 13862: char* es; ! 13863: ! 13864: //error('d',"%k expr::lval %k",base,oper); ! 13865: ! 13866: switch (oper) { ! 13867: case ADDROF: ! 13868: case G_ADDROF: es = "address of"; break; ! 13869: case DEREF: es = "dereference of"; break; ! 13870: case INCR: es = "increment of"; goto def; ! 13871: case DECR: es = "decrement of"; goto def; ! 13872: default: es = "assignment to"; ! 13873: def: ! 13874: if (ignore_const==0 && tp->tconst()) { ! 13875: if (oper) { ! 13876: if (base == NAME) { ! 13877: if (vec_const && Pname(this)->n_scope==ARG) break; ! 13878: error("%s constant%n",es,this); ! 13879: } ! 13880: else ! 13881: error("%s constant",es); ! 13882: } ! 13883: return 0; ! 13884: } ! 13885: } ! 13886: ! 13887: for(;;) { ! 13888: //error('d',"loop %k",ee->base); ! 13889: switch (ee->base) { ! 13890: // case G_CALL: ! 13891: // case CALL: ! 13892: default: ! 13893: defa: ! 13894: if (deref == 0) { ! 13895: if (oper) error("%s%k (not an lvalue)",es,ee->base); ! 13896: return 0; ! 13897: } ! 13898: return 1; ! 13899: case ZERO: ! 13900: case CCON: ! 13901: case ICON: ! 13902: case FCON: ! 13903: if (oper) error("%s numeric constant",es); ! 13904: return 0; ! 13905: case STRING: ! 13906: if (oper) error('w',"%s string constant",es); ! 13907: return 1; ! 13908: case CAST: ! 13909: switch( oper ) { ! 13910: case 0: ! 13911: case ADDROF: ! 13912: case G_ADDROF: ! 13913: case DEREF: ! 13914: goto defa; ! 13915: default: ! 13916: if ( ee->tp->base == PTR ! 13917: && is_dataMemPtr(ee) ) ! 13918: { // check for const class object ! 13919: Pexpr te; ! 13920: te = ee->e1->e1->e1; ! 13921: if ( te->base == G_ADDROF ) ! 13922: te = te->e2; ! 13923: if ( te->base == NAME ) { ! 13924: Ptype pt = te->tp; ! 13925: if ( pt->base == PTR ) ! 13926: pt = Pptr(pt)->typ; ! 13927: if ( pt->tconst() ) ! 13928: error("%sCMP of const%n",es,te); ! 13929: return 0; ! 13930: } ! 13931: } ! 13932: goto defa; ! 13933: } ! 13934: ! 13935: case DEREF: ! 13936: { ! 13937: Pexpr ee1 = ee->e1; ! 13938: // error( 'd', "ee1: %k", ee1->base ); ! 13939: switch (ee1->base) { // *& vanishes ! 13940: case ADDROF: // *& ! 13941: return 1; ! 13942: case G_CM: ! 13943: case CM: // look for *(a,&b) ! 13944: if (ee1->e2->base==G_ADDROF ! 13945: || ee1->e2->base==ADDROF) ! 13946: return 1; ! 13947: goto defaa; ! 13948: case QUEST: // look for *(q?&a:&b) ! 13949: if ((ee1->e1->base==G_ADDROF ! 13950: || ee1->e1->base==ADDROF) ! 13951: && (ee1->e2->base==G_ADDROF ! 13952: || ee1->e2->base==ADDROF)) ! 13953: return 1; ! 13954: // no break ! 13955: default: ! 13956: defaa: ! 13957: ee = ee1; ! 13958: deref = 1; ! 13959: } ! 13960: break; ! 13961: } ! 13962: ! 13963: case QUEST: ! 13964: { int x1 = ee->e1->lval(deref?0:oper); ! 13965: int x2 = ee->e2->lval(deref?0:oper); ! 13966: if (ee->e1->tp->check(ee->e2->tp,0)) return 0; ! 13967: if (deref) return 1; ! 13968: return x1 && x2; ! 13969: } ! 13970: ! 13971: case INCR: ! 13972: case DECR: ! 13973: if (e1) goto defa; // postfix does not preserve lval ! 13974: case ASSIGN: ! 13975: case ASPLUS: ! 13976: case ASMINUS: ! 13977: case ASMUL: ! 13978: case ASDIV: ! 13979: case ASMOD: ! 13980: case ASAND: ! 13981: case ASOR: ! 13982: case ASER: ! 13983: case ASLS: ! 13984: case ASRS: ! 13985: return 1; ! 13986: ! 13987: case CM: ! 13988: case G_CM: ! 13989: if (ee->e2->lval(deref?0:oper)==0) return deref; ! 13990: return 1; ! 13991: ! 13992: case MEMPTR: ! 13993: ee = ee->e2; ! 13994: break; ! 13995: ! 13996: case MDOT: ! 13997: ee = ee->mem; ! 13998: break; ! 13999: ! 14000: case DOT: ! 14001: { ! 14002: // error('d',"dot %k oper %k",ee->e1->base,oper); ! 14003: Pexpr e = 0; ! 14004: int e_const = 0; // to catch x.y.val = 1, where x is const ! 14005: ! 14006: switch (ee->e1->base) { // update use counts, etc. ! 14007: case NAME: ! 14008: switch (oper) { ! 14009: case ADDROF: ! 14010: case G_ADDROF: Pname(ee->e1)->take_addr(); ! 14011: case 0: break; ! 14012: case ASSIGN: Pname(ee->e1)->n_used--; ! 14013: default: Pname(ee->e1)->assign(); // asop ! 14014: } ! 14015: break; ! 14016: case DOT: ! 14017: e = ee->e1; ! 14018: do e=e->e1; while (e->base==DOT); ! 14019: if (e->base == NAME) { ! 14020: e_const = e->tp->tconst(); ! 14021: switch (oper) { ! 14022: case ADDROF: ! 14023: case G_ADDROF: Pname(e)->take_addr(); ! 14024: case 0: break; ! 14025: case ASSIGN: Pname(e)->n_used--; ! 14026: default: Pname(e)->assign(); // asop ! 14027: } ! 14028: } ! 14029: } ! 14030: ! 14031: n = Pname(ee->mem); ! 14032: while (n->base == MDOT) n = Pname(Pref(n)->mem); ! 14033: ! 14034: if (deref==0 && ! 14035: (ee->e1->tp->tconst() || e_const)) { ! 14036: ! 14037: switch (oper) { ! 14038: case 0: ! 14039: case ADDROF: ! 14040: case G_ADDROF: ! 14041: case DEREF: ! 14042: break; ! 14043: default: ! 14044: error("%sM%n of%t",es,n,e_const?e->tp:ee->e1->tp); ! 14045: } ! 14046: return 0; ! 14047: } ! 14048: } ! 14049: goto xx; ! 14050: ! 14051: case REF: ! 14052: n = Pname(ee->mem); ! 14053: while (n->base == MDOT) n = Pname(Pref(n)->mem); ! 14054: ! 14055: if (deref==0 && ee->e1) { //BR ! 14056: Ptype p = ee->e1->tp; ! 14057: zxc: ! 14058: switch (p->base) { ! 14059: case TYPE: p = Pbase(p)->b_name->tp; goto zxc; ! 14060: case PTR: ! 14061: case VEC: break; ! 14062: default: error('i',"expr::lval %t->%n",p,n); ! 14063: } ! 14064: if (Pptr(p)->typ->tconst()) { ! 14065: switch (oper) { ! 14066: case 0: ! 14067: case G_ADDROF: ! 14068: case DEREF: ! 14069: break; ! 14070: case ADDROF: ! 14071: if ( cm_const_save == 0 && const_ptr == 0 ) ! 14072: error(strict_opt?0:'w',"%sM%n of%t",es,n,Pptr(p)->typ); ! 14073: break; ! 14074: default: ! 14075: error("%sM%n of%t",es,n,Pptr(p)->typ); ! 14076: } ! 14077: return 0; ! 14078: } ! 14079: } ! 14080: goto xx; ! 14081: ! 14082: case NAME: ! 14083: n = Pname(ee); ! 14084: xx: ! 14085: // error('d',"name xx: %n oper %d lex_level: %d",n,oper,n->lex_level); ! 14086: if (deref) return 1; ! 14087: if (oper==0) return n->n_stclass != ENUM ; ! 14088: ! 14089: if (n->tp->base==FIELD && Pbase(n->tp)->b_bits==0) { ! 14090: error("%s 0-length field%n",es,n); ! 14091: return 0; ! 14092: } ! 14093: ! 14094: switch (oper) { ! 14095: case ADDROF: ! 14096: case G_ADDROF: ! 14097: { Pfct f = (Pfct)n->tp; ! 14098: ! 14099: if (n->n_sto == REGISTER) { ! 14100: if (warning_opt) error('w',"& register%n",n); ! 14101: // return 0; ! 14102: n->n_sto = 0; ! 14103: n->n_stclass = AUTO; ! 14104: } ! 14105: ! 14106: if (f == 0) { ! 14107: error("& label%n",n); ! 14108: return 0; ! 14109: } ! 14110: ! 14111: if (n->n_stclass == ENUM) { ! 14112: error("& enumerator%n",n); ! 14113: return 0; ! 14114: } ! 14115: ! 14116: if (n->tp->base == FIELD) { ! 14117: error("& field%n",n); ! 14118: return 0; ! 14119: } ! 14120: ! 14121: n->n_used--; ! 14122: if (n->n_qualifier) { // oops, not the real one ! 14123: Pname tn = Pclass(n->n_table->t_name->tp)->memtbl->look(n->string,0); ! 14124: n = tn ? tn : n; ! 14125: } ! 14126: n->take_addr(); ! 14127: ! 14128: // suppress hoisting of local consts ! 14129: int statmem = n->n_scope==0 || n->n_scope==PUBLIC || n->n_scope == FCT; ! 14130: if (n->n_evaluated && n->n_scope!=ARG) { // &const ! 14131: if (statmem == 0 && n->n_dcl_printed==0) { ! 14132: n->n_initializer = new ival(n->n_val); ! 14133: n->dcl_print(0); ! 14134: } ! 14135: } ! 14136: else if (f->base==FCT && n->n_dcl_printed==0) ! 14137: n->dcl_print(0); ! 14138: break; ! 14139: } ! 14140: ! 14141: case ASSIGN: ! 14142: //error('d',"ass %n %d",n,n->n_used); ! 14143: n->n_used--; ! 14144: n->assign(); ! 14145: break; ! 14146: // goto check_void; ! 14147: default: /* incr ops, and asops */ ! 14148: if (cc->tot && n==cc->c_this) { ! 14149: error("%n%k",n,oper); ! 14150: return 0; ! 14151: } ! 14152: // check_void: ! 14153: // { Ptype t = n->tp; ! 14154: // while (t->base==TYPE) t = Pbase(t)->b_name->tp; ! 14155: // if (t==Pvoid_type) { ! 14156: // error("%s%t",es,n->tp); ! 14157: // return 0; ! 14158: // } ! 14159: // } ! 14160: n->assign(); ! 14161: } ! 14162: return 1; ! 14163: } ! 14164: } ! 14165: } ! 14166: ! 14167: int char_to_int(char* s) ! 14168: /* assume s points to a string: ! 14169: 'c' ! 14170: or '\c' ! 14171: or '\0' ! 14172: or '\ddd' ! 14173: or multi-character versions of the above ! 14174: (hex constants have been converted to octal by the parser) ! 14175: */ ! 14176: { ! 14177: register int i = 0; ! 14178: register char c, d, e; ! 14179: ! 14180: switch (*s) { ! 14181: default: ! 14182: error('i',"char constant store corrupted"); ! 14183: case '`': ! 14184: error("bcd constant"); ! 14185: return 0; ! 14186: case '\'': ! 14187: break; ! 14188: } ! 14189: ! 14190: for(;;) /* also handle multi-character constants */ ! 14191: switch (c = *++s) { ! 14192: case '\'': ! 14193: return i; ! 14194: case '\\': /* special character */ ! 14195: switch (c = *++s) { ! 14196: case '0': case '1': case '2': case '3': case '4': ! 14197: case '5': case '6': case '7': /* octal representation */ ! 14198: c -= '0'; ! 14199: switch (d = *++s) { /* try for 2 */ ! 14200: ! 14201: case '0': case '1': case '2': case '3': case '4': ! 14202: case '5': case '6': case '7': ! 14203: d -= '0'; ! 14204: switch (e = *++s) { /* try for 3 */ ! 14205: ! 14206: case '0': case '1': case '2': case '3': case '4': ! 14207: case '5': case '6': case '7': ! 14208: c = c*64+d*8+e-'0'; ! 14209: break; ! 14210: default: ! 14211: c = c*8+d; ! 14212: s--; ! 14213: } ! 14214: break; ! 14215: default: ! 14216: s--; ! 14217: } ! 14218: break; ! 14219: case 'a': ! 14220: c = '\a'; ! 14221: break; ! 14222: case 'b': ! 14223: c = '\b'; ! 14224: break; ! 14225: case 'f': ! 14226: c = '\f'; ! 14227: break; ! 14228: case 'n': ! 14229: c = '\n'; ! 14230: break; ! 14231: case 'r': ! 14232: c = '\r'; ! 14233: break; ! 14234: case 't': ! 14235: c = '\t'; ! 14236: break; ! 14237: case 'v': ! 14238: c = '\v'; ! 14239: break; ! 14240: case '\\': ! 14241: c = '\\'; ! 14242: break; ! 14243: case '\'': ! 14244: c = '\''; ! 14245: break; ! 14246: } ! 14247: /* no break */ ! 14248: default: ! 14249: if (i) i <<= BI_IN_BYTE; ! 14250: i += c; ! 14251: } ! 14252: } ! 14253: ! 14254: const A10 = 'A'-10; ! 14255: const a10 = 'a'-10; ! 14256: ! 14257: long str_to_long(register const char* p) ! 14258: { ! 14259: register c; ! 14260: register unsigned long i= 0; ! 14261: const char* pp = p; ! 14262: ! 14263: // error( 'd', "str_to_long: %s", p ); ! 14264: ! 14265: if ((c=*p++) == '0') { ! 14266: switch (c = *p++) { ! 14267: case 0: ! 14268: return 0; ! 14269: ! 14270: case 'l': ! 14271: case 'L': /* long zero */ ! 14272: return 0; ! 14273: ! 14274: case 'x': ! 14275: case 'X': /* hexadecimal */ ! 14276: while (c=*p++) { ! 14277: switch (c) { ! 14278: case 'l': ! 14279: case 'L': ! 14280: case 'U': ! 14281: case 'u': ! 14282: return i; ! 14283: case 'A': ! 14284: case 'B': ! 14285: case 'C': ! 14286: case 'D': ! 14287: case 'E': ! 14288: case 'F': ! 14289: i = i*16 + c-A10; ! 14290: break; ! 14291: case 'a': ! 14292: case 'b': ! 14293: case 'c': ! 14294: case 'd': ! 14295: case 'e': ! 14296: case 'f': ! 14297: i = i*16 + c-a10; ! 14298: break; ! 14299: default: ! 14300: i = i*16 + c-'0'; ! 14301: } ! 14302: } ! 14303: return i; ! 14304: ! 14305: default: /* octal */ ! 14306: do ! 14307: switch (c) { ! 14308: case 'l': ! 14309: case 'L': ! 14310: case 'U': ! 14311: case 'u': ! 14312: return i; ! 14313: default: ! 14314: i = i*8 + c-'0'; ! 14315: } ! 14316: while (c=*p++); ! 14317: return i; ! 14318: } ! 14319: } ! 14320: /* decimal */ ! 14321: i = c-'0'; ! 14322: while (c=*p++) ! 14323: switch (c) { ! 14324: case 'l': ! 14325: case 'L': ! 14326: case 'U': ! 14327: case 'u': ! 14328: return i; ! 14329: default: ! 14330: { unsigned long ii = i; ! 14331: i = i*10 + c-'0'; ! 14332: if (i<ii) goto bad; ! 14333: } ! 14334: } ! 14335: return i; ! 14336: bad: ! 14337: error("integer constant %s larger than the largest long",pp); ! 14338: return i; ! 14339: ! 14340: ! 14341: } ! 14342: ! 14343: bit type::is_unsigned() ! 14344: { ! 14345: Ptype t = this; ! 14346: while (t->base==TYPE) t = Pbase(t)->b_name->tp; ! 14347: if (t->base == PTR) return 0; ! 14348: return Pbase(t)->b_unsigned; ! 14349: } ! 14350: ! 14351: char* Neval; ! 14352: bit binary_val; ! 14353: ! 14354: unsigned long expr::ueval(long x1, long x2) ! 14355: { ! 14356: unsigned long i1 = (unsigned long) x1; ! 14357: unsigned long i2 = (unsigned long) x2; ! 14358: //error('d',"ueval %k %ld %ld",base,x1,x2); ! 14359: switch (base) { ! 14360: case UMINUS: return -i2; ! 14361: case UPLUS: return i2; ! 14362: case NOT: return !i2; ! 14363: case COMPL: return ~i2; ! 14364: case CAST: return i1; ! 14365: case PLUS: return i1+i2; ! 14366: case MINUS: return i1-i2; ! 14367: case MUL: return i1*i2; ! 14368: case LS: return i1<<i2; ! 14369: case RS: return i1>>i2; ! 14370: case NE: return i1!=i2; ! 14371: case EQ: return i1==i2; ! 14372: case LT: return i1<i2; ! 14373: case LE: return i1<=i2; ! 14374: case GT: return i1>i2; ! 14375: case GE: return i1>=i2; ! 14376: case AND: return i1&i2; ! 14377: case ANDAND: return i1&&i2; ! 14378: case OR: return i1|i2; ! 14379: case OROR: return i1||i2; ! 14380: case ER: return i1^i2; ! 14381: case MOD: if (i2 == 0) { ! 14382: if (Neval == 0) { ! 14383: Neval = "mod zero"; ! 14384: error("mod zero"); ! 14385: } ! 14386: return 1; ! 14387: } ! 14388: return i1%i2; ! 14389: case QUEST: return (cond->eval()) ? i1 : i2; ! 14390: case DIV: if (i2 == 0) { ! 14391: if (Neval == 0) { ! 14392: Neval = "divide by zero"; ! 14393: error("divide by zero"); ! 14394: } ! 14395: return 1; ! 14396: } ! 14397: return i1/i2; ! 14398: case CM: ! 14399: case G_CM: ! 14400: return i2; ! 14401: } ! 14402: ! 14403: Neval = "unsigned expression"; ! 14404: return 0; ! 14405: } ! 14406: ! 14407: long expr::eval() ! 14408: { ! 14409: if (Neval) return 1; ! 14410: // error('d',"eval %k",base); ! 14411: ! 14412: static int targno=0; ! 14413: static int icallflag=0; ! 14414: ! 14415: switch (base) { ! 14416: case ZERO: return 0; ! 14417: case IVAL: return i1; ! 14418: case ICON: return str_to_long(string); ! 14419: case CCON: return char_to_int(string); ! 14420: case FCON: Neval = "float in constant expression"; return 1; ! 14421: case STRING: Neval = "string in constant expression"; return 1; ! 14422: case EOBJ: return Pname(this)->n_val; ! 14423: case SIZEOF: ! 14424: extern no_sizeof; ! 14425: if (no_sizeof) Neval = "sizeof"; ! 14426: return tp2->tsizeof(); ! 14427: ! 14428: case NAME: ! 14429: { Pname n = Pname(this); ! 14430: // error('d',"eval %n eval %d %d",n,n->n_evaluated,n->n_val); ! 14431: // error('d',"eval tp->tconst() %d, n->n_initializer: %k", n->tp->tconst(), n->n_initializer?n->n_initializer->base:0 ); ! 14432: if (n->n_evaluated && n->n_scope!=ARG) return n->n_val; ! 14433: if (binary_val && strcmp(string,"_result")==0) return 8888; ! 14434: Neval = "cannot evaluate constant"; ! 14435: return 1; ! 14436: } ! 14437: case ICALL: ! 14438: if (e1) { ! 14439: icallflag=1; ! 14440: targno=0; ! 14441: il->i_next = curr_icall; ! 14442: curr_icall = il; ! 14443: long i = e1->eval(); ! 14444: curr_icall = il->i_next; ! 14445: icallflag=0; ! 14446: return i; ! 14447: } ! 14448: Neval = "void inlineF"; ! 14449: return 1; ! 14450: case ANAME: ! 14451: { Pname n = (Pname)this; ! 14452: ! 14453: /* ! 14454: int argno; ! 14455: if (icallflag) { ! 14456: argno=targno; ! 14457: targno++; ! 14458: } ! 14459: */ ! 14460: int argno = (int) n->n_val; ! 14461: ! 14462: Pin il; ! 14463: for (il=curr_icall; il; il=il->i_next) ! 14464: if (il->i_table == n->n_table) goto aok; ! 14465: goto bok; ! 14466: aok: ! 14467: if (il->i_args[argno].local) { ! 14468: bok: ! 14469: Neval = "inlineF call too complicated for constant expression"; ! 14470: return 1; ! 14471: } ! 14472: Pexpr aa = il->i_args[argno].arg; ! 14473: return aa->eval(); ! 14474: } ! 14475: case CAST: ! 14476: { if (e1->base==FCON && tp2->base!=FLOAT && tp2->base!=DOUBLE) { ! 14477: char* p = e1->string; ! 14478: while (*p!='.') p++; ! 14479: if (p==e1->string) *p++ = '0'; ! 14480: *p = 0; ! 14481: e1->base = ICON; ! 14482: } ! 14483: long i = e1->eval(); ! 14484: Ptype tt = tp2; ! 14485: strip: ! 14486: switch (tt->base) { ! 14487: default: ! 14488: Neval = "cast to non-integral type in constant expression"; ! 14489: break; ! 14490: case TYPE: ! 14491: tt = Pbase(tt)->b_name->tp; ! 14492: goto strip; ! 14493: case EOBJ: ! 14494: case LONG: ! 14495: case INT: ! 14496: case CHAR: ! 14497: case SHORT: ! 14498: i &= ~(((~(unsigned long)0)<<(BI_IN_BYTE*(tp2->tsizeof()-1)))<<BI_IN_BYTE); ! 14499: break; ! 14500: } ! 14501: return i; ! 14502: } ! 14503: case UMINUS: ! 14504: case UPLUS: ! 14505: case NOT: ! 14506: case COMPL: ! 14507: case PLUS: ! 14508: case MINUS: ! 14509: case MUL: ! 14510: case LS: ! 14511: case RS: ! 14512: case NE: ! 14513: case LT: ! 14514: case LE: ! 14515: case GT: ! 14516: case GE: ! 14517: case AND: ! 14518: case OR: ! 14519: case ER: ! 14520: case DIV: ! 14521: case MOD: ! 14522: case QUEST: ! 14523: case EQ: ! 14524: case ANDAND: ! 14525: break; ! 14526: case OROR: ! 14527: if (binary_val) { // a||b, don't evaluate b if a!=0 ! 14528: long i1 = (e1) ? e1->eval() : 0; ! 14529: if (Neval==0 && i1 && e1->tp->is_unsigned()==0) return i1; ! 14530: } ! 14531: break; ! 14532: case CM: ! 14533: case G_CM: ! 14534: break; ! 14535: case G_ADDROF: ! 14536: case ADDROF: ! 14537: if (binary_val) { // beware of &*(T*)0 ! 14538: switch (e2->base) { ! 14539: case NAME: ! 14540: case DOT: ! 14541: case REF: return 9999; ! 14542: } ! 14543: } ! 14544: default: ! 14545: Neval = "bad operator in constant expression"; ! 14546: return 1; ! 14547: } ! 14548: ! 14549: long i1 = (e1) ? e1->eval() : 0; ! 14550: long i2 = (e2) ? e2->eval() : 0; ! 14551: ! 14552: if (binary_val && i1==9999 && i2==9999) { ! 14553: Neval = ""; ! 14554: return 1; ! 14555: } ! 14556: ! 14557: if (Neval==0 ! 14558: && ((e1&&e1->tp->is_unsigned()) || (e2&&e2->tp->is_unsigned()))) ! 14559: return (long) ueval(i1,i2); ! 14560: ! 14561: switch (base) { ! 14562: case UMINUS: return -i2; ! 14563: case UPLUS: return i2; ! 14564: case NOT: return !i2; ! 14565: case COMPL: return ~i2; ! 14566: case CAST: return i1; ! 14567: case PLUS: return i1+i2; ! 14568: case MINUS: return i1-i2; ! 14569: case MUL: return i1*i2; ! 14570: case LS: return i1<<i2; ! 14571: case RS: return i1>>i2; ! 14572: case NE: return i1!=i2; ! 14573: case EQ: return i1==i2; ! 14574: case LT: return i1<i2; ! 14575: case LE: return i1<=i2; ! 14576: case GT: return i1>i2; ! 14577: case GE: return i1>=i2; ! 14578: case AND: return i1&i2; ! 14579: case ANDAND: return i1&&i2; ! 14580: case OR: return i1|i2; ! 14581: case OROR: return i1||i2; ! 14582: case ER: return i1^i2; ! 14583: case MOD: if (i2 == 0) { ! 14584: if (Neval == 0) { ! 14585: Neval = "mod zero"; ! 14586: error("mod zero"); ! 14587: } ! 14588: return 1; ! 14589: } ! 14590: return i1%i2; ! 14591: case QUEST: return (cond->eval()) ? i1 : i2; ! 14592: case DIV: if (i2 == 0) { ! 14593: if (Neval == 0) { ! 14594: Neval = "divide by zero"; ! 14595: error("divide by zero"); ! 14596: } ! 14597: return 1; ! 14598: } ! 14599: return i1/i2; ! 14600: case CM: ! 14601: case G_CM: ! 14602: return i2; ! 14603: } ! 14604: } ! 14605: bit classdef::baseof(Pname f) ! 14606: /* ! 14607: is ``this'' class a public base class of "f"'s class ! 14608: or its immediate base class ! 14609: */ ! 14610: { ! 14611: Ptable ctbl = f->n_table; ! 14612: Pname b = ctbl->t_name; ! 14613: ! 14614: if (b == 0) return 0; ! 14615: Pclass cl = Pclass(b->tp); ! 14616: if (cl == 0) return 0; ! 14617: if (cl == this) return 1; ! 14618: ppbase = PUBLIC; ! 14619: Pclass bcl = is_base(cl->string); ! 14620: return (bcl && ppbase==PUBLIC); ! 14621: } ! 14622: ! 14623: bit classdef::baseof(Pclass cl) ! 14624: /* ! 14625: is ``this'' class a public base class of "cl" ! 14626: */ ! 14627: { ! 14628: if (cl == 0) return 0; ! 14629: if (cl == this) return 1; ! 14630: ppbase = PUBLIC; ! 14631: Pclass bcl = is_base(cl->string); ! 14632: return (bcl && ppbase==PUBLIC); ! 14633: } ! 14634: ! 14635: static int mem_match(Pfct f1, Pfct f2) ! 14636: /* ! 14637: check class membership. ! 14638: ! 14639: For some reason checking f_this==0 works and f_static doesn't ! 14640: */ ! 14641: { ! 14642: // if (f1->memof) return f2->f_this ?f2->memof==f1->memof : 0; ! 14643: // if (f1 && f1->memof) return f2->f_this?f2->memof==f1->memof : 0; ! 14644: // return f2->f_this==0; ! 14645: if (f1==0 || f2==0) return 0; ! 14646: if (f1->memof && f2->f_this && f2->memof!=f1->memof) return 0; ! 14647: if (f2->f_this) return 0; ! 14648: if (f1->memof && f2->f_static) return 0; ! 14649: if (f1->check(f2,ASSIGN)) return 0; ! 14650: return 1; ! 14651: } ! 14652: ! 14653: int Pchecked; ! 14654: ! 14655: Pexpr ptof(Pfct ef, Pexpr e, Ptable tbl) ! 14656: /* ! 14657: a kludge: initialize/assign-to pointer to function ! 14658: */ ! 14659: { ! 14660: Pfct f; ! 14661: Pname n = 0; ! 14662: eee: ! 14663: //error('d',"ptof %t %t %k",ef,e->tp,e->base); ! 14664: switch (e->base) { ! 14665: case QUEST: ! 14666: e->e1 = ptof(ef,e->e1,tbl); ! 14667: e->e2 = ptof(ef,e->e2,tbl); ! 14668: return e; ! 14669: case CM: ! 14670: case G_CM: ! 14671: e->e2 = ptof(ef,e->e2,tbl); ! 14672: return e; ! 14673: case NAME: ! 14674: f = Pfct(e->tp); ! 14675: Pname nn = Pname(e); ! 14676: ! 14677: switch (f->base) { ! 14678: case OVERLOAD: ! 14679: e = Pgen(f)->find(ef,0); ! 14680: if (e == 0) { ! 14681: error("cannot deduceT for &overloaded%n",nn); ! 14682: return e; ! 14683: } ! 14684: // e = n; ! 14685: // no break ! 14686: case FCT: ! 14687: Pchecked = mem_match(ef,Pfct(e->tp)); ! 14688: e = new expr(G_ADDROF,0,e); ! 14689: return e->typ(tbl); // handle &B::f ! 14690: //e->tp = f; ! 14691: } ! 14692: goto ad; ! 14693: ! 14694: case ZERO: ! 14695: if (ef->memof) { ! 14696: e = new expr(ELIST,zero,zero); ! 14697: e = new expr(ILIST,e,zero); ! 14698: e->tp = zero_type; ! 14699: return e; ! 14700: } ! 14701: break; ! 14702: ! 14703: case MDOT: ! 14704: // ?? error('s',"P toM of not firstB"); ! 14705: do e = e->mem; while (e->base == MDOT); ! 14706: goto eee; ! 14707: ! 14708: case DOT: ! 14709: case REF: ! 14710: f = Pfct(e->mem->tp); ! 14711: ! 14712: switch (f->base) { ! 14713: case OVERLOAD: ! 14714: n = Pgen(f)->find(ef,0); ! 14715: if (n == 0) error("cannot deduceT for &overloaded%n",e->mem); ! 14716: else e = n; ! 14717: // no break ! 14718: case FCT: ! 14719: Pchecked = mem_match(ef,Pfct(e->tp)); ! 14720: e = new expr(G_ADDROF,0,e); ! 14721: return e->typ(tbl); // handle &B::f ! 14722: // n = Pname(e->mem); ! 14723: // e = n->address(); ! 14724: } ! 14725: goto ad; ! 14726: ! 14727: case ADDROF: ! 14728: case G_ADDROF: ! 14729: f = Pfct(e->e2->tp); ! 14730: ad: ! 14731: if (f->base == OVERLOAD) { ! 14732: n = Pgen(f)->find(ef,0); ! 14733: if (n == 0) error("cannot deduceT for &overloaded %s()",Pgen(f)->fct_list->f->string); ! 14734: Pchecked = mem_match(ef,Pfct(n->tp)); ! 14735: e->e2 = n; ! 14736: e->tp = n->tp; ! 14737: } ! 14738: if (n) n->lval(ADDROF); ! 14739: break; ! 14740: ! 14741: case CAST: ! 14742: { ! 14743: Pexpr te = e->e1; ! 14744: if (e->e1->base == G_ADDROF) te = e->e1->e2; ! 14745: (void) ptof(ef,te,tbl); ! 14746: } ! 14747: } ! 14748: return e; ! 14749: } ! 14750: ! 14751: Pexpr ptr_init(Pptr p, Pexpr init, Ptable tbl) ! 14752: /* ! 14753: check for silly initializers ! 14754: ! 14755: char* p = 0L; ?? fudge to allow redundant and incorrect `L' ! 14756: char* p = 2 - 2; ?? worse ! 14757: */ ! 14758: { ! 14759: // error('d',"ptr_init: p=%t init->tp=%t init->base %k",p,init->tp,init->base); ! 14760: ! 14761: Pchecked = 0; ! 14762: ! 14763: Ptype it = init->tp; ! 14764: itl: ! 14765: switch (it->base) { ! 14766: case TYPE: ! 14767: it = Pbase(it)->b_name->tp; goto itl; ! 14768: case ZTYPE: ! 14769: // if (init == zero) break; ! 14770: break; ! 14771: case EOBJ: ! 14772: case INT: ! 14773: case CHAR: ! 14774: case SHORT: ! 14775: case LONG: ! 14776: { Neval = 0; ! 14777: long i = init->eval(); ! 14778: if (Neval) ! 14779: error("badPIr: %s",Neval); ! 14780: else ! 14781: if (i) ! 14782: error("badPIr value %d",i); ! 14783: else { ! 14784: DEL(init); ! 14785: init = zero; ! 14786: } ! 14787: break; ! 14788: } ! 14789: } ! 14790: ! 14791: Pclass c1 = p->memof; ! 14792: ! 14793: if (c1) { ! 14794: if (init==zero) ! 14795: ; ! 14796: else { ! 14797: Pclass c2; ! 14798: // error('d',"it %t %d",it,it->base); ! 14799: switch (it->base) { ! 14800: case FCT: ! 14801: c2 = Pfct(it)->memof; ! 14802: break; ! 14803: case OVERLOAD: ! 14804: c2 = Pfct(Pgen(it)->fct_list->f->tp)->memof; ! 14805: break; ! 14806: case PTR: ! 14807: case RPTR: ! 14808: c2 = Pptr(it)->memof; ! 14809: break; ! 14810: default: ! 14811: c2 = 0; ! 14812: } ! 14813: ! 14814: if (c2 == 0) { ! 14815: // initialization by &A::f ! 14816: //error('d',"curious"); ! 14817: } ! 14818: else if (c1 != c2) { ! 14819: Nptr = 0; ! 14820: Noffset = 0; ! 14821: vcllist->clear(); ! 14822: vcllist=0; ! 14823: int u1 = is_unique_base(c1,c2->string,0); ! 14824: //error('d',"c1 %t c2 %t u1 %d off %d",c1,c2,u1,Noffset); ! 14825: if (u1 && (Nptr || Noffset)) { ! 14826: // requires offset manipulation ! 14827: int bad = 0; ! 14828: if (u1 == 1 && !Nptr) { ! 14829: if (init->base==ILIST) { ! 14830: // d = d+Noffset; ! 14831: switch (init->e1->e1->base) { ! 14832: case IVAL: ! 14833: init->e1->e1->i1 += Noffset; ! 14834: break; ! 14835: case ZERO: ! 14836: init->e1->e1 = new ival(Noffset); ! 14837: break; ! 14838: default: ! 14839: bad = 1; ! 14840: } ! 14841: ! 14842: // if (i<0) f = vptroffset ! 14843: switch (init->e1->e2->base) { ! 14844: case IVAL: ! 14845: if (0<init->e1->e2->i1) { ! 14846: // extern Ptype Pfct_type; ! 14847: // store vptr offset ! 14848: // init->e2=new cast(Pfct_type,zero); ! 14849: } ! 14850: else ! 14851: break; ! 14852: default: ! 14853: bad = 1; ! 14854: } ! 14855: } // end if (init->base==ILIST) ! 14856: else ! 14857: bad = 1; ! 14858: } // end if (u1 == 1 ... ! 14859: else ! 14860: bad = 1; ! 14861: ! 14862: if (bad) error('s',"%t assigned to %t (too complicated)",init->tp,p); ! 14863: } // end if (u1 && ... ! 14864: ! 14865: Nptr = 0; ! 14866: Noffset = 0; ! 14867: vcllist->clear(); ! 14868: vcllist=0; ! 14869: int u2 = is_unique_base(c2,c1->string,0); ! 14870: //error('d',"c1 %t c2 %t u2 %d off %d",c1,c2,u2,Noffset); ! 14871: if (u2 && (Nptr || Noffset)) { ! 14872: // requires offset manipulation ! 14873: error('s',"%t assigned to %t",init->tp,p); ! 14874: } ! 14875: } // end if (c1 != c2 ! 14876: } // end else ! 14877: } // end if (c1) ! 14878: ! 14879: Ptype pit = p->typ; ! 14880: lll: ! 14881: // error('d',"p %t pit %t",p,pit); ! 14882: switch (pit->base) { ! 14883: case TYPE: ! 14884: pit = Pbase(pit)->b_name->tp; ! 14885: goto lll; ! 14886: case FCT: ! 14887: return ptof(Pfct(pit),init,tbl); ! 14888: case COBJ: ! 14889: { Pptr r; ! 14890: // error('d',"cobj: ptr %t, ref %t",it->is_ptr(),it->is_ref()); ! 14891: if (r=it->is_ptr_or_ref()) { ! 14892: Pchecked = 1; ! 14893: TOK b = p->base; // could be REF ! 14894: TOK bb = r->base; ! 14895: if (b==RPTR) p->base = PTR; ! 14896: if (bb==RPTR) r->base = PTR; ! 14897: if (p->check(r,ASSIGN)) { ! 14898: if ( cc && cc->nof && ! 14899: Pfct(cc->nof->tp)->f_const && ! 14900: cc->c_this == init ) ! 14901: error("%n const: assignment of%n (%t) to%t",cc->nof,init,init->tp,p); ! 14902: else ! 14903: error("no standard conversion of %t to %t",init->tp,p); ! 14904: } ! 14905: p->base = b; ! 14906: r->base = bb; ! 14907: Pexpr cp = cast_cptr(Pclass(Pbase(pit)->b_name->tp),init,tbl,0); ! 14908: if (cp != init) { ! 14909: PERM(p); // or else it will be deleted twice! ! 14910: return new cast(p,cp); ! 14911: } ! 14912: } ! 14913: // no break ! 14914: } ! 14915: default: ! 14916: return init; ! 14917: } ! 14918: } ! 14919: ! 14920: static Pname Lcoerce, Rcoerce; ! 14921: extern int suppress_error; ! 14922: ! 14923: int try_to_demote(TOK oper, Ptype t1, Ptype t2) ! 14924: /* ! 14925: look at t1 and t2 and see if there are ``demotions'' of t1 and/or t2 ! 14926: so that ``t1 oper t2'' can be made legal ! 14927: ! 14928: return 0 is not ! 14929: 1 if there is exactly one way ! 14930: >1 if there is more than one way (if in doubt return 2) ! 14931: */ ! 14932: { ! 14933: //error('d',"try_to_demote(%k : %t : %t)",oper,t1,t2); ! 14934: ! 14935: Pname n1 = t1 ? t1->is_cl_obj() : 0; ! 14936: Pclass c1 = n1 ? Pclass(n1->tp) : 0; ! 14937: Pname n2 = t2 ? t2->is_cl_obj() : 0; ! 14938: Pclass c2 = n2 ? Pclass(n2->tp) : 0; ! 14939: ! 14940: Ptype lt = t1; ! 14941: Ptype rt = t2; ! 14942: ! 14943: Lcoerce = Rcoerce = 0; ! 14944: ! 14945: // if (oper == DOT) return 0; ! 14946: ! 14947: if (c1) ! 14948: switch (oper) { ! 14949: case ASSIGN: ! 14950: case ASPLUS: ! 14951: case ASMINUS: ! 14952: case ASMUL: ! 14953: case ASDIV: ! 14954: case ASMOD: ! 14955: case ASAND: ! 14956: case ASOR: ! 14957: case ASER: ! 14958: case ASLS: ! 14959: case ASRS: // don't coerce left hand side of assignment ! 14960: // c1 = 0; ! 14961: if (c1->memtbl->look("__as",0)) return 0; ! 14962: } ! 14963: else ! 14964: switch (oper) { ! 14965: case ADDROF: ! 14966: case INCR: ! 14967: case DECR: // don't coerce unary requiring an lval ! 14968: return 0; ! 14969: } ! 14970: ! 14971: if (c1) { ! 14972: //error('d',"c1 %t",c1); ! 14973: for (Pname on1 = c1->conv; on1; on1=on1->n_list) { ! 14974: // error( 'd', "on1: %s tp: %k", on1->string, on1->tp->base ); ! 14975: Pfct f = Pfct(on1->tp); ! 14976: lt = f->base==FCT ? f->returns : ! 14977: Pfct(Pgen(on1->tp)->fct_list->f->tp)->returns; ! 14978: Pname cn = lt->is_cl_obj(); ! 14979: ! 14980: if (cn && (Lcoerce==0 || Lcoerce->tp->check(f,0))) { ! 14981: Pclass cl = Pclass(cn->tp); ! 14982: Pname n = cl->has_oper(oper); ! 14983: if (n == 0) continue; ! 14984: // while (n->base==REF || n->base==MDOT) n=Pname(n->mem) ; ! 14985: Pfct nf = Pfct(n->tp); ! 14986: // error( 'd', "nf: %d %k", nf->base, nf->base ); ! 14987: if (nf->base == FCT) { ! 14988: if (nf->nargs==1 ! 14989: && t2 ! 14990: && (nf->argtype->tp->check(t2,ARG)==0 ! 14991: || can_coerce(nf->argtype->tp,t2)==1) ! 14992: ) { ! 14993: if (Lcoerce) return 2; ! 14994: Lcoerce = on1; ! 14995: } ! 14996: } ! 14997: else { ! 14998: for (Plist gl=Pgen(nf)->fct_list; gl; gl=gl->l) { ! 14999: Pfct nf = Pfct(gl->f->tp); ! 15000: if (nf->nargs==1 ! 15001: && t2 ! 15002: && (nf->argtype->tp->check(t2,ARG)==0 ! 15003: || can_coerce(nf->argtype->tp,t2)==1) ! 15004: ) { ! 15005: if (Lcoerce) return 2; ! 15006: Lcoerce = on1; ! 15007: } ! 15008: } ! 15009: } ! 15010: continue; ! 15011: } ! 15012: //if (lt->is_cl_obj()) continue; ! 15013: if (c2) { ! 15014: //error('d',"c2 %t",c2); ! 15015: for (Pname on2 = c2->conv; on2; on2=on2->n_list) { ! 15016: Pfct f = Pfct(on2->tp); ! 15017: rt = f->base==FCT ? f->returns : ! 15018: Pfct(Pgen(on2->tp)->fct_list->f->tp)->returns; ! 15019: if (rt->is_cl_obj()) continue; ! 15020: ! 15021: suppress_error = 1; ! 15022: int r1 = lt->kind(oper,0); ! 15023: int r2 = rt->kind(oper,0); ! 15024: if (np_promote(oper,r1,r2,lt,rt,1)!=any_type) { ! 15025: Pname sn = on1; ! 15026: if (Lcoerce) { ! 15027: Pname tn = really_dominate( ! 15028: Lcoerce, ! 15029: on1, ! 15030: const_obj1 ! 15031: ); ! 15032: if(!tn) { ! 15033: suppress_error = 0; ! 15034: return 2; ! 15035: } ! 15036: else sn = tn; ! 15037: } ! 15038: Lcoerce = sn; ! 15039: Rcoerce = on2; ! 15040: ! 15041: } ! 15042: suppress_error = 0; ! 15043: } ! 15044: ! 15045: } ! 15046: else if (rt) { ! 15047: suppress_error = 1; ! 15048: int r1 = lt->kind(oper,0); ! 15049: int r2 = rt->kind(oper,0); ! 15050: if (np_promote(oper,r1,r2,lt,rt,1)!=any_type) { ! 15051: Pname sn = on1; ! 15052: if (Lcoerce) { ! 15053: Pname tn = really_dominate( ! 15054: Lcoerce, ! 15055: on1, ! 15056: const_obj1 ! 15057: ); ! 15058: if(!tn) { ! 15059: suppress_error = 0; ! 15060: return 2; ! 15061: } ! 15062: else sn = tn; ! 15063: } ! 15064: Lcoerce = sn; ! 15065: } ! 15066: suppress_error = 0; ! 15067: } ! 15068: else { ! 15069: Pname sn = on1; ! 15070: if (Lcoerce) { ! 15071: Pname tn = really_dominate( ! 15072: Lcoerce, ! 15073: on1, ! 15074: const_obj1 ! 15075: ); ! 15076: if(!tn) return 2; ! 15077: else sn = tn; ! 15078: } ! 15079: Lcoerce = sn; ! 15080: } ! 15081: } ! 15082: } ! 15083: else if (c2) { ! 15084: //error('d',"c2 %n",c2); ! 15085: for (Pname on = c2->conv; on; on=on->n_list) { ! 15086: Pfct f = Pfct(on->tp); ! 15087: rt = f->base==FCT ? f->returns : ! 15088: Pfct(Pgen(on->tp)->fct_list->f->tp)->returns; ! 15089: Pname cn = rt->is_cl_obj(); ! 15090: //error('d',"cn %n",cn); ! 15091: if (cn && (Rcoerce==0 || Rcoerce->tp->check(f,0))) { ! 15092: Pclass cl = Pclass(cn->tp); ! 15093: Pname n = cl->has_oper(oper); ! 15094: if (n == 0) continue; ! 15095: ! 15096: // while (n->base==REF || n->base==MDOT) n=Pname(n->mem); ! 15097: Pfct nf = Pfct(n->tp); ! 15098: if (nf->base == FCT) { ! 15099: if (nf->nargs == 0) { ! 15100: if (Lcoerce || Rcoerce) return 2; ! 15101: Rcoerce = on; ! 15102: } ! 15103: } ! 15104: else { ! 15105: for (Plist gl=Pgen(nf)->fct_list; gl; gl=gl->l) ! 15106: if (Pfct(gl->f->tp)->nargs == 0) { ! 15107: if (Lcoerce || Rcoerce) return 2; ! 15108: Rcoerce = on; ! 15109: } ! 15110: } ! 15111: continue; ! 15112: } ! 15113: //if (rt->is_cl_obj()) continue; ! 15114: if( lt ) { ! 15115: suppress_error = 1; ! 15116: int r1 = lt->kind(oper,0); ! 15117: int r2 = rt->kind(oper,0); ! 15118: ! 15119: if (np_promote(oper,r1,r2,lt,rt,1)!=any_type) { ! 15120: Pname sn = on; ! 15121: if (Lcoerce || Rcoerce) { ! 15122: Pname tn = really_dominate( ! 15123: Rcoerce, ! 15124: on, ! 15125: const_obj2 ! 15126: ); ! 15127: if(!tn) { ! 15128: suppress_error = 0; ! 15129: return 2; ! 15130: } ! 15131: else sn = tn; ! 15132: } ! 15133: Rcoerce = sn; ! 15134: } ! 15135: suppress_error = 0; ! 15136: } ! 15137: } ! 15138: } ! 15139: ! 15140: //error('d',"->%d || %d",Lcoerce,Rcoerce); ! 15141: return (Lcoerce || Rcoerce); ! 15142: } ! 15143: ! 15144: Pexpr expr::try_to_overload(Ptable tbl) ! 15145: { ! 15146: // TOK bb = (base==DEREF && e2==0) ? MUL : base; ! 15147: // error('d',"try_to_overload %k %d",base,base); ! 15148: ! 15149: Pname n1 = 0; ! 15150: Ptype t1 = 0; ! 15151: const_obj1 = 0; ! 15152: const_obj2 = 0; ! 15153: ! 15154: if (e1) { ! 15155: t1 = e1->tp; ! 15156: Ptype tpx = t1; ! 15157: while (tpx->base == TYPE) tpx = Pbase(tpx)->b_name->tp; ! 15158: n1 = tpx->is_cl_obj(); ! 15159: const_obj1 = t1->tconst(); ! 15160: ! 15161: Pexpr ee = e1; ! 15162: while (ee && (ee->base==DOT || ee->base==REF)) { ! 15163: Pexpr m = ee->mem; ! 15164: if ( ee->base==REF && m->tp && m->tp->is_ptr()) ! 15165: break; ! 15166: ee = ee->e1; ! 15167: } ! 15168: if (ee) { ! 15169: int tc; ! 15170: Ptype ttt = ee->tp; ! 15171: switch (e1->base) { ! 15172: case REF: ! 15173: Pptr p = ttt?ttt->is_ptr():0; ! 15174: if (p && p->typ->tconst()) ! 15175: const_obj1 = 1; ! 15176: break; ! 15177: case DOT: ! 15178: tc = ttt ? ttt->tconst() : 0; ! 15179: if (ttt && tc && (!strict_opt || tc!=2)) ! 15180: const_obj1 = 1; ! 15181: } ! 15182: } ! 15183: } ! 15184: ! 15185: TOK bb = base; ! 15186: switch (bb) { ! 15187: case DEREF: ! 15188: if (e2 == 0) bb = MUL; ! 15189: // no break; ! 15190: case CALL: ! 15191: case G_CALL: ! 15192: if (n1 == 0) return 0; // ignore type of argument list ! 15193: } ! 15194: ! 15195: Pname n2 = 0; ! 15196: Ptype t2 = 0; ! 15197: ! 15198: if (e2 && e2->base!=ELIST) { ! 15199: t2 = e2->tp; ! 15200: Ptype tpx = t2; ! 15201: while (tpx->base == TYPE) tpx = Pbase(tpx)->b_name->tp; ! 15202: n2 = tpx->is_cl_obj(); ! 15203: const_obj2 = t2->tconst(); ! 15204: Pexpr ee = e2; ! 15205: while (ee && (ee->base==DOT || ee->base==REF)) { ! 15206: Pexpr m = ee->mem; ! 15207: if ( ee->base==REF && m->tp && m->tp->is_ptr()) ! 15208: break; ! 15209: ee = ee->e1; ! 15210: } ! 15211: if (ee) { ! 15212: int tc; ! 15213: Ptype ttt = ee->tp; ! 15214: switch (e2->base) { ! 15215: case REF: ! 15216: Pptr p = ttt?ttt->is_ptr():0; ! 15217: if (p && p->typ->tconst()) ! 15218: const_obj2 = 1; ! 15219: break; ! 15220: case DOT: ! 15221: tc = ttt ? ttt->tconst() : 0; ! 15222: if (ttt && tc && (!strict_opt || tc!=2)) ! 15223: const_obj2 = 1; ! 15224: } ! 15225: } ! 15226: } ! 15227: ! 15228: if (n1==0 && n2==0) return 0; ! 15229: if (n1 && n1->tp == 0) return 0; // make_assign() fudge ! 15230: // error('d',"e1: %k e2: %k", e1?e1->base:0, e2?e2->base:0 ); ! 15231: // error('d',"t1 %t t2 %t",t1,t2); ! 15232: // error('d',"n1 %n n2 %n",n1,n2); ! 15233: /* first try for non-member function: op(e1,e2) or op(e2) or op(e1) */ ! 15234: Pexpr oe2 = e2; ! 15235: Pexpr ee2 = (e2 && e2->base!=ELIST) ? e2 = new expr(ELIST,e2,0) : 0; ! 15236: Pexpr ee1 = e1 ? new expr(ELIST,e1,e2) : ee2; ! 15237: char* obb = oper_name(bb); ! 15238: Pname gname = tbl->look(obb,0); ! 15239: // if necessary check for ambiguities ! 15240: int go = gname ? over_call(gname,ee1) : 0; ! 15241: //error('d',"go %d",go); ! 15242: if (go) gname = Nover; ! 15243: ! 15244: if (n1) { ! 15245: if (bb == ASSIGN) { ! 15246: Pclass c1 = Pclass(n1->tp); ! 15247: //error('d',"look %k %d",bb,c1->memtbl->look(obb,0)); ! 15248: if (c1->memtbl->look(obb,0)==0) { ! 15249: Pclass bcl = c1->baselist?c1->baselist->bclass:0; ! 15250: if (n2==0 ! 15251: || (Pclass(n2->tp)!=c1 ! 15252: && Pclass(n2->tp)->has_base(c1)==0)) { ! 15253: // if legal, a=1 can be optimized to a.ctor(1) ! 15254: if (2 < go) goto glob; ! 15255: return 0; ! 15256: } ! 15257: ! 15258: if (bcl ! 15259: && c1->obj_size!=bcl->obj_size ! 15260: && bcl->memtbl->look(obb,0)) { ! 15261: // cannot inherit from smaller base class ! 15262: // make_assignment(n1); ! 15263: // return try_to_overload(tbl); ! 15264: goto mkas; ! 15265: } ! 15266: ! 15267: if (c1->c_xref&(C_VBASE|C_VPTR|C_ASS)) { ! 15268: // make operator=() if ! 15269: // no base (shouldn't happen ! 15270: // different (smaller) sized base ! 15271: // two bases ! 15272: mkas: ! 15273: if (2 < go) goto glob; ! 15274: // make_assignment(n1); ! 15275: // return try_to_overload(tbl); ! 15276: return make_assignment(n1) ? try_to_overload(tbl) : 0; ! 15277: } ! 15278: // error('d',"n2 %n",n2); ! 15279: // if (n2 && Pclass(n2->tp)==c1) ! 15280: return 0; ! 15281: } ! 15282: // now take care of other assignments, ! 15283: } ! 15284: ! 15285: int dbconv = 0; ! 15286: Pclass ccl = Pclass(n1->tp); ! 15287: // Pexpr mn = Pclass(n1->tp)->memtbl->look(obb,0); ! 15288: Pexpr mn = ccl->memtbl->look(obb,0); ! 15289: // error('d', "tcl %d %t cl %d %t", tcl, tcl, ccl, ccl); ! 15290: if(strcmp(obb,"__as")) { ! 15291: tcl = ccl; // ugh!!! ! 15292: if(!mn) dbconv = 2; ! 15293: } ! 15294: // tcl = ccl; // ugh!!! ! 15295: mn = ccl->find_name(obb,0); ! 15296: ! 15297: Pname mname = Pname(mn); ! 15298: // error('d',"mn %n %d %k %s",mname,mn,mn?mn->base:0,obb); ! 15299: if (mname == 0) goto glob; ! 15300: ! 15301: zaq: ! 15302: switch (mname->base) { ! 15303: case REF: ! 15304: case MDOT: ! 15305: mname = Pname(Pexpr(mname)->mem); ! 15306: goto zaq; ! 15307: } ! 15308: ! 15309: int mo = over_call(mname,e2); ! 15310: int smo = mo; ! 15311: if(mo && dbconv && mo >= dbconv) mo = dbconv; ! 15312: //error('d',"mo %d (go %d)",mo,go); ! 15313: if (mo==0 || mo<go) ! 15314: goto glob; ! 15315: else if (mo && mo==go) { ! 15316: //error('d',"t1 %t t2 %t",t1,t2); ! 15317: if (gname->tp->base == OVERLOAD) { // find right version ! 15318: for (Plist l = Pgen(gname->tp)->fct_list; l; l=l->l) { ! 15319: Pname n = l->f; ! 15320: int x = over_call(n,ee1); ! 15321: if (x == go) { ! 15322: gname = n; ! 15323: break; ! 15324: } ! 15325: } ! 15326: } ! 15327: //error('d',"gname %n: %t",gname,gname->tp); ! 15328: Pname aa = Pfct(gname->tp)->argtype; ! 15329: Pptr p; ! 15330: Ptype gt1 = aa->tp; ! 15331: if (p = gt1->is_ref()) gt1 = p->typ; ! 15332: Ptype gt2 = aa->n_list->tp; ! 15333: //error('d',"gt1 %t gt2 %t",gt1,gt2); ! 15334: if (mname->tp->base == OVERLOAD) { // find right version ! 15335: for (Plist l = Pgen(mname->tp)->fct_list; l; l=l->l) { ! 15336: Pname n = l->f; ! 15337: int x = over_call(n,e2); ! 15338: if (x == smo) { ! 15339: mname = n; ! 15340: break; ! 15341: } ! 15342: } ! 15343: } ! 15344: //error('d',"mname %n: %t",mname,mname->tp); ! 15345: Ptype mt1 = Pfct(mname->tp)->f_this->tp; ! 15346: mt1 = Pptr(mt1)->typ; ! 15347: Ptype mt2 = Pfct(mname->tp)->argtype->tp; ! 15348: //error('d',"mt1 %t mt2 %t",mt1,mt2); ! 15349: Pname mm = new name; ! 15350: Pname a1 = new name; ! 15351: a1->tp = mt1; ! 15352: Pname a2 = new name; ! 15353: a2->tp = mt2; ! 15354: a1->n_list = a2; ! 15355: mm->tp = new fct(void_type,a1,2); ! 15356: Pname gg = new name; ! 15357: Pname a3 = new name; ! 15358: a3->tp = gt1; ! 15359: Pname a4 = new name; ! 15360: a4->tp = gt2; ! 15361: a3->n_list = a4; ! 15362: gg->tp = new fct(void_type,a3,1); ! 15363: extern Pname dominate(Pname,Pname,Pexpr,int,int); ! 15364: aa = dominate(gg,mm,ee1,0,1); ! 15365: delete a1; ! 15366: delete a2; ! 15367: delete a3; ! 15368: delete a4; ! 15369: DEL( gg->tp ); ! 15370: DEL( mm->tp ); ! 15371: //delete gg->tp; ! 15372: //delete mm->tp; ! 15373: if (aa == 0) { ! 15374: delete gg; ! 15375: delete mm; ! 15376: error("ambiguous operandTs%n and%t for%k",n1,t2,bb); ! 15377: tp = any_type; ! 15378: return this; ! 15379: } ! 15380: else if (aa == gg) { ! 15381: delete gg; ! 15382: delete mm; ! 15383: goto glob; ! 15384: } ! 15385: delete gg; ! 15386: delete mm; ! 15387: } ! 15388: else if (mo < 2) { // user-defined conversion user ! 15389: ! 15390: if (try_to_demote(bb,t1,t2)) ! 15391: error("ambiguous use of overloaded%k",bb); ! 15392: } ! 15393: ! 15394: base = G_CALL; // e1.op(e2) or e1.op() ! 15395: Pname xx = new name(mname->string); // do another lookup ! 15396: // . suppresses virtual ! 15397: e1 = new ref(DOT,e1,xx); ! 15398: if (ee1) delete ee1; ! 15399: return typ(tbl); ! 15400: } ! 15401: ! 15402: if (n2 && e1==0) { /* look for unary operator */ ! 15403: suppress_error++; ! 15404: Pexpr mn = Pclass(n2->tp)->find_name(obb,0); ! 15405: suppress_error--; ! 15406: Pname mname = Pname(mn); ! 15407: if (mname == 0) goto glob; ! 15408: zaqq: ! 15409: switch (mname->base) { ! 15410: case REF: ! 15411: case MDOT: ! 15412: mname = Pname(Pexpr(mname)->mem); ! 15413: goto zaqq; ! 15414: } ! 15415: ! 15416: switch (mname->n_scope) { ! 15417: default: goto glob; ! 15418: case 0: ! 15419: case PUBLIC: break; // try e2.op() ! 15420: } ! 15421: ! 15422: int mo = over_call(mname,0); ! 15423: //error('d',"e2 mo %d (go %d)",mo,go); ! 15424: if (mo==0 || mo<go) ! 15425: goto glob; ! 15426: else if (mo==go) { ! 15427: error("ambiguous operandT%n for%k",n2,bb); ! 15428: tp = any_type; ! 15429: return this; ! 15430: } ! 15431: else if (mo < 2) { // user-defined conversion user ! 15432: if (try_to_demote(bb,t1,t2)) ! 15433: error("ambiguous use of overloaded%k",bb); ! 15434: } ! 15435: base = G_CALL; // e2.op() ! 15436: Pname xx = new name(Nover->string); // do another lookup ! 15437: // . suppresses virtual ! 15438: e1 = new ref(DOT,oe2,xx); ! 15439: e2 = 0; ! 15440: if (ee2) delete ee2; ! 15441: if (ee1 && ee1!=ee2) delete ee1; ! 15442: return typ(tbl); ! 15443: } ! 15444: ! 15445: glob: ! 15446: // error('d',"glob %d",go); ! 15447: ! 15448: if (go) { ! 15449: if (go < 2) { // user-defined conversion necessary => binary ! 15450: if (try_to_demote(bb,t1,t2)) ! 15451: error("ambiguous use of overloaded%k: %t and %t",bb,t1,t2); ! 15452: } ! 15453: ! 15454: base = gname->n_table == gtbl ? G_CALL : CALL; ! 15455: //error('d',"gname %n %t",gname,gname->tp); ! 15456: e1 = new name(gname->string); ! 15457: // if global scope, look only for globals ! 15458: if(gname->n_table == gtbl) Pname(e1)->n_qualifier = sta_name; ! 15459: e2 = ee1; ! 15460: return typ(tbl); ! 15461: } ! 15462: ! 15463: if (ee2) delete ee2; ! 15464: if (ee1 && ee1!=ee2) delete ee1; ! 15465: e2 = oe2; ! 15466: ! 15467: // error('d',"bb %d %k",bb,bb); ! 15468: switch (bb) { ! 15469: case CM: ! 15470: case G_CM: ! 15471: case G_ADDROF: ! 15472: return 0; ! 15473: case ASSIGN: ! 15474: if (n1 ! 15475: && n2 ! 15476: && (n1->tp==n2->tp || Pclass(n2->tp)->has_base(Pclass(n1->tp)))) { ! 15477: if (make_assignment(n1)) ! 15478: return try_to_overload(tbl); ! 15479: else ! 15480: return 0; ! 15481: } ! 15482: case DEREF: ! 15483: case CALL: ! 15484: if (n1 == 0) break; ! 15485: ! 15486: default: /* look for conversions to basic types */ ! 15487: if (n1 ! 15488: && Pclass(n1->tp)->conv ! 15489: && (bb==ANDAND || bb==OROR)) { ! 15490: e1 = check_cond(e1,bb,tbl); ! 15491: return 0; ! 15492: } ! 15493: ! 15494: if (n2 ! 15495: && Pclass(n2->tp)->conv ! 15496: && (bb==ANDAND || bb==OROR || bb==NOT || ! 15497: bb==UMINUS || bb==UPLUS || bb==COMPL)) { ! 15498: e2 = check_cond(e2,bb,tbl); ! 15499: return 0; ! 15500: } ! 15501: ! 15502: // error( 'd', "bb: %k t1: %k t2: %k", bb, t1?t1->base:0, t2?t2->base:0 ); ! 15503: switch (try_to_demote(bb,t1,t2)) { ! 15504: default: ! 15505: if (Lcoerce) error("ambiguous conversion of%n",n1); ! 15506: if (Rcoerce) error("ambiguous conversion of%n",n2); ! 15507: case 0: ! 15508: break; ! 15509: case 1: ! 15510: if (Lcoerce) { ! 15511: Pname xx = new name(Lcoerce->string); ! 15512: Pref r = new ref(DOT,e1,xx); ! 15513: e1 = new expr(G_CALL,r,0); ! 15514: } ! 15515: ! 15516: if (Rcoerce) { ! 15517: Pname xx = new name(Rcoerce->string); ! 15518: Pref r = new ref(DOT,e2,xx); ! 15519: e2 = new expr(G_CALL,r,0); ! 15520: } ! 15521: return typ(tbl); ! 15522: } ! 15523: ! 15524: switch (bb) { ! 15525: case CM: ! 15526: case ADDROF: // has legal built-in meaning ! 15527: return 0; ! 15528: } ! 15529: ! 15530: if (t1 && t2) ! 15531: error("bad operandTs%t%t for%k",t1,t2,bb); ! 15532: else ! 15533: error("bad operandT%t for%k",t1?t1:t2,bb); ! 15534: ! 15535: tp = any_type; ! 15536: return this; ! 15537: } ! 15538: ! 15539: return 0; ! 15540: } ! 15541: ! 15542: Pexpr cast_cptr(Pclass ccl, Pexpr ee, Ptable tbl, int real_cast) ! 15543: /* ! 15544: "ee" is being cast to pointer object of class "ccl" ! 15545: if necessary modify "ee" ! 15546: */ ! 15547: { ! 15548: ! 15549: // Ptype etp = ee->tp; ! 15550: // error('d',"cast_cptr %k ccl %t ee->tp %t",ee->tp->base,ccl,ee->tp); ! 15551: // if (etp->base!=PTR && etp->base!=RPTR) return ee; ! 15552: Ptype etp = ee->tp->is_ptr_or_ref(); ! 15553: if (etp == 0) return ee; ! 15554: ! 15555: Pname on = Pptr(etp)->typ->is_cl_obj(); ! 15556: if (on == 0) return ee; ! 15557: ! 15558: Pclass ocl = Pclass(on->tp); ! 15559: if (ocl==ccl || ccl==0 || ocl==0) return ee; ! 15560: ! 15561: // error('d',"cast_cptr %t(%t) real %d",ccl,ocl,real_cast); ! 15562: int oo = 0; ! 15563: Pexpr r = 0; ! 15564: ! 15565: if (ocl->baselist ! 15566: && (ocl->baselist->bclass!=ccl || ocl->baselist->base!=NAME)) { ! 15567: // casting derived to second or virtual base? ! 15568: Nptr = 0; ! 15569: Nvis = 0; ! 15570: Nalloc_base = 0; ! 15571: vcllist->clear(); ! 15572: vcllist=0; ! 15573: int x = is_unique_base(ocl,ccl->string,0); ! 15574: if (Nvis) { ! 15575: if (real_cast==0) ! 15576: error("cast:%n* ->B%t*; privateBC",on,ccl); ! 15577: else if (warning_opt) ! 15578: error('w',"cast:%n* ->B%t*; privateBC",on,ccl); ! 15579: real_cast = 1; // suppress further error mesages ! 15580: Nvis = 0; ! 15581: } ! 15582: ! 15583: switch (x) { ! 15584: default: ! 15585: error("cast:%n* ->B%t*;%t isB more than once",on,ccl,ccl); ! 15586: case 0: // unrelated; ! 15587: break; ! 15588: case 1: ! 15589: oo = Noffset; ! 15590: break; ! 15591: } ! 15592: ! 15593: if (Nptr) { // => ee?Nptr:0 ! 15594: if (ocl->c_body==1) ocl->dcl_print(0); ! 15595: Nptr->mem = ee; // ee->Pbase_class ! 15596: if ( Nalloc_base ) { ! 15597: // error('d', "cast_cptr: nalloc_base: %s", Nalloc_base); ! 15598: Nptr->i1 = 5; ! 15599: Nptr->string4 = new char[strlen(Nalloc_base)]; ! 15600: strcpy(Nptr->string4,Nalloc_base); ! 15601: Nalloc_base = 0; ! 15602: } ! 15603: else Nptr->i1 = 3; ! 15604: ! 15605: if (ee->base==ADDROF || ee->base==G_ADDROF) ! 15606: ee = Nptr; ! 15607: else { ! 15608: Pexpr p = new expr(QUEST,Nptr,zero); ! 15609: nin = 1; ! 15610: if (ee->not_simple()) { // need temp ! 15611: Ptype t = ee->tp; ! 15612: Pname pp = make_tmp('N',t,tbl); ! 15613: Pname(pp)->n_assigned_to = 1; ! 15614: ee = new expr(ASSIGN,pp,ee); ! 15615: ee->tp = t; ! 15616: Nptr->mem = pp; ! 15617: } ! 15618: nin = 0; ! 15619: p->cond = ee; ! 15620: p->tp = ee->tp; ! 15621: ee = p; ! 15622: } ! 15623: } ! 15624: } ! 15625: ! 15626: if (ccl->baselist ! 15627: && (ccl->baselist->bclass!=ocl || ccl->baselist->base!=NAME)) { ! 15628: // casting second or virtual base to derived? ! 15629: Nptr = 0; ! 15630: vcllist->clear(); ! 15631: vcllist=0; ! 15632: int x = is_unique_base(ccl,ocl->string,0); ! 15633: switch (x) { ! 15634: default: ! 15635: error("cast:%n* ->derived%t*;%n isB more than once",on,ccl,on); ! 15636: case 0: // unrelated; ! 15637: break; ! 15638: case 1: ! 15639: oo = -Noffset; ! 15640: if (Nptr) ! 15641: error("cast:%n* ->derived%t*;%n is virtualB",on,ccl,on); ! 15642: break; ! 15643: } ! 15644: Nvis = 0; // visibility no concern when converting from base to derived ! 15645: } ! 15646: // error('d',"oo %d ee %k",oo,ee->base); ! 15647: if (oo) { // => ee?ee+offset:0 ! 15648: if (ee->base==ADDROF || ee->base==G_ADDROF) ! 15649: ee = rptr(ee->tp,ee,oo); ! 15650: else { ! 15651: Pexpr p; ! 15652: nin = 1; ! 15653: if (ee->not_simple()) { // need temp ! 15654: Ptype t = ee->base==MDOT?ee->mem->tp:ee->tp; ! 15655: Pname pp = make_tmp('M',t,tbl); ! 15656: Pname(pp)->n_assigned_to = 1; ! 15657: ee = new expr(ASSIGN,pp,ee); ! 15658: ee->tp = t; ! 15659: p = rptr(t,pp,oo); ! 15660: } ! 15661: else ! 15662: p = rptr(ee->base==MDOT?ee->mem->tp:ee->tp,ee,oo); ! 15663: nin = 0; ! 15664: Pexpr pp = new expr(QUEST,p,zero); ! 15665: pp->tp = ee->tp; ! 15666: pp->cond = ee; ! 15667: ee = pp; ! 15668: } ! 15669: } ! 15670: ! 15671: Nvis = 0; // Nvis set by has_base() ! 15672: if (ocl->has_base(ccl) && Nvis) { ! 15673: if (real_cast==0) ! 15674: error("cast:%n* ->B%t*; privateBC",on,ccl); ! 15675: else if (warning_opt) ! 15676: error('w',"cast:%n* ->B%t*; privateBC",on,ccl); ! 15677: Nvis = 0; ! 15678: } ! 15679: ! 15680: // error('d',"return %d %k %t",ee,ee->base,ee->tp); ! 15681: return ee; ! 15682: } ! 15683: ! 15684: Pexpr expr::donew(Ptable tbl) ! 15685: { ! 15686: Ptype tt = tp2; ! 15687: Ptype tpx = tt; ! 15688: bit v = 0; ! 15689: bit old = new_type; ! 15690: int init = 0; // non-constructor initialization ! 15691: new_type = 1; ! 15692: ! 15693: tt->dcl(tbl); ! 15694: new_type = old; ! 15695: // error('d',"donew %d %d (%k) tt %t",e1,e2,e2?e2->base:0,tt); ! 15696: if (e1) e1 = e1->typ(tbl); ! 15697: if (e2) e2 = e2->typ(tbl); ! 15698: ll: ! 15699: //error('d',"ll %d",tt->base); ! 15700: switch (tt->base) { ! 15701: default: ! 15702: if ( e1) { ! 15703: if (v) { ! 15704: error("Ir for array created using \"new\""); ! 15705: break; ! 15706: } ! 15707: init = 1; ! 15708: } ! 15709: // if (e1) { ! 15710: // error("Ir for nonCO created using \"new\""); ! 15711: // e1 = 0; ! 15712: // } ! 15713: break; ! 15714: case VEC: ! 15715: if (v && Pvec(tt)->dim) error("only 1st array dimension can be non-constant"); ! 15716: if (Pvec(tt)->size==0 && Pvec(tt)->dim==0) error("array dimension missing in `new'"); ! 15717: // if (Pvec(tt)->dim==zero) { ! 15718: // Pvec(tt)->size = 0; ! 15719: // Pvec(tt)->dim = 0; ! 15720: // } ! 15721: v++; ! 15722: tt = Pvec(tt)->typ; ! 15723: goto ll; ! 15724: case TYPE: ! 15725: tt = Pbase(tt)->b_name->tp; ! 15726: goto ll; ! 15727: case VOID: ! 15728: error("badT for `new': void"); ! 15729: break; ! 15730: case COBJ: ! 15731: { Pname cn = Pbase(tt)->b_name; ! 15732: Pclass cl = Pclass(cn->tp); ! 15733: Pname icn = 0; ! 15734: ! 15735: if ( e1 ) { // arguments ! 15736: if ( e1->e2 == 0 && e1->base == ELIST ) { ! 15737: e1 = e1->e1; ! 15738: e1 = e1->typ(tbl); ! 15739: } ! 15740: icn = (e1->base!=ELIST)?e1->tp->is_cl_obj():0; ! 15741: } ! 15742: //Pname icn = (e1 && e1->base!=ELIST)?e1->tp->is_cl_obj() : 0; ! 15743: ! 15744: Pclass icl = icn ? Pclass(icn->tp) : 0; ! 15745: ! 15746: if (cl->c_abstract) { ! 15747: error("`new' of abstractC%t",cl); ! 15748: break; ! 15749: } ! 15750: ! 15751: if (v && e1) { ! 15752: error("Ir for array ofCO created using \"new\""); ! 15753: break; ! 15754: } ! 15755: ! 15756: if ((cl->defined&(DEFINED|SIMPLIFIED)) == 0) { ! 15757: error("new%n;%n isU",cn,cn); ! 15758: break; ! 15759: } ! 15760: ! 15761: Pname ctor = cl->has_ctor(); ! 15762: ! 15763: if (ctor) { ! 15764: if (v) { ! 15765: Pname ic; ! 15766: if ((ic = cl->has_ictor())==0) { ! 15767: error("array ofC%n that does not have aK taking noAs",cn); ! 15768: break; ! 15769: } ! 15770: ! 15771: if (Pfct(ic->tp)->nargs) { ! 15772: error("defaultAs forK for array ofC%n",cn); ! 15773: break; ! 15774: } ! 15775: } ! 15776: ! 15777: if (icl ! 15778: && cl->has_itor()==0 // incomplete: ! 15779: // what if X(Y&) exists ! 15780: // for class Y : X ? ! 15781: && (icl==cl || icl->has_base(cl))) { ! 15782: init = 1; ! 15783: break; ! 15784: } ! 15785: e1 = call_ctor(tbl,0,ctor,e1); ! 15786: } ! 15787: else if (e1) { ! 15788: if (icl==cl || icl->has_base(cl)) ! 15789: init = 1; ! 15790: else ! 15791: error("new%n(As ); %n does not have aK",cn,cn); ! 15792: } ! 15793: } ! 15794: } ! 15795: ! 15796: if (init) { ! 15797: Pname tmp = make_tmp('N',tt->addrof(),tbl); ! 15798: e1 = e1->typ(tbl); ! 15799: if (tt->check(e1->tp,ASSIGN)) ! 15800: error("badIrT %t for new operator (%t X)",e1->tp,tt); ! 15801: e1 = new expr(0,tmp,e1); ! 15802: tmp->assign(); ! 15803: } ! 15804: ! 15805: // tp = (v) ? tpx : tpx->addrof(); ! 15806: switch (v) { ! 15807: case 0: ! 15808: tp = tpx->addrof(); ! 15809: break; ! 15810: case 1: ! 15811: tp = tpx; ! 15812: break; ! 15813: default: ! 15814: tp = tpx; ! 15815: } ! 15816: //error('d',"donew(%d) -> %t",v,tp); ! 15817: return this; ! 15818: } ! 15819: ! 15820: static is_dataMemPtr( Pexpr ee ) ! 15821: /* this is utterly implementation dependent ! 15822: * called by expr::lval to determine ! 15823: * const objects bounds to pointers to data members ! 15824: */ ! 15825: { ! 15826: Pexpr te = ee->e1; ! 15827: if ( te == 0 ) return 0; ! 15828: if ( te->base != PLUS ) return 0; ! 15829: if ( (te = te->e2) == 0 ) return 0; ! 15830: if ( te->base != MINUS ) return 0; ! 15831: if ( (te = te->e1) == 0 ) return 0; ! 15832: if ( te->base != CAST ) return 0; ! 15833: if ( (te = te->e1) == 0 ) return 0; ! 15834: if ( te->tp->base != PTR ) return 0; ! 15835: if ( Pptr(te->tp)->memof == 0 ) return 0; ! 15836: return 1; ! 15837: } ! 15838: 0707071010112044301004440001630000160000010200700466055402100001000000162346expr3.c /*ident "@(#)ctrans:src/expr3.c 1.6" */ ! 15839: /*************************************************************************** ! 15840: ! 15841: C++ source for cfront, the C++ compiler front-end ! 15842: written in the computer science research center of Bell Labs ! 15843: ! 15844: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 15845: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 15846: ! 15847: expr3.c: ! 15848: ! 15849: type check function calls, casts, and explicit coercions ! 15850: ! 15851: ************************************************************************/ ! 15852: ! 15853: #include "cfront.h" ! 15854: #include "size.h" ! 15855: ! 15856: int pr_dominate(Ptype t1, Ptype t2) ! 15857: /* ! 15858: */ ! 15859: { ! 15860: Pname cn1 = t1->is_cl_obj(); ! 15861: Pname cn2 = t2->is_cl_obj(); ! 15862: //error('d',"pr_dominate(%t,%t)",t1,t2); ! 15863: ! 15864: if (cn1==0 || cn2==0) { ! 15865: Ptype p1 = t1->is_ptr(); ! 15866: Ptype p2 = t2->is_ptr(); ! 15867: if (p1 && p2) { // pointers ! 15868: cn1 = Pptr(p1)->typ->is_cl_obj(); ! 15869: cn2 = Pptr(p2)->typ->is_cl_obj(); ! 15870: if (cn1==0 || cn2==0) return 0; ! 15871: } ! 15872: else { ! 15873: p1 = t1->is_ref(); ! 15874: p2 = t2->is_ref(); ! 15875: if (p1 && p2) { // references ! 15876: cn1 = Pptr(p1)->typ->is_cl_obj(); ! 15877: cn2 = Pptr(p2)->typ->is_cl_obj(); ! 15878: if (cn1==0 || cn2==0) return 0; ! 15879: } ! 15880: // else if (p1 && cn2) { ! 15881: // cn1 = Pptr(p1)->typ->is_cl_obj(); ! 15882: // } ! 15883: else ! 15884: return 0; // not the same and not classes ! 15885: } ! 15886: } ! 15887: Pclass c1 = Pclass(cn1->tp); ! 15888: Pclass c2 = Pclass(cn2->tp); ! 15889: //error('d'," c1 : c2 %d; c2 : c1 %d",c1->has_base(c2),c2->has_base(c1)); ! 15890: if (c1->has_base(c2)) return 1; ! 15891: if (c2->has_base(c1)) return 2; ! 15892: return 0; ! 15893: } ! 15894: ! 15895: int exact1(Pname,Ptype); ! 15896: static exact2(Pname,Ptype); ! 15897: static exact3(Pname,Ptype); ! 15898: ! 15899: static Pname user_dominate(Pname n1, Pname n2, Pexpr arg) ! 15900: { ! 15901: Pfct f1 = Pfct(n1->tp); ! 15902: Pfct f2 = Pfct(n2->tp); ! 15903: ! 15904: Pname a1 = f1->argtype; ! 15905: Pname a2 = f2->argtype; ! 15906: //error('d',"user_dominate: %n %t %t",n1,f1,f2); ! 15907: ! 15908: for(; a1 && a2; a1 = a1->n_list, a2 = a2->n_list) { ! 15909: Ptype t1 = a1->tp; ! 15910: Ptype t2 = a2->tp; ! 15911: } ! 15912: ! 15913: if (a1 && !a1->n_evaluated) return n1; ! 15914: if (a2 && !a2->n_evaluated) return n2; ! 15915: ! 15916: a1 = f1->argtype; ! 15917: a2 = f2->argtype; ! 15918: ! 15919: Pname prev = 0; ! 15920: Pexpr e = arg; ! 15921: ! 15922: for(; a1 && a2 && e; a1 = a1->n_list, a2 = a2->n_list, e = e->e2) { ! 15923: Ptype t1 = a1->tp; ! 15924: Ptype t2 = a2->tp; ! 15925: Ptype at = e->e1->tp; ! 15926: ! 15927: int j = can_coerce(t1,at); ! 15928: Ptype tt1 = Ncoerce ? Pfct(Ncoerce->tp)->returns : 0; ! 15929: j = can_coerce(t2,at); ! 15930: Ptype tt2 = Ncoerce ? Pfct(Ncoerce->tp)->returns : 0; ! 15931: if(!tt1 || !tt2 || tt1->check(tt2,OVERLOAD)) ! 15932: return 0; ! 15933: ! 15934: int one = 0, two = 0; ! 15935: if(exact1(a1,tt1)) one = 4; ! 15936: else if(exact2(a1,tt1)) one = 3; ! 15937: else if(exact3(a1,tt1)) one = 2; ! 15938: else one = 1; ! 15939: if(exact1(a2,tt1)) two = 4; ! 15940: else if(exact2(a2,tt1)) two = 3; ! 15941: else if(exact3(a2,tt1)) two = 2; ! 15942: else two = 1; ! 15943: ! 15944: if(one > two && (!prev || prev==n1)) prev = n1; ! 15945: else if(two > one && (!prev || prev==n2)) prev = n2; ! 15946: else if(one == two && one) ; ! 15947: else return 0; ! 15948: } ! 15949: if(prev) return prev; ! 15950: ! 15951: return 0; ! 15952: } ! 15953: ! 15954: Pname dominate(Pname n1, Pname n2, Pexpr arg, int const_obj, int level) ! 15955: /* ! 15956: the two functions n1 and n2 can each respond to a call using ! 15957: standard conversions. Does the one dominate the other in the ! 15958: sense that all its arguments are identical to the other or ! 15959: classes defived from the class of the corresponding argument ! 15960: of the other. ! 15961: ! 15962: If so return it, otherwise return 0; ! 15963: */ ! 15964: { ! 15965: Pname res = 0; ! 15966: ! 15967: Pfct f1 = Pfct(n1->tp); ! 15968: Pfct f2 = Pfct(n2->tp); ! 15969: ! 15970: Pname a1 = f1->argtype; ! 15971: Pname a2 = f2->argtype; ! 15972: Pexpr e = arg; ! 15973: //error('d',"dominate: %n %t %t e %d",n1,f1,f2,e); ! 15974: ! 15975: if (e == 0) { ! 15976: if (const_obj) { ! 15977: if (f1->f_const && f2->f_const==0) return n1; ! 15978: if (f2->f_const && f1->f_const==0) return n2; ! 15979: } ! 15980: else { ! 15981: if (f1->f_const==0 && f2->f_const) return n1; ! 15982: if (f2->f_const==0 && f1->f_const) return n2; ! 15983: } ! 15984: return 0; ! 15985: } ! 15986: ! 15987: for(; a1 && a2 && e; a1 = a1->n_list, a2 = a2->n_list, e = e->e2) { ! 15988: Ptype t1 = a1->tp; ! 15989: Ptype t2 = a2->tp; ! 15990: Ptype at = e->e1->tp; ! 15991: //error('d',"t1 %t t2 %t at %t",t1,t2,at); ! 15992: if (t1==t2 || t1->check(t2,0)==0 ) ! 15993: continue; ! 15994: Pptr r1 = t1->is_ref(); ! 15995: Pptr r2 = t2->is_ref(); ! 15996: //error('d',"const_problem %t %t %t %d",t1,t2,at,const_problem); ! 15997: if (const_problem) { // t1 and t1 differs only in const ! 15998: Pname rr; ! 15999: if (at->check(t1,0)==0 && const_problem==0) { ! 16000: if (t1->is_ptr()) ! 16001: rr = n1; ! 16002: else ! 16003: goto nc; ! 16004: } ! 16005: else if (at->check(t2,0)==0 && const_problem==0) { ! 16006: if (t2->is_ptr()) ! 16007: rr = n2; ! 16008: else ! 16009: goto nc; ! 16010: } ! 16011: else if (r1 && r1->typ->check(at,0)==0 && const_problem==0) ! 16012: rr = n1; ! 16013: else if (r2 && r2->typ->check(at,0)==0 && const_problem==0) ! 16014: rr = n2; ! 16015: else ! 16016: goto nc; ! 16017: ! 16018: if (res && res!=rr) return 0; // mutual dominace ! 16019: res = rr; ! 16020: continue; // identical ! 16021: } ! 16022: nc: ! 16023: if (r2 && (t1==r2 || t1->check(r2->typ,0)==0)) continue; ! 16024: if (r1 && (t2==r1 || t2->check(r1->typ,0)==0)) continue; ! 16025: ! 16026: Pname rr = 0; ! 16027: if (t1==at || exact1(a1,at)) ! 16028: rr = n1; ! 16029: else if (t2==at || exact1(a2,at)) ! 16030: rr = n2; ! 16031: else if (1<level) { // try integral promotion ! 16032: if (exact2(a1,at)) ! 16033: rr = n1; ! 16034: if (exact2(a2,at)) { ! 16035: if (rr) rr = 0; ! 16036: else rr = n2; ! 16037: } ! 16038: } ! 16039: if (!rr && 2<level) { // try standard conversions ! 16040: if (exact3(a1,at)) ! 16041: rr = n1; ! 16042: if (exact3(a2,at)) { ! 16043: if (rr) rr = 0; ! 16044: else rr = n2; ! 16045: } ! 16046: } ! 16047: if (rr) { ! 16048: if (res && res!=rr) return 0; // mutual dominance ! 16049: res = rr; ! 16050: continue; ! 16051: } ! 16052: ! 16053: int r = pr_dominate(t1,t2); ! 16054: //error('d',"pr1 %d",r); ! 16055: if (r) { ! 16056: Pname rr = r==1?n1:n2; ! 16057: if (res && res!=rr) return 0; // mutual dominace ! 16058: res = rr; ! 16059: continue; ! 16060: } ! 16061: ! 16062: r = pr_dominate(t1,at); ! 16063: //error('d',"pr2 %d",r); ! 16064: if (r==2) { ! 16065: if (res && res!=n1) return 0; // mutual dominace ! 16066: res = n1; ! 16067: r = pr_dominate(t2,at); ! 16068: if (r==2) return 0; // mutual dominace ! 16069: continue; ! 16070: } ! 16071: ! 16072: r = pr_dominate(t2,at); ! 16073: //error('d',"pr3 %d",r); ! 16074: if (r==2) { ! 16075: if (res && res!=n2) return 0; // mutual dominace ! 16076: res = n2; ! 16077: continue; ! 16078: } ! 16079: ! 16080: } ! 16081: //if (a1==0 && a2 && a2->n_initializer==0) return 0; // wrong number of arguments ! 16082: //if (a2==0 && a1 && a1->n_initializer==0) return 0; // wrong number of arguments ! 16083: ! 16084: if (e) { ! 16085: //error('d',"more args %t a1 %t a2 %t",e->e1->tp,a1?a1->tp:0,a2?a2->tp:0); ! 16086: int k1 = f1->nargs_known!=ELLIPSIS; ! 16087: int k2 = f2->nargs_known!=ELLIPSIS; ! 16088: if (a1 && a1->tp->check(e->e1->tp,ASSIGN)==0) return n1; ! 16089: if (a2 && a2->tp->check(e->e1->tp,ASSIGN)==0) return n2; ! 16090: if (k1 && k2) return 0; ! 16091: } ! 16092: ! 16093: if (a1==0 && a2 && a2->n_initializer==0) return 0; ! 16094: if (a2==0 && a1 && a1->n_initializer==0) return 0; ! 16095: if (res==0) ! 16096: if (const_obj) { ! 16097: if (f1->f_const && f2->f_const==0) return n1; ! 16098: if (f2->f_const && f1->f_const==0) return n2; ! 16099: } ! 16100: else { ! 16101: if (f1->f_const==0 && f2->f_const) return n1; ! 16102: if (f2->f_const==0 && f1->f_const) return n2; ! 16103: } ! 16104: //error('d'," -> %n %t",res,res?res->tp:0); ! 16105: return res; ! 16106: } ! 16107: ! 16108: Pname Ntmp; ! 16109: ! 16110: static refd; // initialization routine called by ref_init, do not apply itor ! 16111: static no_sti; ! 16112: extern int stat_init; ! 16113: ! 16114: Pname make_tmp(char c, Ptype t, Ptable tbl) ! 16115: { ! 16116: int dt = 0; ! 16117: Pname tn = tbl->t_name; ! 16118: Pname cn = t->is_cl_obj(); ! 16119: ! 16120: if (tn && tn->tp) error('s',"defaultA too complicated"); ! 16121: if (cn && Pclass(cn->tp)->has_dtor()) dt = 1; ! 16122: if (Ntmp == 0 && dt ) Ntmp = cn; ! 16123: ! 16124: //error('d',"tbl %d cstmt %d %d sti %d",tbl,Cstmt,Cstmt?Cstmt->memtbl:0,sti_tbl); ! 16125: if (Cstmt) { // make Cstmt into a block ! 16126: if (Cstmt->memtbl == 0) Cstmt->memtbl = new table(4,tbl,0); ! 16127: tbl = Cstmt->memtbl; ! 16128: } ! 16129: else if (tbl == gtbl && no_sti == 0) { ! 16130: if (sti_tbl == 0) sti_tbl = new table(8,gtbl,0); ! 16131: tbl = sti_tbl; ! 16132: } ! 16133: ! 16134: Pname tmpx = new name(make_name(c)); ! 16135: tmpx->where = no_where; ! 16136: tmpx->tp = t; ! 16137: (void) t->tsizeof(); ! 16138: if ( t->base == COBJ ) { ! 16139: Pclass cl = Pclass(Pbase(t)->b_name->tp); ! 16140: if ( cl->lex_level ) tmpx->lex_level = cl->lex_level; ! 16141: } ! 16142: ! 16143: TOK scop = ARG; ! 16144: if (stat_init && dt) { ! 16145: tmpx->n_sto = STATIC; scop = ARGS; ! 16146: } ! 16147: ! 16148: // ARG[S]: no init; ARGS: static dtor ! 16149: Pname tmp = tmpx->dcl(tbl,scop); ! 16150: delete tmpx; ! 16151: ! 16152: // n_scope == ARGS sets static dtor in simpl2.c ! 16153: tmp->n_scope = (scop==ARG) ? FCT : ARGS; ! 16154: return tmp; ! 16155: } ! 16156: ! 16157: Pexpr init_tmp(Pname tmp, Pexpr init, Ptable tbl) ! 16158: { ! 16159: Pname cn = tmp->tp->is_cl_obj(); ! 16160: Pname ct = cn ? Pclass(cn->tp)->has_itor() : 0; ! 16161: ! 16162: tmp->n_assigned_to = 1; ! 16163: //error('d',"init_tmp %n ct %n refd %d",tmp,ct,refd); ! 16164: if (ct) { // must initialize ! 16165: if (refd) { ! 16166: //error('d',"'orrible %k",init->e1->base); ! 16167: switch (init->e1->base) { // 'orrible 'ack ! 16168: case NAME: ! 16169: case REF: ! 16170: case DEREF: ! 16171: if (init->e1->tp->is_ptr()) ! 16172: init = init->e1; ! 16173: else ! 16174: init = new expr(G_CM,init,init->e1->address()); ! 16175: ! 16176: } ! 16177: if (ct->tp->base == OVERLOAD) ct = Pgen(ct->tp)->fct_list->f; // first fct ! 16178: tbl = 0; ! 16179: } ! 16180: return call_ctor(tbl,tmp,ct,init,DOT); ! 16181: } ! 16182: Pexpr ass = new expr(ASSIGN,tmp,init); // no ctor: can assign ! 16183: ass->tp = tmp->tp; ! 16184: return ass; ! 16185: } ! 16186: /* ! 16187: int exact0(Pname nn, Ptype at) ! 16188: // return 1 if ! 16189: // exact match ! 16190: ! 16191: { ! 16192: if (nn == 0) return 0; //known==ELLIPSIS; ! 16193: Ptype nt = nn->tp; ! 16194: if (at == nt) return 1; ! 16195: //error('d',"exact0 %d",nt->check(at,0)); ! 16196: return nt->check(at,0)==0; ! 16197: } ! 16198: */ ! 16199: ! 16200: int exact3(Pname nn, Ptype at) ! 16201: /* ! 16202: return 1 if ! 16203: match with standard conversions ! 16204: */ ! 16205: { ! 16206: if (nn == 0) return 0; //known==ELLIPSIS; ! 16207: Ptype nt = nn->tp; ! 16208: ! 16209: while(nt->base == TYPE) ! 16210: nt = Pbase(nt)->b_name->tp; ! 16211: ! 16212: if (at == nt) return 1; ! 16213: ! 16214: switch (nt->base) { ! 16215: case RPTR: ! 16216: if (at==zero_type && Pptr(nt)->typ->is_ptr()==0) return 0; //break; ! 16217: if (nt->check(at,COERCE)) { ! 16218: Pptr pt = at->addrof(); ! 16219: nt->base = PTR; // handle derived classes ! 16220: if (nt->check(pt,COERCE)) { ! 16221: nt->base = RPTR; ! 16222: delete pt; ! 16223: return 0; ! 16224: } ! 16225: nt->base = RPTR; ! 16226: delete pt; ! 16227: } ! 16228: break; ! 16229: default: ! 16230: switch (at->base) { ! 16231: default: ! 16232: if (nt->check(at,COERCE)) return 0; ! 16233: break; ! 16234: case OVERLOAD: ! 16235: // the actual argument is an overloaded function ! 16236: // we'll try each instance until one matches ! 16237: register Plist gl; ! 16238: int no_match = 1; ! 16239: ! 16240: for (gl = Pgen(at)->fct_list; gl; gl=gl->l) { ! 16241: if (nt->check(gl->f->tp,COERCE)==0) { ! 16242: no_match = 0; ! 16243: break; ! 16244: } ! 16245: } ! 16246: ! 16247: if ( no_match ) return 0; ! 16248: } ! 16249: } ! 16250: return 1; ! 16251: } ! 16252: ! 16253: int exact1(Pname nn, Ptype at) ! 16254: /* ! 16255: return 1 if ! 16256: exact match with ! 16257: T <-> const T ! 16258: X -> X& ! 16259: T* -> const T* ! 16260: T* -> T*const ! 16261: taken into account ! 16262: */ ! 16263: { ! 16264: if (nn == 0) return 0;//known==ELLIPSIS; ! 16265: Ptype nt = nn->tp; ! 16266: if (at == nt) return 1; ! 16267: ! 16268: //error('d',"exact1 nt %t at %t",nt,at); ! 16269: if (nt->check(at,0)) { ! 16270: //error('d',"nt %t at %t cp %d",nt,at,const_problem); ! 16271: if (const_problem) return 1; // handle T <-> const T ! 16272: ! 16273: Pptr rt = nt->is_ref(); //handle X -> X& ! 16274: if (rt && (at->check(Pptr(rt)->typ,0)==0 || const_problem)) return 1; ! 16275: ! 16276: Pptr art = at->is_ptr(); ! 16277: if (rt && art) return 0; // ptrs do not match refs ! 16278: ! 16279: // handle T* -> const T* and ! 16280: // T* -> T*const ! 16281: if (rt || (rt = nt->is_ptr())) { ! 16282: if (art == 0) art = at->is_ref(); ! 16283: if (art) { ! 16284: //error('d',"art %t %t",art->typ,rt->typ); ! 16285: if (art->typ->check(rt->typ,0)) { ! 16286: if (const_problem) return 1; ! 16287: } ! 16288: else // T* -> T*const ! 16289: return 1; ! 16290: } ! 16291: } ! 16292: return 0; ! 16293: } ! 16294: return 1; ! 16295: } ! 16296: ! 16297: Pexpr Ninit; // default argument used; ! 16298: int Nstd; // standard coercion used (derived* =>base* or int=>long or ...) ! 16299: ! 16300: bit exact_match(Pname n, Pexpr arg) ! 16301: /* ! 16302: look for an exact match between "n" and the argument list "arg" ! 16303: This function goes through three stages: ! 16304: (1) exact match (no coercions at all) ! 16305: (2) do integral promotions and float->double and re-try exact match ! 16306: (3) try for unique standard conversions ! 16307: ! 16308: */ ! 16309: { ! 16310: Pfct f = Pfct(n->tp); ! 16311: register Pexpr e; ! 16312: register Pname nn; ! 16313: ! 16314: // error('d',"exact_match(%n) %t",n,n->tp); ! 16315: ! 16316: for (e=arg, nn=f->argtype; e; e=e->e2, nn=nn->n_list) { ! 16317: Pexpr a = e->e1; ! 16318: Ptype at = a->tp; ! 16319: if (at->base == ANY) return 0; ! 16320: if (at->base == ZTYPE) at = int_type; ! 16321: if (exact1(nn,at)==0) return 0; ! 16322: } ! 16323: ! 16324: //error('d',"exact %d -> %d",nn,nn?nn->n_initializer!=0:1); ! 16325: if (nn) { ! 16326: Ninit = nn->n_initializer; ! 16327: return Ninit!=0; ! 16328: } ! 16329: ! 16330: //error('d',"return 1"); ! 16331: return 1; // exact match without any promotions ! 16332: } ! 16333: ! 16334: int exact2(Pname nn, Ptype at) ! 16335: /* ! 16336: return 1 if ! 16337: do integral promotion and float->double on at, then match ! 16338: */ ! 16339: { ! 16340: //error('d',"exact2 nt %t at %t",nn?nn->tp:0,at); ! 16341: while(at->base == TYPE) ! 16342: at = Pbase(at)->b_name->tp; ! 16343: ! 16344: switch (at->base) { ! 16345: case EOBJ: ! 16346: at = Penum(Pbase(at)->b_name->tp)->e_type; ! 16347: break; ! 16348: case ZTYPE: ! 16349: at = int_type; ! 16350: break; ! 16351: case CHAR: ! 16352: case SHORT: ! 16353: at = (Pbase(at)->b_unsigned && at->tsizeof()==SZ_INT) ? uint_type : int_type; ! 16354: break; ! 16355: case FLOAT: ! 16356: at = double_type; ! 16357: } ! 16358: ! 16359: if (nn == 0) return 0;//known==ELLIPSIS; ! 16360: Ptype nt = nn->tp; ! 16361: //error('d'," exact2 nt %t at %t",nt,at); ! 16362: if (at == nt) return 1; ! 16363: if (nt->check(at,0)) { ! 16364: if (const_problem) return 1; ! 16365: ! 16366: Pptr rt = nt->is_ref(); // handle X -> X& ! 16367: if (rt && (at->check(Pptr(rt)->typ,0)==0 || const_problem)) return 1; ! 16368: ! 16369: Pptr art = at->is_ptr(); ! 16370: if (rt && art) return 0; // ptrs do not match refs ! 16371: ! 16372: // handle T* -> const T* and ! 16373: // T* -> T*const ! 16374: if (rt || (rt = nt->is_ptr())) { ! 16375: if (art == 0) art = at->is_ref(); ! 16376: if (art) { ! 16377: if (art->typ->check(rt->typ,0)) { ! 16378: if (const_problem) return 1; ! 16379: } ! 16380: else // T* -> T*const ! 16381: return 1; ! 16382: } ! 16383: } ! 16384: return 0; ! 16385: } ! 16386: return 1; ! 16387: } ! 16388: ! 16389: bit prom_match(Pname n, Pexpr arg) ! 16390: /* ! 16391: look for an exact match between "n" and the argument list "arg" ! 16392: using integral promotions and float->double ! 16393: ! 16394: */ ! 16395: { ! 16396: Pfct f = Pfct(n->tp); ! 16397: register Pexpr e; ! 16398: register Pname nn; ! 16399: ! 16400: // error('d',"prom_match(%n) %t",n,n->tp); ! 16401: ! 16402: for (e=arg, nn=f->argtype; e; e=e->e2, nn=nn->n_list) { ! 16403: Pexpr a = e->e1; ! 16404: Ptype at = a->tp; ! 16405: if (at->base == ANY) return 0; ! 16406: ! 16407: if (exact2(nn,at)==0) return 0; ! 16408: } ! 16409: ! 16410: if (nn) { ! 16411: Ninit = nn->n_initializer; ! 16412: return Ninit!=0; ! 16413: } ! 16414: ! 16415: return 1; // exact match with promotions ! 16416: } ! 16417: ! 16418: bit std_match(Pname n, Pexpr arg) ! 16419: /* ! 16420: look for an exact match between "n" and the argument list "arg" ! 16421: using standard conversions ! 16422: ! 16423: */ ! 16424: { ! 16425: Pfct f = Pfct(n->tp); ! 16426: register Pexpr e; ! 16427: register Pname nn; ! 16428: ! 16429: // error('d',"std_match(%n) %t",n,n->tp); ! 16430: ! 16431: for (e=arg, nn=f->argtype; e; e=e->e2, nn=nn->n_list) { ! 16432: Pexpr a = e->e1; ! 16433: Ptype at = a->tp; ! 16434: ! 16435: if (at->base == ANY) return 0; ! 16436: if ( exact3(nn,at) == 0) return 0; ! 16437: } ! 16438: ! 16439: if (nn) { ! 16440: Ninit = nn->n_initializer; ! 16441: return Ninit!=0; ! 16442: } ! 16443: ! 16444: return 1; ! 16445: } ! 16446: ! 16447: Pname Ncoerce; ! 16448: int ref_cast; ! 16449: ! 16450: bit can_coerce(Ptype t1, Ptype t2) ! 16451: /* return number of possible coercions of t2 into t1, ! 16452: Ncoerce holds a coercion function (not constructor), if found ! 16453: */ ! 16454: { ! 16455: int zz = 0; ! 16456: Ncoerce = 0; ! 16457: if (t2->base == ANY) return 0; ! 16458: // error('d',"can_coerce t1 %t t2 %t",t1, t2); ! 16459: ! 16460: while(t1->base == TYPE) ! 16461: t1 = Pbase(t1)->b_name->tp; ! 16462: ! 16463: switch (t1->base) { ! 16464: case RPTR: ! 16465: while(t2->base == TYPE) ! 16466: t2 = Pbase(t2)->b_name->tp; ! 16467: ! 16468: switch (t2->base) { ! 16469: // case VEC: ! 16470: // case PTR: ! 16471: // case RPTR: ! 16472: // if (t1->check(t2,COERCE) == 0) return 1; ! 16473: default: ! 16474: { Ptype tt2 = t2->addrof(); ! 16475: if (t1->check(tt2,COERCE) == 0) return 1; ! 16476: if (ref_cast) break;//return 0; // (T&): no coercions ! 16477: // except operator T&() ! 16478: Ptype tt1 = Pptr(t1)->typ; ! 16479: while (tt1->base==TYPE) tt1 = Pbase(tt1)->b_name->tp; ! 16480: int bc; ! 16481: if ( tt1->base != PTR && tt1->base != RPTR ) { ! 16482: bc = Pbase(tt1)->b_const; ! 16483: Pbase(tt1)->b_const = 0; ! 16484: } ! 16485: int i = can_coerce(tt1,t2); ! 16486: if ( tt1->base != PTR && tt1->base != RPTR ) ! 16487: Pbase(tt1)->b_const = bc; ! 16488: if (i) return i; ! 16489: zz = 1; ! 16490: } ! 16491: } ! 16492: } ! 16493: ! 16494: Pname c1 = t1->is_cl_obj(); ! 16495: Pname c2 = t2->is_cl_obj(); ! 16496: int val = 0; ! 16497: if (ref_cast || zz) goto oper_coerce; ! 16498: if (c1) { ! 16499: Pclass cl = Pclass(c1->tp); ! 16500: if (c2 && c2->tp==cl) return 1; ! 16501: ! 16502: // A more comprehensive test for template classes ! 16503: if (c2 && (Pclass(c1->tp)->same_class(Pclass(c2->tp)))) ! 16504: return 1 ; ! 16505: ! 16506: /* look for constructor ! 16507: with one argument ! 16508: or with default for second argument ! 16509: of acceptable type ! 16510: */ ! 16511: Pname ctor = cl->has_ctor(); ! 16512: if (ctor == 0) goto oper_coerce; ! 16513: register Pfct f = Pfct(ctor->tp); ! 16514: //error('d',"ctor %n f %t",ctor,f); ! 16515: switch (f->base) { ! 16516: case FCT: ! 16517: switch (f->nargs) { ! 16518: case 1: ! 16519: one: ! 16520: { Ptype tt = f->argtype->tp; ! 16521: if (tt->check(t2,COERCE)==0) ! 16522: val = 1; ! 16523: else if (const_problem) { ! 16524: Pptr p1 = tt->is_ptr_or_ref(); ! 16525: if (p1==0 || p1->typ->tconst()) val = 1; ! 16526: } ! 16527: if (tt = tt->is_ref()) { ! 16528: Pptr pt = t2->addrof(); // handle derived classed ! 16529: tt->base = PTR; ! 16530: if (tt->check(pt,COERCE) == 0) val = 1; ! 16531: tt->base = RPTR; ! 16532: delete pt; ! 16533: } ! 16534: goto oper_coerce; ! 16535: } ! 16536: default: ! 16537: if (f->argtype->n_list->n_initializer) goto one; ! 16538: case 0: ! 16539: goto oper_coerce; ! 16540: } ! 16541: case OVERLOAD: ! 16542: { register Plist gl; ! 16543: ! 16544: for (gl=Pgen(f)->fct_list; gl; gl=gl->l) { // look for match ! 16545: Pname nn = gl->f; ! 16546: Pfct ff = Pfct(nn->tp); ! 16547: ! 16548: switch (ff->nargs) { ! 16549: case 0: ! 16550: break; ! 16551: case 1: ! 16552: over_one: ! 16553: { Ptype tt = ff->argtype->tp; ! 16554: //error('d',"over one %t %t -> %d %d",tt,t2,tt->check(t2,COERCE),const_problem); ! 16555: if (tt->check(t2,COERCE)==0) ! 16556: val = 1; ! 16557: else if (const_problem) { ! 16558: Pptr p1 = tt->is_ptr_or_ref(); ! 16559: if (p1==0 || p1->typ->tconst()) val = 1; ! 16560: } ! 16561: if (tt=tt->is_ref()) { ! 16562: Pptr pt = t2->addrof(); // handle derived classed ! 16563: tt->base = PTR; ! 16564: if (tt->check(pt,COERCE) == 0) { ! 16565: tt->base = RPTR; ! 16566: delete pt; ! 16567: val = 1; ! 16568: goto oper_coerce; ! 16569: } ! 16570: tt->base = RPTR; ! 16571: delete pt; ! 16572: } ! 16573: break; ! 16574: } ! 16575: default: ! 16576: if (ff->argtype->n_list->n_initializer) goto over_one; ! 16577: } ! 16578: } ! 16579: goto oper_coerce; ! 16580: } ! 16581: default: ! 16582: error('i',"cannot_coerce(%k)\n",f->base); ! 16583: } ! 16584: } ! 16585: ! 16586: oper_coerce: ! 16587: //error('d',"oper_coerce %d",val); ! 16588: if (c2) { ! 16589: Pclass cl = Pclass(c2->tp); ! 16590: int std = 0; ! 16591: int oval = val; ! 16592: extern Pname conv_dominates(Pname,Pname); ! 16593: for (Pname ox, on=cl->conv; on; on=ox) { ! 16594: ox = on->n_list; ! 16595: // error( 'd', "can_coerce: ox: %s on: %s tp: %k", ox?ox->string:"", on->string, on->tp->base ); ! 16596: Plist gl = 0; ! 16597: if ( on->tp->base == OVERLOAD ) { ! 16598: gl = Pgen(on->tp)->fct_list; ! 16599: on = gl->f; ! 16600: gl = gl->l; ! 16601: } ! 16602: ! 16603: overlist: ! 16604: // error( 'd', "can coerce: on: %n tp: %t gl: %d", on, on->tp, gl ); ! 16605: ! 16606: Pfct f = Pfct(on->tp); ! 16607: Nstd = 0; ! 16608: if (t1->check(f->returns,COERCE) == 0) { ! 16609: if (Nstd==0) { // forget solutions involving standard conversions ! 16610: Pname old = Ncoerce; ! 16611: if (std) { // forget ! 16612: val = oval+1; ! 16613: std = 0; ! 16614: Ncoerce = on; ! 16615: } ! 16616: else if (Ncoerce == 0) { ! 16617: // val = 1; ! 16618: val++; ! 16619: Ncoerce = on; ! 16620: } ! 16621: else if ((Ncoerce = conv_dominates(Ncoerce,on))==0) { ! 16622: if (val == 1) { ! 16623: //error('d',"val==1 on %n old %n",on,old); ! 16624: Ptype ton = Pfct(on->tp)->returns; ! 16625: Ptype tco = Pfct(old->tp)->returns; ! 16626: if (t1->check(ton,0)==0) ! 16627: ; ! 16628: else if (t1->check(tco,0)==0) ! 16629: on = old; ! 16630: else ! 16631: val++; ! 16632: } ! 16633: else ! 16634: val++; ! 16635: Ncoerce = on; ! 16636: } ! 16637: } ! 16638: else { // take note only if no exact match seen ! 16639: if (Ncoerce==0 || on->tp->check(Ncoerce->tp,0)) { ! 16640: if (val==0 || std) { ! 16641: ! 16642: if (Ncoerce) Ncoerce = conv_dominates(Ncoerce,on); ! 16643: if (Ncoerce == 0) { ! 16644: Ncoerce = on; ! 16645: val++; ! 16646: std = 1; ! 16647: } ! 16648: } ! 16649: } ! 16650: } ! 16651: } ! 16652: // error( 'd', "can_coerce: gl: %d", gl ); ! 16653: if ( gl ) { ! 16654: on = gl->f; ! 16655: gl = gl->l; ! 16656: goto overlist; // must walk list of overloaded instances ! 16657: } ! 16658: } ! 16659: } ! 16660: //error('d',"val %d",val); ! 16661: if (val) return val; ! 16662: if (c1 && Pclass(c1->tp)->has_itor()) return 0; ! 16663: //error('d',"%t->check(%t) -> %d",t1,t2,t1->check(t2,COERCE)); ! 16664: if (t1->check(t2,COERCE)) return 0; ! 16665: return 1; ! 16666: } ! 16667: ! 16668: int gen_coerce(Pname n, Pexpr arg) ! 16669: /* ! 16670: look to see if the argument list "arg" can be coerced into a call of "n" ! 16671: 1: it can ! 16672: 0: it cannot or it can be done in more than one way ! 16673: */ ! 16674: { ! 16675: Pfct f = (Pfct) n->tp; ! 16676: register Pexpr e; ! 16677: register Pname nn; ! 16678: ! 16679: //error('d',"gen_coerce(%n,%d) %t",n,arg,n->tp); ! 16680: for (e=arg, nn=f->argtype; e; e=e->e2, nn=nn->n_list) { ! 16681: if (nn == 0) return f->nargs_known==ELLIPSIS; ! 16682: Pexpr a = e->e1; ! 16683: Ptype at = a->tp; ! 16684: int i = can_coerce(nn->tp,at); ! 16685: if (i != 1) return 0; ! 16686: } ! 16687: if (nn && nn->n_initializer==0) return 0; ! 16688: return 1; ! 16689: } ! 16690: ! 16691: ! 16692: Pname Nover; ! 16693: // int Nover_coerce; ! 16694: ! 16695: int over_call(Pname n, Pexpr arg) ! 16696: /* ! 16697: return 4 if n(arg) can be performed without coercion of arg ! 16698: return 3 if n(arg) can be performed only with promotion coercion of arg ! 16699: return 2 if n(arg) can be performed only with standard coercion of arg ! 16700: return 1 if n(arg) can be performed only with user defined coercion of arg ! 16701: return 0 if n(arg) is an error ! 16702: Nover is the function found, if any ! 16703: Nstd is the number of standard coercions used ! 16704: */ ! 16705: { ! 16706: register Plist gl; ! 16707: Pgen g = Pgen(n->tp); ! 16708: if (arg && arg->base!= ELIST) error('i',"ALX"); ! 16709: ! 16710: //error('d',"over_call(%n) %k",n,n->tp->base); ! 16711: extern suppress_error; ! 16712: suppress_error = 1; ! 16713: // Nover_coerce = 0; ! 16714: Nstd = 0; ! 16715: switch (g->base) { ! 16716: default: error('i',"over_call(%t)\n",g); ! 16717: case OVERLOAD: break; ! 16718: case FCT: ! 16719: Nover = n; ! 16720: Ninit = 0; ! 16721: if (exact_match(n,arg)) {suppress_error = 0; return 4;} ! 16722: if (prom_match(n,arg)) {suppress_error = 0; return 3;} ! 16723: if (std_match(n,arg) && Ninit==0) {suppress_error = 0; return 2;} ! 16724: Nstd = 0; ! 16725: suppress_error = 0; ! 16726: return gen_coerce(n,arg); ! 16727: } ! 16728: ! 16729: Pname exact = 0; ! 16730: int no_exact = 0; ! 16731: int ret = 0; ! 16732: Pname nret; ! 16733: for (gl=g->fct_list; gl; gl=gl->l) { /* look for match */ ! 16734: Nover = gl->f; ! 16735: Ninit = 0; ! 16736: Nstd = 0; ! 16737: if (exact_match(Nover,arg)) {suppress_error = 0; return 4;} // no coercion ! 16738: // if (prom_match(Nover,arg)) return 3; // only promotion ! 16739: // if (std_match(Nover,arg) && Ninit==0) return 2; // only built-in conversion ! 16740: if (ret<3 && prom_match(Nover,arg)) { ! 16741: nret = Nover; ! 16742: ret = 3; ! 16743: } ! 16744: if (ret<2 && std_match(Nover,arg) && Ninit==0) { ! 16745: nret = Nover; ! 16746: ret = 2; ! 16747: } ! 16748: } ! 16749: ! 16750: suppress_error = 0; ! 16751: if (ret) { ! 16752: Nover = nret; ! 16753: return ret; ! 16754: } ! 16755: ! 16756: Nover = 0; ! 16757: for (gl=g->fct_list; gl; gl=gl->l) { /* look for coercion */ ! 16758: Pname nn = gl->f; ! 16759: if (gen_coerce(nn,arg)) { ! 16760: Nover = nn; ! 16761: return 1; ! 16762: } ! 16763: } ! 16764: return 0; ! 16765: ! 16766: } ! 16767: ! 16768: Ptype expr::call_fct(Ptable tbl) ! 16769: /* ! 16770: check "this" call: ! 16771: e1(e2) ! 16772: e1->typ() and e2->typ() has been done ! 16773: */ ! 16774: { ! 16775: Pfct f; ! 16776: Pname fn; ! 16777: int x; ! 16778: int k; ! 16779: Pname nn; ! 16780: Pexpr e; ! 16781: Ptype t; ! 16782: Pexpr arg = e2; ! 16783: Ptype t1 = e1?e1->tp:0; ! 16784: int argno; ! 16785: Pexpr etail = 0; ! 16786: bit no_change = 0; ! 16787: Pname no_virt = 0; // set if explicit qualifier was used: c::f() ! 16788: Pname chk = 0; // set if visibility check is needed ! 16789: // that is if function name might have been ! 16790: // found without use of find_name() ! 16791: int const_obj = 0; ! 16792: ! 16793: if (t1 == any_type) return any_type; ! 16794: ! 16795: switch (base) { ! 16796: case CALL: ! 16797: case G_CALL: break; ! 16798: default: error('i',"call_fct(%k)",base); ! 16799: } ! 16800: ! 16801: // error('d',"call %d %k %n arg %d",this,e1->base,e1->base==NAME?e1:0,arg); ! 16802: if (t1 == 0) error('i',"call_fct(e1=%d,e1->tp=%t)",e1,t1); ! 16803: if (arg && arg->base!=ELIST) error('i',"badAL%d%k",arg,arg->base); ! 16804: ! 16805: switch (e1->base) { ! 16806: case NAME: ! 16807: fn = Pname(e1); ! 16808: //error('d',"name %n %k",fn,fn->n_oper); ! 16809: switch (fn->n_oper) { ! 16810: case 0: ! 16811: case CTOR: ! 16812: case DTOR: ! 16813: case TYPE: ! 16814: case NEW: ! 16815: case DELETE: ! 16816: break; ! 16817: default: // real operator: check for operator+(1,2); ! 16818: if (arg == 0) break; ! 16819: Pexpr a = arg->e1; // first operand ! 16820: ! 16821: if (Pfct(fn->tp)->memof // obj.operator(1) is OK ! 16822: || a->tp->is_cl_obj() ! 16823: || a->tp->is_ref()) break; ! 16824: a = arg->e2; ! 16825: if (a == 0) // unary ! 16826: error("%k of basicT",fn->n_oper); ! 16827: else { // binary ! 16828: a = a->e1; // second operand ! 16829: if (a->tp->is_cl_obj() || a->tp->is_ref()) break; ! 16830: error("%k of basicTs",fn->n_oper); ! 16831: } ! 16832: break; ! 16833: } ! 16834: break; ! 16835: case REF: ! 16836: case DOT: ! 16837: no_virt = Pname(e1->n_initializer); ! 16838: e1->n_initializer = 0; ! 16839: if (e1 && e1->e1) { ! 16840: Ptype t = e1->e1->tp; ! 16841: Pptr tt = t->is_ptr_or_ref(); ! 16842: Ptype ft = tt ? tt->typ : t; ! 16843: Pexpr ee = e1->e1; ! 16844: const_obj = ft->tconst(); ! 16845: while (ee && (ee->base==DOT || ee->base==REF)) { ! 16846: Pexpr m = ee->mem; ! 16847: if ( ee->base==REF && m->tp && m->tp->is_ptr()) ! 16848: break; ! 16849: ee = ee->e1; ! 16850: } ! 16851: if (ee) { ! 16852: Ptype ttt = ee->tp; ! 16853: int tc; ! 16854: switch (e1->base) { ! 16855: case REF: ! 16856: Pptr p = ttt?ttt->is_ptr():0; ! 16857: if (p && p->typ->tconst()) ! 16858: const_obj = 1; ! 16859: break; ! 16860: case DOT: ! 16861: tc = ttt ? ttt->tconst() : 0; ! 16862: if(ttt && tc && (!strict_opt || tc!=2)) ! 16863: const_obj = 1; ! 16864: } ! 16865: } ! 16866: } ! 16867: case MDOT: ! 16868: { Pexpr n = e1->mem; ! 16869: lxlx: ! 16870: switch (n->base) { ! 16871: case MDOT: ! 16872: // reverse mdot (see expr::print()) ! 16873: // p->a.b() => (&p->a)->b() => b(&p->a) ! 16874: // or p->a->b() => (p->a)->b() => b(p->a) ! 16875: // or oo.a.b() => (&oo.a)->b() => b(&oo.a) ! 16876: // or oo.a->b() => (oo.a)->b() => b(oo.a) ! 16877: { ! 16878: Pexpr r = e1; ! 16879: Pexpr p = r->e1; ! 16880: for (Pexpr m = r->mem; m->base==MDOT; m = r->mem) { ! 16881: p = new mdot(m->string2,p); ! 16882: p->i1 = m->i1+2; ! 16883: p->tp = p->mem->tp; ! 16884: r->mem = m->mem; ! 16885: r->e1 = p; ! 16886: } ! 16887: } ! 16888: case REF: ! 16889: case DOT: ! 16890: n = n->mem; ! 16891: goto lxlx; ! 16892: case NAME: ! 16893: break; ! 16894: default: ! 16895: error('i',"ref %k",n->base); ! 16896: } ! 16897: fn = Pname(n); ! 16898: //error('d',"mem %n",fn); ! 16899: break; ! 16900: } ! 16901: case MEMPTR: ! 16902: default: ! 16903: fn = 0; ! 16904: }; ! 16905: ! 16906: lll: ! 16907: //error('d',"lll: %t %k",t1,t1->base); ! 16908: switch (t1->base) { ! 16909: case TYPE: ! 16910: t1 = Pbase(t1)->b_name->tp; ! 16911: goto lll; ! 16912: ! 16913: case PTR: // pf() allowed as shorthand for (*pf)() ! 16914: switch (Pptr(t1)->typ->base) { ! 16915: case FCT: ! 16916: case OVERLOAD: ! 16917: if (Pptr(t1)->memof) error("O missing in call throughP toMF"); ! 16918: t1 = Pptr(t1)->typ; ! 16919: fn = 0; ! 16920: goto lll; ! 16921: } ! 16922: ! 16923: default: ! 16924: if (fn) ! 16925: error("call of%n;%n is a%t",fn,fn,e1->tp); ! 16926: else ! 16927: error("call of%kE ofT%t",e1->base,e1->tp); ! 16928: ! 16929: case ANY: ! 16930: return any_type; ! 16931: ! 16932: case OVERLOAD: ! 16933: { register Plist gl; ! 16934: Pgen g = Pgen(t1); ! 16935: Pname found = 0; ! 16936: Pname exact = 0; ! 16937: int no_exact = 0; ! 16938: int no_gen = 0; ! 16939: ! 16940: for (gl=g->fct_list; gl; gl=gl->l) { // look for exact match ! 16941: register Pname nn = gl->f; ! 16942: if (exact_match(nn,arg)) { ! 16943: //error('d',"found exact %n %t",nn,nn->tp); ! 16944: if (found) { ! 16945: // check if one fct dominates the other ! 16946: Pname d = dominate(found,nn,arg,const_obj,0); ! 16947: if (d) ! 16948: nn = d; ! 16949: else ! 16950: error("two exact matches for%n:%t and%t",nn,nn->tp,found->tp); ! 16951: } ! 16952: found = nn; ! 16953: } ! 16954: } ! 16955: //error('d',"found exact2 %n",found); ! 16956: if (found) goto fnd; ! 16957: ! 16958: Pname mvec[20]; ! 16959: ! 16960: /**************************************************************************** ! 16961: the next 2 loops have been commented out to eliminate the rule that calls ! 16962: requiring only promotions and standard conversions are preferred over ! 16963: calls requiring user-defined conversions. ! 16964: ! 16965: for (gl=g->fct_list; gl; gl=gl->l) { // look for exact match ! 16966: register Pname nn = gl->f; ! 16967: ! 16968: if (prom_match(nn,arg)) { ! 16969: if (found) { ! 16970: // check if one fct dominates the other ! 16971: Pname d = dominate(found,nn,arg,const_obj,1); ! 16972: if (d) ! 16973: nn = d; ! 16974: else ! 16975: error("two exact matches (after integral promotions) for%n:%t and%t",nn,nn->tp,found->tp); ! 16976: } ! 16977: found = nn; ! 16978: } ! 16979: } ! 16980: //error('d',"found exact2 %n",found); ! 16981: if (found) goto fnd; ! 16982: ! 16983: // for (gl=g->fct_list; gl; gl=gl->l) { // look for exact match ! 16984: // register Pname nn = gl->f; ! 16985: // ! 16986: // if (exact_match(nn,arg) || prom_match(nn,arg)) { ! 16987: // found = nn; ! 16988: // goto fnd; ! 16989: // } ! 16990: // } ! 16991: ! 16992: for (gl=g->fct_list; gl; gl=gl->l) { // look for match ! 16993: // with standard conversion ! 16994: register Pname nn = gl->f; ! 16995: Ninit = 0; ! 16996: Nstd = 0; ! 16997: if (std_match(nn,arg)) { ! 16998: // if (Nstd == 0) { ! 16999: // found = nn; ! 17000: // goto fnd; ! 17001: // } ! 17002: if (exact) { ! 17003: // check if one fct dominates the other ! 17004: Pname d = dominate(exact,nn,arg,const_obj,2); ! 17005: if (d == 0) { ! 17006: mvec[no_exact++] = nn; ! 17007: // no_exact++; ! 17008: // error("two standard conversions possible for%n: %t and %t",fn,exact->tp,nn->tp); ! 17009: } ! 17010: else ! 17011: exact = d; ! 17012: } ! 17013: else ! 17014: exact = nn; ! 17015: } ! 17016: ! 17017: } ! 17018: ! 17019: //error('d',"excact %n",exact); ! 17020: if (exact) { ! 17021: if (no_exact) { ! 17022: while (no_exact) { ! 17023: Pname d = dominate(exact,mvec[--no_exact],arg,const_obj,2); ! 17024: if (d) ! 17025: exact = d; ! 17026: else ! 17027: error("two standard conversions possible for%n: %t and %t",fn,exact->tp,mvec[no_exact]->tp); ! 17028: } ! 17029: ! 17030: } ! 17031: //error('d',"found exact3 %n",found); ! 17032: found = exact; ! 17033: goto fnd; ! 17034: } ! 17035: ! 17036: this is the end of the commented out section. ! 17037: ************************************************************************/ ! 17038: ! 17039: for (gl=g->fct_list; gl; gl=gl->l) { /* look for coercion */ ! 17040: register Pname nn = gl->f; ! 17041: if (prom_match(nn,arg) || ! 17042: std_match(nn,arg) || ! 17043: gen_coerce(nn,arg)) { ! 17044: //error('d',"user2 %n %t",nn,nn->tp); ! 17045: if (found) { ! 17046: // check if one fct dominates the other ! 17047: Pname d = dominate(found,nn,arg,const_obj,3); ! 17048: //error('d',"dom d %d",d); ! 17049: if (d == 0) d = user_dominate(found,nn,arg); ! 17050: if (d == 0) { ! 17051: mvec[no_gen++] = nn; ! 17052: } ! 17053: else ! 17054: found = d; ! 17055: } ! 17056: else ! 17057: found = nn; ! 17058: } ! 17059: } ! 17060: if(found) { ! 17061: while(no_gen) { ! 17062: Pname d = dominate(found,mvec[--no_gen],arg,const_obj,3); ! 17063: if(d==0) d = user_dominate(found,mvec[no_gen],arg); ! 17064: if(d) ! 17065: found = d; ! 17066: else { ! 17067: //error("ambiguousA for%n: %t and %t",fn,found->tp,mvec[no_gen]->tp); ! 17068: error("ambiguous call of%n: %t and %t",fn,found->tp,mvec[no_gen]->tp); ! 17069: } ! 17070: } ! 17071: } ! 17072: fnd: ! 17073: //error('d',"fnd %t",found?found->tp:0); ! 17074: if (found) { ! 17075: overFound = chk = fn = found; ! 17076: f = Pfct(fn->tp); ! 17077: } ! 17078: else { ! 17079: error("badAL for%n (no match against any %n)",fn,fn); ! 17080: return any_type; ! 17081: } ! 17082: break; ! 17083: } ! 17084: case FCT: ! 17085: f = Pfct(t1); ! 17086: if (fn) { ! 17087: switch (fn->n_oper) { ! 17088: case CTOR: ! 17089: case TYPE: ! 17090: chk = fn; ! 17091: } ! 17092: } ! 17093: } ! 17094: ! 17095: //error('d',"chk %n",chk); ! 17096: if (chk) { ! 17097: Ptype t = 0; ! 17098: Pexpr ee = e1->e1; ! 17099: ! 17100: switch (e1->base) { ! 17101: case REF: // ptr->chk() ! 17102: if (ee == 0) { // 0->x() fudge handling new x() ! 17103: check_visibility(chk,no_virt,Pclass(chk->n_table->t_name->tp),tbl,cc->nof); ! 17104: break; ! 17105: }; ! 17106: t = ee->tp; ! 17107: while(t->base==TYPE) t = Pbase(t)->b_name->tp; ! 17108: t = Pptr(t)->typ; ! 17109: break; ! 17110: case DOT: // obj.chk() ! 17111: t = ee->tp; ! 17112: } ! 17113: ! 17114: Pname cn = t?t->is_cl_obj():0; ! 17115: Pclass cl = cn?Pclass(cn->tp):0; // class of ``this'' for chk ! 17116: ! 17117: if (cl) { ! 17118: if (chk->n_oper==CTOR ! 17119: && chk->n_protect ! 17120: && cc->nof ! 17121: && cc->nof->n_oper==CTOR) ! 17122: // BUG: cannot handle protected base ! 17123: // class constructor ! 17124: ; ! 17125: else { ! 17126: check_visibility(chk,no_virt,cl,tbl,cc->nof); ! 17127: } ! 17128: } ! 17129: } ! 17130: ! 17131: if (fn && f->returns->is_cl_obj() && f->f_result==0) { ! 17132: // protect against class cn; cn f(); ... class cn { cn(cn&); ... }; ! 17133: make_res(f); ! 17134: //error('d',"returns %t",f->returns); ! 17135: f->returns->tsizeof(); // make sure it is declared ! 17136: } ! 17137: ! 17138: //error('d',"fn %n %t printed %d",fn,fn?fn->tp:0,fn?fn->n_dcl_printed:0); ! 17139: if (fn && fn->n_dcl_printed==0) { ! 17140: if (f->f_inline==0 && f->f_imeasure) { ! 17141: extern void uninline(Pname fn); ! 17142: uninline(fn); ! 17143: } ! 17144: ! 17145: // ensure printout of class declaration: ! 17146: for (Pname nn=f->argtype; nn; nn=nn->n_list) ! 17147: if (nn->tp->is_cl_obj()) (void) nn->tp->tsizeof(); ! 17148: ! 17149: fn->dcl_print(0); ! 17150: } ! 17151: ! 17152: if (no_virt && f->f_static==0) { ! 17153: if (e1->base==REF || e1->base==DOT) e1->n_initializer = fn; ! 17154: } ! 17155: else ! 17156: fct_name = fn; ! 17157: //error('d',"fn %n %t %d %d",fn,f,f->f_this,f->f_static); ! 17158: if (f->f_this) { //SSS call of non-static memberfunction ! 17159: switch (e1->base) { ! 17160: case MEMPTR: ! 17161: case REF: ! 17162: case DOT: ! 17163: break; ! 17164: default: ! 17165: error("O orP missing for%n ofT %t",fct_name,f); ! 17166: } ! 17167: } ! 17168: else if (fn) { //SSS call of static function ! 17169: sss: ! 17170: switch (e1->base) { ! 17171: case REF: ! 17172: case DOT: ! 17173: e1 = e1->mem; ! 17174: goto sss; ! 17175: } ! 17176: } ! 17177: ! 17178: if (fn) fn->use(); // a patch: ctors are sometimes not use()d ! 17179: ! 17180: if (f->f_const==0 ! 17181: && (fn==0 || (fn->n_oper!=CTOR && fn->n_oper!=DTOR))) { //CCC ! 17182: Pexpr ee = e1->e1; ! 17183: // while (ee && (ee->base==DOT || ee->base==REF)) ee = ee->e1; ! 17184: while (ee && (ee->base==DOT || ee->base==REF)) { ! 17185: Pexpr m = ee->mem; ! 17186: // error('d', "m: %k tp %t", m?m->base:0, m?m->tp:0 ); ! 17187: if ( ee->base==REF && m->tp && m->tp->is_ptr()) ! 17188: break; ! 17189: ee = ee->e1; ! 17190: } ! 17191: // error('d', "ee: %k tp %k", ee?ee->base:0, ee?ee->tp->base:0); ! 17192: ! 17193: if (ee) { ! 17194: Ptype tt = ee->tp; ! 17195: switch (e1->base) { ! 17196: case REF: ! 17197: { Pptr p = tt?tt->is_ptr():0; ! 17198: if (p && p->typ->tconst()) ! 17199: error(strict_opt?0:'w',"non-constMF%n called for constO (anachronism)",fn); ! 17200: // is really an error, but only warn to help transition ! 17201: break; ! 17202: } ! 17203: case DOT: ! 17204: int tc = tt ? tt->tconst() : 0; ! 17205: if (tt && tc && (!strict_opt || tc!=2)) ! 17206: error(strict_opt?0:'w',"non-constMF%n called for constO (anachronism)",fn); ! 17207: // is really an error, but only warn to help transition ! 17208: } ! 17209: } ! 17210: } ! 17211: ! 17212: t = f->returns; ! 17213: x = f->nargs; ! 17214: k = f->nargs_known; ! 17215: ! 17216: e = arg; ! 17217: if (k == 0) goto rlab; ! 17218: ! 17219: for (nn=f->argtype, argno=1; e||nn; nn=nn->n_list, e=etail->e2, argno++) { ! 17220: Pexpr a; ! 17221: int save_base = 0; ! 17222: char* save_name = 0; ! 17223: ! 17224: if (e) { ! 17225: a = e->e1; ! 17226: etail = e; ! 17227: ! 17228: if (nn) { /* type check */ ! 17229: Ptype t1 = nn->tp; ! 17230: //error('d',"argtp %t etp %t a %k",t1,a->tp,a->base); ! 17231: ! 17232: while(t1->base == TYPE) ! 17233: t1 = Pbase(t1)->b_name->tp; ! 17234: ! 17235: switch (t1->base) { ! 17236: case RPTR: ! 17237: { Ptype pt = Pptr(t1)->typ; ! 17238: if (pt->base != FCT || ! 17239: ( pt->base == FCT && ! 17240: pt->check(a->tp,0))) ! 17241: a = ref_init(Pptr(nn->tp),a,tbl); ! 17242: goto cbcb; ! 17243: } ! 17244: case COBJ: ! 17245: if (a->base!=G_CM ! 17246: || nn->tp->check(a->tp,ASSIGN)) ! 17247: a = class_init(0,t1,a,tbl); ! 17248: else ! 17249: a->e2=class_init(0,t1,a->e2,tbl); ! 17250: if (nn->n_xref) { ! 17251: // (temp.ctor(arg),&arg) ! 17252: a = a->address(); ! 17253: } ! 17254: else { ! 17255: // defend against: ! 17256: // int f(X); ... X(X&); ! 17257: Pname cln = Pbase(t1)->b_name; ! 17258: if (cln && Pclass(cln->tp)->has_itor()) { ! 17259: // mark X(X&) arguments ! 17260: nn->n_xref = 1; ! 17261: a = a->address(); ! 17262: } ! 17263: } ! 17264: cbcb: ! 17265: //error('d',"cbcb: a %d %k %t",a->base,a->base,a->tp); ! 17266: if (a->base==G_CM) { ! 17267: if (a->e1->base==DEREF) a->e1 = a->e1->e2; // (*e1,e2) => (e1,e2) ! 17268: //error('d'," a %d %k",a->e1->base,a->e1->base); ! 17269: if (a->e1->base==G_CALL ! 17270: && Pname(a->e1->fct_name) ! 17271: && Pname(a->e1->fct_name)->n_oper==CTOR ! 17272: && (a->e2->base==G_ADDROF || a->e2->base==ADDROF)) { ! 17273: a = a->e1; // (ctor(&tmp),&tmp) => ctor(&tmp) ! 17274: //error('d',"tmp %k %n",a->e2->base,a->e2->e2); ! 17275: goto cccc; ! 17276: } ! 17277: else if (a->e2->base==G_ADDROF ! 17278: && a->e2->e2->base==NAME) { ! 17279: cccc: ! 17280: //error('d',"cccc: a %d %k %t",a->base,a->base,a->tp); ! 17281: if (t1->base==RPTR ! 17282: && Pptr(t1)->typ->tconst()==0) { // temporary used ! 17283: if (warning_opt) ! 17284: error('w',"temporary used for non-const%tA",nn->tp); ! 17285: else { ! 17286: Ptype atp = a->tp; ! 17287: if (atp==void_type ! 17288: && a->base==G_CALL ! 17289: && a->e1->tp->base==FCT) ! 17290: atp = Pfct(a->e1->tp)->s_returns; ! 17291: ! 17292: Ptype tt = t1->is_ref(); ! 17293: //error('d',"tt %t atp %t",tt,atp); ! 17294: if (tt) { ! 17295: if (Pptr(tt)->typ->tsizeof()!=atp->tsizeof()) { // sliced ! 17296: Ptype aat = atp->is_ptr_or_ref(); ! 17297: if (aat==0 ! 17298: || Pptr(tt)->typ->tsizeof()!=Pptr(aat)->typ->tsizeof()) ! 17299: error('w',"temporary used for non-const%tA",nn->tp); ! 17300: } ! 17301: } ! 17302: else if (t1->tsizeof()!=atp->tsizeof()) // sliced ! 17303: error('w',"temporary used for non-const%tA",nn->tp); ! 17304: } ! 17305: ! 17306: // if (warning_opt // blabber ! 17307: // || t1->tsizeof()!=a->tp->tsizeof())) // sliced ! 17308: // error('w',"temporary used for non-const%tA",nn->tp); ! 17309: ! 17310: } ! 17311: } ! 17312: } ! 17313: e->e1 = a; ! 17314: break; ! 17315: case ANY: ! 17316: goto rlab; ! 17317: case PTR: ! 17318: { ! 17319: save_base = e->e1->base; ! 17320: if(a->tp->base==OVERLOAD) ! 17321: save_name = Pgen(a->tp)->fct_list->f->string; ! 17322: Pexpr te_a = a; ! 17323: e->e1 = a = ptr_init(Pptr(t1),a,tbl); ! 17324: no_change = (te_a == a); ! 17325: // if (x==a || x==a->e2) goto def; // needs checking ! 17326: if (Pchecked == 0) goto def; ! 17327: break; ! 17328: } ! 17329: // e->e1 = a = ptr_init(Pptr(t1),a,tbl); ! 17330: // goto def; ! 17331: case CHAR: ! 17332: case SHORT: ! 17333: case INT: ! 17334: // if (a->base==ICON && a->tp==long_type) ! 17335: // error('w',"long constantA for%n,%kX",fn,t1->base); ! 17336: { Ptype t = a->tp; ! 17337: while(t->base == TYPE) ! 17338: t = Pbase(t)->b_name->tp; ! 17339: ! 17340: switch (t->base) { ! 17341: case LONG: ! 17342: case FLOAT: ! 17343: case DOUBLE: ! 17344: case LDOUBLE: ! 17345: error('w',"A%d: %t passed as %t",argno,a->tp,t1); ! 17346: } ! 17347: } ! 17348: // no break ! 17349: case LONG: ! 17350: if (Pbase(t1)->b_unsigned ! 17351: && a->base==UMINUS ! 17352: && a->e2->base==ICON) ! 17353: error('w',"negativeA for%n, unsignedX",fn); ! 17354: default: ! 17355: def: ! 17356: { Pexpr x = try_to_coerce(t1,a,"argument",tbl); ! 17357: //error('d',"x %d t1 %t nn %t a1 %t",x,t1,nn->tp,a->tp); ! 17358: if (x) { ! 17359: if (Pchecked == 0 && no_change) { ! 17360: Pexpr te_x = ptr_init(Pptr(t1), x, tbl); ! 17361: ! 17362: if ( te_x != x ) e->e1 = a = te_x; else e->e1=x; ! 17363: } ! 17364: else ! 17365: e->e1 = x; ! 17366: } ! 17367: else if (nn->tp->check(a->tp,ARG)) { ! 17368: error("badA %dT for%n:%t (%tX)",argno,fn,a->tp,nn->tp); ! 17369: return any_type; ! 17370: } ! 17371: } ! 17372: } ! 17373: ! 17374: Pexpr tt = e->e1; ! 17375: while ( tt->base == CAST ) ! 17376: tt = tt->e1; ! 17377: if ( tt->base == ILIST ) ! 17378: e->e1 = tt; ! 17379: ! 17380: if (e->e1->base == ILIST) { ! 17381: // memptr constant ! 17382: // f({1,2,f}) ==> memptr t; f((t={1,2,f},t)) ! 17383: if(save_base == REF) { ! 17384: Pptr m = Pptr(a->tp); ! 17385: error(strict_opt?0:'w', ! 17386: "address of boundF (try using ``%s::*'' forPT and ``&%s::%s'' for address) (anachronism)", ! 17387: m->memof->string, ! 17388: m->memof->string, ! 17389: save_name ! 17390: ); ! 17391: } ! 17392: Pname temp = make_tmp('A',mptr_type,tbl); ! 17393: e->e1 = mptr_assign(temp,e->e1); ! 17394: e->e1 = a = new expr(G_CM,e->e1,temp); ! 17395: a->tp = temp->tp; ! 17396: } ! 17397: ! 17398: } ! 17399: else { ! 17400: if (k != ELLIPSIS) { ! 17401: error("unexpected %dA for%n",argno,fn); ! 17402: return any_type; ! 17403: } ! 17404: Pexpr te=e; ! 17405: while(e) { ! 17406: if (e->e1->base == ILIST) { ! 17407: // memptr constant ! 17408: // f({1,2,f}) ==> memptr t; f((t={1,2,f},t)) ! 17409: Pname temp = make_tmp('A',mptr_type,tbl); ! 17410: e->e1 = mptr_assign(temp,e->e1); ! 17411: e->e1 = a = new expr(G_CM,e->e1,temp); ! 17412: a->tp = temp->tp; ! 17413: } ! 17414: e = e->e2; ! 17415: } ! 17416: e = te; ! 17417: goto rlab; ! 17418: } ! 17419: } ! 17420: else { /* default argument? */ ! 17421: a = nn->n_initializer; ! 17422: if (a == 0) { ! 17423: error("A %d ofT%tX for%n",argno,nn->tp,fn); ! 17424: return any_type; ! 17425: } ! 17426: if (a->base == ILIST) { ! 17427: // memptr constant ! 17428: // f({1,2,f}) ==> memptr t; f((t={1,2,f},t)) ! 17429: Pname temp = make_tmp('A',mptr_type,tbl); ! 17430: a = mptr_assign(temp,a); ! 17431: a = new expr(G_CM,a,temp); ! 17432: a->tp = temp->tp; ! 17433: } ! 17434: a->permanent = 2; // ought not be necessary, but it is ! 17435: e = new expr(ELIST,a,0); ! 17436: if (etail) ! 17437: etail->e2 = e; ! 17438: else ! 17439: e2 = e; ! 17440: etail = e; ! 17441: } ! 17442: } ! 17443: ! 17444: rlab: ! 17445: //error('d',"rlab fct_name %n %t",fct_name,fct_name?fct_name->tp:0); ! 17446: for (; e; e = e->e2) { // unchecked arguments ! 17447: Pexpr a = e->e1; ! 17448: Pname cn; ! 17449: ! 17450: if (a->base==NAME && a->tp->base==FCT) { ! 17451: // function name that escaped the type system: ! 17452: // update use count ! 17453: a->lval(ADDROF); ! 17454: } ! 17455: else if (warning_opt && (cn = a->tp->is_cl_obj())) { ! 17456: Pclass cl = Pclass(cn->tp); ! 17457: if (cl->has_ctor() || cl->memtbl->look("__as",0))//cl->has_oper(ASSIGN) ! 17458: { ! 17459: if (fct_name) ! 17460: error('w',"O ofC%t withK or = copied asA to%n (%t)",cl,fct_name,fct_name->tp); ! 17461: else ! 17462: error('w',"O ofC%t withK or = copied asA to `...'",cl); ! 17463: } ! 17464: } ! 17465: else if (a->tp->is_ref()) ! 17466: e->e1 = a->contents(); ! 17467: } ! 17468: ! 17469: if (f->f_result) { // f(args) => (f(&temp,args),temp) ! 17470: Pname tn = make_tmp('R',f->returns,tbl); ! 17471: e2 = new expr(ELIST,tn->address(),e2); ! 17472: // error('d',"result %n refd: %d",fn, refd); ! 17473: Pexpr ee = new expr(0,0,0); ! 17474: *ee = *this; ! 17475: base = G_CM; // (f(&temp,args),temp) ! 17476: e1 = ee; ! 17477: if (refd == 2) ! 17478: e2 = tn->address(); ! 17479: else e2 = tn; ! 17480: tp = tn->tp; ! 17481: } ! 17482: ! 17483: return t; ! 17484: } ! 17485: ! 17486: int cm_const_save; ! 17487: ! 17488: Pexpr ref_init(Pptr p, Pexpr init, Ptable tbl) ! 17489: /* ! 17490: initialize the "p" with the "init" ! 17491: remember to call ptr_init to ensure that pointers to second bases ! 17492: are handled correctly. ! 17493: */ ! 17494: { ! 17495: register Ptype it = init->tp; ! 17496: Pptr px = p; ! 17497: while (px->base == TYPE) px = Pptr(Pbase(px)->b_name->tp); ! 17498: Ptype p1 = px->typ; ! 17499: Pname c1 = p1->is_cl_obj(); ! 17500: // error('d',"ref_init: p %t, p1 %t, px %t, init->tp %t",p,p1,px,it); ! 17501: // error('d', "ref_init: nof: %n f_const: %d", cc?cc->nof:0, cc?(cc->nof?Pfct(cc->nof->tp)->f_const:0):0); ! 17502: ! 17503: if (init->base == ILIST) error("IrL as RIr"); ! 17504: ! 17505: if (init->base==NAME ! 17506: && Pname(init)->n_scope==ARG ! 17507: && init->tp->base==FLOAT) ! 17508: error('w',"initializing a float& with floatA is non-portable"); ! 17509: ! 17510: while(it->base == TYPE) ! 17511: it = Pbase(it)->b_name->tp; ! 17512: ! 17513: switch (it->base) { ! 17514: default: ! 17515: { Ptype tt = it->addrof(); ! 17516: px->base = PTR; // allow &x for y& when y : public x ! 17517: // but not &char for int& ! 17518: int x = px->check(tt,COERCE); ! 17519: ! 17520: if (x == 0) { //CCC type is fine check for constness: ! 17521: if (init->tp->tconst() ! 17522: && vec_const==0 ! 17523: && fct_const==0) { ! 17524: // not ``it'' ! 17525: if (init->base == ELIST) init = init->e1; ! 17526: if (px->typ->tconst() == 0) error("R to constO"); ! 17527: px->base = RPTR; ! 17528: // if we have a const lvalue we can still pass its address ! 17529: ignore_const++; ! 17530: if (init->lval(0)) { ! 17531: init->lval(ADDROF); // force output ! 17532: ignore_const--; ! 17533: //error('d',"in1 %t",init->tp); ! 17534: return ptr_init(px,init->address(),tbl);//return init->address(); ! 17535: } ! 17536: ignore_const--; ! 17537: goto xxx; ! 17538: } ! 17539: px->base = RPTR; ! 17540: if (init->lval(0)) { // can pass the address // no temporary needed ! 17541: init->lval(ADDROF); // force output ! 17542: //error('d',"px %t init %t init %t",px,init->tp,init->tp); ! 17543: return ptr_init(px,init->address(),tbl); ! 17544: } ! 17545: goto xxx; ! 17546: } ! 17547: ! 17548: px->base = RPTR; ! 17549: } ! 17550: } ! 17551: ! 17552: //error('d',"c1 %n",c1); ! 17553: if (c1) { // assigning to a const X & is fine ! 17554: ref_cast++; ! 17555: Pexpr x = try_to_coerce(p,init,"reference initialization",tbl); ! 17556: ref_cast--; ! 17557: if (x) { ! 17558: init = x; ! 17559: goto xxx; ! 17560: } ! 17561: while (p1->base==TYPE) p1 = Pbase(p1)->b_name->tp; ! 17562: int bc = Pbase(p1)->b_const; ! 17563: Pbase(p1)->b_const = 0; ! 17564: // refd = 1; ! 17565: switch ( init->base ) { ! 17566: case STRING: case ZERO: case CCON: ! 17567: case ICON: case FCON: case IVAL: ! 17568: case NAME: ! 17569: refd = 1; ! 17570: break; ! 17571: default: ! 17572: refd = (init->e1 && init->e1->base == NAME && ! 17573: init->e1->tp->base != RPTR && ! 17574: Pname(init->e1)->n_xref == 0) ? 2: 1; ! 17575: break; ! 17576: } ! 17577: // error('d', "***** refd: %d", refd ); ! 17578: Pexpr a = class_init(0,p1,init,tbl); ! 17579: Pbase(p1)->b_const = bc; ! 17580: refd = 0; ! 17581: if (a==init && init->tp!=any_type) goto xxx; ! 17582: // error('d',"ri a %d %k",a->base,a->base); ! 17583: switch (a->base) { ! 17584: case G_CALL: ! 17585: // case CM: ! 17586: // case G_CM: ! 17587: init = a; ! 17588: goto xxx; ! 17589: } ! 17590: a = a->address(); ! 17591: a = ptr_init(px,a,tbl); ! 17592: return a; ! 17593: // return ptr_init(px,a->address(),tbl);//a->address(); ! 17594: } ! 17595: ! 17596: //error('d',"p1 %t it %t",p1,it); ! 17597: if (p1->check(it,0)) { ! 17598: ! 17599: if (p1->check(it,ASSIGN) == 0) { ! 17600: // if (p1->is_ptr()) // check for base* = derived* ! 17601: // goto xxx; ! 17602: ! 17603: // things like ``double& rr = 1;'' temporary needed ! 17604: // warn in case of ``slightly wrong lvalue'', e.g. ! 17605: // int i; double& r = i; ! 17606: if (init->lval(0) && p1->tconst()==0) ! 17607: error('w',"temporary used toIR; no changes will be propagated to actualA"); ! 17608: goto def; ! 17609: } ! 17610: ! 17611: Pexpr x = try_to_coerce(p1,init,"reference",tbl); // x==init ! 17612: if (x==0) x = try_to_coerce(px,init,"reference",tbl); // x&=init ! 17613: if (x) { ! 17614: init = x; ! 17615: goto def; ! 17616: } ! 17617: ! 17618: error("badIrT:%t (%tX)",it,p); ! 17619: if (init->base != NAME) init->tp = any_type; ! 17620: return init; ! 17621: } ! 17622: ! 17623: xxx: /* ! 17624: here comes the test of a ``fundamental theorem'': ! 17625: a structure valued expression is ! 17626: (1) an lvalue of type T (possibly const) ! 17627: or (2) the result of a function (a _result if X(X&) is defined) ! 17628: or (3) a * or [] or ? or , expression ! 17629: */ ! 17630: //error('d',"xxx %k %d %t",init->base,init->base,init->tp); ! 17631: ! 17632: switch (init->base) { ! 17633: case NAME: ! 17634: case DEREF: ! 17635: case REF: ! 17636: case DOT: // init => &init ! 17637: if (it->tconst() && vec_const==0 && fct_const==0) goto def; ! 17638: if ( cc && cc->nof && ! 17639: Pfct(cc->nof->tp)->f_const ) ! 17640: cm_const_save = Pbase(p->typ)->b_const; ! 17641: init->lval(ADDROF); ! 17642: cm_const_save = 0; ! 17643: ! 17644: if (vec_const) return init; ! 17645: if (fct_const && p1->is_ptr()) goto def; // fptr& = fct ! 17646: // no break ! 17647: case CM: ! 17648: case G_CM: // & (f(&temp), temp) ! 17649: return ptr_init(px,init->address(),tbl);//init->address(); ! 17650: default: ! 17651: def: ! 17652: { ! 17653: // error('d',"def: init->tp %t p1 %t ",init->tp,p1); ! 17654: // error('d',"p1: %t const_ptr: %d", p1, const_ptr); ! 17655: if (const_ptr == 0) { ! 17656: if (tbl == gtbl || strict_opt) ! 17657: error("Ir for%snon-constR not an lvalue", strict_opt?"":" global "); ! 17658: else ! 17659: if (warning_opt) ! 17660: error('w', "Ir for non-constR not an lvalue (anachronism)"); ! 17661: } ! 17662: ! 17663: Pname tcl = p1->is_cl_obj (); ! 17664: if(tcl && Pclass(tcl->tp)->c_abstract) ! 17665: error("a temporary is needed for a parameter, but the argument type is abstract class %t.", tcl->tp); ! 17666: ! 17667: Pname n = make_tmp('I',p1,tbl); ! 17668: Pexpr a; ! 17669: Pname ic = init->tp->is_cl_obj(); ! 17670: ! 17671: if (p1->tconst()==0 ! 17672: && (init->tp->tconst() && vec_const==0 && fct_const==0) ! 17673: && p1->check(it,ASSIGN)==0) ! 17674: error('w',"constIr: temporary used toI reference"); ! 17675: ! 17676: switch (p1->base) { ! 17677: case INT: ! 17678: case CHAR: ! 17679: case SHORT: ! 17680: switch (it->base) { ! 17681: case LONG: ! 17682: case FLOAT: ! 17683: case DOUBLE: ! 17684: case LDOUBLE: ! 17685: error('w',"%t assigned to %t inRIr",it,p1); ! 17686: } ! 17687: } ! 17688: ! 17689: if (ic!=c1 && Pclass(ic->tp) != Pclass(c1->tp)) { ! 17690: // derived class1 => must cast: ``it Ix; (Ix=init,(p)&Ix);'' ! 17691: n->tp = init->tp; ! 17692: a = ptr_init(px,n->address(),tbl);//n->address(); ! 17693: PERM(p); ! 17694: a = new texpr(CAST,p,a); ! 17695: a->tp = p; ! 17696: } ! 17697: else ! 17698: a = n->address(); ! 17699: ! 17700: refd = 1; ! 17701: Pexpr as = init_tmp(n,init,tbl); ! 17702: refd = 0; ! 17703: a = new expr(G_CM,as,a); ! 17704: a->tp = a->e2->tp; ! 17705: return a; ! 17706: } ! 17707: } ! 17708: } ! 17709: ! 17710: Pexpr class_init(Pexpr nn, Ptype tt, Pexpr init, Ptable tbl) ! 17711: /* ! 17712: initialize "nn" of type "tt" with "init" ! 17713: if nn==0 make a temporary, ! 17714: nn may not be a name ! 17715: */ ! 17716: { ! 17717: if (init == dummy) return 0; ! 17718: //error('d',"class_init %t with %t init %k refd %d",tt,init->tp,init->base,refd); ! 17719: Pname c1 = tt->is_cl_obj(); ! 17720: ! 17721: if (init == 0) { ! 17722: error("emptyIr"); ! 17723: return dummy; ! 17724: } ! 17725: ! 17726: if (c1) { ! 17727: Pclass cl = Pclass(c1->tp); ! 17728: Pname c2 = init->tp->is_cl_obj(); ! 17729: ! 17730: if (c1!=c2 || (refd==0 && cl->has_itor())) { ! 17731: /* really ought to make a temp if refd, ! 17732: but ref_init can do that ! 17733: */ ! 17734: int i = can_coerce(tt,init->tp); ! 17735: //error('d',"i %d nn %n",i,nn); ! 17736: switch (i) { ! 17737: default: ! 17738: error("%d ways of making a%n from a%t",i,c1,init->tp); ! 17739: init->tp = any_type; ! 17740: return init; ! 17741: case 0: ! 17742: if (c2 && Pclass(c2->tp)->has_base(cl)) { ! 17743: init = init->address(); ! 17744: Pexpr x = cast_cptr(cl,init,tbl,0); ! 17745: ! 17746: if (x == init) { ! 17747: Ptype pt = tt->addrof(); ! 17748: PERM(pt); ! 17749: x = new cast(pt,init); ! 17750: } ! 17751: ! 17752: return x->contents(); ! 17753: } ! 17754: error("cannot make a%n from a%t",c1,init->tp); ! 17755: init->tp = any_type; ! 17756: return init; ! 17757: case 1: ! 17758: //error('d',"ncoerce %n %k %d",Ncoerce,init->base,init->base); ! 17759: if (Ncoerce == 0) { ! 17760: Pexpr a = new expr(ELIST,init,0); ! 17761: a = new texpr(VALUE,tt,a); ! 17762: a->e2 = nn; ! 17763: // return a->typ(tbl); ! 17764: a = a->typ(tbl); ! 17765: //error('d',"ci a %k %d %t",a->base,a->base,a->tp); ! 17766: return a; ! 17767: } ! 17768: ! 17769: switch (init->base) { ! 17770: case CM: ! 17771: case G_CM: //ddd ! 17772: case NAME: /* init.coerce() */ ! 17773: /* *ref */ case DEREF: ! 17774: { Pref r = new ref(DOT,init,Ncoerce); ! 17775: Pexpr rr = r->typ(tbl); ! 17776: init = new expr(G_CALL,rr,0); ! 17777: init->fct_name = Ncoerce; ! 17778: break; ! 17779: } ! 17780: default: // (temp=init,temp.coerce()) ! 17781: { Pname tmp = make_tmp('U',init->tp,tbl); ! 17782: int x = refd; ! 17783: refd = 0; // ?? ! 17784: Pexpr ass = init_tmp(tmp,init,tbl); ! 17785: refd = x; ! 17786: Pref r = new ref(DOT,tmp,Ncoerce); ! 17787: Pexpr rr = r->typ(tbl); ! 17788: Pexpr c = new expr(G_CALL,rr,0); ! 17789: c->fct_name = Ncoerce; ! 17790: c = c->typ(tbl); ! 17791: init = new expr(CM,ass,c); ! 17792: init->tp = c->tp; ! 17793: if (refd) { // &f() => (t=f(), &t) ! 17794: Pname tmp2 = make_tmp('L',c->tp,tbl); ! 17795: ass = init_tmp(tmp2,init,tbl); ! 17796: init = new expr(G_CM,ass,tmp2); ! 17797: } ! 17798: } ! 17799: } ! 17800: //error('d',"nn %n",nn); ! 17801: if (nn) { ! 17802: Pexpr a = new expr(ELIST,init,0); ! 17803: a = new texpr(VALUE,tt,a); ! 17804: a->e2 = nn; ! 17805: return a->typ(tbl); ! 17806: } ! 17807: } ! 17808: //error('d',"c1 %n c2 %n",c1,c2); ! 17809: return init->typ(tbl); ! 17810: } ! 17811: return init; ! 17812: } ! 17813: //error('d',"ci check tt %t init->tp %t",tt,init->tp); ! 17814: if (tt->check(init->tp,ASSIGN) && refd==0) { ! 17815: error("badIrT:%t (%tX)",init->tp,tt); ! 17816: init->tp = any_type; ! 17817: } ! 17818: ! 17819: return init; ! 17820: } ! 17821: ! 17822: extern int bound; // fudge for bound pointers to functions ! 17823: ! 17824: Pexpr expr::docast(Ptable tbl) ! 17825: { ! 17826: // check cast against value, INCOMPLETE ! 17827: ! 17828: //error('d',"docast %d %t %k",this,tp2,e1->base); ! 17829: if (e1 == dummy) { ! 17830: error("E missing for cast"); ! 17831: tp = any_type; ! 17832: return this; ! 17833: } ! 17834: ! 17835: int pmf = 0; ! 17836: int ptom_cast = 0; ! 17837: Pexpr ee = e1; ! 17838: ! 17839: //error('d',"ee %k %d",ee->base,ee->base); ! 17840: switch (ee->base) { ! 17841: case ADDROF: ! 17842: ee = ee->e2; ! 17843: switch (ee->base) { ! 17844: case NAME: goto nm; ! 17845: case REF: goto rf; ! 17846: } ! 17847: break; ! 17848: ! 17849: case NAME: ! 17850: nm: ! 17851: if (Pname(ee)->n_qualifier) pmf = 1; ! 17852: break; ! 17853: ! 17854: case REF: ! 17855: rf: ! 17856: if (ee->e1->base == THIS) bound = 1; ! 17857: break; ! 17858: } ! 17859: ! 17860: e1 = e1->typ(tbl); ! 17861: ! 17862: int b = bound; // distinguish between explicit and implicit THIS ! 17863: bound = 0; ! 17864: pmf = pmf && e1->base==CAST; ! 17865: ! 17866: Ptype etp = e1->tp; ! 17867: Ptype tt = tp2; ! 17868: Ptype t = tt; ! 17869: tt->dcl(tbl); ! 17870: ! 17871: while (etp->base == TYPE) etp = Pbase(etp)->b_name->tp; ! 17872: while (tt->base == TYPE) tt = Pbase(tt)->b_name->tp; ! 17873: ! 17874: //error('d',"e1 %k etp %t tt %t",e1->base,etp,tt); ! 17875: ! 17876: switch (etp->base) { ! 17877: case PTR: ! 17878: case RPTR: ! 17879: if (Pptr(etp)->typ->base == OVERLOAD) goto over; ! 17880: ! 17881: if (warning_opt && i2==0 && Pptr(etp)->typ->tconst()) { ! 17882: switch (tt->base) { ! 17883: case FCT: ! 17884: break; ! 17885: case PTR: ! 17886: case RPTR: ! 17887: if (Pptr(tt)->typ->tconst()) break; ! 17888: default: ! 17889: // casting away const ! 17890: // should be an error ! 17891: // but ANSI says OK so I chicken out ! 17892: // to be able to compile strtok(), etc. ! 17893: error('w',"const cast away:%t->%t",e1->tp,tp2); ! 17894: } ! 17895: } ! 17896: else ! 17897: i2 = 0; // to allow cfront to escape its own checking ! 17898: break; ! 17899: case COBJ: ! 17900: { ref_cast = 1; ! 17901: Pexpr x = try_to_coerce(tt,e1,"cast",tbl); ! 17902: ref_cast = 0; ! 17903: //error('d',"x %k %t tt %d %t",x?x->base:0,x?x->tp:0,tt,tt); ! 17904: if (x) { ! 17905: if (x!=e1 && x->base==DEREF && tt->is_ref()) x = x->e1; ! 17906: if (tt==x->tp || tt->check(x->tp,0)==0 || const_problem) ! 17907: return x; ! 17908: else ! 17909: return new cast(tt,x); ! 17910: } ! 17911: // else if (e1->base==DEREF && tt->is_ref()) return e1; ! 17912: break; ! 17913: } ! 17914: case VOID: ! 17915: if (tt->base == VOID) { ! 17916: tp = t; ! 17917: return this; ! 17918: } ! 17919: error("cast of void value"); ! 17920: // no break; ! 17921: case ANY: ! 17922: any: ! 17923: tp = any_type; ! 17924: return this; ! 17925: case FCT: ! 17926: if (tt->base == PTR && Pptr(tt)->typ->base != FCT) ! 17927: error('w',"P toF cast toP to nonF"); ! 17928: break; ! 17929: case OVERLOAD: ! 17930: over: ! 17931: error("cast of overloaded"); ! 17932: goto any; ! 17933: } ! 17934: ! 17935: //error('d',"tt %t",tt); ! 17936: switch (tt->base) { ! 17937: case PTR: ! 17938: if (Pptr(tt)->typ->base==FCT && Pptr(tt)->memof) { ! 17939: if (etp->base!=PTR ! 17940: || Pptr(etp)->typ->base!=FCT ! 17941: || Pptr(etp)->memof==0) ! 17942: error("cast toP toM %t",tt); ! 17943: else { // adjust delta in MI case ! 17944: // for the moment just suppress the cast ! 17945: // all pmfs are the same to cc ! 17946: /* ! 17947: Pclass c1 = Pptr(tt)->memof; ! 17948: Pclass c2 = Pptr(etp)->memof; ! 17949: */ ! 17950: ptom_cast = 1; ! 17951: tp2 = void_type; ! 17952: } ! 17953: } ! 17954: ! 17955: switch (etp->base) { ! 17956: case COBJ: ! 17957: error("cannot castCO toP"); ! 17958: break; ! 17959: case FCT: ! 17960: e1 = new expr(G_ADDROF,0,e1); ! 17961: bound = b; ! 17962: e1 = e1->typ(tbl); ! 17963: bound = 0; ! 17964: if (e1->base == CAST) ! 17965: pmf = 1; ! 17966: else ! 17967: break; ! 17968: // no break; ! 17969: ! 17970: case PTR: ! 17971: { Pname cn = Pptr(tt)->typ->is_cl_obj(); ! 17972: if (cn) { ! 17973: Pexpr x = cast_cptr(Pclass(cn->tp),e1,tbl,1); ! 17974: ! 17975: if (x == e1) { ! 17976: PERM(tt); ! 17977: e1 = new cast(tt,e1); ! 17978: e1->i2 = i2; ! 17979: } ! 17980: else ! 17981: e1 = x; ! 17982: } ! 17983: if (pmf) { ! 17984: while(tt->base == TYPE) ! 17985: tt = Pbase(tt)->b_name->tp; ! 17986: ! 17987: switch (tt->base) { ! 17988: case PTR: ! 17989: if (Pptr(tt)->memof) break; ! 17990: default: ! 17991: error("%t cast to%t (%t is not aP toM)",e1->tp,tp2,tp2); ! 17992: } ! 17993: } ! 17994: } ! 17995: } ! 17996: break; ! 17997: ! 17998: case RPTR: // (x&)e: pretend e is an x ! 17999: { Ptype er = etp; ! 18000: Ptype cr = tt; ! 18001: do { ! 18002: if (er = er->is_ptr_or_ref()) er = Pptr(er)->typ; ! 18003: if (cr = cr->is_ptr_or_ref()) cr = Pptr(cr)->typ; ! 18004: } while (er && cr); ! 18005: int pp = er!=0; // if `e' is a suitable pointer cast it: ! 18006: // (x&)e => (x*)e, otherwise ! 18007: // (x&)e => *(x*)&e ! 18008: // error('d',"rptr tt %t e1->base %k e1->tp %t",tt,e1->base,e1->tp); ! 18009: // if (Pptr(tt)->typ->tsizeof()>etp->tsizeof()) goto zse; ! 18010: // we need to be able to ``raise the type'' from base to derived ! 18011: // if (etp->is_cl_obj() && Pptr(tt)->typ->is_cl_obj()==0) goto zse; ! 18012: ! 18013: if (e1->base==G_CM ! 18014: || e1->base==CALL ! 18015: || e1->base==G_CALL ! 18016: || e1->lval(0)) ! 18017: ; ! 18018: else if (e1->tp->tconst()) { ! 18019: // casting away const ! 18020: // should be an error ! 18021: // but ANSI says OK so I chicken out ! 18022: // to be able to compile strtok(), etc. ! 18023: if (warning_opt && Pptr(tt)->typ->tconst()==0) ! 18024: error('w',"const cast away:%t->%t",e1->tp,tp2); ! 18025: ! 18026: } ! 18027: else ! 18028: error("cannot cast%t to%t",etp,t); ! 18029: //error('d',"e1 %k %t %d",e1->base,e1->tp,pp); ! 18030: if (pp == 0) e1 = e1->address(); // *(x*)&e ! 18031: tp = t; ! 18032: ! 18033: // do proper pointer manipulation for multiple inheritance ! 18034: Pname cn = Pptr(tt)->typ->is_cl_obj(); ! 18035: if (cn) { ! 18036: Pexpr x = cast_cptr(Pclass(cn->tp),e1,tbl,1); ! 18037: ! 18038: if (x == e1) { ! 18039: PERM(tt); ! 18040: e1 = new cast(tt,e1); ! 18041: e1->i2 = i2; ! 18042: } ! 18043: else ! 18044: e1 = x; ! 18045: } ! 18046: ! 18047: return pp ? this : contents(); ! 18048: // zse: ! 18049: // error("cannot cast%t to%t",etp,t); ! 18050: // tp2 = tt = any_type; ! 18051: // break; ! 18052: } ! 18053: case COBJ: ! 18054: base = VALUE; // (x)e => x(e): construct an x from e ! 18055: e1 = new expr(ELIST,e1,0); ! 18056: return typ(tbl); ! 18057: ! 18058: case CHAR: ! 18059: case INT: ! 18060: case SHORT: ! 18061: case LONG: ! 18062: switch (etp->base) { ! 18063: case FCT: ! 18064: e1 = new expr(ADDROF,0,e1); ! 18065: e1 = e1->typ(tbl); ! 18066: //etp = e1->tp; ! 18067: case PTR: ! 18068: if(!e1->tp->memptr() && e1->tp->tsizeof()>tt->tsizeof()) ! 18069: error("type ``%t'' not large enough for values of ``%t ''",tt,etp); ! 18070: break; ! 18071: case COBJ: ! 18072: error("cannot castCO to%k",tt->base); ! 18073: break; ! 18074: } ! 18075: break; ! 18076: ! 18077: case FLOAT: ! 18078: case DOUBLE: ! 18079: case LDOUBLE: ! 18080: switch (etp->base) { ! 18081: case FLOAT: ! 18082: case DOUBLE: ! 18083: case LDOUBLE: ! 18084: case CHAR: ! 18085: case INT: ! 18086: case SHORT: ! 18087: case LONG: ! 18088: case EOBJ: ! 18089: case ZTYPE: ! 18090: break; ! 18091: default: ! 18092: error("cannot cast ``%t '' to ``%t''",etp,tt); ! 18093: break; ! 18094: } ! 18095: break; ! 18096: ! 18097: case FCT: ! 18098: error("cannot cast toFT"); ! 18099: break; ! 18100: } ! 18101: ! 18102: tp = t; ! 18103: ! 18104: if (e1->base==ILIST && ptom_cast==0) { // pointer to member constant ! 18105: Pexpr ee = e1->e1; // ELIST ! 18106: int i; ! 18107: switch (ee->e2->base) { ! 18108: case IVAL: ! 18109: i = int(ee->e2->i1); ! 18110: break; ! 18111: case ZERO: ! 18112: i = 0; ! 18113: } ! 18114: ! 18115: if (i<0) ! 18116: e1 = e1->e2; // just the function ! 18117: else ! 18118: e1 = ee->e2; // just the index ! 18119: return this; ! 18120: } ! 18121: ! 18122: if (etp->base==PTR && Pptr(etp)->memof && Pptr(etp)->typ->base==FCT) { ! 18123: Pclass cl = Pptr(etp)->memof; ! 18124: ! 18125: if (Pptr(tt)->memof==0 && b == 0 ) { ! 18126: Pexpr y = new mdot("f",e1); ! 18127: y->i1 = 9; ! 18128: y = new cast(tt,y); ! 18129: if (cl->virt_count && b==0) { ! 18130: // ERROR: no check for side effects ! 18131: Pexpr z = new mdot("i",e1); ! 18132: Pexpr x = new mdot("i",e1); ! 18133: x->i1 = 9; ! 18134: x = new cast(tt,x); ! 18135: z->i1 = 9; ! 18136: Pexpr q = new expr (QUEST,x,y); ! 18137: q->cond = new expr(LE,zero,z); ! 18138: q->tp = tt; ! 18139: delete this; ! 18140: return q; ! 18141: } ! 18142: delete this; ! 18143: return y; ! 18144: } ! 18145: } ! 18146: ! 18147: return this; ! 18148: } ! 18149: ! 18150: Pexpr expr::dovalue(Ptable tbl) ! 18151: { ! 18152: Ptype tt = tp2; ! 18153: Pclass cl; ! 18154: Pname cn; ! 18155: ! 18156: //error('d',"value %d %t e1 %d e2 %d",tt,tt,e1,e2); ! 18157: ! 18158: tt->dcl(tbl); ! 18159: ! 18160: while(tt->base == TYPE) ! 18161: tt = Pbase(tt)->b_name->tp; ! 18162: ! 18163: switch (tt->base) { ! 18164: case EOBJ: ! 18165: default: ! 18166: if (e1 == 0) { ! 18167: error("value missing in conversion to%t",tt); ! 18168: return dummy; ! 18169: } ! 18170: base = CAST; ! 18171: e1 = e1->e1; // strip ELIST ! 18172: return typ(tbl); ! 18173: ! 18174: case CLASS: ! 18175: cl = Pclass(tt); ! 18176: tp2 = Pptr(cl->this_type)->typ; ! 18177: break; ! 18178: ! 18179: case COBJ: ! 18180: cn = Pbase(tt)->b_name; ! 18181: cl = Pclass(cn->tp); ! 18182: } ! 18183: ! 18184: //error('d',"e1 %k e1->e2 %k",e1->base,e1?e1->e2->base:0); ! 18185: if (e1 && e1->e2==0) { // single argument ! 18186: if (e1->e1->base==ELIST) e1->e1 = e1->e1->e1; // spurious elist ! 18187: e1->e1 = e1->e1->typ(tbl); ! 18188: if (tt->base==COBJ) { ! 18189: Pexpr x = try_to_coerce(tt,e1->e1,"type conversion",tbl); ! 18190: if (x) return x; ! 18191: } ! 18192: ! 18193: Pname acn = e1->e1->tp->is_cl_obj(); ! 18194: //error('d',"acn %n %d",acn,cl->has_itor()); ! 18195: if (acn && cl->has_itor()==0) { ! 18196: Pclass acl = Pclass(acn->tp); ! 18197: int hb = acl->has_base(cl); ! 18198: ! 18199: if (acl==cl || hb) { ! 18200: vcllist->clear(); ! 18201: vcllist=0; ! 18202: if (1<is_unique_base(acl,cl->string,0)) error("ambiguous assignment to base %t",cl); ! 18203: Pexpr ee = e1->e1; ! 18204: if (ee->base == ELIST) ee = ee->e1; // ??? ! 18205: if (hb) { // ee => *(tp2*)&ee ! 18206: // remember = may be overloaded ! 18207: //error('d',"hb %k %t %d",ee->base,ee->tp,ee->lval(0)); ! 18208: ignore_const++; ! 18209: if (ee->lval(0)==0) { ! 18210: Pname tmp = make_tmp('T',ee->tp,tbl); ! 18211: ee = init_tmp(tmp,ee,tbl); ! 18212: ee = new expr(G_CM,ee,tmp->address()); ! 18213: } ! 18214: else ! 18215: ee = ee->address(); ! 18216: ignore_const--; ! 18217: ee = new texpr(CAST,new ptr(PTR,tp2),ee); //new cast(new ptr(PTR,tp2),ee); ! 18218: ee = ee->contents(); ! 18219: ee->typ(tbl); ! 18220: } ! 18221: ! 18222: if (e2) { // x(x_obj) => e2=x_obj ! 18223: base = ASSIGN; ! 18224: e1 = e2; ! 18225: e2 = ee; ! 18226: tp = tp2; ! 18227: return this; ! 18228: } ! 18229: return ee; // strip ELIST: x(x_obj) => x_obj ! 18230: } ! 18231: } ! 18232: } ! 18233: ! 18234: ! 18235: /* x(a) => obj.ctor(a); where e1==obj */ ! 18236: Pname ctor = cl->has_ctor(); ! 18237: if (ctor == 0) { ! 18238: error("cannot make a%t",cl); ! 18239: return dummy; ! 18240: } ! 18241: ! 18242: // error('d',"e2 %k",e2?e2->base:0); ! 18243: // error('d',"refd: %d const_ptr: %d", refd, const_ptr); ! 18244: if (e2 == 0) { // x(a) => x temp; (temp.x(a),temp) ! 18245: /* incomplete condition ! 18246: if ( refd && const_ptr == 0) { ! 18247: if ( tbl == gtbl ) { ! 18248: error("Ir forG non-constCR not an lvalue"); ! 18249: } ! 18250: else ! 18251: if (strict_opt) ! 18252: error("Ir for non-constCR not an lvalue"); ! 18253: else ! 18254: if (warning_opt) ! 18255: error('w', "Ir for non-constR not an lvalue (anachronism)"); ! 18256: } ! 18257: */ ! 18258: ! 18259: no_sti = 1; ! 18260: Pname n = make_tmp('V',tp2,tbl); ! 18261: no_sti = 0; ! 18262: n->assign(); ! 18263: if (tbl == gtbl) n->dcl_print(0); // a hack ! 18264: Pexpr c = call_ctor(tbl,n,ctor,e1,DOT); ! 18265: c = new expr(G_CM,c,n); ! 18266: c->tp = n->tp; ! 18267: //error('d',"tp1 %t",c->tp); ! 18268: return c; ! 18269: } ! 18270: else { ! 18271: Pexpr c = call_ctor(tbl,e2,ctor,e1,DOT); ! 18272: c = new expr(DEREF,c,0); // deref value returned by constructor ! 18273: c->tp = c->e1->tp; ! 18274: //error('d',"tp2 %t",c->tp); ! 18275: return c; ! 18276: } ! 18277: } ! 18278: ! 18279: 0707071010112044311004440001630000160000010201300466055402500000700000074341find.c /*ident "@(#)ctrans:src/find.c 1.5" */ ! 18280: /****************************************************************** ! 18281: ! 18282: C++ source for cfront, the C++ compiler front-end ! 18283: written in the computer science research center of Bell Labs ! 18284: ! 18285: Copyright (c) 1986 AT&T, Inc. All Rights Reserved ! 18286: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 18287: ! 18288: find.c: ! 18289: ! 18290: name lookup and visibility checks ! 18291: ! 18292: *******************************************************************/ ! 18293: ! 18294: #include "cfront.h" ! 18295: ! 18296: Pname undef(Pname n, Ptable tbl, TOK f) ! 18297: { ! 18298: switch (f) { ! 18299: case CCON: ! 18300: error("illegalF call: explicit call ofK %s()",n->string); ! 18301: break; ! 18302: case 0: error("%nU",n); break; ! 18303: case CALL: error("UF%n called",n); break; ! 18304: case REF: ! 18305: case DOT: error("M%nU",n); break; ! 18306: case ADDROF: error("address ofU%n",n); break; ! 18307: } ! 18308: ! 18309: if (tbl == gtbl) { ! 18310: Pname nn = tbl->insert(n,0); ! 18311: if (f == CALL) { ! 18312: nn->tp = new fct(defa_type,0,0); ! 18313: nn->n_sto = nn->n_scope = EXTERN; ! 18314: } ! 18315: else ! 18316: nn->tp = any_type; ! 18317: delete n; ! 18318: return nn; ! 18319: } ! 18320: ! 18321: n->n_table = tbl; ! 18322: n->tp = any_type; ! 18323: return n; ! 18324: } ! 18325: ! 18326: ! 18327: ! 18328: static int mptr; // &C::m ! 18329: static Pname me; // name of fct requesting access to name using find_name() ! 18330: static Pfct mef; // fct requesting access to name using find_name() ! 18331: Pclass tcl; // class of original ``this'' ! 18332: Pclass mec; // class requesting access to name using find_name() ! 18333: int mex; ! 18334: ! 18335: Ptable lcl_tbl = 0; // handle local function reference of local const for dimen size ! 18336: ! 18337: ! 18338: Pexpr find_name(Pname n, Pclass cl, Ptable tbl, int f, Pname m) ! 18339: /* ! 18340: in function ``m'' find the true name for "n", ! 18341: implicitly define if undefined ! 18342: ! 18343: f==CALL: n() cl == cc->cot ! 18344: f==REF: p->n cl == class of *p ! 18345: f==DOT: obj.n cl == class of obj ! 18346: f==ADDROF: &n cl == cc->cot ! 18347: f==0 n (none of the above) ! 18348: ! 18349: "tbl" defines local scope (block or global) ! 18350: ! 18351: */ ! 18352: { ! 18353: if ( n == 0 ) error('i',"find_name(n==0,cl==%t,tbl==%d,f==%k,m==%n)",cl,tbl,f,m); ! 18354: Pname q = n->n_qualifier; ! 18355: char* s = n->string; ! 18356: Pexpr ee; ! 18357: DB( if(Ddebug>=3) { ! 18358: error('d',"find_name %s::%s cl %t",q?q->string:"",s,cl); ! 18359: error('d'," f %d m %n",f,m); ! 18360: if(q&&q->tp&&q->tp->base==COBJ) ! 18361: fprintf(stderr," -- cb==%d\n",Pclass(q->tp)->c_body); ! 18362: }); ! 18363: ! 18364: tcl = cl; ! 18365: ! 18366: //if (n) { ! 18367: mex = 1; ! 18368: if (me = m) { ! 18369: mef = Pfct(me->tp); ! 18370: if (mef->base!=FCT) ! 18371: error('i',"mef %d %k",mef,mef->base); ! 18372: mec = mef->memof; ! 18373: } ! 18374: else { ! 18375: mef = 0; ! 18376: mec = cl; ! 18377: } ! 18378: //} ! 18379: //else ! 18380: // mex = 0; ! 18381: ! 18382: if (n->base == MDOT) error('i',"find (mdot %n)",n); ! 18383: ! 18384: if (n->n_table) { me = 0; return n; } ! 18385: ! 18386: //error('d',"q %n %t f %k",q,q?q->tp:0,f); ! 18387: if (q) { // qualified name: q::s ! 18388: ! 18389: if (q == sta_name) { // explicitly global: ::s ! 18390: Pname nn = gtbl->look(s,0); ! 18391: if (nn == 0) { me = 0; return undef(n,gtbl,f); } ! 18392: nn->use(); ! 18393: delete n; ! 18394: me = 0; ! 18395: return nn; ! 18396: } ! 18397: ! 18398: { ! 18399: Pname aq = q; // actual q ! 18400: while ( aq->tp->base == TYPE ) aq = Pbase(aq->tp)->b_name; ! 18401: if (aq->tp->base != COBJ) { ! 18402: error("Qr%nnot aCN",q); ! 18403: me = 0; ! 18404: return undef(n,gtbl,f); ! 18405: } ! 18406: q = aq; ! 18407: } ! 18408: Pclass qcl = Pclass(Pbase(q->tp)->b_name->tp); ! 18409: ! 18410: Pclass bcl = cl; ! 18411: ! 18412: if (cl==0 || f==ADDROF) ! 18413: bcl = cl = qcl; // Pclass(Pbase(q->tp)->b_name->tp); ! 18414: else { ! 18415: // if (strcmp(q->string,cl->string)) { // really a base? ! 18416: // bcl = cl->is_base(q->string); ! 18417: if (strcmp(qcl->string,cl->string)) { // really a base? ! 18418: bcl = cl->is_base(qcl->string); ! 18419: if (bcl == 0) { ! 18420: if (f==REF || f==DOT) { ! 18421: error("%s is not aBC of %t",q->string,cl); ! 18422: me = 0; ! 18423: return undef(n,cl->memtbl,7); ! 18424: } ! 18425: goto sss; ! 18426: } ! 18427: // else try in base or for static ! 18428: } ! 18429: } ! 18430: ! 18431: if (f == ADDROF) mptr = 1; // &C::m ! 18432: ee = cl->find_name(s,bcl==cl?0:bcl); // really a member? ! 18433: mptr = 0; ! 18434: ! 18435: if (ee == 0) { ! 18436: sss: ! 18437: //error('d',"sss %k",f); ! 18438: if (f!=REF && f!=DOT) { ! 18439: // try for static member of other class: ! 18440: Pclass qcl = Pclass(Pbase(q->tp)->b_name->tp); ! 18441: mptr = 1; ! 18442: if ( cl && cl->csu == ANON ) { ! 18443: mec = (cc-1)->cot; ! 18444: ee = qcl->find_name(s,qcl); ! 18445: } else ! 18446: ee = qcl->find_name(s,qcl); ! 18447: mptr = 0; ! 18448: if (ee && ee->base==NAME) { ! 18449: // switch (ee->tp->base) { ! 18450: // case FCT: ! 18451: // case OVERLOAD: ! 18452: // break; ! 18453: // default: ! 18454: delete n; ! 18455: me = 0; ! 18456: return ee; ! 18457: // } ! 18458: } ! 18459: } ! 18460: error("QdN%n::%n not found in %t",q,n,cl); ! 18461: me = 0; ! 18462: return undef(n,bcl?bcl->memtbl:cl->memtbl,7); ! 18463: } ! 18464: ! 18465: if (ee->base==REF && ee->e1==0) { // &C::f, no ``this'' ! 18466: //error('d',"ee %k %d f %k",ee->base,ee->e1,f); ! 18467: switch (f) { ! 18468: case 0: ! 18469: case CALL: //SSS ! 18470: { Pexpr mm = ee->mem; ! 18471: while (mm->base==REF || mm->base==MDOT) mm = mm->mem; ! 18472: if (mm->base==NAME) ! 18473: switch (mm->tp->base) { ! 18474: case FCT: ! 18475: case OVERLOAD: ! 18476: goto addrof; ! 18477: default: ! 18478: if (Pname(mm)->n_stclass == STATIC) goto addrof; ! 18479: } ! 18480: } ! 18481: error("O orOP missing forM%n",n); ! 18482: ! 18483: case ADDROF: ! 18484: addrof: ! 18485: Pexpr x = ee; ! 18486: ee = ee->mem; ! 18487: delete x; ! 18488: case REF: ! 18489: case DOT: ! 18490: break; ! 18491: default: ! 18492: error("QdN%n::%n used in nonC context",q,n); ! 18493: } ! 18494: } ! 18495: ! 18496: delete n; ! 18497: me = 0; ! 18498: return ee; ! 18499: } ! 18500: ! 18501: if (f!=DOT && f!=REF) { // not .s or ->s: look for local, global, and member ! 18502: ! 18503: Pname nn = tbl->look(s,0); ! 18504: if (nn) { // local, global, or member ! 18505: if (nn->n_table->t_name) { // global or member ! 18506: if (cl) { // might be member ! 18507: if ((ee = cl->find_name(s,0))==0 && ! 18508: cl->in_class) ! 18509: { // nested class ! 18510: Pclass nstd_cl = cl->in_class; ! 18511: for (; nstd_cl; nstd_cl=nstd_cl->in_class) ! 18512: { ! 18513: // error( 'd', "find_name( %s ): nested class %t",s,nstd_cl ); ! 18514: if (ee=nstd_cl->find_name(s,0)) ! 18515: { ! 18516: if ( cl->nested_sig == 0 ) { ! 18517: error('w',"%s, accessed within nestedC%t, is visible bothGly and within enclosingC%t -- using %n (anachronism)", s, cl, nstd_cl, nn ); ! 18518: ee = 0; ! 18519: } ! 18520: break; ! 18521: } ! 18522: } ! 18523: } // nested class ! 18524: ! 18525: if ( ee ) ! 18526: { // class member name ! 18527: if (ee->base==REF && ee->e1==0 ) ! 18528: { ! 18529: Pexpr mm = ee->mem; ! 18530: while (mm->base==REF || mm->base==MDOT) mm = mm->mem; ! 18531: if (mm->base==NAME) ! 18532: switch (mm->tp->base) { ! 18533: default: ! 18534: if (Pname(mm)->n_stclass != STATIC) ! 18535: break; ! 18536: case FCT: ! 18537: case OVERLOAD: ! 18538: delete n; ! 18539: me = 0; ! 18540: return mm; ! 18541: } ! 18542: error("O orOP missing for%n",Pref(ee)->mem); ! 18543: } ! 18544: delete n; ! 18545: me = 0; ! 18546: return ee; ! 18547: } // if ee ! 18548: } // if cl ! 18549: } // else local, global, or member ! 18550: ! 18551: nn->use(); ! 18552: delete n; ! 18553: me = 0; ! 18554: return nn; ! 18555: } ! 18556: ! 18557: if (cl) { ! 18558: if ( cl->csu == ANON ) { ! 18559: mec = (cc-1)->cot; ! 18560: ee = (cc-1)->cot->find_name(s,0); ! 18561: } else ! 18562: ee = cl->find_name(s,0); ! 18563: if (ee) { ! 18564: if (ee->base==REF && ee->e1==0) { ! 18565: Pexpr mm = ee->mem; ! 18566: while (mm->base==REF || mm->base==MDOT) mm = mm->mem; ! 18567: if (mm->base==NAME) ! 18568: switch (mm->tp->base) { ! 18569: default: ! 18570: if (Pname(mm)->n_stclass != STATIC) ! 18571: break; ! 18572: case FCT: ! 18573: case OVERLOAD: ! 18574: delete n; ! 18575: me = 0; ! 18576: return mm; ! 18577: ! 18578: } ! 18579: error("O orOP missing for%n",Pref(ee)->mem); ! 18580: } ! 18581: delete n; ! 18582: me = 0; ! 18583: return ee; ! 18584: } ! 18585: } ! 18586: ! 18587: if ( lcl_tbl && (nn=lcl_tbl->look(s,0)) ) { ! 18588: nn->use(); ! 18589: delete n; ! 18590: me = 0; ! 18591: return nn; ! 18592: } ! 18593: ! 18594: if (nn = gtbl->look(s,0)) { // global ! 18595: nn->use(); ! 18596: delete n; ! 18597: me = 0; ! 18598: return nn; ! 18599: } ! 18600: ! 18601: me = 0; ! 18602: return undef(n,gtbl,f); ! 18603: } ! 18604: ! 18605: if (ee = cl->find_name(s,cl)) { // .s or ->s ! 18606: delete n; ! 18607: me = 0; ! 18608: return ee; ! 18609: } ! 18610: ! 18611: if(!strcmp(s,cl->string)) { ! 18612: me = 0; ! 18613: return undef(n,gtbl,CCON); ! 18614: } ! 18615: ! 18616: me = 0; ! 18617: return undef(n,gtbl,f); ! 18618: } ! 18619: ! 18620: int classdef::check_dup(Pclass cl, TOK bb) ! 18621: /* ! 18622: see if cl is a base of this; return 0 if no clash ! 18623: */ ! 18624: { ! 18625: for (Pbcl b = baselist; b; b=b->next) { ! 18626: if (cl == b->bclass) { ! 18627: if (bb!=VIRTUAL) { ! 18628: if (b->base==VIRTUAL) ! 18629: error('w',"%t inaccessible because of virtual%t in%t",cl,cl,this); ! 18630: else ! 18631: error('w',"%t inaccessible because of%t in%t",cl,cl,this); ! 18632: return 1; ! 18633: } ! 18634: else if (b->base!=VIRTUAL) { ! 18635: error('w',"virtual %t inaccessible because of%t in%t",cl,cl,this); ! 18636: return 1; ! 18637: } ! 18638: } ! 18639: if (b->bclass->check_dup(cl,bb)) return 1; ! 18640: } ! 18641: return 0; ! 18642: } ! 18643: ! 18644: ! 18645: int Nvis; ! 18646: TOK Nvirt; ! 18647: TOK ppbase; ! 18648: ! 18649: Pclass classdef::is_base(char* s) ! 18650: /* ! 18651: is "s" a public base class of this? ! 18652: */ ! 18653: { ! 18654: //error('d',"%s->is_base(%s) %k",string,s,ppbase); ! 18655: TOK pp = ppbase; ! 18656: for (Pbcl b = baselist; b; b=b->next) { ! 18657: /* ! 18658: if (b->ppp!=PUBLIC ! 18659: && cc->cot!=this ! 18660: && (cc->nof==0 || this->has_friend(Pfct(cc->nof->tp))==0)) ! 18661: ppbase = b->ppp<pp?pp:b->ppp; // PUBLIC<PROTECTED<PRIVATE ! 18662: */ ! 18663: if (strcmp(s,b->bclass->string) == 0) { ! 18664: if (b->ppp!=PUBLIC ! 18665: && cc->cot!=this ! 18666: && (cc->nof==0 || this->has_friend(Pfct(cc->nof->tp))==0)) ! 18667: ppbase = b->ppp<pp?pp:b->ppp; // PUBLIC<PROTECTED<PRIVATE ! 18668: Nvirt = b->base; ! 18669: return b->bclass; ! 18670: } ! 18671: else { ! 18672: Pclass bc = b->bclass->is_base(s); ! 18673: if (bc) { ! 18674: if (b->ppp!=PUBLIC ! 18675: && cc->cot!=this ! 18676: && (cc->nof==0 || this->has_friend(Pfct(cc->nof->tp))==0)) ! 18677: ppbase = b->ppp<pp?pp:b->ppp; // PUBLIC<PROTECTED<PRIVATE ! 18678: return bc; ! 18679: } ! 18680: } ! 18681: } ! 18682: ppbase = pp; ! 18683: return 0; ! 18684: } ! 18685: ! 18686: bit classdef::has_base(Pclass cl) ! 18687: /* ! 18688: is "cl" a base of this? ! 18689: */ ! 18690: { ! 18691: // error('d', "%t->has_base( %t ) cc->cot: %t", this, cl, cc->cot?cc->cot:0 ); ! 18692: ! 18693: if (this == 0) return 0; ! 18694: for (Pbcl b = baselist; b; b=b->next) { ! 18695: // error('d', "b: %t ppp: %k", b->bclass, b->ppp ); ! 18696: if (b->bclass==cl) { ! 18697: if (b->ppp!=PUBLIC ! 18698: && cc->cot!=this ! 18699: && (cc->nof==0 || ! 18700: this->has_friend(Pfct(cc->nof->tp))==0) ! 18701: && this->has_friend(cc->cot)==0) ! 18702: Nvis = 1; // no standard coercion ! 18703: Nvirt = b->base; ! 18704: return 1; ! 18705: } ! 18706: if (b->bclass->has_base(cl)) return 1; ! 18707: } ! 18708: return 0; ! 18709: } ! 18710: ! 18711: int Noffset; ! 18712: Pexpr Nptr; ! 18713: char *Nalloc_base; ! 18714: clist* vcllist; ! 18715: ! 18716: int clist::onlist(Pclass c) ! 18717: { ! 18718: for (clist* p = this; p; p = p->next) ! 18719: if (p->cl == c) return 1; ! 18720: return 0; ! 18721: } ! 18722: ! 18723: void clist::clear() ! 18724: { ! 18725: if (this == 0) return; ! 18726: clist* p = next; ! 18727: while (p) { ! 18728: clist* q = p->next; ! 18729: delete p; ! 18730: p = q; ! 18731: }; ! 18732: delete this; ! 18733: } ! 18734: ! 18735: Pbcl Nvbc_alloc; ! 18736: int is_unique_base(Pclass cl, char* s, int offset, int in_base ) ! 18737: /* ! 18738: is "s" a unique base class of this? ! 18739: */ ! 18740: { ! 18741: int i = 0; ! 18742: static Pclass priSeen = 0; ! 18743: // error('d',"is_unique_base(cl: %t, s: %s,%d,%d)",cl,s,offset,in_base); ! 18744: for (Pbcl b = cl->baselist; b; b=b->next) { ! 18745: int no = 0; ! 18746: if (b->base!=VIRTUAL) ! 18747: no = offset + b->obj_offset; ! 18748: else if (in_base) ! 18749: continue; ! 18750: if (strcmp(s,b->bclass->string) == 0) { ! 18751: Noffset = no; ! 18752: i++; ! 18753: if ((b->ppp!=PUBLIC || priSeen ) ! 18754: && (cc->cot!=cl || cc->cot != priSeen ) ! 18755: && (cc->nof==0 || cl->has_friend(Pfct(cc->nof->tp))==0) ! 18756: || (priSeen && priSeen->has_friend(Pfct(cc->nof->tp))==0)) ! 18757: Nvis = 1; // no standard coercion ! 18758: ! 18759: if (b->base==VIRTUAL) { ! 18760: Nptr = new mdot(s,0); ! 18761: if (b->allocated == 0) { ! 18762: Nvbc_alloc = 0; ! 18763: Nalloc_base = cl->has_allocated_base(s); ! 18764: } ! 18765: } ! 18766: } ! 18767: else { ! 18768: if (b->base==VIRTUAL) { ! 18769: if (vcllist->onlist(b->bclass) )continue; ! 18770: vcllist = new clist(b->bclass,vcllist); ! 18771: } ! 18772: ! 18773: Pclass clscope = 0; ! 18774: if ( cc && cc->c_this ) { ! 18775: Ptype t = Pptr(cc->c_this->tp)->typ; ! 18776: clscope = Pclass(Pbase(t)->b_name->tp); ! 18777: } ! 18778: // error('d', "cl: %t %d clscope: %t %d", cl, cl, clscope, clscope); ! 18779: if (b->ppp != PUBLIC && ! 18780: cl != clscope && priSeen == 0 ) priSeen = cl; ! 18781: ! 18782: int ii = is_unique_base(b->bclass,s,no,1); ! 18783: if (in_base == 0) priSeen = 0; ! 18784: // error('d',"base %t i %d ii %d",b->bclass,i,ii); ! 18785: // error('d',"base %t %k allocated: %d", b->bclass, b->base, b->allocated); ! 18786: i += ii; ! 18787: if (ii==1 && b->base==VIRTUAL) { ! 18788: Nptr = new mdot(b->bclass->string,0); ! 18789: if (b->allocated == 0) { ! 18790: Nvbc_alloc = 0; ! 18791: Nalloc_base = cl->has_allocated_base(b->bclass->string); ! 18792: } ! 18793: } ! 18794: } ! 18795: } ! 18796: ! 18797: return i; ! 18798: } ! 18799: ! 18800: /* ! 18801: int classdef::has_allocated_base(Pclass bcl) ! 18802: ! 18803: search the list of !first base classes for this virtual base ! 18804: space will have been allocated in !first bases for virtual bases ! 18805: declared in !first classes ! 18806: ! 18807: in addition bcl may bave been specified explicitly as a base ! 18808: ! 18809: { ! 18810: int off; ! 18811: for (Pbcl l = baselist; l; l=l->next) { ! 18812: if (l->base == VIRTUAL) continue; // another non-allocated virtual base ! 18813: if (l==baselist) continue; // first base ! 18814: ! 18815: Pclass bc = l->bclass; ! 18816: off = l->obj_offset; ! 18817: ! 18818: for (Pbcl ll = bc->baselist; ll; ll=ll->next) { ! 18819: // cannot share non-virtual base ! 18820: if (ll->base != VIRTUAL) continue; ! 18821: if (ll->bclass==bcl) return off + ll->obj_offset; ! 18822: } ! 18823: } ! 18824: return 0; ! 18825: } ! 18826: */ ! 18827: ! 18828: int classdef::has_allocated_base(Pclass bcl) ! 18829: /* ! 18830: search the list of base classes for this virtual base ! 18831: space will be allocated in first virtual version found. ! 18832: return offset. ! 18833: ! 18834: A virtual base cannot have offset 0 (its pointer at least is ahead) ! 18835: */ ! 18836: { ! 18837: //error('d',"%t->has_allocated_base(%t) ",this,bcl); ! 18838: for (Pbcl l = baselist; l; l=l->next) { ! 18839: if (l->base==VIRTUAL ! 18840: && l->bclass==bcl ! 18841: && l->obj_offset) ! 18842: return l->obj_offset; ! 18843: ! 18844: if (l->base==VIRTUAL || l!=baselist) { ! 18845: // allocated as an object, ! 18846: // not unravelled as a set of members ! 18847: int i = l->bclass->has_allocated_base(bcl); ! 18848: if (i) return l->obj_offset + i; ! 18849: } ! 18850: } ! 18851: return 0; ! 18852: } ! 18853: ! 18854: char *classdef::has_allocated_base(char *str) ! 18855: /* ! 18856: * str is an unallocated virtual base class of this ! 18857: * return the name of the second or subsequent base class ! 18858: * containing the member ``struct str *P<str>'' ! 18859: */ ! 18860: { ! 18861: // error('d',"%t::has_allocated_base(%s) baselist: %t",this,str,baselist->bclass); ! 18862: for (Pbcl l = baselist; l; l=l->next) { ! 18863: if (l->base == VIRTUAL) { ! 18864: if ( l->allocated ) Nvbc_alloc = l; ! 18865: continue; ! 18866: } ! 18867: ! 18868: Pclass bc = l->bclass; ! 18869: for (Pbcl ll = bc->baselist; ll; ll=ll->next) { ! 18870: if (ll->base != VIRTUAL) continue; ! 18871: if (ll->allocated && ! 18872: strcmp( str, ll->bclass->string) == 0 ) ! 18873: { ! 18874: if (bc == baselist->bclass) { ! 18875: // NfirstBase=1; ! 18876: return 0; ! 18877: } ! 18878: return bc->string; ! 18879: } ! 18880: } ! 18881: } ! 18882: return 0; ! 18883: } ! 18884: ! 18885: /* ! 18886: int allocated_base(Pclass cl,Pclass bcl) ! 18887: { ! 18888: static second; ! 18889: int s2 = second; ! 18890: for (Pbcl l = cl->baselist; l; l=l->next) { ! 18891: if (l->base==VIRTUAL ! 18892: && l->bclass==bcl ! 18893: && l->obj_offset ! 18894: && (second || l!=cl->baselist)) return (second=s2,1); ! 18895: int i = allocated_base(l->bclass,bcl); ! 18896: if (i) return (second=s2,1); ! 18897: second = 1; ! 18898: } ! 18899: second = s2; ! 18900: return 0; ! 18901: } ! 18902: */ ! 18903: Pname vfct(Pclass cl, char* s) ! 18904: /* ! 18905: Called for each name "s" in a vtbl for "cl" ! 18906: Find the "s" to go in the vtbl. ! 18907: The "s" that caused the vtbl entry to be created ! 18908: is found if nothing else is ! 18909: */ ! 18910: { ! 18911: Pname n = cl->memtbl->look(s,0); ! 18912: if (n) return n; ! 18913: ! 18914: for (Pbcl b = cl->baselist; b; b=b->next) { ! 18915: Pname nn = vfct(b->bclass,s); ! 18916: if (nn) { ! 18917: //error('d',"nn %nn",nn); ! 18918: if (n && n!=nn) { ! 18919: Pclass ncl = Pclass(n->n_table->t_name->tp); ! 18920: Pclass nncl = Pclass(nn->n_table->t_name->tp); ! 18921: //error('d',"ncl %t nncl %t",ncl,nncl); ! 18922: if (nncl->is_base(ncl->string)) ! 18923: n = nn; // use nn ! 18924: } ! 18925: else ! 18926: n = nn; ! 18927: } ! 18928: } ! 18929: ! 18930: return n; ! 18931: } ! 18932: ! 18933: Pexpr rptr(Ptype t, Pexpr p, int offset) ! 18934: /* ! 18935: return rvalue of offset off pointer: ! 18936: (t)((char*)p+offset) ! 18937: */ ! 18938: { ! 18939: if ( t == 0 ) error( 'i', "rptr(), t==0 (type passed for cast)" ); ! 18940: Pexpr pp = p; ! 18941: //error('d',"rptr %t %d",t,offset); ! 18942: if (offset) { ! 18943: Pexpr i = new ival(offset); ! 18944: // pp = new texpr(CAST,Pchar_type,pp); ! 18945: pp = new cast(Pchar_type,pp); ! 18946: pp = new expr(PLUS,pp,i); ! 18947: } ! 18948: pp = new cast(t,pp); ! 18949: return pp; ! 18950: } ! 18951: /* ! 18952: Pexpr lptr(Ptype t, Pexpr p, int offset) ! 18953: ! 18954: return lvalue of offset off pointer: ! 18955: *(t*)((char*)p+offset) ! 18956: ! 18957: { ! 18958: Pexpr pp = p; ! 18959: if (offset) { ! 18960: Pexpr i = new ival(offset); ! 18961: // pp = new texpr(CAST,Pchar_type,pp); ! 18962: pp = new cast(Pchar_type,pp); ! 18963: pp = new expr(PLUS,pp,i); ! 18964: } ! 18965: pp = new cast(t->addrof(),pp); ! 18966: pp = new expr(DEREF,pp,0); ! 18967: pp->tp = t; ! 18968: return pp; ! 18969: } ! 18970: */ ! 18971: int friend_check(Pclass start,Pclass stop, Pfct f) ! 18972: /* ! 18973: is `f' a friend of a class between `start' and `stop' ! 18974: in a class DAG? ! 18975: */ ! 18976: { ! 18977: //error('d',"friend_check(%t,%t)",start,stop); ! 18978: ! 18979: if (start->has_friend(f)) return 1; ! 18980: if (stop == start) return 0; ! 18981: for (Pbcl b = start->baselist; b; b = b->next) { ! 18982: if (b->bclass->has_friend(f)) return 1; ! 18983: if (friend_check(b->bclass,stop,f)) return 1; ! 18984: } ! 18985: return 0; ! 18986: } ! 18987: ! 18988: bit classdef::has_friend(Pfct f) ! 18989: /* ! 18990: does this class have function "f" as its friend? ! 18991: */ ! 18992: { ! 18993: // error('d',"%t->has_friend(%t) %d %d ",this,f,f,f->base); ! 18994: ! 18995: for (Plist l=friend_list; l; l=l->l) { ! 18996: Pname fr = l->f; ! 18997: Ptype frt = fr->tp; ! 18998: //error('d',"frt %t %d %d",frt,frt,frt->base); ! 18999: switch (frt->base) { ! 19000: case FCT: ! 19001: if (f == frt) return 1; ! 19002: break; ! 19003: case OVERLOAD: ! 19004: l->f = fr = Pgen(frt)->fct_list->f; // first fct ! 19005: if (fr->tp == f) return 1; ! 19006: case CLASS: ! 19007: break; ! 19008: default: ! 19009: error('i',"bad friend %k",fr->tp->base); ! 19010: } ! 19011: } ! 19012: return 0; ! 19013: } ! 19014: ! 19015: bit classdef::has_friend(Pclass cl) ! 19016: /* ! 19017: does this class have class "cl" as its friend? ! 19018: */ ! 19019: { ! 19020: // error('d',"%t->has_friend(%t) ",this,cl); ! 19021: ! 19022: for (Plist l=friend_list; l; l=l->l) { ! 19023: Pname fr = l->f; ! 19024: Ptype frt = fr->tp; ! 19025: switch (frt->base) { ! 19026: case CLASS: ! 19027: // error('d',"class friend: %t", frt); ! 19028: if ((frt == cl) || cl->same_class(Pclass(frt))) ! 19029: return 1; ! 19030: case FCT: ! 19031: case OVERLOAD: ! 19032: break; ! 19033: default: ! 19034: {error('i',"bad friend %k",frt->base);} ! 19035: } ! 19036: } ! 19037: return 0; ! 19038: } ! 19039: ! 19040: Pname find_virtual(Pclass cl, Pname s) ! 19041: /* ! 19042: does ``cl'' have a virtual function ``s'' in some base class ! 19043: */ ! 19044: { ! 19045: for (Pbcl b = cl->baselist; b; b = b->next) { ! 19046: Pclass bcl = b->bclass; ! 19047: Pname n; ! 19048: if (n = bcl->memtbl->look(s->string,0)) { ! 19049: // error('d', "find_virtual: n: %d base: %k", n, n->base ); ! 19050: if ( n->base == PUBLIC ) // x::foo; ! 19051: continue; ! 19052: Pfct f = Pfct(n->tp); ! 19053: if (f->base == OVERLOAD) { ! 19054: for (Plist gl=Pgen(f)->fct_list; gl; gl=gl->l) { ! 19055: n = gl->f; ! 19056: // if (f != s->tp) continue; ! 19057: // Replaced by: ! 19058: if (n->tp->check(s->tp,VIRTUAL)) continue; ! 19059: if (Pfct(n->tp)->f_virtual) return n; ! 19060: } ! 19061: } ! 19062: // else if (f->f_virtual) ! 19063: else if (f->f_virtual && n->tp->check(s->tp,VIRTUAL)==0) ! 19064: return n; ! 19065: } ! 19066: else if (n = find_virtual(bcl,s)) ! 19067: return n; ! 19068: } ! 19069: return 0; ! 19070: } ! 19071: ! 19072: Pname dummy_fct; ! 19073: ! 19074: static int ! 19075: is_accessible(Pname n, Pclass this_class, bit noCdcl = 0) ! 19076: // 0 means n is not accessible to this_class ! 19077: { ! 19078: // error('d',"is_accessible(%n,%t)", n, this_class ! 19079: // error('d',"%n: %k mef %t",n,n->n_protect,mef); ! 19080: // error('d'," this_class %d %t",this_class,this_class); ! 19081: // error('d'," mec %d %t",mec,mec); ! 19082: // error('d'," tcl %d %t",tcl,tcl); ! 19083: // error('d',"mec->has_base(this_class) %d",mec?mec->has_base(this_class):0); ! 19084: // error('d',"tcl->has_base(mec) %d",tcl?tcl->has_base(mec):0); ! 19085: // error('d',"tcl->has_base(this_class) %d",tcl?tcl->has_base(this_class):0); ! 19086: // error('d',"tcl->has_friend(mef) %d",tcl?tcl->has_friend(mef):0); ! 19087: ! 19088: if (this_class==mec || ! 19089: (mec && this_class->has_friend(mec)) || ! 19090: (mef && this_class->has_friend(mef))) ! 19091: return 1; ! 19092: ! 19093: if ( n->n_protect && tcl ) { ! 19094: if ( mec ) ! 19095: { ! 19096: if ( tcl->has_friend(mec) || ! 19097: ( mec->has_base(this_class) && ! 19098: (tcl==mec || tcl->has_base(mec)))) ! 19099: return 1; ! 19100: } ! 19101: ! 19102: if ( mef ) ! 19103: { ! 19104: if ( tcl->has_base(this_class) && ! 19105: // && tcl->has_friend(mef)) ! 19106: friend_check(tcl,this_class,mef)) ! 19107: return 1; ! 19108: } ! 19109: } ! 19110: ! 19111: // call from check_visibility ! 19112: if ( noCdcl ) return 0; ! 19113: ! 19114: if ( Cdcl && Cdcl->base == NAME && ! 19115: Cdcl->n_stclass == STATIC && ! 19116: Cdcl->n_initializer && ! 19117: Cdcl->n_qualifier ) ! 19118: { ! 19119: Pbase bn = Pbase(Cdcl->n_qualifier->tp); ! 19120: Pclass cl = Pclass(bn->b_name->tp); ! 19121: ! 19122: if ( cl == this_class || ! 19123: (n->n_protect && cl->has_base(this_class)) || ! 19124: cl->has_friend(this_class)) ! 19125: return 1; ! 19126: } ! 19127: ! 19128: return 0; ! 19129: } ! 19130: ! 19131: Pexpr classdef::find_name(char* s, Pclass cl, int access_only) ! 19132: /* ! 19133: look for "s" in "this" class and its base classes ! 19134: if (cl) ! 19135: accept only a member of "cl" or "cl"'s base classes ! 19136: (that is cl::s was seen) ! 19137: ! 19138: complicated by hiding rules: private, protected, friend ! 19139: ! 19140: */ ! 19141: { ! 19142: // error('d',"%s->find_name(%s,%s) memtbl %d",string,s,cl?cl->string:"",memtbl); ! 19143: Pname n = memtbl->look(s,0); ! 19144: ! 19145: if (n) { ! 19146: if (n->tp) { ! 19147: switch (n->tp->base) { ! 19148: case OVERLOAD: ! 19149: break; ! 19150: case FCT: ! 19151: if (Pfct(n->tp)->f_virtual==0) { ! 19152: if (n->n_dcl_printed==0) n->dcl_print(0); ! 19153: break; ! 19154: } ! 19155: default: ! 19156: if (c_body==1) dcl_print(0); ! 19157: } ! 19158: } ! 19159: ! 19160: if (n->base == PUBLIC) { ! 19161: if (mex && n->n_scope==0) { ! 19162: if ( is_accessible(n,this) == 0 ) ! 19163: { ! 19164: if ( me == dummy_fct ) ! 19165: error("G scope cannot access%n: %sM",n,n->n_protect?"protected":"private"); ! 19166: else error("%n cannot access%n: %sM",me,n,n->n_protect?"protected":"private"); ! 19167: mex = 0; // suppress further error messages ! 19168: } ! 19169: } ! 19170: mex = 0; // don't have find_in_base complain about n ! 19171: return find_in_base(s, cl); ! 19172: } ! 19173: ! 19174: if (cl==0 || cl==this) { ! 19175: if (mptr==0 ! 19176: && n->n_stclass!=STATIC ! 19177: && n->n_stclass!=ENUM) { ! 19178: Ptype t = n->tp; ! 19179: ! 19180: // error('d',"cl %d this %d",cl,this); ! 19181: ! 19182: if (mex && n->n_scope==0 && n->tp->base!=OVERLOAD) { ! 19183: if ( is_accessible(n,this)==0 ) ! 19184: { ! 19185: if ( me == dummy_fct ) ! 19186: error("G scope cannot access%n: %sM",n,n->n_protect?"protected":"private"); ! 19187: else error("%n cannot access%n: %sM",me,n,n->n_protect?"protected":"private"); ! 19188: mex = 0; // suppress further error messages ! 19189: } ! 19190: } ! 19191: ! 19192: Pname th = cc->c_this; ! 19193: Pexpr r = new ref(REF,th,n); ! 19194: ! 19195: if ( access_only == 0 ) { ! 19196: if (th) th->use(); ! 19197: n->use(); ! 19198: } ! 19199: r->tp = t; ! 19200: return r; ! 19201: } ! 19202: ! 19203: if (mex && n->n_scope==0 && n->tp->base!=OVERLOAD) { ! 19204: if ( is_accessible(n,this)==0 ) ! 19205: { ! 19206: if ( me == dummy_fct ) ! 19207: error("G scope cannot access%n: %sM",n,n->n_protect?"protected":"private"); ! 19208: else error("%n cannot access%n: %sM",me,n,n->n_protect?"protected":"private"); ! 19209: mex = 0; // suppress further error messages ! 19210: } ! 19211: } ! 19212: n->use(); ! 19213: return n; ! 19214: } ! 19215: } ! 19216: ! 19217: if ((cl==0 || cl==this) // not qualified to a base class ! 19218: && csu!=UNION ! 19219: && csu!=ANON ! 19220: && strcmp(s,"__as")==0) { // assignment is special: you cannot inherit it ! 19221: if (baselist==0 ! 19222: || (baselist && baselist->bclass->obj_size!=obj_size)) { ! 19223: Pname cn = ktbl->look(string,0); ! 19224: if (cn->tp->base == COBJ) cn = Pbase(cn->tp)->b_name; ! 19225: Pname x = gtbl->look("__as",0); ! 19226: if (x) { // what if there is an (illegal) global assignment operation? ! 19227: // hack hack don't declare global assignment operations! ! 19228: Pfct f = Pfct(x->tp); ! 19229: if (f->base == FCT) { ! 19230: Pptr r = f->argtype->tp->is_ref(); ! 19231: if (r) { ! 19232: Pname cnn = r->typ->is_cl_obj(); ! 19233: if (cnn && cn==cnn) return 0; ! 19234: } ! 19235: } else { ! 19236: for (Plist gl = Pgen(f)->fct_list; gl; gl=gl->l) { ! 19237: Pptr r = Pfct(gl->f)->argtype->tp->is_ref(); ! 19238: if (r) { ! 19239: Pname cnn = r->typ->is_cl_obj(); ! 19240: if (cnn &&cn==cnn) return 0; ! 19241: } ! 19242: } ! 19243: } ! 19244: } ! 19245: return make_assignment(cn) ? find_name(s,cl) : 0; ! 19246: } ! 19247: } ! 19248: ! 19249: return find_in_base(s, cl); ! 19250: } ! 19251: ! 19252: static Pclass rootClass; ! 19253: static Pbcl pubVClass; ! 19254: static struct PendingMessage { ! 19255: Pbcl bc; ! 19256: Pname mf; ! 19257: char *nm; ! 19258: } *pM; ! 19259: ! 19260: Pexpr classdef::find_in_base(char* s, Pclass cl) ! 19261: { ! 19262: Pbcl bc = 0; ! 19263: Pexpr e = 0; ! 19264: ! 19265: // error('d',"%s->find_in_base(%s %s)",string,s,cl?cl->string:""); ! 19266: ! 19267: if ( me == 0 ) mef = 0; ! 19268: if (rootClass == 0) rootClass = this; ! 19269: for (Pbcl b=baselist; b; b=b->next) { ! 19270: Pclass ccl = cl==this?0:cl; ! 19271: // error('d',"try %t %s %k",b->bclass,b->bclass?b->bclass->string:"?", b->base); ! 19272: Pexpr ee = b->bclass->find_name(s,ccl); ! 19273: ! 19274: if (ee) { ! 19275: if (c_body == 1) { // look for first use (through this) ! 19276: if (b!=baselist || b->base==VIRTUAL) ! 19277: dcl_print(0); ! 19278: else { ! 19279: Pexpr ex = ee; ! 19280: while ((ex->base==MDOT && ex->i1==1) ! 19281: || (ex->base==REF && ex->e1==cc->c_this)) ex = ex->mem; ! 19282: switch (ex->tp->base) { ! 19283: case OVERLOAD: ! 19284: break; ! 19285: case FCT: ! 19286: if (Pfct(ex->tp)->f_virtual==0) break; ! 19287: default: ! 19288: dcl_print(0); ! 19289: } ! 19290: } ! 19291: } ! 19292: ! 19293: if (e) { ! 19294: // error( 'd', "find_in_base: b( %s ): %k %k ",b->bclass->string,b->base,b->ppp); ! 19295: Pexpr ex = e; ! 19296: int evb = 0; // number of vbase indirections ! 19297: int eb = 0; ! 19298: ! 19299: // note that this does not catch enum members ! 19300: while (ex->base == MDOT ! 19301: || (ex->base==REF && ex->e1==cc->c_this)) { ! 19302: if (ex->base==MDOT) evb += int(ex->i1); ! 19303: ex = ex->mem; ! 19304: } ! 19305: ! 19306: Pexpr eex = ee; ! 19307: int eevb = b->base==VIRTUAL; // number of vbase indirections (incl. possibly this one) ! 19308: int eeb = b->base!=VIRTUAL; ! 19309: ! 19310: while (eex->base == MDOT ! 19311: || (eex->base==REF && eex->e1==cc->c_this)) { ! 19312: if (eex->base==MDOT) eevb += int(eex->i1); ! 19313: eex = eex->mem; ! 19314: } ! 19315: ! 19316: // error('d', "find_in_base: ex: %k eex: %k, eevb: %d evb: %d", ex->base, eex->base, eevb, evb ); ! 19317: // relying on simple counts for sub-object identification isn't good enough ! 19318: ! 19319: if (ex != eex) { ! 19320: // error('d',"ex %k tp %k eex %k tp %k", ex->base, ex->tp->base, eex->base, eex->tp->base ); ! 19321: // if (!mqua) { ! 19322: Pclass ocl, ncl; ! 19323: if ( ex->tp->base == FCT ) ! 19324: ocl = Pfct(ex->tp)->memof; ! 19325: else ! 19326: if ( ex->tp->base == OVERLOAD ) ! 19327: ocl = Pfct(Pgen(ex->tp)->fct_list->f->tp)->memof; ! 19328: else ocl = Pclass(ex->n_table->t_name->tp); ! 19329: // else ocl = 0; ! 19330: ! 19331: if ( eex->tp->base == FCT ) ! 19332: ncl = Pfct(eex->tp)->memof; ! 19333: else ! 19334: if ( eex->tp->base == OVERLOAD ) ! 19335: ncl = Pfct(Pgen(eex->tp)->fct_list->f->tp)->memof; ! 19336: else ncl = Pclass(eex->n_table->t_name->tp); ! 19337: // else ncl = 0; ! 19338: ! 19339: // Pclass ocl = Pfct(ex->tp)->memof; ! 19340: // Pclass ncl = Pfct(eex->tp)->memof; ! 19341: int eb = ocl?ocl->has_base(ncl):0; ! 19342: int eeb = ncl?ncl->has_base(ocl):0; ! 19343: ! 19344: //error('d',"eb %d eeb %d evb %d eevb %d",eb,eeb,evb,eevb); ! 19345: if (eb==0 && eeb==0) { ! 19346: // different ! 19347: error("ambiguous%n and%n",ex,eex); ! 19348: break; ! 19349: } ! 19350: else if (eb) { // ex dominates ! 19351: if (eevb<evb) error("ambiguous%n and%n (different sub-objects)",ex,eex); ! 19352: } ! 19353: else { // eex dominates ! 19354: e = ee; ! 19355: bc = b; ! 19356: if (evb<eevb) error("ambiguous%n and%n (different sub-objects)",ex,eex); ! 19357: } ! 19358: if (evb==0 && eevb==0) { ! 19359: error("ambiguous%n and%n (different sub-objects)",ex,eex); ! 19360: } ! 19361: // } ! 19362: // else { ! 19363: // // different ! 19364: // error("ambiguous%n and%n",ex,eex); ! 19365: // break; ! 19366: // } ! 19367: } ! 19368: else if (ex->base==NAME ! 19369: && (Pname(ex)->n_evaluated || Pname(ex)->n_sto==EXTERN)) { ! 19370: //error('d',"enum"); ! 19371: } ! 19372: else if (evb==0 && eevb==0) { ! 19373: //error('d',"e %k",e->base); ! 19374: // no virtual base => different ! 19375: error("ambiguous%n and%n (no virtualB)",ex,eex); ! 19376: break; ! 19377: } ! 19378: else if ((evb && eevb==0) || (eevb && evb==0)) { ! 19379: // only one virtual base => different ! 19380: error("ambiguous%n and%n (one not in virtualB)",ex,eex); ! 19381: break; ! 19382: } ! 19383: } ! 19384: else { ! 19385: e = ee; ! 19386: bc = b; ! 19387: } ! 19388: } ! 19389: } ! 19390: ! 19391: if (rootClass == this ) { ! 19392: if ( pM ) { ! 19393: // deferred until all base classes of ``this'' examined ! 19394: error("%n cannot access %s: %s is a privateBC",pM->mf,pM->nm,pM->bc->bclass->string); ! 19395: delete pM; pM=0; ! 19396: } ! 19397: rootClass = 0; ! 19398: pubVClass = 0; ! 19399: } ! 19400: ! 19401: if (e == 0) return 0; ! 19402: ! 19403: if (mex) { ! 19404: if ( bc->ppp==PRIVATE ) { // private base ! 19405: if (this==mec || ! 19406: (mec && has_friend(mec)) || ! 19407: (mef && has_friend(mef))) ! 19408: ; ! 19409: else ! 19410: if ( bc->base == VIRTUAL && ! 19411: rootClass != this ) { ! 19412: // if one instance is public, it dominates ! 19413: if ( pubVClass == 0 || ! 19414: strcmp(pubVClass->bclass->string,bc->bclass->string)) { ! 19415: pM = (PendingMessage *) new char[sizeof(*pM)]; ! 19416: pM->bc = bc; pM->mf = me; pM->nm = s; ! 19417: } ! 19418: } ! 19419: else { ! 19420: if ( me == dummy_fct ) ! 19421: error("G scope cannot access %s: %s is a privateBC",s,bc->bclass->string); ! 19422: else error("%n cannot access %s: %s is a privateBC",me,s,bc->bclass->string); ! 19423: mex = 0; ! 19424: } ! 19425: } ! 19426: else { // public base class ! 19427: if ( bc->base == VIRTUAL ) { ! 19428: if ( pM && ! 19429: strcmp(bc->bclass->string,pM->bc->bclass->string)==0 ) { ! 19430: delete pM; ! 19431: pM=0; ! 19432: pubVClass = bc; ! 19433: } // previous private member becomes public ! 19434: else pubVClass = bc; // ignore subsequent private instances ! 19435: } ! 19436: } ! 19437: } ! 19438: ! 19439: if (e->base==NAME ! 19440: && Pname(e)->n_stclass==STATIC) { // static member ! 19441: Pname(e)->use(); ! 19442: return e; ! 19443: } ! 19444: if (e->base != NAME) ! 19445: if (bc->base == VIRTUAL) { // this->mem => this->Pbclass->mem ! 19446: e->mem = new mdot(bc->bclass->string,e->mem); ! 19447: e->mem->i1 = 1; ! 19448: e->mem->tp = e->mem->mem->tp; ! 19449: } ! 19450: else if (bc!=baselist) { // not first base ! 19451: if (e->e1 == cc->c_this) { // this->mem => this->Obcl.mem ! 19452: e->mem = new mdot(bc->bclass->string,e->mem); ! 19453: e->mem->tp = e->mem->mem->tp; ! 19454: } ! 19455: else { // this->p->mem => this->Obcl.p->mem ! 19456: Pexpr ee = e; ! 19457: while (ee->e1->base == REF) ee = ee->e1; ! 19458: ee->mem = new mdot(bc->bclass->string,ee->mem); ! 19459: ee->mem->tp = ee->mem->mem->tp; ! 19460: } ! 19461: } ! 19462: ! 19463: return e; ! 19464: } ! 19465: ! 19466: int has_virt(Pclass cl) ! 19467: { ! 19468: if (cl->virt_count) return 1; ! 19469: for (Pbcl b = cl->baselist; b; b = b->next) ! 19470: if (b->bclass->virt_count || has_virt(b->bclass)) return 1; ! 19471: return 0; ! 19472: } ! 19473: ! 19474: Pname find_vptr(Pclass cl) ! 19475: /* ! 19476: find virtual function table ! 19477: in memtbl or memtbl of ``first bases'' ! 19478: */ ! 19479: { ! 19480: //error('d',"find_vptr %t",cl); ! 19481: while (cl) { ! 19482: Pname vp = cl->memtbl->look("__vptr",0); ! 19483: if (vp) return vp; ! 19484: Pbcl b = cl->baselist; ! 19485: cl = 0; ! 19486: for (; b; b = b->next) ! 19487: if (b->base == NAME) { ! 19488: cl = b->bclass; ! 19489: break; ! 19490: } ! 19491: } ! 19492: //error('d',"return 0"); ! 19493: return 0; ! 19494: } ! 19495: ! 19496: void make_dummy() ! 19497: /* a function with no special privileges */ ! 19498: { ! 19499: Pname x = new name(".." /*"__static_initializer"*/); ! 19500: x->tp = new fct(Pvoid_type,0,1); ! 19501: dummy_fct = x->dcl(gtbl,EXTERN); ! 19502: // dummy_fct->string = ""; ! 19503: delete x; ! 19504: } ! 19505: ! 19506: void check_visibility(Pname n, Pname q, Pclass cl, Ptable tbl, Pname fn) ! 19507: /* ! 19508: "fn" calls "n" a member function of "cl" ! 19509: fn can be zero (for functions called in arguments to static constructors) ! 19510: */ ! 19511: { ! 19512: // error('d',"check_visibility(%n, %t, %d, %n)",n,cl,tbl,fn); ! 19513: if (fn==0) { ! 19514: if (dummy_fct == 0) make_dummy(); ! 19515: fn = dummy_fct; ! 19516: } ! 19517: Pname nn = new name; ! 19518: char* s = n->n_gen_fct_name; // overloaded name ! 19519: nn->string = s?s:n->string; ! 19520: nn->n_qualifier = q; ! 19521: Pname nx = Pname(find_name(nn,cl,tbl,REF,fn)); // nn deleted by find_name ! 19522: if (nx->tp->base != OVERLOAD) return; ! 19523: ! 19524: // can we get here? ! 19525: ! 19526: // overloaded not checked by find_name() ! 19527: // (since it looks for NAMEs not functions) ! 19528: ! 19529: for (Plist gl=Pgen(nx->tp)->fct_list; gl; gl=gl->l) { ! 19530: Pname nn = gl->f; ! 19531: if (n == nn) { ! 19532: if (nn->n_scope) return; // public member ! 19533: ! 19534: Pfct omef = mef; ! 19535: Pclass omec = mec; ! 19536: Pclass otcl = tcl; ! 19537: ! 19538: Pclass ncl = Pclass(nn->n_table->t_name->tp); ! 19539: Pname fncn = fn->n_table->t_name; ! 19540: ! 19541: mec = fncn?Pclass(fncn->tp):0; ! 19542: Pfct f = mef = Pfct(fn->tp); ! 19543: tcl = cl; ! 19544: ! 19545: int ok = is_accessible( n, ncl, 1 ); ! 19546: ! 19547: // restore global values ! 19548: mef = omef; mec = omec; tcl = otcl; ! 19549: ! 19550: if ( ok ) return; ! 19551: ! 19552: if ( Cdcl && Cdcl->base == NAME && ! 19553: Cdcl->n_stclass == STATIC && ! 19554: Cdcl->n_initializer && ! 19555: Cdcl->n_qualifier ) ! 19556: { ! 19557: Pbase bn = Pbase(Cdcl->n_qualifier->tp); ! 19558: Pclass ccl = Pclass(bn->b_name->tp); ! 19559: ! 19560: if ( ccl == cl || ccl->has_friend(f) || ! 19561: (n->n_protect && ccl->has_base(ncl))) ! 19562: return; ! 19563: } ! 19564: ! 19565: if ( fn == dummy_fct ) ! 19566: error("G scope cannot access%n: %sM",nn,nn->n_protect?"protected":"private"); ! 19567: else error("%n cannot access%n: %sM",fn,nn,nn->n_protect?"protected":"private"); ! 19568: return; ! 19569: } ! 19570: } ! 19571: error('i',"visibility check failed"); ! 19572: } ! 19573: 0707071010112044321004440001630000160000010202000466055403200000700000150132gram.y /*ident "@(#)ctrans:src/gram.y 1.11" */ ! 19574: /************************************************************************* ! 19575: ! 19576: C++ source for cfront, the C++ compiler front-end ! 19577: written in the computer science research center of Bell Labs ! 19578: ! 19579: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 19580: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 19581: ! 19582: gram.y: ! 19583: ! 19584: This is the C++ syntax analyser. ! 19585: ! 19586: Syntax extensions for error handling: ! 19587: nested functions ! 19588: any expression can be empty ! 19589: any expression can be a constant_expression ! 19590: ! 19591: A call to error() does not change the parser's state ! 19592: ! 19593: ***************************************************************************/ ! 19594: ! 19595: %{ ! 19596: #include "cfront.h" ! 19597: #include "size.h" ! 19598: #include "template.h" ! 19599: #include <string.h> ! 19600: // include tqueue.h after YYSTYPE is defined ... ! 19601: ! 19602: ! 19603: struct parstate { ! 19604: Ptype intypedef; ! 19605: int defercheck; ! 19606: Pname intag; ! 19607: } pstate[BLMAX]; ! 19608: static int px; ! 19609: static void ! 19610: SAVE_STATE() ! 19611: { ! 19612: if ( px++ >= BLMAX ) error('i',"maximum scope depth exceeded"); ! 19613: pstate[px].intypedef = in_typedef; ! 19614: in_typedef = 0; ! 19615: pstate[px].defercheck = defer_check; ! 19616: defer_check = 0; ! 19617: pstate[px].intag = in_tag; ! 19618: in_tag = 0; ! 19619: } ! 19620: static void ! 19621: RESTORE_STATE() ! 19622: { ! 19623: if ( --px < 0 ) error('i',"scope stack underflow"); ! 19624: in_typedef = pstate[px].intypedef; ! 19625: defer_check = pstate[px].defercheck; ! 19626: in_tag = pstate[px].intag; ! 19627: } ! 19628: ! 19629: #define copy_if_need_be(s) ((templp->in_progress || templp->parameters_in_progress) ? strdup(s) : s) ! 19630: #define YYMAXDEPTH 600 ! 19631: ! 19632: #ifdef DBG ! 19633: #ifndef YYDEBUG ! 19634: #define YYDEBUG 1 ! 19635: #endif ! 19636: #endif ! 19637: ! 19638: static init_seen = 0; ! 19639: static cdi = 0; ! 19640: static Pnlist cd = 0, cd_vec[BLMAX]; ! 19641: static char stmt_seen = 0, stmt_vec[BLMAX]; ! 19642: ! 19643: //local class ! 19644: static Plist tn_vec[BLMAX], lcl_tn_vec[BLMAX], lcl_blk_vec[BLMAX]; ! 19645: extern void local_restore(); ! 19646: extern void local_name(); ! 19647: ! 19648: //nested class ! 19649: static Plist nested_tn_vec[BLMAX], nested_type_vec[BLMAX]; ! 19650: extern void nested_restore(); ! 19651: ! 19652: static Pname err_name = 0; ! 19653: ! 19654: // fcts put into norm2.c just to get them out of gram.y ! 19655: void sig_name(Pname); ! 19656: Ptype tok_to_type(TOK); ! 19657: void memptrdcl(Pname, Pname, Ptype, Pname); ! 19658: ! 19659: static Pptr doptr(TOK p, TOK t) ! 19660: { ! 19661: Pptr r = new ptr(p,0); ! 19662: switch (t) { ! 19663: case CONST: ! 19664: r->rdo = 1; ! 19665: // if (p == RPTR) error('w',"redundant `const' after &"); ! 19666: break; ! 19667: case VOLATILE: ! 19668: error('w',"\"volatile\" not implemented (ignored)"); ! 19669: break; ! 19670: default: ! 19671: error("syntax error: *%k",t); ! 19672: } ! 19673: return r; ! 19674: } ! 19675: ! 19676: static Pbcl dobase(TOK pr, Pname n, TOK v = 0) ! 19677: { ! 19678: Pbcl b = new basecl(0,0); ! 19679: ! 19680: if (pr == PROTECTED) { ! 19681: pr = PUBLIC; ! 19682: error("protectedBC"); ! 19683: } ! 19684: b->ppp = pr; // save protection indicator ! 19685: ! 19686: if (n) { ! 19687: if (n->base != TNAME) { ! 19688: error("BN%n not aTN",n); ! 19689: return 0; ! 19690: } ! 19691: ! 19692: Pbase bt = Pbase(n->tp); ! 19693: while (bt->base == TYPE) bt = Pbase(bt->b_name->tp); ! 19694: ! 19695: if (bt->base != COBJ) { ! 19696: error("BN%n not aCN",n); ! 19697: return 0; ! 19698: } ! 19699: ! 19700: if (v) { ! 19701: if (v != VIRTUAL) error("syntax error:%k inBCD",v); ! 19702: b->base = VIRTUAL; ! 19703: } ! 19704: else ! 19705: b->base = NAME; ! 19706: ! 19707: b->bclass = Pclass(bt->b_name->tp); ! 19708: } ! 19709: ! 19710: return b; ! 19711: } ! 19712: ! 19713: ! 19714: #define Ndata(a,b) b->normalize(Pbase(a),0,0) ! 19715: #define Ncast(a,b) b->normalize(Pbase(a),0,1) ! 19716: #define Nfct(a,b,c) b->normalize(Pbase(a),Pblock(c),0) ! 19717: #define Ncopy(n) (n->base==TNAME)?new name(n->string):n ! 19718: ! 19719: #define Finit(p) Pfct(p)->f_init ! 19720: #define Fargdcl(p,q,r) Pfct(p)->argdcl(q,r) ! 19721: #define Freturns(p) Pfct(p)->returns ! 19722: #define Vtype(v) Pvec(v)->typ ! 19723: #define Ptyp(p) Pptr(p)->typ ! 19724: ! 19725: /* avoid redefinitions */ ! 19726: #undef EOFTOK ! 19727: #undef ASM ! 19728: #undef BREAK ! 19729: #undef CASE ! 19730: #undef CONTINUE ! 19731: #undef DEFAULT ! 19732: #undef DELETE ! 19733: #undef DO ! 19734: #undef ELSE ! 19735: #undef ENUM ! 19736: #undef FOR ! 19737: #undef FORTRAN ! 19738: #undef FRIEND ! 19739: #undef GOTO ! 19740: #undef IF ! 19741: #undef NEW ! 19742: #undef OPERATOR ! 19743: #undef RETURN ! 19744: #undef SIZEOF ! 19745: #undef SWITCH ! 19746: #undef THIS ! 19747: #undef WHILE ! 19748: #undef LP ! 19749: #undef RP ! 19750: #undef LB ! 19751: #undef RB ! 19752: #undef REF ! 19753: #undef DOT ! 19754: #undef NOT ! 19755: #undef COMPL ! 19756: #undef MUL ! 19757: #undef AND ! 19758: #undef PLUS ! 19759: #undef MINUS ! 19760: #undef ER ! 19761: #undef OR ! 19762: #undef ANDAND ! 19763: #undef OROR ! 19764: #undef QUEST ! 19765: #undef COLON ! 19766: #undef ASSIGN ! 19767: #undef CM ! 19768: #undef SM ! 19769: #undef LC ! 19770: #undef RC ! 19771: #undef ID ! 19772: #undef STRING ! 19773: #undef ICON ! 19774: #undef FCON ! 19775: #undef CCON ! 19776: #undef ZERO ! 19777: #undef ASOP ! 19778: #undef RELOP ! 19779: #undef EQUOP ! 19780: #undef DIVOP ! 19781: #undef SHIFTOP ! 19782: #undef ICOP ! 19783: #undef TYPE ! 19784: #undef TNAME ! 19785: #undef EMPTY ! 19786: #undef NO_ID ! 19787: #undef NO_EXPR ! 19788: #undef FDEF ! 19789: #undef ELLIPSIS ! 19790: #undef AGGR ! 19791: #undef MEM ! 19792: #undef MEMPTR ! 19793: #undef PR ! 19794: #undef TSCOPE ! 19795: #undef DECL_MARKER ! 19796: #undef REFMUL ! 19797: #undef LDOUBLE ! 19798: #undef LINKAGE ! 19799: #undef LOCAL ! 19800: #undef TEMPLATE ! 19801: ! 19802: #undef XVIRT ! 19803: #undef XNLIST ! 19804: #undef XILINE ! 19805: #undef XIA ! 19806: #undef STATEMENT ! 19807: #undef EXPRESSION ! 19808: #undef SM_PARAM ! 19809: #undef TEMPLATE_TEST ! 19810: #undef PTNAME ! 19811: #undef NEW_INIT_KLUDGE ! 19812: %} ! 19813: ! 19814: %union { ! 19815: char* s; ! 19816: TOK t; ! 19817: int i; ! 19818: loc l; ! 19819: Pname pn; ! 19820: Ptype pt; ! 19821: Pexpr pe; ! 19822: Pstmt ps; ! 19823: Pbase pb; ! 19824: Pnlist nl; ! 19825: Pslist sl; ! 19826: Pelist el; ! 19827: Pbcl pbc; ! 19828: Pptr pp; ! 19829: PP p; // fudge: pointer to all class node objects ! 19830: Plist pl; ! 19831: toknode* q; // token queue ! 19832: } ! 19833: %{ ! 19834: #include "tqueue.h" ! 19835: extern YYSTYPE yylval, yyval; ! 19836: extern int yyparse(); ! 19837: ! 19838: // in_typedef should allow for nested in_typedef ! 19839: extern int declTag; // !1: inline, virtual mod permitted ! 19840: int in_sizeof = 0; ! 19841: Ptype in_typedef = 0; // catch redefinition of TNAME ! 19842: Pname in_tag = 0; // handle complex typedefs: int (*)() ! 19843: extern int defer_check; // redefinition typedef check delay ! 19844: Pname curr_scope; ! 19845: ! 19846: extern int must_be_id; // !0, TNAME => ID, i.e., int X ! 19847: int DECL_TYPE = 0; // lalex() wants this set for global x(*fp)() ! 19848: int in_arg_list=0; // !0 when parsing argument list ! 19849: static int in_binit_list=0; ! 19850: int in_class_decl=0; // !0 when processing class definition ! 19851: int parsing_class_members=0; // !0 when parsing class def but not member function body ! 19852: int in_mem_fct=0; // !0 when parsing member function definition ! 19853: ! 19854: #define yylex lalex ! 19855: #define NEXTTOK() ( (yychar==-1) ? (yychar=yylex(),yychar) : yychar ) ! 19856: #define EXPECT_ID() must_be_id = 1 ! 19857: #define NOT_EXPECT_ID() must_be_id = 0 ! 19858: ! 19859: Pname syn() ! 19860: { ! 19861: ll: ! 19862: switch (yyparse()) { ! 19863: case 0: return 0; // EOF ! 19864: case 1: goto ll; // no action needed ! 19865: default: return yyval.pn; ! 19866: } ! 19867: } ! 19868: ! 19869: %} ! 19870: /* ! 19871: the token definitions are copied from token.h, ! 19872: and all %token replaced by %token ! 19873: */ ! 19874: /* keywords in alphabetical order */ ! 19875: %token EOFTOK 0 ! 19876: %token ASM 1 ! 19877: %token AUTO 2 ! 19878: %token BREAK 3 ! 19879: %token CASE 4 ! 19880: %token CONTINUE 7 ! 19881: %token DEFAULT 8 ! 19882: %token DELETE 9 ! 19883: %token DO 10 ! 19884: %token ELSE 12 ! 19885: %token ENUM 13 ! 19886: %token FOR 16 ! 19887: %token FORTRAN 17 ! 19888: %token FRIEND 18 ! 19889: %token GOTO 19 ! 19890: %token IF 20 ! 19891: %token NEW 23 ! 19892: %token OPERATOR 24 ! 19893: %token RETURN 28 ! 19894: %token SIZEOF 30 ! 19895: %token SWITCH 33 ! 19896: %token THIS 34 ! 19897: %token WHILE 39 ! 19898: ! 19899: /* operators in priority order (sort of) */ ! 19900: %token LP 40 ! 19901: %token RP 41 ! 19902: %token LB 42 ! 19903: %token RB 43 ! 19904: %token REF 44 ! 19905: %token DOT 45 ! 19906: %token NOT 46 ! 19907: %token COMPL 47 ! 19908: %token MUL 50 ! 19909: %token AND 52 ! 19910: %token PLUS 54 ! 19911: %token MINUS 55 ! 19912: %token LT 58 ! 19913: %token GT 60 ! 19914: %token ER 64 ! 19915: %token OR 65 ! 19916: %token ANDAND 66 ! 19917: %token OROR 67 ! 19918: %token QUEST 68 ! 19919: %token COLON 69 ! 19920: %token ASSIGN 70 ! 19921: %token CM 71 ! 19922: %token SM 72 ! 19923: %token LC 73 ! 19924: %token RC 74 ! 19925: ! 19926: /* = constants etc. */ ! 19927: %token ID 80 ! 19928: %token STRING 81 ! 19929: %token ICON 82 ! 19930: %token FCON 83 ! 19931: %token CCON 84 ! 19932: %token NAME 85 ! 19933: %token ZERO 86 ! 19934: /* groups of tokens */ ! 19935: %token ASOP 90 /* op= */ ! 19936: %token RELOP 91 /* LE GE LT GT */ ! 19937: %token EQUOP 92 /* EQ NE */ ! 19938: %token DIVOP 93 /* DIV MOD */ ! 19939: %token SHIFTOP 94 /* LS RS */ ! 19940: %token ICOP 95 /* INCR DECR */ ! 19941: %token TYPE 97 ! 19942: /* TYPE = INT FLOAT CHAR DOUBLE REGISTER STATIC EXTERN AUTO ! 19943: LONG SHORT UNSIGNED INLINE FRIEND VIRTUAL */ ! 19944: ! 19945: %token TNAME 123 ! 19946: %token EMPTY 124 ! 19947: %token NO_ID 125 ! 19948: %token NO_EXPR 126 ! 19949: %token FDEF 127 ! 19950: ! 19951: %token ELLIPSIS 155 ! 19952: %token AGGR 156 ! 19953: %token MEM 160 ! 19954: %token MEMPTR 173 ! 19955: %token PR 175 /* PUBLIC PRIVATE PROTECTED */ ! 19956: %token TSCOPE 178 /* TNAME :: */ ! 19957: %token DECL_MARKER 179 ! 19958: %token REFMUL 180 /* ->*, .* */ ! 19959: %token LDOUBLE 181 ! 19960: %token LINKAGE 182 /* extern "asdf" */ ! 19961: %token LOCAL 183 /* local class */ ! 19962: %token TEMPLATE 185 /* local class */ ! 19963: ! 19964: /* "tokens" for aux data structures */ ! 19965: ! 19966: %token XVIRT 200 /* class virt */ ! 19967: %token XNLIST 201 /* struct name_list */ ! 19968: %token XILINE 202 ! 19969: %token XIA 203 ! 19970: %token STATEMENT 205 ! 19971: %token EXPRESSION 206 ! 19972: %token SM_PARAM 207 ! 19973: %token TEMPLATE_TEST 208 ! 19974: %token PTNAME 209 ! 19975: %token NEW_INIT_KLUDGE 210 ! 19976: %token XDELETED_NODE 211 ! 19977: %token DUMMY_LAST_NODE 212 ! 19978: ! 19979: %type <p> external_def fct_dcl fct_def att_fct_def arg_dcl_list ! 19980: base_init init_list binit ! 19981: data_dcl ext_def vec ptr ! 19982: type tp enum_dcl moe_list moe ! 19983: tag ttag enumtag class_head class_dcl cl_mem_list ! 19984: cl_mem dl decl_list ! 19985: fname decl initializer stmt_list ! 19986: caselab_stmt caselablist ! 19987: block statement simple ex_list elist e ee term prim ! 19988: term_elist ! 19989: cast_decl cast_type c_decl c_type c_tp ! 19990: arg_decl formal_decl at arg_type arg_list arg_type_list ! 19991: new_decl new_type ! 19992: condition ! 19993: TSCOPE tscope TNAME tn_list MEMPTR ! 19994: qualified_tname ! 19995: PTNAME tname ptname template_def ! 19996: %type <l> LC RC SWITCH CASE DEFAULT FOR IF DO WHILE GOTO RETURN DELETE ! 19997: BREAK CONTINUE ! 19998: %type <t> oper ellipsis_opt ! 19999: EQUOP DIVOP SHIFTOP ICOP RELOP GT LT ASOP ! 20000: ANDAND OROR PLUS MINUS MUL ASSIGN OR ER AND ! 20001: LP LB NOT COMPL AGGR ! 20002: TYPE PR REFMUL ! 20003: STATEMENT EXPRESSION stmt_or_expr ! 20004: %type <s> CCON ZERO ICON FCON STRING LINKAGE ! 20005: %type <pn> ID FDEF inline_fct_def identifier ! 20006: %type <pbc> base_list base_unit_list base_unit ! 20007: %type <q> EMPTY ! 20008: %type <i> fct_attributes ! 20009: %type <pl> arg_lp ! 20010: %type <pe> temp_inst_parm ! 20011: %type <el> temp_inst_parms ! 20012: ! 20013: %left EMPTY ! 20014: %left NO_ID ! 20015: %left RC LC ID BREAK CONTINUE RETURN GOTO DELETE DO IF WHILE FOR CASE DEFAULT ! 20016: AGGR ENUM TYPE TNAME TSCOPE ! 20017: %left NO_EXPR ! 20018: ! 20019: %left CM ! 20020: %right ASOP ASSIGN ! 20021: %right QUEST COLON ! 20022: %left OROR ! 20023: %left ANDAND ! 20024: %left OR ! 20025: %left ER ! 20026: %left AND ! 20027: %left EQUOP ! 20028: %left RELOP GT LT ! 20029: %left SHIFTOP ! 20030: %left PLUS MINUS ! 20031: %left MUL DIVOP MEMPTR ! 20032: %left REFMUL ! 20033: %right NOT COMPL NEW ! 20034: %right ICOP SIZEOF ! 20035: %left LB LP DOT REF MEM ! 20036: ! 20037: %start ext_def ! 20038: ! 20039: %% ! 20040: /* ! 20041: this parser handles declarations one by one, ! 20042: NOT a complete .c file ! 20043: */ ! 20044: ! 20045: ! 20046: /************** DECLARATIONS in the outermost scope: returns Pname (in yylval) ***/ ! 20047: ! 20048: ext_def : external_def { return 2; } ! 20049: | SM { return 1; } ! 20050: | EOFTOK { return 0; } ! 20051: | LINKAGE LC ! 20052: { ! 20053: set_linkage($<s>1); ! 20054: bl_level--; ! 20055: return 1; ! 20056: } ! 20057: | RC ! 20058: { ! 20059: set_linkage(0); ! 20060: bl_level++; ! 20061: return 1; ! 20062: } ! 20063: | template { return 1; } ! 20064: | template_test { return 1 ;} ! 20065: ; ! 20066: ! 20067: ! 20068: template_test : TEMPLATE_TEST identifier LT temp_inst_parms GT SM ! 20069: { Ptreet t = tree_template::get($<pn>2->string) ; ! 20070: Pexpr e = 0 ; ! 20071: if (t) ! 20072: e = t->expand(expr_unlist($<el>4)) ; ! 20073: else error ("%s wasn't an expression template", ! 20074: $<pn>2->string) ; ! 20075: } ; ! 20076: ! 20077: template : TEMPLATE ! 20078: { templp->start() ; } ! 20079: LT template_parm_list GT ! 20080: {templp->enter_parameters() ; } ! 20081: template_def ! 20082: {templp->end($<pn>7); ! 20083: templp->in_progress = false ; ! 20084: goto mod;} ! 20085: ; ! 20086: ! 20087: template_def : att_fct_def ! 20088: { goto mod; } ! 20089: | fct_def ! 20090: { goto mod; } ! 20091: | class_dcl SM ! 20092: { Pname pn = $<pb>1->aggr(); ! 20093: /* basetype:aggr() does not return the name for a forward */ ! 20094: /* declaration, so extract it directly */ ! 20095: $$ = (pn ? pn : $<pb>1->b_name) ; ! 20096: DECL_TYPE = 0; } ! 20097: /* internal template specification productions*/ ! 20098: | STATEMENT ! 20099: {templp->curr_tree_template = $1 ; } ! 20100: identifier COLON statement ! 20101: {$<pn>3->n_initializer = $<pe>5 ; /* actually a stmt */ ! 20102: $<pn>$ = $<pn>3; } ! 20103: | EXPRESSION ! 20104: {templp->curr_tree_template = $1 ; } ! 20105: identifier COLON ee SM ! 20106: {$<pn>3->n_initializer = $<pe>5 ; /* actually a stmt */ ! 20107: $<pn>$ = $<pn>3 ; } ! 20108: ; ! 20109: ! 20110: identifier : ID ! 20111: | qualified_tname ! 20112: { $<pn>$ = Ncopy($<pn>1) ;} ; ! 20113: ; ! 20114: ! 20115: external_def : data_dcl ! 20116: { ! 20117: /* if function declartion with arguments ! 20118: * need to make sure modified_tn is traversed */ ! 20119: if ( $<pn>1 != 0 ! 20120: && $<pn>1->tp->base == FCT ! 20121: && Pfct($<pn>1->tp)->nargs !=0 ) ! 20122: goto mod; ! 20123: else { ! 20124: modified_tn = 0; ! 20125: curr_scope = 0; ! 20126: if ($<pn>1==0) $<i>$ = 1; ! 20127: } ! 20128: } ! 20129: | att_fct_def ! 20130: { goto mod; } ! 20131: | fct_def ! 20132: { goto mod; } ! 20133: | fct_dcl ! 20134: { mod: if (modified_tn) { ! 20135: restore(); ! 20136: modified_tn = 0; ! 20137: } ! 20138: local_blk = 0; ! 20139: curr_scope = 0; ! 20140: if (local_tn) { ! 20141: local_restore(); ! 20142: local_tn = 0; ! 20143: } ! 20144: ! 20145: if (nested_tn) { // x::f(){} ! 20146: nested_restore(); ! 20147: nested_tn = 0; ! 20148: nested_type = 0; ! 20149: } ! 20150: } ! 20151: | ASM LP STRING RP SM ! 20152: { Pname n = new name(make_name('A')); ! 20153: n->tp = new basetype(ASM,0); ! 20154: Pbase(n->tp)->b_name = Pname($<s>3); ! 20155: $$ = n; ! 20156: } ! 20157: ; ! 20158: ! 20159: fct_dcl : decl ASSIGN initializer SM ! 20160: { ! 20161: err_name = $<pn>1; ! 20162: if(err_name) err_name->n_initializer = $<pe>3; ! 20163: goto fix; ! 20164: } ! 20165: | decl SM ! 20166: { ! 20167: Ptype t; ! 20168: err_name = $<pn>1; ! 20169: fix: ! 20170: if (err_name == 0) { ! 20171: error("syntax error:TX"); ! 20172: $$ = Ndata(defa_type,err_name); ! 20173: } ! 20174: else if ((t=err_name->tp) == 0) { ! 20175: error("TX for%n",err_name); ! 20176: $$ = Ndata(defa_type,err_name); ! 20177: } ! 20178: else if (t->base==FCT) { ! 20179: if (Pfct(t)->returns==0) ! 20180: $$ = Nfct(defa_type,err_name,0); ! 20181: else ! 20182: $$ = Ndata(0,err_name); ! 20183: } ! 20184: else { ! 20185: error("syntax error:TX for%k%n",t->base,err_name); ! 20186: $$ = Ndata(defa_type,err_name); ! 20187: } ! 20188: } ! 20189: ; ! 20190: ! 20191: att_fct_def : type decl arg_dcl_list check_inline base_init block ! 20192: { Pname n = Nfct($1,$<pn>2,$6); ! 20193: Fargdcl(n->tp,name_unlist($<nl>3),n); ! 20194: Finit(n->tp) = $<pn>5; ! 20195: $$ = n; ! 20196: NOT_EXPECT_ID(); ! 20197: //???POP_SCOPE(); // undef arg names ! 20198: } ! 20199: | type decl arg_dcl_list check_inline EMPTY ! 20200: { ! 20201: Pname n = Nfct($1,$<pn>2,dummy); ! 20202: Fargdcl(n->tp,name_unlist($<nl>3),n); ! 20203: $<q>5->retval.pn = n; ! 20204: $$ = n; ! 20205: NOT_EXPECT_ID(); ! 20206: } ! 20207: | type decl arg_dcl_list check_inline NO_ID /*syntax error*/ ! 20208: { ! 20209: error(&$<pn>2->where,"syntax error -- did you forget a ';'?"); ! 20210: Pname n = Nfct($1,$<pn>2,0); ! 20211: $$ = n; ! 20212: NOT_EXPECT_ID(); ! 20213: //???POP_SCOPE(); // undef arg names ! 20214: } ! 20215: ; ! 20216: ! 20217: fct_def : decl arg_dcl_list check_inline base_init block ! 20218: { Pname n = Nfct(defa_type,$<pn>1,$5); ! 20219: Fargdcl(n->tp,name_unlist($<nl>2),n); ! 20220: if ( $<pn>4 && $<pn>4->n_list && ! 20221: ccl && ccl->csu == UNION ) ! 20222: error( "multiple initializers in unionK %s::%n", $<pn>1->string, $<pn>1 ); ! 20223: Finit(n->tp) = $<pn>4; ! 20224: $$ = n; ! 20225: NOT_EXPECT_ID(); ! 20226: //???POP_SCOPE(); // undef arg names ! 20227: } ! 20228: | decl arg_dcl_list check_inline EMPTY ! 20229: { ! 20230: Pname n = Nfct(defa_type,$<pn>1,dummy); ! 20231: Fargdcl(n->tp,name_unlist($<nl>2),n); ! 20232: $<q>4->retval.pn = n; ! 20233: $$ = n; ! 20234: NOT_EXPECT_ID(); ! 20235: } ! 20236: | decl arg_dcl_list check_inline NO_ID /*syntax error*/ ! 20237: { ! 20238: error(&$<pn>1->where,"badD of%n -- did you forget a ';'?",$<pn>1); ! 20239: Pname n = Nfct(defa_type,$<pn>1,0); ! 20240: $$ = n; ! 20241: NOT_EXPECT_ID(); ! 20242: //???POP_SCOPE(); // undef arg names ! 20243: } ! 20244: ; ! 20245: ! 20246: inline_fct_def : FDEF ! 20247: {//PUSH_ARG_SCOPE ! 20248: arg_redec($<pn>1); ! 20249: } ! 20250: base_init block ! 20251: { ! 20252: Finit($1->tp) = $<pn>3; ! 20253: Pfct($1->tp)->body = Pblock($4); ! 20254: $$ = $1; ! 20255: NOT_EXPECT_ID(); ! 20256: //???POP_SCOPE(); // undef arg names ! 20257: } ! 20258: ; ! 20259: ! 20260: ! 20261: check_inline : /* empty */ ! 20262: { ! 20263: // if parsing implicit inline def, save body ! 20264: // of function for parsing after class def ! 20265: switch ( NEXTTOK() ) { ! 20266: case LC: case COLON: ! 20267: if ( in_class_decl ) { ! 20268: // mem or friend inline def ! 20269: // save text of mem_init & ftn ! 20270: la_backup(yychar,yylval); ! 20271: // yylval used as dummy... ! 20272: la_backup(FDEF, yylval); ! 20273: if ( yylval.q = save_text() ) ! 20274: yychar = EMPTY; ! 20275: else { // syntax error ! 20276: // just parse in place ! 20277: yylex(); // FDEF ! 20278: yychar = yylex(); ! 20279: } ! 20280: } // if in_class_decl ! 20281: break; ! 20282: default: ! 20283: la_backup(yychar,yylval); ! 20284: yychar = NO_ID; // 'graceful' recovery ! 20285: break; ! 20286: } ! 20287: } ! 20288: ; ! 20289: ! 20290: base_init : COLON { ++in_binit_list; } init_list ! 20291: { ! 20292: $$ = $3; ! 20293: in_arg_list = 0; ! 20294: --in_binit_list; ! 20295: } ! 20296: | %prec EMPTY ! 20297: { $$ = 0; } ! 20298: ; ! 20299: ! 20300: init_list : binit ! 20301: { $$ = $1; } ! 20302: | init_list CM binit ! 20303: { $<pn>$ = $<pn>3; $<pn>$->n_list = $<pn>1; } ! 20304: ; ! 20305: ! 20306: binit : LP elist RP ! 20307: { ! 20308: $<pn>$ = new name; ! 20309: $<pn>$->n_initializer = $<pe>2; ! 20310: } ! 20311: | ttag LP elist RP ! 20312: { ! 20313: Pname n = Ncopy($<pn>1); ! 20314: n->base = $<pn>1->base; ! 20315: n->tp = $<pn>1->tp; ! 20316: n->n_initializer = $<pe>3; ! 20317: $<pn>$ = n; ! 20318: } ! 20319: ! 20320: /* ! 20321: | NEW LP elist RP ! 20322: { Pname n = new name; ! 20323: n->base = NEW; ! 20324: n->n_initializer = $<pe>3; ! 20325: $<pn>$ = n; ! 20326: } ! 20327: */ ! 20328: ; ! 20329: ! 20330: ! 20331: ! 20332: ! 20333: /*************** declarations: returns Pname ********************/ ! 20334: ! 20335: arg_dcl_list : arg_dcl_list data_dcl ! 20336: { if ($<pn>2 == 0) ! 20337: error("badAD"); ! 20338: else if ($<pn>2->tp->base == FCT) ! 20339: error("FD inAL (%n)",$<pn>2); ! 20340: else if ($1) ! 20341: $<nl>1->add_list($<pn>2); ! 20342: else ! 20343: $<nl>$ = new nlist($<pn>2); ! 20344: } ! 20345: | %prec EMPTY ! 20346: { ! 20347: $$ = 0; ! 20348: } ! 20349: ; ! 20350: ! 20351: dl : decl ! 20352: | ID COLON ! 20353: { ! 20354: if ( in_typedef ) { ! 20355: error("Tdef field"); ! 20356: in_typedef = 0; ! 20357: } ! 20358: // ENTER_NAME($<pn>1); ! 20359: } ! 20360: e %prec CM ! 20361: { $$ = $<pn>1; ! 20362: $<pn>$->tp = new basetype(FIELD,$<pn>4); ! 20363: } ! 20364: | COLON e %prec CM ! 20365: { $$ = new name; ! 20366: $<pn>$->tp = new basetype(FIELD,$<pn>2); ! 20367: if ( in_typedef ) { ! 20368: error("Tdef field"); ! 20369: in_typedef = 0; ! 20370: } ! 20371: } ! 20372: | decl ASSIGN ! 20373: { ! 20374: // ENTER_NAME($<pn>1); ! 20375: } ! 20376: initializer ! 20377: { Pexpr e = $<pe>4; ! 20378: if (e == dummy) error("emptyIr"); ! 20379: $<pn>1->n_initializer = e; ! 20380: init_seen = 0; ! 20381: } ! 20382: ; ! 20383: ! 20384: decl_list : dl ! 20385: { ! 20386: if ($1) $<nl>$ = new nlist($<pn>1); ! 20387: if ( NEXTTOK() == CM && la_look() == TNAME ) ! 20388: EXPECT_ID(); ! 20389: } ! 20390: | decl_list CM dl ! 20391: { if ($1) ! 20392: if ($3) ! 20393: $<nl>1->add($<pn>3); ! 20394: else ! 20395: error("DL syntax"); ! 20396: else { ! 20397: if ($3) $<nl>$ = new nlist($<pn>3); ! 20398: error("DL syntax"); ! 20399: } ! 20400: if ( NEXTTOK() == CM && la_look() == TNAME ) ! 20401: EXPECT_ID(); ! 20402: } ! 20403: ; ! 20404: ! 20405: data_dcl : type decl_list SM ! 20406: { ! 20407: extern int co_hack; ! 20408: co_hack = 1; ! 20409: /*$$ = Ndata($1,name_unlist($<nl>2));*/ ! 20410: Pname n = Ndata($1,name_unlist($<nl>2)); ! 20411: if ( in_typedef && in_tag ) { ! 20412: if ( n->tp->check( in_tag->tp, 0 )) ! 20413: error("%nredefined: previous: %t now: %t", in_tag, in_tag->tp, n->tp ); ! 20414: } ! 20415: in_typedef = 0; ! 20416: in_tag = 0; ! 20417: co_hack = 0; ! 20418: DECL_TYPE = 0; ! 20419: $$ = n; ! 20420: } ! 20421: | type SM ! 20422: { ! 20423: $$ = $<pb>1->aggr(); ! 20424: in_typedef = 0; ! 20425: in_tag = 0; ! 20426: DECL_TYPE = 0; ! 20427: } ! 20428: ! 20429: ; ! 20430: ! 20431: /* This is where parametrized types, and regular types come together. */ ! 20432: ! 20433: lt : LT { templp->parameters_in_progress++; }; ! 20434: gt : GT { templp->parameters_in_progress--; }; ! 20435: ! 20436: tname : qualified_tname { $<pn>$ = templp->check_tname($<pn>1) ; } ! 20437: | qualified_tname lt temp_inst_parms gt ! 20438: { ! 20439: $<pn>$ = parametrized_typename($<pn>1, ! 20440: (expr_unlist($<el>3))) ; ! 20441: } ! 20442: | NAME LT temp_inst_parms GT ! 20443: { extern Pbase any_type; ! 20444: error("%n was not a parametrized type.", $<pn>$) ; ! 20445: $<pn>$= $<pn>1->tdef() ; ! 20446: $<pn>$->tp = any_type ; } ; ! 20447: ! 20448: ! 20449: ! 20450: tp : TYPE ! 20451: { ! 20452: $$ = new basetype($<t>1,0); ! 20453: if ( $<t>1 == TYPEDEF ) in_typedef = $<pt>$; ! 20454: if (DECL_TYPE == -1) DECL_TYPE = 0; ! 20455: } ! 20456: | LINKAGE ! 20457: { $$ = new basetype(EXTERN,0); ! 20458: $<pb>$->b_linkage = $<s>1; ! 20459: if (DECL_TYPE == -1) DECL_TYPE = 0; ! 20460: } ! 20461: | qualified_tname ! 20462: { ! 20463: templp->check_tname($<pn>1); ! 20464: $$ = new basetype(TYPE,$<pn>1); ! 20465: if (DECL_TYPE == -1) DECL_TYPE = 0; ! 20466: } ! 20467: /*XXX*/ | tn_list DECL_MARKER ! 20468: { // modified tn_list TNAME ! 20469: $$ = new basetype(TYPE,$<pn>2); ! 20470: //xxx qualifier currently ignored... ! 20471: if (DECL_TYPE == -1) DECL_TYPE = 0; ! 20472: } ! 20473: | qualified_tname lt temp_inst_parms gt ! 20474: { ! 20475: $<pb>$ = parametrized_basetype($<pn>1,(expr_unlist($<el>3))); ! 20476: } ! 20477: | class_dcl ! 20478: | enum_dcl ! 20479: | DECL_MARKER ! 20480: { ! 20481: if (DECL_TYPE == TNAME) ! 20482: $$ = new basetype(TYPE,$<pn>1); ! 20483: // else if (DECL_TYPE == TSCOPE) ! 20484: // $$ = 0; ! 20485: else ! 20486: if (DECL_TYPE == 0 && ! 20487: $<p>1->base == TNAME) ! 20488: $$ = new basetype(TYPE,$<pn>1); ! 20489: else ! 20490: $$ = new basetype($<t>1,0); ! 20491: DECL_TYPE = -1; ! 20492: } ! 20493: ; ! 20494: ! 20495: type : tp ! 20496: | type TYPE ! 20497: { ! 20498: if ( DECL_TYPE != -1 ) { ! 20499: switch ($<pb>1->base) { Pbase bt; ! 20500: case COBJ: case EOBJ: ! 20501: bt = new basetype(0,0); ! 20502: *bt = *$<pb>1; ! 20503: DEL($<pb>1); ! 20504: $<pb>1 = bt; ! 20505: } ! 20506: $$ = $<pb>1->type_adj($<t>2); ! 20507: } ! 20508: DECL_TYPE = 0; ! 20509: } ! 20510: | type tname ! 20511: { ! 20512: //error('d',"decl_type: %d $1: %t $2: %n",DECL_TYPE,$<pb>1,$<pn>2); ! 20513: if ( DECL_TYPE != -1 ) ! 20514: $$ = $<pb>1->name_adj($<pn>2); ! 20515: /*XXX*/ else if($<pb>1==0) $$=new basetype(TYPE,$<pn>2); ! 20516: DECL_TYPE = 0; ! 20517: } ! 20518: | type class_dcl { $$ = $<pb>1->base_adj($<pb>2); } ! 20519: | type enum_dcl { $$ = $<pb>1->base_adj($<pb>2); } ! 20520: | type DECL_MARKER ! 20521: { ! 20522: if (DECL_TYPE == TYPE) { ! 20523: switch ($<pb>1->base) { Pbase bt; ! 20524: case COBJ: case EOBJ: ! 20525: bt = new basetype(0,0); ! 20526: *bt = *$<pb>1; ! 20527: DEL($<pb>1); ! 20528: $<pb>1 = bt; ! 20529: } ! 20530: $$ = $<pb>1->type_adj($<t>2); ! 20531: } ! 20532: /*XXX*/ else if (DECL_TYPE == TSCOPE) { ! 20533: /*XXX*/ error('i',"type decl_marker(tscope)"); ! 20534: /*XXX*/ // $$ = $1;//ignore(?) ! 20535: /*XXX*/ } ! 20536: else ! 20537: $$ = $<pb>1->name_adj($<pn>2); ! 20538: DECL_TYPE = -1; ! 20539: } ! 20540: ; ! 20541: ! 20542: temp_inst_parms : temp_inst_parms CM temp_inst_parm ! 20543: {$<el>1->add(new expr(ELIST,$<pe>3,NULL)) ; } ! 20544: | temp_inst_parm { $<el>$ = ! 20545: new elist(new expr(ELIST,$<pe>1,NULL)); } ; ! 20546: ! 20547: temp_inst_parm : new_type ! 20548: {$<pn>1->n_template_arg = template_actual_arg_dummy ; ! 20549: $<pe>$ = $<pn>1; /* keep yacc happy */ } ! 20550: | e %prec GT ! 20551: { $<pe>$ = $<pe>1 ; } ; ! 20552: ! 20553: /***************** aggregate: returns Pname *****************/ ! 20554: ! 20555: enumtag : tag ! 20556: { enumcheck: ! 20557: Ptype tx = $<pn>1->tp; ! 20558: $$ = $1; ! 20559: if ( tx->base == TYPE ) { ! 20560: $$ = Pbase(tx)->b_name; ! 20561: tx = $<pn>$->tp; ! 20562: if ( tx->base != EOBJ ! 20563: || strcmp($<pn>$->string,$<pn>1->string) ! 20564: ) ! 20565: error("%n of type%t redeclared as enum.",$<pn>1,tx); ! 20566: } else if ( tx->base != EOBJ ) ! 20567: error("%n of type%t redeclared as enum",$<pn>1,tx); ! 20568: } ! 20569: | DECL_MARKER { goto enumcheck; } ! 20570: ; ! 20571: ! 20572: enum_dcl : ENUM LC moe_list RC { $$ = end_enum(0,$<nl>3); } ! 20573: | ENUM enumtag LC moe_list RC { $$ = end_enum($<pn>2,$<nl>4); } ! 20574: | ENUM enumtag { $<pb>$ = (Pbase)$<pn>2->tp; } ! 20575: ; ! 20576: ! 20577: moe_list : moe ! 20578: { if ($1) $<nl>$ = new nlist($<pn>1); } ! 20579: | moe_list CM moe ! 20580: { if( $3) ! 20581: if ($1) ! 20582: $<nl>1->add($<pn>3); ! 20583: else ! 20584: $<nl>$ = new nlist($<pn>3); ! 20585: } ! 20586: ; ! 20587: ! 20588: template_parm_list : template_parm_list CM template_parm ! 20589: | template_parm ! 20590: | { $<pn>$ = NULL ;} ; ! 20591: ! 20592: ! 20593: stmt_or_expr : STATEMENT | EXPRESSION ; ! 20594: ! 20595: template_parm : AGGR identifier ! 20596: /* Build the name for the parameter ! 20597: /* Check that AGGR is indeed CLASS */ ! 20598: { templp->collect($<t>1, $<pn>2) ; } ! 20599: | stmt_or_expr identifier ! 20600: { templp->collect($<t>1, $<pn>2) ; } ! 20601: | type formal_decl ! 20602: {templp->collect(Ndata($1,$<pn>2)); } ; ! 20603: ! 20604: ! 20605: /* Sam: these productions are a variant of the ones for arg_decl, ! 20606: verify them against arg_decl for each release. */ ! 20607: formal_decl : ID ! 20608: { $$ = $<pn>1; } ! 20609: | ptr formal_decl %prec MUL ! 20610: { Ptyp($1) = $<pn>2->tp; ! 20611: $<pn>2->tp = (Ptype)$1; ! 20612: $$ = $2; ! 20613: } ! 20614: | formal_decl vec %prec LB ! 20615: { Vtype($2) = $<pn>1->tp; ! 20616: $<pn>1->tp = (Ptype)$2; ! 20617: } ! 20618: | formal_decl arg_list ! 20619: { Freturns($2) = $<pn>1->tp; ! 20620: $<pn>1->tp = (Ptype)$2; ! 20621: } ; ! 20622: ! 20623: ! 20624: moe : ID ! 20625: { $$ = $<pn>1; $<pn>$->tp = moe_type; } ! 20626: | ID ASSIGN e ! 20627: { $$ = $<pn>1; ! 20628: $<pn>$->tp = moe_type; ! 20629: $<pn>$->n_initializer = $<pe>3; ! 20630: } ! 20631: | /* empty: handle trailing CM: enum e { a,b, }; */ ! 20632: { $$ = 0; } ! 20633: ; ! 20634: ! 20635: class_dcl : class_head cl_mem_list RC ! 20636: { parsing_class_members = 0; ! 20637: RESTORE_STATE(); ! 20638: switch ( NEXTTOK() ) { ! 20639: case TYPE: case AGGR: case ENUM: case EOFTOK: ! 20640: error("`;' or declaratorX afterCD"); ! 20641: la_backup(yychar,yylval); ! 20642: yychar = SM; ! 20643: break; ! 20644: } ! 20645: la_backup(yychar,yylval); ! 20646: yychar = -1; ! 20647: restore_text(); ! 20648: ++bl_level; // scope weirdness! ! 20649: ++in_mem_fct; ! 20650: } ! 20651: inline_mem_defs ! 20652: { ! 20653: --in_mem_fct; ! 20654: --bl_level; // scope weirdness! ! 20655: if ( yychar == ID ) { ! 20656: // (yuk!) adjust lex level ! 20657: --yylval.pn->lex_level; ! 20658: } ! 20659: ccl->mem_list = name_unlist($<nl>2); ! 20660: if ( --in_class_decl ) // nested class ! 20661: // continue to parse enclosing class ! 20662: parsing_class_members = 1; ! 20663: ccl->nest_list = nested_type; ! 20664: if ( nested_tn ) nested_restore(); ! 20665: nested_type = nested_type_vec[in_class_decl]; ! 20666: nested_tn = nested_tn_vec[in_class_decl]; ! 20667: end_cl(); ! 20668: declTag = 1; ! 20669: //POP_SCOPE(); ! 20670: } ! 20671: | AGGR tag ! 20672: { aggrcheck: ! 20673: $<pb>$ = (Pbase)$<pn>2->tp; ! 20674: if ( $$->base == TYPE ) { ! 20675: Pname nx = $<pb>$->b_name; ! 20676: $<pb>$ = (Pbase)nx->tp; ! 20677: if ( $$->base != COBJ ! 20678: || strcmp(nx->string,$<pn>2->string) ! 20679: ) ! 20680: error("%n of type%t redeclared as%k.",$<pn>2,$<pb>$,$<t>1); ! 20681: } else if ( $$->base != COBJ ) ! 20682: error("%n of type%t redeclared as%k",$<pn>2,$<pb>$,$<t>1); ! 20683: check_tag(); ! 20684: } ! 20685: | AGGR qualified_tname lt temp_inst_parms gt ! 20686: { ! 20687: Pname p = parametrized_typename($<pn>2, (expr_unlist($<el>4))) ; ! 20688: $<pb>$ = (Pbase)p->tp; ! 20689: check_tag(); ! 20690: } ! 20691: | AGGR DECL_MARKER ! 20692: { ! 20693: goto aggrcheck; ! 20694: } ! 20695: ; ! 20696: ! 20697: ! 20698: inline_mem_defs : /* empty */ ! 20699: | inline_mem_defs inline_fct_def ! 20700: ; ! 20701: ! 20702: base_list : COLON base_unit_list { $$ = $2; } ! 20703: | %prec EMPTY { $$ = 0; } ! 20704: ; ! 20705: ! 20706: base_unit_list : base_unit ! 20707: | base_unit_list CM base_unit ! 20708: { if ($3) { $$ = $3; $<pbc>$->next = $1; } } ! 20709: ; ! 20710: ! 20711: base_unit : ttag { $$ = dobase(0,$<pn>1); } ! 20712: | PR ttag { $$ = dobase($<t>1,$<pn>2); } ! 20713: | TYPE ttag { $$ = dobase(0,$<pn>2,$<t>1); } ! 20714: | PR TYPE ttag { $$ = dobase($<t>1,$<pn>3,$<t>2); } ! 20715: | TYPE PR ttag { $$ = dobase($<t>2,$<pn>3,$<t>1); } ! 20716: ; ! 20717: ! 20718: class_head : AGGR LC ! 20719: {//PUSH_CLASS_SCOPE(0); ! 20720: parsing_class_members = 1; ! 20721: $$ = start_cl($<t>1,0,0); ! 20722: nested_tn_vec[in_class_decl] = nested_tn; ! 20723: nested_type_vec[in_class_decl++] = nested_type; ! 20724: nested_tn = nested_type = 0; ! 20725: SAVE_STATE(); ! 20726: } ! 20727: ! 20728: | AGGR tag base_list LC ! 20729: { //PUSH_CLASS_SCOPE($<pn>2->string); ! 20730: parsing_class_members = 1; ! 20731: $$ = start_cl($<t>1,$<pn>2,$<pbc>3); ! 20732: nested_tn_vec[in_class_decl] = nested_tn; ! 20733: nested_type_vec[in_class_decl++] = nested_type; ! 20734: nested_tn = nested_type = 0; ! 20735: SAVE_STATE(); ! 20736: } ! 20737: ; ! 20738: ! 20739: tag : ID { $$ = $1; } ! 20740: | qualified_tname { $$=$1; } ! 20741: ; ! 20742: ! 20743: ttag : ID { $$ = $1; } ! 20744: | tname { $$=$1; } ! 20745: ; ! 20746: ! 20747: cl_mem_list : cl_mem_list cl_mem ! 20748: { ! 20749: if ($2) { ! 20750: if ($1) ! 20751: $<nl>1->add_list($<pn>2); ! 20752: else ! 20753: $<nl>$ = new nlist($<pn>2); ! 20754: } ! 20755: } ! 20756: | %prec EMPTY { $$ = 0; } ! 20757: | cl_mem_list TEMPLATE ! 20758: { ! 20759: error( "ZizedTD must be atG, notC scope" ); ! 20760: error('i', "cannot recover from previous error" ); ! 20761: } ! 20762: ; ! 20763: ! 20764: cl_mem : data_dcl ! 20765: | att_fct_def SM ! 20766: | fct_def SM ! 20767: | fct_def ! 20768: | att_fct_def ! 20769: | fct_dcl ! 20770: | PR COLON ! 20771: { $$ = new name; ! 20772: $<pn>$->base = $<t>1; ! 20773: } ! 20774: /*XXX | tn_list TNAME SM ! 20775: * { Pname n = Ncopy($<pn>2); ! 20776: * n->n_qualifier = $<pn>1; ! 20777: * n->base = PR; ! 20778: * $$ = n; ! 20779: * } ! 20780: */ | tn_list fname SM ! 20781: { Pname n = Ncopy($<pn>2); ! 20782: if (n->n_oper == TYPE) { ! 20783: error('s',"visibilityD for conversion operator"); ! 20784: // n->tp = Ptype(n->n_initializer); ! 20785: n->tp = Ptype(n->cond); ! 20786: n->cond = 0; ! 20787: // n->n_initializer = 0; ! 20788: n->n_oper = 0; ! 20789: sig_name(n); ! 20790: } ! 20791: n->n_qualifier = $<pn>1; ! 20792: n->base = PR; ! 20793: $$ = n; ! 20794: } ! 20795: ; ! 20796: ! 20797: /************* declarators: returns Pname **********************/ ! 20798: /* a ``decl'' is used for function and data declarations, ! 20799: and for member declarations ! 20800: (it has a name) ! 20801: an ``arg_decl'' is used for argument declarations ! 20802: (it may or may not have a name) ! 20803: an ``cast_decl'' is used for casts ! 20804: (it does not have a name) ! 20805: a ``new_decl'' is used for type specifiers for the NEW operator ! 20806: (it does not have a name, and PtoF and PtoV cannot be expressed) ! 20807: */ ! 20808: ! 20809: fname : ID ! 20810: { $$ = $<pn>1; } ! 20811: | COMPL TNAME /* qualified_tname? */ ! 20812: { $$ = Ncopy($<pn>2); ! 20813: $<pn>$->n_oper = DTOR; ! 20814: } ! 20815: | OPERATOR oper ! 20816: { $$ = new name(oper_name($2)); ! 20817: $<pn>$->n_oper = $<t>2; ! 20818: } ! 20819: | OPERATOR c_type ! 20820: { Pname n = $<pn>2; ! 20821: n->string = "_type"; ! 20822: n->n_oper = TYPE; ! 20823: n->cond = Pexpr(n->tp); ! 20824: // n->n_initializer = Pexpr(n->tp); ! 20825: n->tp = 0; ! 20826: $$ = n; ! 20827: } ! 20828: ; ! 20829: ! 20830: oper : PLUS ! 20831: | MINUS ! 20832: | MUL ! 20833: | AND ! 20834: | OR ! 20835: | ER ! 20836: | SHIFTOP ! 20837: | EQUOP ! 20838: | DIVOP ! 20839: | RELOP ! 20840: | LT ! 20841: | GT ! 20842: | ANDAND ! 20843: | OROR ! 20844: | LP RP { $$ = CALL; } ! 20845: | LB RB { $$ = DEREF; } ! 20846: | NOT ! 20847: | COMPL ! 20848: | ICOP ! 20849: | ASOP ! 20850: | ASSIGN ! 20851: | NEW { $$ = NEW; } ! 20852: | DELETE { $$ = DELETE; } ! 20853: | REF { $$ = REF; } ! 20854: | CM { $$ = CM; } ! 20855: | REFMUL { $$ = REFMUL; ! 20856: if ($<t>1 == DOT) error(".* cannot be overloaded"); ! 20857: } ! 20858: ; ! 20859: ! 20860: tn_list : tscope ! 20861: /*XXX*/ { if ( $<pn>1 != sta_name ) { ! 20862: // error('d',"tn_list: tscope: pn1: %s", $<pn>1->string); ! 20863: Ptype t = $<pn>1->tp; ! 20864: while ( t->base == TYPE ) ! 20865: t = Pbase(t)->b_name->tp; ! 20866: Pname n = Pbase(t)->b_name; ! 20867: if (NEXTTOK() == TNAME ! 20868: && strcmp(n->string,yylval.pn->string)==0){ ! 20869: // ctor -- change to ID to avoid ! 20870: // parsing as type spec ! 20871: yychar = ID; ! 20872: yylval.pn = Ncopy(yylval.pn); ! 20873: yylval.pn->n_oper = TNAME; ! 20874: } ! 20875: } ! 20876: $<pn>$ = $<pn>1; ! 20877: } ! 20878: /* YYY | tn_list tscope { $<pn>$ = $<pn>1; } */ ! 20879: | tn_list tscope { error('s', "CNs do not nest, use typedef x::y y_in_x"); }; ! 20880: /*XXX | tn_list ID DOT { error("CNs do not nest"); } */ ! 20881: ; ! 20882: ! 20883: qualified_tname : tn_list TNAME ! 20884: { $<pn>$ = $<pn>2; ! 20885: //xxx qualifier currently ignored... ! 20886: // $<pn>$ = Ncopy( $<pn>2 ); ! 20887: // $<pn>$->n_oper = TNAME; ! 20888: // $<pn>$->n_qualifier = $<pn>1; ! 20889: } ! 20890: | TNAME ! 20891: { $<pn>$ = $<pn>1; ! 20892: // $<pn>$ = Ncopy( $<pn>1 ); ! 20893: // $<pn>$->n_oper = TNAME; ! 20894: } ! 20895: ; ! 20896: ! 20897: fct_attributes : /* empty */ ! 20898: { $$ = 0; } ! 20899: | fct_attributes TYPE ! 20900: { /* const/volatile function */ ! 20901: switch ( $<t>2 ) { ! 20902: case VOLATILE: ! 20903: error('s',"volatile functions"); ! 20904: break; ! 20905: case CONST: ! 20906: $$ = ($1 | 1); ! 20907: break; ! 20908: default: ! 20909: if ( NEXTTOK() != SM ! 20910: && yychar != COLON ! 20911: && yychar != LC ) { ! 20912: la_backup(yychar,yylval); ! 20913: yylval.t = $<t>2; ! 20914: la_backup(TYPE,yylval); ! 20915: yylval.t = SM; ! 20916: yychar = SM; ! 20917: error("syntax error: unexpected%k (did you forget a `;'?)",$<t>2); ! 20918: } else error("FD syntax: unexpected%k",$<t>2); ! 20919: break; ! 20920: } ! 20921: } ! 20922: ; ! 20923: ! 20924: decl : decl arg_list ! 20925: { Freturns($2) = $<pn>1->tp; ! 20926: $<pn>1->tp = $<pt>2; ! 20927: } ! 20928: | decl LP RP fct_attributes ! 20929: { /* function with no argument */ ! 20930: $<pn>1->tp = new fct($<pn>1->tp,0,1); ! 20931: Pfct($<pn>1->tp)->f_const = ($<i>4 & 1); ! 20932: } ! 20933: | tname arg_list ! 20934: { Pname n = $<pn>1; ! 20935: $$ = Ncopy(n); ! 20936: //??? what if tname is qualified ??? ! 20937: if (ccl && strcmp(n->string,ccl->string)) n->hide(); ! 20938: $<pn>$->n_oper = TNAME; ! 20939: Freturns($2) = $<pn>$->tp; ! 20940: $<pn>$->tp = $<pt>2; ! 20941: } ! 20942: | decl arg_lp elist RP ! 20943: /* may be class object initializer, ! 20944: class object vector initializer, ! 20945: if not elist will be a CM or an ID ! 20946: */ ! 20947: { ! 20948: $<pn>1->tp = new fct($<pn>1->tp,$<pn>3,1); ! 20949: in_arg_list = 0; ! 20950: end_al($2,0); ! 20951: RESTORE_STATE(); ! 20952: //POP_SCOPE(); // similar to end_al() ! 20953: } ! 20954: | tname LP MUL ID RP arg_list ! 20955: { ! 20956: Pptr p = new ptr( PTR, 0 ); ! 20957: Ptyp(p) = new basetype(TYPE,$<pn>1); ! 20958: Freturns( $6 ) = Ptype(p); ! 20959: $<pn>4->tp = $<pt>6; ! 20960: $$ = $4; ! 20961: if (DECL_TYPE == -1) DECL_TYPE = 0; ! 20962: } ! 20963: | tname LP elist RP ! 20964: { $$ = Ncopy($<pn>1); ! 20965: $<pn>$->n_oper = TNAME; ! 20966: $<pn>$->tp = new fct(0,$<pn>3,1); ! 20967: } ! 20968: | tname LP RP fct_attributes ! 20969: { /* function with no argument */ ! 20970: $$ = Ncopy($<pn>1); ! 20971: $<pn>$->n_oper = TNAME; ! 20972: $<pn>$->tp = new fct(0,0,1); ! 20973: Pfct($<pn>1->tp)->f_const = ($<i>4 & 1); ! 20974: } ! 20975: | tname LP MEMPTR decl RP arg_list ! 20976: { memptrdcl($<pn>3,$<pn>1,$<pt>6,$<pn>4); ! 20977: $$ = $4; ! 20978: } ! 20979: | fname ! 20980: | ID DOT fname ! 20981: { $$ = Ncopy($<pn>3); ! 20982: $<pn>$->n_qualifier = $1; ! 20983: error(strict_opt?0:'w',"`.' used for qualification; please use `::' (anachronism)"); ! 20984: } ! 20985: | tn_list fname ! 20986: { $$ = $2; ! 20987: if ( $<pn>1 != sta_name ) { ! 20988: set_scope($<pn>1); ! 20989: $<pn>$->n_qualifier = $<pn>1; ! 20990: } ! 20991: } ! 20992: /*XXX*/ | tn_list ID DOT fname ! 20993: { $$ = Ncopy($<pn>4); ! 20994: $<pn>$->n_qualifier = $2; ! 20995: error(ansi_opt?0:'w',"anachronism `.' used for qualification; please use `::'"); ! 20996: if ( $<pn>1 != sta_name ) { ! 20997: set_scope($<pn>1); ! 20998: $<pn>2->n_qualifier = $<pn>1; ! 20999: } ! 21000: } ! 21001: /*XXX | tn_list TNAME ! 21002: * { ! 21003: * if ( $<pn>1 == sta_name ) ! 21004: * error( ":: applied to CN%n", $<pn>2 ); ! 21005: * $$ = Ncopy($<pn>2); ! 21006: * set_scope($<pn>1); ! 21007: * $<pn>$->n_oper = TNAME; ! 21008: * $<pn>$->n_qualifier = $<pn>1; ! 21009: * } ! 21010: */ | ptr decl %prec MUL ! 21011: { Ptyp($1) = $<pn>2->tp; ! 21012: $<pn>2->tp = $<pt>1; ! 21013: $$ = $2; ! 21014: } ! 21015: | ptr tname %prec MUL ! 21016: { $$ = Ncopy($<pn>2); ! 21017: $<pn>$->n_oper = TNAME; ! 21018: // cannot evaluate at this point: defer until data_dcl ! 21019: if ( in_typedef ) { ! 21020: defer_check = 1; ! 21021: in_tag = $<pn>2; ! 21022: } ! 21023: $<pn>2->hide(); ! 21024: defer_check = 0; ! 21025: $<pn>$->tp = $<pt>1; ! 21026: } ! 21027: | tname vec %prec LB ! 21028: { $$ = Ncopy($<pn>1); ! 21029: $<pn>$->n_oper = TNAME; ! 21030: if ( in_typedef ) { ! 21031: defer_check = 1; ! 21032: in_tag = $<pn>1; ! 21033: } ! 21034: $<pn>1->hide(); ! 21035: defer_check = 0; ! 21036: $<pn>$->tp = $<pt>2; ! 21037: } ! 21038: | decl vec %prec LB ! 21039: { Vtype($2) = $<pn>1->tp; ! 21040: $<pn>1->tp = $<pt>2; ! 21041: } ! 21042: /* ! 21043: | LP decl RP arg_list ! 21044: { ! 21045: Freturns($4) = $<pn>2->tp; ! 21046: $<pn>2->tp = $<pt>4; ! 21047: $$ = $2; ! 21048: } ! 21049: | LP decl RP vec ! 21050: { Vtype($4) = $<pn>2->tp; ! 21051: $<pn>2->tp = $<pt>4; ! 21052: $$ = $2; ! 21053: } ! 21054: */ ! 21055: | arg_lp decl RP ! 21056: { ! 21057: $$ = $2; ! 21058: in_arg_list = 0; ! 21059: end_al($1,0); ! 21060: RESTORE_STATE(); ! 21061: //POP_SCOPE(); // similar to end_al() ! 21062: } ! 21063: ; ! 21064: ! 21065: arg_decl : ID ! 21066: { $$ = $<pn>1; } ! 21067: | ptr qualified_tname %prec MUL ! 21068: { $$ = Ncopy($<pn>2); ! 21069: $<pn>$->n_oper = TNAME; ! 21070: $<pn>2->hide(); ! 21071: $<pn>$->tp = $<pt>1; ! 21072: } ! 21073: | %prec NO_ID ! 21074: { ! 21075: $$ = new name; ! 21076: NOT_EXPECT_ID(); ! 21077: } ! 21078: | ptr arg_decl %prec MUL ! 21079: { Ptyp($1) = $<pn>2->tp; ! 21080: $<pn>2->tp = (Ptype)$1; ! 21081: $$ = $2; ! 21082: } ! 21083: | arg_decl vec %prec LB ! 21084: { Vtype($2) = $<pn>1->tp; ! 21085: $<pn>1->tp = (Ptype)$2; ! 21086: } ! 21087: | arg_decl arg_list ! 21088: { Freturns($2) = $<pn>1->tp; ! 21089: $<pn>1->tp = (Ptype)$2; ! 21090: } ! 21091: /* ! 21092: | LP arg_decl RP arg_list ! 21093: { Freturns($4) = $<pn>2->tp; ! 21094: $<pn>2->tp = (Ptype)$4; ! 21095: $$ = $2; ! 21096: } ! 21097: | LP arg_decl RP vec ! 21098: { Vtype($4) = $<pn>2->tp; ! 21099: $<pn>2->tp = (Ptype)$4; ! 21100: $$ = $2; ! 21101: } ! 21102: */ ! 21103: | arg_lp arg_decl RP ! 21104: { ! 21105: // error('d', "arg_lp arg_decl rp in_arg_list: %d", in_arg_list ); ! 21106: $$ = $2; ! 21107: in_arg_list = 0; ! 21108: end_al($1,0); ! 21109: RESTORE_STATE(); ! 21110: //POP_SCOPE(); // similar to end_al() ! 21111: } ! 21112: ; ! 21113: ! 21114: new_decl : %prec NO_ID ! 21115: { $$ = new name; } ! 21116: | ptr new_decl %prec MUL ! 21117: { Ptyp($1) = $<pn>2->tp; ! 21118: $<pn>2->tp = (Ptype)$1; ! 21119: $$ = $2; ! 21120: NOT_EXPECT_ID(); ! 21121: } ! 21122: | new_decl vec %prec LB ! 21123: { Vtype($2) = $<pn>1->tp; ! 21124: $<pn>1->tp = (Ptype)$2; ! 21125: } ! 21126: ; ! 21127: ! 21128: cast_decl : %prec NO_ID { $$ = new name; } ! 21129: | ptr cast_decl %prec MUL ! 21130: { Ptyp($1) = $<pn>2->tp; ! 21131: $<pn>2->tp = (Ptype)$1; ! 21132: $$ = $2; ! 21133: NOT_EXPECT_ID(); ! 21134: } ! 21135: | cast_decl vec %prec LB ! 21136: { Vtype($2) = $<pn>1->tp; ! 21137: $<pn>1->tp = (Ptype)$2; ! 21138: } ! 21139: | LP cast_decl RP arg_list ! 21140: { Freturns($4) = $<pn>2->tp; ! 21141: $<pn>2->tp = $<pt>4; ! 21142: $$ = $2; ! 21143: } ! 21144: | LP cast_decl RP vec ! 21145: { Vtype($4) = $<pn>2->tp; ! 21146: $<pn>2->tp = $<pt>4; ! 21147: $$ = $2; ! 21148: } ! 21149: ; ! 21150: ! 21151: c_decl : %prec NO_ID ! 21152: { $$ = new name; } ! 21153: | ptr c_decl %prec MUL ! 21154: { Ptyp($1) = $<pn>2->tp; ! 21155: $<pn>2->tp = (Ptype)$1; ! 21156: $$ = $2; ! 21157: } ! 21158: ; ! 21159: ! 21160: ! 21161: ! 21162: /***************** statements: returns Pstmt *****************/ ! 21163: stmt_list : /* empty */ ! 21164: { ! 21165: $$ = 0; ! 21166: } ! 21167: | stmt_list TEMPLATE ! 21168: { ! 21169: error( "ZizedTD must be atG, not local scope" ); ! 21170: error('i', "cannot recover from previous error" ); ! 21171: } ! 21172: | stmt_list caselab_stmt ! 21173: { ! 21174: if ($2) ! 21175: if ($1) ! 21176: $<sl>1->add($<ps>2); ! 21177: else { ! 21178: $<sl>$ = new slist($<ps>2); ! 21179: stmt_seen = 1; ! 21180: } ! 21181: } ! 21182: ; ! 21183: caselab_stmt : caselablist statement ! 21184: { ! 21185: $$ = $2; ! 21186: if ($2) stmt_seen = 1; ! 21187: } ! 21188: ; ! 21189: ! 21190: caselablist : /* empty */ ! 21191: { ! 21192: $$ = 0; ! 21193: check_decl(); ! 21194: } ! 21195: ; ! 21196: ! 21197: condition : LP e RP ! 21198: { $$ = $2; ! 21199: /* if ($<pe>$ == dummy) error("empty condition");*/ ! 21200: stmt_seen = 1; ! 21201: } ! 21202: ; ! 21203: ! 21204: block : LC ! 21205: {//PUSH_BLOCK_SCOPE ! 21206: cd_vec[cdi] = cd; ! 21207: stmt_vec[cdi] = stmt_seen; ! 21208: tn_vec[cdi] = modified_tn; ! 21209: lcl_blk_vec[cdi++] = local_blk; ! 21210: lcl_tn_vec[cdi] = local_tn; ! 21211: local_blk = 0; ! 21212: local_tn = 0; ! 21213: cd = 0; ! 21214: stmt_seen = 0; ! 21215: modified_tn = 0; ! 21216: } ! 21217: stmt_list RC ! 21218: { Pname n = name_unlist(cd); ! 21219: Pstmt ss = stmt_unlist($<sl>3); ! 21220: $$ = new block($<l>1,n,ss,$<l>4); ! 21221: if ( local_tn ) local_restore(); ! 21222: if ( local_blk ) local_name(); ! 21223: if (modified_tn) restore(); ! 21224: cd = cd_vec[--cdi]; ! 21225: stmt_seen = stmt_vec[cdi]; ! 21226: modified_tn = tn_vec[cdi]; ! 21227: local_tn = lcl_tn_vec[cdi]; ! 21228: local_blk = lcl_blk_vec[cdi]; ! 21229: if (cdi < 0) error('i',"block level(%d)",cdi); ! 21230: NOT_EXPECT_ID(); ! 21231: //POP_SCOPE(); // similar to end_al() ! 21232: } ! 21233: | LC RC ! 21234: { $$ = new block($<l>1,0,0,$<l>2); NOT_EXPECT_ID();} ! 21235: | LC error RC ! 21236: { $$ = new block($<l>1,0,0,$<l>3); NOT_EXPECT_ID();} ! 21237: ; ! 21238: ! 21239: simple : ee ! 21240: { $$ = new estmt(SM,curloc,$<pe>1,0); } ! 21241: | BREAK ! 21242: { $$ = new stmt(BREAK,$<l>1,0); } ! 21243: | CONTINUE ! 21244: { $$ = new stmt(CONTINUE,$<l>1,0); } ! 21245: | GOTO ID ! 21246: { $$ = new lstmt(GOTO,$<l>1,$<pn>2,0); } ! 21247: | DO { stmt_seen=1; } caselab_stmt WHILE condition ! 21248: { $$ = new estmt(DO,$<l>1,$<pe>5,$<ps>3); } ! 21249: | ASM LP STRING RP ! 21250: { ! 21251: if (stmt_seen) ! 21252: $$ = new estmt(ASM,curloc,(Pexpr)$<s>3,0); ! 21253: else { ! 21254: Pname n = new name(make_name('A')); ! 21255: n->tp = new basetype(ASM,(Pname)$<s>3); ! 21256: if (cd) ! 21257: cd->add_list(n); ! 21258: else ! 21259: cd = new nlist(n); ! 21260: $$ = 0; ! 21261: } ! 21262: } ! 21263: ; ! 21264: ! 21265: sm : { ! 21266: if ( NEXTTOK() != SM ) { ! 21267: error("`;' missing afterS"); ! 21268: la_backup(yychar,yylval); ! 21269: yychar = SM; ! 21270: } ! 21271: } SM ! 21272: ; ! 21273: ! 21274: statement : simple sm ! 21275: | SM ! 21276: { $$ = new estmt(SM,$<l>1,dummy,0); } ! 21277: | RETURN e SM ! 21278: { $$ = new estmt(RETURN,$<l>1,$<pe>2,0); } ! 21279: | TYPE STRING block ! 21280: { ! 21281: error("local linkage specification"); ! 21282: $$ = $<pn>3; ! 21283: } ! 21284: | data_dcl ! 21285: { Pname n = $<pn>1; ! 21286: if (n) { ! 21287: //error('d',"adding local dcl of%n%t ll %d in_typedef%t",n,n->tp,n->lex_level,in_typedef); ! 21288: if (stmt_seen) { ! 21289: $$ = new block(n->where,n,0); ! 21290: $<ps>$->base = DCL; ! 21291: } ! 21292: else { ! 21293: if (cd) ! 21294: cd->add_list(n); ! 21295: else ! 21296: cd = new nlist(n); ! 21297: $$ = 0; ! 21298: } ! 21299: } // if n ! 21300: } ! 21301: | att_fct_def ! 21302: { ! 21303: Pname n = $<pn>1; ! 21304: error(&n->where,"%n's definition is nested (did you forget a ``}''?)",n); ! 21305: if (cd) ! 21306: cd->add_list(n); ! 21307: else ! 21308: cd = new nlist(n); ! 21309: $$ = 0; ! 21310: } ! 21311: | block ! 21312: | IF condition caselab_stmt ! 21313: { $$ = new ifstmt($<l>1,$<pe>2,$<ps>3,0); } ! 21314: | IF condition caselab_stmt ELSE caselab_stmt ! 21315: { $$ = new ifstmt($<l>1,$<pe>2,$<ps>3,$<ps>5); } ! 21316: | WHILE condition caselab_stmt ! 21317: { $$ = new estmt(WHILE,$<l>1,$<pe>2,$<ps>3); } ! 21318: | FOR LP { stmt_seen=1; } caselab_stmt e SM e RP caselab_stmt ! 21319: { $$ = new forstmt($<l>1,$<ps>4,$<pe>5,$<pe>7,$<ps>9); } ! 21320: | SWITCH condition caselab_stmt ! 21321: { $$ = new estmt(SWITCH,$<l>1,$<pe>2,$<ps>3); } ! 21322: | ID COLON { $$ = $1; stmt_seen=1; } caselab_stmt ! 21323: { Pname n = $<pn>3; ! 21324: $$ = new lstmt(LABEL,n->where,n,$<ps>4); ! 21325: } ! 21326: | TNAME COLON { $$ = new name($<pn>1->string); stmt_seen=1; } caselab_stmt ! 21327: { Pname n = $<pn>3; ! 21328: $$ = new lstmt(LABEL,n->where,n,$<ps>4); ! 21329: } ! 21330: | CASE { stmt_seen=1; } e COLON caselab_stmt ! 21331: { if ($<pe>3 == dummy) error("empty case label"); ! 21332: $$ = new estmt(CASE,$<l>1,$<pe>3,$<ps>5); ! 21333: } ! 21334: | DEFAULT COLON { stmt_seen=1; } caselab_stmt ! 21335: { $$ = new stmt(DEFAULT,$<l>1,$<ps>4); } ! 21336: ; ! 21337: ! 21338: ! 21339: ! 21340: /********************* expressions: returns Pexpr **************/ ! 21341: elist : ex_list ! 21342: { Pexpr e = expr_unlist($<el>1); ! 21343: while (e && e->e1==dummy) { ! 21344: register Pexpr ee2 = e->e2; ! 21345: if (ee2) error("EX inEL"); ! 21346: delete e; ! 21347: e = ee2; ! 21348: } ! 21349: $$ = e; ! 21350: } ! 21351: ; ! 21352: ! 21353: ex_list : initializer %prec CM ! 21354: { $<el>$ = new elist(new expr(ELIST,$<pe>1,0)); } ! 21355: | ex_list CM initializer ! 21356: { $<el>1->add(new expr(ELIST,$<pe>3,0)); } ! 21357: ; ! 21358: ! 21359: initializer : e %prec CM ! 21360: | LC elist RC ! 21361: { ! 21362: if ( in_arg_list ) ! 21363: error( "syntax error: IrL not permitted in AL" ); ! 21364: else if ( in_binit_list ) ! 21365: error( "syntax error: IrL not permitted inMIr" ); ! 21366: else ! 21367: init_seen = 1; ! 21368: Pexpr e; ! 21369: if ($2) ! 21370: e = $<pe>2; ! 21371: else ! 21372: e = new expr(ELIST,dummy,0); ! 21373: $$ = new expr(ILIST,e,0); ! 21374: } ! 21375: ; ! 21376: ! 21377: ee : ee ASSIGN ee ! 21378: { bbinop: $$ = new expr($<t>2,$<pe>1,$<pe>3); } ! 21379: | ee PLUS ee { goto bbinop; } ! 21380: | ee MINUS ee { goto bbinop; } ! 21381: | ee MUL ee { goto bbinop; } ! 21382: | ee AND ee { goto bbinop; } ! 21383: | ee OR ee { goto bbinop; } ! 21384: | ee ER ee { goto bbinop; } ! 21385: | ee SHIFTOP ee { goto bbinop; } ! 21386: | ee EQUOP ee { goto bbinop; } ! 21387: | ee DIVOP ee { goto bbinop; } ! 21388: | ee RELOP ee { goto bbinop; } ! 21389: | ee GT ee { goto bbinop; } ! 21390: | ee LT ee { goto bbinop; } ! 21391: | ee ANDAND ee { goto bbinop; } ! 21392: | ee OROR ee { goto bbinop; } ! 21393: | ee ASOP ee { goto bbinop; } ! 21394: | ee CM ee { goto bbinop; } ! 21395: | ee QUEST ee COLON ee ! 21396: { $$ = new qexpr($<pe>1,$<pe>3,$<pe>5); } ! 21397: | DELETE term ! 21398: { $$ = new expr(DELETE,$<pe>2,0); } ! 21399: | DELETE LB e RB term ! 21400: { ! 21401: if($<pe>3 != dummy) { ! 21402: if ( warning_opt || strict_opt ) ! 21403: error(strict_opt?0:'w',"v in `delete[v]' is redundant; use `delete[] instead (anachronism)"); ! 21404: } ! 21405: $$ = new expr(DELETE,$<pe>5,$<pe>3); ! 21406: } ! 21407: | MEM DELETE term ! 21408: { $$ = new expr(GDELETE,$<pe>3,0); } ! 21409: | MEM DELETE LB e RB term ! 21410: { ! 21411: if($<pe>4 != dummy) { ! 21412: if ( warning_opt || strict_opt ) ! 21413: error(strict_opt?0:'w',"v in `::delete[v]' is redundant; use `::delete[] instead (anachronism)"); ! 21414: } ! 21415: $$ = new expr(DELETE,$<pe>6,$<pe>4); ! 21416: } ! 21417: | term ! 21418: ; ! 21419: ! 21420: e : e ASSIGN e ! 21421: { binop: $$ = new expr($<t>2,$<pe>1,$<pe>3); } ! 21422: | e PLUS e { goto binop; } ! 21423: | e MINUS e { goto binop; } ! 21424: | e MUL e { goto binop; } ! 21425: | e AND e { goto binop; } ! 21426: | e OR e { goto binop; } ! 21427: | e ER e { goto binop; } ! 21428: | e SHIFTOP e { goto binop; } ! 21429: | e EQUOP e { goto binop; } ! 21430: | e DIVOP e { goto binop; } ! 21431: | e RELOP e { goto binop; } ! 21432: | e LT e { goto binop; } ! 21433: | e GT e { goto binop; } ! 21434: | e ANDAND e { goto binop; } ! 21435: | e OROR e { goto binop; } ! 21436: | e ASOP e { goto binop; } ! 21437: | e CM e { goto binop; } ! 21438: | e QUEST e COLON e ! 21439: { $$ = new qexpr($<pe>1,$<pe>3,$<pe>5); } ! 21440: | DELETE term ! 21441: { $$ = new expr(DELETE,$<pe>2,0); } ! 21442: | DELETE LB e RB term ! 21443: { ! 21444: if($<pe>3 != dummy) { ! 21445: if ( warning_opt || strict_opt ) ! 21446: error(strict_opt?0:'w',"v in `delete[v]' is redundant; use `delete[] instead (anachronism)"); ! 21447: } ! 21448: $$ = new expr(DELETE,$<pe>5,$<pe>3); ! 21449: } ! 21450: | MEM DELETE term ! 21451: { $$ = new expr(GDELETE,$<pe>3,0); } ! 21452: | MEM DELETE LB e RB term ! 21453: { ! 21454: if($<pe>4 != dummy) { ! 21455: if ( warning_opt || strict_opt ) ! 21456: error(strict_opt?0:'w',"v in `::delete[v]' is redundant; use `::delete[] instead (anachronism)"); ! 21457: } ! 21458: $$ = new expr(DELETE,$<pe>6,$<pe>4); ! 21459: } ! 21460: | term { ! 21461: init_seen = 0; ! 21462: } ! 21463: | %prec NO_EXPR ! 21464: { $$ = dummy; } ! 21465: ; ! 21466: ! 21467: term : NEW cast_type { goto new1; } ! 21468: | NEW new_type ! 21469: { new1: ! 21470: Ptype t = $<pn>2->tp; ! 21471: $$ = new texpr(NEW,t,0); ! 21472: } ! 21473: | MEM NEW cast_type { goto new3; } ! 21474: | MEM NEW new_type ! 21475: { new3: ! 21476: Ptype t = $<pn>3->tp; ! 21477: $$ = new texpr(GNEW,t,0); ! 21478: } ! 21479: | term ICOP ! 21480: { $$ = new expr($<t>2,$<pe>1,0); } ! 21481: | cast_type term %prec ICOP ! 21482: { $$ = new texpr(CAST,$<pn>1->tp,$<pe>2); } ! 21483: | MUL term ! 21484: { $$ = new expr(DEREF,$<pe>2,0); } ! 21485: | AND term ! 21486: { $$ = new expr(ADDROF,0,$<pe>2); } ! 21487: | MINUS term ! 21488: { $$ = new expr(UMINUS,0,$<pe>2); } ! 21489: | PLUS term ! 21490: { $$ = new expr(UPLUS,0,$<pe>2); } ! 21491: | NOT term ! 21492: { $$ = new expr(NOT,0,$<pe>2); } ! 21493: | COMPL term ! 21494: { $$ = new expr(COMPL,0,$<pe>2); } ! 21495: | ICOP term ! 21496: { $$ = new expr($<t>1,0,$<pe>2); } ! 21497: | SIZEOF term ! 21498: { ! 21499: $$ = new texpr(SIZEOF,0,$<pe>2); ! 21500: in_sizeof = 0; ! 21501: } ! 21502: | SIZEOF cast_type %prec SIZEOF ! 21503: { ! 21504: $$ = new texpr(SIZEOF,$<pn>2->tp,0); ! 21505: in_sizeof = 0; ! 21506: } ! 21507: | term LB e RB ! 21508: { $$ = new expr(DEREF,$<pe>1,$<pe>3); } ! 21509: | term REF prim ! 21510: { $$ = new ref(REF,$<pe>1,$<pn>3); } ! 21511: | term REFMUL term ! 21512: { $$ = new expr($<t>2,$<pe>1,$<pe>3); } ! 21513: | term REF qualified_tname ! 21514: { $$ = new ref(REF,$<pe>1,Ncopy($<pn>3)); } ! 21515: | term DOT prim ! 21516: { $$ = new ref(DOT,$<pe>1,$<pn>3); } ! 21517: | term DOT qualified_tname ! 21518: { $$ = new ref(DOT,$<pe>1,Ncopy($<pn>3)); } ! 21519: | prim ! 21520: | term_elist ! 21521: { ! 21522: if ( init_seen ) ! 21523: error( "syntax error:IrL illegal within ()"); ! 21524: } ! 21525: ! 21526: | term_lp e RP ! 21527: { ! 21528: if ( $2 == dummy ) ! 21529: error("syntax error: nullE"); ! 21530: $$ = $2; ! 21531: } ! 21532: | ZERO ! 21533: { $$ = zero; } ! 21534: | ICON ! 21535: { $$ = new expr(ICON,0,0); ! 21536: $<pe>$->string = copy_if_need_be($<s>1); ! 21537: } ! 21538: | FCON ! 21539: { $$ = new expr(FCON,0,0); ! 21540: $<pe>$->string = copy_if_need_be($<s>1); ! 21541: } ! 21542: | STRING ! 21543: { $$ = new expr(STRING,0,0); ! 21544: $<pe>$->string = copy_if_need_be($<s>1); ! 21545: } ! 21546: | CCON ! 21547: { $$ = new expr(CCON,0,0); ! 21548: $<pe>$->string = copy_if_need_be($<s>1); ! 21549: } ! 21550: | THIS ! 21551: { $$ = new expr(THIS,0,0); } ! 21552: ; ! 21553: ! 21554: term_elist : TYPE LP elist RP ! 21555: { $$ = new texpr(VALUE,tok_to_type($<t>1),$<pe>3); } ! 21556: /* ! 21557: | qualified_tname LP elist RP ! 21558: */ ! 21559: | tname LP elist RP ! 21560: { $$ = new texpr(VALUE,$<pn>1->tp,$<pe>3); } ! 21561: | NEW term_lp elist RP cast_type { goto new2; } ! 21562: | NEW term_lp elist RP new_type /* allow separate allocation */ ! 21563: { new2: ! 21564: Ptype t = $<pn>5->tp; ! 21565: $$=new texpr(NEW,t,0); ! 21566: $<pe>$->e2 = $<pe>3; ! 21567: } ! 21568: | MEM NEW term_lp elist RP cast_type { goto new4; } ! 21569: | MEM NEW term_lp elist RP new_type /* allow separate allocation */ ! 21570: { new4: ! 21571: Ptype t = $<pn>6->tp; ! 21572: $$ = new texpr(GNEW,t,0); ! 21573: $<pe>$->e2 = $<pe>4; ! 21574: } ! 21575: | term LP elist RP ! 21576: { ! 21577: Pexpr ee = $<pe>3; ! 21578: Pexpr e = $<pe>1; ! 21579: if (e->base==NEW || e->base==GNEW) ! 21580: e->e1 = ee; ! 21581: else ! 21582: $$ = new call(e,ee); ! 21583: } ! 21584: ! 21585: ; ! 21586: ! 21587: ptname : PTNAME lt temp_inst_parms gt ! 21588: { ! 21589: $<pn>$ =parametrized_typename($<pn>1,(expr_unlist($<el>3))); ! 21590: } ! 21591: ; ! 21592: ! 21593: tscope : TSCOPE ! 21594: { ! 21595: $<pn>$ = $<pn>1; ! 21596: curr_scope = $<pn>1; ! 21597: } ! 21598: | MEM { $<pn>$ = sta_name; } ! 21599: | ptname TSCOPE { $<pn>$ = $<pn>1; } ! 21600: ; ! 21601: ! 21602: ! 21603: prim : ID ! 21604: { $$ = $<pn>1; } ! 21605: /*XXX*/ | tn_list ID ! 21606: { $$ = Ncopy($<pn>2); ! 21607: $<pn>$->n_qualifier = $<pn>1; ! 21608: } ! 21609: | OPERATOR oper ! 21610: { $$ = new name(oper_name($2)); ! 21611: $<pn>$->n_oper = $<t>2; ! 21612: } ! 21613: | tn_list OPERATOR oper ! 21614: { $$ = new name(oper_name($3)); ! 21615: $<pn>$->n_oper = $<t>3; ! 21616: $<pn>$->n_qualifier = $<pn>1; ! 21617: } ! 21618: | OPERATOR c_type ! 21619: { $$ = $2; ! 21620: sig_name($<pn>$); ! 21621: } ! 21622: | tn_list OPERATOR c_type ! 21623: { $$ = $3; ! 21624: sig_name($<pn>$); ! 21625: $<pn>$->n_qualifier = $<pn>1; ! 21626: } ! 21627: | tn_list COMPL tag /* allow explicit call of destructor */ ! 21628: { ! 21629: if (strcmp($<pn>1->string,$<pn>3->string)) error("syntax error: inconsistent destructor notation"); ! 21630: $$ = new name(oper_name(DTOR)); ! 21631: $<pn>$->n_oper = DTOR; ! 21632: $<pn>$->n_qualifier = $<pn>1; ! 21633: } ! 21634: ; ! 21635: ! 21636: ! 21637: ! 21638: /****************** abstract types (return type Pname) *************/ ! 21639: cast_type : term_lp type cast_decl RP ! 21640: { $$ = Ncast($2,$<pn>3); } ! 21641: ; ! 21642: ! 21643: term_lp : LP { check_cast(); } ! 21644: ; ! 21645: ! 21646: c_tp : TYPE ! 21647: { ! 21648: TOK t = $<t>1; ! 21649: ! 21650: switch (t) { ! 21651: case FRIEND: ! 21652: case OVERLOAD: ! 21653: case REGISTER: ! 21654: case STATIC: ! 21655: case EXTERN: ! 21656: case AUTO: ! 21657: case VIRTUAL: ! 21658: error("%k in operatorT",t); ! 21659: t = INT; ! 21660: ! 21661: } ! 21662: ! 21663: $$ = new basetype(t,0); ! 21664: ! 21665: } ! 21666: | tname { $$ = new basetype(TYPE,$<pn>1); } ! 21667: | c_tp TYPE ! 21668: { ! 21669: if ( DECL_TYPE != -1 ) { ! 21670: switch ($<pb>1->base) { Pbase bt; ! 21671: case COBJ: case EOBJ: ! 21672: bt = new basetype(0,0); ! 21673: *bt = *$<pb>1; ! 21674: DEL($<pb>1); ! 21675: $<pb>1 = bt; ! 21676: } ! 21677: $$ = $<pb>1->type_adj($<t>2); ! 21678: } ! 21679: DECL_TYPE = 0; ! 21680: } ! 21681: | c_tp tname ! 21682: { ! 21683: if ( DECL_TYPE != -1 ) ! 21684: $$ = $<pb>1->name_adj($<pn>2); ! 21685: DECL_TYPE = 0; ! 21686: } ! 21687: ; ! 21688: ! 21689: c_type : c_tp c_decl { $$ = Ncast($1,$<pn>2); } ! 21690: ; ! 21691: ! 21692: new_type : type new_decl { $$ = Ncast($1,$<pn>2); }; ! 21693: ! 21694: arg_type : type arg_decl ! 21695: { ! 21696: // ENTER_NAME($<pn>2); ! 21697: $$ = Ndata($1,$<pn>2); ! 21698: } ! 21699: | type arg_decl ASSIGN ! 21700: { ! 21701: // ENTER_NAME($<pn>2); ! 21702: } ! 21703: initializer ! 21704: { $$ = Ndata($1,$<pn>2); ! 21705: $<pn>$->n_initializer = $<pe>5; ! 21706: } ! 21707: ; ! 21708: ! 21709: arg_lp : LP ! 21710: {//PUSH_ARG_SCOPE ! 21711: SAVE_STATE(); ! 21712: check_decl(); ! 21713: in_arg_list=1; ! 21714: $$ = modified_tn; ! 21715: modified_tn = 0; ! 21716: } ! 21717: ; ! 21718: ! 21719: arg_list : arg_lp arg_type_list ellipsis_opt RP fct_attributes ! 21720: { ! 21721: $$ = new fct(0,name_unlist($<nl>2),$<t>3); ! 21722: if ( NEXTTOK() != COLON ) in_arg_list=0; ! 21723: //in_arg_list=0; ! 21724: Pfct($<pt>$)->f_const = ($<i>5 & 1); ! 21725: if ( parsing_class_members ! 21726: || (NEXTTOK()!=LC && yychar!=COLON)) { ! 21727: end_al($1,1); ! 21728: //POP_SCOPE(); // similar to end_al() ! 21729: } else ! 21730: end_al($1,0); ! 21731: RESTORE_STATE(); ! 21732: } ! 21733: ; ! 21734: ! 21735: arg_type_list : arg_type_list CM at ! 21736: { ! 21737: if ($3) ! 21738: if ($1) ! 21739: $<nl>1->add($<pn>3); ! 21740: else { ! 21741: error("AD syntax"); ! 21742: $<nl>$ = new nlist($<pn>3); ! 21743: } ! 21744: else ! 21745: error("AD syntax"); ! 21746: } ! 21747: | at %prec CM ! 21748: { ! 21749: if ($1) $<nl>$ = new nlist($<pn>1); ! 21750: } ! 21751: ; ! 21752: ! 21753: at : arg_type ! 21754: | %prec EMPTY { $$ = 0; } ! 21755: ; ! 21756: ! 21757: ellipsis_opt : /* empty */ ! 21758: { $$ = 1; } ! 21759: | ELLIPSIS ! 21760: { $$ = ELLIPSIS; } ! 21761: | CM ELLIPSIS ! 21762: { $$ = ELLIPSIS; } ! 21763: ; ! 21764: ! 21765: ptr : MUL %prec NO_ID ! 21766: { ! 21767: $$ = new ptr(PTR,0); ! 21768: EXPECT_ID(); ! 21769: } ! 21770: | AND %prec NO_ID ! 21771: { ! 21772: $$ = new ptr(RPTR,0); ! 21773: EXPECT_ID(); ! 21774: } ! 21775: | MUL TYPE %prec NO_ID ! 21776: { $$ = doptr(PTR,$<t>2); } ! 21777: | ptr TYPE %prec NO_ID ! 21778: { ! 21779: switch ( $<t>2 ) { ! 21780: case CONST: ! 21781: $<pp>1->rdo = 1; break; ! 21782: case VOLATILE: ! 21783: error('w',"\"volatile\" not implemented (ignored)"); ! 21784: break; ! 21785: default: ! 21786: error( "syntax error: *%k", $<t>2 ); ! 21787: } ! 21788: $$ = $<pp>1; ! 21789: } ! 21790: | AND TYPE %prec NO_ID ! 21791: { $$ = doptr(RPTR,$<t>2); } ! 21792: | ptname MEMPTR %prec NO_ID ! 21793: { goto memptr1; } ! 21794: | MEMPTR %prec NO_ID ! 21795: { ! 21796: memptr1: ! 21797: $$ = new ptr(PTR,0); ! 21798: $<pp>$->memof = Pclass(Pbase($<pn>1->tp)->b_name->tp); ! 21799: EXPECT_ID(); ! 21800: } ! 21801: | ptname MEMPTR TYPE %prec NO_ID ! 21802: { ! 21803: $<t>2 = $<t>3; ! 21804: goto memptr2; ! 21805: } ! 21806: | MEMPTR TYPE %prec NO_ID ! 21807: { ! 21808: memptr2: ! 21809: $$ = doptr(PTR,$<t>2); ! 21810: $<pp>$->memof = Pclass(Pbase($<pn>1->tp)->b_name->tp); ! 21811: } ! 21812: ; ! 21813: ! 21814: vec : LB e RB { $$ = new vec(0,$<pe>2!=dummy?$<pe>2:0 ); } ! 21815: | NOT %prec LB { $$ = new vec(0,0); } ! 21816: ; ! 21817: ! 21818: %% ! 21819: ! 21820: static void ! 21821: check_tag() ! 21822: /* ! 21823: Allow the case of inline/virtual/overload as ! 21824: modifiers of return type of form struct/class/union x foo() ! 21825: SM, COLON, LC ==> real class declaration, not return type ! 21826: */ ! 21827: { ! 21828: switch ( NEXTTOK() ) { ! 21829: case SM: case COLON: case LC: ! 21830: declTag = 1; ! 21831: break; ! 21832: default: ! 21833: declTag = 0; ! 21834: break; ! 21835: } ! 21836: } ! 21837: ! 21838: static void ! 21839: end_al( Plist mtn, int rst ) ! 21840: // unhide type names hidden by arg names ! 21841: // mtn == saved modified_tn ! 21842: { ! 21843: if ( rst == 0 ) { ! 21844: // not really an arg list, or we are entering a function def ! 21845: // merge modified_tn and don't restore ! 21846: if ( modified_tn == 0 ) modified_tn = mtn; ! 21847: else { ! 21848: for ( Plist l = modified_tn; l->l; l = l->l ) ; ! 21849: l->l = mtn; ! 21850: } ! 21851: } else { ! 21852: restore(); ! 21853: modified_tn = mtn; ! 21854: } ! 21855: } ! 21856: static void ! 21857: arg_redec( Pname fn ) ! 21858: { ! 21859: if ( fn==0 || fn->tp->base != FCT ) ! 21860: error('i',"bad inline rewrite!"); ! 21861: Pname al = Pfct(fn->tp)->argtype; ! 21862: Pname n = 0; ! 21863: for ( ; al; al = al->n_list ) { ! 21864: DB( if(Ydebug>=1)error('d',"arg_redec: %n %d",al,al->lex_level); ); ! 21865: // nested function args should have lex_level >= 1 ! 21866: if ( al->lex_level==1 && (n=ktbl->look(al->string,0)) ) ! 21867: n->hide(); ! 21868: else if ( al->lex_level>1 && (n=ktbl->look(al->string,LOCAL)) ) ! 21869: n->hide(); ! 21870: DB( if(Ydebug>=1)error('d'," %n",n); ); ! 21871: } ! 21872: } ! 21873: ! 21874: ! 21875: 0707071010112046011004440001630000160000010211100466055415400000700000014643hash.c /* ident "@(#)ctrans:src/hash.c 1.2" */ ! 21876: /* ! 21877: $Header: /usr2/odi/libmisc/RCS/hash.C,v 1.11 90/03/22 09:24:07 sam Exp $ ! 21878: ! 21879: Copyright (c) 1989 by Object Design, Inc., Burlington, Mass. ! 21880: All rights reserved. ! 21881: ! 21882: */ ! 21883: ! 21884: #include <stdio.h> ! 21885: #include "hash.h" ! 21886: #include <osfcn.h> ! 21887: ! 21888: #define EMPTY 0 ! 21889: #define VALID 1 ! 21890: #define DELETED 2 ! 21891: ! 21892: void default_Hash_error_handler(const char* msg) ! 21893: { ! 21894: fprintf(stderr, "Fatal Hash error: %s\n", msg) ; ! 21895: exit(1) ; ! 21896: } ! 21897: ! 21898: Error_Proc Hash_error_handler = default_Hash_error_handler ; ! 21899: ! 21900: Error_Proc set_Hash_error_handler(Error_Proc f) ! 21901: { ! 21902: Error_Proc old = Hash_error_handler ; ! 21903: Hash_error_handler = f ; ! 21904: return old ; ! 21905: } ! 21906: ! 21907: void Hash::error(const char* msg) ! 21908: { ! 21909: (*Hash_error_handler)(msg) ; ! 21910: } ! 21911: ! 21912: Hash::Hash(int sz= DEFAULT_INITIAL_HASH_SIZE) ! 21913: { ! 21914: tab = new HashTableEntry[size = sz] ; ! 21915: for (int i = 0; i < size; ++i) tab[i].status = EMPTY ; ! 21916: entry_count = 0 ; ! 21917: } ! 21918: ! 21919: Hash::Hash(Hash& a) ! 21920: { ! 21921: tab = new HashTableEntry[size = a.size] ; ! 21922: ! 21923: key_hash_function = a.key_hash_function ; ! 21924: key_key_equality_function = a.key_key_equality_function ; ! 21925: ! 21926: for (int i = 0; i < size; ++i) tab[i].status = EMPTY ; ! 21927: entry_count = 0 ; ! 21928: for (HashWalker p(a); p; p.advance()) ! 21929: (*this)[p.key()] = p.get() ; ! 21930: } ! 21931: ! 21932: Hash& Hash::operator = (Hash& a) ! 21933: { ! 21934: if (a.tab != tab) ! 21935: { ! 21936: clear() ; ! 21937: delete [size] tab ; ! 21938: tab = new HashTableEntry[size = a.size] ; ! 21939: for (int i = 0; i < size; ++i) tab[i].status = EMPTY ; ! 21940: entry_count = 0 ; ! 21941: for (HashWalker p(a); p; p.advance()) ! 21942: (*this)[p.key()] = p.get() ; ! 21943: } ! 21944: return *this ; ! 21945: } ! 21946: ! 21947: /* ! 21948: * hashing method: double hash based on high bits of hash fct, ! 21949: * followed by linear probe. Can't do too much better if Assoc ! 21950: * sizes not constrained to be prime. ! 21951: */ ! 21952: ! 21953: ! 21954: static inline doublehashinc(unsigned int h, int s) ! 21955: { ! 21956: return ((h / s) % s) >> 1 ; ! 21957: } ! 21958: ! 21959: // IWBNI we knew whether we were being called as an lvalue or rvalue. ! 21960: // If the former, then we wouldn't have to scan through the whole ! 21961: // table just to tell if we should rehash or not. Sigh. ! 21962: int& Hash::operator [](int key) ! 21963: { ! 21964: unsigned int hashval = key_hash(key) ; ! 21965: while (1) ! 21966: { ! 21967: int bestspot = -1 ; ! 21968: int h = hashval % size ; ! 21969: for (int i = 0; i <= size; ++i) ! 21970: { ! 21971: if (tab[h].status == EMPTY) ! 21972: { ! 21973: // resize if the hash table is more than 87.5% full ! 21974: if (entry_count > ((size>>1)+(size>>2)+(size>>3))) ! 21975: // resize and insert again ! 21976: break ; ! 21977: if (bestspot < 0) bestspot = h ; ! 21978: tab[bestspot].key = key ; ! 21979: tab[bestspot].status = VALID ; ! 21980: ++entry_count ; ! 21981: return tab[bestspot].cont ; ! 21982: } ! 21983: else if (tab[h].status == DELETED) ! 21984: { ! 21985: if (bestspot < 0) bestspot = h ; ! 21986: } ! 21987: else if (key_key_eq(tab[h].key, key)) ! 21988: return tab[h].cont ; ! 21989: if (i == 0) ! 21990: h = (h + doublehashinc(hashval, size)) % size ; ! 21991: else if (++h >= size) ! 21992: h -= size ; ! 21993: } ! 21994: resize(size << 1) ; ! 21995: } ! 21996: } ! 21997: ! 21998: /* This seems convoluted, but it does whatever you want without ! 21999: redundant probing of the hash table. */ ! 22000: ! 22001: void Hash::action (int key, int val, insert_action what, ! 22002: int& found, int& old_val) ! 22003: { ! 22004: unsigned int hashval = key_hash(key) ; ! 22005: while (1) ! 22006: { ! 22007: int bestspot = -1 ; ! 22008: int h = hashval % size ; ! 22009: for (int i = 0; i <= size; ++i) ! 22010: { ! 22011: if (tab[h].status == EMPTY) ! 22012: { ! 22013: // resize if the hash table is more than 87.5% full ! 22014: if (entry_count > ((size>>1)+(size>>2)+(size>>3))) ! 22015: // resize and insert again ! 22016: break ; ! 22017: if (bestspot < 0) bestspot = h ; ! 22018: found = 0; ! 22019: if(what != probe) { ! 22020: tab[bestspot].key = key ; ! 22021: tab[bestspot].status = VALID ; ! 22022: ++entry_count ; ! 22023: tab[bestspot].cont = val; ! 22024: } ! 22025: return; ! 22026: } ! 22027: else if (tab[h].status == DELETED) ! 22028: { ! 22029: if (bestspot < 0) bestspot = h ; ! 22030: } ! 22031: else if (key_key_eq(tab[h].key, key)) { ! 22032: found = 1; ! 22033: old_val = tab[h].cont; ! 22034: if(what == replace) ! 22035: tab[h].cont = val; ! 22036: return; ! 22037: } ! 22038: if (i == 0) ! 22039: h = (h + doublehashinc(hashval, size)) % size ; ! 22040: else if (++h >= size) ! 22041: h -= size ; ! 22042: } ! 22043: resize(size << 1) ; ! 22044: } ! 22045: } ! 22046: ! 22047: int Hash::contains(int key) ! 22048: { ! 22049: unsigned int hashval = key_hash(key) ; ! 22050: int h = hashval % size ; ! 22051: for (int i = 0; i <= size; ++i) ! 22052: { ! 22053: if (tab[h].status == EMPTY) ! 22054: return 0 ; ! 22055: else if (tab[h].status == VALID && key_key_eq(tab[h].key, key)) ! 22056: return 1 ; ! 22057: if (i == 0) ! 22058: h = (h + doublehashinc(hashval, size)) % size ; ! 22059: else if (++h >= size) ! 22060: h -= size ; ! 22061: } ! 22062: return 0 ; ! 22063: } ! 22064: ! 22065: int Hash::del(int key) ! 22066: { ! 22067: unsigned int hashval = key_hash(key) ; ! 22068: int h = hashval % size ; ! 22069: for (int i = 0; i <= size; ++i) ! 22070: { ! 22071: if (tab[h].status == EMPTY) ! 22072: return 0 ; ! 22073: else if (tab[h].status == VALID && key_key_eq(tab[h].key, key)) ! 22074: { ! 22075: tab[h].status = DELETED ; ! 22076: --entry_count ; ! 22077: return 1 ; ! 22078: } ! 22079: if (i == 0) ! 22080: h = (h + doublehashinc(hashval, size)) % size ; ! 22081: else if (++h >= size) ! 22082: h -= size ; ! 22083: } ! 22084: return 0 ; ! 22085: } ! 22086: ! 22087: void Hash::apply(intProc f) ! 22088: { ! 22089: for (int i = 0; i < size; ++i) ! 22090: if (tab[i].status == VALID) ! 22091: (*f)(tab[i].cont) ; ! 22092: } ! 22093: ! 22094: void Hash::clear() ! 22095: { ! 22096: for (int i = 0; i < size; ++i) ! 22097: tab[i].status = EMPTY ; ! 22098: entry_count = 0 ; ! 22099: } ! 22100: ! 22101: void Hash::resize(int newsize) ! 22102: { ! 22103: if (newsize < entry_count) ! 22104: error("requested resize too small") ; ! 22105: HashTableEntry* oldtab = tab ; ! 22106: int oldsize = size ; ! 22107: tab = new HashTableEntry[size = newsize] ; ! 22108: for (int i = 0; i < size; ++i) ! 22109: tab[i].status = EMPTY ; ! 22110: entry_count = 0 ; ! 22111: for (i = 0; i < oldsize; ++i) ! 22112: if (oldtab[i].status == VALID) ! 22113: (*this)[oldtab[i].key] = oldtab[i].cont ; ! 22114: delete [oldsize] oldtab ; ! 22115: } ! 22116: ! 22117: void HashWalker::reset() ! 22118: { ! 22119: for (pos = 0; pos < h->size; ++pos) ! 22120: if (h->tab[pos].status == VALID) ! 22121: return ; ! 22122: pos = -1 ; ! 22123: } ! 22124: ! 22125: void HashWalker::advance() ! 22126: { ! 22127: if (pos < 0) ! 22128: return ; ! 22129: for (pos++; pos < h->size; ++pos) ! 22130: if (h->tab[pos].status == VALID) ! 22131: return ; ! 22132: pos = -1 ; ! 22133: } ! 22134: ! 22135: /* ! 22136: unsigned int foo(int bar) {return bar;} ! 22137: int baz(int a, int b) {return a == b;} ! 22138: ! 22139: main() ! 22140: { ! 22141: Hash vh(10) ; ! 22142: HashWalker vt(vh) ; ! 22143: int i ; ! 22144: ! 22145: vh.key_hash_function = &foo ; ! 22146: vh.key_key_equality_function = baz ; ! 22147: printf("Capacity=%d \n", vh.capacity()) ; ! 22148: for (i=0; i<500; i+= 5) ! 22149: { ! 22150: vh[i] = i * i ; ! 22151: } ! 22152: vt.reset() ; ! 22153: while (vt.valid()) ! 22154: { ! 22155: printf("key=%d, data=%d\t", vt.key(), vt.get()); ! 22156: vt.advance() ; ! 22157: } ! 22158: for (i=0; i<500; i+= 10) ! 22159: { ! 22160: vh.del (i) ; ! 22161: printf("After delete: %d\n", vh[i]); ! 22162: } ! 22163: printf("\n-----------------\n") ; ! 22164: vt.reset() ; ! 22165: while (vt.valid()) ! 22166: { ! 22167: printf("key=%d, data=%d\t", vt.key(), vt.get()); ! 22168: vt.advance() ; ! 22169: } ! 22170: } ! 22171: ! 22172: */ ! 22173: 0707071010112046061004440001630000160000010212400466055420200000700000011465hash.h /* ident "@(#)ctrans:src/hash.h 1.2" */ ! 22174: /* Compiler interface to hash tables from odi library. ! 22175: $Source: /usr3/lang/benson/work/stripped_cfront/RCS/hash.h,v $ $RCSfile: hash.h,v $ ! 22176: $Revision: 1.1 $ $Date: 89/11/20 08:50:36 $ ! 22177: $Author: benson $ $Locker: $ ! 22178: $State: Exp $ ! 22179: ! 22180: $Header: /usr2/odi/objectstore.src/libos/RCS/hash.H,v 1.4 89/09/26 09:37:31 benson Exp $ ! 22181: ! 22182: Copyright (c) 1989 by Object Design, Inc., Burlington, Mass. ! 22183: All rights reserved. ! 22184: ! 22185: */ ! 22186: ! 22187: #ifndef _HASH_H ! 22188: #define _HASH_H ! 22189: ! 22190: #include <string.h> ! 22191: ! 22192: typedef void (*Error_Proc) (const char*) ; ! 22193: ! 22194: extern void default_Hash_error_handler (const char*) ; ! 22195: extern Error_Proc Hash_error_handler ; ! 22196: extern Error_Proc set_Hash_error_handler (Error_Proc f) ; ! 22197: ! 22198: #ifndef _hash_typedefs ! 22199: #define _hash_typedefs 1 ! 22200: typedef void (*intProc)(int) ; ! 22201: #endif ! 22202: ! 22203: #define DEFAULT_INITIAL_HASH_SIZE 100 ! 22204: ! 22205: struct HashTableEntry ! 22206: { ! 22207: int key ; ! 22208: int cont ; ! 22209: char status ; ! 22210: } ; ! 22211: ! 22212: class HashWalker ; ! 22213: ! 22214: class Hash ! 22215: { ! 22216: friend class HashWalker ; ! 22217: ! 22218: HashTableEntry* tab ; ! 22219: int size ; ! 22220: int entry_count ; ! 22221: ! 22222: public: ! 22223: unsigned int (*key_hash_function)(int) ; ! 22224: int (*key_key_equality_function) (int, int) ; ! 22225: ! 22226: unsigned int key_hash(int a) ; ! 22227: int key_key_eq(int a, int b); ! 22228: ! 22229: Hash(int sz) ; ! 22230: Hash(Hash& a) ; ! 22231: ~Hash() ; ! 22232: ! 22233: Hash& operator= (Hash& a) ; ! 22234: ! 22235: int count() ; ! 22236: int empty() ; ! 22237: int full() ; ! 22238: int capacity() ; ! 22239: ! 22240: void clear() ; ! 22241: void resize(int newsize) ; ! 22242: ! 22243: enum insert_action { probe, insert, replace }; ! 22244: void action (int key, int val, insert_action what, ! 22245: int& found, int& old_val); ! 22246: int& operator [] (int k) ; ! 22247: int contains(int key) ; ! 22248: int del(int key) ; ! 22249: ! 22250: void apply (intProc f) ; ! 22251: void error(const char* msg) ; ! 22252: } ; ! 22253: ! 22254: class HashWalker ! 22255: { ! 22256: Hash* h ; ! 22257: int pos ; ! 22258: ! 22259: public: ! 22260: HashWalker(Hash& l) ; ! 22261: ~HashWalker() ; ! 22262: ! 22263: int null() ; ! 22264: int valid() ; ! 22265: operator void* () ; ! 22266: int operator ! () ; ! 22267: void advance() ; ! 22268: void reset() ; ! 22269: void reset(Hash& l) ; ! 22270: const int& key() ; ! 22271: int& get() ; ! 22272: } ; ! 22273: ! 22274: inline unsigned int Hash::key_hash(int a) ! 22275: { ! 22276: #ifdef HASHFUNCTION ! 22277: return HASHFUNCTION(a) ; ! 22278: #else ! 22279: return (*key_hash_function)(a) ; ! 22280: #endif ! 22281: } ! 22282: ! 22283: inline int Hash::key_key_eq(int a, int b) ! 22284: { ! 22285: #ifdef EQUALITYFUNCTION ! 22286: return EQUALITYFUNCTION(a, b) ; ! 22287: #else ! 22288: return (*key_key_equality_function)(a, b) ; ! 22289: #endif ! 22290: } ! 22291: ! 22292: ! 22293: inline Hash::~Hash() ! 22294: { ! 22295: delete [size] tab ; ! 22296: } ! 22297: ! 22298: inline int Hash::count() ! 22299: { ! 22300: return entry_count ; ! 22301: } ! 22302: ! 22303: inline int Hash::empty() ! 22304: { ! 22305: return entry_count == 0 ; ! 22306: } ! 22307: ! 22308: inline int Hash::full() ! 22309: { ! 22310: return entry_count == size ; ! 22311: } ! 22312: ! 22313: inline int Hash::capacity() ! 22314: { ! 22315: return size ; ! 22316: } ! 22317: inline HashWalker::HashWalker(Hash& a) ! 22318: { ! 22319: h = &a ; ! 22320: reset() ; ! 22321: } ! 22322: ! 22323: inline void HashWalker::reset(Hash& a) ! 22324: { ! 22325: h = &a ; ! 22326: reset() ; ! 22327: } ! 22328: ! 22329: ! 22330: inline HashWalker::~HashWalker() {} ! 22331: ! 22332: inline int HashWalker::null() ! 22333: { ! 22334: return pos < 0 ; ! 22335: } ! 22336: ! 22337: inline int HashWalker::valid() ! 22338: { ! 22339: return pos >= 0 ; ! 22340: } ! 22341: ! 22342: inline HashWalker::operator void* () ! 22343: { ! 22344: return (pos < 0)? 0 : this ; ! 22345: } ! 22346: ! 22347: inline int HashWalker::operator ! () ! 22348: { ! 22349: return (pos < 0) ; ! 22350: } ! 22351: ! 22352: ! 22353: inline const int& HashWalker::key() ! 22354: { ! 22355: if (pos < 0) ! 22356: h->error("operation on null Walker") ; ! 22357: return h->tab[pos].key ; ! 22358: } ! 22359: ! 22360: inline int& HashWalker::get() ! 22361: { ! 22362: if (pos < 0) ! 22363: h->error("operation on null Walker") ; ! 22364: return h->tab[pos].cont ; ! 22365: } ! 22366: ! 22367: inline int pointer_hasheq (int a, int b) ! 22368: { ! 22369: return a == b; ! 22370: }; ! 22371: ! 22372: inline unsigned int pointer_hash_fcn (int x) ! 22373: { ! 22374: unsigned X = (unsigned) x; ! 22375: return ((X << 16) | (X >> 16)) ^ x; ! 22376: } ! 22377: ! 22378: class pointer_hash : public Hash { ! 22379: public: ! 22380: pointer_hash (int sz = 0) : Hash (sz) { ! 22381: key_hash_function = pointer_hash_fcn; ! 22382: key_key_equality_function = pointer_hasheq; ! 22383: } ! 22384: ! 22385: pointer_hash (pointer_hash& h) : Hash (h) {}; ! 22386: }; ! 22387: ! 22388: inline int string_hasheq (int a, int b) ! 22389: { ! 22390: return !strcmp((char *)a, (char *) b); ! 22391: }; ! 22392: ! 22393: static unsigned int string_hash_fcn (int x) ! 22394: { ! 22395: char * str = (char *)x; ! 22396: int l = strlen(str); ! 22397: ! 22398: if(x <= 4) return str[0]; ! 22399: else { ! 22400: unsigned int * f4 = (unsigned int *) str; ! 22401: if (l < 8) return ((*f4 << 16) | (*f4 >> 16)) ^ *f4; ! 22402: else { ! 22403: unsigned int * s4 = f4 ++; ! 22404: return ((*f4 << 16) | (*f4 >> 16)) ^ *s4; ! 22405: } ! 22406: } ! 22407: }; ! 22408: ! 22409: ! 22410: class string_hash : public Hash { ! 22411: public: ! 22412: ! 22413: string_hash (int sz = 0) : Hash (sz) { ! 22414: key_hash_function = string_hash_fcn; ! 22415: key_key_equality_function = string_hasheq; ! 22416: }; ! 22417: ! 22418: string_hash (string_hash& h) : Hash (h) {}; ! 22419: }; ! 22420: ! 22421: #endif ! 22422: 0707071010112046071004440001630000160000010210470466055420500001500000001056ios_printf.h /* ident "@(#)ctrans:src/ios_printf.h 1.2" */ ! 22423: /* Begin iostream_printf.H -- printf functions that work on ostreams. ! 22424: someday, perhaps, scanf functions for istreams. */ ! 22425: ! 22426: #include <stdarg.h> ! 22427: #include <iostream.h> ! 22428: ! 22429: int vostream_printf(const char *format, va_list argp, ostream& fp); ! 22430: int ostream_printf(ostream& stream, const char * format ...); ! 22431: ! 22432: // returns count of characters added. ! 22433: int printf_to_string (char * string, int length, const char * format ...); ! 22434: ! 22435: // returns string which came from malloc. ! 22436: char * printf_to_alloc_string (const char * format ...); ! 22437: 0707071010112044331004440001630000160000010202700466055403600001000000134002lalex.c /*ident "@(#)ctrans:src/lalex.c 1.15" */ ! 22438: /************************************************************************** ! 22439: ! 22440: C++ source for cfront, the C++ compiler front-end ! 22441: written in the computer science research center of Bell Labs ! 22442: ! 22443: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 22444: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 22445: ! 22446: lalex.c: ! 22447: ! 22448: lookahead ! 22449: ! 22450: *****************************************************************************/ ! 22451: #include <stdio.h> ! 22452: ! 22453: #ifdef c_plusplus ! 22454: overload is_empty; ! 22455: #endif ! 22456: ! 22457: #include "cfront.h" ! 22458: #include "yystype.h" ! 22459: #include "tqueue.h" ! 22460: #include "template.h" ! 22461: ! 22462: #ifdef DBG ! 22463: #define LDB(val,a) { if(Ldebug>=val) {a;} } ! 22464: #else ! 22465: #define LDB(val,a) /**/ ! 22466: #endif ! 22467: ! 22468: #ifdef DBG ! 22469: static char* ! 22470: image( int t ) ! 22471: { ! 22472: if(keys[t]) return keys[t]; ! 22473: else { static char b[20]; ! 22474: sprintf(b,"token(%d)",t); ! 22475: return b; ! 22476: } ! 22477: } ! 22478: static void ! 22479: printok( toknode* t ) ! 22480: { ! 22481: switch(t->tok) { ! 22482: default: ! 22483: fprintf(stderr,"\t%s",image(t->tok)); ! 22484: break; ! 22485: case ID: case ICON: case CCON: case FCON: case STRING: ! 22486: fprintf(stderr,"ID '%s'",t->retval.s); ! 22487: break; ! 22488: case TNAME: ! 22489: fprintf(stderr,"TNAME '%s'",t->retval.pn->string); ! 22490: break; ! 22491: case PTNAME: ! 22492: fprintf(stderr,"PTNAME '%s'",t->retval.pn->string); ! 22493: break; ! 22494: case TSCOPE: ! 22495: fprintf(stderr,"TSCOPE '%s'::",t->retval.pn->string); ! 22496: break; ! 22497: case MEMPTR: ! 22498: fprintf(stderr,"MEMPTR '%s'::*",t->retval.pn->string); ! 22499: break; ! 22500: } ! 22501: putc(' ',stderr); ! 22502: t->place.put(stderr); ! 22503: putc('\n',stderr); ! 22504: } ! 22505: static void ! 22506: showQ( char* where ) ! 22507: /* ! 22508: display token Q ! 22509: */ ! 22510: { ! 22511: fprintf(stderr,"TOKEN Q (%s):\n",where); ! 22512: for (register toknode* t = front; t; t = t->next) printok(t); ! 22513: putc('\n',stderr); ! 22514: } ! 22515: #endif ! 22516: ! 22517: int bl_level; ! 22518: ! 22519: static int laexpr( TOK ); ! 22520: static int latype( TOK ); ! 22521: static int la_decl(); ! 22522: static TOK lookahead(); ! 22523: ! 22524: /* make this a toknode! */ ! 22525: static int lasttk = 0; // one token history ! 22526: static YYSTYPE lastval; // yylval lasttk value ! 22527: ! 22528: int must_be_expr = 0; // handle redundant parentheses ! 22529: int must_be_id = 0; // !0, TNAME => ID, i.e., int X ! 22530: ! 22531: loc curloc; ! 22532: int curr_file; ! 22533: ! 22534: toknode* latok; // current lookahead token ! 22535: toknode* front = 0; ! 22536: toknode* rear = 0; ! 22537: ! 22538: const TQCHUNK = 16; ! 22539: ! 22540: void* ! 22541: toknode::operator new(size_t) ! 22542: { ! 22543: register toknode* p; ! 22544: ! 22545: if ((p=free_toks) == 0) { ! 22546: register toknode* q; ! 22547: free_toks = q = (toknode*)malloc( TQCHUNK * sizeof(toknode) ); ! 22548: p = free_toks; ! 22549: for (; q != &p[TQCHUNK-1]; q->next = q+1, ++q); ! 22550: q->next = 0; ! 22551: } ! 22552: free_toks = p->next; ! 22553: return p; ! 22554: } ! 22555: ! 22556: toknode::toknode(TOK t, YYSTYPE r, loc tloc) ! 22557: { ! 22558: tok = t; ! 22559: used = 0; ! 22560: retval = r; ! 22561: place = tloc; ! 22562: next = last = 0; ! 22563: } ! 22564: ! 22565: void ! 22566: toknode::operator delete(void* vp,size_t) ! 22567: { ! 22568: register toknode* p = (toknode*)vp; ! 22569: p->next = free_toks; ! 22570: free_toks = p; ! 22571: vp = 0; ! 22572: } ! 22573: ! 22574: #define USE_TOKEN(T,W) \ ! 22575: LDB(2,error('d',&(T)->place,"use_token('%k','%s')",(T)->tok,W);); \ ! 22576: if ( !(T)->used ) use_token(T); ! 22577: ! 22578: Ptype ! 22579: return_nstd_local_type( Pname n, TOK &sw ) ! 22580: { ! 22581: Ptype tt; ! 22582: switch ( n->tp->base ) { ! 22583: case EOBJ: ! 22584: case COBJ: ! 22585: tt = Pbase(n->tp)->b_name->tp; ! 22586: sw = n->tp->base; ! 22587: break; ! 22588: default: ! 22589: tt = n->tpdef; ! 22590: sw = NESTED; // in repr.c, prints ``typedef'' ! 22591: break; ! 22592: } ! 22593: return tt; ! 22594: } ! 22595: ! 22596: static Pname ! 22597: local_nested_kludge( Pname n, Pname tn ) ! 22598: /* ! 22599: * for backward compatibility with 2.0 ! 22600: * in transitional model of nested class types ! 22601: * ! 22602: * struct T { ... }; ! 22603: * foobar() { ! 22604: * class X { ! 22605: * typedef int T; ! 22606: * // ... ! 22607: * }; ! 22608: * T t; ! 22609: * } ! 22610: * ! 22611: * pure nested classes, choose global struct T{}; ! 22612: * no nested classes, choose typedef int T ! 22613: * transitional model: choose typedef, and generate warning ! 22614: * BUG: local typedefs and enums do not have lex_level set ! 22615: */ ! 22616: { ! 22617: // error( 'd', "local_nested_kludge: n: %n", n ); ! 22618: for ( Pname nn = n; nn; nn = nn->n_tbl_list ) ! 22619: { ! 22620: Pname local_class; ! 22621: TOK ntd; ! 22622: if ( nn->n_key != NESTED ) continue; ! 22623: Ptype tt = return_nstd_local_type(nn,ntd); ! 22624: Pclass cl = tt->in_class; ! 22625: while ( cl->in_class ) cl = cl->in_class; ! 22626: if (cl->lex_level && ! 22627: (local_class = ktbl->look(cl->string,LOCAL))) ! 22628: { ! 22629: // same typedef at nested and non-nested scope ! 22630: if (ntd == NESTED && tn && tn->tp == nn->tp ) ! 22631: ; ! 22632: else ! 22633: error('w',"%s occurs at outer and nested localC scope; using %k %t::%s", n->string,ntd,cl,n->string); ! 22634: ! 22635: /* ! 22636: if ( ntd == NESTED && nn->n_dcl_printed != 2 ) { ! 22637: nn->dcl_print(0); ! 22638: nn->n_dcl_printed = 2; ! 22639: } ! 22640: */ ! 22641: return nn; ! 22642: } ! 22643: } ! 22644: return 0; ! 22645: } ! 22646: ! 22647: enum { one_back, two_back }; ! 22648: ! 22649: static void ! 22650: use_token( toknode* T ) ! 22651: /* ! 22652: lookup TNAMEs here instead of in tlex() ! 22653: maintain block level ! 22654: */ ! 22655: { ! 22656: static TOK last_tokens[2]; // TSCOPE not reduced at this point ! 22657: static Pname last_tname; // tname :: id, where id is nested class ! 22658: static Pname tdef_name; // typedef tname tdef_name ! 22659: T->used = 1; ! 22660: ! 22661: DB(if(Ldebug>=1) { ! 22662: error('d',&T->place,"\n*** use_token(%k )",T->tok); ! 22663: printok(T); ! 22664: error('D',&T->place," lasttk%k last_tname%n last tokens%k%k",lasttk,last_tname,last_tokens[one_back],last_tokens[two_back]); ! 22665: }); ! 22666: ! 22667: switch ( T->tok ) { ! 22668: case ID: ! 22669: Pname n; ! 22670: // error('d', &T->place, "use_token: %s", T->retval.s ); ! 22671: if ( last_tokens[one_back] == MEM && ! 22672: last_tokens[two_back] == TNAME && ! 22673: (n=ktbl->look(T->retval.s,NESTED))) ! 22674: { // TYPEDEF :: ID, nested class ctor ! 22675: if (tdef_name && tdef_name->n_key==NESTED && ! 22676: strcmp(tdef_name->string,n->string)==0) ! 22677: { ! 22678: T->tok = TNAME; ! 22679: T->retval.pn = n; ! 22680: break; ! 22681: } ! 22682: else { // TNAME :: ID, where ID may be nested class ! 22683: for ( Pname nn = n; nn; nn = nn->n_tbl_list ) ! 22684: { ! 22685: TOK sw; ! 22686: if ( nn->n_key != NESTED ) continue; ! 22687: Ptype tt = return_nstd_local_type(nn,sw); ! 22688: Pclass cl = tt->in_class; ! 22689: if (strcmp(last_tname->string,cl->string)==0) ! 22690: { ! 22691: T->tok = TNAME; ! 22692: T->retval.pn = nn; ! 22693: break; ! 22694: } ! 22695: } ! 22696: } ! 22697: } ! 22698: else ! 22699: if ( bl_level && ! 22700: // TNAME:: and :: cannot refer to ``local'' TNAME ! 22701: last_tokens[one_back] != MEM && ! 22702: (n=ktbl->look(T->retval.s,LOCAL)) ) ! 22703: { ! 22704: DB( if(Ldebug>=1)error( 'd', &T->place, "use_token: local class instance: %n", n ) ); ! 22705: T->tok = TNAME; ! 22706: T->retval.pn = n; ! 22707: } ! 22708: else if ( n=ktbl->look(T->retval.s,0) ) { ! 22709: DB( if(Ldebug>=1)error( 'd', &T->place, "use_token:GC instance: %n", n ) ); ! 22710: // error( 'd', &T->place, "use_token:GC instance: %n %t", n, n->tp ); ! 22711: ! 22712: // X:: ?, then n cannot be a global TNAME ! 22713: // except in the case of a constructor ! 22714: if (last_tokens[one_back] == MEM && ! 22715: last_tokens[two_back] == TNAME && ! 22716: strcmp(T->retval.s,last_tname->string)) ! 22717: ; // do nothing; i.e., return ID ! 22718: else ! 22719: if ( bl_level && n->tp->base != COBJ && ! 22720: last_tokens[one_back] == MEM && ! 22721: last_tokens[two_back] != TNAME && ! 22722: gtbl->look(T->retval.s,0)) ! 22723: ; // do nothing: local typedefs & enums not implemented ! 22724: else { ! 22725: Pname nn = 0; ! 22726: TOK ntd; ! 22727: if (bl_level && (nn=ktbl->look(T->retval.s,NESTED))) ! 22728: { ! 22729: (void) return_nstd_local_type(n,ntd); ! 22730: nn = local_nested_kludge(nn,ntd==NESTED?n:0); ! 22731: } ! 22732: T->tok = TNAME; ! 22733: T->retval.pn = nn?nn:n; ! 22734: } ! 22735: } ! 22736: #ifdef DBG ! 22737: else if(Ldebug>=1) ! 22738: error('d',&T->place,"use_token: id %s",T->retval.s); ! 22739: #endif ! 22740: break; ! 22741: case LC: ++bl_level; break; ! 22742: case RC: --bl_level; break; ! 22743: } ! 22744: ! 22745: if (T->tok != COMPL || last_tokens[one_back] != MEM) { ! 22746: last_tokens[two_back] = last_tokens[one_back]; ! 22747: last_tokens[one_back] = T->tok; ! 22748: if (T->tok == TNAME) last_tname = T->retval.pn; ! 22749: if ( last_tname && ! 22750: last_tname->tp->base == TYPE ) ! 22751: { ! 22752: tdef_name = last_tname; ! 22753: do ! 22754: tdef_name = Pbase(tdef_name->tp)->b_name; ! 22755: while ( tdef_name->tp->base == TYPE ); ! 22756: } ! 22757: } ! 22758: } ! 22759: ! 22760: void ! 22761: addtok(TOK t, YYSTYPE r, loc tloc) ! 22762: { ! 22763: toknode* T = new toknode(t,r,tloc); ! 22764: if (front == 0) ! 22765: front = rear = T; ! 22766: else { ! 22767: rear->next = T; ! 22768: T->last = rear; ! 22769: rear = T; ! 22770: } ! 22771: //error('d',&tloc,"addtok: %k '%s'",t,t==ID?r.s:""); ! 22772: //showQ("addtok"); ! 22773: } ! 22774: ! 22775: extern TOK ! 22776: deltok( int noset = 0 ) ! 22777: { ! 22778: register toknode* T = front; ! 22779: USE_TOKEN(T,"deltok"); ! 22780: register TOK tk = T->tok; ! 22781: if ( !noset ) { yylval = T->retval; curloc = T->place; } ! 22782: curr_file = curloc.file; ! 22783: if (front = front->next) ! 22784: front->last = 0; ! 22785: else ! 22786: latok = rear = 0; ! 22787: delete T; ! 22788: return tk; ! 22789: } ! 22790: ! 22791: static void ! 22792: add_tokens() ! 22793: /* ! 22794: extend lookahead token queue when depleted ! 22795: */ ! 22796: { ! 22797: TOK tk = tlex(); ! 22798: if ( tk != ID ) ! 22799: return; ! 22800: ! 22801: while (tk == ID || tk == MEM || tk == DOT ) ! 22802: tk = tlex(); ! 22803: } ! 22804: ! 22805: extern TOK ! 22806: la_look() ! 22807: /* ! 22808: peek at head of token queue ! 22809: */ ! 22810: { ! 22811: LDB(1,fprintf(stderr,"\n*** la_look()")); ! 22812: if ( front == 0 ) ! 22813: add_tokens(); ! 22814: ! 22815: latok = front; ! 22816: USE_TOKEN(latok,"la_look"); ! 22817: LDB(1,fprintf(stderr," -- %s\n",image(latok->tok))); ! 22818: return latok->tok; ! 22819: } ! 22820: ! 22821: #define NEXTTOK() ( (yychar==-1) ? (yychar=lalex(),yychar) : yychar ) ! 22822: void ! 22823: check_decl() ! 22824: /* ! 22825: Lookahead to direct parsing of local/arg type declarations ! 22826: la_decl() returns 1 if lookahead sees a declaration. ! 22827: */ ! 22828: { ! 22829: TOK tk2; ! 22830: switch( NEXTTOK() ) { ! 22831: default: ! 22832: break; ! 22833: case TSCOPE: //XXX ! 22834: tk2 = la_look(); ! 22835: while ( tk2 == TSCOPE ) tk2 = lookahead(); ! 22836: if ( tk2 == TNAME ) { ! 22837: toknode* t = latok; ! 22838: if(t->tok!=TNAME) ! 22839: error('i',&t->place,"check_decl() token scan"); ! 22840: tk2 = lookahead(); ! 22841: if ( tk2 == LP && la_decl() ) { ! 22842: t->tok = DECL_MARKER; //TNAME ! 22843: } ! 22844: } ! 22845: break; ! 22846: case TYPE: case TNAME: ! 22847: if ( la_look() == LP && la_decl() ) { ! 22848: must_be_id = 0; ! 22849: DECL_TYPE=yychar; ! 22850: yychar = DECL_MARKER; ! 22851: } ! 22852: } ! 22853: } ! 22854: ! 22855: void ! 22856: check_cast() ! 22857: /* ! 22858: Lookahead to direct parsing of cast ! 22859: la_cast() returns 1 if lookahead sees an ambiguous old-style C cast. ! 22860: */ ! 22861: { ! 22862: TOK tk2; ! 22863: switch( NEXTTOK() ) { ! 22864: case TSCOPE: //XXX ! 22865: tk2 = la_look(); ! 22866: while ( tk2 == TSCOPE ) tk2 = lookahead(); ! 22867: if ( tk2 == TNAME ) { ! 22868: toknode* t = latok; ! 22869: if(t->tok!=TNAME) ! 22870: error('i',&t->place,"check_cast() token scan"); ! 22871: tk2 = lookahead(); ! 22872: if ( tk2 == LP && la_decl() ) { ! 22873: t->tok = DECL_MARKER;//TNAME ! 22874: } ! 22875: } ! 22876: break; ! 22877: case TYPE: case TNAME: ! 22878: if ( la_look() == LP && la_cast() ) { ! 22879: must_be_id = 0; ! 22880: DECL_TYPE = yychar; ! 22881: yychar = DECL_MARKER; ! 22882: } ! 22883: } ! 22884: } ! 22885: ! 22886: ! 22887: static int ! 22888: latype( TOK t ) ! 22889: { ! 22890: switch ( t ) { ! 22891: default: // includes friend, typedef, storage classes, etc. ! 22892: return 0; ! 22893: case CHAR: case SHORT: case INT: case LONG: ! 22894: case FLOAT: case DOUBLE: ! 22895: case UNSIGNED: ! 22896: return 1; ! 22897: } ! 22898: } ! 22899: ! 22900: static int ! 22901: laexpr( TOK t ) ! 22902: { ! 22903: switch ( t ) { ! 22904: default: ! 22905: return 0; ! 22906: case RETURN: case NEW: case AND: case ANDAND: case OR: case OROR: ! 22907: case SIZEOF: case NOT: case COMPL: case MUL: case PLUS: case MINUS: ! 22908: case ER: case ASSIGN: case ASOP: case RELOP: case EQUOP: case DIVOP: ! 22909: case SHIFTOP: case ICOP: ! 22910: return 1; ! 22911: } ! 22912: } ! 22913: ! 22914: static toknode *get_next_token(toknode *t) { ! 22915: if (! t->next) ! 22916: add_tokens() ; ! 22917: ! 22918: return t->next ; ! 22919: } ! 22920: ! 22921: ! 22922: static int template_tscope(Pname tn, toknode *lt) ! 22923: /* provide the looakhead for determining TSCOPE tokens when the name is a ! 22924: * parametrized type name; the lookahead here is non-trivial, because it ! 22925: * involves stepping over the template arguments. ! 22926: */ ! 22927: { ! 22928: int nest = 0 ; // the LT has been fetched ! 22929: ! 22930: if (lt->tok != LT) error ('i', "a `<' token was expected") ; ! 22931: ! 22932: // assume the worst, ensure that name strings are consed in the heap ! 22933: templp->parameters_in_progress++ ; ! 22934: ! 22935: for (toknode *t = lt;; t = get_next_token(t)) ! 22936: switch (t->tok) { ! 22937: ! 22938: case LT: ! 22939: ++nest; ! 22940: continue; ! 22941: case GT: ! 22942: // *************** ! 22943: // need to fold in awareness of x::y::z ! 22944: if (--nest == 0) { ! 22945: t = get_next_token(t); ! 22946: if (t->tok == MEM) { ! 22947: // determine whether it is a memptr ! 22948: if (t->next == 0) add_tokens(); ! 22949: if (t->next->tok == MUL) { ! 22950: t->tok = MEMPTR; ! 22951: t->next = t->next->next ; ! 22952: } else t->tok = TSCOPE ; ! 22953: t->retval.pn = tn ; ! 22954: --templp->parameters_in_progress; ! 22955: return 1; ! 22956: } ! 22957: else return 0 ; ! 22958: } ! 22959: continue; ! 22960: ! 22961: case SM: case LC: case RC: // a quick exit in case of error ! 22962: case EOFTOK: ! 22963: --templp->parameters_in_progress; ! 22964: return 0 ; ! 22965: ! 22966: default: ! 22967: continue; ! 22968: } ! 22969: } ! 22970: ! 22971: static TOK ! 22972: lookahead() ! 22973: /* ! 22974: advance lookahead pointer, lexing at end of Q ! 22975: handle occurrences of TNAME and TSCOPE ! 22976: (should be kept up to date with lalex()) ! 22977: */ ! 22978: { ! 22979: TOK tk; ! 22980: TOK tk2; ! 22981: TOK prev_tk = 0; ! 22982: YYSTYPE lastval; ! 22983: ! 22984: if ( latok == rear ) { ! 22985: add_tokens(); ! 22986: if ( latok ) ! 22987: latok = latok->next; ! 22988: else ! 22989: latok = front; ! 22990: } ! 22991: else ! 22992: latok = latok->next; ! 22993: ! 22994: if ( latok->last ) { ! 22995: prev_tk = latok->last->tok; ! 22996: lastval = latok->last->retval; ! 22997: } ! 22998: ! 22999: nexttok: ! 23000: USE_TOKEN(latok,"lookahead1"); ! 23001: tk = latok->tok; ! 23002: if ( tk == ID || tk == TNAME ) ! 23003: { ! 23004: if (latok->next == 0) add_tokens(); ! 23005: USE_TOKEN(latok->next,"lookahead2"); ! 23006: /* TOK */ tk2 = latok->next->tok; ! 23007: if ( tk == TNAME ) { ! 23008: if (tk2 == LT) { ! 23009: // a parametrized type name -- differentiate from TNAME ! 23010: // so that it can be dealt with in the grammar. ! 23011: if (template_tscope(latok->retval.pn, latok->next)) tk = PTNAME; ! 23012: } ! 23013: else ! 23014: if ( tk2 == MEM || tk2 == DOT ) { ! 23015: tscope: ! 23016: tk = TSCOPE; ! 23017: // error('d',"lookahead: tk: %k tk2: %k", tk, tk2 ); ! 23018: // XXX -- should be modified to loop and do lookup ! 23019: latok = latok->next; ! 23020: if (latok->next == 0) add_tokens(); ! 23021: USE_TOKEN(latok->next,"lookahead3"); ! 23022: tk2 = latok->next->tok; ! 23023: if ( tk2 == MUL ) { ! 23024: tk = MEMPTR; ! 23025: latok = latok->next; ! 23026: } ! 23027: } ! 23028: else if (( prev_tk == MUL && tk2 != RP ) ! 23029: || prev_tk == AND ) ! 23030: { ! 23031: tk = ID; ! 23032: latok->retval.pn->hide(); ! 23033: latok->tok = ID; ! 23034: latok->retval.s = latok->retval.pn->string; ! 23035: } ! 23036: } ! 23037: else if ( tk2 == MEM ) { ! 23038: // ID :: ! 23039: //XXX latok = latok->next->next; ! 23040: //XXX goto nexttok; ! 23041: goto tscope; // treat as tscope ! 23042: } ! 23043: ! 23044: if ( tk == ID && ! 23045: ( tk2 == ID || ! 23046: ( prev_tk == ID && ( tk2 == COLON || tk2 == LC )))) { ! 23047: // ID ID ! 23048: latok = latok->next; ! 23049: goto nexttok; ! 23050: } ! 23051: } ! 23052: ! 23053: if ( tk == ID ) { ! 23054: Pname nstd = ktbl->look(latok->retval.s,NESTED); ! 23055: if (nstd && (must_be_id == 0 || ! 23056: must_be_id && prev_tk == LP)) { ! 23057: extern Pname check_for_nested(Pname,TOK,YYSTYPE,TOK); // use this in lalex, too ! 23058: Pname n = check_for_nested(nstd,prev_tk,lastval,tk2); ! 23059: if ( n ) { ! 23060: tk = latok->tok = TNAME; ! 23061: latok->retval.pn = n; ! 23062: } ! 23063: } ! 23064: } ! 23065: ! 23066: return tk; ! 23067: } ! 23068: ! 23069: static Pname mem_sel = 0; ! 23070: ! 23071: static Pname ! 23072: do_local_class( Pname n, int lex_level ) ! 23073: { /* ! 23074: * modify to ``do_local_type: ! 23075: * do local types: enums and typedefs ! 23076: */ ! 23077: Pname nn = n; ! 23078: if ( n->tp ) { // already a TNAME ! 23079: Pclass cl = n->tp->base==COBJ ? Pclass(Pbase(n->tp)->b_name->tp) : 0; ! 23080: if ( n->lex_level != lex_level || (cl && cl->lcl) ) { ! 23081: local_hide( n ); ! 23082: nn = new name( n->string ); ! 23083: nn->lex_level = lex_level>=0?lex_level:0; ! 23084: } ! 23085: else ! 23086: if ( lex_level == n->lex_level && cl->defined ) { ! 23087: error( "localC %n redefined", n ); ! 23088: return n; ! 23089: } ! 23090: } ! 23091: ! 23092: nn = nn->tname( lastval.t ); ! 23093: modified_tn = modified_tn->l; ! 23094: nn->n_key = LOCAL; ! 23095: local_class = new name_list( nn, local_class ); ! 23096: local_blk = new name_list( nn, local_blk ); ! 23097: ! 23098: // error('d', "do_local_class: nn %n tp %t", nn, Pclass(Pbase(nn->tp)->b_name->tp)); ! 23099: return nn; ! 23100: } ! 23101: ! 23102: static char* ! 23103: make_nested_name( char *s, Pclass cl ) ! 23104: { // Q<cnt>_<class_names><space><null> ! 23105: const nested_depth = 9; ! 23106: char *str_arr[nested_depth]; ! 23107: int size_arr[nested_depth]; ! 23108: int cnt = 2; ! 23109: int size = 4; // Q,<cnt>,<_>,<null> ! 23110: ! 23111: str_arr[0] = s; str_arr[1] = cl->string; ! 23112: ! 23113: size += size_arr[0] = strlen(s); ! 23114: size += size_arr[1] = cl->strlen?cl->strlen:strlen(cl->string); ! 23115: ! 23116: for (Pclass nc = cl->in_class; nc; nc = nc->in_class ) { ! 23117: if (cnt > nested_depth-1) error('s',"nested depth class beyond %d unsupported",nested_depth); ! 23118: size += size_arr[cnt] = nc->strlen?nc->strlen:strlen(nc->string); ! 23119: str_arr[cnt++] = nc->string; ! 23120: } ! 23121: ! 23122: for ( int i=0; i<cnt; i++ ) // <nnn><string> ! 23123: size += size_arr[i]>99?3:size_arr[i]<10?1:2; ! 23124: ! 23125: //error('d', "make_nested_name( %s, %t ) cnt: %d size: %d", s, cl, cnt, size ); ! 23126: char *result = new char[size]; ! 23127: sprintf(result, "Q%d_", cnt ); ! 23128: size = 3; ! 23129: for ( i=cnt; i; i-- ) { ! 23130: sprintf(result+size,"%d%s", size_arr[i-1], str_arr[i-1]); ! 23131: size += size_arr[i-1] + (size_arr[i-1]>99?3:size_arr[i-1]<10?1:2); ! 23132: } ! 23133: ! 23134: //error('d', "size: %d ", size ); ! 23135: result[size] = '\0'; ! 23136: //error('d', "make_nested_name result: %s", result ); ! 23137: return result; ! 23138: } ! 23139: ! 23140: int is_empty( Pclass cl, bit const_chk ) ! 23141: { /* for nested class check, empty means *no* members ! 23142: * for const object check, means no *data* members ! 23143: */ ! 23144: ! 23145: // error('d',"%t->is_empty: max: %d real_size: %d", cl, cl->memtbl->max(),cl->real_size ); ! 23146: ! 23147: int mbr_cnt = cl->memtbl->max(); ! 23148: if ( mbr_cnt == 0 ) return 1; ! 23149: ! 23150: if ( cl->baselist == 0 && cl->real_size!=1 ) ! 23151: return 0; ! 23152: ! 23153: // empty class to turn on transitional nested class scope ! 23154: if ( const_chk == 0 && ! 23155: ( cl->baselist != 0 || mbr_cnt > 1 )) return 0; ! 23156: ! 23157: int i = 1; ! 23158: for (Pname nn=cl->memtbl->get_mem(i); nn; nn=cl->memtbl->get_mem(++i)) { ! 23159: if (nn->base==NAME && ! 23160: nn->n_union==0 && ! 23161: nn->tp->base!=FCT && ! 23162: nn->tp->base!=OVERLOAD && ! 23163: nn->tp->base!=CLASS && ! 23164: nn->tp->base!=ENUM && ! 23165: nn->tp->base!=EOBJ && ! 23166: nn->n_stclass != STATIC) ! 23167: { ! 23168: if ( nn->string[0]=='_' && ! 23169: nn->string[1]=='_' && ! 23170: nn->string[2]=='W' ) ! 23171: return 1; ! 23172: else return 0; ! 23173: } ! 23174: } ! 23175: ! 23176: return 1; // if here, no data members encountered ! 23177: } ! 23178: ! 23179: static int ! 23180: is_empty( Penum en ) ! 23181: { // is this an empty enum ?? ! 23182: ! 23183: // error('d', "%t no_of_enumerators: %d", en, en->no_of_enumerators); ! 23184: if ( en->no_of_enumerators != 0 ) ! 23185: return 0; ! 23186: ! 23187: return 1; ! 23188: } ! 23189: ! 23190: static Pname ! 23191: check_nested_type( Pname nm ) ! 23192: { ! 23193: // error('d', "check nested type: %n ccl: %t", nm, ccl ); ! 23194: ! 23195: Pname nx, n = ktbl->look(nm->string, NESTED); ! 23196: if ( n == 0 || n == nm ) return nm; ! 23197: ! 23198: int cnt = 1; ! 23199: for (nx = n; n; n=n->n_tbl_list ) ! 23200: if (n->n_key == NESTED) ++cnt; ! 23201: ! 23202: if ( cnt > 1 ) { ! 23203: error( "ambiguous nested type %s (%d instances), use x::y syntax", nm->string, cnt ); ! 23204: error( 'i', "cannot recover from previous errors" ); ! 23205: } ! 23206: else { ! 23207: TOK ntk; ! 23208: Ptype tt = return_nstd_local_type(nx,ntk); ! 23209: error('w', "use %t:: to access nested %k %s (anachronism)", tt->in_class, ntk, nx->string); ! 23210: } ! 23211: return nx; ! 23212: } ! 23213: ! 23214: static int ! 23215: in_local_class( Pclass cl ) ! 23216: { ! 23217: if ( cl->lex_level ) ! 23218: return 1; ! 23219: if ( cl->in_class ) ! 23220: return in_local_class( cl->in_class ); ! 23221: return 0; ! 23222: } ! 23223: ! 23224: Pname ! 23225: do_nested_type( Pname n ) ! 23226: { ! 23227: Pname nn = n; ! 23228: char *str = 0; ! 23229: ! 23230: // error('d', "do_nested_type: %s in_typedef: %d ccl: %t", n->string, in_typedef, ccl ); ! 23231: if ( in_typedef && ccl->string[0]=='_' ! 23232: && ccl->string[1]=='_' ! 23233: && ccl->string[2]=='C') return n; ! 23234: ! 23235: if ( n->tp ) ! 23236: { // already a TNAME : ! 23237: // hide existing instance, encode new instance ! 23238: /* ! 23239: * need handle the anomaly: ! 23240: * class x; ! 23241: * x *p; ! 23242: * class y { ! 23243: * class x{ ... }; // oops ! 23244: * }; ! 23245: */ ! 23246: if (n->tp->base==COBJ) { ! 23247: Pclass cl = Pclass(Pbase(n->tp)->b_name->tp); ! 23248: if (cl->defined == 0 && lasttk == AGGR) { ! 23249: error('w',"forwardD ofC%n resolved to nested%t::%s",n,ccl,n->string); ! 23250: cl->lcl = new char[9]; ! 23251: strcpy(cl->lcl,"FUDGE007"); // license to hack ! 23252: n->lex_level=Pbase(n->tp)->b_name->lex_level=0; ! 23253: return n; ! 23254: } ! 23255: } ! 23256: else if (n->tp->base==EOBJ) { // watch out for enum x; ! 23257: Penum en = Penum(Pbase(n->tp)->b_name->tp); ! 23258: if (en->defined == 0 && lasttk == ENUM) return n; ! 23259: } ! 23260: ! 23261: nested_hide( n ); ! 23262: nn = new name( n->string ); ! 23263: str = make_nested_name( n->string, ccl ); ! 23264: } ! 23265: else ! 23266: // make sure we haven't already seen a nested instance ! 23267: // if so, for transition, this needs to be an error ! 23268: if (ktbl->look( n->string, NESTED )) ! 23269: error("multiple type %s nestings (to do this define an empty class/enum %s {};)",n->string,n->string); ! 23270: if ( in_typedef ) { ! 23271: if (strcmp(ccl->string, nn->string)==0) { // class x { typedef T x; ! 23272: error( "nested Tdef %s redefines immediately enclosing class", nn->string ); ! 23273: error( 'i', "cannot recover from previous errors" ); ! 23274: } ! 23275: ! 23276: // make sure there isn't an identifier at global scope being defined ! 23277: // by a nested typedef -- previously an error; keep it so for transition ! 23278: Pname tn; ! 23279: if ( n->tp == 0 && in_local_class(ccl)==0 && ! 23280: (tn=gtbl->look(n->string,0))) { ! 23281: error( "nested Tdef %s redefinesG %n", n->string, tn ); ! 23282: error( 'i', "cannot recover from previous errors" ); ! 23283: } ! 23284: ! 23285: nn->tpdef = new type; ! 23286: nn->tpdef->nested_sig = str; ! 23287: nn->tpdef->in_class = ccl; ! 23288: nn->tpdef->lex_level = NESTED; ! 23289: PERM(nn->tpdef); ! 23290: } ! 23291: else { ! 23292: nn = nn->tname( lastval.t ); ! 23293: Pname tn = Pbase(nn->tp)->b_name; ! 23294: Ptype tt = tn->tp; ! 23295: if ( tt->defined && tt->in_class == ccl) { ! 23296: error( "nested %t redefines immediately enclosing class", nn->string ); ! 23297: error( 'i', "cannot recover from previous errors" ); ! 23298: } ! 23299: tt->nested_sig = str; ! 23300: modified_tn = modified_tn->l; ! 23301: nn->lex_level = tn->lex_level = 0; ! 23302: nested_type = new name_list( nn, nested_type ); ! 23303: } ! 23304: nn->n_key = NESTED; ! 23305: return nn; ! 23306: } ! 23307: ! 23308: static Pname dtor_seen; ! 23309: static int in_expr; ! 23310: extern int in_sizeof; ! 23311: ! 23312: extern TOK ! 23313: lalex() ! 23314: /* return next token to grammar */ ! 23315: { ! 23316: register TOK tk; ! 23317: if ( front == 0 ) ! 23318: add_tokens(); // extend lookahead queue ! 23319: LDB(1,fprintf(stderr,"\n*** lalex()\n");showQ("before")); ! 23320: ! 23321: gettok: ! 23322: tk = deltok(); ! 23323: // error('d',&curloc,"lalex: just got %k '%s' in_typedef: %d",tk,tk==ID?yylval.s:tk==TNAME?yylval.pn->string:"", in_typedef); ! 23324: ! 23325: if ( tk == ID || tk == TNAME ) ! 23326: { ! 23327: TOK tk2 = la_look(); ! 23328: int lex_level = bl_level - in_class_decl - (tk2 == LC ); ! 23329: ! 23330: if ( tk == TNAME ) ! 23331: { ! 23332: //error('d', "lalex tname %n; lasttk: %k tk2: %k", yylval.pn, lasttk, tk2); ! 23333: //error('d', " must_be_id: %d must_be_expr %d decl_type %d",must_be_id,must_be_expr,DECL_TYPE); ! 23334: //error('d', " bl_level: %d parsing_members %d",bl_level,parsing_class_members); ! 23335: if ( tk2 == LP ! 23336: && (bl_level == 0 || parsing_class_members) ! 23337: && ( laexpr(lasttk) == 0 ) ! 23338: && must_be_expr == 0 ! 23339: && DECL_TYPE == 0 ) { ! 23340: if (la_decl()) { ! 23341: must_be_id = 0; ! 23342: DECL_TYPE = tk; ! 23343: tk = DECL_MARKER; ! 23344: goto ret; ! 23345: } ! 23346: } ! 23347: ! 23348: // note: *** can handle local typedefs here, too! ! 23349: if ( in_typedef && ! 23350: in_typedef->base != 0 && ! 23351: ccl && in_mem_fct == 0 && ! 23352: (tk2 == SM || tk2 == RP || tk2 == LB)) ! 23353: yylval.pn = do_nested_type(yylval.pn); ! 23354: ! 23355: if ( lasttk == AGGR || lasttk == ENUM ) { ! 23356: if ( tk2 == LC || tk2 == COLON ) { // class definition ! 23357: if ( lex_level ! 23358: && (in_class_decl==0 || in_mem_fct) ! 23359: && lasttk != ENUM ) // temporary ! 23360: yylval.pn = do_local_class( yylval.pn, lex_level ); ! 23361: else ! 23362: if ( in_class_decl && ccl ) ! 23363: yylval.pn = do_nested_type( yylval.pn ); ! 23364: } ! 23365: } ! 23366: ! 23367: if (tk2 == LT) { ! 23368: // a parametrized type name ! 23369: if (template_tscope(yylval.pn,latok)) ! 23370: tk = PTNAME ; ! 23371: } else ! 23372: if ( tk2 == MEM || (tk2 == DOT && mem_sel == 0 )) { ! 23373: if (tk2==DOT) ! 23374: error(strict_opt?0:'w',"``.'' used for qualification; please use ``::'' (anachronism)"); ! 23375: crunch: ! 23376: tk = TSCOPE; ! 23377: {//XXX -- should be modified to do lookup and del at each :: ! 23378: while ( (tk2 = lookahead()) == TSCOPE ) ; ! 23379: if ( tk2 == TNAME ) { ! 23380: tk2 = lookahead(); ! 23381: if ( tk2 == LP ! 23382: && (bl_level == 0 || parsing_class_members) ! 23383: && ( laexpr(lasttk) == 0 ) ! 23384: && must_be_expr == 0 ! 23385: && DECL_TYPE == 0 ) { ! 23386: if (la_decl()) { ! 23387: must_be_id = 0; ! 23388: //DECL_TYPE = tk;//??? ! 23389: DECL_TYPE = TNAME; ! 23390: //front should be :: ! 23391: front->tok = TSCOPE; ! 23392: front->retval.pn = yylval.pn; ! 23393: yylval.pn = 0; ! 23394: tk = DECL_MARKER; ! 23395: goto ret; ! 23396: } ! 23397: } ! 23398: } ! 23399: } ! 23400: tk2 = deltok(1); ! 23401: tk2 = la_look(); ! 23402: if ( tk2 == MUL ) { ! 23403: tk = MEMPTR; ! 23404: tk2 = deltok(1); ! 23405: } ! 23406: } ! 23407: // Have a TNAME. Check to be sure. ! 23408: else if ( must_be_id ){ ! 23409: //error('d',"lalex: must_be_id: <tname %n> <%k>",yylval.pn,tk2); ! 23410: if ( in_class_decl ! 23411: && lasttk == TYPE ! 23412: && tk2 == LP ! 23413: && strcmp(yylval.pn->string,ccl->string) == 0 ) ! 23414: error("%nK with returnT", yylval.pn); ! 23415: ! 23416: else if ( lasttk == TYPE && lastval.t == OVERLOAD ! 23417: && ( tk2 == SM || tk2 == LP ) ) ! 23418: { ! 23419: tk = ID; ! 23420: yylval.pn->hide(); ! 23421: yylval.pn = new name( yylval.pn->string ); ! 23422: yylval.pn->n_oper = TNAME; ! 23423: } ! 23424: else if ( lasttk == OPERATOR || ! 23425: in_typedef && yylval.pn->n_key == NESTED) ! 23426: must_be_id = 0; ! 23427: else if ( lasttk != TSCOPE // watch out for X::X ! 23428: || lastval.pn != yylval.pn ! 23429: || (in_typedef && ! 23430: in_typedef->check( yylval.pn->tp,0) == 0 )) ! 23431: { ! 23432: tk = ID; ! 23433: if ( in_typedef && (lasttk == MUL || lasttk == REF)) { ! 23434: defer_check = 1; ! 23435: in_tag = yylval.pn; ! 23436: } ! 23437: ! 23438: if ( lasttk == MEM && yylval.pn->lex_level ) { ! 23439: Pname nn = gtbl->look( yylval.pn->string, 0 ); ! 23440: if (nn == 0 ) ! 23441: error( "%k%s undeclared", lasttk, yylval.pn->string); ! 23442: else ! 23443: yylval.pn = nn; ! 23444: } ! 23445: else { ! 23446: // error('d',"lalex: else: lasttk: %k", lasttk ); ! 23447: if (lasttk!=DOT && lasttk!=REF ! 23448: && lasttk!=TSCOPE && lasttk != GOTO ) { ! 23449: // handle typedefs in basetype::check ! 23450: // when type is available ! 23451: if (!in_typedef) { ! 23452: // error('d',"\"%s\" line %d: hiding%n",__FILE__,__LINE__,yylval.pn); ! 23453: yylval.pn->hide(); ! 23454: } ! 23455: yylval.pn = new name(yylval.pn->string); ! 23456: yylval.pn->n_oper = TNAME; ! 23457: } ! 23458: } ! 23459: if ( defer_check ) defer_check = 0; ! 23460: } ! 23461: } // must_be_id ! 23462: ! 23463: if ( in_class_decl && ! 23464: ccl->lex_level && ! 23465: yylval.pn->lex_level != 0 && ! 23466: yylval.pn->tp && ! 23467: (yylval.pn->tp->base != COBJ && yylval.pn->tp->base != EOBJ)) ! 23468: { ! 23469: Pname n = gtbl->look( yylval.pn->string,0); ! 23470: if ( in_mem_fct ) { ! 23471: if (n && n->base == TNAME ) { ! 23472: error('w', "local typedef %n(%t) is not in scope of local class %s members; usingG (%t)", yylval.pn, yylval.pn->tp, ccl->string, n->tp ); ! 23473: yylval.pn = n; ! 23474: } else ! 23475: error( "local typedef %sis not in scope of inline member function of local class %s", yylval.pn->string, ccl->string); ! 23476: } ! 23477: } ! 23478: ! 23479: // if we still have a TNAME, make sure have the right TNAME ! 23480: // possibility of ananchronistic reference to nested type ! 23481: Ptype nbt = yylval.pn->tp; ! 23482: if (tk == TNAME && curr_scope == 0 && nbt && // Y y; not X::Y y; ! 23483: (nbt->base == EOBJ || nbt->base == COBJ)) ! 23484: { ! 23485: Ptype t = Pbase(nbt)->b_name->tp; ! 23486: if ( ccl && t->in_class && ! 23487: strcmp(t->in_class->string, ccl->string)) ! 23488: { ! 23489: switch( nbt->base ) { ! 23490: case COBJ: ! 23491: if (is_empty(Pclass(t))) ! 23492: yylval.pn = check_nested_type( yylval.pn ); ! 23493: break; ! 23494: case EOBJ: ! 23495: if (is_empty(Penum(t))) ! 23496: yylval.pn = check_nested_type( yylval.pn ); ! 23497: break; ! 23498: }; ! 23499: } ! 23500: } ! 23501: } ! 23502: else ! 23503: { // tk == ID ! 23504: char *s = yylval.s; ! 23505: Pname n = ktbl->look( s, HIDDEN ); ! 23506: Pname nstd = ktbl->look( s, NESTED ); ! 23507: ! 23508: // inside a class definition, ccl, that is nested ! 23509: // s is a nested class name, and is the name of ccl ! 23510: if (ccl && ccl->in_class && nstd && ! 23511: strcmp(s, ccl->string)==0) ! 23512: { ! 23513: for (Pname nn=nstd; nn; nn=nn->n_tbl_list) { ! 23514: Ptype tt = (nn->tp->base==COBJ || nn->tp->base==EOBJ) ! 23515: ? Pbase(nn->tp)->b_name->tp : nn->tpdef; ! 23516: Pclass cl = tt->in_class; ! 23517: if ( nn->n_key != NESTED ) continue; ! 23518: if (strcmp(ccl->in_class->string,cl->string) == 0) { ! 23519: tk = TNAME; ! 23520: yylval.pn = nn; ! 23521: n = nstd = nn; ! 23522: } ! 23523: } ! 23524: } ! 23525: ! 23526: if (tk2 == MEM) { ! 23527: // ID :: ! 23528: if (n) { ! 23529: yylval.pn = n; ! 23530: /*XXX*/ goto crunch; ! 23531: } ! 23532: else ! 23533: if (nstd && ! 23534: nstd->n_tbl_list==0) ! 23535: { ! 23536: yylval.pn = nstd; ! 23537: tk = TSCOPE; ! 23538: tk2 = deltok(1); ! 23539: tk2 = la_look(); ! 23540: if (tk2 == MUL ) { ! 23541: tk = MEMPTR; ! 23542: tk2 = deltok(1); ! 23543: } ! 23544: } ! 23545: else { ! 23546: error( "%s:: %sis not aTN", s, s ); ! 23547: tk2 = deltok(1); ! 23548: goto gettok; ! 23549: } ! 23550: } ! 23551: else // transitional kludge ! 23552: if ( n && nstd && n == nstd ) ! 23553: ; // null statement ! 23554: ! 23555: // Have an ID. Check last token to be sure. ! 23556: else if (lasttk==ENUM || lasttk==AGGR && ! 23557: // template <class id, class id> ! 23558: (tk2 != GT && tk2 != CM)) ! 23559: { ! 23560: int fd = tk2!=LC && tk2!=COLON; ! 23561: tk = TNAME; ! 23562: if ( nstd ) { ! 23563: // in transitional model, need flag this as error ! 23564: if ( fd == 0 ) { // real definition ! 23565: if ( ccl == 0 ) ! 23566: error("nested andG%k %s(to do this placeG%k %s {}; first)",lasttk==ENUM?lasttk:CLASS, s, lasttk==ENUM?lasttk:CLASS, s); ! 23567: else ! 23568: error("multiple nested%k %s(to do this placeG%k %s {}; first)",lasttk==ENUM?lasttk:CLASS, s, lasttk==ENUM?lasttk:CLASS,s); ! 23569: error( 'i', "cannot recover from previous errors" ); ! 23570: } ! 23571: } ! 23572: else ! 23573: // new tag, define it ! 23574: if (n==0 || ! 23575: (n->n_template_arg == template_type_formal)) ! 23576: { ! 23577: // error('d', "ccl: %t fd: %d, in_mem_fct: %d, in_class_decl: %d", ccl, fd, in_mem_fct, in_class_decl); ! 23578: n = new name( s ); ! 23579: if ( fd ) // struct X*, etc. ! 23580: n->lex_level=0; ! 23581: else ! 23582: n->lex_level=lex_level>=0?lex_level:0; ! 23583: ! 23584: if ( ccl && fd == 0 && ! 23585: in_class_decl && ! 23586: (bl_level == ccl->lex_level + in_class_decl + 1)) ! 23587: n = do_nested_type( n ); ! 23588: else ! 23589: // note: ***** modify to handle local typedef ! 23590: // note: ***** add local enums ! 23591: if ( n->lex_level && ! 23592: lasttk != ENUM ) // temporary ! 23593: n = do_local_class( n, n->lex_level ); ! 23594: else { ! 23595: n = n->tname( lastval.t ); ! 23596: modified_tn = modified_tn->l; ! 23597: if (fd && gtbl->look(n->string,0)) statStat = n; ! 23598: } ! 23599: } ! 23600: else { ! 23601: if (n->tp->base!=COBJ && n->tp->base!=EOBJ) { ! 23602: error( 'i', "hidden%n:%t",n,n->tp ); ! 23603: goto gettok; ! 23604: } ! 23605: ! 23606: if ( tk2 == LC || tk2 == COLON ) { ! 23607: // class declared and hidden but not yet defined ! 23608: // may have ctor defined which invalidates hiding ! 23609: statStat = n; ! 23610: n->n_key = 0; // inside class definition it cannot be hidden ! 23611: } ! 23612: } ! 23613: yylval.pn = nstd?nstd:n; ! 23614: } ! 23615: else { ! 23616: tk = ID; ! 23617: yylval.pn = new name( s ); ! 23618: } ! 23619: ! 23620: if ( tk == ID ) ! 23621: { ! 23622: switch ( tk2 ) { ! 23623: case ID: case TNAME: case AGGR: case ENUM: ! 23624: { ! 23625: Pname n = 0; ! 23626: ! 23627: if ((curr_scope||ccl) && nstd) { ! 23628: // within class scope in which nested class is visible ! 23629: // curr_scope == set by TSCOPE, X::foo() { ... } ! 23630: // ccl == parsing class definition ``ccl'' ! 23631: ! 23632: char *str = curr_scope?curr_scope->string:ccl->string; ! 23633: for (Pname nn=nstd; nn; nn=nn->n_tbl_list) { ! 23634: Ptype tt = (nn->tp->base==COBJ || nn->tp->base==EOBJ) ! 23635: ? Pbase(nn->tp)->b_name->tp : nn->tpdef; ! 23636: Pclass cl = tt->in_class; ! 23637: if ( nn->n_key != NESTED ) continue; ! 23638: if ( strcmp(str,cl->string) == 0){ ! 23639: tk = TNAME; ! 23640: yylval.pn = nn; ! 23641: if (lasttk == TYPE && ! 23642: lastval.t == TYPEDEF ) ! 23643: in_typedef = yylval.pn->tp; ! 23644: break; ! 23645: } ! 23646: } ! 23647: } ! 23648: if (tk == TNAME) break; // found nested class ! 23649: ! 23650: n = ktbl->look( s, HIDDEN ); ! 23651: if ( n ) { ! 23652: Pname nn = n; ! 23653: switch ( n->tp->base ) { ! 23654: default: ! 23655: error("typedef %sis not visible in this scope", s ); ! 23656: break; ! 23657: case COBJ: ! 23658: if (is_empty(Pclass(Pbase(n->tp)->b_name->tp))) ! 23659: n = check_nested_type( nn ); ! 23660: if (nn == n) ! 23661: error("%sis hidden: use struct %s%s", s,s,front->retval.s); ! 23662: break; ! 23663: case EOBJ: ! 23664: if (is_empty(Penum(Pbase(n->tp)->b_name->tp))) ! 23665: n = check_nested_type( nn ); ! 23666: if (nn == n) ! 23667: error("%sis hidden: use enum %s%s", s,s,front->retval.s); ! 23668: break; ! 23669: }; ! 23670: tk = TNAME; ! 23671: yylval.pn = n; ! 23672: } ! 23673: else ! 23674: if (n=ktbl->look(s,NESTED)) ! 23675: { ! 23676: TOK ntk; ! 23677: bit ok = 0; ! 23678: Ptype tt = return_nstd_local_type(n,ntk); ! 23679: Pclass cl = tt->in_class; ! 23680: if (ccl) { ! 23681: // x::y unncessary with in_class, ! 23682: // a derived class of in_class ! 23683: // or classes enclosing in_class ! 23684: if (ccl==cl || ccl->has_base(cl)) ! 23685: ok++; ! 23686: else { ! 23687: for (Pclass eccl=ccl->in_class;eccl; eccl=eccl->in_class) ! 23688: if ( eccl == cl ) { ok++; break; } ! 23689: } ! 23690: } ! 23691: if (!ok) ! 23692: error('w', "use %t:: to access nested %k %s (anachronism)", cl, ntk, n->string ); ! 23693: tk = TNAME; ! 23694: yylval.pn = n; ! 23695: } ! 23696: else { // probably a typo ! 23697: if ( tk2 == ID ) ! 23698: error("%s%s: %sis not aTN", s,front->retval.s,s); ! 23699: else if ( tk2 == TNAME ) ! 23700: error("%s%s: %sis not aTN", s,front->retval.pn->string,s); ! 23701: else ! 23702: error("%s%k: %sis not aTN", s,front->retval.t,s); ! 23703: goto gettok; ! 23704: } ! 23705: break; ! 23706: } ! 23707: case DOT: case REF: ! 23708: mem_sel = yylval.pn; ! 23709: break; ! 23710: default: ! 23711: if ( lasttk == TNAME && tk2 == LC ) ! 23712: { ! 23713: error("T%s %k: %s is unexpected", s, tk2, s ); ! 23714: goto gettok; ! 23715: } ! 23716: ! 23717: // have an ID. lets just make sure it should not be a TNAME ! 23718: if (curr_scope||ccl||nstd) { ! 23719: if (ccl && in_typedef && ! 23720: in_typedef->base != 0 && ! 23721: in_mem_fct == 0 && ! 23722: (tk2 == SM || tk2 == RP || tk2 == LB)) ! 23723: { ! 23724: yylval.pn = do_nested_type( yylval.pn ); ! 23725: tk = TNAME; ! 23726: } ! 23727: else ! 23728: if (nstd && must_be_id == 0 && in_expr == 0) { ! 23729: // error('d',"nstd: %n must_be_id 0 have id tk2: %k lasttk: %k",nstd,tk2,lasttk); ! 23730: // error('d',"nstd: in_expr %d lex_level %d",in_expr,lex_level); ! 23731: Pclass xcl = curr_scope?Pclass(Pbase(curr_scope->tp)->b_name->tp):(ccl?ccl:0); ! 23732: for (Pname nn=nstd; nn; nn=nn->n_tbl_list) { ! 23733: TOK ntk; ! 23734: bit ok = 0; ! 23735: Ptype tt = return_nstd_local_type(nn,ntk); ! 23736: Pclass cl = tt->in_class; ! 23737: // error('d',"xcl: %t ccl: %t", xcl, ccl ); ! 23738: if ( xcl ) { ! 23739: if (xcl==cl || xcl->has_base(cl) || ccl == cl) ! 23740: ok++; ! 23741: else { ! 23742: for (Pclass eccl=xcl->in_class;eccl;eccl=eccl->in_class) ! 23743: if ( eccl == cl ) { ok++; break; } ! 23744: } ! 23745: } ! 23746: ! 23747: if (nn == nstd) ! 23748: { ! 23749: if ( ! 23750: // special case: foo(X, ! 23751: // in_arg_list not set until **after** X is handled ! 23752: ((in_arg_list || lasttk==LP) && // foo(nestedX ! 23753: (tk2==CM || tk2==ASSIGN || ! 23754: (tk2==RP && lasttk!=MUL && lasttk!=REF))) ! 23755: || // class x : public nestedX ! 23756: (tk2==LC && (lasttk==PR || lasttk==VIRTUAL)) ! 23757: || // nestedX [*&] ! 23758: (tk2 == MUL || tk2==AND) ! 23759: || (lasttk==LP && tk2==RP) ! 23760: || (lasttk==TSCOPE && lastval.pn == nn) ! 23761: || (lasttk==COMPL && dtor_seen == nn) ! 23762: || (lasttk==TYPE && lastval.t == TYPEDEF) ! 23763: || lasttk == OPERATOR ! 23764: || lasttk == NEW || in_sizeof ) ! 23765: { // must be type name, and it must be nested: ! 23766: if ( nstd->n_tbl_list == 0 ) { // only one: ok ! 23767: if (lasttk != TSCOPE && !ok ) ! 23768: error('w', "use %t:: to access nested %k %s (anachronism)", cl, ntk, nn->string); ! 23769: break; ! 23770: } ! 23771: else { ! 23772: if (lasttk != TSCOPE && lasttk != TYPE && !ok){ ! 23773: error("ambiguous nested type %s, use %t::%s",nn->string,xcl,nn->string); ! 23774: error( 'i', "cannot recover from previous errors" ); ! 23775: } ! 23776: } ! 23777: } ! 23778: ! 23779: } ! 23780: if ( nn->n_key != NESTED ) continue; ! 23781: if (xcl && ! 23782: strcmp(xcl->string,cl->string) == 0) break; ! 23783: } // end: for nn = nstd ! 23784: ! 23785: if (nn) { ! 23786: tk = TNAME; ! 23787: yylval.pn = nn; ! 23788: if (lasttk == TYPE && ! 23789: lastval.t == TYPEDEF ) ! 23790: in_typedef = yylval.pn->tp; ! 23791: } ! 23792: } // end: if (nstd) ! 23793: } // end: if (curr_scope||ccl) ! 23794: break; ! 23795: } // end: switch tk2 ! 23796: } // end: if (tk == ID) ! 23797: } ! 23798: ! 23799: // error('d',"testing for in_expr: in_expr: %d tk: %k", in_expr, tk ); ! 23800: // error('d',"testing for in_expr: tk2: %k lasttk: %k", tk2, lasttk ); ! 23801: if (lex_level && tk==ID && tk2==LP && ! 23802: (lasttk==LC || lasttk==RC || lasttk==RP || ! 23803: lasttk == ASSIGN || lasttk == SM)) ! 23804: in_expr = 1; ! 23805: else in_expr = 0; ! 23806: ! 23807: } ! 23808: if ( tk == TNAME || ( tk == TYPE && latype(yylval.t) ) ! 23809: // XXX || tk == TSCOPE || tk == MEM ! 23810: || tk == REF || tk == DOT || tk == GOTO ! 23811: || tk == MEMPTR ) ! 23812: // TNAME cannot immediately follow a type name, ! 23813: // scope operator, right curly, selection, or goto ! 23814: must_be_id = 1; ! 23815: else ! 23816: must_be_id = 0; ! 23817: ! 23818: switch ( tk ) { ! 23819: case SM: ! 23820: mem_sel = 0; // no break ! 23821: in_expr = 0; ! 23822: case RP: case RC: must_be_expr = 0; break; ! 23823: case COLON: ! 23824: if (lasttk == RP || ! 23825: (lasttk == TYPE && lastval.t == CONST)) ! 23826: must_be_expr = 1; ! 23827: break; ! 23828: case SIZEOF: ! 23829: in_sizeof = 1; ! 23830: break; ! 23831: }; ! 23832: ret: ! 23833: if ( tk == COMPL && lasttk == TSCOPE ) ! 23834: dtor_seen = lastval.pn; ! 23835: else dtor_seen = 0; ! 23836: lasttk = tk; ! 23837: lastval = yylval; ! 23838: LDB(1,showQ("after"); ! 23839: fprintf(stderr,"returning '%s'",image(tk)); ! 23840: if ( tk==ID || tk==TNAME ) fprintf(stderr," -- '%s'",yylval.pn->string); ! 23841: fprintf(stderr,"\n"); ! 23842: ); ! 23843: // error('d',"returning tk: %k dtor_seen: %n", tk,dtor_seen ); ! 23844: return tk; ! 23845: } ! 23846: ! 23847: extern void ! 23848: la_backup( TOK t, YYSTYPE r ) ! 23849: /* ! 23850: called by parser to push token back on front of queue ! 23851: */ ! 23852: { ! 23853: LDB(1,fprintf(stderr,"\n*** la_backup( '%s', ...)\n",image(t))); ! 23854: if ( t == ID ) { Pname n = r.pn; r.s = n->string; DEL(n); } ! 23855: register toknode* T = new toknode(t,r,curloc); ! 23856: if (front) { ! 23857: front->last = T; ! 23858: T->next = front; ! 23859: T->last = 0; ! 23860: front = T; ! 23861: } else ! 23862: front = rear = T; ! 23863: lasttk = 0; ! 23864: } ! 23865: ! 23866: extern int ! 23867: la_sctype( TOK t ) ! 23868: { ! 23869: //error('d',&latok->place,"la_sctype(%k ) -- latok ==%k",t,latok->tok); ! 23870: if ( t != latok->tok && t != TSCOPE && t != MEMPTR ) ! 23871: error( 'i', &latok->place, "la_sctype, lalex.c" ); ! 23872: ! 23873: switch( latok->retval.t ) { ! 23874: case TYPEDEF: ! 23875: case EXTERN: ! 23876: case STATIC: ! 23877: case AUTO: ! 23878: case REGISTER: ! 23879: case OVERLOAD: ! 23880: case INLINE: ! 23881: case FRIEND: ! 23882: case CONST: ! 23883: case VOLATILE: ! 23884: return 1; ! 23885: default: ! 23886: return 0; ! 23887: } ! 23888: } ! 23889: ! 23890: extern int ! 23891: la_cast() ! 23892: /* ! 23893: called in reduction of term_lp to check for ambiguous prefix-style cast ! 23894: if result is 1, caller inserts DECL_MARKER to force reduction of cast ! 23895: */ ! 23896: { ! 23897: // yychar already designates TYPE or TNAME ! 23898: // LP must start the lookahead queue! ! 23899: LDB(1,fprintf(stderr,"\n*** la_cast()\n");); ! 23900: int tk, tk2 = latok->tok; ! 23901: ! 23902: for ( ; ; ) { ! 23903: tk = tk2; ! 23904: tk2 = lookahead(); ! 23905: ! 23906: switch( tk ) { ! 23907: case LP: ! 23908: if ( tk2 == MUL || tk2 == AND || ! 23909: tk2 == TSCOPE || tk2 == MEMPTR ) ! 23910: // T ( * ... ! 23911: // T ( C ::* ... ! 23912: continue; ! 23913: else ! 23914: // T ( exp ) ! 23915: return 0; ! 23916: case MUL: case AND: ! 23917: //if ( tk2 == SCTYPE ) ! 23918: if ( la_sctype( tk2 ) ) ! 23919: // T ( * const ... ! 23920: // T ( * volatile ... ! 23921: tk2 = lookahead(); ! 23922: continue; ! 23923: case MEMPTR: ! 23924: if ( tk2 == RP ) continue; ! 23925: break; ! 23926: case TSCOPE: ! 23927: if ( tk2 == MUL ) ! 23928: // T ( C :: * ... ! 23929: continue; ! 23930: else ! 23931: // T ( exp ) ! 23932: return 0; ! 23933: case RP: case LB: ! 23934: // T (*)() ! 23935: // T (*[])() ! 23936: return 1; ! 23937: } ! 23938: ! 23939: return 0; ! 23940: } ! 23941: } ! 23942: ! 23943: static int ! 23944: la_decl() ! 23945: /* ! 23946: handles ambiguities ! 23947: type (*x) () ! 23948: type (*x) [] ! 23949: at start of arg list / statement ! 23950: return val == 1 if lookahead finds a declaration ! 23951: (used for error messages only) ! 23952: if declaration is "ambiguous" (i.e., can't be recognized with ! 23953: 1-symbol lookahead), insert DECL_MARKER to force reduction ! 23954: of "type" ! 23955: */ ! 23956: { ! 23957: ! 23958: // LP must start the lookahead queue! ! 23959: LDB(1,fprintf(stderr,"\n*** la_decl()\n");); ! 23960: int tk, tk2 = latok->tok; ! 23961: int paren = 0; ! 23962: int ptr = 0; ! 23963: ! 23964: for ( ; ; ) { ! 23965: ! 23966: tk = tk2; ! 23967: tk2 = lookahead(); ! 23968: ! 23969: // fprintf(stderr,"\nla_decl:tk:%d %s tk2: %d %s", tk, keys[tk], tk2, keys[tk2]); ! 23970: switch( tk ) { ! 23971: case LP: ! 23972: if ( tk2 == MUL || tk2 == AND || tk2 == TSCOPE ) { ! 23973: // T ( * ... ! 23974: ++paren; ! 23975: ptr = 1; ! 23976: continue; ! 23977: } else ! 23978: if ( tk2 == MEMPTR ) { ! 23979: // T ( C ::* ... ! 23980: return 1; ! 23981: } else ! 23982: // possible redundant parens ! 23983: if ( tk2 == ID && lookahead() == RP ) { ! 23984: TOK tp = lookahead(); ! 23985: // error( 'd', "tp %k tk: %k tk2: %k", tp, tk, tk2 ); ! 23986: // error( 'd', "bl_level: %d, in_class_decl: %d", bl_level,in_class_decl ); ! 23987: if ( tp == SM || tp == CM || tp == ASSIGN ) ! 23988: { ! 23989: // member initialization list ! 23990: if ( tp != SM && in_arg_list == 0 ) return 1; ! 23991: } ! 23992: else ! 23993: if ( tp == RP && (bl_level-in_class_decl==0)) ! 23994: return 1; ! 23995: if ( tp != LP ) ! 23996: return 0; ! 23997: latok=latok->last; // restore lookahead ! 23998: ++paren; ! 23999: continue; ! 24000: } ! 24001: else ! 24002: // T ( exp ) ! 24003: return 0; ! 24004: case MUL: case AND: ! 24005: //if ( tk2 == SCTYPE ) ! 24006: if ( la_sctype( tk2 )) ! 24007: // T ( * const ... ! 24008: // T ( * volatile ... ! 24009: return 1; ! 24010: else { ! 24011: ptr = 0; ! 24012: continue; ! 24013: } ! 24014: case MEMPTR: ! 24015: // T ( C :: * ... ! 24016: return 1; ! 24017: case TSCOPE: ! 24018: if ( tk2 == MUL ) //??tk SHOULD HAVE TRANSLATED TO MEMPTR!! ! 24019: // T ( C :: * ... ! 24020: return 1; ! 24021: else if ( ptr ) ! 24022: // T ( exp ) ! 24023: return 0; ! 24024: else if ( tk2 == ID || tk2 == OPERATOR ) ! 24025: // T ( * C :: id ... ! 24026: continue; ! 24027: else ! 24028: // error ! 24029: return 0; ! 24030: } ! 24031: ! 24032: break; ! 24033: } ! 24034: ! 24035: if ( tk == RP || tk == LB ) ! 24036: // T (*)() ! 24037: // T (*[])() ! 24038: return 1; ! 24039: ! 24040: if ( tk != ID && tk != OPERATOR ) ! 24041: // T ( exp ) ! 24042: return 0; ! 24043: ! 24044: if ( tk == OPERATOR ) ! 24045: switch ( tk2 ) { ! 24046: case PLUS: case MINUS: case MUL: case REFMUL: ! 24047: case AND: case OR: case ER: case SHIFTOP: case EQUOP: ! 24048: case DIVOP: case RELOP: case ANDAND: case OROR: ! 24049: case NOT: case COMPL: case ICOP: case ASSIGN: ! 24050: case ASOP: case NEW: case GNEW: case DELETE: ! 24051: // OPERATOR oper ! 24052: tk2 = lookahead(); ! 24053: break; ! 24054: case LP: ! 24055: // OPERATOR () ! 24056: tk2 = lookahead(); ! 24057: if ( tk2 == RP ) { ! 24058: tk2 = lookahead(); ! 24059: break; ! 24060: } else ! 24061: return 0; ! 24062: case LB: ! 24063: // OPERATOR [] ! 24064: tk2 = lookahead(); ! 24065: if ( tk2 == LB ) { ! 24066: tk2 = lookahead(); ! 24067: break; ! 24068: } else ! 24069: return 0; ! 24070: default: // illegal operator ! 24071: return 0; ! 24072: } ! 24073: ! 24074: int allow_lp = 1; ! 24075: int allow_rp = 1; ! 24076: for ( ; ; ) { ! 24077: tk = tk2; ! 24078: tk2 = lookahead(); ! 24079: ! 24080: // fprintf(stderr,"\nla_decl2:tk:%d %s tk2: %d %s", tk, keys[tk], tk2, keys[tk2]); ! 24081: switch( tk ) { ! 24082: case LP: ! 24083: if ( !allow_lp ) ! 24084: // T ( * id [ exp ] ( ... ! 24085: return 0; ! 24086: ! 24087: // Current lookahead will be a decl if ! 24088: // the next lookahead is an arg decl ! 24089: if ( tk2 == RP || tk2 == ENUM || tk2==AGGR ! 24090: || tk2==ELLIPSIS || la_sctype( tk2 )) ! 24091: // T ( * id () ! 24092: // T ( * id ) () ! 24093: return 1; ! 24094: ! 24095: if ( tk2 == TYPE || tk2 == TNAME ) { ! 24096: // T ( * id ) ( T2 ... ! 24097: if ( lookahead() == LP && !la_decl() ) ! 24098: return 0; ! 24099: return 1; ! 24100: } ! 24101: ! 24102: return 0; ! 24103: case LB: ! 24104: if ( tk2 == RB || lookahead() == RB ) ! 24105: // T ( * id [] ... ! 24106: return 1; ! 24107: else { ! 24108: // T ( * id [ exp ] ... ! 24109: allow_lp = 0; ! 24110: allow_rp = 1; ! 24111: while ( lookahead() != RB ); ! 24112: tk2 = lookahead(); ! 24113: continue; ! 24114: } ! 24115: case RP: ! 24116: // error ('d', "rp: allow_rp: %d paren: %d", allow_rp, paren ); ! 24117: if ( !allow_rp || !paren ) ! 24118: // T ( * id ) ) ! 24119: return 0; ! 24120: // permit redundant parentheses ! 24121: else ! 24122: if ( tk2 == SM || tk2 == CM || tk2 == ASSIGN ) ! 24123: return 1; ! 24124: else ! 24125: if ( tk2 == RP && (bl_level-in_class_decl == 0)) ! 24126: return 1; ! 24127: else ! 24128: { ! 24129: // T ( * id ) ... ! 24130: allow_lp = 1; ! 24131: allow_rp = 0; ! 24132: --paren; ! 24133: continue; ! 24134: } ! 24135: default: ! 24136: return 0; ! 24137: } ! 24138: } ! 24139: } ! 24140: ! 24141: ! 24142: ! 24143: /* ! 24144: ** PROCESSING OF INLINE MEMBER FUNCTIONS ! 24145: */ ! 24146: static int la_snarf(); ! 24147: ! 24148: extern toknode* ! 24149: save_text() ! 24150: /* ! 24151: save text of inline def on q of class ! 24152: */ ! 24153: { ! 24154: // Q should contain at least the tokens < FDEF, X ... > ! 24155: // where X is either LC or COLON (start of ftn) ! 24156: LDB(2,fprintf(stderr,"save_text()")); ! 24157: LDB(3,fprintf(stderr,"front: %s",image(front->tok))); ! 24158: LDB(3,fprintf(stderr,"front->next: %s",image(front->next->tok))); ! 24159: latok = front->next; ! 24160: if ( la_snarf() ) { ! 24161: // append this set of tokens to ! 24162: // inline tokenq for class ! 24163: toknode* t = front; // FDEF ! 24164: if ( ccl->c_funqf == 0 ) ! 24165: ccl->c_funqf = front; ! 24166: else { ! 24167: ccl->c_funqr->next = front; ! 24168: front->last = ccl->c_funqr; ! 24169: } ! 24170: ccl->c_funqr = latok; ! 24171: front = latok->next; ! 24172: latok->next = 0; ! 24173: if (front) front->last = 0; ! 24174: return t; ! 24175: } ! 24176: return 0; ! 24177: } ! 24178: ! 24179: ! 24180: extern void ! 24181: restore_text() ! 24182: /* ! 24183: restore tokens for member inlines onto token q ! 24184: */ ! 24185: { ! 24186: LDB(2,fprintf(stderr,"restore_text()")); ! 24187: if (ccl->c_funqf == 0) // no inlines on Q ! 24188: return; ! 24189: LDB(3,fprintf(stderr," Q present: %d,%d",ccl->c_funqf,ccl->c_funqr)); ! 24190: LDB(3,fprintf(stderr," front==%s",image(ccl->c_funqf->tok))); ! 24191: LDB(3,fprintf(stderr," rear ==%s",image(ccl->c_funqr->tok))); ! 24192: ccl->c_funqr->next = front; ! 24193: if (front) front->last = ccl->c_funqr; ! 24194: front = ccl->c_funqf; ! 24195: ccl->c_funqf = ccl->c_funqr = 0; ! 24196: } ! 24197: ! 24198: ! 24199: static void ! 24200: del_tokens( toknode* marker ) ! 24201: /* ! 24202: delete tokens from marker to latok, not inclusive ! 24203: */ ! 24204: { ! 24205: if ( marker == 0 || marker == latok || marker->next == 0 ) ! 24206: error('i', "bad token queue"); ! 24207: ! 24208: LDB(2,fprintf(stderr,"del_tokens: %s..%s\n",image(marker->tok),image(latok->tok))); ! 24209: ! 24210: register toknode* tt = marker->next; ! 24211: if ( tt == latok ) return; ! 24212: marker->next = latok; ! 24213: latok->last->next = 0; ! 24214: latok->last = marker; ! 24215: register toknode* tx = tt; ! 24216: do { ! 24217: LDB(3,fprintf(stderr," deleting %s\n",image(tt->tok))); ! 24218: tx = tx->next; ! 24219: delete tt; ! 24220: tt = tx; ! 24221: } while ( tx ); ! 24222: } ! 24223: ! 24224: ! 24225: static int ! 24226: la_snarf() ! 24227: /* ! 24228: scan function def without processing declarations ! 24229: */ ! 24230: { ! 24231: LDB(2,fprintf(stderr,"la_snarf()")); ! 24232: loc *L = &latok->place; ! 24233: //DBPLACE(1,L.l,L.f); ! 24234: int parens = 0; ! 24235: int paren_error = 0; ! 24236: toknode* marker = latok; ! 24237: switch ( latok->tok ) { ! 24238: default: ! 24239: error('i', L, "bad token Q snarfing function: %d", latok->tok); ! 24240: case COLON: ! 24241: break; ! 24242: case LC: ! 24243: --bl_level; ! 24244: goto eatf; ! 24245: } ! 24246: LDB(2,fprintf(stderr,"\"eat\" member initializers")); ! 24247: for (;;) { ! 24248: if (latok->next == 0) add_tokens(); ! 24249: switch ( (latok=latok->next)->tok ) { ! 24250: case LP: ! 24251: ++parens; ! 24252: default: ! 24253: LDB(3,fprintf(stderr,"...%s",image(latok->tok))); ! 24254: continue; ! 24255: case RP: ! 24256: if ( (--parens < 0) && (paren_error++ == 0) ) ! 24257: error(0,&latok->place,"unbalanced ()"); ! 24258: continue; ! 24259: case LC: ! 24260: case RC: ! 24261: if ( parens <= 0 ) ! 24262: goto eatf; ! 24263: continue; ! 24264: case SM: ! 24265: if ( parens <= 0 ) { ! 24266: error(0, L, "illegal bit field"); ! 24267: del_tokens( front ); ! 24268: delete front; ! 24269: front = latok; ! 24270: front->last = 0; ! 24271: return 0; ! 24272: } ! 24273: continue; ! 24274: case EOFTOK: ! 24275: error('i',&latok->place,"unexpected end of file"); ! 24276: } // switch ! 24277: } // for ! 24278: ! 24279: eatf: ! 24280: int level = 1; ! 24281: for (;;) { ! 24282: if (latok->next == 0) add_tokens(); ! 24283: switch ( (latok=latok->next)->tok ) { ! 24284: case LC: ! 24285: ++level; ! 24286: default: ! 24287: LDB(3,fprintf(stderr,"...%s",image(latok->tok))); ! 24288: continue; ! 24289: case RC: ! 24290: LDB(3,fprintf(stderr,"...RC")); ! 24291: if (--level <= 0) { ! 24292: if (level < 0) { ! 24293: error(0,&latok->place,"unexpected '}'"); ! 24294: goto bad; ! 24295: } ! 24296: return 1; ! 24297: } ! 24298: break; ! 24299: case EOFTOK: ! 24300: error('e', &latok->place, "unbalanced {}"); ! 24301: goto bad; ! 24302: } // switch ! 24303: } // for ! 24304: bad: ! 24305: del_tokens( marker ); ! 24306: marker->tok = SM; ! 24307: return 0; ! 24308: } ! 24309: ! 24310: Pname check_for_nested( Pname nstd, TOK lasttk, YYSTYPE lastval, TOK tk2) ! 24311: { ! 24312: // error('d',"nstd: %n must_be_id 0 tk2: %k lasttk: %d",nstd,tk2,lasttk); ! 24313: TOK tk = ID; ! 24314: Pclass xcl = curr_scope?Pclass(Pbase(curr_scope->tp)->b_name->tp):(ccl?ccl:0); ! 24315: ! 24316: for (Pname nn=nstd; nn; nn=nn->n_tbl_list) { ! 24317: TOK ntk; ! 24318: bit ok = 0; ! 24319: Ptype tt = return_nstd_local_type(nn,ntk); ! 24320: Pclass cl = tt->in_class; ! 24321: if ( xcl ) { ! 24322: if (xcl==cl || xcl->has_base(cl)) ! 24323: ok++; ! 24324: else { ! 24325: for (Pclass eccl=xcl->in_class;eccl;eccl=eccl->in_class) ! 24326: if ( eccl == cl ) { ok++; break; } ! 24327: } ! 24328: } ! 24329: ! 24330: if (nn == nstd) ! 24331: { ! 24332: if ( ((in_arg_list || lasttk==LP) && // foo(nestedX ! 24333: (tk2==CM || tk2==ASSIGN || tk2==RP)) ! 24334: || (tk2==LC && (lasttk==PR || lasttk==VIRTUAL)) ! 24335: || (tk2 == MUL || tk2==AND) ! 24336: || (lasttk==LP && tk2==RP) ! 24337: || (lasttk==TSCOPE && lastval.pn == nn) ! 24338: || (lasttk==COMPL && dtor_seen == nn) ! 24339: || (lasttk==TYPE && lastval.t == TYPEDEF) ! 24340: || lasttk == NEW || in_sizeof ) ! 24341: { ! 24342: if ( nstd->n_tbl_list == 0 ) { // only one: ok ! 24343: break; ! 24344: } else { ! 24345: if (lasttk != TSCOPE && !ok){ ! 24346: error("ambiguous nested type %s, use X::%s",nn->string,nn->string); ! 24347: error( 'i', "cannot recover from previous errors" ); ! 24348: } ! 24349: } ! 24350: } ! 24351: } ! 24352: if ( nn->n_key != NESTED ) continue; ! 24353: if (xcl && strcmp(xcl->string,cl->string) == 0) break; ! 24354: } // end: for nn = nstd ! 24355: return nn; ! 24356: } ! 24357: ! 24358: 0707071010112044341004440001630000160000010203200466055404200000600000066146lex.c /*ident "@(#)ctrans:src/lex.c 1.4" */ ! 24359: /*************************************************************************** ! 24360: ! 24361: C++ source for cfront, the C++ compiler front-end ! 24362: written in the computer science research center of Bell Labs ! 24363: ! 24364: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 24365: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 24366: ! 24367: lex.c: ! 24368: lexical analyser based on pcc's and cpre's scanners ! 24369: modified to handle classes: ! 24370: new keywords: class ! 24371: public ! 24372: call ! 24373: etc. ! 24374: names are not entered in the symbol table by lex() ! 24375: names can be of arbitrary length ! 24376: error() is used to report errors ! 24377: {} and () must match ! 24378: numeric constants are not converted into internal representation ! 24379: but stored as strings ! 24380: ! 24381: ****************************************************************************/ ! 24382: ! 24383: #include "cfront.h" ! 24384: #include "yystype.h" ! 24385: #include "size.h" ! 24386: #include "tqueue.h" ! 24387: #include "template.h" ! 24388: ! 24389: # define CCTRANS(x) x ! 24390: #define copy_if_need_be(s) ((templp->in_progress || templp->parameters_in_progress) ? strdup(s) : (s)) ! 24391: ! 24392: /* lexical actions */ ! 24393: ! 24394: #define A_ERR 0 /* illegal character */ ! 24395: #define A_LET 1 /* saw a letter */ ! 24396: #define A_DIG 2 /* saw a digit */ ! 24397: #define A_1C 3 /* return a single character */ ! 24398: #define A_STR 4 /* string */ ! 24399: #define A_CC 5 /* character constant */ ! 24400: #define A_BCD 6 /* GCOS BCD constant */ ! 24401: #define A_SL 7 /* saw a / */ ! 24402: #define A_DOT 8 /* saw a . */ ! 24403: #define A_2C 9 /* possible two character symbol */ ! 24404: #define A_WS 10 /* whitespace (not \n) */ ! 24405: #define A_NL 11 /* \n */ ! 24406: #define A_LC 12 /* { */ ! 24407: #define A_RC 13 /* } */ ! 24408: #define A_L 14 /* ( */ ! 24409: #define A_R 15 /* ) */ ! 24410: #define A_EOF 16 ! 24411: #define A_ASS 17 ! 24412: #define A_LT 18 ! 24413: #define A_GT 19 /* > */ ! 24414: #define A_ER 20 ! 24415: #define A_OR 21 ! 24416: #define A_AND 22 ! 24417: #define A_MOD 23 ! 24418: #define A_NOT 24 ! 24419: #define A_MIN 25 ! 24420: #define A_MUL 26 ! 24421: #define A_PL 27 ! 24422: #define A_COL 28 /* : */ ! 24423: #define A_SHARP 29 /* # */ ! 24424: #define A_DOLL 30 /* $ */ ! 24425: ! 24426: /* character classes */ ! 24427: ! 24428: # define LEXLET 01 ! 24429: # define LEXDIG 02 ! 24430: /* no LEXOCT because 8 and 9 used to be octal digits */ ! 24431: # define LEXHEX 010 ! 24432: # define LEXWS 020 ! 24433: # define LEXDOT 040 ! 24434: ! 24435: const FIRSTCHUNK = 8*1024-8; ! 24436: const BUFCHUNK = 4*1024-8; ! 24437: ! 24438: /* text buffer */ ! 24439: static char inbuf[FIRSTCHUNK/*TBUFSZ*/]; ! 24440: static char* txtmax = &inbuf[FIRSTCHUNK/*TBUFSZ*/-1]; ! 24441: static char* txtstart = 0; ! 24442: static char* txtfree = 0; ! 24443: ! 24444: static struct buf* bufhead; ! 24445: static buf* freebuf; ! 24446: //static bufs; ! 24447: ! 24448: struct buf { ! 24449: buf* next; ! 24450: char chars[BUFCHUNK]; ! 24451: // buf() { next=bufhead; bufhead=this; } ! 24452: }; ! 24453: ! 24454: new_buf(char c) ! 24455: { ! 24456: //fprintf(stderr,"new_buf %d\n",bufs++); ! 24457: buf* pbuf; ! 24458: if (freebuf) { ! 24459: pbuf = freebuf; ! 24460: freebuf = freebuf->next; ! 24461: } ! 24462: else ! 24463: pbuf = new buf; // allocate and register new chunk ! 24464: pbuf->next = bufhead; ! 24465: bufhead = pbuf; ! 24466: ! 24467: if (BUFCHUNK < txtmax-txtstart) error('l',"lexical token too long"); ! 24468: ! 24469: // copy current token: ! 24470: char* p = txtstart; ! 24471: txtstart = txtfree = &pbuf->chars[0]; ! 24472: while (p<txtmax) *txtfree++ = *p++; ! 24473: *txtfree++=c; ! 24474: txtmax = &pbuf->chars[BUFCHUNK-1]; ! 24475: return 0; ! 24476: } ! 24477: ! 24478: ! 24479: #define pch(c) ((txtmax<=txtfree)?new_buf(c):(*txtfree++=c)) ! 24480: #define start_txt() txtstart = txtfree ! 24481: #define del_txt() txtfree = txtstart ! 24482: ! 24483: static int Nfile;// = 1; ! 24484: static char* file_name[MAXFILE*4]; // source file names ! 24485: // file_name[0] == src_file_name ! 24486: // file_name[0] == 0 means stdin ! 24487: static short file_stack[MAXFILE]; // stack of file name indices ! 24488: static int tcurr_file; // current index in file_stack ! 24489: // that is current #include nest level ! 24490: ! 24491: Linkage linkage = linkage_default; // linkage is default C++ ! 24492: const LINKMAX = 10; ! 24493: static Linkage lvec[LINKMAX] = { linkage_default }; ! 24494: static int lcount = 0; ! 24495: ! 24496: void set_linkage(char* p) ! 24497: { ! 24498: if (p==0 || *p == 0) { // resume previous linkage ! 24499: if (lcount>0) linkage = lvec[--lcount]; ! 24500: } ! 24501: else { ! 24502: if (LINKMAX<=++lcount) { ! 24503: error('l',"linkage directive nested too deep"); ! 24504: --lcount; ! 24505: } else if (strcmp(p,"C")==0) ! 24506: lvec[lcount] = linkage = linkage_C; ! 24507: else if (strcmp(p,"C++")==0) ! 24508: lvec[lcount] = linkage = linkage_Cplusplus; ! 24509: else { ! 24510: error("%s linkage",p); ! 24511: --lcount; ! 24512: } ! 24513: } ! 24514: } ! 24515: ! 24516: static struct loc tloc; ! 24517: FILE * out_file = stdout; ! 24518: FILE * in_file = stdin; ! 24519: Ptable ktbl; ! 24520: Ptable keyword_table; ! 24521: ! 24522: static int p_level = 0; /* number of unmatched ``(''s */ ! 24523: static int b_level = 0; /* number of unmatched ``{''s */ ! 24524: ! 24525: # ifdef ibm ! 24526: ! 24527: # define CSMASK 0377 ! 24528: # define CSSZ 256 ! 24529: ! 24530: # else ! 24531: ! 24532: # define CSMASK 0177 ! 24533: # define CSSZ 128 ! 24534: ! 24535: # endif ! 24536: ! 24537: static short lxmask[CSSZ+1]; ! 24538: ! 24539: int saved = 0; /* putback character, avoid ungetchar */ ! 24540: static int lxtitle(); ! 24541: ! 24542: // overload rt; ! 24543: inline YYSTYPE rt(char* x) { YYSTYPE y; y.s = x; return y; } ! 24544: inline YYSTYPE rt(int x) { YYSTYPE y; y.t = x; return y; } ! 24545: inline YYSTYPE rt(loc x) { YYSTYPE y; y.l = x; return y; } ! 24546: inline YYSTYPE rt(void* x) { YYSTYPE y; y.pn = Pname(x); return y; } ! 24547: ! 24548: #define get(c) (c=getc(in_file)) ! 24549: #define unget(c) ungetc(c,in_file) ! 24550: ! 24551: #define reti(a,b) { addtok(a, rt(b), tloc); return a; } ! 24552: #define retn(a,b) { addtok(a, rt((Pnode)b), tloc); return a; } ! 24553: #define rets(a,b) { addtok(a, rt(b), tloc); return a; } ! 24554: #define retl(a) { addtok(a, rt(tloc), tloc); return a; } ! 24555: ! 24556: // keys[] holds the external form for tokens with fixed representation ! 24557: // illegal tokens and those with variable representation have 0 entries ! 24558: char* keys[MAXTOK+1]; ! 24559: ! 24560: static void ! 24561: new_key(char* s, TOK toknum, TOK yyclass) ! 24562: /* ! 24563: make "s" a new keyword with the representation (token) "toknum" ! 24564: "yyclass" is the yacc token (for example new_key("int",INT,TYPE); ) ! 24565: "yyclass==0" means yyclass=toknum; ! 24566: */ ! 24567: { ! 24568: Pname n = new name(s); ! 24569: ! 24570: keys[(toknum==LOC)?yyclass:toknum] = s; ! 24571: n = new name(s); ! 24572: Pname nn = keyword_table->insert(n,0); ! 24573: // if (Nold) error('i',"keyword %sD twice",s); ! 24574: nn->base = toknum; ! 24575: nn->syn_class = (yyclass) ? yyclass : toknum; ! 24576: delete n; ! 24577: } ! 24578: ! 24579: const int keyword_count = 67; ! 24580: static void ! 24581: ktbl_init() ! 24582: /* ! 24583: enter keywords into keyword table for use by lex() ! 24584: and into keyword representation table used for output ! 24585: ! 24586: ktbl is only for types. We put nothing in it. ! 24587: keyword_table is for user-defined reserved words ! 24588: */ ! 24589: { ! 24590: ktbl = new table(KTBLSIZE,0,0); ! 24591: keyword_table = new table(keyword_count,0,0); ! 24592: ! 24593: new_key("asm",ASM,0); ! 24594: new_key("auto",AUTO,TYPE); ! 24595: new_key("break",LOC,BREAK); ! 24596: new_key("case",LOC,CASE); ! 24597: new_key("continue",LOC,CONTINUE); ! 24598: new_key("char",CHAR,TYPE); ! 24599: new_key("do",LOC,DO); ! 24600: new_key("double",DOUBLE,TYPE); ! 24601: new_key("default",LOC,DEFAULT); ! 24602: new_key("enum",ENUM,0); ! 24603: new_key("else",LOC,ELSE); ! 24604: new_key("extern",EXTERN,TYPE); ! 24605: new_key("float",FLOAT,TYPE); ! 24606: new_key("for",LOC,FOR); ! 24607: new_key("goto",LOC,GOTO); ! 24608: new_key("catch",CATCH,CATCH); ! 24609: new_key("try",TRY,TRY); ! 24610: new_key("if",LOC,IF); ! 24611: new_key("int",INT,TYPE); ! 24612: new_key("long",LONG,TYPE); ! 24613: new_key("return",LOC,RETURN); ! 24614: new_key("register",REGISTER,TYPE); ! 24615: new_key("static",STATIC,TYPE); ! 24616: new_key("struct",STRUCT,AGGR); ! 24617: new_key("sizeof",SIZEOF,0); ! 24618: new_key("short",SHORT,TYPE); ! 24619: new_key("switch",LOC,SWITCH); ! 24620: new_key("typedef",TYPEDEF,TYPE); ! 24621: new_key("unsigned",UNSIGNED,TYPE); ! 24622: new_key("union",UNION,AGGR); ! 24623: new_key("void",VOID,TYPE); ! 24624: new_key("while",LOC,WHILE); ! 24625: ! 24626: new_key("class",CLASS,AGGR); ! 24627: new_key("const",CONST,TYPE); ! 24628: new_key("delete",LOC,DELETE); ! 24629: new_key("friend",FRIEND,TYPE); ! 24630: new_key("inline",INLINE,TYPE); ! 24631: new_key("new",NEW,0); ! 24632: new_key("operator",OPERATOR,0); ! 24633: new_key("overload",OVERLOAD,TYPE); ! 24634: new_key("private",PRIVATE,PR); ! 24635: new_key("protected",PROTECTED,PR); ! 24636: new_key("public",PUBLIC,PR); ! 24637: new_key("signed",SIGNED,TYPE); ! 24638: new_key("template",TEMPLATE,0); ! 24639: new_key("this",THIS,0); ! 24640: new_key("virtual",VIRTUAL,TYPE); ! 24641: new_key("volatile",VOLATILE,TYPE); ! 24642: ! 24643: new_key("__statement", STATEMENT, 0) ; ! 24644: new_key("__expression", EXPRESSION, 0) ; ! 24645: new_key("__template_test", TEMPLATE_TEST, 0) ; ! 24646: } ! 24647: ! 24648: loc last_line; ! 24649: loc noloc = { 0, 0 }; ! 24650: ! 24651: void loc::putline() ! 24652: { ! 24653: if (file==0 && line==0) return; ! 24654: // fix, Nfile, not MAXFILE; Nfile == MAXFILE*4 ! 24655: // if (0<=file && file<MAXFILE) { ! 24656: if ( 0<=file && file <= Nfile ) { ! 24657: char* f = file_name[file]; ! 24658: if (f==0) f = src_file_name; ! 24659: fprintf(out_file,line_format,line,f); ! 24660: last_line = *this; ! 24661: } ! 24662: } ! 24663: ! 24664: void loc::put(FILE* p) ! 24665: { ! 24666: // fix, Nfile, not MAXFILE; Nfile == MAXFILE*4 ! 24667: // if (0<=file && file<MAXFILE) { ! 24668: if ( 0<=file && file <= Nfile ) { ! 24669: char* f = file_name[file]; ! 24670: if (f==0) f = src_file_name; ! 24671: fprintf(p,"\"%s\", line %d: ",f,line); ! 24672: } ! 24673: } ! 24674: ! 24675: void lxenter(register char* s, short m) ! 24676: /* enter a mask into lxmask */ ! 24677: { ! 24678: register c; ! 24679: ! 24680: while( c= *s++ ) lxmask[c+1] |= m; ! 24681: ! 24682: } ! 24683: ! 24684: ! 24685: void lxget(register c, register m) ! 24686: /* ! 24687: put 'c' back then scan for members of character class 'm' ! 24688: terminate the string read with \0 ! 24689: txtfree points to the character position after that \0 ! 24690: */ ! 24691: { ! 24692: pch(c); ! 24693: while ( (get(c), lxmask[c+1]&m) ) pch(c); ! 24694: unget(c); ! 24695: pch('\0'); ! 24696: } ! 24697: ! 24698: struct LXDOPE { ! 24699: short lxch; /* the character */ ! 24700: short lxact; /* the action to be performed */ ! 24701: TOK lxtok; /* the token number to be returned */ ! 24702: } lxdope[] = { ! 24703: #ifdef apollo ! 24704: '@', A_ERR, 0, /* illegal characters go here... */ ! 24705: #else ! 24706: '$', A_DOLL, 0, ! 24707: // '$', A_ERR, 0, /* illegal characters go here... */ ! 24708: #endif ! 24709: '_', A_LET, 0, /* letters point here */ ! 24710: '0', A_DIG, 0, /* digits point here */ ! 24711: ' ', A_WS, 0, /* whitespace goes here */ ! 24712: '\n', A_NL, 0, ! 24713: '"', A_STR, 0, /* character string */ ! 24714: '\'', A_CC, 0, /* ASCII character constant */ ! 24715: '`', A_BCD, 0, /* 'foreign' character constant, e.g. BCD */ ! 24716: '(', A_L, LP, ! 24717: ')', A_R, RP, ! 24718: '{', A_LC, LC, ! 24719: '}', A_RC, RC, ! 24720: '[', A_1C, LB, ! 24721: ']', A_1C, RB, ! 24722: '*', A_MUL, MUL, ! 24723: '?', A_1C, QUEST, ! 24724: ':', A_COL, COLON, ! 24725: '+', A_PL, PLUS, ! 24726: '-', A_MIN, MINUS, ! 24727: '/', A_SL, DIV, ! 24728: '%', A_MOD, MOD, ! 24729: '&', A_AND, AND, ! 24730: '|', A_OR, OR, ! 24731: '^', A_ER, ER, ! 24732: '!', A_NOT, NOT, ! 24733: '~', A_1C, COMPL, ! 24734: ',', A_1C, CM, ! 24735: ';', A_1C, SM, ! 24736: '.', A_DOT, DOT, ! 24737: '<', A_LT, LT, ! 24738: '>', A_GT, GT, ! 24739: '=', A_ASS, ASSIGN, ! 24740: '#', A_SHARP, 0, ! 24741: EOF, A_EOF, EOFTOK ! 24742: }; ! 24743: /* note: EOF is used as sentinel, so must be <=0 and last entry in table */ ! 24744: ! 24745: static struct LXDOPE *lxcp[CSSZ+1]; ! 24746: ! 24747: void ! 24748: lex_init() ! 24749: { ! 24750: register struct LXDOPE *p; ! 24751: register i; ! 24752: register char *cp; ! 24753: /* set up character classes */ ! 24754: ! 24755: /* first clear lexmask */ ! 24756: for(i=0; i<=CSSZ; i++) lxmask[i] = 0; ! 24757: ! 24758: #ifdef apollo ! 24759: lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_$", LEXLET ); ! 24760: #else ! 24761: lxenter( "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_", LEXLET ); ! 24762: #endif ! 24763: lxenter( "0123456789", LEXDIG ); ! 24764: lxenter( "0123456789abcdefABCDEF", LEXHEX ); ! 24765: /* \013 should become \v someday; \013 is OK for ASCII and EBCDIC */ ! 24766: lxenter( " \t\r\b\f\013", LEXWS ); ! 24767: lxmask['.'+1] |= LEXDOT; ! 24768: ! 24769: /* make lxcp point to appropriate lxdope entry for each character */ ! 24770: ! 24771: /* initialize error entries */ ! 24772: ! 24773: for( i= 0; i<=CSSZ; ++i ) lxcp[i] = lxdope; ! 24774: ! 24775: /* make unique entries */ ! 24776: ! 24777: for( p=lxdope; ; ++p ) { ! 24778: lxcp[p->lxch+1] = p; ! 24779: if( p->lxch < 0 ) break; ! 24780: } ! 24781: ! 24782: /* handle letters, digits, and whitespace */ ! 24783: /* by convention, first, second, and third places */ ! 24784: ! 24785: cp = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; ! 24786: while( *cp ) lxcp[*cp++ + 1] = &lxdope[1]; ! 24787: cp = "123456789"; ! 24788: while( *cp ) lxcp[*cp++ + 1] = &lxdope[2]; ! 24789: cp = "\t\b\r\f\013"; ! 24790: while( *cp ) lxcp[*cp++ + 1] = &lxdope[3]; ! 24791: ! 24792: file_name[0] = src_file_name; ! 24793: // set both curloc and tloc so curloc is valid at program startup ! 24794: // curloc.file = tloc.file = 0; ! 24795: curloc.line = tloc.line = 1; ! 24796: ! 24797: ktbl_init(); ! 24798: lex_clear(); ! 24799: saved = lxtitle(); ! 24800: } ! 24801: ! 24802: void lex_clear() ! 24803: { ! 24804: // delete extra buffers: ! 24805: buf* p = bufhead; ! 24806: bufhead = 0; ! 24807: //if (p) { ! 24808: //fprintf(stderr,"lex_clear\n"); ! 24809: //bufs=0; ! 24810: //} ! 24811: while (p) { ! 24812: buf* pp = p; ! 24813: p = p->next; ! 24814: pp->next = freebuf; ! 24815: freebuf = pp; ! 24816: } ! 24817: ! 24818: // re-set to static buffer: ! 24819: txtstart = txtfree = inbuf; ! 24820: txtmax = &inbuf[FIRSTCHUNK/*TBUFSZ*/-1]; ! 24821: } ! 24822: ! 24823: int int_val(char hex) ! 24824: { ! 24825: switch (hex) { ! 24826: case '0': case '1': case '2': case '3': case '4': ! 24827: case '5': case '6': case '7': case '8': case '9': ! 24828: return hex-'0'; ! 24829: case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': ! 24830: return hex-'a'+10; ! 24831: case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': ! 24832: return hex-'A'+10; ! 24833: } ! 24834: } ! 24835: ! 24836: void hex_to_oct() ! 24837: /* ! 24838: \x has been seen on input (in char const or string) and \ printed ! 24839: read the following hexadecimal integer and replace it with an octal ! 24840: */ ! 24841: { ! 24842: int i = 0; ! 24843: int c; ! 24844: get(c); ! 24845: if (lxmask[c+1] & LEXHEX) { ! 24846: i = int_val(c); ! 24847: get(c); // try for two ! 24848: if (lxmask[c+1] & LEXHEX) { ! 24849: i = (i<<4) + int_val(c); ! 24850: get(c); // try for three ! 24851: if (lxmask[c+1] & LEXHEX) ! 24852: i = (i<<4) + int_val(c); ! 24853: else ! 24854: unget(c); ! 24855: } ! 24856: else ! 24857: unget(c); ! 24858: } ! 24859: else { ! 24860: error("hexadecimal digitE after \\x"); ! 24861: unget(c); ! 24862: } ! 24863: ! 24864: // if (0377 < i) error('l',"hexadecimal constant too large"); ! 24865: i &= 0377; ! 24866: ! 24867: pch(('0'+(i>>6))); ! 24868: pch(('0'+((i&070)>>3))); ! 24869: pch(('0'+(i&7))); ! 24870: } ! 24871: ! 24872: ! 24873: char * chconst() ! 24874: /* ! 24875: read a character constant into inbuf ! 24876: */ ! 24877: { ! 24878: register c; ! 24879: int nch = 0; ! 24880: ! 24881: pch('\''); ! 24882: ! 24883: for(;;) { ! 24884: char* p; ! 24885: char cc = 0; ! 24886: ! 24887: switch (get(c)) { ! 24888: case '\'': ! 24889: goto ex; ! 24890: case EOF: ! 24891: error("eof in char constant"); ! 24892: goto ex; ! 24893: case '\n': ! 24894: error("newline in char constant"); ! 24895: goto ex; ! 24896: case '\\': ! 24897: if (SZ_INT == nch++) error('l',"char constant too long"); ! 24898: pch(c); ! 24899: switch (get(c)){ ! 24900: case '\n': ! 24901: ++tloc.line; ! 24902: default: ! 24903: pch(c); ! 24904: break; ! 24905: case '4': case '5': case '6': case '7': // octal ! 24906: p = txtfree; ! 24907: cc = c-4; ! 24908: case '0': case '1': case '2': case '3': ! 24909: pch(c); ! 24910: get(c); /* try for 2 */ ! 24911: if( lxmask[c+1] & LEXDIG && c<'8'){ ! 24912: pch(c); ! 24913: get(c); /* try for 3 */ ! 24914: if (lxmask[c+1] & LEXDIG && c<'8') { ! 24915: if (cc) *p = cc; // zap high bit ! 24916: pch(c); ! 24917: } ! 24918: else ! 24919: unget(c); ! 24920: } ! 24921: else ! 24922: unget(c); ! 24923: break; ! 24924: case 'x': // hexadecimal ! 24925: hex_to_oct(); ! 24926: break; ! 24927: }; ! 24928: break; ! 24929: default: ! 24930: if (SZ_INT == nch++) error('l',"char constant too long"); ! 24931: pch(c); ! 24932: } ! 24933: } ! 24934: ex: ! 24935: if(nch==0) ! 24936: error("empty char constant"); ! 24937: pch('\''); ! 24938: pch('\0'); ! 24939: return txtstart; ! 24940: } ! 24941: ! 24942: void lxcom() ! 24943: /* process a "block comment" */ ! 24944: { ! 24945: register c; ! 24946: ! 24947: for(;;) ! 24948: switch (get(c)) { ! 24949: case EOF: ! 24950: error('w',"eof in comment"); ! 24951: return; ! 24952: case '\n': ! 24953: tloc.line++; ! 24954: // Nline++; ! 24955: break; ! 24956: case '*': ! 24957: if (get(c) == '/') return; ! 24958: unget(c); ! 24959: break; ! 24960: case '/': ! 24961: if (get(c) == '*') error('w',"``/*'' in comment"); ! 24962: unget(c); ! 24963: break; ! 24964: } ! 24965: } ! 24966: ! 24967: ! 24968: void linecom() ! 24969: // process a "line comment" ! 24970: { ! 24971: register c; ! 24972: ! 24973: get(c); ! 24974: #ifdef DBG ! 24975: if ( c=='@' && get(c)=='!' ) { ! 24976: while ( get(c) != '\n' && c != EOF ) pch(c); ! 24977: pch('\0'); ! 24978: process_debug_flags(txtstart); ! 24979: del_txt(); ! 24980: } ! 24981: #endif ! 24982: for(;;get(c)) ! 24983: switch (c) { ! 24984: case EOF: ! 24985: error('w',"eof in comment"); ! 24986: return; ! 24987: case '\n': ! 24988: tloc.line++; ! 24989: // Nline++; ! 24990: saved = lxtitle(); ! 24991: return; ! 24992: } ! 24993: } ! 24994: ! 24995: char eat_whitespace() ! 24996: { ! 24997: ! 24998: for(;;) { ! 24999: register c = get(c); ! 25000: lx: ! 25001: ! 25002: switch (c) { ! 25003: case EOF: ! 25004: error('w',"unexpected comment"); ! 25005: return EOF; ! 25006: case '/': ! 25007: switch (get(c)) { ! 25008: case '*': ! 25009: lxcom(); ! 25010: break; ! 25011: case '/': ! 25012: linecom(); ! 25013: break; ! 25014: default: ! 25015: unget(c); ! 25016: return '/'; ! 25017: } ! 25018: break; ! 25019: case '\n': ! 25020: ++tloc.line; ! 25021: c = lxtitle(); ! 25022: goto lx; ! 25023: case ' ': ! 25024: case '\t': ! 25025: break; ! 25026: default: ! 25027: return c; ! 25028: } ! 25029: } ! 25030: } ! 25031: ! 25032: void get_string() ! 25033: { ! 25034: int lxchar; ! 25035: ! 25036: for(;;) ! 25037: switch (get(lxchar)) { ! 25038: case '\\': ! 25039: pch('\\'); ! 25040: switch (get(lxchar)){ ! 25041: case '\n': ! 25042: ++tloc.line; ! 25043: default: ! 25044: pch(lxchar); ! 25045: break; ! 25046: case 'x': // hexadecimal ! 25047: hex_to_oct(); ! 25048: break; ! 25049: }; ! 25050: break; ! 25051: case '"': ! 25052: { char* p = txtstart; // eat_whitespace() moves txtstart ! 25053: if ((lxchar = eat_whitespace()) == '"') { ! 25054: // string catenation, break with ! 25055: // newline to avoid merging characters ! 25056: // (e.g. "\xAB" "C") ! 25057: pch('\\'); ! 25058: pch('\n'); ! 25059: ! 25060: continue; // eat '\"' and carry on ! 25061: }; ! 25062: ! 25063: txtstart = p; ! 25064: unget(lxchar); ! 25065: pch(0); ! 25066: return; ! 25067: } ! 25068: case '\n': ! 25069: error("newline in string"); ! 25070: pch(0); ! 25071: return; ! 25072: case EOF: ! 25073: error("eof in string"); ! 25074: pch(0); ! 25075: return; ! 25076: default: ! 25077: pch(lxchar); ! 25078: } ! 25079: } ! 25080: ! 25081: TOK tlex() ! 25082: { ! 25083: TOK ret; ! 25084: Pname n; ! 25085: ! 25086: // Ntoken++; ! 25087: ! 25088: for(;;) { ! 25089: register lxchar; ! 25090: register struct LXDOPE *p; ! 25091: ! 25092: start_txt(); ! 25093: ! 25094: if (saved) { ! 25095: lxchar = saved; ! 25096: saved = 0; ! 25097: } ! 25098: else ! 25099: get(lxchar); ! 25100: ! 25101: if (lxchar+1 >= CSSZ ) ! 25102: error( "illegal input character encountered: %d", lxchar ); ! 25103: ! 25104: switch( (p=lxcp[lxchar+1])->lxact ){ ! 25105: ! 25106: case A_1C: // eat up a single character, and return an opcode ! 25107: reti(p->lxtok,p->lxtok); ! 25108: ! 25109: case A_EOF: ! 25110: if (p_level || b_level+lcount) ! 25111: error("'%s' missing at end of input",(b_level+lcount) ? "}" : ")"); ! 25112: ! 25113: reti(EOFTOK,0); ! 25114: ! 25115: case A_SHARP: ! 25116: // cope with header file not ended with '\n' ! 25117: unget('#'); ! 25118: saved = lxtitle(); ! 25119: continue; ! 25120: ! 25121: case A_ERR: ! 25122: { if (' '<=lxchar && lxchar<='~') // ASCII printable ! 25123: error("illegal character '%c' (ignored)",lxchar); ! 25124: else ! 25125: error("illegal character '0%o' (ignored)",lxchar); ! 25126: continue; ! 25127: } ! 25128: ! 25129: case A_DOLL: ! 25130: { // lex a name of the for $id for template tree formals ! 25131: Pname fn ; ! 25132: lxget( lxchar, LEXLET|LEXDIG ) ; ! 25133: ! 25134: if (!templp->in_progress || !txtstart[1]) { ! 25135: // no name string immediately follows, treat it ! 25136: // like an illegal character ! 25137: error("illegal character '0%o' (ignored)",lxchar); ! 25138: continue; ! 25139: } ! 25140: ! 25141: txtstart++ ; ! 25142: if(fn=templ_compilation::tree_parameter(txtstart)) { ! 25143: switch (fn->n_template_arg) { ! 25144: case template_expr_tree_formal: ! 25145: // retain the $ in the name ! 25146: retn(ID, strdup(--txtstart)) ; ! 25147: ! 25148: case template_stmt_tree_formal: ! 25149: retn(SM_PARAM, fn) ; ! 25150: } ! 25151: } ! 25152: error("%s wasn't a statement or expression formal", txtstart); ! 25153: rets(ID, copy_if_need_be(txtstart)); ! 25154: } ! 25155: ! 25156: case A_LET: // collect an identifier and check for keyword ! 25157: { ! 25158: char ll; ! 25159: switch (ll = lxchar) { ! 25160: // case 'l': ! 25161: case 'L': ! 25162: switch (get(lxchar)) { ! 25163: case '\'': ! 25164: error('s',"wide character constant"); ! 25165: unget(lxchar); ! 25166: continue; ! 25167: case '"': ! 25168: error('s',"wide character string"); ! 25169: unget(lxchar); ! 25170: continue; ! 25171: } ! 25172: unget(lxchar); ! 25173: lxchar = ll; ! 25174: } ! 25175: } ! 25176: ! 25177: lxget( lxchar, LEXLET|LEXDIG ); ! 25178: /* look for a keyword or a global type */ ! 25179: if ((n = keyword_table->look(txtstart,0)) /* keyword */ ! 25180: || (n = ktbl->look(txtstart, 0))) /* local type */ ! 25181: { ! 25182: TOK x; ! 25183: del_txt(); ! 25184: switch (x=n->base) { ! 25185: case TNAME: ! 25186: rets(ID,n->string); ! 25187: case LOC: ! 25188: retl(n->syn_class); ! 25189: case EXTERN: ! 25190: if ((lxchar = eat_whitespace()) == '\"') { ! 25191: // linkage directive ! 25192: get_string(); ! 25193: rets(LINKAGE,txtstart); ! 25194: } ! 25195: unget(lxchar); ! 25196: reti(TYPE,EXTERN); ! 25197: case CATCH: ! 25198: // case TEMPLATE: ! 25199: error('s',"%k",n->syn_class); ! 25200: continue; ! 25201: case TRY: ! 25202: { ! 25203: static int warn_try; ! 25204: if (!warn_try) { ! 25205: Pname n = keyword_table->look("try",0); ! 25206: n->n_key = DEFAULT; ! 25207: error('w',&tloc,"%k is a future reserved keyword",n->syn_class); ! 25208: warn_try++; ! 25209: } ! 25210: rets(ID,n->string); ! 25211: } ! 25212: default: ! 25213: reti(n->syn_class,x); ! 25214: } ! 25215: } ! 25216: // rets(ID,txtstart); ! 25217: rets(ID, copy_if_need_be(txtstart)) ; ! 25218: ! 25219: case A_DIG: ! 25220: ! 25221: ret = ICON; ! 25222: ! 25223: if (lxchar=='0') { ! 25224: int pkchar; ! 25225: get(pkchar); ! 25226: if(pkchar=='x' || pkchar=='X') { // hex ! 25227: pch(lxchar); ! 25228: lxget(pkchar,LEXHEX); ! 25229: txtfree--; ! 25230: if (txtfree-txtstart<3) // minimum "0Xd\0" ! 25231: error("hex digitX after \"0x\""); ! 25232: get(lxchar); ! 25233: goto getsuffix; ! 25234: } ! 25235: unget(pkchar); ! 25236: } ! 25237: ! 25238: lxget(lxchar,LEXDIG); ! 25239: txtfree--; ! 25240: ! 25241: if (get(lxchar) == '.') { ! 25242: getfp: ! 25243: lxget('.', LEXDIG ); ! 25244: txtfree--; ! 25245: ret = FCON; ! 25246: get(lxchar); ! 25247: }; ! 25248: ! 25249: if (lxchar=='e' || lxchar=='E') { ! 25250: pch(lxchar); ! 25251: get(lxchar); ! 25252: if(lxchar=='-' || lxchar=='+') { ! 25253: pch(lxchar); ! 25254: get(lxchar); ! 25255: } ! 25256: if (lxmask[lxchar+1] & LEXDIG) { ! 25257: lxget( lxchar, LEXDIG ); ! 25258: txtfree--; ! 25259: get(lxchar); ! 25260: } ! 25261: else ! 25262: error("missing exponent digits?"); ! 25263: ret = FCON; ! 25264: }; ! 25265: ! 25266: if(*txtstart=='0' && ret==ICON) { ! 25267: char *bch = txtstart; ! 25268: while (++bch <= txtfree) { ! 25269: if(*bch=='8' || *bch=='9') ! 25270: error("%c used as octal digit",*bch); ! 25271: } ! 25272: } ! 25273: ! 25274: getsuffix: ! 25275: switch (lxchar) { ! 25276: case 'f': ! 25277: case 'F': ! 25278: if (ret==ICON) ! 25279: error("%c suffix for integer constant",lxchar); ! 25280: else ! 25281: pch(lxchar); ! 25282: break; ! 25283: case 'u': ! 25284: case 'U': ! 25285: if (ret==FCON) { ! 25286: error("%c suffix for floating constant",lxchar); ! 25287: break; ! 25288: } ! 25289: pch(lxchar); ! 25290: switch(get(lxchar)) { ! 25291: case 'l': ! 25292: case 'L': ! 25293: pch(lxchar); ! 25294: break; ! 25295: default: ! 25296: saved=lxchar; ! 25297: break; ! 25298: } ! 25299: break; ! 25300: case 'l': ! 25301: case 'L': ! 25302: pch(lxchar); ! 25303: if (ret==FCON) { ! 25304: break; ! 25305: } ! 25306: switch(get(lxchar)) { ! 25307: case 'u': ! 25308: case 'U': ! 25309: pch(lxchar); ! 25310: break; ! 25311: default: ! 25312: saved=lxchar; ! 25313: break; ! 25314: } ! 25315: break; ! 25316: default: ! 25317: saved = lxchar; ! 25318: break; ! 25319: }; ! 25320: ! 25321: if(*txtstart=='0' && txtfree-txtstart==1) ! 25322: reti(ZERO,0); // plain zero ! 25323: ! 25324: pch(0); ! 25325: rets(ret,txtstart); ! 25326: ! 25327: ! 25328: case A_DOT: ! 25329: switch (get(lxchar)) { ! 25330: case '.': // look for ellipsis ! 25331: if (get(lxchar) != '.') { ! 25332: error("token .. ?"); ! 25333: saved = lxchar; ! 25334: } ! 25335: reti(ELLIPSIS,0); ! 25336: case '*': ! 25337: reti (REFMUL,DOT); ! 25338: } ! 25339: ! 25340: if (lxmask[lxchar+1] & LEXDIG){// look for floating constant ! 25341: unget(lxchar); ! 25342: goto getfp; ! 25343: } ! 25344: saved = lxchar; ! 25345: reti(DOT,0); ! 25346: ! 25347: case A_STR: ! 25348: /* save string constant in buffer */ ! 25349: get_string(); ! 25350: rets(STRING,txtstart); ! 25351: ! 25352: case A_CC: ! 25353: /* character constant */ ! 25354: rets(CCON,chconst()); ! 25355: ! 25356: case A_BCD: ! 25357: { ! 25358: register i; ! 25359: int j; ! 25360: ! 25361: pch('`'); ! 25362: ! 25363: for (i=0; i<7; ++i) { ! 25364: pch(get(j)); ! 25365: if (j == '`' ) break; ! 25366: } ! 25367: pch(0); ! 25368: if (6<i) ! 25369: error('l',"bcd constant exceeds 6 characters" ); ! 25370: rets(CCON,txtstart); ! 25371: } ! 25372: ! 25373: case A_SL: /* / */ ! 25374: switch (get(lxchar)) { ! 25375: case '*': ! 25376: lxcom(); ! 25377: break; ! 25378: case '/': ! 25379: linecom(); ! 25380: break; ! 25381: case '=': ! 25382: reti(ASOP,ASDIV); ! 25383: default: ! 25384: saved = lxchar; ! 25385: reti(DIVOP,DIV); ! 25386: } ! 25387: ! 25388: case A_WS: ! 25389: continue; ! 25390: ! 25391: case A_NL: ! 25392: ++tloc.line; ! 25393: // Nline++; ! 25394: saved = lxtitle(); ! 25395: continue; ! 25396: ! 25397: case A_LC: ! 25398: if (BLMAX <= b_level++) { ! 25399: error('l',"blocks too deeply nested"); ! 25400: ext(3); ! 25401: } ! 25402: retl(LC); ! 25403: ! 25404: case A_RC: ! 25405: if (lcount+b_level-- <= 0) { ! 25406: error("unexpected '}'"); ! 25407: b_level = 0; ! 25408: } ! 25409: retl(RC); ! 25410: ! 25411: case A_L: ! 25412: p_level++; ! 25413: reti(LP,0); ! 25414: ! 25415: case A_R: ! 25416: if (p_level-- <= 0) { ! 25417: error("unexpected ')'"); ! 25418: p_level = 0; ! 25419: } ! 25420: reti(RP,0); ! 25421: ! 25422: case A_ASS: ! 25423: switch (get(lxchar)) { ! 25424: case '=': ! 25425: reti(EQUOP,EQ); ! 25426: default: ! 25427: saved = lxchar; ! 25428: reti(ASSIGN,ASSIGN); ! 25429: } ! 25430: ! 25431: case A_COL: ! 25432: switch (get(lxchar)) { ! 25433: case ':': ! 25434: reti(MEM,0); ! 25435: case '=': ! 25436: error("':=' is not a c++ operator"); ! 25437: reti(ASSIGN,ASSIGN); ! 25438: default: ! 25439: saved = lxchar; ! 25440: reti(COLON,COLON); ! 25441: } ! 25442: case A_NOT: ! 25443: switch (get(lxchar)) { ! 25444: case '=': ! 25445: reti(EQUOP,NE); ! 25446: default: ! 25447: saved = lxchar; ! 25448: reti(NOT,NOT); ! 25449: } ! 25450: case A_GT: ! 25451: switch(get(lxchar)) { ! 25452: case '>': ! 25453: switch (get(lxchar)) { ! 25454: case '=': ! 25455: reti(ASOP,ASRS); ! 25456: break; ! 25457: default: ! 25458: saved = lxchar; ! 25459: reti(SHIFTOP,RS); ! 25460: } ! 25461: case '=': ! 25462: reti(RELOP,GE); ! 25463: default: ! 25464: saved = lxchar; ! 25465: reti(GT,GT); ! 25466: } ! 25467: case A_LT: ! 25468: switch (get(lxchar)) { ! 25469: case '<': ! 25470: switch (get(lxchar)) { ! 25471: case '=': ! 25472: reti(ASOP,ASLS); ! 25473: default: ! 25474: saved = lxchar; ! 25475: reti(SHIFTOP,LS); ! 25476: } ! 25477: case '=': ! 25478: reti(RELOP,LE); ! 25479: default: ! 25480: saved = lxchar; ! 25481: reti(LT,LT); ! 25482: } ! 25483: case A_AND: ! 25484: switch (get(lxchar)) { ! 25485: case '&': ! 25486: reti(ANDAND,ANDAND); ! 25487: case '=': ! 25488: reti(ASOP,ASAND); ! 25489: default: ! 25490: saved = lxchar; ! 25491: reti(AND,AND); ! 25492: } ! 25493: case A_OR: ! 25494: switch (get(lxchar)) { ! 25495: case '|': ! 25496: reti(OROR,OROR); ! 25497: case '=': ! 25498: reti(ASOP,ASOR); ! 25499: default: ! 25500: saved = lxchar; ! 25501: reti(OR,OR); ! 25502: } ! 25503: case A_ER: ! 25504: switch (get(lxchar)) { ! 25505: case '=': ! 25506: reti(ASOP,ASER); ! 25507: default: ! 25508: saved = lxchar; ! 25509: reti(ER,ER); ! 25510: } ! 25511: case A_PL: ! 25512: switch (get(lxchar)) { ! 25513: case '=': ! 25514: reti(ASOP,ASPLUS); ! 25515: case '+': ! 25516: reti(ICOP,INCR); ! 25517: default: ! 25518: saved = lxchar; ! 25519: reti(PLUS,PLUS); ! 25520: } ! 25521: case A_MIN: ! 25522: switch (get(lxchar)) { ! 25523: case '=': ! 25524: reti(ASOP,ASMINUS); ! 25525: case '-': ! 25526: reti(ICOP,DECR); ! 25527: case '>': ! 25528: if (get(lxchar) == '*') ! 25529: {reti(REFMUL,REF);} ! 25530: else ! 25531: saved = lxchar; ! 25532: reti(REF,REF); ! 25533: default: ! 25534: saved = lxchar; ! 25535: reti(MINUS,MINUS); ! 25536: } ! 25537: case A_MUL: ! 25538: switch (get(lxchar)) { ! 25539: case '=': ! 25540: reti(ASOP,ASMUL); ! 25541: case '/': ! 25542: error('w',"*/ not as end of comment"); ! 25543: default: ! 25544: saved = lxchar; ! 25545: reti(MUL,MUL); ! 25546: } ! 25547: case A_MOD: ! 25548: switch (get(lxchar)) { ! 25549: case '=': ! 25550: reti(ASOP,ASMOD); ! 25551: default: ! 25552: saved = lxchar; ! 25553: reti(DIVOP,MOD); ! 25554: } ! 25555: default: ! 25556: {error('i',"lex act==%d getc()->%d",p,lxchar);} ! 25557: ! 25558: } ! 25559: ! 25560: error('i',"lex, main switch"); ! 25561: } ! 25562: ! 25563: } ! 25564: ! 25565: int lxtitle() ! 25566: /* ! 25567: called after a newline; set linenumber and file name ! 25568: */ ! 25569: { ! 25570: register c; ! 25571: ! 25572: for(;;) ! 25573: switch ( get(c) ) { ! 25574: default: // e.g. not '\n', not '#' ! 25575: return c; ! 25576: case '\n': ! 25577: tloc.line++; ! 25578: // Nline++; ! 25579: ll: ! 25580: break; ! 25581: case '#': /* # lineno "filename" */ ! 25582: { int cl = tloc.line; ! 25583: tloc.line = 0; ! 25584: for(;;) ! 25585: switch (get(c)) { ! 25586: case '"': ! 25587: start_txt(); ! 25588: for(;;) ! 25589: switch (get(c)) { ! 25590: case '"': ! 25591: pch('\0'); ! 25592: ! 25593: while (get(c) != '\n') ; // skip to eol.. ignore anything more ! 25594: ! 25595: if (*txtstart) { // stack file name ! 25596: char* fn; ! 25597: if (tcurr_file == 0){ ! 25598: if (( fn = file_name[0]) ! 25599: && (strcmp(txtstart,fn)!=0)){ // 1st include ! 25600: if (MAXFILE*4<++Nfile) error('i',"fileN buffer overflow"); ! 25601: if (MAXFILE<++tcurr_file) error('i',"fileN stack overflow"); ! 25602: file_stack[tcurr_file] = Nfile; ! 25603: ! 25604: char* p1 = new char[txtfree-txtstart]; ! 25605: (void) strcpy(p1,txtstart); ! 25606: file_name[Nfile] = p1; ! 25607: // Nstr++; ! 25608: } ! 25609: else { //&& line is dummy #line "input.c" ! 25610: // ignore ! 25611: } ! 25612: //&& dead, dead, dead goto push; ! 25613: } ! 25614: else if ( (fn=file_name[file_stack[tcurr_file]]) ! 25615: && (strcmp(txtstart,fn)==0) ) { ! 25616: //new line, same file: ignore ! 25617: } ! 25618: else if ( (fn=file_name[file_stack[tcurr_file-1]]) ! 25619: && (strcmp(txtstart,fn)==0) ) { ! 25620: // previous file: pop ! 25621: tcurr_file--; ! 25622: } ! 25623: else { // new file name: push ! 25624: //&& push: ! 25625: if (MAXFILE*4<Nfile++) error('i',"fileN buffer overflow"); ! 25626: if (MAXFILE<tcurr_file++) error('i',"fileN stack overflow"); ! 25627: file_stack[tcurr_file] = Nfile; ! 25628: char* p = new char[txtfree-txtstart]; ! 25629: (void) strcpy(p,txtstart); ! 25630: file_name[Nfile] = p; ! 25631: // Nstr++; ! 25632: } ! 25633: } ! 25634: else { // no name .. back to the original .c file: "" ! 25635: tcurr_file = 0; ! 25636: } ! 25637: del_txt(); ! 25638: tloc.file = file_stack[tcurr_file]; ! 25639: goto ll; ! 25640: case '\n': ! 25641: error("unexpected end of line on '# line'"); ! 25642: default: ! 25643: pch(c); ! 25644: } ! 25645: case ' ': ! 25646: break; ! 25647: ! 25648: case '0': ! 25649: case '1': ! 25650: case '2': ! 25651: case '3': ! 25652: case '4': ! 25653: case '5': ! 25654: case '6': ! 25655: case '7': ! 25656: case '8': ! 25657: case '9': ! 25658: tloc.line = tloc.line*10+c-'0'; ! 25659: break; ! 25660: ! 25661: case 'l': // look for "#line ..." and then ignore "line" ! 25662: if (get(c)=='i' && get(c)=='n' && get(c)=='e') break; ! 25663: case '\n': ! 25664: tloc.putline(); ! 25665: goto ll; ! 25666: ! 25667: default: // pass #rubbish through ! 25668: tloc.line = cl; ! 25669: pch('#'); ! 25670: pch(c); ! 25671: while (get(c) != '\n') pch(c); ! 25672: pch('\0'); ! 25673: fprintf(out_file,"\n%s\n",txtstart); ! 25674: start_txt(); ! 25675: tloc.line++; ! 25676: // Nline++; ! 25677: goto ll; ! 25678: } ! 25679: } ! 25680: } ! 25681: } ! 25682: 0707071010112044351004440001630000160000010204200466055404600000700000046311main.c /*ident "@(#)ctrans:src/main.c 1.9" */ ! 25683: /*********************************************************************** ! 25684: ! 25685: C++ source for cfront, the C++ compiler front-end ! 25686: written in the computer science research center of Bell Labs ! 25687: ! 25688: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 25689: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 25690: ! 25691: main.c: ! 25692: ! 25693: Initialize global environment ! 25694: Read argument line ! 25695: Start compilation ! 25696: Clean up and exit ! 25697: ! 25698: **************************************************************************/ ! 25699: ! 25700: #ifdef __cplusplus ! 25701: #include <stdlib.h> ! 25702: #endif ! 25703: ! 25704: #include <ctype.h> ! 25705: #include <string.h> ! 25706: #include <libc.h> ! 25707: #include <osfcn.h> ! 25708: #include <fstream.h> ! 25709: #include "size.h" ! 25710: #include "cfront.h" ! 25711: #include "tree_dump.h" ! 25712: #include "template.h" ! 25713: #include "hash.h" ! 25714: ! 25715: char* prog_name = "<<AT&T C++ Translator <(3.0)(PT)> 08/08/90>>"; ! 25716: char* src_file_name = ""; ! 25717: char* line_format = "\n# %d \"%s\"\n"; ! 25718: ! 25719: int dump_tree; ! 25720: int tree_dump_brief = 0; ! 25721: dcn_arg dump_tree_arg; ! 25722: ! 25723: #ifdef unix ! 25724: #include <signal.h> ! 25725: ! 25726: static void core_dump(int = 0) ! 25727: { ! 25728: if (error_count) ! 25729: fprintf(stderr,"sorry, cannot recover from previous error\n"); ! 25730: else ! 25731: error('i',"bus error (or something nasty like that)"); ! 25732: ext(99); ! 25733: } ! 25734: #endif ! 25735: ! 25736: Plist isf_list; ! 25737: Pstmt st_ilist; ! 25738: Pstmt st_dlist; ! 25739: Ptable sti_tbl; ! 25740: Ptable std_tbl; ! 25741: Plist stat_mem_list; ! 25742: ! 25743: int vtbl_opt = -1; // how to deal with vtbls: ! 25744: // -1 static and defined ! 25745: // 0 external and supposed to be defined elsewhere ! 25746: // 1 external and defined ! 25747: int debug_opt; ! 25748: int gplus_opt; // -g to cc, overrides print optimization ! 25749: int ansi_opt; ! 25750: int strict_opt; // disallow features from the anachronism section ! 25751: // of the manual ! 25752: int warning_opt; // produce more warnings if set ! 25753: bit stmtno = 0; ! 25754: ! 25755: extern simpl_init(); ! 25756: extern typ_init(); ! 25757: extern syn_init(); ! 25758: extern lex_init(); ! 25759: extern error_init(); ! 25760: ! 25761: char *st_name(char*); // generates names of static ctor, dtor callers, ptbl_vec ! 25762: Pname def_name; // first definition in file ! 25763: Pname pdef_name; // used with ptbl_vec if function is first definition ! 25764: ! 25765: int syn_count = 0; // to set conditional breakpoints to find particular expressions ! 25766: Hash *dumper_node_hash_table; ! 25767: ! 25768: void static ! 25769: clean_dumper_hash_table() { ! 25770: if(!dumper_node_hash_table) ! 25771: return; ! 25772: else { ! 25773: HashWalker hi(*dumper_node_hash_table); ! 25774: while(hi.valid ()) { ! 25775: struct node& n = *(struct node*) hi.key(); ! 25776: if(n.permanent == 0 || n.permanent == 3) /* flush deleted nodes */ ! 25777: dumper_node_hash_table->del(hi.key()); ! 25778: hi.advance(); ! 25779: } ! 25780: } ! 25781: } ! 25782: ! 25783: void run() ! 25784: /* ! 25785: run the appropriate stages ! 25786: */ ! 25787: { ! 25788: Pname n; ! 25789: templp = new templ_compilation; // canonical instance ! 25790: ! 25791: ! 25792: if(dump_tree) { ! 25793: dumper_node_hash_table = ! 25794: dump_tree_arg.nodes_seen_hash = new pointer_hash (10000); ! 25795: dump_tree_arg.verbose = dt_recursive_1; ! 25796: } ! 25797: ! 25798: while (n=syn()) { ! 25799: if (n == Pname(1)) continue; ! 25800: if (n->n_list) PERM(n->tp); ! 25801: ! 25802: DB( if(Rdebug>=1) error('d',"run: syn(): '%s'", n->string);); ! 25803: templp->instantiate_ref_templ(); ! 25804: ! 25805: for (Pname nx, nn=n; nn; nn=nx) { ! 25806: Pname rr; ! 25807: ++syn_count; ! 25808: nx = nn->n_list; ! 25809: nn->n_list = 0; ! 25810: ! 25811: DB( if(Rdebug>=1) error('d',"run: dcl(): %n, base: %k",nn,nn->base);); ! 25812: ! 25813: if ((rr=nn->dcl(gtbl,EXTERN))==0 ! 25814: || nn->base==0 ! 25815: || error_count) continue; ! 25816: ! 25817: DB( if(Rdebug>=1) error('d',"run: simpl(): %n",nn);); ! 25818: ! 25819: nn->simpl(); ! 25820: ! 25821: if (error_count) { ! 25822: if(dump_tree) { ! 25823: display_cfront_node (dump_tree_arg, nn); ! 25824: *dump_tree_arg.output_stream << "---------------------------\n\n"; ! 25825: } ! 25826: continue; ! 25827: } ! 25828: ! 25829: DB( if(Rdebug>=1) error('d',"run:print(): %n (%k) tp %t",nn,nn->base,nn->tp);); ! 25830: ! 25831: if (nn->base == TNAME) ! 25832: nn->dcl_print(0); ! 25833: else { ! 25834: Ptype t = nn->tp; ! 25835: llxx: ! 25836: switch (t->base) { ! 25837: case TYPE: ! 25838: t = Pbase(t)->b_name->tp; goto llxx; ! 25839: case CLASS: ! 25840: DB( if(Rdebug>=1) fprintf(stderr," -- class\n");); ! 25841: if (vtbl_opt==1 || gplus_opt) n->dcl_print(0); ! 25842: break; ! 25843: case ENUM: ! 25844: DB( if(Rdebug>=1) fprintf(stderr," -- enum\n");); ! 25845: Penum(n->tp)->dcl_print(0); ! 25846: break; ! 25847: case FCT: ! 25848: DB( if(Rdebug>=1) error('d'," -- fct%n inline %d body %d",nn,Pfct(t)->f_inline,Pfct(t)->body);); ! 25849: if (Pfct(t)->body==0 ! 25850: || (debug_opt==0 && Pfct(t)->f_inline && ((n->n_table!=gtbl) || strcmp(nn->string,"main"))) ! 25851: || Pfct(t)->f_imeasure && Pfct(t)->f_inline==0) break; ! 25852: DB( if(Rdebug>=1) error('d',"rr %n inline %d body %d",rr,Pfct(rr->tp)->f_inline,Pfct(rr->tp)->body);); ! 25853: rr->dcl_print(0); ! 25854: break; ! 25855: ! 25856: default: ! 25857: DB( if(Rdebug>=1) error('d'," -- %n tpbase: %k",nn,nn->tp->base);); ! 25858: // print class def, if appropriate ! 25859: // can't use tsizeof() since this may ! 25860: // print an error if class isn't defined ! 25861: { for(Ptype tx = t;;) { ! 25862: switch ( tx->base ) { ! 25863: case VEC: ! 25864: tx=Pvec(tx)->typ; ! 25865: continue; ! 25866: case TYPE: case COBJ: ! 25867: tx=Pbase(tx)->b_name->tp; ! 25868: continue; ! 25869: } ! 25870: Pclass cl = Pclass(tx); ! 25871: if ( cl->base == CLASS ! 25872: && (cl->defined&(DEFINED|SIMPLIFIED)) ! 25873: && cl->c_body==1 ) ! 25874: cl->dcl_print(0); ! 25875: break; ! 25876: } ! 25877: } ! 25878: nn->dcl_print(0); ! 25879: } ! 25880: } ! 25881: ! 25882: if(dump_tree) { ! 25883: display_cfront_node (dump_tree_arg, nn); ! 25884: *dump_tree_arg.output_stream << "---------------------------\n\n"; ! 25885: } ! 25886: ! 25887: if (error_count) continue; ! 25888: ! 25889: DB( if(Rdebug>=1) error('d',"run: cleanup");); ! 25890: switch (nn->tp->base) { // clean up ! 25891: default: ! 25892: { ! 25893: Pexpr i = nn->n_initializer; ! 25894: DB( if(Rdebug>=1) error('d',"default nn %n i %d",nn,i);); ! 25895: if (i && i!=Pexpr(1)) { ! 25896: DEL(i); ! 25897: nn->n_initializer = 0; ! 25898: if (def_name==0 && rr->n_scope != STATIC) { ! 25899: def_name = rr; ! 25900: if (pdef_name == 0) ptbl_init(0); ! 25901: } ! 25902: } ! 25903: break; ! 25904: } ! 25905: ! 25906: case FCT: ! 25907: { ! 25908: Pfct f = Pfct(nn->tp); ! 25909: DB( if(Rdebug>=1) error('d', "function nn: %n local_class: %d %d", nn, local_class, f->local_class );); ! 25910: if (f->body ! 25911: && f->f_inline==0 ! 25912: && f->f_imeasure==0) { ! 25913: if ( local_class = f->local_class ) { ! 25914: delete_local(); ! 25915: local_class = 0; ! 25916: } ! 25917: ! 25918: if (ansi_opt && f->f_this) { ! 25919: f->f_this->n_table = 0; ! 25920: for (Pname n=f->f_this->n_list; n; n=n->n_list) ! 25921: n->n_table = 0; ! 25922: } ! 25923: ! 25924: DEL(f->body); ! 25925: if (def_name==0) { ! 25926: def_name = rr; ! 25927: if (pdef_name == 0) ptbl_init(0); ! 25928: } ! 25929: } ! 25930: break; ! 25931: } ! 25932: ! 25933: case CLASS: ! 25934: { Pclass cl = Pclass(nn->tp); ! 25935: for (Pname px, p=cl->mem_list; p; p=px) { ! 25936: px = p->n_list; ! 25937: if (p->tp) { ! 25938: switch (p->tp->base) { ! 25939: case FCT: ! 25940: { Pfct f = (Pfct)p->tp; ! 25941: if (f->body) { ! 25942: if (f->f_inline==0 ! 25943: && f->f_imeasure==0) { ! 25944: if ( local_class = f->local_class ) { ! 25945: delete_local(); ! 25946: local_class = 0; ! 25947: } ! 25948: DEL(f->body); ! 25949: f->body = 0; ! 25950: } ! 25951: } ! 25952: } ! 25953: case CLASS: ! 25954: case ENUM: ! 25955: break; ! 25956: case COBJ: ! 25957: case EOBJ: ! 25958: DEL(p); ! 25959: break; ! 25960: default: ! 25961: delete p; ! 25962: } ! 25963: } else { ! 25964: delete p; ! 25965: } ! 25966: } // for ! 25967: cl->mem_list = 0; ! 25968: cl->permanent = 3; ! 25969: break; ! 25970: } ! 25971: } ! 25972: DEL(nn); ! 25973: } ! 25974: lex_clear(); ! 25975: if (dump_tree) clean_dumper_hash_table(); ! 25976: } ! 25977: templp->end_of_compilation() ; ! 25978: ! 25979: switch (no_of_undcl) { ! 25980: case 1: {error('w',"undeclaredF%n called",undcl);} ! 25981: case 0: break; ! 25982: default: {error('w',"%d undeclaredFs called; for example%n",no_of_undcl,undcl);} ! 25983: } ! 25984: ! 25985: switch (no_of_badcall) { ! 25986: case 1: {error('w',"%n declaredWoutAs calledWAs",badcall);} ! 25987: case 0: break; ! 25988: default: {error('w',"%d Fs declaredWoutAs calledWAs; for example%n",no_of_badcall,badcall);} ! 25989: } ! 25990: ! 25991: if (error_count) return; ! 25992: ! 25993: int i = 1; ! 25994: for (Pname m=gtbl->get_mem(i); m; m=gtbl->get_mem(++i)) { ! 25995: if (m->base==TNAME ! 25996: || m->n_sto==EXTERN ! 25997: || m->n_stclass == ENUM) continue; ! 25998: ! 25999: Ptype t = m->tp; ! 26000: if (t == 0) continue; ! 26001: switch (t->base) { ! 26002: case CLASS: ! 26003: case ENUM: ! 26004: case OVERLOAD: continue; ! 26005: case COBJ: ! 26006: //case ANON: ! 26007: case VEC: break; ! 26008: case FCT: ! 26009: if (Pfct(t)->f_inline || Pfct(t)->body==0) continue; ! 26010: } ! 26011: ! 26012: //error('d',&m->where,"%n %d %d %s",m,m->n_addr_taken,m->n_used,m->n_sto==STATIC?"static":""); ! 26013: //xxx doesn't check anon union members as their use bits are set differently ! 26014: if (m->n_addr_taken==0 ! 26015: && m->n_used==0 ! 26016: && m->n_sto == STATIC) { // (static or anon?) ! 26017: for(;;) { ! 26018: //error('d',&m->where," %t tconst(): %d",t,t->tconst()); ! 26019: if(t->base==TYPE) { ! 26020: if(t->tconst()) break; ! 26021: t=Pbase(t)->b_name->tp; ! 26022: } else if(t->base==VEC) { ! 26023: t=Pvec(t)->typ; ! 26024: } else { ! 26025: if ( t->tconst() == 0 ) { ! 26026: //error('d',"m%n tp%t t%t",m,m->tp,t); ! 26027: if ( t->base != COBJ ) ! 26028: error('w',&m->where,"%n defined but not used",m); ! 26029: else { Pclass cl; ! 26030: cl = Pclass(Pbase(t)->b_name->tp); ! 26031: if ( cl->has_ctor()==0 ) ! 26032: if ( cl->csu == ANON ) ! 26033: ; //error('w',&m->where,"anonymous union defined but not used"); ! 26034: else ! 26035: error('w',&m->where,"%n defined but not used",m); ! 26036: } ! 26037: } // if const ! 26038: break; ! 26039: } ! 26040: } // for ! 26041: } // if static and not used ! 26042: } ! 26043: ! 26044: Pname ctor = 0; ! 26045: Pname dtor = 0; ! 26046: --curloc.line; ! 26047: ! 26048: if (st_ilist) { // make an "init" function; ! 26049: // it calls all constructors for static objects ! 26050: DB( if(Rdebug>=1) error('d',"make sti"); ); ! 26051: Pname n = new name( st_name("__sti__") ); ! 26052: Pfct f = new fct(void_type,0,1); ! 26053: n->tp = f; ! 26054: f->body = new block(st_ilist->where,0,st_ilist); ! 26055: // f->body->s = st_ilist; ! 26056: f->body->memtbl = sti_tbl; ! 26057: n->n_sto = EXTERN; ! 26058: // assignments here are really initializations: ! 26059: ignore_const++; ! 26060: f->f_linkage = linkage_C; ! 26061: f->sign(); ! 26062: (void) n->dcl(gtbl,EXTERN); ! 26063: ignore_const--; ! 26064: n->simpl(); ! 26065: n->dcl_print(0); ! 26066: ctor = n; ! 26067: } ! 26068: ! 26069: if (st_dlist) { // make a "done" function; ! 26070: // it calls all destructors for static objects ! 26071: DB( if(Rdebug>=1) error('d',"make std"); ); ! 26072: Pname n = new name( st_name("__std__") ); ! 26073: Pfct f = new fct(void_type,0,1); ! 26074: n->tp = f; ! 26075: f->body = new block(st_dlist->where,0,st_dlist); ! 26076: // f->body->s = st_dlist; ! 26077: f->body->memtbl = std_tbl; ! 26078: n->n_sto = EXTERN; ! 26079: f->f_linkage = linkage_C; ! 26080: f->sign(); ! 26081: (void) n->dcl(gtbl,EXTERN); ! 26082: n->simpl(); ! 26083: n->dcl_print(0); ! 26084: dtor = n; ! 26085: } ! 26086: ! 26087: #ifdef PATCH ! 26088: /*For fast load: make a static "__link" */ ! 26089: if (ctor || dtor) ! 26090: { ! 26091: printf("static struct __linkl { struct __linkl * next;\n"); ! 26092: if ( ansi_opt ) ! 26093: printf("void (*ctor)(); void (*dtor)(); } __link = \n"); ! 26094: else ! 26095: printf("char (*ctor)(); char (*dtor)(); } __link = \n"); ! 26096: // printf("{ (struct __linkl *)0, %s, %s };\n", ! 26097: // ctor_name ? ctor_name : "0", ! 26098: // dtor_name ? dtor_name : "0"); ! 26099: putstring("{ (struct __linkl *)0, "); ! 26100: if (ctor) ctor->print(); else putch('0'); ! 26101: putch(','); ! 26102: if (dtor) dtor->print(); else putch('0'); ! 26103: putstring("};\n"); ! 26104: } ! 26105: #endif ! 26106: ! 26107: DB( if(Rdebug>=1) error( 'd', "run: vlist: %d", vlist ); ); ! 26108: do { ! 26109: for (vl* v = vlist; v; v = v->next) v->cl->really_print(v->vt); ! 26110: vlist = 0; ! 26111: ! 26112: for (Plist l=isf_list; l; l=l->l) { ! 26113: Pname n = l->f; ! 26114: Pfct f = Pfct(n->tp); ! 26115: DB( if(Rdebug>=1)error('d',"isf %n %t f %d addr %d",n,f,f,n->n_addr_taken); ); ! 26116: if (f->base == OVERLOAD) { ! 26117: n = Pgen(f)->fct_list->f; // first fct ! 26118: f = Pfct(n->tp); ! 26119: } ! 26120: ! 26121: if (debug_opt==0 && ! 26122: n->n_addr_taken) { ! 26123: f->f_inline = 0; ! 26124: if (n->n_dcl_printed<2) { ! 26125: if (warning_opt) ! 26126: error('w',"out-of-line copy of %n created",n); ! 26127: n->dcl_print(0); ! 26128: } ! 26129: } ! 26130: } ! 26131: } while (vlist); ! 26132: ! 26133: if (strict_opt == 0) { // define static members ! 26134: // patch for SysV VAX -g linkage botch ! 26135: for (Plist l=stat_mem_list; l; l=l->l) { ! 26136: Pname n = l->f; ! 26137: // error('d',"stat mem %n %d %d ",n,n->n_initializer,n->n_evaluated); ! 26138: if (n->n_initializer==0 && n->n_evaluated==0) { ! 26139: Ptype t = n->tp; ! 26140: n->n_sto = 0; ! 26141: Pname cn = t->is_cl_obj(); ! 26142: if (cn==0) cn = cl_obj_vec; ! 26143: if (cn) (void) t->tsizeof(); // be sure to print class ! 26144: if ((cn && Pclass(cn->tp)->has_ctor()) ! 26145: || t->is_ref()) ! 26146: ; // force explicit definition ! 26147: else ! 26148: n->dcl_print(0); ! 26149: } ! 26150: } ! 26151: } ! 26152: ! 26153: i = 1; ! 26154: for (Pname nm=ptbl->get_mem(i); nm; nm=ptbl->get_mem(++i)) { ! 26155: DB( if(Rdebug>=1) error('d',"ptbl anme %s string2 %s key:%k",nm->string==0?"???":nm->string2,nm->string2==0?"???":nm->string2,nm->n_key); ); ! 26156: if ( nm->n_key == 0 ) { // ptbl used in file, generate definition ! 26157: int str1 = (*src_file_name)?strlen(src_file_name)+2:0; // +2 for __ ! 26158: int str2 = strlen(nm->string2) - str1; ! 26159: char *ps = new char[ str2 + 1 ]; ! 26160: strncpy( ps, nm->string2, str2 ); // grab vtbl name ! 26161: ps[str2]='\0'; ! 26162: ps[2] = 'v'; ! 26163: fprintf(out_file,"extern struct __mptr %s[];\n",ps); ! 26164: // fprintf(out_file,"struct __mptr* %s = %s;\n",nm->string2,ps); ! 26165: ptbl_add_pair(nm->string2,ps); ! 26166: delete ps; ! 26167: } ! 26168: } ! 26169: ! 26170: ptbl_init(1); ! 26171: curloc.putline(); ! 26172: fprintf(out_file,"\n/* the end */\n"); ! 26173: } ! 26174: ! 26175: ! 26176: #ifdef DBG ! 26177: int Adebug = 0; ! 26178: int Ddebug = 0; ! 26179: int Edebug = 0; ! 26180: int Ldebug = 0; ! 26181: int Mdebug = 0; ! 26182: int Ndebug = 0; ! 26183: int Pdebug = 0; ! 26184: int Rdebug = 0; ! 26185: int Sdebug = 0; ! 26186: int Tdebug = 0; ! 26187: //Ydebug == yydebug initialized in y.tab.c ! 26188: void ! 26189: process_debug_flags( char* p ) ! 26190: { ! 26191: // arg to +Dxxx or debugging comments //@!xxx ! 26192: // format of xxx == sequence of any combination of ! 26193: // +flags -- increment flags (default) ! 26194: // -flags -- decrement flags ! 26195: // 0flags -- unset flags ! 26196: // where flags are single chars ! 26197: int incr = 1; ! 26198: char c; ! 26199: fprintf(stderr,"\n*** processing debugging flags '%s'\n",p); ! 26200: while ( c = *p++ ) { ! 26201: switch ( c ) { ! 26202: case '+': incr = 1; break; ! 26203: case '-': incr = -1; break; ! 26204: case '0': incr = 0; break; ! 26205: case ' ': break; ! 26206: // flags... ! 26207: case 'A': if(incr==0) Adebug=0; else Adebug+=incr; break; ! 26208: case 'D': if(incr==0) Ddebug=0; else Ddebug+=incr; break; ! 26209: case 'E': if(incr==0) Edebug=0; else Edebug+=incr; break; ! 26210: case 'L': if(incr==0) Ldebug=0; else Ldebug+=incr; break; ! 26211: case 'M': if(incr==0) Mdebug=0; else Mdebug+=incr; break; ! 26212: case 'N': if(incr==0) Ndebug=0; else Ndebug+=incr; break; ! 26213: case 'P': if(incr==0) Pdebug=0; else Pdebug+=incr; break; ! 26214: case 'R': if(incr==0) Rdebug=0; else Rdebug+=incr; break; ! 26215: case 'S': if(incr==0) Sdebug=0; else Sdebug+=incr; break; ! 26216: case 'T': if(incr==0) Tdebug=0; else Tdebug+=incr; break; ! 26217: case 'Y': if(incr==0) Ydebug=0; else Ydebug+=incr; break; ! 26218: default: error('w',"unknown debugging flag '%c'",c); ! 26219: } ! 26220: } ! 26221: } ! 26222: #endif /*DBG*/ ! 26223: ! 26224: int no_of_undcl, no_of_badcall; ! 26225: Pname undcl, badcall; ! 26226: ! 26227: void pt_option(char * ostr) ! 26228: { // options +O[BTo] for PT ! 26229: ostr ++; /* skip the O */ ! 26230: switch(*ostr) { ! 26231: default: ! 26232: fprintf(stderr, "cfront: argument syntax: invalidZizedTs option (+O[BTo]."); ! 26233: exit(11); ! 26234: case 'B': ! 26235: tree_dump_brief = 1; ! 26236: case 'T': ! 26237: dump_tree = 1; ! 26238: if(0 == *(ostr + 1) || strcmp (ostr, "T-") == 0) ! 26239: dump_tree_arg.output_stream = (ostream*)&cout; ! 26240: else { ! 26241: dump_tree_arg.output_stream ! 26242: = new ofstream (ostr+1, ios::out); ! 26243: if(dump_tree_arg.output_stream->fail()) { ! 26244: perror ("cfront"); ! 26245: fprintf (stderr, "Failed to open %s\n", ostr + 1); ! 26246: exit (11); ! 26247: } ! 26248: } ! 26249: break; ! 26250: case 'o': ! 26251: out_file = fopen (ostr+1, "w"); ! 26252: if(out_file == NULL) { ! 26253: perror ("cfront"); ! 26254: fprintf(stderr, "Failed to open %s\n", ostr+1); ! 26255: exit(11); ! 26256: } ! 26257: break; ! 26258: } ! 26259: } ! 26260: ! 26261: main(int argc, char* argv[]) ! 26262: /* ! 26263: read options, initialize, and run ! 26264: */ ! 26265: { ! 26266: register char * cp; ! 26267: char* afile = ""; ! 26268: #ifdef unix ! 26269: ! 26270: #ifdef COMPLETE_SIG_PF ! 26271: signal(SIGILL,core_dump); ! 26272: signal(SIGIOT,core_dump); ! 26273: signal(SIGEMT,core_dump); ! 26274: signal(SIGFPE,core_dump); ! 26275: signal(SIGBUS,core_dump); ! 26276: signal(SIGSEGV,core_dump); ! 26277: #else ! 26278: typedef void (*ST)(int ...); // trick to circumvent problems with old ! 26279: ST sick = ST(&signal); // (or C) versions <signal.h> ! 26280: (*sick)(SIGILL,core_dump); ! 26281: (*sick)(SIGIOT,core_dump); ! 26282: (*sick)(SIGEMT,core_dump); ! 26283: (*sick)(SIGFPE,core_dump); ! 26284: (*sick)(SIGBUS,core_dump); ! 26285: (*sick)(SIGSEGV,core_dump); ! 26286: ! 26287: #endif ! 26288: #endif ! 26289: ! 26290: // SUM: not needed ! 26291: // #ifdef apollo ! 26292: // set_sbrk_size(1000000); // resets free store size ! 26293: //#else ! 26294: #ifndef apollo ! 26295: //(void) malloc(0); // suppress cashing in V8 malloc ! 26296: #endif ! 26297: ! 26298: error_init(); ! 26299: ! 26300: for (int i=1; i<argc; ++i) { ! 26301: switch (*(cp=argv[i])) { ! 26302: case '+': ! 26303: while (*++cp) { ! 26304: switch(*cp) { ! 26305: case 'O': ! 26306: pt_option(cp); ! 26307: goto xx; ! 26308: case 'f': ! 26309: src_file_name = cp+1; ! 26310: goto xx; ! 26311: case 'x': // read cross compilation table ! 26312: if (read_align(afile = cp+1)) { ! 26313: fprintf(stderr,"bad size-table (option +x)\n"); ! 26314: exit(11); ! 26315: } ! 26316: goto xx; ! 26317: case 'e': ! 26318: switch (*++cp) { ! 26319: case '0': ! 26320: case '1': ! 26321: vtbl_opt = *cp-'0'; ! 26322: break; ! 26323: default: ! 26324: fprintf(stderr,"bad +e option\n"); ! 26325: exit(11); ! 26326: } ! 26327: break; ! 26328: case 'd': ! 26329: debug_opt = 1; ! 26330: break; ! 26331: case 'g': ! 26332: gplus_opt = 1; ! 26333: break; ! 26334: case 'D': ! 26335: #ifdef DBG ! 26336: process_debug_flags(++cp); ! 26337: #else ! 26338: error('w',"cfront not compiled for debugging -- +D%s ignored",++cp); ! 26339: #endif ! 26340: goto xx; ! 26341: case 'w': ! 26342: warning_opt = 1; ! 26343: break; ! 26344: case 'a': ! 26345: switch (*++cp) { ! 26346: case '0': ! 26347: case '1': ! 26348: ansi_opt = *cp-'0'; ! 26349: break; ! 26350: default: ! 26351: fprintf(stderr,"bad +a option\n"); ! 26352: exit(11); ! 26353: } ! 26354: break; ! 26355: case 'p': ! 26356: strict_opt = 1; ! 26357: break; ! 26358: case 'L': ! 26359: line_format = "\n#line %d \"%s\"\n"; ! 26360: break; ! 26361: default: ! 26362: fprintf(stderr,"%s: unexpected option: +%c ignored\n",prog_name,*cp); ! 26363: ! 26364: } ! 26365: } ! 26366: xx: ! 26367: break; ! 26368: default: ! 26369: fprintf(stderr,"%s: bad argument \"%s\"\n",prog_name,cp); ! 26370: exit(11); ! 26371: } ! 26372: } ! 26373: ! 26374: ! 26375: fprintf(out_file,line_format+1,1,src_file_name); // strips leading \n ! 26376: fprintf(out_file,"\n/* %s */\n",prog_name); ! 26377: if (*src_file_name) fprintf(out_file,"/* < %s > */\n",src_file_name); ! 26378: ! 26379: // if (Nspy) { ! 26380: // start_time = time(0); ! 26381: // print_align(afile); ! 26382: // } ! 26383: fflush(stderr); ! 26384: otbl_init(); ! 26385: lex_init(); ! 26386: syn_init(); ! 26387: typ_init(); ! 26388: simpl_init(); ! 26389: scan_started = 1; ! 26390: curloc.putline(); ! 26391: if ((BI_IN_BYTE==0) && (SZ_INT==0) && (SZ_WPTR==0)) ! 26392: error("no size/alignment values - use +x of provide #ifdef in size.h"); ! 26393: run(); ! 26394: if(dump_tree) { ! 26395: ostream_printf(*dump_tree_arg.output_stream, "------------ GTBL ------------\n\n"); ! 26396: display_cfront_node (dump_tree_arg, ktbl); ! 26397: ostream_printf(*dump_tree_arg.output_stream, "------------ KTBL ------------\n\n"); ! 26398: display_cfront_node (dump_tree_arg, ktbl); ! 26399: } ! 26400: ! 26401: // if (Nspy) { ! 26402: // stop_time = time(0); ! 26403: // spy(src_file_name); ! 26404: // } ! 26405: exit( (0<=error_count && error_count<127) ? error_count : 127); ! 26406: } ! 26407: ! 26408: char* st_name(char* pref) ! 26409: /* ! 26410: make name "pref|source_file_name|_" or "pref|source_file_name|_" ! 26411: where non alphanumeric characters are replaced with '_' ! 26412: and add def_name at end to ensure uniqueness ! 26413: */ ! 26414: { ! 26415: int prefl = strlen(pref); ! 26416: int strl = prefl + 2; // trailing '_' and 0 ! 26417: if (*src_file_name) strl += strlen(src_file_name); ! 26418: char* defs; ! 26419: int defl; ! 26420: if (def_name) { ! 26421: defs = def_name->string; ! 26422: defl = strlen(defs)+1; // '_' ! 26423: } ! 26424: else { ! 26425: defs = 0; ! 26426: defl = 0; ! 26427: } ! 26428: char* name = new char[strl+defl]; ! 26429: strcpy(name,pref); ! 26430: if (*src_file_name) strcpy(name+prefl,src_file_name); ! 26431: name[strl-2] = '_'; ! 26432: name[strl-1] = 0; ! 26433: // char *p = name; ! 26434: // while ( *++p ) if (!isalpha(*p) && !isdigit(*p)) *p = '_'; ! 26435: for (char* p = name; *p; p++) if (!isalpha(*p) && !isdigit(*p)) *p = '_'; ! 26436: if (defs) { ! 26437: strcpy(name+strl-1,defs); // after the '_' ! 26438: name[strl+defl-2] = '_'; ! 26439: name[strl+defl-1] = 0; ! 26440: } ! 26441: #ifdef DENSE ! 26442: void chop(char*); ! 26443: chop(name); ! 26444: #endif ! 26445: ! 26446: return name; ! 26447: } ! 26448: 0707071010112041141004440001630000160000010112640466055427400001100000007532makefile #ident "@(#)ctrans:src/makefile 1.3" ! 26449: ############################################################################### ! 26450: # Copyright (c) 1984 AT&T ! 26451: # All Rights Reserved ! 26452: # ! 26453: # THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T ! 26454: # ! 26455: # The copyright notice above does not evidence any ! 26456: # actual or intended publication of such source code. ! 26457: # ! 26458: ############################################################################### ! 26459: CC = CC ! 26460: ! 26461: #The ANSI_OUT option has been replaced by the +a1 and +a0 compilation options ! 26462: ! 26463: #for systems which only recognize identifiers of up to 31 characters ! 26464: #setting DENSE to -DDENSE causes cfront to generate internal names ! 26465: #of 31 characters or less ! 26466: DENSE= ! 26467: ! 26468: # The use of RETBUG is nolonger needed with version 2.0 and has been removed. ! 26469: # RETBUG was used in 1.* Translator versions to circumvent a C compiler bug. ! 26470: ! 26471: CCFLAGS=-O ! 26472: ! 26473: # top level makefile modifies the following ! 26474: MPMACRO = PATCH ! 26475: MPFILE = patch ! 26476: ! 26477: OFILES = alloc.o dcl.o dcl2.o dcl3.o dcl4.o del.o \ ! 26478: discrim.o doprint.o error.o expand.o \ ! 26479: expr.o expr2.o expr3.o find.o hash.o lalex.o lex.o main.o \ ! 26480: norm.o norm2.o print.o print2.o print_self.o repr.o simpl.o \ ! 26481: simpl2.o size.o table.o template.o tree_copy.o tree_dump.o \ ! 26482: tree_walk.o typ.o typ2.o y.tab.o ! 26483: ! 26484: cfront: $(OFILES) ! 26485: $(CC) -o cfront $(CCFLAGS) $(OFILES) ! 26486: ! 26487: $(OFILES): cfront.h token.h typedef.h ! 26488: ! 26489: y.tab.c: gram.y ! 26490: yacc gram.y ! 26491: ! 26492: alloc.o: alloc.c ! 26493: $(CC) $(CCFLAGS) -c alloc.c ! 26494: ! 26495: dcl.o: dcl.c size.h ! 26496: $(CC) $(CCFLAGS) -c dcl.c ! 26497: ! 26498: dcl2.o: dcl2.c size.h ! 26499: $(CC) $(CCFLAGS) -c dcl2.c ! 26500: ! 26501: dcl3.o: dcl3.c size.h ! 26502: $(CC) $(CCFLAGS) -c dcl3.c ! 26503: ! 26504: dcl4.o: dcl4.c size.h ! 26505: $(CC) $(CCFLAGS) -c dcl4.c ! 26506: ! 26507: del.o: del.c ! 26508: $(CC) $(CCFLAGS) -c del.c ! 26509: ! 26510: discrim.o: discrim.c cfront.h ! 26511: $(CC) $(CCFLAGS) -c discrim.c ! 26512: ! 26513: doprint.o: doprint.c ! 26514: $(CC) $(CCFLAGS) -c doprint.c ! 26515: ! 26516: error.o: error.c size.h ! 26517: $(CC) $(CCFLAGS) -c error.c ! 26518: ! 26519: expand.o: expand.c ! 26520: $(CC) $(CCFLAGS) -c expand.c ! 26521: ! 26522: expr.o: expr.c size.h ! 26523: $(CC) $(CCFLAGS) -c expr.c ! 26524: ! 26525: expr2.o: expr2.c size.h ! 26526: $(CC) $(CCFLAGS) -c expr2.c ! 26527: ! 26528: expr3.o: expr3.c size.h ! 26529: $(CC) $(CCFLAGS) -c expr3.c ! 26530: ! 26531: find.o: find.c ! 26532: $(CC) $(CCFLAGS) -c find.c ! 26533: ! 26534: hash.o: hash.c hash.h ! 26535: $(CC) $(CCFLAGS) -c hash.c ! 26536: ! 26537: lalex.o:lalex.c yystype.h tqueue.h ! 26538: $(CC) $(CCFLAGS) -c lalex.c ! 26539: ! 26540: lex.o: lex.c size.h tqueue.h yystype.h ! 26541: $(CC) $(CCFLAGS) -c lex.c ! 26542: ! 26543: # main depends on this makefile to force recompilation ! 26544: # when going from patch to munch ! 26545: main.o: main.c makefile ! 26546: $(CC) -D$(MPMACRO) $(DENSE) $(CCFLAGS) -c main.c ! 26547: ! 26548: norm.o: norm.c size.h ! 26549: $(CC) $(CCFLAGS) -c norm.c ! 26550: ! 26551: norm2.o: norm2.c size.h ! 26552: $(CC) $(CCFLAGS) -c norm2.c ! 26553: ! 26554: print.o: print.c ! 26555: $(CC) $(CCFLAGS) -c print.c ! 26556: ! 26557: print2.o: print2.c ! 26558: $(CC) $(DENSE) $(CCFLAGS) -c print2.c ! 26559: ! 26560: print_self.o: print_self.c ! 26561: $(CC) $(CCFLAGS) -c print_self.c ! 26562: ! 26563: repr.o: repr.c ! 26564: $(CC) $(CCFLAGS) -c repr.c ! 26565: ! 26566: simpl.o: simpl.c size.h ! 26567: $(CC) $(CCFLAGS) -c simpl.c ! 26568: ! 26569: simpl2.o: simpl2.c size.h ! 26570: $(CC) $(CCFLAGS) -c simpl2.c ! 26571: ! 26572: size.o: size.c size.h ! 26573: $(CC) $(CCFLAGS) -c size.c ! 26574: ! 26575: table.o: table.c ! 26576: $(CC) $(CCFLAGS) -c table.c ! 26577: ! 26578: template.o: template.c ! 26579: $(CC) $(CCFLAGS) -c template.c ! 26580: ! 26581: tree_copy.o: tree_copy.c ! 26582: $(CC) $(CCFLAGS) -c tree_copy.c ! 26583: ! 26584: tree_dump.o: tree_dump.c cfront.h ! 26585: $(CC) $(CCFLAGS) -c tree_dump.c ! 26586: ! 26587: tree_walk.o: tree_walk.c ! 26588: $(CC) $(CCFLAGS) -c tree_walk.c ! 26589: ! 26590: typ.o: typ.c size.h ! 26591: $(CC) $(CCFLAGS) -c typ.c ! 26592: ! 26593: typ2.o: typ2.c size.h ! 26594: $(CC) $(CCFLAGS) -c typ2.c ! 26595: ! 26596: y.tab.o: y.tab.c size.h ! 26597: $(CC) -DGRAM $(CCFLAGS) -c y.tab.c ! 26598: ! 26599: cpio: ! 26600: ls alloc.c dcl.c dcl2.c dcl3.c dcl4.c del.c discrim.c doprint.c \ ! 26601: error.c expand.c expr.c expr2.c expr3.c find.c hash.c \ ! 26602: lalex.c lex.c main.c norm.c norm2.c print.c print2.c \ ! 26603: print_self.c repr.c simpl.c simpl2.c size.c table.c \ ! 26604: template.c tree_copy.c tree_dump.c tree_walk.c typ.c typ2.c \ ! 26605: gram.y \ ! 26606: cfront.h token.h size.h tqueue.h typedef.h yystype.h \ ! 26607: hash.h ios_printf.h node_classes.h print_self.h \ ! 26608: template.h token_names.h tree_copy.h tree_dump.h tree_walk.h \ ! 26609: makefile | cpio -oc > cfront.cpio ! 26610: ! 26611: 0707071010112046101004440001630000160000010212500466055421000001700000012215node_classes.h /* ident "@(#)ctrans:src/node_classes.h 1.2" */ ! 26612: /* ! 26613: * node_classes.h ! 26614: */ ! 26615: ! 26616: #ifndef _node_classes ! 26617: #define _node_classes ! 26618: ! 26619: enum discriminator_error { ! 26620: discrim_none_valid = 0, ! 26621: discrim_bad_index = -1, ! 26622: discrim_inconsistent_node = -2, ! 26623: }; ! 26624: ! 26625: enum node_class { ! 26626: nc_unused = 0, ! 26627: nc_eof = 1, ! 26628: nc_virt = 2, ! 26629: nc_nlist = 3, ! 26630: nc_gen = 4, ! 26631: nc_vec = 5, ! 26632: nc_ptr = 6, ! 26633: nc_fct = 7, ! 26634: nc_table = 8, ! 26635: nc_basetype = 9, ! 26636: nc_name = 10, ! 26637: nc_expr = 11, ! 26638: nc_stmt = 12, ! 26639: nc_enumdef = 13, ! 26640: nc_classdef = 14, ! 26641: nc_baseclass = 15, ! 26642: nc_iline = 16, ! 26643: nc_ia = 17, ! 26644: }; ! 26645: ! 26646: /* ! 26647: searching this is slower than a directly indexed array, ! 26648: but this is more maintainable. We can speed it up later. ! 26649: */ ! 26650: ! 26651: #ifdef DEFINE_TOKEN_CLASS_TABLE ! 26652: struct token_class { ! 26653: TOK token; ! 26654: node_class nclass; ! 26655: } token_classes[] = { ! 26656: { EOFTOK, nc_eof }, ! 26657: { ASM, nc_stmt }, ! 26658: { AUTO, nc_basetype }, ! 26659: { BREAK, nc_stmt }, ! 26660: { CASE, nc_stmt }, ! 26661: { CHAR, nc_basetype }, ! 26662: { CLASS, nc_classdef }, ! 26663: { CONTINUE, nc_stmt }, ! 26664: { DEFAULT, nc_stmt }, ! 26665: { DELETE, nc_expr }, ! 26666: { DO, nc_stmt }, ! 26667: { DOUBLE, nc_basetype }, ! 26668: { ELSE, nc_stmt }, ! 26669: { ENUM, nc_enumdef }, ! 26670: { EXTERN, nc_basetype }, ! 26671: { FLOAT, nc_basetype }, ! 26672: { FOR, nc_stmt }, ! 26673: { FORTRAN, nc_unused }, ! 26674: { FRIEND, nc_basetype }, ! 26675: { GOTO, nc_stmt }, ! 26676: { IF, nc_stmt }, ! 26677: { INT, nc_basetype }, ! 26678: { LONG, nc_basetype }, ! 26679: { NEW, nc_expr }, ! 26680: { OPERATOR, nc_fct }, ! 26681: { RETURN, nc_stmt }, ! 26682: { PUBLIC, nc_name }, ! 26683: { CONST, nc_basetype }, ! 26684: { REGISTER, nc_basetype }, ! 26685: { RETURN, nc_stmt }, ! 26686: { SHORT, nc_basetype }, ! 26687: { SIZEOF, nc_expr }, ! 26688: { STATIC, nc_basetype }, ! 26689: { STRUCT, nc_unused }, ! 26690: { SWITCH, nc_stmt }, ! 26691: { THIS, nc_expr }, ! 26692: { TYPEDEF, nc_basetype }, ! 26693: { UNION, nc_unused }, ! 26694: { UNSIGNED, nc_basetype }, ! 26695: { VOID, nc_basetype }, ! 26696: { WHILE, nc_stmt }, ! 26697: { LP, nc_unused }, ! 26698: { RP, nc_unused }, ! 26699: { LB, nc_unused }, ! 26700: { RB, nc_unused }, ! 26701: { REF, nc_expr }, ! 26702: { DOT, nc_expr }, ! 26703: { NOT, nc_expr }, ! 26704: { COMPL, nc_expr }, ! 26705: { INCR, nc_expr }, ! 26706: { DECR, nc_expr }, ! 26707: { MUL, nc_expr }, ! 26708: { DIV, nc_expr }, ! 26709: { AND, nc_expr }, ! 26710: { MOD, nc_expr }, ! 26711: { PLUS, nc_expr }, ! 26712: { MINUS, nc_expr }, ! 26713: { LS, nc_expr }, ! 26714: { RS, nc_expr }, ! 26715: { LT, nc_expr }, ! 26716: { LE, nc_expr }, ! 26717: { GT, nc_expr }, ! 26718: { GE, nc_expr }, ! 26719: { EQ, nc_expr }, ! 26720: { NE, nc_expr }, ! 26721: { ER, nc_expr }, ! 26722: { OR, nc_expr }, ! 26723: { ANDAND, nc_expr }, ! 26724: { OROR, nc_expr }, ! 26725: { QUEST, nc_expr }, ! 26726: { COLON, nc_unused }, ! 26727: { ASSIGN, nc_expr }, ! 26728: { CM, nc_expr }, ! 26729: { SM, nc_stmt }, ! 26730: { SM_PARAM, nc_stmt }, ! 26731: { LC, nc_unused }, ! 26732: { RC, nc_unused }, ! 26733: { INLINE, nc_fct }, ! 26734: { OVERLOAD, nc_gen }, ! 26735: { VIRTUAL, nc_fct }, /* but might be a basecl */ ! 26736: { COERCE, nc_unused }, ! 26737: { PROTECTED, nc_name }, ! 26738: { ID, nc_unused }, ! 26739: { STRING, nc_expr }, ! 26740: { ICON, nc_expr }, ! 26741: { FCON, nc_expr }, ! 26742: { CCON, nc_expr }, ! 26743: { NAME, nc_name }, /* but might be basecl */ ! 26744: { ZERO, nc_expr }, ! 26745: { ASOP, nc_expr }, ! 26746: { RELOP, nc_expr }, ! 26747: { EQUOP, nc_expr }, ! 26748: { DIVOP, nc_expr }, ! 26749: { SHIFTOP, nc_expr }, ! 26750: { ICOP, nc_expr }, ! 26751: { UNOP, nc_expr }, ! 26752: { TYPE, nc_basetype }, ! 26753: { UMINUS, nc_expr }, ! 26754: { FCT, nc_fct }, ! 26755: { CALL, nc_expr }, ! 26756: { VEC, nc_vec }, ! 26757: { DEREF, nc_expr }, ! 26758: { ADDROF, nc_expr }, ! 26759: { CAST, nc_expr }, ! 26760: { FIELD, nc_basetype }, ! 26761: { LABEL, nc_stmt }, ! 26762: { BLOCK, nc_stmt }, ! 26763: { DCL, nc_stmt }, ! 26764: { COBJ, nc_basetype }, ! 26765: { EOBJ, nc_basetype }, ! 26766: { TNAME, nc_name }, ! 26767: { ILIST, nc_expr }, ! 26768: { PTR, nc_ptr }, ! 26769: { ASPLUS, nc_expr }, ! 26770: { ASMINUS, nc_expr }, ! 26771: { ASMUL, nc_expr }, ! 26772: { ASDIV, nc_expr }, ! 26773: { ASMOD, nc_expr }, ! 26774: { ASAND, nc_expr }, ! 26775: { ASOR, nc_expr }, ! 26776: { ASER, nc_expr }, ! 26777: { ASLS, nc_expr }, ! 26778: { ASRS, nc_expr }, ! 26779: { ARG, nc_basetype }, ! 26780: { ZTYPE, nc_basetype }, ! 26781: { ARGT, nc_basetype }, ! 26782: { ELIST, nc_expr }, ! 26783: { ANY, nc_basetype }, ! 26784: { TABLE, nc_table }, ! 26785: { LOC, nc_unused }, ! 26786: { DUMMY, nc_expr }, ! 26787: { G_ADDROF, nc_expr }, ! 26788: { G_CALL, nc_expr }, ! 26789: { G_CM, nc_expr }, ! 26790: { IVAL, nc_expr }, ! 26791: { ELLIPSIS, nc_unused }, ! 26792: { AGGR, nc_unused }, ! 26793: { RPTR, nc_ptr }, ! 26794: { HIDDEN, nc_unused }, ! 26795: { MEM, nc_expr }, ! 26796: { CTOR, nc_unused }, ! 26797: { DTOR, nc_unused }, ! 26798: { CONST_PTR, nc_ptr }, ! 26799: { CONST_RPTR, nc_ptr }, ! 26800: { TEXT, nc_expr }, ! 26801: { PAIR, nc_stmt }, ! 26802: { ANON, nc_unused }, ! 26803: { ICALL, nc_expr }, ! 26804: { ANAME, nc_expr }, ! 26805: { VOLATILE, nc_basetype }, ! 26806: { SIGNED, nc_basetype }, ! 26807: { UPLUS, nc_expr }, ! 26808: { MEMPTR, nc_unused }, ! 26809: { PRIVATE, nc_name }, ! 26810: { PR, nc_unused }, ! 26811: { MDOT, nc_expr }, ! 26812: { TSCOPE, nc_unused }, ! 26813: { DECL_MARKER, nc_unused }, ! 26814: { REFMUL, nc_expr }, ! 26815: { LDOUBLE, nc_basetype }, ! 26816: { LINKAGE, nc_unused }, ! 26817: { LOCAL, nc_basetype }, ! 26818: { GNEW, nc_expr }, ! 26819: { TEMPLATE, nc_unused }, ! 26820: { STAT_INIT, nc_unused }, ! 26821: { CATCH, nc_unused }, ! 26822: { GDELETE, nc_expr }, ! 26823: { XVIRT, nc_virt }, ! 26824: { XNLIST, nc_nlist }, ! 26825: { XILINE, nc_iline }, ! 26826: { XIA, nc_ia }, ! 26827: { VALUE, nc_expr }, ! 26828: { XDELETED_NODE, nc_unused }, ! 26829: }; ! 26830: #endif ! 26831: ! 26832: node_class classify_node (Pnode, int&); ! 26833: node_class classify_node (Pnode); ! 26834: ! 26835: #endif ! 26836: 0707071010112044361004440001630000160000010204500466055405300000700000120447norm.c /*ident "@(#)ctrans:src/norm.c 1.10" */ ! 26837: /************************************************************************ ! 26838: ! 26839: C++ source for cfront, the C++ compiler front-end ! 26840: written in the computer science research center of Bell Labs ! 26841: ! 26842: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 26843: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 26844: ! 26845: norm.c: ! 26846: ! 26847: "normalization" handles problems which could have been handled ! 26848: by the syntax analyser; but has not been done. The idea is ! 26849: to simplify the grammar and the actions accociated with it, ! 26850: and to get a more robust error handling ! 26851: ! 26852: ****************************************************************************/ ! 26853: #ifdef c_plusplus ! 26854: overload nested_hide; ! 26855: #endif ! 26856: ! 26857: #include "cfront.h" ! 26858: #include "size.h" ! 26859: #include "template.h" ! 26860: ! 26861: extern Pname do_nested_type(Pname); ! 26862: extern int is_anon(char*); ! 26863: ! 26864: Pname sta_name = 0; ! 26865: ! 26866: void syn_init() ! 26867: { ! 26868: any_type = new basetype(ANY,0); ! 26869: PERM(any_type); any_type->defined = DEFINED; ! 26870: dummy = new expr(DUMMY,0,0); ! 26871: PERM(dummy); ! 26872: dummy->tp = any_type; ! 26873: zero = new expr(ZERO,0,0); ! 26874: PERM(zero); ! 26875: sta_name = new name; ! 26876: PERM(sta_name); ! 26877: // Gtbl = new table(GTBLSIZE,0,0); //SYM ! 26878: // Ctbl = Gtbl; //SYM ! 26879: } ! 26880: ! 26881: int stcount; ! 26882: ! 26883: char* make_name(TOK c) ! 26884: { ! 26885: char* s = new char[8]; // as it happens: fits in two words ! 26886: ! 26887: if (10000 <= ++stcount) error('i',"too many generatedNs"); ! 26888: ! 26889: sprintf(s,"__%c%d",c,stcount); ! 26890: return s; ! 26891: } ! 26892: ! 26893: Pbase basetype::type_adj(TOK t) ! 26894: { ! 26895: DB(if(Ndebug>=1)error('d',"'%k'->type_adj(%k) --%t b_xname%n",base,t,this,b_xname);); ! 26896: if (b_xname) { ! 26897: if (base) ! 26898: error("badBT:%n%k",b_xname,t); ! 26899: else { ! 26900: base = TYPE; ! 26901: b_name = b_xname; ! 26902: } ! 26903: b_xname = 0; ! 26904: } ! 26905: ! 26906: switch (t) { ! 26907: case TYPEDEF: b_typedef = 1; break; ! 26908: case INLINE: b_inline = 1; break; ! 26909: case VIRTUAL: b_virtual = 1; break; ! 26910: case CONST: if (b_const) error('w',"two const declarators"); ! 26911: b_const = 1; break; ! 26912: case UNSIGNED: b_unsigned = 1; break; ! 26913: case SHORT: b_short = 1; break; ! 26914: case LONG: if (b_long) error('w',"two long declarators"); ! 26915: if (base == DOUBLE) ! 26916: base = LDOUBLE; ! 26917: else ! 26918: b_long = 1; ! 26919: break; ! 26920: case FRIEND: ! 26921: case OVERLOAD: ! 26922: case EXTERN: ! 26923: case STATIC: ! 26924: case AUTO: ! 26925: case REGISTER: ! 26926: if (b_sto) ! 26927: error("badBT:%k%k",b_sto,t); ! 26928: else ! 26929: b_sto = t; ! 26930: break; ! 26931: case DOUBLE: ! 26932: if (b_long) { ! 26933: t = LDOUBLE; ! 26934: b_long = 0; ! 26935: } ! 26936: // no break ! 26937: case VOID: ! 26938: case CHAR: ! 26939: case INT: ! 26940: case FLOAT: ! 26941: if (base) ! 26942: error("badBT:%k%k",base,t); ! 26943: else ! 26944: base = t; ! 26945: break; ! 26946: case SIGNED: ! 26947: case VOLATILE: ! 26948: error('w',"\"%k\" not implemented (ignored)",t); ! 26949: break; ! 26950: default: ! 26951: error('i',"BT::type_adj(%k)",t); ! 26952: } ! 26953: return this; ! 26954: } ! 26955: ! 26956: Pbase basetype::name_adj(Pname n) ! 26957: { ! 26958: DB(if(Ndebug>=1)error('d',"'%k'->name_adj(%n) --%t b_xname%n",base,n,this,b_xname)); ! 26959: if (b_xname) { ! 26960: if (base) ! 26961: error("badBT:%n%n",b_xname,n); ! 26962: else { ! 26963: base = TYPE; ! 26964: b_name = b_xname; ! 26965: } ! 26966: b_xname = 0; ! 26967: } ! 26968: ! 26969: if ( base==0 ! 26970: && n->base == TNAME ! 26971: && ( n->tp->base!=COBJ || in_arg_list )) { ! 26972: base = TYPE; ! 26973: b_name = n; ! 26974: } ! 26975: else ! 26976: b_xname = n; ! 26977: ! 26978: return this; ! 26979: } ! 26980: ! 26981: static TOK type_set( Pbase b ) ! 26982: { ! 26983: TOK t = 0; ! 26984: ! 26985: if ( b->b_long ) t = LONG; ! 26986: else if ( b->b_short ) t = SHORT; ! 26987: else if ( b->b_unsigned ) t = UNSIGNED; ! 26988: else if ( b->b_inline ) t = INLINE; ! 26989: else if ( b->b_virtual ) t = VIRTUAL; ! 26990: else if ( b->b_sto == OVERLOAD ) t = OVERLOAD; ! 26991: return t; ! 26992: } ! 26993: ! 26994: int declTag = 1; ! 26995: ! 26996: Pbase basetype::base_adj(Pbase b) ! 26997: { ! 26998: DB(if(Ndebug>=1)error('d',"'%k'->base_adj(%t) --%t b_xname%n",base,b,this,b_xname)); ! 26999: Pname bn = b->b_name; ! 27000: ! 27001: switch (base) { ! 27002: case COBJ: ! 27003: case EOBJ: ! 27004: error("NX after%k%n",base,b_name); ! 27005: return this; ! 27006: } ! 27007: ! 27008: TOK t; ! 27009: if (base) { ! 27010: if (b_name) ! 27011: error("badBT:%k%n%k%n",base,b_name,b->base,bn); ! 27012: else ! 27013: error("badBT:%k%k%n",base,b->base,bn); ! 27014: } ! 27015: else if ( t = type_set(this)) { ! 27016: if (b_name) ! 27017: error("badBT:%k%n%k%n",t,b_name,b->base,bn); ! 27018: else { ! 27019: if ( declTag++ && (t!= INLINE)) error("badBT:%k%k%n",t,b->base,bn); ! 27020: base=b->base; b_name = bn; ! 27021: // error('d',"base_adj: t: %k", t ); ! 27022: } ! 27023: } ! 27024: else { ! 27025: base = b->base; ! 27026: b_name = bn; ! 27027: b_table = b->b_table; ! 27028: } ! 27029: ! 27030: if ( b->base == COBJ ) { ! 27031: Pclass cl = Pclass(bn->tp); ! 27032: if ( cl->in_class && ! 27033: bn->tpdef && ! 27034: bn->tpdef->lex_level == NESTED ) ! 27035: { // peculiar case: class x { typedef class bn {} _bn; ... ! 27036: // bn has been half dealt with in do_nested_type ... ! 27037: Pname n = new name(bn->string); ! 27038: n->tp = b; ! 27039: Pname nn = ktbl->insert(n, NESTED); //SYM ! 27040: nn->tpdef = bn->tpdef; ! 27041: nn->tpdef->lex_level = nn->lex_level = 0; ! 27042: bn->tpdef = 0; ! 27043: } ! 27044: } ! 27045: ! 27046: return this; ! 27047: } ! 27048: ! 27049: Pbase basetype::check(Pname n) ! 27050: /* ! 27051: "n" is the first name to be declared using "this" ! 27052: check the consistency of "this" ! 27053: and use "b_xname" for "n->string" if possible and needed ! 27054: */ ! 27055: { ! 27056: b_inline = 0; ! 27057: b_virtual = 0; ! 27058: //error('d',"basetype::check(%n) base %k b_xname %n",n,base,b_xname); ! 27059: ! 27060: if (b_xname && (n->tp || n->string)) { ! 27061: if (base) ! 27062: error("badBT:%k%n",base,b_xname); ! 27063: else { ! 27064: base = TYPE; ! 27065: b_name = b_xname; ! 27066: } ! 27067: b_xname = 0; ! 27068: } ! 27069: ! 27070: if (b_xname) { ! 27071: if (n->string) ! 27072: error("twoNs inD:%n%n",b_xname,n); ! 27073: else { ! 27074: n->string = b_xname->string; ! 27075: b_xname->hide(); ! 27076: } ! 27077: b_xname = 0; ! 27078: } ! 27079: ! 27080: if (ccl==0 ! 27081: && n ! 27082: && n->n_oper==TNAME ! 27083: && n->n_qualifier==0 ! 27084: && n->string) { // hide type name ! 27085: Pname nx = ktbl->look(n->string,0); //SYM ! 27086: if (nx) nx->hide(); ! 27087: } ! 27088: ! 27089: int defa = 0; ! 27090: switch (base) { ! 27091: case 0: ! 27092: defa = 1; ! 27093: base = INT; ! 27094: break; ! 27095: case EOBJ: ! 27096: case COBJ: ! 27097: if (b_name->base == TNAME) error('i',"TN%n inCO %p",b_name,this); ! 27098: } ! 27099: ! 27100: if (b_long || b_short) { ! 27101: TOK sl = (b_short) ? SHORT : LONG; ! 27102: if (b_long && b_short) error("badBT:long short%k%n",base,n); ! 27103: if (base != INT) ! 27104: error("badBT:%k%k%n",sl,base,n); ! 27105: else ! 27106: base = sl; ! 27107: b_short = b_long = 0; ! 27108: } ! 27109: ! 27110: if (b_typedef && b_sto) error("badBT:Tdef%k%n",b_sto,n); ! 27111: b_typedef = b_sto = 0; ! 27112: ! 27113: if (b_linkage) { ! 27114: if (1 <= bl_level) error("local linkage directive"); ! 27115: } ! 27116: ! 27117: if (Pfctvec_type == 0) return this; ! 27118: ! 27119: if (b_const) { ! 27120: if (b_unsigned) { ! 27121: switch (base) { ! 27122: default: ! 27123: error("badBT: unsigned const %k%n",base,n); ! 27124: b_unsigned = 0; ! 27125: case LONG: ! 27126: case SHORT: ! 27127: case INT: ! 27128: case CHAR: ! 27129: return this; ! 27130: } ! 27131: } ! 27132: return this; ! 27133: } ! 27134: else if (b_unsigned) { ! 27135: switch (base) { ! 27136: case LONG: ! 27137: delete this; ! 27138: return ulong_type; ! 27139: case SHORT: ! 27140: delete this; ! 27141: return ushort_type; ! 27142: case INT: ! 27143: delete this; ! 27144: return uint_type; ! 27145: case CHAR: ! 27146: delete this; ! 27147: return uchar_type; ! 27148: default: ! 27149: error("badBT: unsigned%k%n",base,n); ! 27150: b_unsigned = 0; ! 27151: return this; ! 27152: } ! 27153: } ! 27154: else { ! 27155: switch (base) { ! 27156: case LONG: ! 27157: delete this; ! 27158: return long_type; ! 27159: case SHORT: ! 27160: delete this; ! 27161: return short_type; ! 27162: case INT: ! 27163: if (this==int_type || this==defa_type) return this; ! 27164: // if (this != int_type) ! 27165: delete this; ! 27166: if (defa) return defa_type; ! 27167: return int_type; ! 27168: case CHAR: ! 27169: delete this; ! 27170: return char_type; ! 27171: case VOID: ! 27172: delete this; ! 27173: return void_type; ! 27174: case TYPE: ! 27175: /* use a single base saved in the keyword */ ! 27176: if (b_name->n_qualifier) { ! 27177: Pbase rv = Pbase(b_name->n_qualifier); ! 27178: delete this; ! 27179: return rv; ! 27180: } ! 27181: else { ! 27182: PERM(this); ! 27183: b_name->n_qualifier = (Pname)this; ! 27184: return this; ! 27185: } ! 27186: default: ! 27187: return this; ! 27188: } ! 27189: } ! 27190: } ! 27191: ! 27192: Pname basetype::aggr() ! 27193: /* ! 27194: "type SM" seen e.g. struct s {}; ! 27195: class x; ! 27196: enum e; ! 27197: int tname; ! 27198: friend cname; ! 27199: friend class x; ! 27200: int; ! 27201: ! 27202: typedef int i; // where i is tname ! 27203: ! 27204: convert ! 27205: union { ... }; ! 27206: into ! 27207: union name { ... } name ; ! 27208: */ ! 27209: { ! 27210: DB(if(Ndebug>=1)error('d',"'%k'->aggr() --%t b_xname%n ccl%t",base,this,b_xname,ccl)); ! 27211: if (b_xname) { ! 27212: if (base) { ! 27213: Pname n = new name(b_xname->string); ! 27214: /*SYM?*/if (ccl && b_xname->tpdef) ! 27215: /*SYM?*/ n->tpdef = b_xname->tpdef; ! 27216: b_xname->hide(); ! 27217: b_xname = 0; ! 27218: return n->normalize(this,0,0); ! 27219: } ! 27220: else { ! 27221: base = TYPE; ! 27222: b_name = b_xname; ! 27223: b_xname = 0; ! 27224: } ! 27225: } ! 27226: ! 27227: switch (base) { ! 27228: case COBJ: ! 27229: { Pclass cl = Pclass(b_name->tp); ! 27230: char* s = cl->string; ! 27231: /*SYM?*/if (b_name->base == TNAME) error('i',"TN%n inCO",b_name); ! 27232: if (b_const) error("const%k%n",cl->csu,b_name); ! 27233: ! 27234: if (cl->c_body == 2) { /* body seen */ ! 27235: if (s[0]=='_' && s[1]=='_' && s[2]=='C') { ! 27236: char* ss = new char[8]; // max size of generated name is 7 chars, see make_name() ! 27237: Pname obj = new name(ss); ! 27238: strcpy(ss,s); ! 27239: if (cl->csu == UNION) { ! 27240: ss[2] = 'O'; ! 27241: cl->csu = ANON; ! 27242: return obj->normalize(this,0,0); ! 27243: } ! 27244: error('w',"unusable%k ignored",cl->csu); ! 27245: } ! 27246: if ( b_sto == FRIEND ) ! 27247: error("friend%k%n{...}",cl->csu,b_name); ! 27248: cl->c_body = 1; ! 27249: return b_name; ! 27250: } ! 27251: else { /* really a typedef for cfront only: class x; */ ! 27252: if (b_sto == FRIEND) goto frr; ! 27253: if (ansi_opt) printf("struct %s;\n",s); ! 27254: return 0; ! 27255: } ! 27256: } ! 27257: ! 27258: case EOBJ: ! 27259: { Penum en = Penum(b_name->tp); ! 27260: /*SYM?*/if (b_name->base == TNAME) error('i',"TN%n in enumO",b_name); ! 27261: if (b_const) error("const enum%n",b_name); ! 27262: if (en->e_body == 2) { ! 27263: en->e_body = 1; ! 27264: return b_name; ! 27265: } ! 27266: else { ! 27267: error("forwardD of enum%n", b_name); ! 27268: en->e_type = int_type; ! 27269: } ! 27270: return 0; ! 27271: } ! 27272: ! 27273: case 0: ! 27274: { Pname n = new name(make_name('D')); ! 27275: n->tp = defa_type; ! 27276: error("NX inDL"); ! 27277: return n; ! 27278: } ! 27279: default: ! 27280: if (b_typedef) error('w',"illegalTdef ignored"); ! 27281: ! 27282: if (b_sto == FRIEND && b_name ) { ! 27283: frr: ! 27284: Pname fr = ktbl->look(b_name->string,0); //SYM ! 27285: if (fr == 0) error('i',"cannot find friend%n",b_name); ! 27286: Pname n = new name(b_name->string); ! 27287: n->n_sto = FRIEND; ! 27288: // If it is a parameterized type, use the instantiation ! 27289: // type, not the general type. ! 27290: if ((fr->tp->base == COBJ) && ! 27291: (Pclass(Pbase(fr->tp)->b_name->tp)->class_base == ! 27292: template_class)) ! 27293: { ! 27294: if (base == COBJ) ! 27295: n->tp = this; ! 27296: else ! 27297: if ((base == TYPE) && ! 27298: (Pbase(this)->b_name->base == TNAME) && ! 27299: (Pbase(this)->b_name->tp->base == COBJ)) ! 27300: n->tp = Pbase(this)->b_name->tp; ! 27301: else ! 27302: error('i', "basetype wasn't a COBJ"); ! 27303: } ! 27304: else n->tp = fr->tp; ! 27305: return n; ! 27306: } ! 27307: else { ! 27308: Pname n = new name(make_name('D')); ! 27309: n->tp = defa_type; ! 27310: error('w',"NX inDL"); ! 27311: return n; ! 27312: } ! 27313: } ! 27314: } ! 27315: ! 27316: void local_name() //SYM -- to be removed ! 27317: { /* need to provide an additional temporary name ! 27318: * to handle case of ! 27319: * f() { ! 27320: * { class x{...}; } ! 27321: * { class x{...}; } ! 27322: * } ! 27323: * generate name after closing } of block ! 27324: * to distinquish between separate blocks at same lexical level ! 27325: */ ! 27326: for (Plist l=local_blk; l; l=l->l) { ! 27327: Pname n = l->f; ! 27328: if ( n->tp == 0 ) error( 'i', "no tp yet: #0 local_name" ); ! 27329: if ( Pbase(n->tp)->b_name == 0 ) error( 'i', "no tp yet: #1 local_name" ); ! 27330: Pname bn = Pbase(n->tp)->b_name; ! 27331: if ( bn->tp == 0 ) error( 'i', "no tp yet#2: local_name" ); ! 27332: Pclass cl = Pclass(bn->tp); ! 27333: cl->lcl = make_name( 'L' ); ! 27334: // error( 'd', "local_name(): %n bn: %n: cl : %s nof: %d", n, bn, cl->string, cc->nof ); ! 27335: } ! 27336: } ! 27337: ! 27338: void local_restore() //SYM -- to be removed ! 27339: { ! 27340: for (Plist l=local_tn; l; l=l->l) { ! 27341: Pname n = l->f; ! 27342: // error('d',"local_restore: n %n %t %d bl_level: %d", n, n->tp, n->lex_level, bl_level ); ! 27343: n->n_key = (n->lex_level==0) ? 0 ! 27344: : (n->lex_level && n->lex_level<=bl_level) ? LOCAL : HIDDEN; ! 27345: } ! 27346: } ! 27347: ! 27348: void local_hide( Pname n ) //SYM -- to be removed ! 27349: { ! 27350: // error('d',"local_hide(%n )",n); ! 27351: ! 27352: if ( n->base != TNAME ) return; ! 27353: if ( n->n_key == 0 ) { ! 27354: local_tn = new name_list( n, local_tn ); ! 27355: n->n_key = HIDDEN; ! 27356: // error( 'd', "local_hide(): %n n_key: %d", n, n->n_key ); ! 27357: } ! 27358: } ! 27359: ! 27360: void ! 27361: nested_restore() //SYM -- to be removed ! 27362: { ! 27363: for (Plist l = nested_type; l; l=l->l) ! 27364: { ! 27365: Pname n = l->f; ! 27366: n->n_key = NESTED; ! 27367: } ! 27368: ! 27369: for (l=nested_tn; l; l=l->l) { ! 27370: Pname n = l->f; ! 27371: Ptype tp = n->tp; ! 27372: // error('d',"nested_restore: n %n %t %d bl_level: %d", n, n->tp, n->lex_level, bl_level ); ! 27373: // error('d'," --- n_key %k", n->n_key ); ! 27374: ! 27375: if ( tp->in_class ) ! 27376: n->n_key = NESTED; ! 27377: else ! 27378: if ( tp->lex_level ) ! 27379: n->n_key = LOCAL; ! 27380: else ! 27381: n->n_key = 0; ! 27382: // error('d'," --- n_key %k", n->n_key ); ! 27383: } ! 27384: } ! 27385: ! 27386: void ! 27387: nested_hide( Pname n ) //SYM -- to be removed ! 27388: { ! 27389: // error('d',"nested_hide(%n )",n); ! 27390: ! 27391: if ( n->base != TNAME ) return; ! 27392: if ( n->n_key == 0 ) { ! 27393: nested_tn = new name_list( n, nested_tn ); ! 27394: n->n_key = HIDDEN; ! 27395: // error( 'd', "nested_hide(): %n n_key: %d", n, n->n_key ); ! 27396: } ! 27397: } ! 27398: ! 27399: static void ! 27400: nested_hide( Plist l ) //SYM -- to be removed ! 27401: { ! 27402: // error('d',"nested_hide( list )"); ! 27403: ! 27404: for (; l; l=l->l) { ! 27405: Pname nn = l->f; ! 27406: Pname n = ktbl->look(nn->string,0); ! 27407: // error('d',"nested_hide %n %t", n, n->tp, n->n_key); ! 27408: if (n==0) continue; ! 27409: ! 27410: if ( n->base != TNAME ) ! 27411: error('i', "nested_hide: %n not a type name (%t)", n, n->tp ); ! 27412: if ( n->n_key == 0 ) { ! 27413: nested_tn = new name_list( n, nested_tn ); ! 27414: n->n_key = HIDDEN; ! 27415: // error( 'd', "nested_hide(list): %n n_key: %d", n, n->n_key ); ! 27416: // nn->n_key = 0; ! 27417: } ! 27418: } ! 27419: } ! 27420: ! 27421: int defer_check = 0; ! 27422: Pname statStat = 0; ! 27423: ! 27424: void name::hide() ! 27425: /* ! 27426: hide "this": that is, "this" should not be a keyword in this scope ! 27427: */ ! 27428: { ! 27429: if (base != TNAME) return; ! 27430: // error('d',"'%n '->hide() -- %t lex_level %d bl_level %d",this,tp,lex_level,::bl_level); ! 27431: if (n_key == 0) { ! 27432: if (lex_level == bl_level && in_arg_list == 0) { ! 27433: if (tp->base != COBJ) { ! 27434: if ( !in_typedef ) ! 27435: error("%n redefined: typedef and identifier", this); ! 27436: else if ( in_typedef->base ! 27437: && tp->base != type_set(Pbase(in_typedef)) ! 27438: && in_typedef->check(tp,0) ) { ! 27439: if ( defer_check == 0 ) ! 27440: error("%n redefined: previous: %t now: %t", this, tp, in_typedef); ! 27441: } ! 27442: } ! 27443: else { ! 27444: //error('d',"in_typedef%t %d tp%t %d",in_typedef,in_typedef,tp,tp); ! 27445: //error('d',"in_typedef%k tp%k",in_typedef->base,tp->base); ! 27446: if ( in_typedef && in_typedef->base ! 27447: && in_typedef->check(tp, 0) ) { ! 27448: if ( defer_check == 0 ) ! 27449: error( "%n redefined: previous: %t now: %t", this, tp, in_typedef); ! 27450: } ! 27451: else { ! 27452: Pname nn = Pbase(tp)->b_name; ! 27453: Pclass cl = Pclass( nn->tp ); ! 27454: // check for 'typedef class X X;' ! 27455: // and 'typedef X X;' ! 27456: if ( in_typedef ) ! 27457: while ( in_typedef->base == TYPE ) ! 27458: in_typedef = Pbase(in_typedef)->b_name->tp; ! 27459: if ( in_typedef ! 27460: && in_typedef->base==COBJ ! 27461: && Pbase(in_typedef)->b_name->tp==cl ) ! 27462: in_typedef = tp; ! 27463: else if ( cl->has_ctor() ) ! 27464: error( "%n redefined: both aCNWK and %s", this, in_typedef?"a type name":"an identifier" ); ! 27465: } ! 27466: } ! 27467: ! 27468: } ! 27469: // error( 'd', "%n::hide", this ); ! 27470: modified_tn = new name_list(this,modified_tn); ! 27471: n_key = HIDDEN; ! 27472: } ! 27473: } ! 27474: ! 27475: static Pname Ntncheck; // ensure TNAMES hidden within class scopes ! 27476: static int notReally = 0; ! 27477: ! 27478: void set_scope(Pname tn) //SYM -- to be shrunk ! 27479: /* enter the scope of class tn after seeing "tn::f" */ ! 27480: { ! 27481: // error( 'd', "set_scope: %n %t %d", tn, tn->tp, tn->tp->base ); ! 27482: // error( 'd', "set_scope: %d", notReally ); ! 27483: ! 27484: Pbase b = Pbase(tn->tp); ! 27485: while ( b->base == TYPE ) b=Pbase(b->b_name->tp); // typedef class X T ! 27486: if (b->base != COBJ) return; // error caught elsewhere ! 27487: ! 27488: Pclass cl = Pclass(b->b_name->tp); ! 27489: char *str = cl->string; ! 27490: ! 27491: if ( cl->nest_list && notReally == 0 ) { ! 27492: nested_type = cl->nest_list; ! 27493: nested_hide(cl->nest_list); ! 27494: } ! 27495: ! 27496: Pname ntn = Ntncheck; ! 27497: if( notReally == 0 ) ! 27498: while ( ntn && ntn->tp->base == TYPE ) ntn = Pbase(ntn->tp)->b_name; ! 27499: ! 27500: if ( notReally || ntn == 0 || strcmp( str,ntn->string )) { ! 27501: if ( cl->baselist ) { ! 27502: Pname nb = new name, nbc = new name; ! 27503: nb->tp = new basetype(COBJ,0); ! 27504: Pbase(nb->tp)->b_name = nbc; ! 27505: for (Pbcl bx, bb=cl->baselist; bb; bb = bb->next) { ! 27506: bx = bb->next; ! 27507: if ( bb->bclass != 0 ) { ! 27508: nbc->tp = bb->bclass; ! 27509: notReally++; set_scope(nb); notReally--; ! 27510: } ! 27511: } ! 27512: DEL(nbc); /*DEL(nb->tp);*/ DEL(nb); ! 27513: } ! 27514: ! 27515: int i = 1; ! 27516: Pname n = 0; ! 27517: Plist ll = 0; ! 27518: if (b->parametrized_class()) { ! 27519: for (Pname nn = cl->mem_list; nn; nn = nn->n_list) ! 27520: switch (nn->base) { ! 27521: case PUBLIC: case PRIVATE: case PROTECTED: ! 27522: continue; ! 27523: default: ! 27524: if (nn->tp->base == CLASS) continue; ! 27525: if (nn->tp->base == ENUM) continue; ! 27526: if ((nn->base == NAME) && ! 27527: ((nn->n_oper == TNAME) && (nn->tp->base == FCT)) || ! 27528: (nn->n_oper == CTOR) || ! 27529: (nn->n_oper == DTOR)) continue ; ! 27530: n = ktbl->look( nn->string, 0 ); ! 27531: if (n) ll = new name_list( n, ll ); ! 27532: } ! 27533: } // if b->parametrized_class() ! 27534: else ! 27535: for (Pname nn=cl->memtbl->get_mem(i); nn; nn=cl->memtbl->get_mem(++i) ) { ! 27536: if (nn->base == TNAME || nn->base == PUBLIC) continue; ! 27537: if (nn->tp->base == CLASS) continue; ! 27538: if (nn->tp->base == ENUM) continue; ! 27539: n = ktbl->look( nn->string, 0 ); ! 27540: if (n) ll = new name_list( n, ll ); ! 27541: } ! 27542: ! 27543: if ( ll ) cl->tn_list = ll; ! 27544: if (notReally == 0) Ntncheck = tn; ! 27545: } ! 27546: ! 27547: for (Plist l=cl->tn_list; l; l=l->l) { ! 27548: Pname n = l->f; ! 27549: n->n_key = (n->lex_level) ? 0 : HIDDEN; ! 27550: modified_tn = new name_list(n,modified_tn); ! 27551: } ! 27552: } ! 27553: ! 27554: void restore() //SYM -- to be removed ! 27555: { ! 27556: for (Plist l=modified_tn; l; l=l->l) { ! 27557: Pname n = l->f; ! 27558: // error('d',"restore: n %n %t %d bl_level: %d", n, n->tp, n->lex_level, bl_level ); ! 27559: //fprintf(stderr," -- n_key %d\n",n->n_key); ! 27560: n->n_key = (n->lex_level==0 || (n->lex_level && n->lex_level<=bl_level)) ? 0 : HIDDEN; ! 27561: //fprintf(stderr," -- n_key %d\n",n->n_key); ! 27562: if ( n->lex_level == 0 ! 27563: && (n->tp->base == COBJ || n->tp->base == EOBJ)) { ! 27564: Pname nn = gtbl->look( n->string, 0 ); ! 27565: if ( nn ) n->n_key = HIDDEN; ! 27566: } ! 27567: //fprintf(stderr," -- n_key %d\n",n->n_key); ! 27568: } ! 27569: } ! 27570: ! 27571: Pbase start_cl(TOK t, Pname c, Pbcl b) ! 27572: { ! 27573: int mk_local = 0; ! 27574: DB(if(Ndebug>=1)error('d',"start_cl(%k,%d,%d)",t,c,b);); ! 27575: if (c == 0) { ! 27576: c = new name(make_name('C')); ! 27577: c->lex_level -= in_class_decl + 1; ! 27578: if ( in_typedef && c->lex_level ) ! 27579: mk_local = 1; ! 27580: else c->lex_level = 0; ! 27581: } ! 27582: ! 27583: for ( Pclass tc = ccl; tc; tc = tc->in_class ) { ! 27584: if ( tc->lex_level == c->lex_level // c not local to mem ftn of tc ! 27585: && strcmp( tc->string, c->string) == 0) { ! 27586: error( "C %s redefined", c->string ); ! 27587: error('i', "can't recover from previous errors"); ! 27588: } ! 27589: } ! 27590: ! 27591: Pname n = c->tname(t); /* t ignored */ ! 27592: ! 27593: if (templp->in_progress && (c->lex_level == 0)) ! 27594: // bring the template in scope ! 27595: templp->introduce_class_templ(n); ! 27596: ! 27597: // typedef struct {} x; ! 27598: if ( mk_local ) { ! 27599: n->n_key = LOCAL; ! 27600: extern Plist local_blk, local_class; // place in cfront.h ! 27601: local_class = new name_list( n, local_class ); ! 27602: local_blk = new name_list( n, local_blk ); ! 27603: modified_tn = modified_tn->l; ! 27604: } ! 27605: ! 27606: n->where = curloc; ! 27607: Pbase bt = Pbase(n->tp); /* COBJ */ ! 27608: if (bt->base != COBJ) { ! 27609: error("twoDs of%n:%t andC",n,bt); ! 27610: error('i', "can't recover from previous errors"); ! 27611: } ! 27612: ! 27613: Pclass occl = ccl; ! 27614: ccl = Pclass(bt->b_name->tp); /* CLASS */ ! 27615: if (ccl->defined) ccl->defined |= IN_ERROR; ! 27616: ccl->defined |= DEF_SEEN; ! 27617: ! 27618: // error('d', "start_cl: %n ccl->in_class: %t lex_level: %d", n, ccl->in_class, n->lex_level ); ! 27619: ! 27620: if (ccl->in_class = occl) { ! 27621: occl->tn_list = modified_tn; // save mod-list ! 27622: modified_tn = 0; ! 27623: } ! 27624: ! 27625: Ntncheck = 0; // zero it out with each new class declaration ! 27626: ccl->string = n->string; ! 27627: ccl->csu = t; ! 27628: ! 27629: if (b) { // list of base classes ! 27630: for (Pbcl bx, bb=b, l=0; bb; bb = bx) { ! 27631: bx = bb->next; ! 27632: bb->next = 0; ! 27633: ! 27634: if ( bb->bclass ! 27635: && strcmp(ccl->string,bb->bclass->string)==0 ) ! 27636: error(&n->where,"%nderived from itself",n); ! 27637: else if (l == 0) ! 27638: l = bb; ! 27639: else { // append and check for duplicates ! 27640: for (Pbcl ll = l;;) { ! 27641: if (bb->bclass && ll->bclass==bb->bclass) { ! 27642: error("%s has %s asB twice",ccl->string,bb->bclass->string); ! 27643: break; ! 27644: } ! 27645: ! 27646: if (ll->next) ! 27647: ll = ll->next; ! 27648: else { ! 27649: bb->next = l; ! 27650: l = bb; ! 27651: break; ! 27652: } ! 27653: } ! 27654: } ! 27655: } ! 27656: ! 27657: ccl->baselist = l; ! 27658: notReally++; set_scope(n); notReally--; ! 27659: } ! 27660: return bt; ! 27661: } ! 27662: ! 27663: void end_cl() ! 27664: { ! 27665: Pclass occl = ccl->in_class; ! 27666: Plist ol = occl ? occl->tn_list : 0; // saved modified name list ! 27667: ccl->c_body = 2; ! 27668: ! 27669: if (modified_tn) { // export nested class names to outer scope: ! 27670: Plist local = 0; ! 27671: for (Plist l=modified_tn, nl=0; l; l=nl) { ! 27672: nl = l->l; ! 27673: Pname n = l->f; ! 27674: ! 27675: // in a pure implementation, no longer do this ! 27676: if (ktbl->look(n->string,0)) { ! 27677: // add it to enclosing class's modified name list ! 27678: l->l = ol; ! 27679: ol = l; ! 27680: } ! 27681: else { // retain it in this class's modified name list ! 27682: l->l = local; ! 27683: local = l; ! 27684: } ! 27685: } ! 27686: if (ccl->tn_list = modified_tn = local) restore(); ! 27687: } ! 27688: modified_tn = ol; // restore mod-list (possibly modified) ! 27689: /* ! 27690: if ( occl ) { ! 27691: Pname n = ktbl->look(ccl->string,NESTED); ! 27692: for (;n; n=n->n_tbl_list) { ! 27693: Ptype tt = Pbase(n->tp)->b_name->tp; ! 27694: // error('d',"end_cl: ccl: %t occl: %t in_class: %t", ccl, occl, tt->in_class); ! 27695: if (strcmp(tt->in_class->string, occl->string) == 0) { ! 27696: n->n_key = 0; ! 27697: } ! 27698: } ! 27699: } ! 27700: */ ! 27701: ccl = occl; ! 27702: } ! 27703: ! 27704: Pbase end_enum(Pname n, nlist* b) ! 27705: { ! 27706: // error( 'd', "end_enum: %n ccl: %t", n , ccl ); ! 27707: if (n == 0) n = new name(make_name('E')); ! 27708: n = n->tname(ENUM); ! 27709: Pbase bt = (Pbase)n->tp; ! 27710: if (bt->base != EOBJ) { ! 27711: error("twoDs of%n:%t and enum",n,bt); ! 27712: error('i', "can't recover from previous errors"); ! 27713: } ! 27714: Penum en = (Penum)bt->b_name->tp; ! 27715: en->e_body = 2; ! 27716: en->mem = name_unlist(b); ! 27717: if (en->defined) { ! 27718: // shouldn't be necessary anymore with nested types ! 27719: // if ( in_class_decl ) ! 27720: // error("%n redefined, enum tag not local to class", n); ! 27721: en->defined |= IN_ERROR; ! 27722: } ! 27723: en->defined |= DEF_SEEN; ! 27724: en->in_class = ccl; ! 27725: if (ccl && (bl_level==ccl->lex_level + in_class_decl) && is_anon(n->string)) ! 27726: n=do_nested_type(n); ! 27727: return bt; ! 27728: } ! 27729: ! 27730: extern Ptype return_nstd_local_type(Pname,TOK&); ! 27731: Pname name::tdef() ! 27732: /* ! 27733: typedef "this" ! 27734: */ ! 27735: { ! 27736: DB(if(Ndebug>=1) { ! 27737: error('d',&where,"'%n'->tdef()%t in_typedef %d",this,tp,in_typedef); ! 27738: error('d',&where," lex_level %d tpdef%t",lex_level,tpdef); ! 27739: }); ! 27740: int anon_cl = 0; ! 27741: if (n_qualifier) { ! 27742: error("QdN in typedef",this); ! 27743: n_qualifier = 0; ! 27744: } ! 27745: ! 27746: Pname n; ! 27747: if ( tpdef && tpdef->in_class ) { // nested typedef ! 27748: // error('d', "*****%s->tdef: %d ccl: %t", string, tpdef, ccl ); ! 27749: n = ktbl->insert(this,NESTED); ! 27750: n->tpdef = tpdef; ! 27751: n->tpdef->lex_level = n->lex_level = 0; ! 27752: nested_type = new name_list( n, nested_type ); ! 27753: } ! 27754: else { ! 27755: Pname nn = ktbl->look(string,NESTED); ! 27756: if ( nn ) { ! 27757: TOK ntk = 0; // set by return_nstd... ! 27758: Ptype tt = return_nstd_local_type(nn,ntk); ! 27759: error("nested%k%t::%s seen beforeGTdef %s (to do this placeG definition first)",ntk, tt->in_class, string, string); ! 27760: error( 'i', "cannot recover from previous errors" ); ! 27761: } ! 27762: lex_level = bl_level - in_class_decl; ! 27763: n = ktbl->insert(this,0); ! 27764: } ! 27765: ! 27766: if (tp == 0) error('i',"Tdef%n tp==0",this); ! 27767: n->base = base = TNAME; ! 27768: PERM(n); ! 27769: PERM(tp); ! 27770: ! 27771: if (tp->base == COBJ || tp->base == EOBJ ) ! 27772: { // typedef struct/enum { } s; => struct/enum s {}; ! 27773: Pname b = Pbase(tp)->b_name; ! 27774: if (b->string[0] == '_' && b->string[1] == '_' ) ! 27775: switch ( tp->base ) { ! 27776: case COBJ: { ! 27777: if (b->string[2] == 'C') { ! 27778: Pclass cl = Pclass(b->tp); ! 27779: b->string = n->string; ! 27780: cl->string = n->string; ! 27781: cl->strlen = strlen(cl->string); ! 27782: if ( lex_level ) { ! 27783: anon_cl = 1; ! 27784: n->n_key = LOCAL; ! 27785: } ! 27786: } ! 27787: break; ! 27788: } ! 27789: case EOBJ: { ! 27790: if (b->string[2] == 'E') { ! 27791: Penum en = Penum(b->tp); ! 27792: b->string = n->string; ! 27793: en->string = n->string; ! 27794: en->strlen = strlen(en->string); ! 27795: } ! 27796: } ! 27797: } ! 27798: } ! 27799: ! 27800: if ( anon_cl == 0 ) ! 27801: modified_tn = new name_list(n,modified_tn); ! 27802: DB(if(Ndebug>=1) { ! 27803: error('d',&where,">>'%n'->tdef()%t returning",this,tp); ! 27804: error('d',&where," lex_level %d tpdef%t",lex_level,tpdef); ! 27805: }); ! 27806: return n; ! 27807: } ! 27808: ! 27809: Pname name::tname(TOK csu) ! 27810: /* ! 27811: "csu" "this" seen, return typedef'd name for "this" ! 27812: return (TNAME,x) ! 27813: x: (COBJ,y) ! 27814: y: (NAME,z) ! 27815: z: (CLASS,ae); ! 27816: */ ! 27817: { ! 27818: //error('d',"'%n'::tname(%k)",this,csu); ! 27819: switch (base) { ! 27820: case TNAME: ! 27821: return this; ! 27822: case NAME: ! 27823: { Pname tn = ktbl->insert(this,0); ! 27824: Pname on = new name; ! 27825: tn->base = TNAME; ! 27826: tn->lex_level = lex_level; ! 27827: modified_tn = new name_list(tn,modified_tn); ! 27828: tn->n_list = n_list = 0; ! 27829: string = tn->string; ! 27830: *on = *this; ! 27831: switch (csu) { ! 27832: case ENUM: ! 27833: tn->tp = new basetype(EOBJ,on); ! 27834: on->tp = new enumdef(0); ! 27835: Penum(on->tp)->string = tn->string; ! 27836: break; ! 27837: case CLASS: ! 27838: case STRUCT: ! 27839: case UNION: ! 27840: on->tp = new classdef(csu); ! 27841: Pclass(on->tp)->string = tn->string; ! 27842: Pclass(on->tp)->lex_level = lex_level; ! 27843: tn->tp = new basetype(COBJ,on); ! 27844: Pbase(tn->tp)->b_table = Pclass(on->tp)->memtbl; ! 27845: break; ! 27846: default: ! 27847: error('i',&where,"illegal csu%k for%n in name::tname()",csu,this); ! 27848: } ! 27849: PERM(tn); ! 27850: PERM(tn->tp); ! 27851: PERM(on); ! 27852: PERM(on->tp); ! 27853: return tn; ! 27854: } ! 27855: default: ! 27856: error('i',"tname(%s %d %k)",string,this,base); ! 27857: } ! 27858: } ! 27859: ! 27860: int co_hack; ! 27861: Pname name::normalize(Pbase b, Pblock bl, bit Cast) ! 27862: /* ! 27863: if (bl) : a function definition (check that it really is a type ! 27864: ! 27865: if (Cast) : no name string ! 27866: ! 27867: for each name on the name list ! 27868: invert the declarator list(s) and attatch basetype ! 27869: watch out for class object initializers ! 27870: ! 27871: convert ! 27872: struct s { int a; } a; ! 27873: into ! 27874: struct s { int a; }; struct s a; ! 27875: */ ! 27876: { ! 27877: Pname n; ! 27878: Pname nn; ! 27879: TOK stc; ! 27880: bit tpdf; ! 27881: bit inli; ! 27882: bit virt; ! 27883: char * lnkg; ! 27884: DB( if(Ndebug>=1) { ! 27885: error('d',"'%n'::normalize(b%t, bl %d, cast %d)",this,b,bl,Cast); ! 27886: error('d'," tp%k - lex_level %d - bl_level %d",tp?tp->base:0,lex_level,bl_level); ! 27887: }); ! 27888: if (b) { ! 27889: stc = b->b_sto; ! 27890: tpdf = b->b_typedef; ! 27891: inli = b->b_inline; ! 27892: virt = b->b_virtual; ! 27893: lnkg = b->b_linkage; ! 27894: } ! 27895: else { ! 27896: stc = 0; ! 27897: tpdf = 0; ! 27898: inli = 0; ! 27899: virt = 0; ! 27900: lnkg = 0; ! 27901: } ! 27902: ! 27903: if (inli && stc==EXTERN) { ! 27904: error("both extern and inline"); ! 27905: inli = 0; ! 27906: } ! 27907: ! 27908: if ( stc==STATIC && tp && ! 27909: tp->base == FCT ! 27910: && Pfct(tp)->f_const ) ! 27911: error( "%n staticMF cannot be const", this ); ! 27912: ! 27913: if (stc==FRIEND && tp==0) { ! 27914: /* friend x; ! 27915: must be handled during syntax analysis to cope with ! 27916: class x { friend y; y* p; }; ! 27917: "y" is not local to "x": ! 27918: class x { friend y; ... }; y* p; ! 27919: is legal ! 27920: ! 27921: examples: ! 27922: ! 27923: typedef void SIG_TYP(int); ! 27924: class x { ! 27925: friend class y; ! 27926: friend z; ! 27927: friend x; // dumb ! 27928: friend int i; // error ! 27929: friend SIG_TYP sigFunc; // subtle ! 27930: friend int f(); ! 27931: friend g(int); ! 27932: }; ! 27933: */ ! 27934: if (b && (b->base || b->b_name || b->b_xname)) goto ccc; ! 27935: ! 27936: if (n_list) { ! 27937: error("L of friends"); ! 27938: n_list = 0; ! 27939: } ! 27940: ! 27941: if (!Cast) { ! 27942: Pname nn = gtbl->look( string, 0 ); ! 27943: if ( nn ) { ! 27944: if (nn->tp->base == FCT) ! 27945: error("friendF must include signature:%n", this ); ! 27946: else ! 27947: error("illegal friendD:%n", this ); ! 27948: } ! 27949: } ! 27950: ! 27951: //error( 'd', "%n ll: %d", ccl, ccl->lex_level ); ! 27952: lex_level = ccl->lex_level; ! 27953: Pname nx = tname(CLASS); ! 27954: modified_tn = modified_tn->l; /* global */ ! 27955: n_sto = FRIEND; ! 27956: tp = nx->tp; ! 27957: return this; ! 27958: } ! 27959: ccc: ! 27960: if (tp // FUDGE: fix the bad grammar ! 27961: && tp->base==FCT ! 27962: && (n_oper==TNAME || Pfct(tp)->returns)) { ! 27963: Pfct f = Pfct(tp); ! 27964: Pfct f2 = Pfct(f->returns); ! 27965: ! 27966: if (f2) { ! 27967: Ptype pt; ! 27968: Ptype t = f2; ! 27969: lxlx: ! 27970: switch (t->base) { ! 27971: case PTR: // x(* p)(args) ? ! 27972: case VEC: // x(* p[10])(args) ? ! 27973: if (pt = Pptr(t)->typ) { ! 27974: if (pt->base == TYPE) { ! 27975: Pptr(t)->typ = 0; ! 27976: b = Pbase(pt); ! 27977: // stc = b->b_sto; ! 27978: // tpdf = b->b_typedef; ! 27979: // inli = b->b_inline; ! 27980: // virt = b->b_virtual; ! 27981: } ! 27982: else { ! 27983: t = pt; ! 27984: goto lxlx; ! 27985: } ! 27986: } ! 27987: goto zse1; ! 27988: case FCT: ! 27989: {// Pexpr e = f2->argtype; ! 27990: Pexpr e = Pfct(f)->argtype; ! 27991: if (e && e->base==ELIST) { // get the real name; fix its type ! 27992: if (e->e2 || e->e1->base!=DEREF) goto zse1; ! 27993: Pexpr ee = e->e1; ! 27994: Ptype t = 0; ! 27995: Ptype tpx; ! 27996: ldld: ! 27997: switch (ee->base) { ! 27998: case DEREF: ! 27999: { Ptype tt = (ee->e2) ? Ptype(new vec(0,ee->e2)) : Ptype (new ptr(PTR,0)); ! 28000: if (t) ! 28001: Pptr(t)->typ = tt; ! 28002: else ! 28003: tpx = tt; ! 28004: t = tt; ! 28005: ee = ee->e1; ! 28006: goto ldld; ! 28007: } ! 28008: case NAME: ! 28009: { Pname rn = Pname(ee); ! 28010: b = new basetype(TYPE,ktbl->look(string,0)); ! 28011: f->returns = tpx; ! 28012: n_oper = 0; ! 28013: string = rn->string; ! 28014: base = NAME; ! 28015: } ! 28016: } ! 28017: } ! 28018: } ! 28019: } ! 28020: } ! 28021: } ! 28022: ! 28023: zse1: ! 28024: if (b == 0) { ! 28025: error("BTX for %s",string); ! 28026: b = Pbase(defa_type); ! 28027: } ! 28028: ! 28029: if (Cast) string = ""; ! 28030: b = b->check(this); ! 28031: ! 28032: switch (b->base) { // separate class definitions ! 28033: // from object and function type declarations ! 28034: case COBJ: ! 28035: nn = b->b_name; ! 28036: if (Pclass(nn->tp)->c_body==2) { /* first occurrence */ ! 28037: if ( stc == FRIEND ) { ! 28038: Pclass cl = Pclass(nn->tp); ! 28039: if ( cl->csu == ANON ) ! 28040: error( &nn->where, "friend anonymous union"); ! 28041: else ! 28042: error( &nn->where, "%k%n defined in friendD",cl->csu,nn); ! 28043: } ! 28044: if (tp && tp->base==FCT && co_hack == 0) { ! 28045: error(&this->where,"%k%n defined as returnT for%n (did you forget a ';' after '}' ?)",Pclass(nn->tp)->csu,nn,this); ! 28046: nn = this; ! 28047: break; ! 28048: } ! 28049: nn->n_list = this; ! 28050: Pclass(nn->tp)->c_body = 1; /* other occurences */ ! 28051: } ! 28052: else ! 28053: nn = this; ! 28054: break; ! 28055: case EOBJ: ! 28056: nn = b->b_name; ! 28057: if (Penum(nn->tp)->e_body==2) { ! 28058: if (tp && tp->base==FCT) { ! 28059: error(&this->where,"enum%n defined as returnT for%n (did you forget a ';'?)",nn,this); ! 28060: nn = this; ! 28061: break; ! 28062: } ! 28063: nn->n_list = this; ! 28064: Penum(nn->tp)->e_body = 1; ! 28065: } ! 28066: else { ! 28067: Penum en = Penum(nn->tp); ! 28068: if ( en->defined == 0 ) ! 28069: error( "forwardD of enum%n", nn ); ! 28070: en->e_type = int_type; ! 28071: nn = this; ! 28072: } ! 28073: break; ! 28074: default: ! 28075: nn = this; ! 28076: } ! 28077: ! 28078: //error('d',&where,"name::normalize: nn%n ll %d nn %d this %d",nn,nn->lex_level,nn,this); ! 28079: Pname nx; ! 28080: for (n=this; n; n=nx) { ! 28081: Ptype t = n->tp; ! 28082: nx = n->n_list; ! 28083: n->n_sto = stc; ! 28084: ! 28085: if (n->base == TNAME) error('i',"redefinition ofTN%n",n); ! 28086: ! 28087: if (t == 0) { ! 28088: if (bl == 0) ! 28089: n->tp = t = b; ! 28090: else { ! 28091: if ( n->base == NAME && n->n_oper ) ! 28092: error(&n->where,"illegalD of %n",n); ! 28093: else ! 28094: error(&n->where,"body of nonF%n",n); ! 28095: t = new fct(0,0,0); ! 28096: } ! 28097: } ! 28098: ! 28099: switch (t->base) { ! 28100: case PTR: ! 28101: case RPTR: ! 28102: n->tp = Pptr(t)->normalize(b); ! 28103: break; ! 28104: case VEC: ! 28105: n->tp = Pvec(t)->normalize(b); ! 28106: break; ! 28107: case FCT: ! 28108: n->tp = Pfct(t)->normalize(b); ! 28109: break; ! 28110: case FIELD: ! 28111: if (n->string == 0) n->string = make_name('F'); ! 28112: n->tp = t; ! 28113: Pbase tb = b; ! 28114: // error('d', "field t %k tb %k", t->base, tb->base ); ! 28115: flatten: ! 28116: switch (tb->base) { ! 28117: case TYPE: /* chase typedefs */ ! 28118: tb = (Pbase)tb->b_name->tp; ! 28119: goto flatten; ! 28120: case CHAR: ! 28121: case SHORT: ! 28122: case EOBJ: ! 28123: case INT: ! 28124: // typedef const unsigned cu_int; ! 28125: // struct x { x(); cu_int b1: 2; } ! 28126: ! 28127: Pbase(t)->b_fieldtype = (b->b_unsigned||tb->b_unsigned) ? uint_type : int_type; ! 28128: // goto iii; ! 28129: // case CHAR: ! 28130: // Pbase(t)->b_fieldtype = (b->b_unsigned) ? uchar_type : char_type; ! 28131: // goto iii; ! 28132: // case SHORT: ! 28133: // Pbase(t)->b_fieldtype = (b->b_unsigned) ? ushort_type : short_type; ! 28134: // goto iii; ! 28135: // iii: ! 28136: Pbase(t)->b_unsigned = b->b_unsigned?b->b_unsigned:tb->b_unsigned; ! 28137: Pbase(t)->b_const = b->b_const?b->b_const:tb->b_const; ! 28138: break; ! 28139: default: ! 28140: error("non-int field"); ! 28141: n->tp = defa_type; ! 28142: } ! 28143: break; ! 28144: } ! 28145: ! 28146: Pfct f = Pfct(n->tp); ! 28147: ! 28148: if (f->base != FCT) { ! 28149: if (bl) { ! 28150: error("body for nonF%n",n); ! 28151: n->tp = f = new fct(defa_type,0,0); ! 28152: continue; ! 28153: } ! 28154: if (inli) error("inline nonF%n",n); ! 28155: if (virt) error("virtual nonF%n",n); ! 28156: ! 28157: if (tpdf) { ! 28158: // error('d', "%n->normalize: ccl: %t", this, ccl ); ! 28159: if (ccl && n->tpdef && ! 28160: (n->tpdef->lex_level == NESTED || ! 28161: n->tpdef->lex_level == LOCAL)) ! 28162: ; // using this field for nested/local type info ! 28163: else ! 28164: if (n->n_initializer) { ! 28165: error("Ir forTdefN%n",n); ! 28166: n->n_initializer = 0; ! 28167: } ! 28168: n->tdef(); ! 28169: // because do_nested_type can't call tdef() ! 28170: if ( n->n_key == NESTED ) ! 28171: modified_tn = modified_tn->l; ! 28172: } ! 28173: continue; ! 28174: } ! 28175: ! 28176: if ( lnkg ) set_linkage(lnkg); ! 28177: f->f_linkage = linkage; ! 28178: if ( lnkg ) set_linkage(0); ! 28179: // wait and call f->sign() after args are checked ! 28180: ! 28181: f->f_inline = inli; ! 28182: extern int vcounter; ! 28183: f->f_virtual = virt?(vcounter++,VTOK):0; ! 28184: ! 28185: if (tpdf) { ! 28186: if (f->body = bl) error("Tdef%n { ... }",n); ! 28187: if (n->n_qualifier) { ! 28188: // typedef T x::f(args); ! 28189: // a pointer to member fucntion: ! 28190: // equivalent to typedef T x::(f)(args); ! 28191: f->memof = Pclass(Pbase(n->n_qualifier->tp)->b_name->tp); ! 28192: n->n_qualifier = 0; ! 28193: } ! 28194: n->tdef(); ! 28195: // because do_nested_type can't call tdef() ! 28196: if ( n->n_key == NESTED ) ! 28197: modified_tn = modified_tn->l; ! 28198: continue; ! 28199: } ! 28200: ! 28201: if (f->body = bl) continue; ! 28202: ! 28203: /* ! 28204: Check function declarations. ! 28205: Look for class object instantiations ! 28206: The real ambiguity: ; class x fo(); ! 28207: is interpreted as an extern function ! 28208: declaration NOT a class object with an ! 28209: empty initializer ! 28210: */ ! 28211: { Pname cn = f->returns->is_cl_obj(); ! 28212: Ptype template_formal_type ; ! 28213: bit clob = (cn || cl_obj_vec); ! 28214: ! 28215: if (f->argtype) { /* check argument/initializer list */ ! 28216: Pname nn; ! 28217: ! 28218: for (nn=f->argtype; nn; nn=nn->n_list) { ! 28219: if (nn->base != NAME) { ! 28220: if (!clob) { ! 28221: if ((f->returns->base == TYPE) && ! 28222: (Pbase(f->returns)->b_name->n_template_arg == template_type_formal)) ! 28223: { ! 28224: // T x(var); wher T is a template formal ! 28225: // it could be a class when instantiated ! 28226: // wait until then to issue error message ! 28227: template_formal_type = f->returns; ! 28228: Pname nnn = Pbase(f->returns)->b_name; ! 28229: nnn->n_template_formal_must_be_class = 1; ! 28230: goto is_obj; ! 28231: } ! 28232: error(&n->where,"ATX for%n",n); ! 28233: goto zzz; ! 28234: } ! 28235: goto is_obj; ! 28236: } ! 28237: //if (nn->string) { ! 28238: // error("AN%n inD of%n",nn,n); ! 28239: // nn->string = 0; ! 28240: //} ! 28241: if (nn->tp) goto ok; ! 28242: } ! 28243: if (!clob) { ! 28244: error("FALX"); ! 28245: goto zzz; ! 28246: } ! 28247: is_obj: ! 28248: /* it was an initializer: expand to constructor */ ! 28249: n->tp = f->returns; ! 28250: if (f->argtype->base != ELIST) f->f_args = f->argtype = (Pname)new expr(ELIST,(Pexpr)f->argtype,0); ! 28251: if ( n->n_initializer ) { ! 28252: error(&n->where,"twoIrs for%n",n); ! 28253: DEL( ((Pexpr)f->argtype) ); ! 28254: f->argtype = 0; ! 28255: } else ! 28256: // n->n_initializer = new texpr(VALUE,cn->tp,(Pexpr)f->argtype); ! 28257: n->n_initializer = new texpr(VALUE, cn ? cn->tp : template_formal_type, (Pexpr)f->argtype); ! 28258: goto ok; ! 28259: zzz: ! 28260: if (f->argtype) { ! 28261: DEL(Pexpr(f->argtype)); ! 28262: f->argtype = 0; ! 28263: f->nargs = 0; ! 28264: f->nargs_known = 1; ! 28265: } ! 28266: } ! 28267: else { /* T a(); => function declaration */ ! 28268: /* ! 28269: if (clob) { ! 28270: DEL(n->tp); ! 28271: n->tp = f->returns; ! 28272: } ! 28273: */ ! 28274: } ! 28275: ok: ! 28276: ; ! 28277: } ! 28278: } ! 28279: return nn; ! 28280: } ! 28281: ! 28282: Ptype vec::normalize(Ptype vecof) ! 28283: { ! 28284: Ptype t = typ; ! 28285: typ = vecof; ! 28286: ! 28287: while(vecof->base == TYPE) ! 28288: vecof = Pbase(vecof)->b_name->tp; ! 28289: ! 28290: switch (vecof->base) { ! 28291: case RPTR: ! 28292: error("array ofRs"); ! 28293: break; ! 28294: case FCT: ! 28295: error("array ofFs"); ! 28296: break; ! 28297: default: ! 28298: break; ! 28299: } ! 28300: ! 28301: if (t == 0) return this; ! 28302: ! 28303: switch (t->base) { ! 28304: case PTR: ! 28305: case RPTR: return Pptr(t)->normalize(this); ! 28306: case VEC: return Pvec(t)->normalize(this); ! 28307: case FCT: return Pfct(t)->normalize(this); ! 28308: default: error('i',"bad arrayT(%d)",t->base); ! 28309: } ! 28310: ! 28311: } ! 28312: ! 28313: Ptype ptr::normalize(Ptype ptrto) ! 28314: { ! 28315: // if (this == 0) error('i',"0->ptr.normalize()"); ! 28316: Ptype t = typ; ! 28317: typ = ptrto; ! 28318: ! 28319: int bc = 0; ! 28320: while (ptrto->base == TYPE) { ! 28321: bc += Pbase(ptrto)->b_const; ! 28322: ptrto = Pbase(ptrto)->b_name->tp; ! 28323: } ! 28324: ! 28325: switch (ptrto->base) { ! 28326: case FCT: ! 28327: if (memof) ! 28328: if (Pfct(ptrto)->memof) { ! 28329: if (memof != Pfct(ptrto)->memof) error("P toMF mismatch: %s and %s",memof->string, Pfct(ptrto)->memof->string); ! 28330: } ! 28331: else ! 28332: Pfct(ptrto)->memof = memof; ! 28333: else ! 28334: memof = Pfct(ptrto)->memof; ! 28335: break; ! 28336: case RPTR: ! 28337: switch (base) { ! 28338: case PTR: error("P toR"); break; ! 28339: case RPTR: error("R toR"); break; ! 28340: } ! 28341: } ! 28342: ! 28343: if (t == 0) { ! 28344: Pbase b = Pbase(ptrto); ! 28345: if (Pfctvec_type ! 28346: && rdo==0 ! 28347: && b->b_unsigned==0 ! 28348: && b->b_const==0 ! 28349: && bc == 0 ! 28350: && memof==0 ! 28351: && base==PTR) { ! 28352: switch (b->base) { ! 28353: case INT: delete this; return Pint_type; ! 28354: case CHAR: delete this; return Pchar_type; ! 28355: case VOID: delete this; return Pvoid_type; ! 28356: } ! 28357: } ! 28358: if (base==RPTR && b->base==VOID) error("void& is not a validT"); ! 28359: return this; ! 28360: } ! 28361: ! 28362: switch (t->base) { ! 28363: case PTR: ! 28364: case RPTR: return Pptr(t)->normalize(this); ! 28365: case VEC: return Pvec(t)->normalize(this); ! 28366: case FCT: return Pfct(t)->normalize(this); ! 28367: default: error('i',"badPT(%k)",t->base); ! 28368: } ! 28369: } ! 28370: ! 28371: Ptype fct::normalize(Ptype ret) ! 28372: /* ! 28373: normalize return type ! 28374: */ ! 28375: { ! 28376: register Ptype t = returns; ! 28377: returns = ret; ! 28378: ! 28379: if (argtype && argtype->base==NAME && argtype->n_qualifier) { ! 28380: error("syntax: ANX"); ! 28381: argtype = 0; ! 28382: nargs = 0; ! 28383: nargs_known = 0; ! 28384: } ! 28385: ! 28386: while(ret->base == TYPE) ! 28387: ret = Pbase(ret)->b_name->tp; ! 28388: ! 28389: switch(ret->base) { ! 28390: case VEC: ! 28391: error("F returning array"); ! 28392: break; ! 28393: case FCT: ! 28394: error("F returningF"); ! 28395: returns = ret = t?t:int_type; ! 28396: break; ! 28397: default: ! 28398: break; ! 28399: } ! 28400: ! 28401: if (t == 0) return this; ! 28402: ! 28403: switch (t->base) { ! 28404: case PTR: ! 28405: case RPTR: return Pptr(t)->normalize(this); ! 28406: case VEC: return Pvec(t)->normalize(this); ! 28407: case FCT: return Pfct(t)->normalize(this); ! 28408: default: error('i',"badFT:%k",t->base); ! 28409: } ! 28410: } ! 28411: ! 28412: void fct::argdcl(Pname dcl, Pname fn) ! 28413: /* ! 28414: sort out the argument types for old syntax: ! 28415: f(a,b) int a; char b; { ... } ! 28416: beware of ! 28417: f(a) struct s { int a; }; struct s a; ! 28418: */ ! 28419: { ! 28420: Pname n; ! 28421: /*fprintf(stderr,"%d argtype %d %d dcl %d %d\n",this, argtype, argtype?argtype->base:0, dcl, dcl?dcl->base:0); fflush(stderr);*/ ! 28422: switch (base) { ! 28423: case FCT: break; ! 28424: case ANY: return; ! 28425: default: error('i',"fct::argdcl(%d)",base); ! 28426: } ! 28427: ! 28428: if (argtype) { ! 28429: switch (argtype->base) { ! 28430: case NAME: ! 28431: if (dcl) error("badF definition syntax"); ! 28432: for (n=argtype; n; n=n->n_list) { ! 28433: if (n->string == 0) n->string = make_name('A'); ! 28434: } ! 28435: return; ! 28436: case ELIST: // expression list: f(a,b,c) int a; ... { ... } ! 28437: // scan the elist and build a NAME list ! 28438: { ! 28439: Pname tail = 0; ! 28440: n = 0; ! 28441: ! 28442: error(strict_opt?0:'w',&fn->where,"old style definition of%n (anachronism)",fn); ! 28443: ! 28444: for (Pexpr e=Pexpr(argtype); e; e=e->e2) { ! 28445: Pexpr id = e->e1; ! 28446: if (id->base != NAME) { ! 28447: error("NX inAL"); ! 28448: argtype = 0; ! 28449: dcl = 0; ! 28450: break; ! 28451: } ! 28452: Pname nn = new name(id->string); ! 28453: if (n) ! 28454: tail = tail->n_list = nn; ! 28455: else ! 28456: tail = n = nn; ! 28457: } ! 28458: f_args = argtype = n; ! 28459: break; ! 28460: } ! 28461: default: ! 28462: error("ALX(%d)",argtype->base); ! 28463: argtype = 0; ! 28464: dcl = 0; ! 28465: } ! 28466: } ! 28467: else if(nargs_known == ELLIPSIS) { ! 28468: return; ! 28469: } ! 28470: else { ! 28471: nargs_known = 1; ! 28472: nargs = 0; ! 28473: if (dcl) error("ADL forFWoutAs"); ! 28474: return; ! 28475: } ! 28476: ! 28477: // nargs_known = 0; ! 28478: ! 28479: if (dcl) { ! 28480: Pname d; ! 28481: Pname dx; ! 28482: /* for each argument name see if its type is specified ! 28483: in the declaration list otherwise give it the default type ! 28484: */ ! 28485: ! 28486: for (n=argtype; n; n=n->n_list) { ! 28487: char* s = n->string; ! 28488: if (s == 0) { ! 28489: error("AN missing inF definition"); ! 28490: n->string = s = make_name('A'); ! 28491: } ! 28492: else if (n->tp) error("twoTs forA %s",n->string); ! 28493: ! 28494: for (d=dcl; d; d=d->n_list) { ! 28495: if (strcmp(s,d->string) == 0) { ! 28496: if (d->tp->base == VOID) { ! 28497: error("voidA%n",d); ! 28498: d->tp = any_type; ! 28499: } ! 28500: n->tp = d->tp; ! 28501: n->n_sto = d->n_sto; ! 28502: d->tp = 0; // now merged into argtype ! 28503: goto xx; ! 28504: } ! 28505: } ! 28506: n->tp = defa_type; ! 28507: xx:; ! 28508: if (n->tp == 0) error('i',"noT for %s",n->string); ! 28509: } ! 28510: ! 28511: /* now scan the declaration list for "unused declarations" ! 28512: and delete it ! 28513: */ ! 28514: for (d=dcl; d; d=dx) { ! 28515: dx = d->n_list; ! 28516: if (d->tp) { /* not merged with argtype list */ ! 28517: /*if (d->base == TNAME) ??? */ ! 28518: switch (d->tp->base) { ! 28519: case CLASS: ! 28520: case ENUM: ! 28521: /* WARNING: this will reverse the order of ! 28522: class and enum declarations ! 28523: */ ! 28524: d->n_list = argtype; ! 28525: f_args = argtype = d; ! 28526: break; ! 28527: default: ! 28528: error("%n inADL not inAL",d); ! 28529: } ! 28530: } ! 28531: } ! 28532: } ! 28533: ! 28534: /* add default argument types if necessary */ ! 28535: for (n=argtype; n; n=n->n_list) { ! 28536: if (n->tp == 0) n->tp = defa_type; ! 28537: nargs++; ! 28538: } ! 28539: } ! 28540: ! 28541: Pname cl_obj_vec; /* set if is_cl_obj() found a array of class objects */ ! 28542: Pname eobj; /* set if is_cl_obj() found an enum */ ! 28543: ! 28544: Pname type::is_cl_obj() ! 28545: /* ! 28546: returns this->b_name if this is a class object ! 28547: returns 0 and sets cl_obj_vec to this->b_name ! 28548: if this is a array of class objects ! 28549: returns 0 and sets eobj to this->b_name ! 28550: if this is an enum object ! 28551: else returns 0 ! 28552: */ ! 28553: { ! 28554: bit v = 0; ! 28555: register Ptype t = this; ! 28556: ! 28557: if (t == 0) return 0; ! 28558: eobj = 0; ! 28559: cl_obj_vec = 0; ! 28560: xx: ! 28561: switch (t->base) { ! 28562: case TYPE: ! 28563: t = Pbase(t)->b_name->tp; ! 28564: goto xx; ! 28565: ! 28566: case COBJ: ! 28567: if (v) { ! 28568: cl_obj_vec = Pbase(t)->b_name; ! 28569: return 0; ! 28570: } ! 28571: else ! 28572: return Pbase(t)->b_name; ! 28573: ! 28574: case VEC: ! 28575: t = Pvec(t)->typ; ! 28576: v=1; ! 28577: goto xx; ! 28578: ! 28579: case EOBJ: ! 28580: eobj = Pbase(t)->b_name; ! 28581: default: ! 28582: return 0; ! 28583: } ! 28584: } ! 28585: ! 28586: /* ! 28587: static Pname ! 28588: lookup(char* s, Pclass cl) ! 28589: { ! 28590: Pbcl bc = 0; ! 28591: Pname n = cl->memtbl->look(s,0); ! 28592: if ( n ) return n; ! 28593: Pname n2 = 0; ! 28594: for (Pbcl b=cl->baselist; b; b=b->next) { ! 28595: n = b->bclass->lookup(s,cl); ! 28596: if ( n == 0 ) continue; ! 28597: if ( n2 ) { // clash? ! 28598: } ! 28599: n2 = n; ! 28600: } ! 28601: } ! 28602: */ ! 28603: 0707071010112044371004440001630000160000010205100466055405600001000000011657norm2.c /*ident "@(#)ctrans:src/norm2.c 1.4" */ ! 28604: /************************************************************************ ! 28605: ! 28606: C++ source for cfront, the C++ compiler front-end ! 28607: written in the computer science research center of Bell Labs ! 28608: ! 28609: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 28610: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 28611: ! 28612: norm2.c: ! 28613: ! 28614: "normalization" handles problems which could have been handled ! 28615: by the syntax analyser; but has not been done. The idea is ! 28616: to simplify the grammar and the actions associated with it, ! 28617: and to get a more robust error handling ! 28618: ! 28619: ****************************************************************************/ ! 28620: ! 28621: #include "cfront.h" ! 28622: #include "size.h" ! 28623: ! 28624: #ifdef DBG ! 28625: long node_id = 0; ! 28626: #define DBCHECK() if(node::allocated) error('i',"allocated node (id %d, base%k) on free list! (src: \"%s\", %d",node::id,node::base,__FILE__,__LINE__); ! 28627: #else ! 28628: #define DBCHECK() /**/ ! 28629: #endif ! 28630: ! 28631: fct::fct(Ptype t, Pname arg, TOK known) ! 28632: { ! 28633: base = FCT; ! 28634: nargs_known = known; ! 28635: returns = t; ! 28636: argtype = arg; ! 28637: DBID(); ! 28638: ! 28639: if (arg==0 || arg->base==ELIST) return; ! 28640: //error('d',"fct::fct %d sig %d",this,f_signature); ! 28641: register Pname n; ! 28642: Pname pn = 0; ! 28643: for (n=arg; n; pn=n,n=n->n_list) { ! 28644: if( n->n_sto==EXTERN ) error("externA"); ! 28645: if( n->n_sto==STATIC ) error("static used forA%n",arg); ! 28646: ! 28647: switch (n->tp->base) { ! 28648: case VOID: ! 28649: argtype = 0; ! 28650: nargs_known = 1; ! 28651: if(n->n_initializer) ! 28652: error("voidFA"); ! 28653: else if (n->string) ! 28654: error("voidFA%n",n); ! 28655: else if (nargs || n->n_list) { ! 28656: error("voidFA"); ! 28657: nargs_known = 0; ! 28658: } ! 28659: nargs = 0; ! 28660: break; ! 28661: case CLASS: ! 28662: case ENUM: ! 28663: error("%k defined inAL (will not be in scope at point of call)",n->tp->base); ! 28664: if (n == argtype) ! 28665: argtype = n->n_list; ! 28666: else ! 28667: pn->n_list = n->n_list; ! 28668: break; ! 28669: default: ! 28670: nargs++; ! 28671: } ! 28672: } ! 28673: } ! 28674: ! 28675: expr::expr(TOK ba, Pexpr a, Pexpr b) ! 28676: { ! 28677: DBCHECK(); ! 28678: ! 28679: base = ba; ! 28680: e1 = a; ! 28681: e2 = b; ! 28682: DBID(); ! 28683: } ! 28684: ! 28685: stmt::stmt(TOK ba, loc ll, Pstmt a) ! 28686: { ! 28687: DBCHECK(); ! 28688: ! 28689: base = ba; ! 28690: where = ll; ! 28691: s=a; ! 28692: DBID(); ! 28693: } ! 28694: ! 28695: classdef::classdef(TOK b) ! 28696: { ! 28697: base = CLASS; ! 28698: csu = b; ! 28699: memtbl = new table(CTBLSIZE,0,0); ! 28700: DBID(); ! 28701: } ! 28702: ! 28703: classdef::~classdef() ! 28704: { ! 28705: delete memtbl; ! 28706: } ! 28707: ! 28708: basetype::basetype(TOK b, Pname n) ! 28709: { ! 28710: switch (b) { ! 28711: case 0: break; ! 28712: case TYPEDEF: b_typedef = 1; break; ! 28713: case INLINE: b_inline = 1; break; ! 28714: case VIRTUAL: b_virtual = 1; break; ! 28715: case CONST: b_const = 1; break; ! 28716: case UNSIGNED: b_unsigned = 1; break; ! 28717: case FRIEND: ! 28718: case OVERLOAD: ! 28719: case EXTERN: ! 28720: case STATIC: ! 28721: case AUTO: ! 28722: case REGISTER: b_sto = b; break; ! 28723: case SHORT: b_short = 1; break; ! 28724: case LONG: b_long = 1; break; ! 28725: case ANY: ! 28726: case ZTYPE: ! 28727: case VOID: ! 28728: case CHAR: ! 28729: case INT: ! 28730: case FLOAT: ! 28731: case LDOUBLE: ! 28732: case DOUBLE: base = b; break; ! 28733: case TYPE: ! 28734: case COBJ: ! 28735: case EOBJ: ! 28736: case FIELD: ! 28737: case ASM: ! 28738: base = b; ! 28739: b_name = n; ! 28740: break; ! 28741: case SIGNED: ! 28742: case VOLATILE: ! 28743: error('w',"\"%k\" not implemented (ignored)",b); ! 28744: break; ! 28745: default: ! 28746: error('i',"badBT:%k",b); ! 28747: } ! 28748: DBID(); ! 28749: } ! 28750: ! 28751: name::name(char* s) : expr(NAME,0,0) ! 28752: { ! 28753: // DBCHECK() called in expr::expr() ! 28754: string = s; ! 28755: where = curloc; ! 28756: lex_level = bl_level; ! 28757: } ! 28758: ! 28759: nlist::nlist(Pname n) ! 28760: { ! 28761: head = n; ! 28762: for (Pname nn=n; nn->n_list; nn=nn->n_list); ! 28763: tail = nn; ! 28764: } ! 28765: ! 28766: void nlist::add_list(Pname n) ! 28767: { ! 28768: if (n->tp && (n->tp->defined & IN_ERROR)) return; ! 28769: ! 28770: tail->n_list = n; ! 28771: for (Pname nn=n; nn->n_list; nn=nn->n_list); ! 28772: tail = nn; ! 28773: } ! 28774: ! 28775: Pname name_unlist(Pnlist l) ! 28776: { ! 28777: if (l == 0) return 0; ! 28778: Pname n = l->head; ! 28779: ! 28780: delete l; ! 28781: return n; ! 28782: } ! 28783: ! 28784: Pstmt stmt_unlist(Pslist l) ! 28785: { ! 28786: if (l == 0) return 0; ! 28787: Pstmt s = l->head; ! 28788: // NFl++; ! 28789: ! 28790: delete l; ! 28791: return s; ! 28792: } ! 28793: ! 28794: Pexpr expr_unlist(Pelist l) ! 28795: { ! 28796: if (l == 0) return 0; ! 28797: Pexpr e = l->head; ! 28798: // NFl++; ! 28799: ! 28800: delete l; ! 28801: return e; ! 28802: } ! 28803: ! 28804: void sig_name(Pname n) ! 28805: { ! 28806: static char buf[256]; ! 28807: buf[0] = '_'; ! 28808: buf[1] = '_'; ! 28809: buf[2] = 'o'; ! 28810: buf[3] = 'p'; ! 28811: char* p = n->tp->signature(buf+4); ! 28812: if (255 < p-buf) error('i',"sig_name():N buffer overflow"); ! 28813: char *s = new char [ p - buf + 1 ]; ! 28814: strcpy(s,buf); ! 28815: n->string = s; ! 28816: n->tp = 0; ! 28817: } ! 28818: ! 28819: Ptype tok_to_type(TOK b) ! 28820: { ! 28821: Ptype t; ! 28822: switch (b) { ! 28823: case CHAR: t = char_type; break; ! 28824: case SHORT: t = short_type; break; ! 28825: case LONG: t = long_type; break; ! 28826: case UNSIGNED: t = uint_type; break; ! 28827: case FLOAT: t = float_type; break; ! 28828: case DOUBLE: t = double_type; break; ! 28829: case LDOUBLE: t = ldouble_type; break; ! 28830: case VOID: t = void_type; break; ! 28831: default: error("illegalK:%k",b); ! 28832: case INT: t = int_type; ! 28833: } ! 28834: return t; ! 28835: } ! 28836: ! 28837: Pbase defa_type; ! 28838: Pbase moe_type; ! 28839: Pexpr dummy; ! 28840: Pexpr zero; ! 28841: ! 28842: Pclass ccl; ! 28843: Plist modified_tn = 0; ! 28844: ! 28845: Plist local_tn = 0; ! 28846: Plist local_blk = 0; ! 28847: Plist local_class = 0; ! 28848: ! 28849: Plist nested_tn = 0; ! 28850: Plist nested_type = 0; ! 28851: ! 28852: void memptrdcl(Pname bn, Pname tn, Ptype ft, Pname n) ! 28853: { ! 28854: Pptr p = new ptr(PTR,0); ! 28855: p->memof = Pclass(Pbase(bn->tp)->b_name->tp); ! 28856: Pbase b = new basetype(TYPE,tn); ! 28857: PERM(p); ! 28858: Pfct f = Pfct(ft); ! 28859: Ptype t = n->tp; ! 28860: if (t) { ! 28861: p->typ = t; ! 28862: ltlt: ! 28863: switch (t->base) { ! 28864: case PTR: ! 28865: case RPTR: ! 28866: case VEC: ! 28867: if (Pptr(t)->typ == 0) { ! 28868: Pptr(t)->typ = b; ! 28869: break; ! 28870: } ! 28871: t = Pptr(t)->typ; ! 28872: goto ltlt; ! 28873: default: ! 28874: error('s',"P toMFT too complicated"); ! 28875: } ! 28876: } ! 28877: else ! 28878: p->typ = b; ! 28879: f->returns = p; ! 28880: n->tp = f; ! 28881: } ! 28882: 0707071010112044401004440001630000160000010205200466055406200001000000061331print.c /*ident "@(#)ctrans:src/print.c 1.3" */ ! 28883: /************************************************************************** ! 28884: ! 28885: C++ source for cfront, the C++ compiler front-end ! 28886: written in the computer science research center of Bell Labs ! 28887: ! 28888: Copyright (c) 1984 AT&T, Inc. All rights Reserved ! 28889: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 28890: ! 28891: print.c: ! 28892: ! 28893: print statements and expressions ! 28894: ! 28895: ****************************************************************************/ ! 28896: ! 28897: #include "cfront.h" ! 28898: ! 28899: static int addrof_cm ; ! 28900: extern void puttok(TOK); ! 28901: ! 28902: /* ! 28903: void cprint(Pexpr e) ! 28904: { ! 28905: if (e == 0) return; ! 28906: //error('d',"%k %n %t",e->base,e->base==NAME?e:0,e->tp); ! 28907: // if ((e->base==NAME || e->base==ANAME) ! 28908: // && Pname(e)->n_evaluated==0) { ! 28909: Ptype t = e->tp; ! 28910: while (t->base == TYPE) t = Pbase(t)->b_name->tp; ! 28911: if (t->base == EOBJ) fprintf(out_file,"(int)"); ! 28912: // } ! 28913: ! 28914: Eprint(e); ! 28915: } ! 28916: */ ! 28917: #define cprint(e) if (e) Eprint(e) ! 28918: #define eprint(e) if (e) Eprint(e) ! 28919: ! 28920: void Eprint(Pexpr e) ! 28921: { ! 28922: switch (e->base) { ! 28923: case REF: ! 28924: if (Pref(e)->mem && Pref(e)->mem->tp && Pref(e)->mem->tp->base == FCT) { ! 28925: // suppress ``this'' in ``this->f'' ! 28926: Pref(e)->mem->print(); ! 28927: break; ! 28928: } ! 28929: case NAME: ! 28930: case MDOT: ! 28931: case ID: ! 28932: case ZERO: ! 28933: case ICON: ! 28934: case CCON: ! 28935: case FCON: ! 28936: case STRING: ! 28937: case IVAL: ! 28938: case TEXT: ! 28939: case CM: ! 28940: case G_CM: ! 28941: case ELIST: ! 28942: case COLON: ! 28943: case ILIST: ! 28944: case DOT: ! 28945: case THIS: ! 28946: case CALL: ! 28947: case G_CALL: ! 28948: case ICALL: ! 28949: case ANAME: ! 28950: e->print(); ! 28951: case DUMMY: ! 28952: break; ! 28953: default: ! 28954: putch('('); ! 28955: e->print(); ! 28956: putch(')'); ! 28957: } ! 28958: } ! 28959: ! 28960: void expr::print() ! 28961: { ! 28962: if (this == 0) error('i',"0->E::print()"); ! 28963: if (this==e1 || this==e2) error('i',"(%p%k)->E::print(%p %p)",this,base,e1,e2); ! 28964: // error('d',"(%d %k)->expr::print(%d %d)",this,base,e1,e2); ! 28965: ! 28966: switch (base) { ! 28967: case MDOT: ! 28968: { ! 28969: // error('d',"mdot %s i1 %d %t",string2,i1,mem->tp); ! 28970: int not_allocated = 0; ! 28971: switch (i1) { ! 28972: case 0: ! 28973: putcat('O',string2); ! 28974: puttok(DOT); // use sub-object directly ! 28975: mem->print(); ! 28976: break; ! 28977: case 1: ! 28978: putcat('P',string2); ! 28979: puttok(REF); // use through pointer ! 28980: mem->print(); ! 28981: break; ! 28982: case 2: ! 28983: if (mem->tp->is_ptr_or_ref()==0) { ! 28984: mem->print(); ! 28985: puttok(DOT); ! 28986: putcat('O',string2); ! 28987: } ! 28988: else ! 28989: { ! 28990: putch('('); // REF turns pointer into object: add & ! 28991: putch('&'); // ``this'' is a pointer ! 28992: putch('('); ! 28993: eprint(mem);//mem->print(); ! 28994: puttok(REF); // call sub-object directly ! 28995: putcat('O',string2); ! 28996: putch(')'); ! 28997: putch(')'); ! 28998: } ! 28999: break; ! 29000: case 5: ! 29001: not_allocated = 1; ! 29002: // no break; ! 29003: case 3: ! 29004: if (mem->tp->is_ptr_or_ref()==0) { ! 29005: putch('('); // Px is a pointer (T*) turn it back to a T ! 29006: putch('*'); // *Px ! 29007: putch('('); ! 29008: eprint(mem);//mem->print(); ! 29009: puttok(DOT); // call through pointer ! 29010: putcat('P',string2); ! 29011: putch(')'); ! 29012: putch(')'); ! 29013: } ! 29014: else { ! 29015: // eprint(mem); // <<< mem->print() ! 29016: if (not_allocated) { ! 29017: putch('('); ! 29018: mem->print(); ! 29019: if ( mem->base == NAME ) ! 29020: puttok(REF); ! 29021: else puttok(DOT); ! 29022: putcat('O',string4); ! 29023: putch(')'); ! 29024: } ! 29025: else eprint(mem); ! 29026: if (mem->base == NAME && not_allocated) ! 29027: puttok(DOT); ! 29028: else puttok(REF); // call through pointer ! 29029: putcat('P',string2); ! 29030: } ! 29031: break; ! 29032: case 9: // vtbl entry: (p->_vtbl).f, (p->_vtbl).i, (p->_vtbl).d ! 29033: // or memptr: mp.f, mp.i, mp.d ! 29034: eprint(mem); ! 29035: putch('.'); ! 29036: putstring(string2); ! 29037: } // end switch(i1) ! 29038: break; ! 29039: } // end MDOT ! 29040: ! 29041: case NAME: ! 29042: { Pname n = Pname(this); ! 29043: if (n->n_evaluated ! 29044: // && n->tp->base!=EOBJ // this output enumerators ! 29045: && n->n_scope!=ARG) { ! 29046: Ptype t = tp; ! 29047: while (t->base == TYPE) t = Pbase(t)->b_name->tp; ! 29048: if (t->base == EOBJ) t = Penum(Pbase(t)->b_name->tp)->e_type; ! 29049: if (t->base!=INT || t->is_unsigned()) { ! 29050: putstring("(("); ! 29051: bit oc = Cast; ! 29052: Cast = 1; ! 29053: t->print(); ! 29054: Cast = oc; ! 29055: fprintf(out_file,")%d)",n->n_val); ! 29056: } ! 29057: else ! 29058: fprintf(out_file,"%d",n->n_val); ! 29059: } ! 29060: else ! 29061: n->print(); ! 29062: break; ! 29063: } ! 29064: case ANAME: ! 29065: if (curr_icall) { // in expansion: look it up ! 29066: Pname n = Pname(this); ! 29067: int argno = int(n->n_val); ! 29068: ! 29069: for (Pin il=curr_icall; il; il=il->i_next) ! 29070: if (n->n_table == il->i_table) goto aok; ! 29071: goto bok; ! 29072: aok: ! 29073: if (n = il->i_args[argno].local) { ! 29074: n->print(); ! 29075: } ! 29076: else { ! 29077: Pexpr ee = il->i_args[argno].arg; ! 29078: Ptype t = il->i_args[argno].tp; ! 29079: if (ee==0 || ee==this) error('i',"%p->E::print(A %p)",this,ee); ! 29080: if (ee->tp==0 ! 29081: || (t!=ee->tp ! 29082: && t->check(ee->tp,0) ! 29083: && t->is_cl_obj()==0 ! 29084: // && eobj==0) ! 29085: ) ! 29086: ) { ! 29087: putstring("(("); ! 29088: bit oc = Cast; ! 29089: Cast = 1; ! 29090: t->print(); ! 29091: Cast = oc; ! 29092: putch(')'); ! 29093: // eprint(ee); ! 29094: // if (ee->base == CAST) { ! 29095: // eprint(ee->e1); ! 29096: // } ! 29097: // else ! 29098: eprint(ee); ! 29099: putch(')'); ! 29100: } ! 29101: else ! 29102: eprint(ee); ! 29103: } ! 29104: } ! 29105: else { ! 29106: bok: /* in body: print it: */ ! 29107: Pname(this)->print(); ! 29108: } ! 29109: break; ! 29110: ! 29111: case ICALL: ! 29112: { il->i_next = curr_icall; ! 29113: curr_icall = il; ! 29114: //error('d',"icall %n",il->fct_name); ! 29115: if (il == 0) error('i',"E::print: iline missing"); ! 29116: Pexpr a0 = il->i_args[0].arg; ! 29117: int val = QUEST; ! 29118: if (il->fct_name->n_oper != CTOR) goto dumb; ! 29119: ! 29120: /* ! 29121: find the value of "this" ! 29122: if the argument is a "this" NOT assigned to ! 29123: by the programmer, it was initialized ! 29124: */ ! 29125: switch (a0->base) { ! 29126: case ZERO: ! 29127: val = 0; ! 29128: break; ! 29129: case ADDROF: ! 29130: case G_ADDROF: ! 29131: val = 1; ! 29132: break; ! 29133: case CAST: ! 29134: if (a0->e1->base == ANAME || a0->e1->base == NAME) { ! 29135: Pname a = (Pname)a0->e1; ! 29136: if (a->n_assigned_to == FUDGE111) val = FUDGE111; ! 29137: } ! 29138: } ! 29139: if (val==QUEST) goto dumb; ! 29140: /* ! 29141: now find the test: "(this==0) ? _new(sizeof(X)) : 0" ! 29142: ! 29143: e1 is a comma expression, ! 29144: the test is either the first sub-expression ! 29145: or the first sub-expression after the assignments ! 29146: initializing temporary variables ! 29147: */ ! 29148: dumb: ! 29149: eprint(e1); ! 29150: if (e2) Pstmt(e2)->print(); ! 29151: curr_icall = il->i_next; ! 29152: break; ! 29153: } ! 29154: case REF: ! 29155: case DOT: ! 29156: eprint(e1); ! 29157: puttok(base); ! 29158: if (mem == 0) { ! 29159: fprintf(out_file,"MEM0"); ! 29160: break; ! 29161: } ! 29162: if (mem->base == NAME) ! 29163: Pname(mem)->print(); ! 29164: else ! 29165: mem->print(); ! 29166: break; ! 29167: ! 29168: case MEMPTR: ! 29169: error("P toMF not called"); ! 29170: break; ! 29171: ! 29172: case VALUE: ! 29173: tp2->print(); ! 29174: puttok(LP); ! 29175: ! 29176: // if (e2) { ! 29177: // putstring(" &"); ! 29178: // e2->print(); ! 29179: // putstring(", "); ! 29180: // } ! 29181: if (e1) e1->print(); ! 29182: puttok(RP); ! 29183: break; ! 29184: ! 29185: case SIZEOF: ! 29186: puttok(SIZEOF); ! 29187: if (e1 && e1!=dummy) { ! 29188: eprint(e1); ! 29189: } ! 29190: else if (tp2) { ! 29191: putch('('); ! 29192: if (tp2->base == CLASS) { ! 29193: Pclass cl = Pclass(tp2); ! 29194: putstring((cl->csu == UNION)?"union ":"struct "); ! 29195: char *str = 0; ! 29196: // nested local class does not encode name ! 29197: if ( cl->lex_level && cl->nested_sig == 0 ) ! 29198: str = make_local_name( cl ); ! 29199: putstring(str?str:(cl->nested_sig?cl->nested_sig:cl->string)); ! 29200: delete str; ! 29201: } ! 29202: else ! 29203: tp2->print(); ! 29204: putch(')'); ! 29205: } ! 29206: break; ! 29207: ! 29208: /* ! 29209: // always turned into function calls: ! 29210: case NEW: ! 29211: case GNEW: ! 29212: // error('d',"print new %d tp2 %t e1 %d e2 %d",base,tp2,e1,e2); ! 29213: puttok(NEW); ! 29214: tp2->print(); ! 29215: if (e1) { ! 29216: putch('('); ! 29217: e1->print(); ! 29218: putch(')'); ! 29219: } ! 29220: break; ! 29221: ! 29222: case DELETE: ! 29223: case GDELETE: ! 29224: //error('d',"print delete"); ! 29225: puttok(DELETE); ! 29226: e1->print(); ! 29227: break; ! 29228: */ ! 29229: case CAST: ! 29230: putch('('); ! 29231: //error('d',"print cast %t",tp2); ! 29232: if (tp2->base != VOID && tp2->memptr() == 0 ) { ! 29233: // when VOID is represented as CHAR not everything ! 29234: // can be cast to VOID ! 29235: putch('('); ! 29236: bit oc = Cast; ! 29237: Cast = 1; ! 29238: tp2->print(); ! 29239: Cast = oc; ! 29240: putch(')'); ! 29241: } ! 29242: eprint(e1); ! 29243: putch(')'); ! 29244: break; ! 29245: ! 29246: case ICON: ! 29247: case FCON: ! 29248: case CCON: ! 29249: case ID: ! 29250: if (string) putst(string); ! 29251: break; ! 29252: ! 29253: case STRING: ! 29254: // avoid printing very long lines ! 29255: ntok += 4; ! 29256: fprintf(out_file,"\"%s\"",string); ! 29257: break; ! 29258: ! 29259: case THIS: ! 29260: case ZERO: ! 29261: putstring("0 "); ! 29262: break; ! 29263: ! 29264: case IVAL: ! 29265: fprintf(out_file,"%d",i1); ! 29266: break; ! 29267: ! 29268: case TEXT: ! 29269: { ! 29270: int oo = vtbl_opt; // make `simulated static' name ! 29271: vtbl_opt = -1; ! 29272: char* s = vtbl_name(string,string2); ! 29273: vtbl_opt = oo; ! 29274: s[2] = 'p'; // pointer, not tbl itself ! 29275: char* t = ptbl_lookup(s); ! 29276: fprintf(out_file, " %s",t); ! 29277: delete t; ! 29278: ! 29279: char *str = 0; ! 29280: if ( string ) { ! 29281: str = new char[ strlen(string) + strlen(string2) + 1 ]; ! 29282: strcpy( str, string ); ! 29283: strcat( str, string2 ); ! 29284: } ! 29285: ! 29286: if ( ptbl->look( str?str:string2, 0 ) == 0 && ! 29287: ptbl->look( str?str:string2, HIDDEN ) == 0 ) { ! 29288: Pname nn = ptbl->insert(new name(str?str:string2),0); ! 29289: nn->string2 = new char[strlen(s)+1]; ! 29290: strcpy(nn->string2,s); ! 29291: } ! 29292: ! 29293: delete str; ! 29294: delete s; ! 29295: } ! 29296: // no break; ! 29297: ! 29298: case DUMMY: ! 29299: break; ! 29300: ! 29301: case G_CALL: ! 29302: case CALL: ! 29303: { Pname fn = fct_name; ! 29304: Pname at; ! 29305: int m_ptr = 0; ! 29306: ! 29307: if (fn) { ! 29308: Pfct f = Pfct(fn->tp); ! 29309: ! 29310: if (f->base==OVERLOAD) { // overloaded after call ! 29311: fct_name = fn = Pgen(f)->fct_list->f; ! 29312: f = Pfct(fn->tp); ! 29313: } ! 29314: ! 29315: fn->print(); ! 29316: at = f->f_args; ! 29317: } ! 29318: else { ! 29319: Pfct f = Pfct(e1->tp); ! 29320: ! 29321: if (f) { // pointer to fct ! 29322: Pexpr exex = e1; ! 29323: if ( exex->base == DEREF ) { ! 29324: exex = exex->e1; ! 29325: while ( exex->base == CAST ) ! 29326: exex = exex->e1; ! 29327: if ( exex->base == MDOT ) ! 29328: m_ptr = 1; ! 29329: } ! 29330: ! 29331: if (f->base == OVERLOAD) { // overloaded after call ! 29332: fct_name = fn = Pgen(f)->fct_list->f; ! 29333: f = Pfct(fn->tp); ! 29334: } ! 29335: ! 29336: while (f->base == TYPE) f = Pfct(Pbase(f)->b_name->tp); ! 29337: if (f->base == PTR) { ! 29338: putstring("(*"); ! 29339: e1->print(); ! 29340: putch(')'); ! 29341: f = Pfct(Pptr(f)->typ); ! 29342: while (f->base == TYPE) f = Pfct(Pbase(f)->b_name->tp); ! 29343: } ! 29344: else ! 29345: eprint(e1); ! 29346: ! 29347: // at = (f->f_result) ? f->f_result : f->argtype; ! 29348: at = f->f_args; ! 29349: } ! 29350: else { // virtual: argtype encoded ! 29351: // f_this already linked to f_result and/or argtype ! 29352: at = (e1->base==QUEST) ? Pname(e1->e1->tp2) : Pname(e1->tp2); ! 29353: eprint(e1); ! 29354: } ! 29355: } ! 29356: ! 29357: puttok(LP); ! 29358: ! 29359: if (e2) { ! 29360: if (at) { ! 29361: Pexpr e = e2; ! 29362: while (at) { ! 29363: Pexpr ex; ! 29364: Ptype t = at->tp; ! 29365: ! 29366: if (t == 0) error('i',"T ofA missing for%n",fn); ! 29367: if (e == 0) error('i',"%tA missing for%n",t,fn); ! 29368: if (e->base == ELIST) { ! 29369: ex = e->e1; ! 29370: e = e->e2; ! 29371: } ! 29372: else ! 29373: ex = e; ! 29374: ! 29375: if (ex == 0) error('i',"A ofT%t missing",t); ! 29376: if (t!=ex->tp ! 29377: && ex->tp ! 29378: && t->check(ex->tp,0) ! 29379: && t->is_cl_obj()==0 ! 29380: && eobj==0 ! 29381: && m_ptr == 0 ! 29382: && (t->is_ptr()==0 || Mptr==0)) { ! 29383: putch('('); ! 29384: bit oc = Cast; ! 29385: Cast = 1; ! 29386: t->print(); ! 29387: Cast = oc; ! 29388: putch(')'); ! 29389: #ifdef sun ! 29390: if (ex->base == DIV) { // defend against perverse SUN cc bug ! 29391: putstring("(0+"); ! 29392: eprint(ex); ! 29393: putch(')'); ! 29394: } ! 29395: else ! 29396: #endif ! 29397: // eprint(ex); ! 29398: // if (ex->base==CAST) { ! 29399: // eprint(ex->e1); ! 29400: // } ! 29401: // else ! 29402: eprint(ex); ! 29403: } ! 29404: else ! 29405: ex->print(); ! 29406: ! 29407: // if m_ptr is set, then don't advance at ! 29408: // at does not know about generated `this' ! 29409: if ( m_ptr ) { ! 29410: m_ptr = 0; ! 29411: if (at) puttok(CM); ! 29412: continue; ! 29413: } ! 29414: ! 29415: at = at->n_list; ! 29416: if (at) puttok(CM); ! 29417: } ! 29418: if (e) { ! 29419: puttok(CM); ! 29420: e->print(); ! 29421: } ! 29422: } ! 29423: else ! 29424: e2->print(); ! 29425: } ! 29426: puttok(RP); ! 29427: break; ! 29428: } ! 29429: ! 29430: case ASSIGN: ! 29431: if (e1->base==ANAME && Pname(e1)->n_assigned_to==FUDGE111) { ! 29432: // suppress assignment to "this" that has been optimized away ! 29433: Pname n = Pname(e1); ! 29434: int argno = int(n->n_val); ! 29435: for (Pin il=curr_icall; il; il=il->i_next) ! 29436: if (il->i_table == n->n_table) goto akk; ! 29437: goto bkk; ! 29438: akk: ! 29439: if (il->i_args[argno].local == 0) { ! 29440: e2->print(); ! 29441: break; ! 29442: } ! 29443: } ! 29444: //no break ! 29445: case EQ: ! 29446: case NE: ! 29447: case GT: ! 29448: case GE: ! 29449: case LE: ! 29450: case LT: ! 29451: bkk: ! 29452: { Ptype t1 = e1->tp; ! 29453: Ptype t2 = e2->tp; ! 29454: ! 29455: if (base!=ASSIGN) { ! 29456: cprint(e1); ! 29457: } ! 29458: else ! 29459: eprint(e1); ! 29460: puttok(base); ! 29461: ! 29462: if (t1 && t1!=t2 && e2->base!=ZERO) { ! 29463: // cast, but beware of int!=long etc. ! 29464: cmp: ! 29465: switch (t1->base) { ! 29466: case TYPE: ! 29467: t1 = Pbase(t1)->b_name->tp; ! 29468: goto cmp; ! 29469: default: ! 29470: // if (e2->base==NAME ! 29471: // && Pname(e2)->n_evaluated==0 ! 29472: // && e2->tp->base==EOBJ) ! 29473: // fprintf(out_file,"(int)"); ! 29474: break; ! 29475: // case EOBJ: ! 29476: // if (base==ASSIGN) goto cst; ! 29477: // break; ! 29478: case PTR: ! 29479: case RPTR: ! 29480: case VEC: ! 29481: if (t2) ! 29482: while ( t2->base == TYPE ) ! 29483: t2 = Pbase(t2)->b_name->tp; ! 29484: ! 29485: if (e2->tp==0 ! 29486: || (Pptr(t1)->typ!=Pptr(t2)->typ && t1->check(t2,0))) { ! 29487: // cst: ! 29488: putch('('); ! 29489: bit oc = Cast; ! 29490: Cast = 1; ! 29491: e1->tp->print(); ! 29492: Cast = oc; ! 29493: putch(')'); ! 29494: } ! 29495: } ! 29496: } ! 29497: ! 29498: eprint(e2); ! 29499: break; ! 29500: } ! 29501: ! 29502: case DEREF: ! 29503: if (e2) { ! 29504: ! 29505: eprint(e1); ! 29506: putch('['); ! 29507: cprint(e2); ! 29508: putch(']'); ! 29509: } ! 29510: else { ! 29511: putch('('); ! 29512: putch('*'); ! 29513: eprint(e1); ! 29514: putch(')'); ! 29515: } ! 29516: break; ! 29517: ! 29518: case ILIST: ! 29519: puttok(LC); ! 29520: if (e1) e1->print(); ! 29521: if (e2) { // member pointer initiliazers ! 29522: puttok(CM); ! 29523: e2->print(); ! 29524: } ! 29525: puttok(RC); ! 29526: break; ! 29527: ! 29528: case ELIST: ! 29529: { Pexpr e = this; ! 29530: for(;;) { ! 29531: if (e->base == ELIST) { ! 29532: e->e1->print(); ! 29533: if (e = e->e2) { ! 29534: puttok(CM); ! 29535: } ! 29536: else ! 29537: return; ! 29538: } ! 29539: else { ! 29540: e->print(); ! 29541: return; ! 29542: } ! 29543: } ! 29544: } ! 29545: ! 29546: case QUEST: ! 29547: { // look for (&a == 0) etc. ! 29548: Neval = 0; ! 29549: binary_val = 1; ! 29550: long i = cond->eval(); ! 29551: binary_val = 0; ! 29552: if (Neval == 0) ! 29553: (i?e1:e2)->print(); ! 29554: else { ! 29555: eprint(cond); ! 29556: putch('?'); ! 29557: cprint(e1); ! 29558: putch(':'); ! 29559: cprint(e2); ! 29560: } ! 29561: break; ! 29562: } ! 29563: ! 29564: case CM: // do &(a,b) => (a,&b) for previously checked inlines ! 29565: case G_CM: ! 29566: puttok(LP); ! 29567: switch (e1->base) { ! 29568: case ZERO: ! 29569: case IVAL: ! 29570: case ICON: ! 29571: case NAME: ! 29572: case MDOT: ! 29573: case DOT: ! 29574: case REF: ! 29575: case FCON: ! 29576: // case FVAL: ! 29577: case STRING: ! 29578: goto le2; // suppress constant a: &(a,b) => (&b) ! 29579: default: ! 29580: { int oo = addrof_cm; // &(a,b) does not affect a ! 29581: addrof_cm = 0; ! 29582: eprint(e1); ! 29583: addrof_cm = oo; ! 29584: } ! 29585: puttok(CM); ! 29586: le2: ! 29587: if (addrof_cm) { ! 29588: switch (e2->base) { ! 29589: case CAST: ! 29590: if (e2->e2) ! 29591: switch (e2->e2->base) { ! 29592: case CM: ! 29593: case G_CM: ! 29594: case ICALL: goto ec; ! 29595: } ! 29596: case NAME: ! 29597: case MDOT: ! 29598: case DOT: ! 29599: case DEREF: ! 29600: case REF: ! 29601: case ANAME: ! 29602: puttok(ADDROF); ! 29603: addrof_cm--; ! 29604: eprint(e2); ! 29605: addrof_cm++; ! 29606: break; ! 29607: case ICALL: ! 29608: // case CALL: ! 29609: case CM: ! 29610: case G_CM: ! 29611: ec: ! 29612: eprint(e2); ! 29613: break; ! 29614: case G_CALL: ! 29615: /* & ( e, ctor() ) with temporary optimized away */ ! 29616: if (e2->fct_name ! 29617: && e2->fct_name->n_oper==CTOR) { ! 29618: addrof_cm--; ! 29619: eprint(e2); ! 29620: addrof_cm++; ! 29621: break; ! 29622: } ! 29623: default: ! 29624: error('i',"& inlineF call (%k)",e2->base); ! 29625: } ! 29626: } ! 29627: else ! 29628: // e2->print(); ! 29629: eprint(e2); ! 29630: puttok(RP); ! 29631: } ! 29632: break; ! 29633: ! 29634: case UPLUS: // only preserved for ansi_opt==1 ! 29635: case UMINUS: ! 29636: case NOT: ! 29637: case COMPL: ! 29638: // puttok(base); ! 29639: // eprint(e2); ! 29640: // break; ! 29641: goto op2; ! 29642: case ADDROF: ! 29643: case G_ADDROF: ! 29644: switch (e2->base) { // & *e1 or &e1[e2] ! 29645: case DEREF: ! 29646: if (e2->e2 == 0) { // &*e == e ! 29647: e2->e1->print(); ! 29648: return; ! 29649: } ! 29650: break; ! 29651: case ICALL: ! 29652: addrof_cm++; // assumes inline expanded into ,-expression ! 29653: eprint(e2); ! 29654: addrof_cm--; ! 29655: return; ! 29656: case ASSIGN: // &(a=b) ??? works on many cc s ! 29657: eprint(e2); // make sure it breaks! ! 29658: return; ! 29659: case NAME: { ! 29660: Pname n = Pname(e2); ! 29661: if(n->n_evaluated) { ! 29662: n->n_evaluated=0; ! 29663: puttok(ADDROF); ! 29664: eprint(e2); ! 29665: n->n_evaluated=1; ! 29666: return; ! 29667: } ! 29668: break; ! 29669: } ! 29670: } ! 29671: ! 29672: // suppress cc warning on &fct ! 29673: if (e2->tp==0 || e2->tp->base!=FCT) puttok(ADDROF); ! 29674: ! 29675: eprint(e2); ! 29676: break; ! 29677: ! 29678: case PLUS: ! 29679: case MINUS: ! 29680: case MUL: ! 29681: case DIV: ! 29682: case MOD: ! 29683: case LS: ! 29684: case RS: ! 29685: case AND: ! 29686: case OR: ! 29687: case ER: ! 29688: case ANDAND: ! 29689: case OROR: ! 29690: case DECR: ! 29691: case INCR: ! 29692: cprint(e1); ! 29693: op2: ! 29694: puttok(base); ! 29695: cprint(e2); ! 29696: break; ! 29697: case ASOR: ! 29698: case ASER: ! 29699: case ASAND: ! 29700: case ASPLUS: ! 29701: case ASMINUS: ! 29702: case ASMUL: ! 29703: case ASMOD: ! 29704: case ASDIV: ! 29705: case ASLS: ! 29706: case ASRS: ! 29707: eprint(e1); ! 29708: goto op2; ! 29709: ! 29710: default: ! 29711: error('i',"%p->E::print%k",this,base); ! 29712: // fprintf(out_file," EEE(%d) ",base); ! 29713: } ! 29714: } ! 29715: ! 29716: Pexpr aval(Pname a) ! 29717: { ! 29718: int argno = int(a->n_val); ! 29719: Pin il; ! 29720: for (il=curr_icall; il; il=il->i_next) ! 29721: if (il->i_table == a->n_table) goto aok; ! 29722: return 0; ! 29723: aok: ! 29724: Pexpr aa = il->i_args[argno].arg; ! 29725: ll: ! 29726: switch (aa->base) { ! 29727: case CAST: aa = aa->e1; goto ll; ! 29728: case ANAME: return aval(Pname(aa)); ! 29729: default: return aa; ! 29730: } ! 29731: } ! 29732: ! 29733: #define putcond() putch('('); e->print(); putch(')') ! 29734: ! 29735: static loc csloc = { 0, 0 }; // loc of last stmt with line!=0 ! 29736: ! 29737: void stmt::print() ! 29738: { ! 29739: //error('d',"S::print %d:%k s %d s_list %d",this,base,s,s_list); ! 29740: if (where.line == 0) { ! 29741: if (csloc.line) csloc.putline(); ! 29742: } else { ! 29743: csloc = where; ! 29744: if (where.line!=last_line.line) ! 29745: if (last_ll = where.line) ! 29746: where.putline(); ! 29747: else ! 29748: last_line.putline(); ! 29749: } ! 29750: ! 29751: if (memtbl && base!=BLOCK) { /* also print declarations of temporaries */ ! 29752: puttok(LC); ! 29753: Ptable tbl = memtbl; ! 29754: memtbl = 0; ! 29755: int i; ! 29756: int bl = 1; ! 29757: for (Pname n=tbl->get_mem(i=1); n; n=tbl->get_mem(++i)){ ! 29758: if (n->tp == any_type) continue; ! 29759: /* avoid double declarartion of temporaries from inlines */ ! 29760: char* s = n->string; ! 29761: if (s[0]!='_' || s[1]!='_' || s[2]!='X') { ! 29762: n->dcl_print(0); ! 29763: bl = 0; ! 29764: } ! 29765: Pname cn; ! 29766: if (bl ! 29767: && (cn=n->tp->is_cl_obj()) ! 29768: && Pclass(cn->tp)->has_dtor()) bl = 0; ! 29769: } ! 29770: if ( last_ll==0 && (last_ll = where.line) ) ! 29771: where.putline(); ! 29772: if (bl) { ! 29773: Pstmt sl = s_list; ! 29774: s_list = 0; ! 29775: print(); ! 29776: memtbl = tbl; ! 29777: puttok(RC); ! 29778: if (sl) { ! 29779: s_list = sl; ! 29780: sl->print(); ! 29781: } ! 29782: } ! 29783: else { ! 29784: print(); ! 29785: memtbl = tbl; ! 29786: puttok(RC); ! 29787: } ! 29788: return; ! 29789: } ! 29790: ! 29791: switch (base) { ! 29792: default: ! 29793: error('i',"S::print(base=%k)",base); ! 29794: ! 29795: case ASM: ! 29796: fprintf(out_file,"asm(\"%s\");\n",(char*)e); ! 29797: break; ! 29798: ! 29799: case DCL: ! 29800: d->dcl_print(SM); ! 29801: break; ! 29802: ! 29803: case BREAK: ! 29804: case CONTINUE: ! 29805: puttok(base); ! 29806: puttok(SM); ! 29807: break; ! 29808: ! 29809: case DEFAULT: ! 29810: puttok(base); ! 29811: //puttok(COLON); ! 29812: putch(':'); ! 29813: s->print(); ! 29814: break; ! 29815: ! 29816: case SM: ! 29817: if (e) { ! 29818: e->print(); ! 29819: if (e->base==ICALL && e->e2) break; /* a block: no SM */ ! 29820: } ! 29821: puttok(SM); ! 29822: break; ! 29823: ! 29824: case WHILE: ! 29825: puttok(WHILE); ! 29826: putcond(); ! 29827: if (s->s_list) { ! 29828: puttok(LC); ! 29829: s->print(); ! 29830: puttok(RC); ! 29831: } ! 29832: else ! 29833: s->print(); ! 29834: break; ! 29835: ! 29836: case DO: ! 29837: puttok(DO); ! 29838: s->print(); ! 29839: puttok(WHILE); ! 29840: putcond(); ! 29841: puttok(SM); ! 29842: break; ! 29843: ! 29844: case SWITCH: ! 29845: puttok(SWITCH); ! 29846: putcond(); ! 29847: s->print(); ! 29848: break; ! 29849: ! 29850: case RETURN: ! 29851: { ! 29852: puttok(RETURN); ! 29853: if (e) { ! 29854: //error('d',"print return rt %t etp %t",ret_tp,e->tp); ! 29855: if (ret_tp && ret_tp!=e->tp) { ! 29856: Ptype tt = ret_tp; ! 29857: gook: ! 29858: switch (tt->base) { ! 29859: case TYPE: ! 29860: tt = Pbase(tt)->b_name->tp; ! 29861: goto gook; ! 29862: case COBJ: ! 29863: break; // cannot cast to struct ! 29864: case RPTR: ! 29865: case PTR: ! 29866: if (Pptr(tt)->typ==Pptr(e->tp)->typ) break; ! 29867: if (Pptr(tt)->memof) break; ! 29868: default: ! 29869: if (e->tp==0 || ret_tp->check(e->tp,0)) { ! 29870: int oc = Cast; ! 29871: putch('('); ! 29872: Cast = 1; ! 29873: ret_tp->print(); ! 29874: Cast = oc; ! 29875: putch(')'); ! 29876: } ! 29877: } ! 29878: } ! 29879: eprint(e); ! 29880: } ! 29881: puttok(SM); ! 29882: } ! 29883: while (s_list && s_list->base==SM) s_list = s_list->s_list; // FUDGE!! ! 29884: break; ! 29885: ! 29886: case CASE: ! 29887: puttok(CASE); ! 29888: eprint(e); ! 29889: putch(':'); ! 29890: s->print(); ! 29891: break; ! 29892: ! 29893: case GOTO: ! 29894: puttok(GOTO); ! 29895: d->print(); ! 29896: puttok(SM); ! 29897: break; ! 29898: ! 29899: case LABEL: ! 29900: d->print(); ! 29901: putch(':'); ! 29902: s->print(); ! 29903: break; ! 29904: ! 29905: case IF: ! 29906: { int val = QUEST; ! 29907: if (e->base == ANAME) { ! 29908: Pname a = Pname(e); ! 29909: Pexpr arg = aval(a); ! 29910: //error('d',"arg %d%k %d (%d)",arg,arg?arg->base:0,arg?arg->base:0,arg?arg->e1:0); ! 29911: if (arg) ! 29912: switch (arg->base) { ! 29913: case ZERO: val = 0; break; ! 29914: case ADDROF: ! 29915: case G_ADDROF: val = 1; break; ! 29916: case IVAL: val = arg->i1!=0; ! 29917: } ! 29918: } ! 29919: //error('d',"val %d",val); ! 29920: switch (val) { ! 29921: case 1: ! 29922: s->print(); ! 29923: break; ! 29924: case 0: ! 29925: if (else_stmt) ! 29926: else_stmt->print(); ! 29927: else ! 29928: puttok(SM); /* null statement */ ! 29929: break; ! 29930: default: ! 29931: puttok(IF); ! 29932: putcond(); ! 29933: if (s->s_list) { ! 29934: puttok(LC); ! 29935: s->print(); ! 29936: puttok(RC); ! 29937: } ! 29938: else ! 29939: s->print(); ! 29940: if (else_stmt) { ! 29941: if (else_stmt->where.line == 0) { ! 29942: if (csloc.line) csloc.putline(); ! 29943: } else { ! 29944: csloc = else_stmt->where; ! 29945: if (else_stmt->where.line!=last_line.line) ! 29946: if (last_ll = else_stmt->where.line) ! 29947: else_stmt->where.putline(); ! 29948: else ! 29949: last_line.putline(); ! 29950: } ! 29951: puttok(ELSE); ! 29952: if (else_stmt->s_list) { ! 29953: puttok(LC); ! 29954: else_stmt->print(); ! 29955: puttok(RC); ! 29956: } ! 29957: else ! 29958: else_stmt->print(); ! 29959: } ! 29960: } ! 29961: break; ! 29962: } ! 29963: ! 29964: case FOR: ! 29965: { ! 29966: // int fi = for_init && ((for_init->base!=SM || for_init->memtbl || for_init->s_list); ! 29967: int fi = 0; // is the initializer statement an expression? ! 29968: if (for_init) { ! 29969: fi = 1; ! 29970: if (for_init->memtbl==0 && for_init->s_list==0) ! 29971: if (for_init->base==SM) ! 29972: if (for_init->e->base!=ICALL || for_init->e->e1) ! 29973: fi = 0; ! 29974: } ! 29975: //error('d',"for(; %d%k; %d%k)",e,e->base,e2,e2->base); ! 29976: if (fi) { ! 29977: puttok(LC); ! 29978: for_init->print(); ! 29979: } ! 29980: putstring("for("); ! 29981: if (fi==0 && for_init) for_init->e->print(); ! 29982: putch(';'); // to avoid newline: not puttok(SM) ! 29983: if (e) e->print(); ! 29984: putch(';'); ! 29985: if (e2) e2->print(); ! 29986: puttok(RP); ! 29987: s->print(); ! 29988: if (fi) puttok(RC); ! 29989: break; ! 29990: } ! 29991: ! 29992: case PAIR: ! 29993: if (s&&s2) { ! 29994: puttok(LC); ! 29995: s->print(); ! 29996: s2->print(); ! 29997: puttok(RC); ! 29998: } ! 29999: else { ! 30000: if (s) s->print(); ! 30001: if (s2) s2->print(); ! 30002: } ! 30003: break; ! 30004: ! 30005: case BLOCK: ! 30006: puttok(LC); ! 30007: //error('d',"block %d d %d memtbl %d own_tbl %d",this,d,memtbl,own_tbl); ! 30008: if (d) d->dcl_print(SM); ! 30009: if (memtbl && own_tbl) { ! 30010: Pname n; ! 30011: int i; ! 30012: for (n=memtbl->get_mem(i=1); n; n=memtbl->get_mem(++i)) { ! 30013: if (n->tp && n->n_union==0 && n->tp!=any_type) ! 30014: switch (n->n_scope) { ! 30015: case ARGT: ! 30016: case ARG: ! 30017: break; ! 30018: default: ! 30019: // error('d', "n: %s %k n_key: %k", n->string, n->base, n->n_key); ! 30020: if ( n->base == TNAME && n->n_key == NESTED ) ! 30021: continue; // printed from nested class ! 30022: n->dcl_print(0); ! 30023: } ! 30024: } ! 30025: if (last_ll==0 && s && (last_ll=s->where.line)) ! 30026: s->where.putline(); ! 30027: } ! 30028: if (s) s->print(); ! 30029: if (where2.line == 0) { ! 30030: if (csloc.line) csloc.putline(); ! 30031: } else { ! 30032: csloc = where2; ! 30033: if (where2.line!=last_line.line) ! 30034: if (last_ll = where2.line) ! 30035: where2.putline(); ! 30036: else ! 30037: last_line.putline(); ! 30038: } ! 30039: putstring("}\n"); ! 30040: if (last_ll && where.line) last_line.line++; ! 30041: } ! 30042: ! 30043: if (s_list) s_list->print(); ! 30044: } ! 30045: ! 30046: /* ! 30047: void table::dcl_print(TOK s, TOK pub) ! 30048: ! 30049: // print the declarations of the entries in the order they were inserted ! 30050: // ignore labels (tp==0) ! 30051: ! 30052: { ! 30053: register Pname* np; ! 30054: register int i; ! 30055: ! 30056: if (this == 0) return; ! 30057: ! 30058: np = entries; ! 30059: for (i=1; i<free_slot; i++) { ! 30060: register Pname n = np[i]; ! 30061: switch (s) { ! 30062: case 0: ! 30063: n->dcl_print(0); ! 30064: break; ! 30065: case EQ: ! 30066: if (n->tp && n->n_scope == pub) n->dcl_print(0); ! 30067: break; ! 30068: case NE: ! 30069: if (n->tp && n->n_scope != pub) n->dcl_print(0); ! 30070: break; ! 30071: } ! 30072: } ! 30073: } ! 30074: */ ! 30075: ! 30076: struct ptbl_rec { ! 30077: char* pname; ! 30078: char* vname; ! 30079: ptbl_rec* next; ! 30080: }; ! 30081: ! 30082: static char* ptbl_name; ! 30083: static ptbl_rec* ptbl_rec_lookup_head = 0; ! 30084: static ptbl_rec* ptbl_rec_pair_head = 0; ! 30085: ! 30086: void ptbl_init(int flag) ! 30087: { ! 30088: if (!flag) { ! 30089: char *p = st_name( "__ptbl_vec__" ); ! 30090: ptbl_name = new char[strlen(p)+1]; ! 30091: strcpy(ptbl_name, p); ! 30092: delete p; ! 30093: fprintf(out_file, "extern struct __mptr* %s[];\n", ptbl_name); ! 30094: if (last_ll) last_line.line++; ! 30095: } ! 30096: else { ! 30097: ptbl_rec *r, *p = ptbl_rec_lookup_head; ! 30098: if ( p == 0 ) return; // don't generate an empty object ! 30099: fprintf(out_file, "struct __mptr* %s[] = {\n", ptbl_name); ! 30100: if (last_ll) last_line.line++; ! 30101: int i = 0; ! 30102: while (p != 0) { ! 30103: r = ptbl_rec_pair_head; ! 30104: while (r && strcmp(r->pname, p->pname)) ! 30105: r = r->next; ! 30106: fprintf(out_file, "%s,\n", r->vname); ! 30107: if (last_ll) last_line.line++; ! 30108: p = p->next; ! 30109: } ! 30110: // fprintf(out_file, "0\n};\n"); ! 30111: fprintf(out_file, "\n};\n"); ! 30112: if (last_ll) last_line.line += 2; ! 30113: } ! 30114: } ! 30115: ! 30116: char* ptbl_lookup(char *name) ! 30117: { ! 30118: ptbl_rec *r, *s, *p = ptbl_rec_lookup_head; ! 30119: int i = 0; ! 30120: ! 30121: while (p && strcmp(name, p->pname)) { ! 30122: r = p; ! 30123: p = p->next; ! 30124: i++; ! 30125: } ! 30126: ! 30127: if (p == 0) { ! 30128: s = new ptbl_rec; ! 30129: s->pname = new char[strlen(name) + 1]; ! 30130: s->vname = 0; ! 30131: s->next = 0; ! 30132: strcpy(s->pname, name); ! 30133: if (ptbl_rec_lookup_head == 0) ! 30134: ptbl_rec_lookup_head = s; ! 30135: else r->next = s; ! 30136: } ! 30137: ! 30138: char *pp = new char[ strlen(ptbl_name) + 10 ]; ! 30139: sprintf(pp, "%s[%d]", ptbl_name, i); ! 30140: return(pp); ! 30141: } ! 30142: ! 30143: void ptbl_add_pair(char* ptbl, char* vtbl) ! 30144: { ! 30145: // error('d', "ptbl_add_pair: ptbl: %s, vtbl: %s", ptbl, vtbl ); ! 30146: ptbl_rec *p = new ptbl_rec; ! 30147: ! 30148: p->pname = new char[strlen(ptbl) + 1]; ! 30149: strcpy(p->pname, ptbl); ! 30150: p->vname = new char[strlen(vtbl) + 1]; ! 30151: ! 30152: strcpy(p->vname, vtbl); ! 30153: p->next = ptbl_rec_pair_head; ! 30154: ! 30155: ptbl_rec_pair_head = p; ! 30156: } ! 30157: 0707071010112044411004440001630000160000010205600466055406600001100000140076print2.c /*ident "@(#)ctrans:src/print2.c 1.4" */ ! 30158: /************************************************************************** ! 30159: ! 30160: C++ source for cfront, the C++ compiler front-end ! 30161: written in the computer science research center of Bell Labs ! 30162: ! 30163: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 30164: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 30165: ! 30166: print2.c: ! 30167: ! 30168: print names and declarations ! 30169: ! 30170: ****************************************************************************/ ! 30171: ! 30172: #include "cfront.h" ! 30173: #include "template.h" ! 30174: ! 30175: bit Cast; ! 30176: int last_ll = 1; ! 30177: Pin curr_icall; ! 30178: char emode; ! 30179: int ntok; ! 30180: ! 30181: static int MAIN; // fudge to get _main() called by main() ! 30182: ! 30183: #define eprint(e) if (e) Eprint(e) ! 30184: ! 30185: #ifdef DENSE ! 30186: void chop(char*); ! 30187: #endif ! 30188: ! 30189: void puttok(TOK t) ! 30190: /* ! 30191: print the output representation of "t" ! 30192: */ ! 30193: { ! 30194: // if (t<=0 || MAXTOK<t) error("illegal token %d",t); ! 30195: // char* s = keys[t]; ! 30196: // if (s == 0) error("V representation token %d",t); ! 30197: ! 30198: putstring(keys[t]); ! 30199: ! 30200: if (12<ntok++) { ! 30201: ntok = 0; ! 30202: last_line.putline(); ! 30203: } ! 30204: else if (t == SM) { ! 30205: ntok = 0; ! 30206: putch('\n'); ! 30207: if (last_ll) last_line.line++; ! 30208: } ! 30209: else ! 30210: putch(' '); ! 30211: } ! 30212: ! 30213: #define MX 20 ! 30214: #define NTBUF 10 ! 30215: class dcl_buf { ! 30216: /* ! 30217: buffer for assembling declaration (or cast) ! 30218: left contains CONST_PTR => *CONST ! 30219: CONST_RPTR => &CONST ! 30220: PTR => * ! 30221: RPTR => & ! 30222: LP => ( ! 30223: right contains RP => ) ! 30224: VEC => [ rnode ] ! 30225: FCT => ( rnode ) ! 30226: FIELD => : rnode ! 30227: */ ! 30228: Pbase b; ! 30229: Pname n; ! 30230: TOK left[MX], right[MX]; ! 30231: Pnode rnode[MX]; ! 30232: Pclass lnode[MX]; ! 30233: int li, ri; ! 30234: public: ! 30235: void init(Pname nn) { b=0; n=nn; li=ri=0; } ! 30236: void base(Pbase bb) { b = bb; } ! 30237: void front(TOK t) { left[++li] = t; } ! 30238: void front(Pclass c) { left[++li] = MEMPTR; lnode[li] = c; } ! 30239: void back(TOK t, Pnode nod) { right[++ri] = t; rnode[ri] = nod; } ! 30240: void paran() { front(LP); back(RP,0); } ! 30241: void put(); ! 30242: } *tbufvec[NTBUF] = {0}, *tbuf = 0; ! 30243: ! 30244: int freetbuf = 0; ! 30245: ! 30246: void dcl_buf::put() ! 30247: { ! 30248: int i; ! 30249: Pfct ff = 0; ! 30250: ! 30251: if (MX<=li || MX<=ri) error('i',"T buffer overflow"); ! 30252: if (b == 0) error('i',"noBT%s",Cast?" in cast":""); ! 30253: ! 30254: if (n && n->n_sto && n->n_sto!=REGISTER) puttok(n->n_sto); ! 30255: ! 30256: b->dcl_print(); ! 30257: ! 30258: for( ; li; li--) { ! 30259: switch (left[li]) { ! 30260: case LP: ! 30261: putch('('); ! 30262: break; ! 30263: case PTR: ! 30264: putch('*'); ! 30265: break; ! 30266: case RPTR: ! 30267: if (emode) ! 30268: putch('&'); ! 30269: else ! 30270: putch('*'); ! 30271: break; ! 30272: case CONST_PTR: ! 30273: if (emode) ! 30274: putstring("*const "); ! 30275: else ! 30276: putch('*'); ! 30277: break; ! 30278: case CONST_RPTR: ! 30279: if (emode) ! 30280: putstring("&const "); ! 30281: else ! 30282: putch('*'); ! 30283: break; ! 30284: case MEMPTR: ! 30285: if (lnode[li]) fprintf(out_file,"%s::",lnode[li]->string); ! 30286: } ! 30287: } ! 30288: ! 30289: if (n) n->print(); ! 30290: ! 30291: for(i=1; i<=ri; i++) { ! 30292: switch (right[i]) { ! 30293: case RP: ! 30294: putch(')'); ! 30295: break; ! 30296: case VEC: ! 30297: putch('['); ! 30298: { Pvec v = (Pvec) rnode[i]; ! 30299: Pexpr d = v->dim; ! 30300: int s = v->size; ! 30301: if (d) d->print(); ! 30302: if (s) fprintf(out_file,"%d",s); ! 30303: } ! 30304: putch(']'); ! 30305: break; ! 30306: case FCT: // beware of function returning pointer to ! 30307: // function expressed witout typedef ! 30308: { Pfct f = Pfct(rnode[i]); ! 30309: if (f->body) ff = f; ! 30310: f->dcl_print(); ! 30311: break; ! 30312: } ! 30313: case FIELD: ! 30314: { Pbase f = (Pbase) rnode[i]; ! 30315: Pexpr d = (Pexpr)f->b_name; ! 30316: int s = f->b_bits; ! 30317: putch(':'); ! 30318: if (d) ! 30319: d->print(); ! 30320: else if (s) ! 30321: fprintf(out_file,"%d",s); ! 30322: else ! 30323: puttok(ZERO); ! 30324: break; ! 30325: } ! 30326: } ! 30327: } ! 30328: void print_body(Pfct); ! 30329: if (ff && emode==0) print_body(ff); ! 30330: } ! 30331: ! 30332: static Pexpr mk_zero_init( Ptype tt, Pname obname, Pname currname ) ! 30333: /* ! 30334: creates 0 initializer for defined objects ! 30335: side effect: generates right nesting level for {} ! 30336: */ ! 30337: { ! 30338: zaq: ! 30339: switch (tt->base) { ! 30340: case TYPE: ! 30341: tt = Pbase(tt)->b_name->tp; goto zaq; ! 30342: case VEC: // type a[size]; => type a[size] = {0}; ! 30343: { ! 30344: if ( obname == currname ) { ! 30345: //xxx initializing vectors blows up the size of some programs ! 30346: return 0; ! 30347: } else { ! 30348: Pexpr i = mk_zero_init(Pvec(tt)->typ,obname,currname); ! 30349: if ( i == 0 ) return 0; ! 30350: return new expr( ILIST, i, 0 ); ! 30351: } ! 30352: } ! 30353: case COBJ: // "X a;" == "X a = {0};" ! 30354: { ! 30355: Pclass cl = Pclass(Pbase(tt)->b_name->tp); ! 30356: if ( !ansi_opt && (cl->csu == ANON || cl->csu == UNION) ) { ! 30357: if ( warning_opt ) { ! 30358: // ridiculous handstands to avoid printing ! 30359: // compiler generated names in warning ! 30360: Ptype tn = obname->tp; ! 30361: for(;;) if(tn->base==VEC) tn=Pvec(tn)->typ; else break; ! 30362: if ( obname == currname && tt == tn ) { ! 30363: if ( cl->string[0]=='_' && cl->string[1]=='_' ) ! 30364: error('w',&obname->where,"cannot generate zeroIr for%n ofT union; toI, compile with +a1 or insert non-union object as first member",obname); ! 30365: else ! 30366: error('w',&obname->where,"cannot generate zeroIr for%n ofT%t; toI, compile with +a1 or insert non-union object as first member",obname,obname->tp); ! 30367: } else { Pclass cx; ! 30368: if ( tn->base == COBJ ! 30369: && (cx=(Pclass)Pbase(tn)->b_name->tp, ! 30370: cx->string[0]=='_' && cx->string[1]=='_') ) ! 30371: error('w',&obname->where,"cannot generate zeroIr for%n (union or aggregate with union as first element); toI, compile with +a1 or insert non-union object as first member",obname); ! 30372: else ! 30373: error('w',&obname->where,"cannot generate zeroIr for%n ofT%t (union or aggregate with union as first element); toI, compile with +a1 or insert non-union object as first member",obname,obname->tp); ! 30374: } ! 30375: } // if warning_opt ! 30376: return 0; ! 30377: } ! 30378: Pbcl l = cl->baselist; ! 30379: while ( l ) { ! 30380: if ( l->base == NAME ) cl = l->bclass; ! 30381: else return new expr(ILIST,zero,0); ! 30382: l = cl->baselist; ! 30383: } ! 30384: int i = 1; ! 30385: Pname nn = cl->memtbl->get_mem(i); ! 30386: for ( ; nn; nn = cl->memtbl->get_mem(++i) ) { ! 30387: Ptype tx = nn->tp; ! 30388: while ( tx->base == TYPE ) tx = Pbase(tx)->b_name->tp; ! 30389: if (nn->base==NAME ! 30390: && nn->n_union==0 ! 30391: && tx->base!=FCT ! 30392: && tx->base!=OVERLOAD ! 30393: && tx->base!=CLASS ! 30394: && tx->base!=ENUM ! 30395: && nn->n_stclass != STATIC) { ! 30396: Pexpr i = mk_zero_init(tx,obname,nn); ! 30397: if ( i == 0 ) return 0; ! 30398: return new expr(ILIST,i,0); ! 30399: } ! 30400: } ! 30401: return 0; ! 30402: } ! 30403: case PTR: ! 30404: if (tt->memptr()) { ! 30405: Pexpr i = new expr(ELIST,zero,zero); ! 30406: return new expr(ILIST,i,zero); ! 30407: } ! 30408: // no break ! 30409: case RPTR: ! 30410: case CHAR: ! 30411: case SHORT: ! 30412: case INT: ! 30413: case EOBJ: ! 30414: case LONG: ! 30415: case FLOAT: ! 30416: case DOUBLE: ! 30417: case LDOUBLE: // "int a;" == "int a = 0;" ! 30418: case FIELD: ! 30419: case ANY: ! 30420: return zero; ! 30421: } ! 30422: return 0; ! 30423: } ! 30424: ! 30425: void name::dcl_print(TOK list) ! 30426: /* ! 30427: Print the declaration for a name (list==0) or a name list (list!=0): ! 30428: For each name ! 30429: (1) print storage class ! 30430: (2) print base type ! 30431: (3) print the name with its declarators ! 30432: Avoid (illegal) repetition of basetypes which are class or enum declarations ! 30433: (A name list may contain names with different base types) ! 30434: list == SM : terminator SM ! 30435: list == 0: single declaration with terminator SM ! 30436: list == CM : separator CM ! 30437: */ ! 30438: { ! 30439: if (error_count) return; ! 30440: ! 30441: for (Pname n=this; n; n=n->n_list) { ! 30442: Ptype t = n->tp; ! 30443: int sm = 0; ! 30444: ! 30445: // error('d',"%s->dcl_print() tp %t sto %k",n->string,t,n->n_sto); ! 30446: if (t == 0) error('i',"N::dcl_print(%n)T missing",n); ! 30447: ! 30448: if (n->n_stclass==ENUM) if (list) continue; else return; ! 30449: ! 30450: if (n->where.line!=last_line.line || n->where.file!=last_line.file) ! 30451: //fprintf(stderr,"%s ",n->string?n->string:"<0>"); n->where.put(stderr); fprintf(stderr," last "); last_line.put(stderr); putc('\n',stderr); ! 30452: if (last_ll = n->where.line) ! 30453: n->where.putline(); ! 30454: else ! 30455: last_line.putline(); ! 30456: ! 30457: int tc = Pbase(t)->b_const; ! 30458: for (Ptype tt = t; tt->base==TYPE; tt = Pbase(tt)->b_name->tp) ! 30459: tc |= Pbase(tt)->b_const; ! 30460: ! 30461: switch (t->base) { ! 30462: case CLASS: ! 30463: //fprintf(stderr,"class %s->dcl_print()\n",n->string); ! 30464: if (n->base != TNAME) { ! 30465: Pclass(t)->dcl_print(n); ! 30466: sm = 1; ! 30467: } ! 30468: break; ! 30469: ! 30470: case ENUM: ! 30471: Penum(t)->dcl_print(0); ! 30472: sm = 1; ! 30473: break; ! 30474: ! 30475: case FCT: ! 30476: { Pfct f = Pfct(t); ! 30477: ! 30478: if (n->base == TNAME) puttok(TYPEDEF); ! 30479: ! 30480: // error('d',"fct %n->dcl_print() printed %d body %d defined %d",n,n->n_dcl_printed,f->body,f->defined); ! 30481: // error('d',"n %d tbl %d tp %t inline %d",n,n->n_table,n->tp,f->f_inline); ! 30482: if (n->n_dcl_printed==2 // definition already printed ! 30483: || (n->n_dcl_printed==1 && f->body==0) ! 30484: // declaration already printed ! 30485: ) { ! 30486: // don't print again ! 30487: sm = 1; // no SM ! 30488: break; ! 30489: } ! 30490: ! 30491: if (f->f_result == 0) make_res(f); ! 30492: ! 30493: if (f->body && n->n_sto==EXTERN) n->n_sto = 0; ! 30494: ! 30495: if (f->f_inline && ((n->n_table!=gtbl) || strcmp(n->string,"main"))) { ! 30496: if (debug_opt) { ! 30497: //error('d',"f %t defined %d inline %d",f,f->defined,f->f_inline); ! 30498: if (f->defined&DEFINED ! 30499: && f->defined&SIMPLIFIED ! 30500: && f->f_inline!=ITOR) ! 30501: goto prnt_def; ! 30502: else if (n->n_dcl_printed==0) ! 30503: goto prnt_dcl; ! 30504: else { ! 30505: sm = 1; ! 30506: break; ! 30507: } ! 30508: } ! 30509: if (f->f_virtual || n->n_addr_taken) { ! 30510: prnt_dcl: ! 30511: //error('d',"prnt_dcl %d %n %k",n,n,n->n_sto); ! 30512: TOK st = n->n_sto; ! 30513: Pblock b = f->body; ! 30514: f->body = 0; ! 30515: t->dcl_print(n); ! 30516: n->n_dcl_printed = 1; ! 30517: n->n_sto = st; ! 30518: f->body = b; ! 30519: break; ! 30520: } ! 30521: else ! 30522: sm = 1; // no SM ! 30523: } ! 30524: else if ((f->defined&DEFINED)==0 ! 30525: || (f->defined&SIMPLIFIED)==0) ! 30526: goto prnt_dcl; ! 30527: else if (n->n_table==gtbl && strcmp(n->string,"main")==0) { ! 30528: if (f->f_inline) { ! 30529: if (warning_opt) { ! 30530: error('w',"main() cannot be inlined"); ! 30531: error('w',"out-of-line copy of main() created"); ! 30532: } ! 30533: n->n_sto=0; ! 30534: } ! 30535: MAIN = 1; ! 30536: gtbl->look("main",0)->use(); ! 30537: f->f_signature = 0; ! 30538: t->dcl_print(n); ! 30539: n->n_dcl_printed = f->body?2:1; ! 30540: MAIN = 0; ! 30541: } ! 30542: else { ! 30543: prnt_def: ! 30544: // error('d',"prnt_def %n %k %d %k",n,n->n_oper,n,n->n_sto); ! 30545: if (n->n_oper==CTOR || n->n_oper==DTOR) { ! 30546: Pclass cl = Pclass(n->n_table->t_name->tp); ! 30547: if (cl->c_body == 3) cl->print_all_vtbls(cl); ! 30548: } ! 30549: ! 30550: if ( n->n_sto == STATIC && ! 30551: pdef_name == 0 && def_name == 0 ) { ! 30552: // error('d', "printing ptbl_vec without first definition" ); ! 30553: pdef_name = n; ! 30554: ptbl_init(0); ! 30555: } ! 30556: t->dcl_print(n); ! 30557: n->n_dcl_printed = f->body?2:1; ! 30558: } ! 30559: if (f->body) sm = 1; ! 30560: break; ! 30561: } ! 30562: ! 30563: case OVERLOAD: ! 30564: { ! 30565: for (Plist gl=Pgen(t)->fct_list; gl; gl=gl->l) { ! 30566: Pname nn = gl->f; ! 30567: nn->dcl_print(0); ! 30568: sm = 1; ! 30569: } ! 30570: break; ! 30571: } ! 30572: ! 30573: case ASM: ! 30574: fprintf(out_file,"asm(\"%s\")\n",(char*)Pbase(t)->b_name); ! 30575: break; ! 30576: ! 30577: case INT: ! 30578: case EOBJ: ! 30579: case CHAR: ! 30580: case LONG: ! 30581: case SHORT: ! 30582: tcx: ! 30583: // do not allocate space for constants unless necessary ! 30584: if (tc ! 30585: && n->n_sto!=EXTERN // extern const one; ! 30586: // const one = 1; ! 30587: // allocates storage ! 30588: && (n->n_scope==EXTERN // FUDGE const one = 1; ! 30589: // is treated as static ! 30590: // need loader support ! 30591: || n->n_scope==STATIC ! 30592: || n->n_scope==FCT) ! 30593: ) { ! 30594: if (n->n_evaluated && n->n_addr_taken==0) { ! 30595: sm = 1; /* no ; */ ! 30596: break; ! 30597: } ! 30598: } ! 30599: tc = 0; ! 30600: // no break; ! 30601: ! 30602: default: ! 30603: { ! 30604: /* ! 30605: // don't print local instance of const ! 30606: if ( n->n_dcl_printed == 3 ) { ! 30607: sm = 1; ! 30608: break; ! 30609: } ! 30610: */ ! 30611: Pexpr i = n->n_initializer; ! 30612: if (n->base == TNAME && n->n_key == NESTED) i = 0; ! 30613: if (tc) { ! 30614: switch (tt->base) { ! 30615: case CHAR: ! 30616: case SHORT: ! 30617: case INT: ! 30618: case LONG: ! 30619: case EOBJ: ! 30620: goto tcx; ! 30621: } ! 30622: } ! 30623: ! 30624: if (n->base == TNAME) { ! 30625: /* Always print template formals, even when they have the same ! 30626: * formal name, since the instantiation name is different. This ! 30627: * fix should not be required when the copy mechanism is in place. */ ! 30628: if (! n_template_arg) ! 30629: for (Pname tn=ktbl->look(n->string,HIDDEN); tn; tn=tn->n_tbl_list) ! 30630: if (tn && tn->lex_level && t==tn->tp) return; ! 30631: puttok(TYPEDEF); ! 30632: } ! 30633: ! 30634: if (n->n_stclass == REGISTER) { ! 30635: // (imperfect) check against member functions ! 30636: // register s a; a.f() illegal ! 30637: Pname cln = n->tp->is_cl_obj(); ! 30638: if (cln) { ! 30639: Pclass cl = Pclass(cln->tp); ! 30640: if (cl->csu!=CLASS ! 30641: && cl->baselist==0 ! 30642: && cl->has_itor()==0 ! 30643: && cl->virt_count==0) puttok(REGISTER); ! 30644: } ! 30645: else ! 30646: puttok(REGISTER); ! 30647: } ! 30648: ! 30649: if (i) { ! 30650: if (n->n_sto==EXTERN && n->n_stclass==STATIC) { ! 30651: n->n_initializer = 0; ! 30652: t->dcl_print(n); ! 30653: puttok(SM); ! 30654: n->n_initializer = i; ! 30655: n->n_sto = 0; ! 30656: t->dcl_print(n); ! 30657: n->n_sto = EXTERN; ! 30658: } ! 30659: else ! 30660: t->dcl_print(n); ! 30661: if(n->n_table) { ! 30662: Pname nn = n->n_table->look(n->string,0); ! 30663: if(nn) ! 30664: nn->n_dcl_printed = 1; ! 30665: else ! 30666: n->n_dcl_printed = 1; ! 30667: } ! 30668: else ! 30669: n->n_dcl_printed = 1; ! 30670: } ! 30671: else if (n->n_evaluated && Pbase(t)->b_const) { ! 30672: if (n->n_sto==EXTERN && n->n_stclass==STATIC) { ! 30673: int v = n->n_evaluated; ! 30674: n->n_evaluated = 0; ! 30675: t->dcl_print(n); ! 30676: puttok(SM); ! 30677: if (n->where.line!=last_line.line || n->where.file!=last_line.file) ! 30678: if (last_ll = n->where.line) ! 30679: n->where.putline(); ! 30680: else ! 30681: last_line.putline(); ! 30682: n->n_evaluated = v; ! 30683: n->n_sto = 0; ! 30684: t->dcl_print(n); ! 30685: n->n_sto = EXTERN; ! 30686: } ! 30687: else ! 30688: t->dcl_print(n); ! 30689: if(n->n_table) { ! 30690: Pname nn = n->n_table->look(n->string,0); ! 30691: if(nn) ! 30692: nn->n_dcl_printed = 1; ! 30693: else ! 30694: n->n_dcl_printed = 1; ! 30695: } ! 30696: else ! 30697: n->n_dcl_printed = 1; ! 30698: } ! 30699: else { ! 30700: //error('d',"%n sto %k val %d stc %k",n,n->n_sto,n->n_val,n_stclass); ! 30701: if ((n->n_sto==0 || (n->n_val && n->n_evaluated==0)) ! 30702: && n_stclass==STATIC ! 30703: && n->n_sto!=STATIC ! 30704: && n->n_table==gtbl) { ! 30705: if (n->n_val && n->n_evaluated==0) { ! 30706: // extern x = f(); ! 30707: // generate int x = 0; ! 30708: // plus dynamic initialization ! 30709: n->n_sto = 0; ! 30710: } ! 30711: ! 30712: n->n_initializer = i = mk_zero_init(t,n,n); ! 30713: } ! 30714: t->dcl_print(n); ! 30715: if(n->n_table) { ! 30716: Pname nn = n->n_table->look(n->string,0); ! 30717: if(nn) ! 30718: nn->n_dcl_printed = 1; ! 30719: else ! 30720: n->n_dcl_printed = 1; ! 30721: } ! 30722: else ! 30723: n->n_dcl_printed = 1; ! 30724: } ! 30725: ! 30726: if (n->n_scope!=ARG) { ! 30727: if (i) { ! 30728: puttok(ASSIGN); ! 30729: ! 30730: Pexpr i2 = i; ! 30731: while (i2->base == CAST) i2 = i2->e1; ! 30732: if (i2->base == ILIST) i = i2; ! 30733: if (t!=i->tp ! 30734: && i->base!=ZERO ! 30735: && i->base!=ILIST /*&& i->tp!=Pchar_type*/) { ! 30736: Ptype t1 = n->tp; ! 30737: cmp: ! 30738: switch (t1->base) { ! 30739: case TYPE: ! 30740: t1 = Pbase(t1)->b_name->tp; ! 30741: goto cmp; ! 30742: default: ! 30743: i->print(); ! 30744: break; ! 30745: // case EOBJ: ! 30746: // goto cst; ! 30747: case VEC: ! 30748: if (Pvec(t1)->typ->base==CHAR) { ! 30749: i->print(); ! 30750: break; ! 30751: } ! 30752: // no break ! 30753: case PTR: ! 30754: case RPTR: ! 30755: if (i->tp==0 || n->tp->check(i->tp,0)) { ! 30756: // cst: ! 30757: putch('('); ! 30758: bit oc = Cast; ! 30759: Cast = 1; ! 30760: t->print(); ! 30761: Cast = oc; ! 30762: putch(')'); ! 30763: } ! 30764: eprint(i); ! 30765: } ! 30766: } ! 30767: else { ! 30768: if (i==zero) { ! 30769: while (t->base == TYPE) t = Pbase(t)->b_name->tp; ! 30770: // if (t->base == EOBJ) { ! 30771: // putch('('); ! 30772: // bit oc = Cast; ! 30773: // Cast = 1; ! 30774: // t->print(); ! 30775: // Cast = oc; ! 30776: // putch(')'); ! 30777: // } ! 30778: } ! 30779: eprint(i); ! 30780: ! 30781: // i->print(); ! 30782: } ! 30783: } ! 30784: else if (n->n_evaluated) { ! 30785: puttok(ASSIGN); ! 30786: if (n->tp->base!=INT || n->tp->is_unsigned()) { ! 30787: putstring("(("); ! 30788: bit oc = Cast; ! 30789: Cast = 1; ! 30790: n->tp->print(); ! 30791: Cast = oc; ! 30792: fprintf(out_file,")%d)",n->n_val); ! 30793: } ! 30794: else ! 30795: fprintf(out_file,"%d",n->n_val); ! 30796: } ! 30797: } ! 30798: } ! 30799: } ! 30800: ! 30801: switch (list) { ! 30802: case SM: ! 30803: if (sm==0) puttok(SM); ! 30804: break; ! 30805: case 0: ! 30806: if (sm==0) puttok(SM); ! 30807: return; ! 30808: case CM: ! 30809: if (n->n_list) puttok(CM); ! 30810: break; ! 30811: } ! 30812: } ! 30813: } ! 30814: ! 30815: char *local_sign( Ptype pt ) ! 30816: { // get function signature for local class ! 30817: char buf[1024]; ! 30818: char* bb = pt->signature(buf); ! 30819: int ll = bb-buf; ! 30820: if (1023 < ll) error('i',"local class N buffer overflow"); ! 30821: char *p = new char[ll+1]; ! 30822: strcpy(p,buf); ! 30823: return p; ! 30824: } ! 30825: ! 30826: void enumdef::dcl_print(Pname cln) ! 30827: /* ! 30828: */ ! 30829: { ! 30830: // note: ***** modify to handle local enums ! 30831: // error('d', "%t::dcl_print(%n) in_class: %t nested_sig: %s", this, cln, in_class, nested_sig ); ! 30832: char* s = nested_sig?nested_sig:(cln ? cln->string:0); ! 30833: if ( nested_sig ) ! 30834: fprintf(out_file,"enum __%s { ",nested_sig); ! 30835: else fprintf(out_file,"enum %s { ",string); ! 30836: ! 30837: for (Pname px, p=mem; p; p=px) { ! 30838: px = p->n_list; ! 30839: if (s) { ! 30840: if (p->n_evaluated) ! 30841: fprintf(out_file,"%s__%s = %d",p->string,s,p->n_val); ! 30842: else ! 30843: fprintf(out_file,"%s__%s",p->string,s); ! 30844: } ! 30845: else { ! 30846: if (p->n_evaluated) ! 30847: fprintf(out_file,"%s = %d",p->string,p->n_val); ! 30848: else ! 30849: fprintf(out_file,"%s",p->string); ! 30850: } ! 30851: if (px) puttok(CM); ! 30852: p->n_initializer = 0; ! 30853: delete p; ! 30854: } ! 30855: mem = 0; ! 30856: puttok(RC); ! 30857: puttok(SM); ! 30858: } ! 30859: ! 30860: void name::print() ! 30861: { // print just the name itself ! 30862: if (this == 0) error('i',"0->N::print()"); ! 30863: if (string == 0) { ! 30864: if (emode) putch('?'); ! 30865: return; ! 30866: } ! 30867: ! 30868: // error( 'd', "%s->name::print(), base: %k", string, base ); ! 30869: switch (base) { ! 30870: case TNAME: ! 30871: if (n_key == NESTED && tpdef && ! 30872: tpdef->nested_sig) { ! 30873: if ( emode == 0 ) { ! 30874: putstring( " __" ); ! 30875: putst(tpdef->nested_sig); ! 30876: } ! 30877: else { ! 30878: putst(tpdef->in_class->string); ! 30879: putstring( "::" ); ! 30880: putst(string); ! 30881: } ! 30882: return; ! 30883: } ! 30884: ! 30885: if (emode && tp) { ! 30886: if (n_template_arg_string) { ! 30887: tp->dcl_print(0); return; ! 30888: } else ! 30889: if(tp->base == COBJ) { ! 30890: Pclass cl = Pclass(Pbase(tp)->b_name->tp); ! 30891: if(cl && cl->base == CLASS && ! 30892: (cl->class_base == instantiated_template_class)) { ! 30893: Ptclass(cl)->inst->print_pretty_name(); return; ! 30894: } ! 30895: } ! 30896: } ! 30897: ! 30898: putst(n_template_arg_string ? n_template_arg_string : string); ! 30899: return; ! 30900: ! 30901: case MDOT: ! 30902: Pexpr(this)->print(); ! 30903: return; ! 30904: } ! 30905: ! 30906: if (emode) { ! 30907: Ptable tbl; ! 30908: char* cs = 0; ! 30909: bit f = 0; ! 30910: if (tp) { ! 30911: switch (tp->base) { ! 30912: case OVERLOAD: ! 30913: case FCT: ! 30914: f = 1; ! 30915: default: ! 30916: if (tbl=n_table) { ! 30917: if (tbl == gtbl) { ! 30918: if (f == 0) putstring("::"); ! 30919: } ! 30920: else { ! 30921: if (tbl->t_name) { ! 30922: Ptclass pc = Ptclass(tbl->t_name->tp); ! 30923: cs = tbl->t_name->string; ! 30924: if ((pc->base == CLASS) && ! 30925: (pc->class_base == instantiated_template_class)) ! 30926: pc->inst->print_pretty_name(); ! 30927: else fprintf(out_file,"%s",cs); ! 30928: fprintf (out_file, "::") ; ! 30929: } ! 30930: } ! 30931: } ! 30932: ! 30933: if (n_scope==ARG && strcmp(string,"this")==0) { ! 30934: // tell which "this" it is ! 30935: Ptype tt = Pptr(tp)->typ; ! 30936: Pname cn = Pbase(tt)->b_name; ! 30937: fprintf(out_file,"%s::",cn->string); ! 30938: } ! 30939: ! 30940: case CLASS: ! 30941: case ENUM: ! 30942: // case TYPE: ! 30943: break; ! 30944: } ! 30945: nop: ! 30946: switch (n_oper) { ! 30947: case TYPE: ! 30948: putstring("operator "); ! 30949: if (tp) Pfct(tp)->returns->dcl_print(0); ! 30950: break; ! 30951: case 0: ! 30952: putstring(string); ! 30953: break; ! 30954: case DTOR: ! 30955: putch('~'); ! 30956: case CTOR: ! 30957: if (cs) { ! 30958: if(tbl->t_name) { ! 30959: Ptclass pc = Ptclass(tbl->t_name->tp); ! 30960: if ((pc->base == CLASS) && ! 30961: (pc->class_base == instantiated_template_class)) ! 30962: pc->inst->print_pretty_name(); ! 30963: else putstring(cs); ! 30964: } ! 30965: } ! 30966: else { ! 30967: if (string) ! 30968: fprintf(out_file,"%s()", n_template_arg_string ! 30969: ? n_template_arg_string : string); ! 30970: else putstring("constructor"); ! 30971: f = 0; ! 30972: } ! 30973: break; ! 30974: case TNAME: ! 30975: putstring(string); ! 30976: break; ! 30977: default: ! 30978: putstring("operator "); ! 30979: putstring(keys[n_oper]); ! 30980: break; ! 30981: } ! 30982: if (f) putstring("()"); ! 30983: } ! 30984: else { ! 30985: if (n_oper) goto nop; ! 30986: if (string) ! 30987: putstring(n_template_arg_string ! 30988: ? n_template_arg_string : string); ! 30989: } ! 30990: return; ! 30991: } ! 30992: ! 30993: char* sig = 0; ! 30994: Pclass cl = 0; ! 30995: Penum en = 0; ! 30996: int i = n_union; ! 30997: ! 30998: if (tp) { ! 30999: Ptable tbl; ! 31000: ! 31001: switch (tp->base) { ! 31002: default: ! 31003: if (tbl=n_table) { // global or member ! 31004: Pname tn; ! 31005: if (tbl == gtbl) { ! 31006: // if (i) fprintf(out_file,"__O%d.",i); ! 31007: if ( i ) { ! 31008: if (n_anon) ! 31009: fprintf(out_file,"__O%d.%s.", i, n_anon ); ! 31010: else fprintf(out_file,"__O%d.",i); ! 31011: } ! 31012: break; ! 31013: } ! 31014: ! 31015: if (tn=tbl->t_name) { ! 31016: cl = Pclass(tn->tp); ! 31017: if (i) { ! 31018: if (cl->string[0]=='_' ! 31019: && cl->string[1]=='_' ! 31020: && cl->string[2]=='C' ) { ! 31021: if (n_anon) ! 31022: fprintf(out_file,"__O%d.%s.", i, n_anon ); ! 31023: else fprintf(out_file,"__O%d.",i); ! 31024: } ! 31025: else ! 31026: if ( cl->nested_sig ) ! 31027: fprintf(out_file,"__O%d__%s.",i,cl->nested_sig); ! 31028: else ! 31029: if ( cl->lex_level ) { ! 31030: char *str = make_local_name(cl,1); ! 31031: fprintf(out_file,"__O%d%s.",i,str); ! 31032: delete str; ! 31033: } ! 31034: else fprintf(out_file,"__O%d__%d%s.",i,cl->strlen,cl->string); ! 31035: cl = 0; ! 31036: } ! 31037: else ! 31038: if (cl->string[0]=='_' ! 31039: && cl->string[1]=='_' ! 31040: && cl->string[2]=='C' ! 31041: && n_stclass != STATIC ) ! 31042: cl = 0; ! 31043: break; ! 31044: } ! 31045: } ! 31046: ! 31047: switch (n_stclass) { // local variable ! 31048: case STATIC: ! 31049: case EXTERN: ! 31050: if (i) ! 31051: fprintf(out_file,"__O%d.",i); ! 31052: else if (n_sto==STATIC && tp->base!=FCT) { ! 31053: if (lex_level == 0) ! 31054: putstring("__S"); ! 31055: else ! 31056: fprintf(out_file,"__%d",lex_level); ! 31057: } ! 31058: break; ! 31059: default: ! 31060: // encode with lexical level UNLESS ``special'' ! 31061: // e.g. __builtin ! 31062: if (string[0]!='_' || string[1]!='_' || string[2] != 'C' ) { ! 31063: if (i) ! 31064: { ! 31065: if (n_anon) ! 31066: fprintf(out_file,"__%d__O%d.%s.",lex_level-1,i,n_anon); ! 31067: else fprintf(out_file,"__%d__O%d.",lex_level-1,i); ! 31068: } ! 31069: else ! 31070: fprintf(out_file,"__%d",lex_level); ! 31071: } ! 31072: } ! 31073: break; ! 31074: case CLASS: ! 31075: case ENUM: ! 31076: if (tp->in_class && tp->nested_sig) en = Penum(tp); ! 31077: break; ! 31078: } ! 31079: ! 31080: if (tp->base==FCT) { ! 31081: sig = Pfct(tp)->f_signature; ! 31082: if (sig && sig[0]==0) sig = 0; ! 31083: } ! 31084: } ! 31085: ! 31086: if (string) { ! 31087: #ifdef DENSE ! 31088: int i = strlen(string); ! 31089: if (cl) i += cl->strlen+4; // __dd<class name> ! 31090: if (sig) { ! 31091: if (cl == 0) i += 2; ! 31092: i += strlen(sig); ! 31093: } ! 31094: ! 31095: if (31<i) { ! 31096: char buf[256]; ! 31097: if (cl && sig) ! 31098: sprintf(buf,"%s__%d%s%s",string,cl->strlen,cl->string,sig); ! 31099: else if (cl) ! 31100: sprintf(buf,"%s__%d%s",string,cl->strlen,cl->string); ! 31101: else if (sig) ! 31102: sprintf(buf,"%s__%s",string,sig); ! 31103: else ! 31104: sprintf(buf,"%s",string); ! 31105: chop(buf); ! 31106: fprintf(out_file,"%s ",buf); ! 31107: return; ! 31108: } ! 31109: #endif ! 31110: ! 31111: if ( en ) ! 31112: fprintf(out_file,"__%s", en->nested_sig); ! 31113: else ! 31114: putstring(n_template_arg_string ! 31115: ? n_template_arg_string : string); ! 31116: ! 31117: if ( cl ) { ! 31118: if ( cl->nested_sig ) ! 31119: fprintf(out_file,"__%s",cl->nested_sig); ! 31120: else ! 31121: if ( cl->lex_level ) { ! 31122: char *str = make_local_name( cl, 1 ); ! 31123: putstring( str ); ! 31124: delete str; ! 31125: } ! 31126: else fprintf(out_file,"__%d%s",cl->strlen,cl->string); ! 31127: } ! 31128: ! 31129: if (sig) { ! 31130: if (cl == 0) putstring("__"); ! 31131: putstring(sig); ! 31132: } ! 31133: putch(' '); ! 31134: } ! 31135: } ! 31136: ! 31137: #ifdef DENSE ! 31138: void chop(char* buf) ! 31139: { ! 31140: static char alpha[] = "_0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; ! 31141: static const asz = sizeof(alpha)-1; ! 31142: int hash = 0; ! 31143: char* p = &buf[29]; ! 31144: ! 31145: while (*p) { ! 31146: hash <<= 1; ! 31147: if (hash & (1<<12)) { ! 31148: hash &= ~(1<<12); ! 31149: hash++; ! 31150: } ! 31151: hash ^= *p++; ! 31152: } ! 31153: ! 31154: buf[29] = alpha[(int)(hash%asz)]; ! 31155: buf[30] = alpha[(int)((hash/asz)%asz)]; ! 31156: buf[31] = 0; ! 31157: } ! 31158: #endif ! 31159: ! 31160: void type::print() ! 31161: { ! 31162: switch (base) { ! 31163: case PTR: ! 31164: case RPTR: ! 31165: case VEC: ! 31166: Pptr(this)->dcl_print(0); ! 31167: break; ! 31168: case FCT: ! 31169: Pfct(this)->dcl_print(); ! 31170: break; ! 31171: // case VEC: ! 31172: // Pvec(this)->dcl_print(0); ! 31173: // break; ! 31174: case CLASS: ! 31175: case ENUM: ! 31176: if (emode) ! 31177: fprintf(out_file,"%k",base); ! 31178: else ! 31179: // error('i',"%p->T::print(%k %s)",this,base,Pclass(this)->string); ! 31180: fprintf(out_file,"struct %s *",Pclass(this)->string); ! 31181: break; ! 31182: case TYPE: ! 31183: if (Cast||Pbase(this)->b_name->lex_level) { ! 31184: Pbase(this)->b_name->tp->print(); ! 31185: break; ! 31186: } ! 31187: // no break ! 31188: default: ! 31189: Pbase(this)->dcl_print(); ! 31190: } ! 31191: } ! 31192: ! 31193: char* type::signature(register char* p) ! 31194: /* ! 31195: take a signature suitable for argument types for overloaded ! 31196: function names ! 31197: */ ! 31198: { ! 31199: Ptype t = this; ! 31200: int pp = 0; // pointer to ! 31201: ! 31202: xx: ! 31203: //error('d',"xx(%d) %d %k",this,t,t->base); ! 31204: ! 31205: // first unroll typedefs and handle derived types: ! 31206: ! 31207: switch (t->base) { ! 31208: case TYPE: ! 31209: if (Pbase(t)->b_const) *p++ = 'C'; ! 31210: t = Pbase(t)->b_name->tp; ! 31211: goto xx; ! 31212: ! 31213: case VEC: ! 31214: if (pp && Pvec(t)->size) { // A<size>_ ! 31215: *p++ = 'A'; ! 31216: sprintf(p,"%d\0",Pvec(t)->size); // don't trust ! 31217: // sprintf return value ! 31218: while (*++p); ! 31219: *p++ = '_'; ! 31220: } ! 31221: else ! 31222: *p++ = 'P'; ! 31223: t = Pvec(t)->typ; ! 31224: pp = 1; ! 31225: goto xx; ! 31226: ! 31227: case PTR: ! 31228: if (Pptr(t)->rdo) *p++ = 'C'; // *const ! 31229: if (Pptr(t)->memof) { // M<size><classname> ! 31230: Pclass cl = Pptr(t)->memof; ! 31231: register char* s = cl->string; ! 31232: int d = cl->strlen; ! 31233: if (d==0) cl->strlen = d = strlen(s); ! 31234: *p++ = 'M'; ! 31235: if (d/10) *p++ = '0'+d/10; ! 31236: *p++ = '0'+ d%10; // assume <100 char ! 31237: while (*p++ = *s++); ! 31238: --p; // not the '\0' ! 31239: } ! 31240: else ! 31241: *p++ = 'P'; ! 31242: t = Pptr(t)->typ; ! 31243: pp = 1; ! 31244: goto xx; ! 31245: ! 31246: case RPTR: ! 31247: *p++ = 'R'; ! 31248: t = Pptr(t)->typ; ! 31249: pp = 1; ! 31250: goto xx; ! 31251: ! 31252: case FCT: ! 31253: { Pfct f = Pfct(t); ! 31254: Pname n = f->argtype; ! 31255: ! 31256: if (f->f_const) *p++ = 'C'; // constant member function ! 31257: if (f->f_static) *p++ = 'S'; // static member function ! 31258: // if (f->memof && f->f_this==0) *p++ = 'S'; //SSS static member function ! 31259: *p++ = 'F'; ! 31260: if (n == 0) ! 31261: *p++ = 'v'; // VOID, that is f() == f(void) ! 31262: else ! 31263: for ( ; n; n=n->n_list) { // print argument encoding ! 31264: // check if argtype is the same ! 31265: // as previously seen argtype ! 31266: int i = 0; ! 31267: for (Pname nn=f->argtype; n!=nn; nn=nn->n_list) { ! 31268: i++; ! 31269: if (nn->tp==n->tp || nn->tp->check(n->tp,0)==0) { ! 31270: // typeof (n) == typeof(arg i) ! 31271: int x = 1; // try for a run after n ! 31272: Pname nnn = n; ! 31273: while ((nnn=nnn->n_list) && x<9) { ! 31274: if (nnn->tp==n->tp ! 31275: || nnn->tp->check(n->tp,0)==0) { ! 31276: x++; ! 31277: n = nnn; ! 31278: } ! 31279: else ! 31280: break; ! 31281: } ! 31282: ! 31283: if (x == 1) // Ti ! 31284: *p++ = 'T'; ! 31285: else { // Nxi ! 31286: *p++ = 'N'; ! 31287: *p++ = '0'+x; ! 31288: } ! 31289: ! 31290: // assume <100 arguments ! 31291: if (9<i) *p++ = '0'+i/10; ! 31292: *p++ = '0'+i%10; ! 31293: goto zk; ! 31294: } ! 31295: } ! 31296: ! 31297: // ``normal'' case print argument type signature ! 31298: // if (n->n_xref) *p++ = 'R'; ! 31299: p = n->tp->signature(p); ! 31300: zk:; ! 31301: } ! 31302: ! 31303: if (f->nargs_known == ELLIPSIS) *p++ = 'e'; ! 31304: ! 31305: if (pp) { // '_' result type ! 31306: *p++ = '_'; ! 31307: p = f->returns->signature(p); ! 31308: } ! 31309: ! 31310: *p = 0; ! 31311: return p; ! 31312: } ! 31313: } ! 31314: ! 31315: // base type modifiers: ! 31316: ! 31317: if ( Pbase(t)->b_const ) *p++ = 'C'; ! 31318: // if ( Pbase(t)->b_signed ) *p++ = 'S'; ! 31319: if ( Pbase(t)->b_unsigned ) *p++ = 'U'; ! 31320: // if ( Pbase(t)->b_volatile ) *p++ = 'V'; ! 31321: ! 31322: ! 31323: // now base types: ! 31324: ! 31325: register char *s, *ns = 0;; ! 31326: int d; ! 31327: Pclass cl; ! 31328: //lll: ! 31329: switch (t->base) { ! 31330: // case TNAME: t = Pbase(t)->b_name->tp; goto lll; ! 31331: case ANY: break; ! 31332: case ZTYPE: break; ! 31333: case VOID: *p++ = 'v'; break; ! 31334: case CHAR: *p++ = 'c'; break; ! 31335: case SHORT: *p++ = 's'; break; ! 31336: // case EOBJ: ! 31337: case INT: *p++ = 'i'; break; ! 31338: case LONG: *p++ = 'l'; break; ! 31339: case FLOAT: *p++ = 'f'; break; ! 31340: case DOUBLE: *p++ = 'd'; break; ! 31341: case LDOUBLE: *p++ = 'r'; break; ! 31342: case EOBJ: ! 31343: // *p++ = 'i'; ! 31344: // break; ! 31345: { Penum en = Penum(Pbase(t)->b_name->tp); ! 31346: // t = en->e_type; ! 31347: // goto lll; ! 31348: ns = en->nested_sig; ! 31349: s = en->string; ! 31350: d = en->strlen; ! 31351: if (d==0) en->strlen = d = strlen(s); ! 31352: goto pppp; ! 31353: } ! 31354: ! 31355: case COBJ: ! 31356: { cl = Pclass(Pbase(t)->b_name->tp); ! 31357: ns = cl->nested_sig; ! 31358: s = cl->string; ! 31359: d = cl->strlen; ! 31360: if (d==0) cl->strlen = d = strlen(s); ! 31361: pppp: ! 31362: if ( ns == 0 ) { ! 31363: if (d/10) *p++ = '0'+d/10; ! 31364: *p++ = '0'+ d%10; // assume less that 99 characters ! 31365: } ! 31366: else s = ns; ! 31367: ! 31368: while (*p++ = *s++); ! 31369: --p; ! 31370: break; ! 31371: } ! 31372: case FIELD: ! 31373: default: ! 31374: error('i',"signature of %k",t->base); ! 31375: } ! 31376: ! 31377: *p = 0; ! 31378: return p; ! 31379: } ! 31380: ! 31381: void basetype::dcl_print() ! 31382: { ! 31383: Pname nn; ! 31384: Pclass cl; ! 31385: ! 31386: if (emode) { ! 31387: if (b_virtual) puttok(VIRTUAL); ! 31388: if (b_inline) puttok(INLINE); ! 31389: } ! 31390: if(ansi_opt || emode) ! 31391: if (b_const) puttok(CONST); ! 31392: if (b_unsigned) puttok(UNSIGNED); ! 31393: ! 31394: switch (base) { ! 31395: case ANY: ! 31396: if (emode) ! 31397: putstring("any "); ! 31398: else ! 31399: putstring("int "); ! 31400: break; ! 31401: ! 31402: case ZTYPE: ! 31403: if (emode) ! 31404: putstring("zero "); ! 31405: else ! 31406: putstring("int "); ! 31407: break; ! 31408: ! 31409: case VOID: ! 31410: if (emode==0 && ansi_opt==0) { ! 31411: // silly trick to bypass BSD C compiler bug ! 31412: // void* (*)() dosn't work there ! 31413: // note simpl.c knows that VOID -> CHAR grep for VCVC ! 31414: puttok(CHAR); ! 31415: break; ! 31416: } ! 31417: case CHAR: ! 31418: case SHORT: ! 31419: case INT: ! 31420: case LONG: ! 31421: case FLOAT: ! 31422: case DOUBLE: ! 31423: case LDOUBLE: ! 31424: puttok(base); ! 31425: break; ! 31426: ! 31427: case EOBJ: ! 31428: nn = b_name; ! 31429: eob: ! 31430: if (emode == 0) ! 31431: // puttok(INT); ! 31432: Penum(nn->tp)->e_type->dcl_print(); ! 31433: else { ! 31434: puttok(ENUM); ! 31435: nn->print(); ! 31436: } ! 31437: break; ! 31438: ! 31439: case COBJ: ! 31440: nn = b_name; ! 31441: cob: ! 31442: cl = Pclass(nn->tp); ! 31443: if (emode && (cl->base == CLASS) && ! 31444: (cl->class_base == instantiated_template_class)) { ! 31445: Ptclass(cl)->inst->print_pretty_name(); ! 31446: break; ! 31447: } else ! 31448: if (cl && (cl->csu==UNION || cl->csu==ANON)) ! 31449: puttok(UNION); ! 31450: else puttok(STRUCT); ! 31451: { ! 31452: char* s = 0; ! 31453: if ( cl && cl->nested_sig ) ! 31454: fprintf(out_file," __%s ",cl->nested_sig); ! 31455: else { ! 31456: if ( cl && cl->lex_level ) ! 31457: s = make_local_name( cl ); ! 31458: putst(s?s:nn->string); ! 31459: delete s; ! 31460: } ! 31461: } ! 31462: break; ! 31463: ! 31464: case TYPE: ! 31465: if (emode == 0) { ! 31466: switch (b_name->tp->base) { ! 31467: case COBJ: ! 31468: nn = Pbase(b_name->tp)->b_name; ! 31469: goto cob; ! 31470: case EOBJ: ! 31471: nn = Pbase(b_name->tp)->b_name; ! 31472: goto eob; ! 31473: } ! 31474: } ! 31475: b_name->print(); ! 31476: break; ! 31477: ! 31478: default: ! 31479: if (emode) { ! 31480: if (0<base && base<=MAXTOK && keys[base]) ! 31481: fprintf(out_file," %s",keys[base]); ! 31482: else ! 31483: putch('?'); ! 31484: } ! 31485: else ! 31486: error('i',"%p->BT::dcl_print(%d)",this,base); ! 31487: } ! 31488: } ! 31489: Pbase memptr_type; ! 31490: ! 31491: void type::dcl_print(Pname n) ! 31492: /* ! 31493: "this" type is the type of "n". Print the declaration ! 31494: */ ! 31495: { ! 31496: //error('d',"%p::dcl_print(%n)",this,n); ! 31497: Ptype t = this; ! 31498: Pptr p; ! 31499: TOK pre = 0; ! 31500: ! 31501: if (t == 0) error('i',"0->dcl_print()"); ! 31502: if (n && n->tp!=t) error('i',"not %n'sT (%p)",n,t); ! 31503: ! 31504: if (base == OVERLOAD) { ! 31505: for (Plist gl=Pgen(this)->fct_list; gl; gl=gl->l) { ! 31506: Pname nn = gl->f; ! 31507: nn->tp->dcl_print(nn); ! 31508: if (gl->l) puttok(SM); ! 31509: } ! 31510: return; ! 31511: } ! 31512: ! 31513: tbuf = tbufvec[freetbuf]; ! 31514: if (tbuf == 0) { ! 31515: if (freetbuf == NTBUF-1) error('i',"AT nesting overflow"); ! 31516: tbufvec[freetbuf] = tbuf = new class dcl_buf; ! 31517: } ! 31518: freetbuf++; ! 31519: if ( base==FIELD && Pbase(this)->b_bits == 0 ) ! 31520: tbuf->init(0);// some compilers can't handle mangled names here ! 31521: else ! 31522: tbuf->init(n); ! 31523: if (n && n->n_xref) tbuf->front(PTR); ! 31524: ! 31525: while (t) { ! 31526: TOK k; ! 31527: ! 31528: switch (t->base) { ! 31529: case PTR: ! 31530: p = Pptr(t); ! 31531: k = (p->rdo) ? CONST_PTR : PTR; ! 31532: goto ppp; ! 31533: case RPTR: ! 31534: p = Pptr(t); ! 31535: k = (p->rdo) ? CONST_RPTR : RPTR; ! 31536: ppp: ! 31537: if (p->memof) { ! 31538: if (emode) { ! 31539: tbuf->front(k); ! 31540: tbuf->front(p->memof); ! 31541: } ! 31542: else { ! 31543: t = p->typ; ! 31544: while (t->base==TYPE) t = Pbase(t)->b_name->tp; ! 31545: if (t->base == FCT) { ! 31546: tbuf->base(mptr_type); ! 31547: goto zaq; ! 31548: } ! 31549: else ! 31550: tbuf->front(k); ! 31551: } ! 31552: } ! 31553: else ! 31554: tbuf->front(k); ! 31555: pre = PTR; ! 31556: t = p->typ; ! 31557: break; ! 31558: case VEC: ! 31559: { Pvec v = Pvec(t); ! 31560: if (Cast && pre != PTR && pre != VEC) { // for Macintosh: ptr to array uses [] notation ! 31561: tbuf->front(PTR); ! 31562: pre = PTR; ! 31563: } ! 31564: else { ! 31565: if (pre == PTR) tbuf->paran(); ! 31566: tbuf->back(VEC,v); ! 31567: pre = VEC; ! 31568: } ! 31569: t = v->typ; ! 31570: break; ! 31571: } ! 31572: ! 31573: case FCT: ! 31574: { Pfct f = Pfct(t); ! 31575: if (pre == PTR) ! 31576: tbuf->paran(); ! 31577: else if (emode && f->memof && n==0) ! 31578: tbuf->front(f->memof); ! 31579: tbuf->back(FCT,f); ! 31580: pre = FCT; ! 31581: t = (f->s_returns) ? f->s_returns : f->returns; ! 31582: break; ! 31583: } ! 31584: case FIELD: ! 31585: tbuf->back(FIELD,t); ! 31586: tbuf->base( Pbase(Pbase(t)->b_fieldtype) ); ! 31587: t = 0; ! 31588: break; ! 31589: case 0: ! 31590: if(!emode)error('i',"noBT(B=0)"); ! 31591: goto dobase; ! 31592: case TYPE: ! 31593: if (Cast||Pbase(t)->b_name->lex_level) { // unravel type in case it contains vectors ! 31594: t = Pbase(t)->b_name->tp; ! 31595: break; ! 31596: } ! 31597: default: // the base has been reached ! 31598: dobase: ! 31599: if (emode) { ! 31600: char* s; ! 31601: for (Ptype tt = t; tt->base==TYPE; tt=Pbase(tt)->b_name->tp); ! 31602: switch (tt->base) { ! 31603: case CLASS: ! 31604: s = Pclass(tt)->string; ! 31605: if (Ptclass(this)->class_base == instantiated_template_class || ! 31606: Ptclass(this)->class_base == uninstantiated_template_class) { ! 31607: Ptclass(this)->inst->print_pretty_name(); ! 31608: --freetbuf; ! 31609: return; ! 31610: } ! 31611: if (s[0]=='_' &&s[1]=='_' && s[2]=='C') s="class"; ! 31612: goto fret; ! 31613: case ENUM: ! 31614: s = "enum"; ! 31615: goto fret; ! 31616: case OVERLOAD: ! 31617: s = "overloaded"; ! 31618: fret: ! 31619: putstring(s); ! 31620: freetbuf--; ! 31621: return; ! 31622: } ! 31623: } ! 31624: ! 31625: tbuf->base( Pbase(t) ); ! 31626: goto zaq; ! 31627: } // switch ! 31628: } // while ! 31629: zaq: ! 31630: tbuf->put(); ! 31631: freetbuf--; ! 31632: } ! 31633: ! 31634: void fct::dcl_print() ! 31635: { ! 31636: Pname nn; ! 31637: //error('d',"fct::dcl_print()"); ! 31638: if (emode) { ! 31639: putch('('); ! 31640: for (nn=argtype; nn;) { ! 31641: nn->tp->dcl_print(0); ! 31642: if (nn=nn->n_list) puttok(CM); else break; ! 31643: } ! 31644: switch (nargs_known) { ! 31645: case 0: // putst("?"); break; ! 31646: case ELLIPSIS: puttok(ELLIPSIS); break; ! 31647: } ! 31648: putch(')'); ! 31649: if (f_const) puttok(CONST); ! 31650: if (f_static) puttok(STATIC); // wrong place for ``static'' ! 31651: return; ! 31652: } ! 31653: ! 31654: Pname at = f_args; ! 31655: putch('('); ! 31656: ! 31657: if (ansi_opt) { ! 31658: // print typed arguments: ! 31659: at = (f_this) ? f_this : (f_result) ? f_result : argtype; ! 31660: // WNG -- note: at = f_args had 0 value with ansi_opt set ! 31661: // mystery fix added here ! 31662: if (at == 0) { ! 31663: if (nargs_known == ELLIPSIS) { ! 31664: putch(')'); ! 31665: return; ! 31666: } ! 31667: puttok(VOID); ! 31668: } ! 31669: else if (body && Cast==0) ! 31670: at->dcl_print(CM); // print argument type and name ! 31671: else { ! 31672: for (nn=at; nn;) { ! 31673: // nn->tp->dcl_print(0); // print argument type ! 31674: nn->tp->dcl_print(nn); // print argument type ! 31675: // (there may not be a name) ! 31676: if (nn=nn->n_list) puttok(CM); else break; ! 31677: } ! 31678: } ! 31679: if (nargs_known == ELLIPSIS) putstring(",..."); ! 31680: putch(')'); ! 31681: } ! 31682: else { ! 31683: // print argument names followed by argument type declarations: ! 31684: if (body && Cast==0) { ! 31685: for (nn=at; nn;) { ! 31686: nn->print(); ! 31687: if (nn=nn->n_list) puttok(CM); else break; ! 31688: } ! 31689: #ifdef mips ! 31690: if (nargs_known == ELLIPSIS) ! 31691: putstring(", va_alist"); ! 31692: #endif ! 31693: #ifdef sparc ! 31694: if (nargs_known == ELLIPSIS) ! 31695: putstring(", __builtin_va_alist"); ! 31696: #endif ! 31697: putch(')'); ! 31698: } ! 31699: else ! 31700: putch(')'); ! 31701: } ! 31702: } ! 31703: ! 31704: void print_body(Pfct f) ! 31705: { ! 31706: if (Cast==0) { ! 31707: ! 31708: if (ansi_opt==0 && f->f_args) { ! 31709: f->f_args->dcl_print(SM); ! 31710: if ( last_ll==0 && (last_ll = f->body->where.line) ) ! 31711: f->body->where.putline(); ! 31712: } ! 31713: ! 31714: if (MAIN) { ! 31715: putstring("{ _main(); "); // call constructors ! 31716: f->body->print(); ! 31717: puttok(RC); ! 31718: } ! 31719: else ! 31720: f->body->print(); ! 31721: } ! 31722: } ! 31723: ! 31724: Pbcl shared_seen; ! 31725: ! 31726: void classdef::print_members() ! 31727: { ! 31728: int i; ! 31729: ! 31730: Pbcl l = baselist; ! 31731: // error('d',"%t->print_members()",this); ! 31732: if (l) { ! 31733: if (l->base == NAME) { ! 31734: l->bclass->print_members(); // first base only ! 31735: // pad to ensure alignment: ! 31736: int boff = l->bclass->real_size; ! 31737: int ba = l->bclass->align(); ! 31738: int xtra = boff%ba; ! 31739: int waste = (xtra) ? ba-xtra : 0; // padding ! 31740: //error('d',"%s: size % align %d waste %d",string,boff,ba,waste); ! 31741: if (waste) { ! 31742: // waste it to protect against structure ! 31743: // assignments to the base class ! 31744: char* s = make_name('W'); ! 31745: fprintf(out_file,"char %s[%d];\n",s,waste); ! 31746: delete s; ! 31747: } ! 31748: l = l->next; ! 31749: } ! 31750: ! 31751: for (; l; l=l->next) ! 31752: /* for second base etc. one must allocate as an object ! 31753: (rather than a list of members) to ensure proper alignment ! 31754: for shared base allocate a pointer ! 31755: size, alignment, & offset handled in cassdef::dcl() ! 31756: */ ! 31757: if (l->base == NAME) { ! 31758: Pclass bcl = l->bclass; ! 31759: char *str = 0; ! 31760: char *cs = bcl->nested_sig?bcl->nested_sig:bcl->string; ! 31761: if (bcl->lex_level && ! 31762: bcl->nested_sig==0) ! 31763: str=make_local_name(bcl); ! 31764: puttok(STRUCT); ! 31765: putst(str?str:cs); ! 31766: putcat('O',bcl->string); // leave as unencoded ! 31767: puttok(SM); ! 31768: delete str; ! 31769: } ! 31770: } ! 31771: ! 31772: // Sam: A class or an enum type declared within a class can hide a ! 31773: // member with the same name, so make sure that it gets printed by ! 31774: // traversing the n_tbl_list to get at these names. ! 31775: for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i)) { ! 31776: do { if (nn->base==NAME ! 31777: && nn->n_union==0 ! 31778: && nn->tp->base!=FCT ! 31779: && nn->tp->base!=OVERLOAD ! 31780: && nn->tp->base!=CLASS ! 31781: && nn->tp->base!=ENUM ! 31782: && nn->n_stclass != STATIC) { ! 31783: // if (nn->tp->base==FIELD && Pbase(nn->tp)->b_bits==0) continue; ! 31784: Pexpr i = nn->n_initializer; ! 31785: nn->n_initializer = 0; ! 31786: nn->dcl_print(0); ! 31787: nn->n_initializer = i; ! 31788: } ! 31789: } while ((nn->base == NAME) && ! 31790: ((nn->tp->base!=CLASS) || (nn->tp->base!=ENUM)) && ! 31791: (nn = nn->n_tbl_list)) ; ! 31792: } ! 31793: ! 31794: for (l=baselist; l; l=l->next) ! 31795: if (l->base==VIRTUAL && l->ptr_offset) { ! 31796: Pclass bcl = l->bclass; ! 31797: char* str = 0; ! 31798: char *cs = bcl->nested_sig?bcl->nested_sig:bcl->string; ! 31799: if (bcl->lex_level && ! 31800: bcl->nested_sig==0) ! 31801: str=make_local_name(bcl); ! 31802: puttok(STRUCT); ! 31803: putst(str?str:cs); ! 31804: putch('*'); ! 31805: putcat('P',bcl->string); // leave unencoded ! 31806: puttok(SM); ! 31807: delete str; ! 31808: } ! 31809: } ! 31810: ! 31811: // void classdef::print_vtbl(Pvirt vtab) ! 31812: // { ! 31813: // error('d',"%s->print_vtbl(%s) vtbl_opt %d",string,vtab->string,vtbl_opt); ! 31814: // error('d',"print_vtbl: lex_level: %d", lex_level ); ! 31815: // ! 31816: // switch (vtbl_opt) { ! 31817: // case -1: ! 31818: // case 1: ! 31819: // vlist = new vl(this,vtab,vlist); ! 31820: // } ! 31821: // ! 31822: // int oo = vtbl_opt; // make `simulated static' name ! 31823: // vtbl_opt = -1; ! 31824: // char* str = lex_level ? make_local_name(this) : 0; ! 31825: // char* s = vtbl_name(vtab->string,str?str:string); ! 31826: // vtbl_opt = oo; ! 31827: // fprintf(out_file,"extern struct __mptr %s[];\n",s); ! 31828: // s[2] = 'p'; // pointer, not tbl itself ! 31829: // fprintf(out_file,"extern struct __mptr* %s;\n",s); ! 31830: // ! 31831: // delete s; ! 31832: // delete str; ! 31833: // } ! 31834: ! 31835: vl* vlist; ! 31836: ! 31837: void really_really_print(Pclass cl, Pvirt vtab, char* s, char* ss); ! 31838: ! 31839: int p2(Pname nn, Ptype t, Pclass cl, Pvirt vtab, char* s) ! 31840: { ! 31841: int init; ! 31842: ! 31843: if (t->base == FCT) { ! 31844: Pfct f = Pfct(t); ! 31845: ! 31846: //error('d',"p2 %n init %d inline %d virtual %d",nn,nn->n_initializer,f->f_inline,f->f_virtual); ! 31847: //error('d',"p2 %s expr %d imeasure %d body %d",s,f->f_expr,f->f_imeasure,f->body); ! 31848: //error('d',"sto %k",nn->n_sto); ! 31849: if (nn->n_initializer ! 31850: || nn->n_sto==STATIC ! 31851: || f->f_inline ! 31852: || f->f_imeasure ! 31853: || f->f_virtual==0) return 0; ! 31854: init = f->body!=0; ! 31855: } ! 31856: else ! 31857: init = nn->n_initializer!=0; ! 31858: ! 31859: int oo = vtbl_opt; ! 31860: vtbl_opt = 1; // make sure the name is universal ! 31861: char *cs = cl->nested_sig?cl->nested_sig:cl->string; ! 31862: char* sstr = (cl->lex_level&&cl->nested_sig==0)? make_local_name(cl) : 0; ! 31863: char* ss = vtbl_name(vtab->string,sstr?sstr:cs); ! 31864: ! 31865: if (init) { // unique definition here ! 31866: really_really_print(cl,vtab,ss,s); ! 31867: } ! 31868: else { // unique definition elsewhere ! 31869: char *vstr = 0; ! 31870: if ( vtab && vtab->string ) { ! 31871: vstr = new char[strlen(vtab->string)+cl->strlen+1]; ! 31872: strcpy( vstr, vtab->string ); ! 31873: strcat( vstr, cl->string ); ! 31874: } ! 31875: Pname nn; ! 31876: if (nn=ptbl->look(vstr?vstr:cl->string,0)) { // use of ptbl in file ! 31877: fprintf(out_file,"extern struct __mptr %s[];\n",ss); ! 31878: s[2] = 'p'; ! 31879: // fprintf(out_file,"struct __mptr* %s = ",s); ! 31880: // fprintf(out_file,"%s;\n",ss); ! 31881: ptbl_add_pair(s, ss); ! 31882: nn->n_key=HIDDEN; ! 31883: } ! 31884: delete vstr; ! 31885: } ! 31886: vtbl_opt = oo; ! 31887: ! 31888: delete ss; ! 31889: delete sstr; ! 31890: ! 31891: return 1; ! 31892: } ! 31893: ! 31894: void classdef::really_print(Pvirt vtab) ! 31895: { ! 31896: // error('d',"really_print %t %d",this,vtbl_opt); ! 31897: int oo = vtbl_opt; // make `simulated static' name ! 31898: vtbl_opt = -1; ! 31899: char *cs = nested_sig?nested_sig:string; ! 31900: char* str = (lex_level&&nested_sig==0) ? make_local_name(this) : 0; ! 31901: char* s = vtbl_name(vtab->string,str?str:cs); ! 31902: // error('d', "really_print: %s, vtab: %s, s: %s", string, vtab->string, s ); ! 31903: vtbl_opt = oo; ! 31904: ! 31905: // see if needed ! 31906: int i; ! 31907: for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) { ! 31908: Ptype t = nn->tp; ! 31909: zse: ! 31910: if (t) ! 31911: switch (t->base) { ! 31912: case TYPE: ! 31913: t = Pbase(t)->b_name->tp; ! 31914: goto zse; ! 31915: /* ! 31916: case COBJ: ! 31917: if (nn->n_sto == EXTERN) ! 31918: { Pclass cl = Pclass(Pbase(t)->b_name->tp); ! 31919: if (cl->has_ctor()) { ! 31920: p2(nn,t,this,vtab,s); ! 31921: return; ! 31922: } ! 31923: } ! 31924: break; ! 31925: */ ! 31926: case FCT: ! 31927: if (p2(nn,t,this,vtab,s)) ! 31928: goto xyzzy; ! 31929: break; ! 31930: ! 31931: case OVERLOAD: ! 31932: { for (Plist gl=Pgen(t)->fct_list; gl; gl=gl->l) ! 31933: if (p2(gl->f,gl->f->tp,this,vtab,s)) ! 31934: goto xyzzy; ! 31935: } ! 31936: } ! 31937: } ! 31938: ! 31939: { // must be initialized var in block to permit goto ! 31940: char* ss = vtbl_name(vtab->string,str?str:cs); ! 31941: // error('d', "really_print: %s, vtab: %s, ss: %s", cs, vtab->string, s ); ! 31942: ! 31943: if (vtbl_opt) ! 31944: really_really_print(this,vtab,ss,s); ! 31945: else { ! 31946: char *vstr = 0; ! 31947: if ( vtab && vtab->string ) { ! 31948: vstr = new char[::strlen(vtab->string)+strlen+1]; ! 31949: strcpy( vstr, vtab->string ); ! 31950: strcat( vstr, string ); ! 31951: } ! 31952: Pname nn; ! 31953: if (nn=ptbl->look(vstr?vstr:string,0)) { // use of ptbl in file ! 31954: fprintf(out_file,"extern struct __mptr %s[];\n",ss); ! 31955: s[2] = 'p'; ! 31956: // fprintf(out_file,"struct __mptr* %s = ",s); ! 31957: // fprintf(out_file,"%s;\n",ss); ! 31958: ptbl_add_pair(s, ss); ! 31959: nn->n_key=HIDDEN; ! 31960: } ! 31961: delete vstr; ! 31962: } ! 31963: delete ss; ! 31964: } ! 31965: xyzzy: ! 31966: delete s; ! 31967: delete str; ! 31968: } ! 31969: ! 31970: void really_really_print(Pclass cl, Pvirt vtab, char* s, char* ss) ! 31971: { ! 31972: // error('d',"really %s %s",s, ss); ! 31973: // make sure function is declared before using ! 31974: // it in vtbl initializer ! 31975: Pname nn; ! 31976: int i; ! 31977: for (i=0; nn = vtab->virt_init[i].n; i++) { ! 31978: Pfct f = Pfct(nn->tp); ! 31979: if (nn->n_initializer) { // pure virtual ! 31980: static pv; ! 31981: if (pv == 0) { // VCVC void->char assumed ! 31982: fprintf(out_file,"char __pure_virtual_called();\n"); ! 31983: pv = 1; ! 31984: } ! 31985: continue; ! 31986: } ! 31987: if (f->base != FCT) error('i',"vtbl %n",nn); ! 31988: //extern void expand_dtor(Pclass cl); ! 31989: // if (f->f_inline == IDTOR) expand_dtor(f->memof); ! 31990: ! 31991: if (nn->n_dcl_printed==0 /*|| f->f_inline*/) { ! 31992: if (f->f_inline && vtbl_opt) puttok(STATIC); ! 31993: if (f->f_result == 0) make_res(f); ! 31994: Ptype r = f->s_returns ? f->s_returns : f->returns; ! 31995: r->print(); ! 31996: nn->print(); ! 31997: putstring("()"); ! 31998: puttok(SM); ! 31999: nn->n_dcl_printed = 1; ! 32000: } ! 32001: } ! 32002: ! 32003: // if (vtbl_opt == -1) puttok(STATIC); ! 32004: ! 32005: ! 32006: fprintf(out_file,"struct __mptr %s[] = {0,0,0,\n",s); ! 32007: ! 32008: Pname n; ! 32009: for (i=0; n=vtab->virt_init[i].n; i++) { ! 32010: if (n->n_initializer) ! 32011: putstring("0,0,(__vptp)__pure_virtual_called,\n"); ! 32012: else { ! 32013: fprintf(out_file,"%d,0,(__vptp)",-vtab->virt_init[i].offset); ! 32014: n->print(); ! 32015: n->n_addr_taken = 1; ! 32016: putstring(",\n"); ! 32017: } ! 32018: } ! 32019: putstring("0,0,0};\n"); ! 32020: ! 32021: ss[2] = 'p'; ! 32022: // fprintf(out_file,"struct __mptr* %s = ",ss); ! 32023: s[2] = 'v'; ! 32024: // fprintf(out_file,"%s;\n",s); ! 32025: ptbl_add_pair(ss,s); ! 32026: ! 32027: Pname nm; ! 32028: char *cstr = 0; ! 32029: char *vstr = 0; ! 32030: char *cs = cl->nested_sig?cl->nested_sig:cl->string; ! 32031: if (cl->lex_level && cl->nested_sig==0) cstr = make_local_name( cl ); ! 32032: if ( vtab && vtab->string ) { ! 32033: vstr = new char[strlen(vtab->string)+(cstr?strlen(cstr):strlen(cs))+1]; ! 32034: strcpy( vstr, vtab->string ); ! 32035: strcat( vstr, cstr?cstr:cs ); ! 32036: } ! 32037: ! 32038: if ( vstr == 0 ) vstr = cstr; ! 32039: if ( nm = ptbl->look(vstr?vstr:cl->string,0) ) ! 32040: nm->n_key = HIDDEN; ! 32041: else ! 32042: if ( ptbl->look(vstr?vstr:cl->string,HIDDEN) == 0 ) ! 32043: ptbl->insert(new name(vstr?vstr:cl->string),HIDDEN); ! 32044: if (cstr == vstr) delete cstr; ! 32045: else { ! 32046: delete cstr; ! 32047: delete vstr; ! 32048: } ! 32049: ! 32050: //error('d',"really-> %s",s); ! 32051: } ! 32052: ! 32053: #include <ctype.h> ! 32054: char* vtbl_name(char* s1, char* s2) ! 32055: { ! 32056: char* s3 = (vtbl_opt == -1 && *src_file_name) ? src_file_name : 0; ! 32057: // if vtbl_opt == -1 fake a static (there are no portable ! 32058: // way of doing a forward declaration of a static in C) ! 32059: int ll = s1 ? strlen(s1) : 0; ! 32060: int ll2 = strlen(s2); ! 32061: int ll3 = s3 ? strlen(s3) : 0; ! 32062: int sz = (ll+ll2+ll3+20)/32+1; // avoid fragmentation ! 32063: ! 32064: sz *= 32; ! 32065: // error('d',"vtbl_name(%s,%s,%s) %d",s1?s1:"",s2,s3?s3:"",sz); ! 32066: char* buf = new char[sz]; ! 32067: if (s3) { ! 32068: if (s1) ! 32069: sprintf(buf,"__vtbl__%d%s__%d%s__%s",ll,s1,ll2,s2,s3); ! 32070: else ! 32071: sprintf(buf,"__vtbl__%d%s__%s",ll2,s2,s3); ! 32072: } ! 32073: else if (s1) ! 32074: sprintf(buf,"__vtbl__%d%s__%d%s",ll,s1,ll2,s2); ! 32075: else ! 32076: sprintf(buf,"__vtbl__%d%s",ll2,s2); ! 32077: ! 32078: if (vtbl_opt == -1) { ! 32079: for (char* p = buf+ll2+11; *p; p++) ! 32080: if (!isalpha(*p) && !isdigit(*p)) *p = '_'; ! 32081: } ! 32082: #ifdef DENSE ! 32083: chop(buf); ! 32084: #endif ! 32085: return buf; ! 32086: } ! 32087: ! 32088: void classdef::print_all_vtbls(Pclass bcl) ! 32089: { ! 32090: //error('d',"%t->print_all_vtbls(%t) vlt %d bl %d",this,bcl,virt_list,baselist); ! 32091: ! 32092: for (Pvirt blist = bcl->virt_list; blist; blist = blist->next) { ! 32093: if (this != blist->vclass) continue; ! 32094: if (blist->printed) continue; ! 32095: // if (blist->string==0 && find_vptr(this)==0) { //BSopt ! 32096: // continue; ! 32097: // } ! 32098: // print_vtbl(blist); ! 32099: vlist = new vl(this,blist,vlist); ! 32100: blist->printed = 1; ! 32101: } ! 32102: ! 32103: for (Pbcl b = bcl->baselist; b; b = b->next) ! 32104: print_all_vtbls(b->bclass); ! 32105: ! 32106: if (this==bcl) c_body = 0; ! 32107: } ! 32108: ! 32109: extern Pclass current_instantiation; ! 32110: void classdef::dcl_print(Pname) ! 32111: { ! 32112: //error('d',"%t->classdef::dcl_print() -- c_body==%d defined==0%o",this,c_body,defined); ! 32113: defined |= REF_SEEN; ! 32114: // ensure template instantiations are printed exactly once. ! 32115: if (class_base != vanilla_class && current_instantiation != this) return; ! 32116: ! 32117: if (c_body==0 || c_body==3 || (defined&DEFINED)==0) return; ! 32118: c_body = 3; ! 32119: ! 32120: int i; ! 32121: for (Pname nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) { ! 32122: if (nn->base==NAME ! 32123: && nn->n_union==0 ! 32124: && nn->tp->base==CLASS ! 32125: && Pclass(nn->tp)->c_body==1) ! 32126: Pclass(nn->tp)->dcl_print(nn); ! 32127: else if (nn->base == TNAME && Pbase(nn->tp)->base != COBJ) ! 32128: nn->dcl_print(0); ! 32129: else if (nn->tp && nn->tp->base == ENUM) { ! 32130: if(nn->n_union==0) Penum(nn->tp)->dcl_print(nn); ! 32131: } ! 32132: } ! 32133: ! 32134: TOK lvl = in_class ? NESTED : lex_level ? LOCAL : 0; ! 32135: Pname n = ktbl->look(string,lvl); ! 32136: if (n==0) n = ktbl->look(string,HIDDEN); ! 32137: ! 32138: if (n) { ! 32139: if (n->where.line!=last_line.line ! 32140: || n->where.file!=last_line.file) ! 32141: if (last_ll = n->where.line) ! 32142: n->where.putline(); ! 32143: else ! 32144: last_line.putline(); ! 32145: } ! 32146: ! 32147: TOK c = csu==CLASS ? STRUCT : csu; ! 32148: puttok(c); ! 32149: // if (string[0]!='_' || string[1]!='_' || string[2]!='C') ! 32150: ! 32151: char *str = 0; ! 32152: if ( lex_level && nested_sig == 0) str = make_local_name( this ); ! 32153: if ( nested_sig ) putstring( " __" ); ! 32154: putst(str?str:(nested_sig?nested_sig:string)); ! 32155: ! 32156: int sm = 0; ! 32157: int sz = tsizeof(); ! 32158: int dvirt = 0; ! 32159: ! 32160: if ( nested_sig ) ! 32161: fprintf(out_file,"{\t/* sizeof __%s == %d */\n",nested_sig,obj_size); ! 32162: else ! 32163: fprintf(out_file,"{\t/* sizeof %s == %d */\n",str?str:string,obj_size); ! 32164: if ( last_ll ) last_line.line++; ! 32165: delete str; ! 32166: ! 32167: print_members(); ! 32168: for (Pbcl b = baselist; b; b = b->next) { // declare virtual classes ! 32169: if (b->base != VIRTUAL) continue; ! 32170: Pclass bcl = b->bclass; ! 32171: dvirt += bcl->virt_count; ! 32172: //error('d',"%t in %t %d",b->bclass,this,b->allocated); ! 32173: if (b->allocated==0) continue; ! 32174: char* str = 0; ! 32175: if (bcl->lex_level) str = make_local_name(bcl); ! 32176: puttok(STRUCT); // struct bcl Obcl; ! 32177: putst(str?str:bcl->string); ! 32178: putcat('O',bcl->string); // leave unencoded ! 32179: puttok(SM); ! 32180: delete str; ! 32181: } ! 32182: putstring("};\n"); ! 32183: if ( last_ll ) last_line.line++; ! 32184: ! 32185: for (nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) { ! 32186: if (nn->base==NAME && nn->n_union==0) { ! 32187: Ptype t = nn->tp; ! 32188: switch (t->base) { ! 32189: case FCT: ! 32190: case OVERLOAD: ! 32191: break; ! 32192: default: ! 32193: if (nn->n_stclass == STATIC) { ! 32194: TOK b = nn->n_sto; ! 32195: //error('d',"print nn %n tp %t b %k eval %d",nn,nn->tp,b,nn->n_evaluated); ! 32196: /* ! 32197: Pname cn; ! 32198: TOK bb = ((cn=nn->tp->is_cl_obj()) ! 32199: && Pclass(cn->tp)->has_ctor())==0 ! 32200: ?0:b; // force explicit initialization ! 32201: nn->n_sto = (nn->n_evaluated) ? STATIC : bb; ! 32202: */ ! 32203: nn->n_sto = (nn->n_evaluated) ? STATIC : b; ! 32204: nn->dcl_print(0); ! 32205: nn->n_sto = b; ! 32206: } ! 32207: } ! 32208: } ! 32209: } ! 32210: if (vtbl_opt != -1) print_all_vtbls(this); // force declaration ! 32211: //error('d',"dcl_print -> "); ! 32212: } ! 32213: ! 32214: ! 32215: char * ! 32216: make_local_name( Pclass cl, int ln ) ! 32217: { ! 32218: char *buf; ! 32219: if ( cl->in_fct == 0 ) error( 'i', "localC %s missingFN", cl->string ); ! 32220: char *fsig = Pfct(cl->in_fct->tp)->f_signature; ! 32221: if ( fsig == 0 ) fsig = local_sign( cl->in_fct->tp ); ! 32222: char *fs = cl->in_fct->string; ! 32223: int class_len=cl->strlen+strlen(fsig)+strlen(fs)+strlen(cl->lcl)+4; ! 32224: int sz = (class_len+20)/32+1; // from vtbl_name() ! 32225: ! 32226: if ( Pfct(cl->in_fct->tp)->memof == 0 ) { ! 32227: sz *= 32; ! 32228: buf = new char[ sz ]; ! 32229: // error('d', "make_local_name: sz: %d", sz ); ! 32230: ! 32231: if (ln) ! 32232: sprintf(buf, "__%d%s__%s__%s%s", class_len, cl->string, fs, fsig, cl->lcl); ! 32233: else ! 32234: sprintf(buf, "%s__%s__%s%s", cl->string, fs, fsig, cl->lcl); ! 32235: } ! 32236: else ! 32237: { ! 32238: char *cs = Pclass(Pfct(cl->in_fct->tp)->memof)->string; ! 32239: int len = Pclass(Pfct(cl->in_fct->tp)->memof)->strlen; ! 32240: if ( len < 10 ) ! 32241: ++class_len; ! 32242: else ! 32243: if ( len > 99 ) ! 32244: class_len += 3; ! 32245: else class_len += 2; ! 32246: class_len += len; ! 32247: sz = (class_len+20)/32+1; ! 32248: sz *= 32; ! 32249: buf = new char[ sz ]; ! 32250: // error('d', "make_local_name: sz: %d", sz ); ! 32251: ! 32252: if ( ln ) ! 32253: sprintf(buf, "__%d%s__%s__%d%s%s%s",class_len,cl->string,fs,len,cs,fsig,cl->lcl); ! 32254: else sprintf(buf, "%s__%s__%d%s%s%s",cl->string,fs,len,cs,fsig,cl->lcl); ! 32255: } ! 32256: ! 32257: #ifdef DENSE ! 32258: chop( buf ); ! 32259: #endif ! 32260: ! 32261: return buf; ! 32262: } ! 32263: ! 32264: 0707071010112046021004440001630000160000010210070466055415700001500000001262print_self.c /* ident "@(#)ctrans:src/print_self.c 1.2" */ ! 32265: /* print_self_default.C -- bailout versions of print_self and format_self */ ! 32266: /* ! 32267: $Source: /usr2/odi/lib.src/RCS/print_self_default.C,v $ $RCSfile: print_self_default.C,v $ ! 32268: $Revision: 1.4 $ $Date: 89/09/19 11:49:58 $ ! 32269: $Author: benson $ $Locker: $ ! 32270: $State: Exp $ ! 32271: */ ! 32272: ! 32273: #include "print_self.h" ! 32274: ! 32275: int ostream_printf (ostream&, const char * ...); ! 32276: ! 32277: int _Print_self::print_self (ostream& stream) const ! 32278: { ! 32279: return ostream_printf (stream, "<%s at 0x%p>", ! 32280: this->type_name(), (void *) this); ! 32281: } ! 32282: ! 32283: int _Print_self::format_self (ostream& stream) const ! 32284: { ! 32285: return ostream_printf (stream, "<%s at 0x%p>", ! 32286: this->type_name(), (void *) this); ! 32287: } ! 32288: 0707071010112046111004440001630000160000010211170466055421300001500000001261print_self.h /* ident "@(#)ctrans:src/print_self.h 1.2" */ ! 32289: /* print_self.H -- base class for objects that want to support ! 32290: the 'official' print self for \T in printf. */ ! 32291: ! 32292: /* ! 32293: $Header: /usr2/odi/include/RCS/print_self.H,v 1.4 89/09/19 11:49:19 benson Exp $ ! 32294: ! 32295: Copyright (c) 1989 by Object Design, Inc., Burlington, Mass. ! 32296: All rights reserved. ! 32297: ! 32298: */ ! 32299: ! 32300: #ifndef _PRINT_SELF_CLASS ! 32301: #define _PRINT_SELF_CLASS ! 32302: #include <iostream.h> ! 32303: ! 32304: class _Print_self { ! 32305: public: ! 32306: virtual char * type_name () const { return "OBJECT"; } ! 32307: virtual int print_self (ostream&) const; // returns count of characters printed. ! 32308: virtual int format_self (ostream&) const; // returns count of characters printed. ! 32309: }; ! 32310: #endif ! 32311: 0707071010112044421004440001630000160000010206300466055407100000700000010531repr.c /*ident "@(#)ctrans:src/repr.c 1.4" */ ! 32312: /************************************************************************** ! 32313: ! 32314: C++ source for cfront, the C++ compiler front-end ! 32315: written in the computer science research center of Bell Labs ! 32316: ! 32317: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 32318: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 32319: ! 32320: repr.c: ! 32321: ! 32322: *****************************************************************************/ ! 32323: ! 32324: #include "cfront.h" ! 32325: ! 32326: char* oper_name(TOK op) ! 32327: /* ! 32328: return the string representation of operator "op" ! 32329: */ ! 32330: { ! 32331: switch (op) { ! 32332: default: error('i',"oper_name(%k)",op); ! 32333: case GNEW: ! 32334: case NEW: return "__nw"; ! 32335: case GDELETE: ! 32336: case DELETE: return "__dl"; ! 32337: case MUL: return "__ml"; ! 32338: case DIV: return "__dv"; ! 32339: case MOD: return "__md"; ! 32340: case UPLUS: ! 32341: case PLUS: return "__pl"; ! 32342: case MINUS: ! 32343: case UMINUS: return "__mi"; ! 32344: case LS: return "__ls"; ! 32345: case RS: return "__rs"; ! 32346: case EQ: return "__eq"; ! 32347: case NE: return "__ne"; ! 32348: case LT: return "__lt"; ! 32349: case GT: return "__gt"; ! 32350: case LE: return "__le"; ! 32351: case GE: return "__ge"; ! 32352: case AND: ! 32353: case ADDROF: return "__ad"; ! 32354: case OR: return "__or"; ! 32355: case ER: return "__er"; ! 32356: case ANDAND: return "__aa"; ! 32357: case OROR: return "__oo"; ! 32358: case NOT: return "__nt"; ! 32359: case COMPL: return "__co"; ! 32360: case INCR: return "__pp"; ! 32361: case DECR: return "__mm"; ! 32362: case CALL: return "__cl"; ! 32363: case DEREF: return "__vc"; ! 32364: case ASSIGN: return "__as"; ! 32365: case REF: return "__rf"; ! 32366: case ASPLUS: return "__apl"; ! 32367: case ASMINUS: return "__ami"; ! 32368: case ASMUL: return "__amu"; ! 32369: case ASDIV: return "__adv"; ! 32370: case ASMOD: return "__amd"; ! 32371: case ASLS: return "__als"; ! 32372: case ASRS: return "__ars"; ! 32373: case ASAND: return "__aad"; ! 32374: case ASOR: return "__aor"; ! 32375: case ASER: return "__aer"; ! 32376: case CTOR: return "__ct"; ! 32377: case DTOR: return "__dt"; ! 32378: // operator T "__op"<signature of T> ! 32379: // case SIZEOF: return "sizeof"; ! 32380: case CM: return "__cm"; ! 32381: case REFMUL: return "__rm"; ! 32382: // library functions: ! 32383: // "_vec_delete" ! 32384: // "_vec_new" ! 32385: // "_main" ! 32386: } ! 32387: } ! 32388: ! 32389: #define new_op(ss,v) keys[v]=ss ! 32390: ! 32391: void otbl_init() ! 32392: /* ! 32393: operator representation table ! 32394: */ ! 32395: { ! 32396: new_op("->",REF); ! 32397: new_op("." ,DOT); ! 32398: new_op(".* or ->*" ,REFMUL); ! 32399: new_op("mdot" ,REFMUL); ! 32400: new_op("!" ,NOT); ! 32401: new_op("~" ,COMPL); ! 32402: new_op("++",INCR); ! 32403: new_op("--",DECR); ! 32404: new_op("*" ,MUL); ! 32405: new_op("&" ,AND); ! 32406: new_op("&" ,ADDROF); ! 32407: new_op("&" ,G_ADDROF); ! 32408: new_op("/" ,DIV); ! 32409: new_op("%" ,MOD); ! 32410: new_op("+" ,PLUS); ! 32411: new_op("+" ,UPLUS); ! 32412: new_op("-" ,MINUS); ! 32413: new_op("-" ,UMINUS); ! 32414: new_op("<<",LS); ! 32415: new_op(">>",RS); ! 32416: new_op("<" ,LT); ! 32417: new_op(">" ,GT); ! 32418: new_op("<=",LE); ! 32419: new_op(">=",GE); ! 32420: new_op("==",EQ); ! 32421: new_op("!=",NE); ! 32422: new_op("^" ,ER); ! 32423: new_op("|" ,OR); ! 32424: new_op("&&",ANDAND); ! 32425: new_op("||",OROR); ! 32426: new_op("?:" ,QUEST); ! 32427: // new_op(":" ,COLON); ! 32428: new_op("=" ,ASSIGN); ! 32429: new_op("," ,CM); ! 32430: new_op("," ,G_CM); ! 32431: ! 32432: new_op(";" ,SM); ! 32433: new_op("{" ,LC); ! 32434: new_op("}" ,RC); ! 32435: new_op("(" ,LP); ! 32436: new_op(")" ,RP); ! 32437: new_op("[" ,LB); ! 32438: new_op("]" ,RB); ! 32439: ! 32440: new_op("+=",ASPLUS); ! 32441: new_op("-=",ASMINUS); ! 32442: new_op("*=",ASMUL); ! 32443: new_op("/=",ASDIV); ! 32444: new_op("%=",ASMOD); ! 32445: new_op("&=",ASAND); ! 32446: new_op("|=",ASOR); ! 32447: new_op("^=",ASER); ! 32448: new_op(">>=",ASRS); ! 32449: new_op("<<=",ASLS); ! 32450: ! 32451: // new_op("sizeof",SIZEOF); ! 32452: // new_op("new",NEW); ! 32453: // new_op("delete",DELETE); ! 32454: ! 32455: new_op("0" ,ZERO); ! 32456: new_op("[]" ,DEREF); ! 32457: new_op("expression list", ELIST); ! 32458: new_op("initializer list", ILIST); ! 32459: new_op("static initializer", STAT_INIT); ! 32460: new_op("()", CALL); ! 32461: new_op("generated function call",G_CALL); ! 32462: new_op("inline function call",ICALL); ! 32463: new_op("cast",CAST); ! 32464: new_op("inline argument",ANAME); ! 32465: new_op("text",TEXT); ! 32466: new_op(".*",MEMPTR); ! 32467: ! 32468: new_op("class type", COBJ); ! 32469: new_op("enum type", EOBJ); ! 32470: new_op("union", ANON); ! 32471: ! 32472: new_op("function",FCT); ! 32473: new_op("pointer",PTR); ! 32474: new_op("reference",RPTR); ! 32475: new_op("array",VEC); ! 32476: new_op("identifier",ID); ! 32477: new_op("name",NAME); ! 32478: new_op("...",ELLIPSIS); ! 32479: new_op("::",MEM); ! 32480: new_op("type name",TYPE); ! 32481: new_op("tname",TNAME); ! 32482: new_op("{}",BLOCK); ! 32483: new_op("pair",PAIR); ! 32484: new_op("declaration",DCL); ! 32485: new_op("character constant",CCON); ! 32486: new_op("integer constant",ICON); ! 32487: new_op("float constant",FCON); ! 32488: new_op("integer value",IVAL); ! 32489: new_op("string",STRING); ! 32490: new_op("label",LABEL); ! 32491: new_op("'class', 'struct', or 'union'",AGGR); ! 32492: new_op(" argument",ARG); ! 32493: new_op(" empty expression",DUMMY); ! 32494: new_op(" ::new",GNEW); ! 32495: new_op(" constructor call",VALUE); ! 32496: new_op(" ::delete",GDELETE); ! 32497: new_op(ansi_opt?" long double":" double",LDOUBLE); ! 32498: new_op(" typedef",NESTED); // did not want to introduce new TOKEN ! 32499: } ! 32500: 0707071010112044431004440001630000160000010206400466055407500001000000067265simpl.c /*ident "@(#)ctrans:src/simpl.c 1.3" */ ! 32501: /****************************************************************** ! 32502: ! 32503: C++ source for cfront, the C++ compiler front-end ! 32504: written in the computer science research center of Bell Labs ! 32505: ! 32506: Copyright (c) 1984 AT&T, Inc. All rights Reserved ! 32507: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 32508: ! 32509: simpl.c: ! 32510: ! 32511: simplify the typechecked function ! 32512: remove: classes: ! 32513: class fct-calls ! 32514: operators ! 32515: value constructors and destructors ! 32516: new and delete operators (replace with function calls) ! 32517: initializers (turn them into statements) ! 32518: constant expressions (evaluate them) ! 32519: inline functions (expand the calls) ! 32520: enums (make const ints) ! 32521: unreachable code (delete it) ! 32522: make implicit coersions explicit ! 32523: ! 32524: in general you cannot simplify something twice ! 32525: ! 32526: *******************************************************************/ ! 32527: ! 32528: #include "cfront.h" ! 32529: ! 32530: Pname new_fct; ! 32531: Pname del_fct; ! 32532: Pname vec_new_fct; ! 32533: Pname vec_del_fct; ! 32534: ! 32535: Pstmt del_list; ! 32536: Pstmt break_del_list; ! 32537: Pstmt continue_del_list; ! 32538: ! 32539: //bit not_inl; // is the current function an inline? ! 32540: Pname curr_fct; // current function ! 32541: Pexpr init_list; ! 32542: Pexpr one; ! 32543: ! 32544: Ptype Pfct_type; ! 32545: Ptype Pvptr_type; ! 32546: Pbase mptr_type; ! 32547: Ptype size_t_type; ! 32548: ! 32549: Pstmt trim_tail(Pstmt tt); ! 32550: Pname find_vptr(Pclass); ! 32551: char *get_classname(char*); ! 32552: char *drop_classname(char*); ! 32553: loc no_where; // 0,0 ! 32554: ! 32555: int imeasure; // a counter trying to measure the complexity of a function ! 32556: // body to try to avoid expanding ``monster'' inlines. ! 32557: ! 32558: static Pclass topclass; ! 32559: ! 32560: void simpl_init() ! 32561: { ! 32562: char* ns = oper_name(NEW); ! 32563: char* ds = oper_name(DELETE); ! 32564: ! 32565: size_t_type = Pvoid_type->tsizeof()>uint_type->tsizeof()?ulong_type:uint_type; ! 32566: ! 32567: Pname nw = new name(ns); ! 32568: nw->n_oper = NEW; ! 32569: Pname a = new name; ! 32570: a->tp = size_t_type; ! 32571: nw->tp = new fct(Pvoid_type,a,1); ! 32572: new_fct = nw->dcl(gtbl,EXTERN); // void* operator new(long); ! 32573: delete nw; ! 32574: // new_fct->use(); ! 32575: ! 32576: Pname dl = new name(ds); ! 32577: dl->n_oper = DELETE; ! 32578: a = new name; ! 32579: a->tp = Pvoid_type; ! 32580: dl->tp = new fct(void_type,a,1); ! 32581: del_fct = dl->dcl(gtbl,EXTERN); ! 32582: delete dl; ! 32583: // del_fct->use(); ! 32584: ! 32585: ! 32586: Pname vn = new name("__vec_new"); ! 32587: Pname vd = new name("__vec_delete"); ! 32588: ! 32589: a = new name; ! 32590: a->tp = Pvoid_type; ! 32591: Pname al = a; ! 32592: a = new name; ! 32593: a->tp = int_type; ! 32594: a->n_list = al; ! 32595: al = a; ! 32596: a = new name; ! 32597: a->tp = int_type; ! 32598: a->n_list = al; ! 32599: al = a; ! 32600: a = new name; ! 32601: a->tp = Pvoid_type; ! 32602: a->n_list = al; ! 32603: al = a; /* (Pvoid, int, int, Pvoid) */ ! 32604: ! 32605: vec_new_fct = gtbl->insert(vn,0); ! 32606: delete vn; ! 32607: vec_new_fct->tp = new fct(Pvoid_type,al,1); ! 32608: Pfct(vec_new_fct->tp)->f_linkage = linkage_C; ! 32609: vec_new_fct->n_scope = EXTERN; ! 32610: PERM(vec_new_fct); ! 32611: PERM(vec_new_fct->tp); ! 32612: vec_new_fct->use(); ! 32613: vec_new_fct->dcl_print(0); ! 32614: ! 32615: a = new name; ! 32616: a->tp = int_type; ! 32617: al = a; ! 32618: a = new name; ! 32619: a->tp = int_type; ! 32620: a->n_list = al; ! 32621: al = a; ! 32622: a = new name; ! 32623: a->tp = Pvoid_type; ! 32624: a->n_list = al; ! 32625: al = a; ! 32626: a = new name; ! 32627: a->tp = int_type; ! 32628: a->n_list = al; ! 32629: al = a; ! 32630: a = new name; ! 32631: a->tp = int_type; ! 32632: a->n_list = al; ! 32633: al = a; ! 32634: a = new name; ! 32635: a->tp = Pvoid_type; ! 32636: a->n_list = al; ! 32637: al = a; /* (Pvoid, int, int, Pvoid, int, int) */ ! 32638: ! 32639: vec_del_fct = gtbl->insert(vd,0); ! 32640: delete vd; ! 32641: vec_del_fct->tp = new fct(void_type,al,1); ! 32642: Pfct(vec_del_fct->tp)->f_linkage = linkage_C; ! 32643: vec_del_fct->n_scope = EXTERN; ! 32644: PERM(vec_del_fct); ! 32645: PERM(vec_del_fct->tp); ! 32646: vec_del_fct->use(); ! 32647: vec_del_fct->dcl_print(0); ! 32648: ! 32649: one = new ival(1); ! 32650: one->tp = int_type; ! 32651: PERM(one); ! 32652: ! 32653: Pfct_type = new fct(int_type,0,1); // int (*)() ! 32654: Pfct_type = Pfct_type->addrof(); ! 32655: PERM(Pfct_type); ! 32656: ! 32657: putstring("typedef int (*__vptp)();\n"); ! 32658: putstring("struct __mptr {short d; short i; __vptp f; };\n"); ! 32659: Pname b = new name("__mptr"); ! 32660: b->tp = new classdef(STRUCT); ! 32661: b->tp->defined = 1; ! 32662: Pclass(b->tp)->obj_size = 8; ! 32663: mptr_type = new basetype(COBJ,b); ! 32664: PERM(mptr_type); ! 32665: ! 32666: Pvptr_type = mptr_type->addrof(); ! 32667: PERM(Pvptr_type); ! 32668: } ! 32669: ! 32670: Ptable scope; /* current scope for simpl() */ ! 32671: Pname expand_fn; /* name of function being expanded or 0 */ ! 32672: Ptable expand_tbl; /* scope for inline function variables */ ! 32673: ! 32674: Pname classdef::has_oper(TOK op) ! 32675: { ! 32676: Pexpr n = find_name(oper_name(op),0); ! 32677: if (n == 0) return 0; ! 32678: ! 32679: while (n->base==REF || n->base==MDOT) { ! 32680: Pexpr e = Pexpr(n); ! 32681: n = Pname(n->mem); ! 32682: delete e; ! 32683: } ! 32684: if (n->tp->base==FCT && Pname(n)->n_dcl_printed==0) Pname(n)->dcl_print(0); ! 32685: return Pname(n); ! 32686: } ! 32687: ! 32688: int is_expr(Pstmt s) ! 32689: /* ! 32690: is this statement simple enough to be converted into an expression for ! 32691: inline expansion? ! 32692: */ ! 32693: { ! 32694: int i = 0; ! 32695: while (s->base == BLOCK) { ! 32696: if (s->s == 0) return 1; ! 32697: s = s->s; ! 32698: } ! 32699: for (Pstmt ss = s; ss; ss = ss->s_list) { ! 32700: //error('d',"ss %k",ss->base); ! 32701: switch (ss->base) { ! 32702: case BLOCK: ! 32703: if (Pblock(ss)->memtbl || is_expr(ss->s)==0) return 0; ! 32704: case SM: ! 32705: if (ss->e && ss->e->base==ICALL) { ! 32706: Pname fn = ss->e->il->fct_name; ! 32707: Pfct f = Pfct(fn->tp); ! 32708: if (f->f_expr == 0) return 0; ! 32709: } ! 32710: break; ! 32711: case IF: ! 32712: if (is_expr(ss->s)==0) return 0; ! 32713: if (ss->else_stmt && is_expr(ss->else_stmt)==0) return 0; ! 32714: break; ! 32715: default: ! 32716: return 0; ! 32717: } ! 32718: i++; ! 32719: } ! 32720: return i; ! 32721: } ! 32722: ! 32723: int no_of_returns; ! 32724: ! 32725: void name::simpl() ! 32726: { ! 32727: //error('d',"name::simpl%n %d %k",this,tp->base,tp->base); ! 32728: if (base == PUBLIC) return; ! 32729: ! 32730: if (tp == 0) error('i',"%n->N::simple(tp==0)",this); ! 32731: ! 32732: switch (tp->base) { ! 32733: case 0: ! 32734: error('i',"%n->N::simpl(tp->B==0)",this); ! 32735: ! 32736: case TYPE: ! 32737: case VEC: ! 32738: case PTR: ! 32739: { ! 32740: Ptype t = tp; ! 32741: xx: ! 32742: switch (t->base) { ! 32743: case TYPE: t = Pbase(t)->b_name->tp; goto xx; ! 32744: case VEC: t = Pvec(t)->typ; goto xx; ! 32745: case PTR: t = Pptr(t)->typ; goto xx; ! 32746: case FCT: break; ! 32747: } ! 32748: break; ! 32749: } ! 32750: ! 32751: case OVERLOAD: ! 32752: { for (Plist gl = Pgen(tp)->fct_list; gl; gl=gl->l) gl->f->simpl(); ! 32753: break; ! 32754: } ! 32755: ! 32756: case FCT: ! 32757: { Pfct f = Pfct(tp); ! 32758: Pname n; ! 32759: Pname th = f->f_this; ! 32760: ! 32761: if (th) { ! 32762: // Make "this" a register if it is used more than twice: ! 32763: if (th->n_addr_taken) error("&this"); ! 32764: th->n_stclass = (2 < th->n_used) ? REGISTER : AUTO; ! 32765: if (warning_opt ! 32766: && th->n_assigned_to ! 32767: && th->n_assigned_to!=FUDGE111) ! 32768: error('w',&where,"assignment to this (anachronism)"); ! 32769: } ! 32770: ! 32771: if (tp->defined & (SIMPLIFIED | ~DEFINED) ) return; ! 32772: ! 32773: for (n=f->f_args; n; n=n->n_list) n->simpl(); ! 32774: ! 32775: if (f->body) { ! 32776: Ptable oscope = scope; ! 32777: Pname ocurr = curr_fct; ! 32778: int oim = imeasure; ! 32779: scope = f->body->memtbl; ! 32780: //error('d',"body"); ! 32781: if (scope == 0) error('i',"%n memtbl missing",this); ! 32782: curr_fct = this; ! 32783: f->simpl(); ! 32784: if (f->f_inline==0 || debug_opt) ! 32785: f->f_imeasure = 0; // not a converted inline ! 32786: else { ! 32787: ! 32788: if (warning_opt && f->f_virtual) ! 32789: error('w',"virtual function %n cannot be inlined",this); ! 32790: // first check if the function is too large to ! 32791: // be worth inlining ! 32792: if (12<f->f_imeasure) { // cut-over point: ! 32793: // about 12 assignments ! 32794: // f->f_imeasure indicates ! 32795: ! 32796: if (warning_opt) { ! 32797: error('w',"%n too large for inlining",this); ! 32798: } ! 32799: f->f_inline = 0;// a converted inline ! 32800: //error('d',"don't inline%n %d %d %d",this,this,f,f->f_imeasure); ! 32801: scope = oscope; ! 32802: tp->defined |= SIMPLIFIED; ! 32803: return; ! 32804: } ! 32805: int i = 0; ! 32806: for (n=f->f_args; n; n=n->n_list) { ! 32807: n->base = ANAME; ! 32808: n->n_val = i++; ! 32809: // ?? if (n->n_table != scope) error('i',"aname scope: %d %n %d %d\n",n,n,n->n_table,scope); ! 32810: } ! 32811: expand_tbl = (f->returns->base!=VOID || n_oper==CTOR) ? scope : 0; ! 32812: expand_fn = this; ! 32813: ! 32814: if (expand_tbl) { ! 32815: genlab: ! 32816: // value returning: generate expr ! 32817: // the body still holds the memtbl ! 32818: Pexpr ee = Pexpr(f->body->expand()); ! 32819: Ptype t = 0; ! 32820: if (f->s_returns) { ! 32821: if (ee->tp!=f->s_returns) t = f->s_returns; ! 32822: } ! 32823: else if (ee->tp!=f->returns) ! 32824: t = f->returns; ! 32825: // VCVC assumes VOID is output as CHAR: ! 32826: if (t && t==void_type) ! 32827: ee = new expr(CM,ee,new cast(char_type,zero)); ! 32828: f->f_expr = (ee->base==CM) ? ee : new expr(CM,zero,ee); ! 32829: // print.c assumes expansion into comma expression ! 32830: } ! 32831: else { ! 32832: if (is_expr(f->body)) { ! 32833: // can generate expr: do ! 32834: expand_tbl = scope; ! 32835: goto genlab; ! 32836: } ! 32837: // not value return: can generate block ! 32838: f->f_expr = 0; ! 32839: f->body = Pblock(f->body->expand()); ! 32840: } ! 32841: expand_fn = 0; ! 32842: expand_tbl = 0; ! 32843: } ! 32844: scope = oscope; ! 32845: curr_fct = ocurr; ! 32846: imeasure = oim; ! 32847: } ! 32848: break; ! 32849: } ! 32850: ! 32851: case CLASS: ! 32852: Pclass(tp)->simpl(); ! 32853: } ! 32854: ! 32855: // if (n_initializer) n_initializer->simpl(); ! 32856: if (n_key != NESTED && n_initializer) n_initializer->simpl(); ! 32857: tp->defined |= SIMPLIFIED; ! 32858: } ! 32859: ! 32860: Pexpr call_ctor(Ptable tbl, Pexpr p, Pexpr ctor, Pexpr args, int d, Pexpr vb_args) ! 32861: { ! 32862: Pexpr ee = new ref(d,p,ctor); ! 32863: if (p==0 || tbl==0) ee->tp = ctor->tp; ! 32864: //error('d',"call_ctor(tbl %d, p %d, %n, args %d)",tbl,p,ctor,args); ! 32865: if (args && args->base!=ELIST) args = new expr(ELIST,args,0); ! 32866: ee = new expr(G_CALL,ee,args); ! 32867: Pname n = Pname(ctor); ! 32868: while (n->base == MDOT) n = Pname(n->mem); ! 32869: if (n->tp->base == FCT) ee->fct_name = n; ! 32870: if (tbl) ! 32871: ee = ee->typ(tbl); ! 32872: else if (n->tp->base == FCT) ! 32873: ee->tp = Pfct(n->tp)->s_returns; ! 32874: if (ee->tp == any_type) return ee; ! 32875: args = ee->e2; ! 32876: ! 32877: if (vb_args == 0) { // attach zero vbase arguments ! 32878: Pfct f = Pfct(ee->fct_name->tp); // not n->fct_name ! 32879: for (Pname nn = f->f_args->n_list; nn && nn!=f->argtype; nn=nn->n_list) ! 32880: args = new expr(ELIST,zero,args); ! 32881: } ! 32882: else { // attach vbase arguments ! 32883: if (args) { ! 32884: for (Pexpr d = vb_args; d->e2; d=d->e2); ! 32885: d->e2 = args; ! 32886: } ! 32887: args = vb_args; ! 32888: } ! 32889: ! 32890: ee->e2 = args; ! 32891: return ee; ! 32892: } ! 32893: ! 32894: Pexpr call_dtor(Pexpr p, Pexpr dtor, Pexpr arg, int d, Pexpr vb_args) ! 32895: { ! 32896: // error('d',"call dtor %k %n %t vb_args %d",d,dtor,dtor->tp,vb_args); ! 32897: Pexpr r = new ref(d,p,dtor); ! 32898: ! 32899: if (arg && vb_args) ! 32900: arg = new ival(3); ! 32901: else if (vb_args) ! 32902: arg = new ival(2); ! 32903: else if (arg==0) ! 32904: arg = zero; ! 32905: if (arg->tp == 0) arg->tp = int_type; ! 32906: ! 32907: Pexpr aa = new expr(ELIST,arg,0); // argument controlling deallocation ! 32908: // 2: destroy vbases ! 32909: // 1: dealllocate, 0: don't ! 32910: ! 32911: Pfct f = Pfct(dtor->tp); // attach virtual base arguments ! 32912: // for (Pname nn = f->f_args->n_list; nn && nn->n_list; nn=nn->n_list) { ! 32913: // Pexpr xx = vb_args ? new cast(nn->tp,one) : zero; ! 32914: // aa = new expr(ELIST,xx,aa); ! 32915: // } ! 32916: ! 32917: ! 32918: Pexpr ee = new call(r,aa); ! 32919: while (dtor->base == MDOT) dtor = dtor->mem; ! 32920: if (d == REF) // could be virtual ! 32921: ee->fct_name = Pname(dtor); ! 32922: else { // virtual suppressed, store fct name ! 32923: r->n_initializer = dtor; ! 32924: ee->fct_name = 0; ! 32925: } ! 32926: ee->base = G_CALL; ! 32927: ee->tp = void_type; ! 32928: ! 32929: if (f->memof->c_body == 1) f->memof->dcl_print(0); ! 32930: if (Pname(dtor)->n_dcl_printed==0) Pname(dtor)->dcl_print(0); ! 32931: ! 32932: return ee; ! 32933: } ! 32934: ! 32935: //extern int new_used; // pre-define new and delete only if the user didn't ! 32936: ! 32937: Pstmt fct::dtor_simpl(Pclass cl, Pexpr th) ! 32938: { ! 32939: Pstmt dtail = 0; ! 32940: //error('d',"simpl_dtor(%t) a %d",cl,f_args); ! 32941: // if (new_used == 0) new_init(); ! 32942: ! 32943: Pname fa = new name("__free"); // fake argument for dtor ! 32944: fa->tp = int_type; ! 32945: Pname free_arg = fa->dcl(body->memtbl,ARG); ! 32946: free_arg->where = no_where; ! 32947: delete fa; ! 32948: Pname a = f_args; ! 32949: if (a==0 || a->n_list==0) error('i',"__freeA missing in destructor for %t",cl); ! 32950: Pname p = 0; ! 32951: for(;;p=a,a=a->n_list) { // replace nameless fake argument ! 32952: //error('d',"a %d %t",a,a->tp); ! 32953: if (a->n_list == 0) { ! 32954: // a->n_list = free_arg; ! 32955: DEL(p->n_list); ! 32956: p->n_list = free_arg; ! 32957: break; ! 32958: } ! 32959: } ! 32960: ! 32961: // generate calls to destructors for all members of class cl: ! 32962: Ptable tbl = cl->memtbl; ! 32963: int i = 1; ! 32964: for (Pname m=tbl->get_mem(i); m; m=tbl->get_mem(++i) ) { ! 32965: ! 32966: if (m->n_stclass == STATIC || m->base == PUBLIC) continue; ! 32967: ! 32968: Ptype t = m->tp; ! 32969: Pexpr ee = 0; ! 32970: Pname cn; ! 32971: Pname dtor; ! 32972: ! 32973: if (cn = t->is_cl_obj()) { ! 32974: Pclass cl = (Pclass)cn->tp; ! 32975: if (dtor = cl->has_dtor()) { // dtor(this,0,ones); ! 32976: ee = new ref(REF,th,m); ! 32977: ee->tp = m->tp; ! 32978: ee = call_dtor(ee,dtor,0,DOT,one); ! 32979: check_visibility(dtor,0,Pclass(dtor->n_table->t_name->tp),tbl,curr_fct); ! 32980: } ! 32981: } ! 32982: else if (cl_obj_vec) { ! 32983: Pclass cl = Pclass(cl_obj_vec->tp); ! 32984: if (dtor = cl->has_dtor()) { ! 32985: Pfct f = Pfct(dtor->tp); ! 32986: int i = 0; ! 32987: for (Pname nn = f->f_args->n_list; nn && nn->n_list; nn=nn->n_list) i++; ! 32988: //error('d',"dtor %n i %d",dtor,i); ! 32989: ee = new ref(REF,th,m); ! 32990: ee->tp = m->tp; ! 32991: ee = cdvec(vec_del_fct,ee,cl,dtor,0,new ival(i)); ! 32992: check_visibility(dtor,0,Pclass(dtor->n_table->t_name->tp),tbl,curr_fct); ! 32993: } ! 32994: } ! 32995: ! 32996: if (ee) { ! 32997: Pstmt es = new estmt(SM,curloc,ee,0); ! 32998: // reverse order of destructors for members ! 32999: es->s_list = del_list; ! 33000: del_list = es; ! 33001: if (dtail == 0) dtail = es; ! 33002: } ! 33003: } ! 33004: ! 33005: ! 33006: Pexpr ee = 0; ! 33007: // look for bases with destructors: ! 33008: // generate: dtor(base,0); ! 33009: ! 33010: Pbcl b = 0; // get dtors in order with virtual bases last ! 33011: Pbcl t = 0; ! 33012: for (Pbcl l = cl->baselist; l; l=l->next) { ! 33013: if (l->base != VIRTUAL) { ! 33014: Pbcl x = new basecl(l->bclass,0); ! 33015: if (t == 0) ! 33016: b = x; ! 33017: else ! 33018: t->next = x; ! 33019: t = x; ! 33020: x->base = l->base; ! 33021: x->obj_offset = l->obj_offset; ! 33022: } ! 33023: } ! 33024: for (l = cl->baselist; l; l=l->next) { ! 33025: if (l->base == VIRTUAL) { ! 33026: b = new basecl(l->bclass,b); ! 33027: b->base = l->base; ! 33028: b->obj_offset = l->obj_offset; ! 33029: } ! 33030: } ! 33031: Pexpr ve = 0; ! 33032: ! 33033: for (; b; b=l) { ! 33034: Pclass bcl = b->bclass; ! 33035: l = b->next; ! 33036: Pname dtor = bcl->has_dtor(); ! 33037: ! 33038: if (dtor) { ! 33039: Pexpr val = rptr(bcl->this_type,th,b->obj_offset); ! 33040: val = val->contents(); ! 33041: Pexpr e = call_dtor(val,dtor); ! 33042: if (b->base == VIRTUAL) { ! 33043: // if (x) this->x.dtor(); where x is a vbase ! 33044: for (Pname dd = f_this->n_list; dd!=argtype; dd=dd->n_list) ! 33045: if (strcmp(dd->string,bcl->string)==0) break; ! 33046: ! 33047: if (ansi_opt) { // q?void:int would be an error ! 33048: e = new expr(G_CM,e,zero); ! 33049: e->tp = zero_type; ! 33050: } ! 33051: e = new expr(QUEST,e,zero); ! 33052: Pexpr two = new ival(2); ! 33053: two->tp = int_type; ! 33054: e->cond = new expr (AND,free_arg,two);//dd; ! 33055: } ! 33056: ee = ee ? new expr(CM,e,ee) : e; ! 33057: } ! 33058: delete b; ! 33059: } ! 33060: ! 33061: Pstmt es = ee ? new estmt(SM,curloc,ee,0) : 0; ! 33062: ! 33063: ee = new expr(ELIST,th,0); // free storage ! 33064: Pname n = new name(oper_name(DELETE)); ! 33065: Pexpr del = find_name(n,cl,scope,CALL,curr_fct); ! 33066: if (del->tp->base==OVERLOAD || Pfct(del->tp)->nargs==2) { ! 33067: Pexpr ss = new texpr(SIZEOF,cl,0); ! 33068: ss->tp = uint_type; ! 33069: ee->e2 = new expr(ELIST,ss,0); ! 33070: } ! 33071: ee = new call(del,ee); ! 33072: ee->tp = ee->call_fct(scope); ! 33073: ! 33074: Pstmt ess = new estmt(SM,curloc,ee,0); ! 33075: ess = new ifstmt(curloc,new expr(AND,free_arg,one),ess,0); ! 33076: if (es) ! 33077: es->s_list = ess; ! 33078: else ! 33079: es = ess; ! 33080: ! 33081: free_arg->use(); ! 33082: Pname(th)->use(); ! 33083: ! 33084: if (dtail) ! 33085: dtail->s_list = es; ! 33086: else ! 33087: del_list = es; ! 33088: ! 33089: del_list = new ifstmt(curloc,th,del_list,0); ! 33090: if (del_list) del_list->simpl(); ! 33091: return dtail; ! 33092: } ! 33093: ! 33094: ! 33095: Pclass find_vbase_ptr(Pclass cl, Pclass vbase) ! 33096: { ! 33097: for (Pbcl bb = cl->baselist; bb; bb = bb->next) { ! 33098: if (bb->base==VIRTUAL) { ! 33099: if (bb->bclass==vbase && bb->ptr_offset) return cl; ! 33100: } ! 33101: else { ! 33102: Pclass f = find_vbase_ptr(bb->bclass,vbase); ! 33103: if (f) return f; ! 33104: } ! 33105: } ! 33106: return 0; ! 33107: } ! 33108: ! 33109: Pclass second_base(Pclass cl, Pclass base) ! 33110: { ! 33111: //error('d',"second_base(%t,%t)",cl,base); ! 33112: for (Pbcl b = cl->baselist; b && b->base==NAME; b = b->next) { ! 33113: if (b->bclass==base) { ! 33114: if (b==cl->baselist) return 0; ! 33115: return base; ! 33116: } ! 33117: Pclass bb = second_base(b->bclass,base); ! 33118: if (bb == Pclass(-1)) continue; // not found ! 33119: if (bb) { ! 33120: if (b!=cl->baselist) error('s',"C hierarchy too complicated"); ! 33121: return bb; // second base of b->bclass ! 33122: } ! 33123: if (b==cl->baselist) return 0; ! 33124: return b->bclass; // b->bclass is second base ! 33125: } ! 33126: return Pclass(-1); ! 33127: } ! 33128: ! 33129: //Pclass topclass; ! 33130: ! 33131: Pexpr classdef::get_vptr_exp(char *s) ! 33132: { ! 33133: //error('d',"%t::get_vptr_exp(%s)",this,s?s:"0"); ! 33134: if (c_body == 1) dcl_print(0); ! 33135: if (c_body == 3) print_all_vtbls(this); ! 33136: if (s == 0) return find_vptr(this); ! 33137: Pbcl b = get_base(get_classname(s)); ! 33138: Pexpr vp = b->bclass->get_vptr_exp(drop_classname(s)); ! 33139: if (b==baselist && b->base!=VIRTUAL) return vp; ! 33140: vp = new mdot(b->bclass->string,vp); ! 33141: if (c_body == 1) b->bclass->dcl_print(0); ! 33142: if (c_body == 3) b->bclass->print_all_vtbls(b->bclass); ! 33143: if (b->base == VIRTUAL) { ! 33144: vp->i1 = 1; ! 33145: if (b->ptr_offset == 0) { // pointer to base in intermediate base ! 33146: Pclass bb = find_vbase_ptr(this,b->bclass); ! 33147: Pclass sb = second_base(topclass,bb); ! 33148: //error('d',"mdot %t %t : %d %t ",topclass,bb,sb,sb==Pclass(-1)?0:sb); ! 33149: if (sb && sb!=Pclass(-1)) vp = new mdot(sb->string,vp); ! 33150: } ! 33151: } ! 33152: return vp; ! 33153: } ! 33154: ! 33155: int fct::ctor_simpl(Pclass cl, Pexpr th) ! 33156: { ! 33157: Ptable tbl = cl->memtbl; ! 33158: ! 33159: int ass_count = 0; ! 33160: init_list = 0; ! 33161: //error('d',"ctor_simpl %t: %t",cl,this); ! 33162: /* ! 33163: initialization order: ! 33164: (1) virtual base pointers and virtual bases ! 33165: (they may be used in non-virtual bases) ! 33166: (2) non-virtual bases ! 33167: (3) virtual function pointers ! 33168: (4) members ! 33169: */ ! 33170: ! 33171: // initialize virtual base pointers and virtual base objects ! 33172: for (Pbcl l = cl->baselist; l; l=l->next) { ! 33173: Pexpr i = l->init; ! 33174: if (l->base != VIRTUAL) continue; ! 33175: l->init = 0; ! 33176: //error('d',"simpl virtual base %t i %d ",l->bclass,i); ! 33177: ! 33178: // assign virtual OP to virtual base AP ! 33179: Pclass bc = l->bclass; ! 33180: Pexpr dp = 0; ! 33181: ! 33182: // dd = pointer argument for this base; ! 33183: // non-zero if already initialized ! 33184: for (Pname dd = f_this->n_list; dd!=argtype; dd=dd->n_list) ! 33185: if (strcmp(dd->string,bc->string)==0) break; ! 33186: ! 33187: // initialize virtual base object ! 33188: //error('d',"bc %t dd %n offset %d init %d",bc,dd,l->obj_offset,l->init); ! 33189: // => bc_arg = (bc*)((char*)this+offset) ! 33190: int off = l->obj_offset; ! 33191: Pexpr val = rptr(bc->this_type,th,off); ! 33192: dp = new expr(ASSIGN,dd,val); ! 33193: dd->assign(); ! 33194: ! 33195: // => bc::bc() ! 33196: if (i) { ! 33197: switch (i->base) { ! 33198: case ASSIGN: ! 33199: case CM: ! 33200: break; ! 33201: case CALL: ! 33202: case G_CALL: ! 33203: { Pcall cc = Pcall(i); ! 33204: Pname bn = cc->fct_name; ! 33205: ass_count = Pfct(bn->tp)->f_this->n_assigned_to; ! 33206: cc->simpl(); ! 33207: break; ! 33208: } ! 33209: default: ! 33210: error('i',"badBCIr %k",i->base); ! 33211: } ! 33212: dp = new expr(CM,dp,i); ! 33213: } ! 33214: ! 33215: // => (bc_arg==0)?dp:bc_arg ! 33216: for (Pname a = f_args->n_list; a; a = a->n_list) ! 33217: if (strcmp(bc->string,a->string)==0) { ! 33218: dp = new expr(QUEST,dp,a); ! 33219: dp->cond = new expr(EQ,a,zero); ! 33220: break; ! 33221: } ! 33222: ! 33223: // Pname dpp = find_vbase_ptr(bc,cl); ! 33224: for (Pbcl ll=cl->baselist; ll; ll=ll->next) { ! 33225: if (ll->bclass==bc && ll->ptr_offset) { ! 33226: // make sure that the delegate_arg is needed ! 33227: // here and not just in a base ! 33228: ! 33229: // this->Pd = (bc_arg==0)?dp:bc_arg ! 33230: Pexpr dpp = new mdot(bc->string,th); ! 33231: dpp->i1 = 3; ! 33232: dp = new expr(ASSIGN,dpp,dp); ! 33233: //error('d',"dpp %n",dpp); ! 33234: break; ! 33235: } ! 33236: } ! 33237: ! 33238: // reverse init order ! 33239: if (dp) init_list = init_list ? new expr(CM,dp,init_list) : dp; ! 33240: } ! 33241: ! 33242: // generate: this=base::base(args) (non-virtual bases) ! 33243: { ! 33244: for (Pbcl l = cl->baselist; l; l=l->next) { ! 33245: Pexpr i = l->init; ! 33246: if (i==0 || l->base==VIRTUAL) continue; ! 33247: //error('d',"simpl base %t i %d ",l->bclass,i); ! 33248: l->init = 0; ! 33249: ! 33250: switch (i->base) { ! 33251: case ASSIGN: ! 33252: case CM: ! 33253: break; ! 33254: case CALL: ! 33255: case G_CALL: ! 33256: { Pcall cc = Pcall(i); ! 33257: Pname bn = cc->fct_name; ! 33258: ass_count = Pfct(bn->tp)->f_this->n_assigned_to; ! 33259: cc->simpl(); ! 33260: // assign to ``this'' only from only base ! 33261: if (l==cl->baselist && cl->baselist->next==0) i = new expr(ASSIGN,th,cc); ! 33262: break; ! 33263: } ! 33264: default: ! 33265: error('i',"badBCIr %k",i->base); ! 33266: } ! 33267: ! 33268: init_list = init_list ? new expr(G_CM,init_list,i) : i; ! 33269: } ! 33270: } ! 33271: ! 33272: // initialize the vptrs that are updated by this class ! 33273: for (Pvirt blist = cl->virt_list; blist; blist = blist->next) { ! 33274: // if (blist->string==0 && find_vptr(cl)==0) { //opt ! 33275: //error('d',"!!!vptr init %s in %s",blist->string,cl->string); ! 33276: // continue; ! 33277: // } ! 33278: //error('d',"vptr init %s in %s",blist->string,cl->string); ! 33279: topclass = cl; ! 33280: Pexpr vp = cl->get_vptr_exp(blist->string); ! 33281: ! 33282: char *str = 0; ! 33283: char *cs = cl->nested_sig?cl->nested_sig:cl->string; ! 33284: if (cl->lex_level && cl->nested_sig==0) str = make_local_name( cl ); ! 33285: Pexpr vtbl = new text_expr(blist->string,str?str:cs); ! 33286: //Pexpr vtbl = new text_expr(blist->string,cl->string); ! 33287: // vtbl = new cast(Pvptr_type,vtbl); ! 33288: ! 33289: Pexpr ee = new ref(REF,th,vp); ! 33290: ee->tp = vp->tp; ! 33291: ee = new expr(ASSIGN,ee,vtbl); ! 33292: init_list = init_list ? new expr(CM,init_list,ee) : ee; ! 33293: } ! 33294: ! 33295: // initialize members in declaration order: ! 33296: int i; ! 33297: for (Pname m=tbl->get_mem(i=1); m; m=tbl->get_mem(++i) ) { ! 33298: Ptype t = m->tp; ! 33299: Pname cn; ! 33300: Pname ctor; ! 33301: if (t == 0) continue; ! 33302: ! 33303: switch (t->base) { ! 33304: case FCT: ! 33305: case OVERLOAD: ! 33306: case CLASS: ! 33307: case ENUM: ! 33308: continue; ! 33309: } ! 33310: ! 33311: switch (m->n_stclass) { ! 33312: case STATIC: ! 33313: case ENUM: ! 33314: continue; ! 33315: } ! 33316: ! 33317: if (m->base == PUBLIC) continue; ! 33318: ! 33319: Pexpr ee = m->n_initializer; ! 33320: if (ee) m->n_initializer = 0; // from fct must not persist until next fct ! 33321: //error('d',"simpl m %n ee %d",m,ee); ! 33322: if (ee) { ! 33323: // init of non-class mem ! 33324: // set in fct::mem_init() ! 33325: } ! 33326: else if (cn=t->is_cl_obj()) { // try for default ! 33327: Pclass cl = Pclass(cn->tp); ! 33328: if (ctor = cl->has_ictor()) { ! 33329: Pexpr r = new ref(REF,th,m); ! 33330: ee = call_ctor(tbl,r,ctor,0,DOT); ! 33331: check_visibility(ctor,0,Pclass(ctor->n_table->t_name->tp),tbl,curr_fct); ! 33332: } ! 33333: else if (cl->has_ctor()) { ! 33334: error("M%n needsIr (no defaultK forC %s)",m,cl->string); ! 33335: } ! 33336: } ! 33337: else if (cl_obj_vec) { ! 33338: Pclass cl = Pclass(cl_obj_vec->tp); ! 33339: if (ctor = cl->has_ictor()) { // _new_vec(vec,noe,sz,ctor); ! 33340: Pexpr mm = new ref(REF,th,m); ! 33341: mm->tp = m->tp; ! 33342: ee = cdvec(vec_new_fct,mm,cl,ctor,-1,0); ! 33343: check_visibility(ctor,0,Pclass(ctor->n_table->t_name->tp),tbl,curr_fct); ! 33344: } ! 33345: else if (cl->has_ctor()) { ! 33346: error("M%n[] needsIr (no defaultK forC %s)",m,cl->string); ! 33347: } ! 33348: } ! 33349: else if (t->is_ref()) { ! 33350: error("RM%n needsIr",m); ! 33351: } ! 33352: else if (t->tconst() && vec_const==0) { ! 33353: error("constM%n needsIr",m); ! 33354: } ! 33355: ! 33356: if (ee) { ! 33357: ee->simpl(); ! 33358: init_list = init_list ? new expr(CM,init_list,ee) : ee; ! 33359: } ! 33360: } // for m ! 33361: //error('d',"ctor->"); ! 33362: return ass_count; ! 33363: } ! 33364: ! 33365: void fct::simpl() ! 33366: /* ! 33367: call only for the function definition (body != 0) ! 33368: ! 33369: simplify argument initializers, and base class initializer, if any ! 33370: then simplify the body, if any ! 33371: ! 33372: for constructor:call allocator if this==0 and this not assigned to ! 33373: (auto and static objects call constructor with this!=0, ! 33374: the new operator generates calls with this==0) ! 33375: call base & member constructors ! 33376: for destructor: call deallocator (no effect if this==0) ! 33377: case base & member destructors ! 33378: ! 33379: for arguments and function return values look for class objects ! 33380: that must be passed by constructor X(X&). ! 33381: ! 33382: Allocate temporaries for class object expressions, and see if ! 33383: class object return values can be passed as pointers. ! 33384: ! 33385: call constructor and destructor for local class variables. ! 33386: */ ! 33387: { ! 33388: Pexpr th = f_this; ! 33389: Ptable tbl = body->memtbl; ! 33390: Pstmt ss = 0; ! 33391: Pstmt tail; ! 33392: Pclass cl = th ? Pclass(Pbase(Pptr(th->tp)->typ)->b_name->tp) : 0; ! 33393: Pstmt dtail = 0; ! 33394: ! 33395: Pname ocurr_fct = curr_fct; ! 33396: int oret = no_of_returns; ! 33397: int oim = imeasure; ! 33398: ! 33399: //error('d',"fct::simpl %n %t",curr_fct,this); ! 33400: // not_inl = f_inline==0; ! 33401: del_list = 0; ! 33402: continue_del_list = 0; ! 33403: break_del_list = 0; ! 33404: scope = tbl; ! 33405: if (scope == 0) error('i',"F::simpl()"); ! 33406: int ass_count = 0; ! 33407: imeasure = 0; ! 33408: no_of_returns = 0; ! 33409: ! 33410: cc->stack(); ! 33411: cc->nof = curr_fct; ! 33412: cc->ftbl = tbl; ! 33413: ! 33414: // modification for local classes defined within inline functions ! 33415: // error( 'd', "simpl local_class: %d", local_class ); ! 33416: for ( Plist l = local_class; l; l = l->l ) { ! 33417: Pname n = l->f; ! 33418: Pclass cl = Pclass(Pbase(n->tp)->b_name->tp); ! 33419: if ( cl->in_fct == 0 ) cl->in_fct = cc->nof; ! 33420: if ( cl->lcl == 0 ) cl->lcl = make_name( 'L' ); ! 33421: if ( cl->c_body == 1 ) cl->dcl_print(0); ! 33422: } ! 33423: ! 33424: Pfct(cc->nof->tp)->local_class = local_class; ! 33425: local_class = 0; ! 33426: // error( 'd', "simpl nof: %n %d local_class: %d", cc->nof, cc->nof, Pfct(cc->nof->tp)->local_class ); ! 33427: ! 33428: switch (curr_fct->n_scope) { ! 33429: case 0: ! 33430: case PUBLIC: ! 33431: cc->not = curr_fct->n_table->t_name; ! 33432: cc->cot = Pclass(cc->not->tp); ! 33433: cc->tot = cc->cot->this_type; ! 33434: } ! 33435: ! 33436: switch (curr_fct->n_oper) { ! 33437: case DTOR: ! 33438: dtail = dtor_simpl(cl,th); ! 33439: break; ! 33440: case CTOR: ! 33441: ass_count = ctor_simpl(cl,th); ! 33442: } ! 33443: ! 33444: tail = body->simpl(); ! 33445: ! 33446: if (returns->base!=VOID || f_result) { // return must have been seen ! 33447: if (no_of_returns) { // could be OK ! 33448: Pstmt tt = (tail->base==RETURN || tail->base==LABEL) ? tail : trim_tail(tail); ! 33449: ! 33450: switch (tt->base) { ! 33451: case RETURN: ! 33452: case GOTO: ! 33453: del_list = 0; // no need for del_list ! 33454: break; ! 33455: case SM: ! 33456: if (tt->e) ! 33457: switch (tt->e->base) { ! 33458: case ICALL: ! 33459: case G_CALL: ! 33460: goto chicken; ! 33461: } ! 33462: default: ! 33463: if (warning_opt || strcmp(curr_fct->string,"main")) ! 33464: error('w',"maybe no value returned from%n",curr_fct); ! 33465: case IF: ! 33466: case SWITCH: ! 33467: case DO: ! 33468: case WHILE: ! 33469: case FOR: ! 33470: case LABEL: ! 33471: chicken: // don't dare write a warning ! 33472: break; ! 33473: } ! 33474: } ! 33475: else { // must be an error ! 33476: // but we don't dare complain about main() ! 33477: // if (strcmp(curr_fct->string,"main")) ! 33478: // error(Pfct(curr_fct->tp)->returns->is_cl_obj()?0:'w',"no value returned from%n",curr_fct); ! 33479: // else if (warning_opt) ! 33480: // error('w',"no value returned from%n",curr_fct); ! 33481: if (Pfct(curr_fct->tp)->f_inline ! 33482: && Pfct(curr_fct->tp)->returns!=void_type ! 33483: && Pfct(curr_fct->tp)->returns->is_cl_obj()) ! 33484: // can cause code generation errors if allowed ! 33485: error("no value returned from%n",curr_fct); ! 33486: else if (warning_opt || strcmp(curr_fct->string,"main")) ! 33487: error('w',"no value returned from%n",curr_fct); ! 33488: } ! 33489: if (del_list) goto zaq; ! 33490: } ! 33491: else if (del_list) { // return may not have been seen ! 33492: zaq: ! 33493: if (tail) ! 33494: tail->s_list = del_list; ! 33495: else ! 33496: body->s = del_list; ! 33497: tail = dtail; ! 33498: } ! 33499: ! 33500: if (curr_fct->n_oper == DTOR) { // body => if (this == 0) body ! 33501: ! 33502: // reset the vptrs that were set by this class ! 33503: for (Pvirt blist = cl->virt_list; blist; blist = blist->next) { ! 33504: //error('d',"vptr init %s in %s",blist->string,cl->string); ! 33505: topclass = cl; ! 33506: Pexpr vp = cl->get_vptr_exp(blist->string); ! 33507: ! 33508: char *str = 0; ! 33509: char *cs = cl->nested_sig?cl->nested_sig:cl->string; ! 33510: if (cl->lex_level && cl->nested_sig==0) str = make_local_name(cl); ! 33511: Pexpr vtbl = new text_expr(blist->string,str?str:cs); ! 33512: ! 33513: Pexpr ee = new ref(REF,th,vp); ! 33514: ee->tp = vp->tp; ! 33515: ee = new expr(ASSIGN,ee,vtbl); ! 33516: Pstmt es = new estmt(SM,curloc,ee,0); ! 33517: es->s_list = body->s; ! 33518: body->s = es; ! 33519: } ! 33520: ! 33521: body->s = new ifstmt(body->where,th,body->s,0); ! 33522: } ! 33523: ! 33524: if (curr_fct->n_oper == CTOR) { ! 33525: ! 33526: loc temploc=body->where; ! 33527: Pstmt tempss=body->s; ! 33528: while (tempss) { ! 33529: temploc=tempss->where; ! 33530: tempss=tempss->s_list; ! 33531: } ! 33532: ! 33533: if (Pname(th)->n_assigned_to == 0) { ! 33534: /* generate: ! 33535: if (this || (this=_new( sizeof(class cl) ))) { ! 33536: init_list ; ! 33537: body; ! 33538: } ! 33539: */ ! 33540: Pname(th)->n_assigned_to = ass_count ? ass_count : FUDGE111; ! 33541: Pexpr sz = new texpr(SIZEOF,cl,0); ! 33542: (void) cl->tsizeof(); ! 33543: sz->tp = uint_type; ! 33544: Pexpr ee = new expr(ELIST,sz,0); ! 33545: Pname n = new name(oper_name(NEW)); ! 33546: Pexpr p = find_name(n,cl,scope,CALL,curr_fct); ! 33547: //error('d',"in ctor %n call %n",curr_fct,p); ! 33548: ee = new call(p,ee); ! 33549: (void) ee->call_fct(cl->memtbl); ! 33550: ee->simpl(); ! 33551: ee = new expr(ASSIGN,th,ee); ! 33552: ee = new expr(OROR,th,ee); ! 33553: /*ifs->simpl(); ! 33554: do not simplify ! 33555: or "this = " will cause an extra call of base::base ! 33556: */ ! 33557: if (init_list) { ! 33558: Pstmt es = new estmt(SM,body->where,init_list,0); ! 33559: es->s_list = body->s; ! 33560: body->s = es; ! 33561: // if (tail == 0) tail = es; ! 33562: } ! 33563: else if (body->s == 0) ! 33564: body->s = new estmt(SM,body->where,0,0); ! 33565: else if(tail->base==RETURN) { ! 33566: if(body->s == tail) { ! 33567: delete body->s; ! 33568: body->s = new estmt(SM,body->where,0,0); ! 33569: } ! 33570: else { ! 33571: Pstmt pr = body->s; ! 33572: while(pr->s_list != tail) ! 33573: pr = pr->s_list; ! 33574: delete pr->s_list; ! 33575: pr->s_list = 0; ! 33576: } ! 33577: } ! 33578: ! 33579: ifstmt* ifs = new ifstmt(body->where,ee,body->s,0); ! 33580: body->s = ifs; ! 33581: // if (tail == 0) ! 33582: tail = ifs; ! 33583: } ! 33584: // generate: body; return this; ! 33585: Pstmt st = new estmt(RETURN,temploc,th,0); ! 33586: if (tail) ! 33587: tail->s_list = st; ! 33588: else ! 33589: body->s = st; ! 33590: tail = st; ! 33591: } ! 33592: f_imeasure = imeasure; ! 33593: curr_fct = ocurr_fct; ! 33594: no_of_returns = oret; ! 33595: imeasure = oim; ! 33596: cc->unstack(); ! 33597: } ! 33598: ! 33599: ! 33600: void classdef::simpl() ! 33601: { ! 33602: int i; ! 33603: //error('d',"classdef::simpl %s %d",string,defined&SIMPLIFIED); ! 33604: ! 33605: if (defined&SIMPLIFIED) return; ! 33606: ! 33607: Pclass oc = in_class; ! 33608: in_class = this; ! 33609: ! 33610: for (Pname m=memtbl->get_mem(i=1); m; m=memtbl->get_mem(++i) ) { ! 33611: Pexpr i = m->n_initializer; ! 33612: m->n_initializer = 0; ! 33613: m->simpl(); ! 33614: m->n_initializer = i; ! 33615: } ! 33616: ! 33617: in_class = oc; ! 33618: ! 33619: for (Plist fl=friend_list; fl; fl=fl->l) { // simplify friends ! 33620: Pname p = fl->f; ! 33621: switch (p->tp->base) { ! 33622: case FCT: ! 33623: case OVERLOAD: ! 33624: p->simpl(); ! 33625: } ! 33626: } ! 33627: ! 33628: defined |= SIMPLIFIED; ! 33629: } ! 33630: 0707071010112045111004440001630000160000010207100466055410100001100000140465simpl2.c /*ident "@(#)ctrans:src/simpl2.c 1.5" */ ! 33631: /****************************************************************** ! 33632: ! 33633: C++ source for cfront, the C++ compiler front-end ! 33634: written in the computer science research center of Bell Labs ! 33635: ! 33636: Copyright (c) 1984 AT&T, Inc. All rights Reserved ! 33637: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 33638: ! 33639: simpl2.c: ! 33640: ! 33641: simplify the typechecked function ! 33642: remove: classes: ! 33643: class fct-calls ! 33644: operators ! 33645: value constructors and destructors ! 33646: new and delete operators (replace with function calls) ! 33647: initializers (turn them into statements) ! 33648: constant expressions (evaluate them) ! 33649: inline functions (expand the calls) ! 33650: enums (make const ints) ! 33651: unreachable code (delete it) ! 33652: make implicit coersions explicit ! 33653: ! 33654: in general you cannot simplify something twice ! 33655: ! 33656: *******************************************************************/ ! 33657: ! 33658: #include "cfront.h" ! 33659: #include "size.h" ! 33660: #include <ctype.h> ! 33661: ! 33662: extern Pname Ntmp; ! 33663: Pname find_vptr(Pclass); ! 33664: ! 33665: extern int no_of_returns; ! 33666: ! 33667: extern Pname new_fct; ! 33668: //extern Pname del_fct; ! 33669: ! 33670: extern Pstmt del_list; ! 33671: extern Pstmt break_del_list; ! 33672: extern Pstmt continue_del_list; ! 33673: ! 33674: extern Pname curr_fct; // current function ! 33675: extern Pexpr init_list; ! 33676: extern int imeasure; ! 33677: ! 33678: Pexpr cdvec(Pname f, Pexpr vec, Pclass cl, Pname cd, int tail, Pexpr i, Pexpr vec2) ! 33679: /* ! 33680: generate a call to construct or destroy the elements of a vector ! 33681: */ ! 33682: { ! 33683: Pexpr sz = new texpr(SIZEOF,cl,0); // sizeof elem ! 33684: sz->tp = uint_type; ! 33685: (void) cl->tsizeof(); ! 33686: ! 33687: Pexpr esz = new texpr(SIZEOF,cl,0); // noe = sizeof(vec)/sizeof(elem) ! 33688: esz->tp = int_type; ! 33689: ! 33690: Pexpr noe; ! 33691: if (vec2) noe = new texpr(SIZEOF,vec2->tp,0); ! 33692: else noe = new texpr(SIZEOF,vec->tp,0); ! 33693: ! 33694: // Pexpr noe = new texpr(SIZEOF,vec->tp,0); ! 33695: noe->tp = int_type; ! 33696: noe = new expr(DIV,noe,esz); ! 33697: noe->tp = uint_type; ! 33698: // error('d',"cdvec tail %d i %d",tail,i); ! 33699: // Pexpr arg = (0<=tail) ? new expr(ELIST,zero,0) : 0; // 0 or 1 for dtors ! 33700: Pexpr arg = (i) ? new expr(ELIST,i,0) : 0; ! 33701: arg = (0<=tail) ? new expr(ELIST,zero,arg) : arg; // 0 or 1 for dtors ! 33702: arg = new expr(ELIST,cd,arg); // constructor or destructor ! 33703: cd->lval(ADDROF); // cd->take_addr(); ! 33704: ! 33705: arg = new expr(ELIST,sz,arg); ! 33706: arg = new expr(ELIST,noe,arg); ! 33707: arg = new expr(ELIST,vec,arg); ! 33708: ! 33709: arg = new call(f,arg); ! 33710: arg->base = G_CALL; ! 33711: arg->fct_name = f; ! 33712: ! 33713: return arg; ! 33714: } ! 33715: ! 33716: /* ! 33717: int new_used; // pre-define new and delete only if the user didn't ! 33718: ! 33719: void new_init() ! 33720: { ! 33721: char* ns = oper_name(NEW); ! 33722: char* ds = oper_name(DELETE); ! 33723: ! 33724: new_used = 1; ! 33725: ! 33726: new_fct = gtbl->look(ns,0); ! 33727: del_fct = gtbl->look(ds,0); ! 33728: ! 33729: if (new_fct && !del_fct) ! 33730: error('w',"%n defined but not operator delete()",new_fct); ! 33731: if (del_fct && !new_fct) ! 33732: error('w',"%n defined but not operator new()",del_fct); ! 33733: ! 33734: if (Pfct(new_fct->tp)->body==0) new_fct->dcl_print(0); ! 33735: if (Pfct(del_fct->tp)->body==0) del_fct->dcl_print(0); ! 33736: } ! 33737: */ ! 33738: Pstmt trim_tail(Pstmt tt) ! 33739: /* ! 33740: strip off statements after RETURN etc. ! 33741: NOT general: used for stripping off spurious destructor calls ! 33742: */ ! 33743: { ! 33744: if (tt == 0) return 0; ! 33745: ! 33746: while (tt->s_list) { ! 33747: Pstmt tpx; ! 33748: switch (tt->base) { ! 33749: case PAIR: ! 33750: tpx = trim_tail(tt->s2); ! 33751: goto tpxl; ! 33752: case BLOCK: ! 33753: tpx = trim_tail(tt->s); ! 33754: tpxl: ! 33755: if (tpx == 0) return 0; ! 33756: ! 33757: switch (tpx->base) { ! 33758: case SM: ! 33759: break; ! 33760: case CONTINUE: ! 33761: case BREAK: ! 33762: case GOTO: ! 33763: case RETURN: ! 33764: if (tt->s_list->base != LABEL) tt->s_list = 0; ! 33765: default: ! 33766: return tpx; ! 33767: } ! 33768: default: ! 33769: if (tt = tt->s_list) break; ! 33770: return 0; ! 33771: case RETURN: ! 33772: if (tt->s_list->base != LABEL) tt->s_list = 0; ! 33773: return tt; ! 33774: } ! 33775: } ! 33776: ! 33777: switch (tt->base) { ! 33778: case PAIR: return trim_tail(tt->s2); ! 33779: // case LABEL: return trim_tail(tt->s); ! 33780: case BLOCK: if (tt->s) return trim_tail(tt->s); ! 33781: default: return tt; ! 33782: } ! 33783: } ! 33784: ! 33785: extern Ptype Pfct_type; ! 33786: ! 33787: Pexpr mptr_assign(Pexpr n, Pexpr in) ! 33788: { ! 33789: Pexpr i1; ! 33790: Pexpr i2; ! 33791: Pexpr i3; ! 33792: ! 33793: if ( n->base == NAME ) ! 33794: Pname(n)->use(); ! 33795: ! 33796: if (in->base == NAME) { ! 33797: i1 = new mdot("d",in); ! 33798: i1->i1 = 9; ! 33799: i2 = new mdot("i",in); ! 33800: i2->i1 = 9; ! 33801: i3 = new mdot("f",in); ! 33802: i3->i1 = 9; ! 33803: } ! 33804: else { ! 33805: i1 = in->e1->e1; ! 33806: i2 = in->e1->e2; ! 33807: i3 = in->e2; ! 33808: } ! 33809: Pexpr nd = new mdot("d",n); ! 33810: nd->i1 = 9; ! 33811: Pexpr e1 = new expr(ASSIGN,nd,i1); ! 33812: ! 33813: Pexpr ni = new mdot("i",n); ! 33814: ni->i1 = 9; ! 33815: Pexpr e2 = new expr(ASSIGN,ni,i2); ! 33816: ! 33817: Pexpr nf = new mdot("f",n); ! 33818: nf->i1 = 9; ! 33819: // Pexpr ii = in->e2; //new cast(Pfct_type,in->e2); ! 33820: Pexpr e3 = new expr(ASSIGN,nf,i3); ! 33821: ! 33822: Pexpr ee = new expr(CM,e2,e3); ! 33823: return new expr(CM,e1,ee); ! 33824: } ! 33825: ! 33826: Pstmt block::simpl() ! 33827: { ! 33828: int i; ! 33829: Pname n; ! 33830: Pstmt ss=0, sst=0; ! 33831: Pstmt dd=0, ddt=0; ! 33832: Pstmt stail; ! 33833: Ptable old_scope = scope; ! 33834: DB( if(Sdebug>=1) ! 33835: error('d',"%d->block::simple() own_tbl %d memtbl %d curr_fct%n",this,own_tbl,memtbl,curr_fct); ! 33836: ); ! 33837: if (own_tbl == 0) { ! 33838: ss = (s) ? s->simpl() : 0; ! 33839: return ss; ! 33840: } ! 33841: ! 33842: scope = memtbl; ! 33843: if (scope->init_stat == 0) scope->init_stat = 1; /* table is simplified. */ ! 33844: ! 33845: for (n=scope->get_mem(i=1); n; n=scope->get_mem(++i)) { ! 33846: Pstmt st = 0; ! 33847: Pname cln; ! 33848: Pexpr in = n->n_initializer; ! 33849: // error('d',"local %k %n in %k %t",n->n_sto,n,in?in->base:0,in?in->tp:0); ! 33850: if (in || n->n_evaluated) { ! 33851: scope->init_stat = 2; /* initializer in this scope */ ! 33852: if (n->n_sto == EXTERN) { ! 33853: error(&n->where,"Id local extern%n",n); ! 33854: continue; ! 33855: } ! 33856: } ! 33857: ! 33858: switch (n->n_scope) { ! 33859: case ARG: ! 33860: case 0: ! 33861: case PUBLIC: ! 33862: continue; ! 33863: } ! 33864: ! 33865: if (n->n_stclass == STATIC) { // local static class object ! 33866: /* initialization of local static objects; ! 33867: * set up first pass switch ! 33868: * temp_switch ? 0 ! 33869: * : (stat_obj=init_expr, temp_switch=1); ! 33870: * ! 33871: * ARGS: temporary class object in init_expr with dtor ! 33872: * must call dtor once in std function ! 33873: */ ! 33874: ! 33875: if ((in==0 && n->n_scope==ARGS) || ! 33876: (in && in->base==STAT_INIT)) ! 33877: { ! 33878: Pname cn; ! 33879: Pname x; ! 33880: Ptype ct; ! 33881: int vec_seen = 0; ! 33882: ! 33883: cn = n->tp->is_cl_obj(); ! 33884: if ( cn == 0 ) { ++vec_seen; cn = cl_obj_vec; } ! 33885: ! 33886: if ( cn ) { ! 33887: ct = new ptr(PTR,vec_seen?Pvec(n->tp)->typ:n->tp); ! 33888: x = make_tmp('F', ct, gtbl ); ! 33889: x->n_initializer = zero; ! 33890: } ! 33891: else ! 33892: x = make_tmp('F',int_type,scope); ! 33893: ! 33894: x->n_sto = n->n_stclass = STATIC; ! 33895: ! 33896: if (in) { ! 33897: if (in->e2) ! 33898: in->base = ASSIGN; ! 33899: else in = in->e1; ! 33900: } ! 33901: ! 33902: Pexpr set; ! 33903: if ( cn ) { ! 33904: x->dcl_print(0); ! 33905: Pclass cl = Pclass(cn->tp); ! 33906: Pname dtor = cl->has_dtor(); ! 33907: ! 33908: Pexpr cc; ! 33909: if ( dtor ) { ! 33910: if ( vec_seen == 0 ) { ! 33911: Pexpr eee = new expr(DEREF, x, 0 ); ! 33912: Pexpr c = call_dtor(eee,dtor,0,DOT,one); ! 33913: c->tp = any_type; ! 33914: cc = new expr( QUEST, c, zero ); ! 33915: cc->cond = x; ! 33916: } ! 33917: else cc = cdvec(vec_del_fct,x,cl,dtor,0,zero,n); ! 33918: cc->tp = any_type; // arghh! ! 33919: ! 33920: Pstmt dls = new estmt( SM, n->where, cc, 0 ); ! 33921: if ( st_dlist ) dls->s_list = st_dlist; ! 33922: st_dlist = dls; ! 33923: } ! 33924: ! 33925: Pexpr xe; ! 33926: if (cn) { ! 33927: if ( vec_seen == 0 ) ! 33928: xe = new expr( G_ADDROF, 0, n ); ! 33929: else { ! 33930: Pexpr ee = new expr( DEREF, n, zero ); ! 33931: xe = new expr( G_ADDROF, 0, ee ); ! 33932: } ! 33933: } ! 33934: ! 33935: set = new expr(ASSIGN,x,xe); ! 33936: set->tp = ct; ! 33937: } ! 33938: else { ! 33939: set = new expr(ASSIGN,x,one); ! 33940: set->tp = int_type; ! 33941: } ! 33942: ! 33943: // set pointer to static object and continue ! 33944: // sorry for goto, but beats rewriting code ! 33945: if ( n->n_scope == ARGS && in == 0 ) { ! 33946: set = new expr( QUEST, zero, set ); ! 33947: set->cond = x; ! 33948: st = new estmt(SM,n->where,set,0); ! 33949: goto init_stat3; ! 33950: } ! 33951: ! 33952: in = new expr(G_CM,in,set); ! 33953: in = new expr(STAT_INIT,zero,in); ! 33954: in->cond = x; ! 33955: } ! 33956: else ! 33957: continue; ! 33958: } ! 33959: ! 33960: if ( in ) { ! 33961: if ((in->base == ILIST && in->e2 == 0) || ! 33962: (in->base == STRING && n->tp->base == VEC)) ! 33963: if (ansi_opt==0) { ! 33964: error('s',&n->where,"initialization of%n (automatic aggregate)",n); ! 33965: continue; ! 33966: } ! 33967: } ! 33968: ! 33969: if (n->tp == 0) continue; /* label */ ! 33970: if (n->n_evaluated) continue; ! 33971: ! 33972: /* construction and destruction of temporaries is handled locally */ ! 33973: { char* s = n->string; ! 33974: register char c3 = s[4]; ! 33975: if (s[0]=='_' && s[1]=='_' && s[2]=='D' && isdigit(c3)) continue; ! 33976: } ! 33977: ! 33978: if ( cln=n->tp->is_cl_obj() ) { ! 33979: Pclass cl = Pclass(cln->tp); ! 33980: Pname d = cl->has_dtor(); ! 33981: ! 33982: if ( n->n_stclass == STATIC // local static class object ! 33983: && in && in->base==STAT_INIT ) ! 33984: goto stat_init; ! 33985: ! 33986: if (d) { // n->cl.dtor(0); ! 33987: Pexpr dl = call_dtor(n,d,0,DOT,one); ! 33988: // Pstmt dls = new estmt(SM,n->where,dl,0); ! 33989: Pstmt dls = new estmt(SM,no_where,dl,0); ! 33990: if (dd) { ! 33991: dls->s_list = dd; ! 33992: dd = dls; ! 33993: } ! 33994: else ! 33995: ddt = dd = dls; ! 33996: } ! 33997: ! 33998: // error('d',"%n: in %d",n,in?in->base:0); ! 33999: if (in) { ! 34000: switch (in->base) { ! 34001: case DEREF: // *constructor? ! 34002: if (in->e1->base == G_CALL) { ! 34003: Pname fn = in->e1->fct_name; ! 34004: if (fn==0 || fn->n_oper!=CTOR) goto ddd; ! 34005: st = new estmt(SM,n->where,in->e1,0); ! 34006: n->n_initializer = 0; ! 34007: break; ! 34008: } ! 34009: goto ddd; ! 34010: case STAT_INIT: ! 34011: stat_init: ! 34012: // error('d', "block::simpl: case #1 stat_init : n: %n", n ); ! 34013: in->base = QUEST; ! 34014: st = new estmt(SM,n->where,in,0); ! 34015: n->n_initializer = 0; ! 34016: break; ! 34017: case G_CM: ! 34018: st = new estmt(SM,n->where,in->e1,0); ! 34019: n->n_initializer = 0; ! 34020: break; ! 34021: case ASSIGN: // assignment to "n"? ! 34022: if (in->e1 == n) { ! 34023: st = new estmt(SM,n->where,in,0); ! 34024: n->n_initializer = 0; ! 34025: break; ! 34026: } ! 34027: default: ! 34028: goto ddd; ! 34029: } ! 34030: } ! 34031: } ! 34032: else if (cl_obj_vec) { ! 34033: Pclass cl = Pclass(cl_obj_vec->tp); ! 34034: Pname d = cl->has_dtor(); ! 34035: Pname c = cl->has_ictor(); ! 34036: n->n_initializer = 0; ! 34037: ! 34038: if ( n->n_stclass == STATIC // local static class object ! 34039: && in && in->base==STAT_INIT ) ! 34040: goto stat_init2; ! 34041: ! 34042: if (c) { // _vec_new(vec,noe,sz,ctor); ! 34043: if (in==0 || in->base==ILIST) { ! 34044: Pexpr a = cdvec(vec_new_fct,n,cl,c,-1,0); ! 34045: st = new estmt(SM,n->where,a,0); ! 34046: } ! 34047: else ! 34048: st = new estmt(SM,n->where,in,0); ! 34049: } ! 34050: // no default ctor but provided all elements with argument ! 34051: else if ( in ) st = new estmt(SM,n->where,in,0); ! 34052: ! 34053: ! 34054: if (d) { // __vec_delete(vec,noe,sz,dtor,0); ! 34055: Pfct f = Pfct(d->tp); ! 34056: int i = 0; ! 34057: for (Pname nn = f->f_args->n_list; ! 34058: nn && nn->n_list; nn=nn->n_list) i++; ! 34059: Pexpr a = cdvec(vec_del_fct,n,cl,d,0,new ival(i)); ! 34060: // Pstmt dls = new estmt(SM,n->where,a,0); ! 34061: Pstmt dls = new estmt(SM,no_where,a,0); ! 34062: if (dd) { ! 34063: dls->s_list = dd; ! 34064: dd = dls; ! 34065: } ! 34066: else ! 34067: ddt = dd = dls; ! 34068: } ! 34069: } ! 34070: else if (in) { ! 34071: switch (in->base) { ! 34072: case ILIST: ! 34073: switch (n->n_scope) { ! 34074: case FCT: ! 34075: if (in->e2) { // pointer to member ! 34076: Pexpr ee = mptr_assign(n,in); ! 34077: st = new estmt(SM,n->where,ee,0); ! 34078: n->n_initializer = 0; ! 34079: break; ! 34080: } ! 34081: case ARG: ! 34082: if (ansi_opt == 0) error('s',"Ir list for localV%n",n); ! 34083: } ! 34084: break; ! 34085: case STAT_INIT: ! 34086: stat_init2: ! 34087: // error('d', "block::simpl: case #2 stat_init : n: %n", n ); ! 34088: in->base = QUEST; ! 34089: st = new estmt(SM,n->where,in,0); ! 34090: n->n_initializer = 0; ! 34091: break; ! 34092: case STRING: ! 34093: if (n->tp->base==VEC) break; /* BUG char vec only */ ! 34094: default: ! 34095: ddd: ! 34096: { Pexpr ee = new expr(ASSIGN,n,in); ! 34097: st = new estmt(SM,n->where,ee,0); ! 34098: n->n_initializer = 0; ! 34099: } ! 34100: } ! 34101: } ! 34102: ! 34103: init_stat3: if (st) { ! 34104: if (ss) ! 34105: sst->s_list = st; ! 34106: else ! 34107: ss = st; ! 34108: sst = st; ! 34109: } ! 34110: } ! 34111: ! 34112: if (dd) { ! 34113: Pstmt od = del_list; ! 34114: Pstmt obd = break_del_list; ! 34115: Pstmt ocd = continue_del_list; ! 34116: ! 34117: dd->simpl(); ! 34118: del_list = (od) ? Pstmt(new pair(curloc,dd,od)) : dd; ! 34119: break_del_list = (break_del_list&&obd) ? Pstmt(new pair(curloc,dd,obd)) : dd; ! 34120: continue_del_list = (continue_del_list&&ocd) ? Pstmt(new pair(curloc,dd,ocd)) : dd; ! 34121: ! 34122: stail = s ? s->simpl() : 0; ! 34123: ! 34124: Pfct f = Pfct(curr_fct->tp); ! 34125: if (this!=f->body ! 34126: || f->returns->base==VOID ! 34127: || (f->returns->base!=VOID && no_of_returns==0 ) // you have been warned! ! 34128: || strcmp(curr_fct->string,"main")==0 ) { ! 34129: // not dropping through the bottom of a value returning function ! 34130: if (stail) { ! 34131: Pstmt tt = (stail->base==RETURN || stail->base==LABEL) ? stail : trim_tail(stail); ! 34132: if (tt && tt->base != RETURN) stail->s_list = dd; ! 34133: } ! 34134: else ! 34135: s = dd; ! 34136: stail = ddt; ! 34137: } ! 34138: ! 34139: del_list = od; ! 34140: continue_del_list = ocd; ! 34141: break_del_list = obd; ! 34142: } ! 34143: else ! 34144: stail = s ? s->simpl() : 0; ! 34145: ! 34146: if (ss) { /* place constructor calls */ ! 34147: ss->simpl(); ! 34148: sst->s_list = s; ! 34149: s = ss; ! 34150: if (stail == 0) stail = sst; ! 34151: } ! 34152: ! 34153: scope = old_scope; ! 34154: ! 34155: return stail; ! 34156: } ! 34157: ! 34158: int no_sizeof; ! 34159: ! 34160: void expr::simpl() ! 34161: { ! 34162: DB(if(Sdebug>=2){ ! 34163: error('d',"%d->expr::simpl() %k",this,this?base:0); ! 34164: if(Sdebug>=3) display_expr(this); ! 34165: }); ! 34166: if (this==0 || permanent==2) return; // already expanded ! 34167: static TOK obase = 0; ! 34168: ! 34169: switch (base) { ! 34170: case MDOT: ! 34171: obase = base; ! 34172: mem->simpl(); ! 34173: obase = 0; ! 34174: // no break ! 34175: ! 34176: case ICALL: // already expanded ! 34177: return; ! 34178: ! 34179: case G_ADDROF: ! 34180: case ADDROF: ! 34181: // error('d',"simpl & %k",e2->base); ! 34182: ! 34183: e2->simpl(); ! 34184: switch (e2->base) { ! 34185: case DOT: ! 34186: case REF: ! 34187: { Pref r = Pref(e2); ! 34188: Pname m = Pname(r->mem); ! 34189: while (m->base == MDOT) m = Pname(m->mem); ! 34190: if (m->n_stclass == STATIC) { // & static member ! 34191: Pexpr x; ! 34192: delp: ! 34193: x = e2; ! 34194: e2 = m; ! 34195: r->mem = 0; ! 34196: DEL(x); ! 34197: } ! 34198: else if (m->tp->base == FCT) { // & member fct ! 34199: Pfct f = Pfct(m->tp); ! 34200: if (f->f_virtual) { // &p->f ==> p->vtbl[fi].f ! 34201: int index = f->f_virtual; ! 34202: Pexpr ie = index ? new ival(index):0; ! 34203: if (ie) ie->tp = int_type; ! 34204: Pname cn = m->n_table->t_name; ! 34205: Pname vp = find_vptr(Pclass(cn->tp)); ! 34206: r->mem = vp; ! 34207: ! 34208: if ( obase == MDOT ) { ! 34209: base = DEREF; ! 34210: e1 = e2; ! 34211: e2 = ie; ! 34212: } ! 34213: else { // support old style &b.vf ! 34214: base = MDOT; ! 34215: mem = new expr(DEREF,e2,ie); ! 34216: string2 = "f"; ! 34217: i1 = 9; ! 34218: } ! 34219: } ! 34220: else { ! 34221: goto delp; ! 34222: } ! 34223: } ! 34224: break; ! 34225: } ! 34226: } ! 34227: break; ! 34228: ! 34229: case ANDAND: ! 34230: case OROR: ! 34231: Ntmp = 0; ! 34232: // no break ! 34233: ! 34234: default: ! 34235: if (e1) e1->simpl(); ! 34236: if (e2) e2->simpl(); ! 34237: break; ! 34238: ! 34239: case CM: ! 34240: case G_CM: ! 34241: { ! 34242: Pname n = 0; ! 34243: e1->simpl(); ! 34244: e2->simpl(); ! 34245: if (e1->base==ICALL && e1->e1==0) n = e1->il->fct_name; ! 34246: if (e2->base==ICALL && e2->e1==0) n = e2->il->fct_name; ! 34247: if (n) error('s',"cannot expand inline void%n called in commaE",n); ! 34248: // no break ! 34249: } ! 34250: case NAME: ! 34251: case DUMMY: ! 34252: case ICON: ! 34253: case FCON: ! 34254: case CCON: ! 34255: case IVAL: ! 34256: // case FVAL: ! 34257: // case LVAL: ! 34258: case STRING: ! 34259: case ZERO: ! 34260: case ILIST: ! 34261: // case MDOT: ! 34262: return; ! 34263: /* ! 34264: case SIZEOF: ! 34265: base = IVAL; ! 34266: i1 = tp2->tsizeof(); ! 34267: tp2 = 0; // can't DEL(tp2) ! 34268: break; ! 34269: */ ! 34270: case SIZEOF: ! 34271: if (e1) e1->simpl(); ! 34272: return; ! 34273: ! 34274: case G_CALL: ! 34275: case CALL: ! 34276: Pcall(this)->simpl(); ! 34277: break; ! 34278: ! 34279: case NEW: ! 34280: case GNEW: ! 34281: simpl_new(); ! 34282: return; ! 34283: ! 34284: case DELETE: ! 34285: case GDELETE: ! 34286: simpl_delete(); ! 34287: break; ! 34288: ! 34289: case QUEST: ! 34290: cond->simpl(); ! 34291: Ntmp = 0; ! 34292: e2->simpl(); ! 34293: // no break ! 34294: ! 34295: case CAST: ! 34296: case REF: ! 34297: e1->simpl(); ! 34298: break; ! 34299: ! 34300: case DOT: ! 34301: e1->simpl(); ! 34302: switch (e1->base) { ! 34303: case CM: ! 34304: case G_CM: ! 34305: { // &( , name). => ( ... , &name)-> ! 34306: Pexpr ex = e1; ! 34307: cfr: ! 34308: switch (ex->e2->base) { ! 34309: case NAME: ! 34310: base = REF; ! 34311: ex->e2 = ex->e2->address(); ! 34312: break; ! 34313: case CM: ! 34314: case G_CM: ! 34315: ex = ex->e2; ! 34316: goto cfr; ! 34317: } ! 34318: } ! 34319: } ! 34320: break; ! 34321: ! 34322: case ASSIGN: ! 34323: { ! 34324: Pfct f = 0; ! 34325: Pexpr th = 0; ! 34326: if ( curr_fct ) { ! 34327: f = Pfct(curr_fct->tp); ! 34328: th = f->f_this; ! 34329: } ! 34330: ! 34331: imeasure++; ! 34332: if (e1) e1->simpl(); ! 34333: if (e2) { ! 34334: Pexpr c = e2; ! 34335: c->simpl(); ! 34336: while (c->base == CAST) c = c->e1; ! 34337: if (c->base == ILIST) e2 = c; ! 34338: ! 34339: if (e2->base == ILIST) { // pointer to member assignment ! 34340: Pexpr ee = mptr_assign(e1,e2); ! 34341: Pexpr eee = new expr(CM,ee->e2,e1); ! 34342: e1 = ee->e1; ! 34343: e2 = eee; ! 34344: base = CM; ! 34345: delete ee; ! 34346: } ! 34347: } ! 34348: ! 34349: if (th && th==e1 && curr_fct->n_oper==CTOR && init_list) { ! 34350: // this=e2 => (this=e2,init_list) ! 34351: Pclass cl = Pclass(Pbase(Pptr(th->tp)->typ)->b_name->tp); ! 34352: if (cl->c_body == 1) cl->dcl_print(0); ! 34353: imeasure++; ! 34354: base = CM; ! 34355: e1 = new expr(ASSIGN,e1,e2); ! 34356: e2 = init_list; ! 34357: if (warning_opt) // timid ! 34358: error('w',"assignment to ``this'' inK: try defining%t::operator new() instead",f->memof); ! 34359: } ! 34360: break; ! 34361: } ! 34362: } ! 34363: ! 34364: switch (base) { ! 34365: case QUEST: ! 34366: case ANDAND: ! 34367: case OROR: ! 34368: if (Ntmp) error('s',"temporary ofC%n with destructor needed in%kE",Ntmp,base); ! 34369: // no break; ! 34370: default: ! 34371: Ntmp = 0; ! 34372: } ! 34373: ! 34374: if (tp==int_type || tp==defa_type) { ! 34375: Neval = 0; ! 34376: no_sizeof = 1; // do not convert sizeof's to ints ! 34377: long i = eval(); ! 34378: no_sizeof = 0; ! 34379: if (Neval == 0) { ! 34380: base = IVAL; ! 34381: i1 = i; ! 34382: } ! 34383: } ! 34384: ! 34385: } ! 34386: ! 34387: Pexpr vptr_entry(Pexpr pp, Pexpr ie, Pclass cl) ! 34388: { ! 34389: Pptr ttemp = pp->tp->is_ptr_or_ref(); ! 34390: ! 34391: if (ttemp) { ! 34392: Ptype pt = ttemp->typ; // check if cast pp = (base*)pp ! 34393: Pclass pc = Pclass(pt->is_cl_obj()->tp); // is needed ! 34394: if (pc!=cl) pp = new cast(cl,pp); ! 34395: } ! 34396: Pname vp = find_vptr(cl); ! 34397: if (vp == 0) error('i',"can't find vptr"); ! 34398: Pexpr vptr = new ref(REF,pp,vp); // pp->vptr ! 34399: return new expr(DEREF,vptr,ie); // pp->vptr[i] ! 34400: } ! 34401: ! 34402: Pexpr new_this(Pexpr pp, Pexpr ee) ! 34403: { ! 34404: //error('d',"new this"); ! 34405: Pexpr dee = new mdot("d",ee); // pp->vptr[i].d ! 34406: dee->i1 = 9; ! 34407: Pexpr nthis = new cast(Pchar_type,pp); ! 34408: nthis = new expr(PLUS,nthis,dee); // ((char*)pp)+delta ! 34409: Ptype ct = pp->tp; ! 34410: if (pp->base==NAME && Pname(pp)->n_xref) ct = pp->tp->addrof(); ! 34411: return new cast(ct,nthis); ! 34412: } ! 34413: ! 34414: Pcall vcall(Pexpr pp, Pexpr ie, Pfct f, Pclass cl, Pexpr args) ! 34415: /* ! 34416: generate a call of the virtual function with the index ``ie'' ! 34417: and type "f" in class ``cl'' for the object pointed to by ``pp'' ! 34418: ! 34419: multiple inheritance virtual call: ! 34420: ! 34421: p->f(x) is resolved like this ! 34422: pp = p; // avoid side effects ! 34423: pp = p.base_object; // often: pp = p; ! 34424: // done when the name was resolved ! 34425: i = index(f); ! 34426: entry = pp->_vtbl[i-1]; ! 34427: pp = (T*)(((char*)pp)+entry.d) ! 34428: (*(ftype)entry.f)(pp,x) ! 34429: */ ! 34430: { ! 34431: //error('d',"vcall %t",cl); ! 34432: if (cl->c_body==1) cl->dcl_print(0); // look for first use of cl ! 34433: ! 34434: imeasure+=6; ! 34435: Pexpr ee = vptr_entry(pp,ie,cl); ! 34436: ! 34437: Pexpr fee = new mdot("f",ee); ! 34438: fee->i1 = 9; ! 34439: Ptype pft = f->addrof(); ! 34440: fee = new cast(pft,fee); // (T)pp->vptr[i].f ! 34441: Pexpr r = new expr(DEREF,fee,0); // *(T)pp->vptr[i].f ! 34442: // e1->tp must be 0, means "argtype encoded" ! 34443: r->tp2 = Ptype(f->f_this); // encode argtype ! 34444: ! 34445: Pexpr nthis = new_this(pp,ee); ! 34446: ! 34447: args = new expr(ELIST,nthis,args); ! 34448: args->simpl(); ! 34449: ! 34450: Pcall c = new call(r,args); ! 34451: c->tp = f->returns; ! 34452: return c; ! 34453: } ! 34454: ! 34455: void call::simpl() ! 34456: /* ! 34457: fix member function calls: ! 34458: p->f(x) becomes f(p,x) ! 34459: o.f(x) becomes f(&o,x) ! 34460: or if f is virtual: ! 34461: p->f(x) is resolved like this ! 34462: pp = p; ! 34463: i = index(f); ! 34464: entry = pp->_vtbl[i-1]; ! 34465: pp = (T*)(((char*)pp)+entry.i) ! 34466: (*entry.f)(pp,x) ! 34467: replace calls to inline functions by the expanded code ! 34468: */ ! 34469: { ! 34470: Pname fn = fct_name; ! 34471: //error('d',"%d call::simpl() fn %n %d e1 %d",this,fn,fn,e1); ! 34472: Pfct f = fn ? Pfct(fn->tp) : 0; ! 34473: ! 34474: if (fn == 0) e1->simpl(); ! 34475: ! 34476: if (f) { ! 34477: switch(f->base) { ! 34478: case ANY: ! 34479: return; ! 34480: case OVERLOAD: ! 34481: fct_name = fn = Pgen(f)->fct_list->f; ! 34482: f = Pfct(fn->tp); ! 34483: } ! 34484: } ! 34485: ! 34486: switch (e1->base) { ! 34487: case MEMPTR: // (p ->* q)(args) ! 34488: { ! 34489: Pexpr p = e1->e1; ! 34490: Pexpr q = e1->e2; ! 34491: Pclass cl = Pclass(e1->tp2); ! 34492: Pfct f = Pfct(q->tp->deref()); ! 34493: ! 34494: if (e2) e2->simpl(); ! 34495: ! 34496: if (f->f_this == 0) { // might not know about ``this'' yet ! 34497: if (f->memof == 0) error('i',"memof missing"); ! 34498: Pname tt = new name("this"); ! 34499: tt->n_scope = ARG; ! 34500: tt->tp = f->memof->this_type; ! 34501: PERM(tt); ! 34502: // f->f_this = f->f_args = tt; ! 34503: tt->n_list = f->argtype; ! 34504: // f->f_this = tt; ! 34505: tt->n_list = f->f_result ? f->f_result : f->argtype; ! 34506: f->f_this = f->f_args = tt; ! 34507: } ! 34508: //error('d',"f_this %d",f->f_this); ! 34509: extern has_virt(Pclass); ! 34510: ! 34511: // beware of sideeffects: ! 34512: nin = 1; ! 34513: if (q->not_simple()) error('s',"2nd operand of .* too complicated"); ! 34514: nin = 0; ! 34515: ! 34516: Pexpr qq = new mdot("f",q); // the function: (*(right type)q.f) ! 34517: qq->i1 = 9; ! 34518: qq = new cast(f->addrof(),qq); ! 34519: Pexpr nc = new expr(DEREF,qq,0); ! 34520: nc->tp2 = Ptype(f->f_this); // encode argtype ! 34521: ! 34522: Pexpr nthis = new_this(p,q); // arguments: (p+q.d,args) ! 34523: Pexpr args = new expr(ELIST,nthis,e2); ! 34524: imeasure+=3; ! 34525: ! 34526: if (has_virt(cl) == 0) { // no virtuals: simple ! 34527: if (cl->defined == 0) ! 34528: error("call throughP toMF before definition ofC %t",cl); ! 34529: //error('d',"no virt"); ! 34530: // (p ->* q)(args) => (*q.f)(p+q.d,args) ! 34531: e1 = nc; ! 34532: e2 = args; ! 34533: return; ! 34534: } ! 34535: ! 34536: if (find_vptr(cl) == 0) { // must be a call to a second base ! 34537: // that we cannot handle yet ! 34538: // it is OK not to to generate ! 34539: // a virtual call since a ! 34540: // `sorry' will have been generated ! 34541: // at the point of initialization ! 34542: e1 = nc; ! 34543: e2 = args; ! 34544: return; ! 34545: ! 34546: } ! 34547: // beware of sideeffects: ! 34548: nin = 1; ! 34549: if (p->not_simple()) error('s',"1st operand of .* too complicated"); ! 34550: nin = 0; ! 34551: ! 34552: Pexpr c = new mdot("i",q); // condition (q.i<0) ! 34553: c->i1 = 9; ! 34554: c = new expr(LT,c,zero); ! 34555: ! 34556: Pexpr ie = new mdot("i",q); ! 34557: ie->i1 = 9; ! 34558: ! 34559: base = QUEST; ! 34560: e1 = new call(nc,args); ! 34561: e2 = vcall(p,ie,f,cl,e2); ! 34562: cond = c; ! 34563: return; ! 34564: } ! 34565: case DOT: ! 34566: // if e1 is an object and not just a reference ! 34567: // the vtbl need not be used ! 34568: case REF: ! 34569: { Pref r = Pref(e1); ! 34570: Pexpr a1 = r->e1; ! 34571: int obj = r->n_initializer!=0; // if B::f don't use vcall ! 34572: ! 34573: if (obj == 0) { // don't use vcall if we have an object ! 34574: // (not a pointer or a reference) ! 34575: if (e1->base==DOT && a1->base!=DEREF) obj = 1; ! 34576: } ! 34577: ! 34578: //error('d',"fct_name %n f %d %d obj %d",fct_name,f,f->f_virtual,obj); ! 34579: if (f && obj==0 && f->f_virtual) { ! 34580: Pexpr a11 = 0; ! 34581: ! 34582: switch(a1->base) { // see if temporary might be needed ! 34583: case NAME: ! 34584: case MDOT: ! 34585: a11 = a1; ! 34586: break; ! 34587: case REF: ! 34588: case DOT: ! 34589: if (a1->e1->base==NAME ! 34590: || ((a1->e1->base==DOT || a1->e1->base==REF) && a1->e1->e1->base==NAME)) a11 = a1; ! 34591: break; ! 34592: case ADDROF: ! 34593: case G_ADDROF: ! 34594: if (a1->e2->base == NAME ! 34595: || ((a1->e2->base==DOT || a1->e2->base==REF) && a1->e2->e1->base==NAME)) a11 = a1; ! 34596: break; ! 34597: case CAST: ! 34598: switch (a1->e1->base) { ! 34599: case NAME: ! 34600: case MDOT: ! 34601: a11 = a1; ! 34602: } ! 34603: } ! 34604: ! 34605: // if( a1->base==REF && fn->n_oper==DTOR ){ ! 34606: // a11 = a1; ! 34607: // goto zsw; ! 34608: // } ! 34609: // ! 34610: if (e1->base == DOT) { ! 34611: // zsw: ! 34612: if (a11) a11 = a11->address(); ! 34613: a1 = a1->address(); ! 34614: } ! 34615: ! 34616: if (a11 == 0) { // temporary (maybe) needed ! 34617: // e->f() => (t=e,t->f(t)) ! 34618: if (a1->base==NAME) ! 34619: a11 = a1; // &*name has become name ! 34620: else { ! 34621: Pname nx = new name(make_name('K')); ! 34622: nx->tp = a1->tp; ! 34623: Pname n = nx->dcl(scope,ARG); // no init! ! 34624: delete nx; ! 34625: Pname cln = a1->tp->is_cl_obj(); ! 34626: if (cln) { ! 34627: Pclass cl = Pclass(cln->tp); ! 34628: if (Ntmp==0 && cl->has_dtor()) Ntmp = cln; ! 34629: if (cl->has_itor()) n->n_xref = 1; ! 34630: } ! 34631: n->n_scope = FCT; ! 34632: n->assign(); ! 34633: a11 = n; ! 34634: a1 = new expr(ASSIGN,n,a1); ! 34635: a1->tp = n->tp; ! 34636: a1->simpl(); ! 34637: Pcall cc = new call(0,0); ! 34638: *cc = *this; ! 34639: base = CM; ! 34640: e1 = a1; ! 34641: e2 = cc; ! 34642: this = cc; ! 34643: } ! 34644: } ! 34645: ! 34646: int i = f->f_virtual; ! 34647: Pexpr ie = i?new ival(i):0; // index ! 34648: Pname cn = fn->n_table->t_name; ! 34649: if (fn ! 34650: && fn->n_initializer ! 34651: && cc->nof ! 34652: && cc->nof->n_oper==CTOR ! 34653: && Pfct(cc->nof->tp)->memof->c_abstract ! 34654: && strcmp(Pfct(cc->nof->tp)->memof->string, cn->string) == 0 ) { ! 34655: // permit x::x( x& xx ) { xx.pvf(); } ! 34656: Pexpr ee = e1->e1; ! 34657: while ( ee && ee->base != NAME ) ee = ee->e1; ! 34658: if ( ee && strcmp( ee->string, "this" )==0) ! 34659: error("call of pure virtualF%n inK%n",fn,cc->nof); ! 34660: } ! 34661: Pcall vc = vcall(a11,ie,f,Pclass(cn->tp),e2); ! 34662: *this = *vc; ! 34663: return; ! 34664: } ! 34665: ! 34666: Ptype tt = r->mem->tp; ! 34667: llp: ! 34668: //error('d',"llp %t",tt); ! 34669: switch (tt->base) { ! 34670: // default: // pointer to function: (n->ptr_mem)(args); do nothing ! 34671: case TYPE: ! 34672: tt = Pbase(tt)->b_name->tp; ! 34673: goto llp; ! 34674: case OVERLOAD: // n->fctmem(args); ! 34675: case FCT: ! 34676: if (fct_name==0) { ! 34677: // reconstitute fn destroyed to suppress "virtual" ! 34678: fct_name = fn = Pname(e1->n_initializer); ! 34679: f = Pfct(fn->tp); ! 34680: } ! 34681: ! 34682: if (e1->base == DOT) a1 = a1->address(); ! 34683: e2 = new expr(ELIST,a1,e2); ! 34684: e1 = r->mem; ! 34685: } ! 34686: } ! 34687: } ! 34688: ! 34689: if (e2) e2->simpl(); ! 34690: //error('d',"fn %n inl %d imes %d",fn,f->f_inline,f->f_imeasure); ! 34691: if (fn && f->f_inline && debug_opt==0) { ! 34692: imeasure += f->f_imeasure; ! 34693: Pclass cl = f->memof; ! 34694: if (cl && cl->c_body) cl->dcl_print(0); ! 34695: Ptable oscope = scope; ! 34696: Pexpr ee = f->expand(fn,scope,e2); ! 34697: scope = oscope; ! 34698: if (ee) *Pexpr(this) = *ee; ! 34699: } ! 34700: else if (fn && f->f_inline==0 && f->f_imeasure) { ! 34701: extern void uninline(Pname fn); ! 34702: uninline(fn); ! 34703: imeasure += 3; ! 34704: } ! 34705: else if (fn && debug_opt && f->f_inline==ITOR) { ! 34706: extern void expand_itor(Pclass); ! 34707: expand_itor(f->memof); ! 34708: } ! 34709: else ! 34710: imeasure += 3; ! 34711: } ! 34712: ! 34713: void uninline(Pname fn) ! 34714: // inline turned static ! 34715: { ! 34716: Pfct f = Pfct(fn->tp); ! 34717: //error('d',"uninline %n %d %d",fn,f->body,f->f_expr); ! 34718: ! 34719: if (warning_opt) { ! 34720: error('w',"%n too complex for inlining",fn); ! 34721: error('w',"out-of-line copy of %n created",fn); ! 34722: } ! 34723: f->f_imeasure = 0; // now it really is just static ! 34724: ! 34725: Pstmt s = f->body->s; ! 34726: // for (s = f->body->s; s; s=s->s_list) ! 34727: //error('d',"start %d %k",s->e,s->e->base); ! 34728: // s = f->body->s; ! 34729: while (s) { ! 34730: //error('d',"s %k %d %k",s->base,s->e,s->e->base); ! 34731: if (s->base == SM) { ! 34732: // turn comma expression into statement list ! 34733: Pexpr e = s->e; ! 34734: if (e) ! 34735: switch (e->base) { ! 34736: case CM: ! 34737: case G_CM: ! 34738: { Pstmt ss = new estmt(SM,no_where,e->e2,0); ! 34739: s->e = e->e1; ! 34740: ss->s_list = s->s_list; ! 34741: s->s_list = ss; ! 34742: delete e; ! 34743: continue; ! 34744: } ! 34745: } ! 34746: } ! 34747: s = s->s_list; ! 34748: } ! 34749: // for (s = f->body->s; s; s=s->s_list) ! 34750: //error('d',"echo %k %d %k",s->base,s->e,s->e->base); ! 34751: ! 34752: fn->dcl_print(0); ! 34753: } ! 34754: ! 34755: /* ! 34756: void ccheck(Pexpr e) ! 34757: ! 34758: Is there a conditional in this expression? (not perfect) ! 34759: ! 34760: { ! 34761: //error('d',"ccheck(e %k)",e,e?e->base,0); ! 34762: if (e) ! 34763: switch (e->base) { ! 34764: case QUEST: ! 34765: case ANDAND: ! 34766: case OROR: ! 34767: error('s',"E too complicated: uses%k and needs temporary ofCW destructor",e->base); ! 34768: break; ! 34769: case LT: ! 34770: case LE: ! 34771: case GT: ! 34772: case GE: ! 34773: case EQ: ! 34774: case NE: ! 34775: case ASSIGN: ! 34776: case ASPLUS: ! 34777: case ASMINUS: ! 34778: case G_CM: ! 34779: case CM: ! 34780: case PLUS: ! 34781: case MINUS: ! 34782: case MUL: ! 34783: case DIV: ! 34784: case OR: ! 34785: case ER: ! 34786: case AND: ! 34787: case G_CALL: ! 34788: case CALL: ! 34789: case ELIST: ! 34790: case DEREF: ! 34791: ccheck(e->e1); ! 34792: case NOT: ! 34793: case COMPL: ! 34794: case CAST: ! 34795: case ADDROF: ! 34796: case G_ADDROF: ! 34797: ccheck(e->e2); ! 34798: break; ! 34799: case ICALL: // check inlined arguments ! 34800: { Pin il = e->il; ! 34801: for (int i = 0; il->args[i].arg && i<il->i_slots; i++) ccheck(il->args[i].arg); ! 34802: } ! 34803: } ! 34804: } ! 34805: */ ! 34806: ! 34807: void temp_in_cond(Pexpr ee, Pstmt ss, Ptable tbl) ! 34808: /* ! 34809: insert destructor calls 'ss' into condition 'ee' ! 34810: ee => (Qnn = ee, dtors, Qnn) ! 34811: */ ! 34812: { ! 34813: //error('d',"temp_in_cond"); ! 34814: // ccheck(ee); ! 34815: while (ee->base==CM || ee->base==G_CM) ee = ee->e2; ! 34816: Ptype ct = ee->tp; ! 34817: Pname n = new name(make_name('Q')); // int Qnn; ! 34818: n->tp = ct; ! 34819: Pname tmp = n->dcl(tbl,ARG); ! 34820: delete n; ! 34821: tmp->n_scope = FCT; ! 34822: ! 34823: Pexpr v = new expr(0,0,0); ! 34824: *v = *ee; ! 34825: PERM(ct); ! 34826: v = new cast(ct,v); ! 34827: ! 34828: tmp->n_assigned_to = 1; ! 34829: Pexpr c = new expr(ASSIGN,tmp,v); // Qnn = ee ! 34830: c->tp = ct; ! 34831: ee->base = CM; ! 34832: ee->e1 = c; ! 34833: ! 34834: Pexpr ex = 0; // add dtors at end ! 34835: ! 34836: for (Pstmt sx = ss; sx; sx = sx->s_list) { ! 34837: if (ex) { ! 34838: ex = new expr(CM,ex,sx->e); ! 34839: ex->tp = sx->e->tp; ! 34840: } ! 34841: else ! 34842: ex = sx->e; ! 34843: } ! 34844: ee->e2 = new expr(CM,ex,tmp); // add Qnn at end ! 34845: ee->e2->tp = ct; ! 34846: } ! 34847: ! 34848: bit not_safe(Pexpr e) ! 34849: { ! 34850: ! 34851: switch (e->base) { ! 34852: default: ! 34853: return 1; ! 34854: /* ! 34855: case CALL: ! 34856: case G_CALL: ! 34857: case DOT: ! 34858: case REF: ! 34859: case ANAME: ! 34860: return 1; ! 34861: */ ! 34862: case NAME: ! 34863: // if the name is automatic and has a destructor it is not safe ! 34864: // to destroy it before returning an expression depending on it ! 34865: { Pname n = Pname(e); ! 34866: if (n->n_table!=gtbl && n->n_table->t_name==0) { ! 34867: Pname cn = n->tp->is_cl_obj(); ! 34868: if (cn && Pclass(cn->tp)->has_dtor()) return 1; ! 34869: } ! 34870: } ! 34871: case IVAL: ! 34872: case ICON: ! 34873: case CCON: ! 34874: case FCON: ! 34875: case STRING: ! 34876: return 0; ! 34877: case NOT: ! 34878: case COMPL: ! 34879: case ADDROF: ! 34880: case G_ADDROF: ! 34881: return not_safe(e->e2); ! 34882: case DEREF: ! 34883: // return not_safe(e->e1) || e->e2?not_safe(e->e2):0; ! 34884: { int i = not_safe(e->e1); ! 34885: if (i) return i; ! 34886: if (e->e2) return not_safe(e->e2); ! 34887: return 0; ! 34888: } ! 34889: case CM: ! 34890: case PLUS: ! 34891: case MINUS: ! 34892: case MUL: ! 34893: case DIV: ! 34894: case MOD: ! 34895: case ASSIGN: ! 34896: case ASPLUS: ! 34897: case ASMINUS: ! 34898: case ASMUL: ! 34899: case ASDIV: ! 34900: case OR: ! 34901: case AND: ! 34902: case OROR: ! 34903: case ANDAND: ! 34904: case LT: ! 34905: case LE: ! 34906: case GT: ! 34907: case GE: ! 34908: case EQ: ! 34909: case NE: ! 34910: return not_safe(e->e1) || not_safe(e->e2); ! 34911: case QUEST: ! 34912: return not_safe(e->cond) || not_safe(e->e1) || not_safe(e->e2); ! 34913: } ! 34914: } ! 34915: ! 34916: ! 34917: Pexpr curr_expr; /* to protect against an inline being expanded twice ! 34918: in a simple expression keep track of expressions ! 34919: being simplified ! 34920: */ ! 34921: Pstmt stmt::simpl() ! 34922: /* ! 34923: return a pointer to the last statement in the list, or 0 ! 34924: */ ! 34925: { ! 34926: if (this == 0) error('i',"0->S::simpl()"); ! 34927: DB( if(Sdebug>=1){ ! 34928: error('d',"%d->stmt::simpl(): %k",this,base); ! 34929: if(Sdebug>=2) display_stmt(this); ! 34930: }); ! 34931: //Pstmt ostmt = Cstmt; ! 34932: //if ( where.line ) Cstmt = this; ! 34933: ! 34934: stmtno++; ! 34935: curr_expr = e; ! 34936: //error('d',"stmt::simpl %k s_list %d",base,s_list); ! 34937: ! 34938: switch (base) { ! 34939: default: ! 34940: error('i',"S::simpl(%k)",base); ! 34941: ! 34942: case ASM: ! 34943: break; ! 34944: ! 34945: case BREAK: ! 34946: if (break_del_list) { // break => { _dtor()s; break; } ! 34947: Pstmt bs = new stmt(base,where,0); ! 34948: Pstmt dl = break_del_list->copy(); ! 34949: base = BLOCK; ! 34950: s = new pair(where,dl,bs); ! 34951: } ! 34952: break; ! 34953: ! 34954: case CONTINUE: ! 34955: if (continue_del_list) { // continue => { _dtor()s; continue; } ! 34956: Pstmt bs = new stmt(base,where,0); ! 34957: Pstmt dl = continue_del_list->copy(); ! 34958: base = BLOCK; ! 34959: s = new pair(where,dl,bs); ! 34960: } ! 34961: break; ! 34962: ! 34963: case DEFAULT: ! 34964: s->simpl(); ! 34965: break; ! 34966: ! 34967: case SM: ! 34968: if (e) { ! 34969: if (e->base == DEREF) e = e->e1; ! 34970: e->simpl(); ! 34971: if (e->base == DEREF) e = e->e1; ! 34972: } ! 34973: break; ! 34974: ! 34975: case RETURN: ! 34976: { /* return x; ! 34977: => ! 34978: { dtor()s; return x; } ! 34979: OR (returning an X where X(X&) is defined) => ! 34980: { ctor(_result,x); _dtor()s; return; } ! 34981: OR (where x needs temporaries) ! 34982: OR (where x might involve an object to be destroyed) => ! 34983: { _result = x; _dtor()s; return _result; } ! 34984: return; => ! 34985: { _dtor()s; return; } ! 34986: OR (in constructors) => ! 34987: { _dtor()s; return _this; } ! 34988: */ ! 34989: Pstmt sx = this; ! 34990: Pexpr ex = e; ! 34991: ! 34992: no_of_returns++; ! 34993: ! 34994: Pstmt dl = (del_list) ? del_list->copy() : 0; ! 34995: Pfct f = Pfct(curr_fct->tp); ! 34996: ! 34997: if (e == 0) e = dummy; ! 34998: if (e==dummy && curr_fct->n_oper==CTOR) e = f->f_this; ! 34999: ! 35000: ! 35001: // need to generate a temporary for mptr return ! 35002: Pexpr tt = e; ! 35003: while ( tt->base == CAST ) ! 35004: tt = tt->e1; ! 35005: if ( tt->base == ILIST ) ! 35006: e = tt; ! 35007: ! 35008: if (e->base == ILIST) { ! 35009: extern Pbase mptr_type; ! 35010: extern Ptype Pvptr_type; ! 35011: Pexpr mptr_assign(Pexpr, Pexpr); ! 35012: // memptr constant ! 35013: // return({1,2,f}) ==> memptr t; return((t={1,2,f},&t)) ! 35014: ! 35015: Ptable ftbl = Pfct(curr_fct->tp)->body->memtbl; ! 35016: Pname temp = make_tmp('A',mptr_type,ftbl); ! 35017: ! 35018: // placed in mptr_assign() ! 35019: // temp->use(); // necessary for inlines to force declaration ! 35020: ! 35021: e = mptr_assign(temp,e); ! 35022: e = new expr(G_CM,e,temp); ! 35023: e->tp = mptr_type; ! 35024: } ! 35025: ! 35026: if (f->f_result) { // ctor(_result,x); dtors; return; ! 35027: if (e->base == G_CM) e = replace_temp(e,f->f_result); ! 35028: e->simpl(); ! 35029: Pstmt cs = new estmt(SM,where,e,0); ! 35030: if (dl) cs = new pair(where,cs,dl); ! 35031: base = PAIR; ! 35032: s = cs; ! 35033: s2 = new estmt(RETURN,where,0,0); ! 35034: //#ifdef RETBUG ! 35035: // s2->empty = 1; // fudge to bypass C bug (see print.c) ! 35036: // s2->ret_tp = ret_tp; ! 35037: //#endif ! 35038: } ! 35039: else { // dtors; return e; ! 35040: e->simpl(); ! 35041: if (dl) { ! 35042: if (e!=dummy && not_safe(e)) { ! 35043: // { _result = x; _dtor()s; return _result; } ! 35044: Ptable ftbl = Pfct(curr_fct->tp)->body->memtbl; ! 35045: ! 35046: Pname r = ftbl->look("_result",0); ! 35047: if (r == 0) { ! 35048: r = new name("_result"); ! 35049: r->tp = ret_tp; ! 35050: Pname rn = r->dcl(ftbl,ARG); ! 35051: rn->n_scope = FCT; ! 35052: rn->where = no_where; ! 35053: rn->assign(); ! 35054: delete r; ! 35055: r = rn; ! 35056: } ! 35057: Pexpr as = new expr(ASSIGN,r,e); ! 35058: as->tp = ret_tp; // wrong if = overloaded, but then X(X&) ought to have been used ! 35059: Pstmt cs = new estmt(SM,where,as,0); ! 35060: cs = new pair(where,cs,dl); ! 35061: base = PAIR; ! 35062: s = cs; ! 35063: s2 = new estmt(RETURN,where,r,0); ! 35064: // s2->ret_tp = ret_tp; ! 35065: } ! 35066: else { // { _dtor()s; return x; } ! 35067: base = PAIR; ! 35068: s = dl; ! 35069: s2 = new estmt(RETURN,where,e,0); ! 35070: } ! 35071: s2->ret_tp = ret_tp; ! 35072: } ! 35073: } ! 35074: ! 35075: // if (sx->memtbl) { ! 35076: // int i; ! 35077: // for (Pname n=sx->memtbl->get_mem(i=1); n; n=sx->memtbl->get_mem(++i)) { ! 35078: // Pname cn = n->tp->is_cl_obj(); ! 35079: // if (cn && Pclass(cn->tp)->has_dtor()) { ! 35080: // ccheck(ex); ! 35081: // break; ! 35082: // } ! 35083: // } ! 35084: // } ! 35085: break; ! 35086: } ! 35087: ! 35088: case WHILE: ! 35089: case DO: ! 35090: e->simpl(); ! 35091: { Pstmt obl = break_del_list; ! 35092: Pstmt ocl = continue_del_list; ! 35093: break_del_list = 0; ! 35094: continue_del_list = 0; ! 35095: s->simpl(); ! 35096: break_del_list = obl; ! 35097: continue_del_list = ocl; ! 35098: } ! 35099: break; ! 35100: ! 35101: case SWITCH: ! 35102: e->simpl(); ! 35103: { Pstmt obl = break_del_list; ! 35104: break_del_list = 0; ! 35105: s->simpl(); ! 35106: break_del_list = obl; ! 35107: } ! 35108: switch (s->base) { ! 35109: case DEFAULT: ! 35110: case LABEL: ! 35111: case CASE: ! 35112: break; ! 35113: case BLOCK: ! 35114: if (s->s) ! 35115: switch (s->s->base) { ! 35116: case BREAK: // to cope with #define Case break; case ! 35117: case CASE: ! 35118: case LABEL: ! 35119: case DEFAULT: ! 35120: break; ! 35121: default: ! 35122: goto df; ! 35123: } ! 35124: break; ! 35125: default: ! 35126: df: ! 35127: error(&s->where,"S orIdE not reached: (case label missing?)"); ! 35128: } ! 35129: break; ! 35130: ! 35131: case CASE: ! 35132: e->simpl(); ! 35133: s->simpl(); ! 35134: break; ! 35135: ! 35136: case LABEL: ! 35137: if (del_list) error('s',"label in blockW destructors"); ! 35138: s->simpl(); ! 35139: break; ! 35140: ! 35141: case GOTO: ! 35142: /* If the goto is going to a different (effective) scope, ! 35143: then it is necessary to activate all relevant destructors ! 35144: on the way out of nested scopes, and issue errors if there ! 35145: are any constructors on the way into the target. ! 35146: ! 35147: Only bother if the goto and label have different effective ! 35148: scopes. (If mem table of goto == mem table of label, then ! 35149: they're in the same scope for all practical purposes. ! 35150: */ ! 35151: { ! 35152: Pname n = scope->look( d->string, LABEL ); ! 35153: if (n == 0) error('i',&where,"label%n missing",d); ! 35154: if(n->n_realscope!=scope && n->n_assigned_to) { ! 35155: ! 35156: /* Find the root of the smallest subtree containing ! 35157: the path of the goto. This algorithm is quadratic ! 35158: only if the goto is to an inner or unrelated scope. ! 35159: */ ! 35160: ! 35161: Ptable r = 0; ! 35162: ! 35163: for(Ptable q=n->n_realscope; q!=gtbl; q=q->next) { ! 35164: for( Ptable p = scope; p != gtbl; p = p->next ) { ! 35165: if( p==q ) { ! 35166: r = p; // found root of subtree! ! 35167: goto xyzzy; ! 35168: } ! 35169: } ! 35170: } ! 35171: ! 35172: xyzzy: if( r==0 ) error( 'i',&where,"finding root of subtree" ); ! 35173: ! 35174: /* At this point, r = root of subtree, n->n_realscope ! 35175: * = mem table of label, and scope = mem table of goto. */ ! 35176: ! 35177: /* Climb the tree from the label mem table to the table ! 35178: * preceding the root of the subtree, looking for ! 35179: * initializers and ctors. If the mem table "belongs" ! 35180: * to an unsimplified block(s), the n_initializer field ! 35181: * indicates presence of initializer, otherwise initializer ! 35182: * information is recorded in the init_stat field of ! 35183: * mem table. */ ! 35184: ! 35185: for( Ptable p=n->n_realscope; p!=r; p=p->next ) ! 35186: if( p->init_stat == 2 ) { ! 35187: error(&where,"goto%n pastDWIr",d); ! 35188: goto plugh; /* avoid multiple error msgs */ ! 35189: } ! 35190: else if( p->init_stat == 0 ) { ! 35191: int i; ! 35192: for(Pname nn=p->get_mem(i=1);nn;nn=p->get_mem(++i)) ! 35193: if(nn->n_initializer||nn->n_evaluated){ ! 35194: error(&nn->where,"goto%n pastId%n",d,nn); ! 35195: goto plugh; ! 35196: } ! 35197: } ! 35198: plugh: ! 35199: ! 35200: /* Proceed in a similar manner from the point of the goto, ! 35201: * generating the code to activate dtors before the goto. */ ! 35202: /* There is a bug in this code. If there are class objects ! 35203: * of the same name and type in (of course) different mem ! 35204: * tables on the path to the root of the subtree from the ! 35205: * goto, then the innermost object's dtor will be activated ! 35206: * more than once. */ ! 35207: ! 35208: { ! 35209: Pstmt dd = 0, ddt = 0; ! 35210: ! 35211: for( Ptable p=scope; p!=r; p=p->next ) { ! 35212: int i; ! 35213: for(Pname n=p->get_mem(i=1);n;n=p->get_mem(++i)) { ! 35214: Pname cln; ! 35215: if (n->tp == 0) continue; /* label */ ! 35216: ! 35217: if ( cln=n->tp->is_cl_obj() ) { ! 35218: Pclass cl = (Pclass)cln->tp; ! 35219: Pname d = cl->has_dtor(); ! 35220: ! 35221: if (d) { /* n->cl::~cl(0); */ ! 35222: Pexpr dl = call_dtor(n,d,0,DOT,one); ! 35223: Pstmt dls = new estmt(SM,n->where,dl,0); ! 35224: if (dd) ! 35225: ddt->s_list = dls; ! 35226: else ! 35227: dd = dls; ! 35228: ddt = dls; ! 35229: } ! 35230: ! 35231: } ! 35232: else if (cl_obj_vec) { ! 35233: Pclass cl = (Pclass)cl_obj_vec->tp; ! 35234: // Pname c = cl->has_ictor(); ! 35235: Pname d = cl->has_dtor(); ! 35236: ! 35237: if (d) { // __vec_delete(vec,noe,sz,dtor,0); ! 35238: Pfct f = Pfct(d->tp); ! 35239: int i = 0; ! 35240: for (Pname nn = f->f_args->n_list; ! 35241: nn && nn->n_list; nn=nn->n_list) i++; ! 35242: Pexpr a = cdvec(vec_del_fct,n,cl,d,0,new ival(i)); ! 35243: Pstmt dls = new estmt(SM,n->where,a,0); ! 35244: if (dd) ! 35245: ddt->s_list = dls; ! 35246: else ! 35247: dd = dls; ! 35248: ddt = dls; ! 35249: } ! 35250: } ! 35251: } /* end mem table scan */ ! 35252: } /* end dtor loop */ ! 35253: ! 35254: /* "activate" the list of dtors obtained. */ ! 35255: ! 35256: if( dd ) { ! 35257: dd->simpl(); ! 35258: Pstmt bs = new stmt( base, where, 0 ); ! 35259: *bs = *this; ! 35260: base = PAIR; ! 35261: s = dd; ! 35262: s2 = bs; ! 35263: } ! 35264: } ! 35265: } /* end special case for non-local goto */ ! 35266: } ! 35267: break; ! 35268: ! 35269: case IF: ! 35270: e->simpl(); ! 35271: s->simpl(); ! 35272: if (else_stmt) else_stmt->simpl(); ! 35273: break; ! 35274: ! 35275: case FOR: // "for (s;e;e2) s2; => "s; for(;e,e2) s2" ! 35276: if (for_init) for_init->simpl(); ! 35277: if (e) { ! 35278: curr_expr = e; ! 35279: e->simpl(); ! 35280: } ! 35281: if (e2) { ! 35282: curr_expr = e2; ! 35283: e2->simpl(); ! 35284: if (e2->base==ICALL) ! 35285: if (e2->e1 == 0) error('s',"cannot expand inline void%n called in forE", e2->il->fct_name); ! 35286: } ! 35287: { Pstmt obl = break_del_list; ! 35288: Pstmt ocl = continue_del_list; ! 35289: break_del_list = 0; ! 35290: continue_del_list = 0; ! 35291: s->simpl(); ! 35292: break_del_list = obl; ! 35293: continue_del_list = ocl; ! 35294: } ! 35295: break; ! 35296: ! 35297: case BLOCK: ! 35298: Pblock(this)->simpl(); ! 35299: break; ! 35300: ! 35301: case PAIR: ! 35302: break; ! 35303: } ! 35304: ! 35305: /*if (s) s->simpl();*/ ! 35306: //error('d',"base %k memtbl %d",base,memtbl); ! 35307: if (base!=BLOCK && memtbl) { ! 35308: Pstmt t1 = (s_list) ? s_list->simpl() : 0; ! 35309: Pstmt tpx = t1 ? t1 : this; ! 35310: ! 35311: Pstmt ss = 0; ! 35312: Pname cln; // used for warnings ! 35313: int i; ! 35314: Pname tn = memtbl->get_mem(i=1); ! 35315: for (; tn; tn=memtbl->get_mem(++i)) { ! 35316: if (cln = tn->tp->is_cl_obj()) { ! 35317: Pname d = Pclass(cln->tp)->has_dtor(); ! 35318: if (d) { /* n->cl::~cl(0); */ ! 35319: Pexpr dl = call_dtor(tn,d,0,DOT,one); ! 35320: Pstmt dls = new estmt(SM,tn->where,dl,0); ! 35321: dls->s_list = ss; ! 35322: ss = dls; ! 35323: } ! 35324: } ! 35325: } ! 35326: ! 35327: if (ss) { ! 35328: Pstmt t2 = ss->simpl(); ! 35329: ! 35330: switch (base) { ! 35331: case IF: ! 35332: case WHILE: ! 35333: case DO: ! 35334: case SWITCH: ! 35335: temp_in_cond(e,ss,memtbl); ! 35336: break; ! 35337: ! 35338: case PAIR: // can hide a return ! 35339: { Pstmt ts = s2; ! 35340: while (ts->base==PAIR) ts = ts->s2; ! 35341: if (ts->base == RETURN) { // sordid ! 35342: this = ts; ! 35343: goto retu; ! 35344: } ! 35345: goto def; ! 35346: } ! 35347: case RETURN: ! 35348: retu: ! 35349: { ! 35350: if (e == 0) { ! 35351: // return; dtors; => dtors; return; ! 35352: Pstmt rs = new estmt(RETURN,where,0,0); ! 35353: //rs->empty = empty; // BSD fudge ! 35354: rs->ret_tp = ret_tp; ! 35355: base = PAIR; ! 35356: s = ss; ! 35357: s2 = rs; ! 35358: //Cstmt = ostmt; ! 35359: return t1 ? t1 : rs; ! 35360: } ! 35361: ! 35362: Pname cln = e->tp->is_cl_obj(); ! 35363: if (cln==0 ! 35364: || Pclass(cln->tp)->has_oper(ASSIGN)==0) { ! 35365: // ... return e; dtors; => ! 35366: // ... X r; ... r = e; dtors; return r; ! 35367: Pname rv = new name("_rresult"); // NOT "_result" ! 35368: rv->tp = ret_tp /* e->tp */; ! 35369: if (memtbl == 0) memtbl = new table(4,0,0); ! 35370: Pname n = rv->dcl(memtbl,ARG); ! 35371: n->where = no_where; ! 35372: n->n_scope = FCT; ! 35373: n->n_assigned_to = 1; ! 35374: delete rv; ! 35375: Pstmt rs = new estmt(RETURN,where,n,0); ! 35376: rs->ret_tp = ret_tp; ! 35377: base = SM; ! 35378: e = new expr(ASSIGN,n,e); ! 35379: e->tp = n->tp; ! 35380: Pstmt ps = new pair(where,ss,rs); ! 35381: ps->s_list = s_list; ! 35382: s_list = ps; ! 35383: //Cstmt = ostmt; ! 35384: return t1 ? t1 : rs; ! 35385: } ! 35386: } ! 35387: ! 35388: case FOR: // don't know which expression the temp comes from ! 35389: error('s',&where,"E in %kS needs temporary ofC%nW destructor",base,cln); ! 35390: break; ! 35391: ! 35392: case SM: // place dtors after all "converted" DCLs ! 35393: if (t1) { ! 35394: // ccheck(e); ! 35395: for (Pstmt ttt, tt=this; ! 35396: (ttt=tt->s_list) && ttt->base==SM; ! 35397: tt = ttt) ; ! 35398: t2->s_list = ttt; ! 35399: tt->s_list = ss; ! 35400: //Cstmt = ostmt; ! 35401: return t1!=tt ? t1 : t2; ! 35402: } ! 35403: default: ! 35404: def: ! 35405: // if (e) ccheck(e); ! 35406: if (t1) { // t1 == tail of statment list ! 35407: t2->s_list = s_list; ! 35408: s_list = ss; ! 35409: //Cstmt = ostmt; ! 35410: return t1; ! 35411: } ! 35412: s_list = ss; ! 35413: //Cstmt = ostmt; ! 35414: return t2; ! 35415: } ! 35416: } ! 35417: //Cstmt = ostmt; ! 35418: return (t1) ? t1 : this; ! 35419: } ! 35420: ! 35421: //Cstmt = ostmt; ! 35422: return (s_list) ? s_list->simpl() : this; ! 35423: } ! 35424: ! 35425: Pstmt stmt::copy() ! 35426: // now handles dtors in the expression of an IF stmt ! 35427: // not general! ! 35428: { ! 35429: Pstmt ns = new stmt(0,curloc,0); ! 35430: ! 35431: *ns = *this; ! 35432: if (s) ns->s = s->copy(); ! 35433: if (s_list) ns->s_list = s_list->copy(); ! 35434: ! 35435: switch (base) { ! 35436: case PAIR: ! 35437: ns->s2 = s2->copy(); ! 35438: break; ! 35439: } ! 35440: ! 35441: return ns; ! 35442: } ! 35443: ! 35444: Pname overFound = 0; ! 35445: ! 35446: static Pexpr ! 35447: mk_new_with_args( Pexpr pe, Ptype tt, Pclass cl, Pexpr vec = 0 ) ! 35448: { // allocate using operator new(sizeof(cl),args1) ! 35449: Pexpr p; ! 35450: Pexpr args = pe->e2; ! 35451: ! 35452: // Pexpr ce = new texpr(SIZEOF,tt,0); ! 35453: Pexpr ce; ! 35454: if (vec) ! 35455: ce = vec; ! 35456: else ce = new texpr(SIZEOF,tt,0); ! 35457: ! 35458: (void) tt->tsizeof(); ! 35459: ce->tp = size_t_type; ! 35460: args = new expr(ELIST,ce,args); ! 35461: char* s = oper_name(NEW); ! 35462: Pname n = new name(s); ! 35463: if (pe->base == GNEW) // ::new ! 35464: p = gtbl->look(s,0); ! 35465: else ! 35466: p = find_name(n,cl,scope,CALL,curr_fct); ! 35467: p = new call(p,args); ! 35468: overFound=0; // set in call_fct ! 35469: (void) p->call_fct(cl->memtbl); ! 35470: if (overFound && overFound->n_scope != EXTERN) ! 35471: check_visibility(overFound,0,cl,cc->ftbl,cc->nof); ! 35472: overFound=0; ! 35473: return p; ! 35474: } ! 35475: ! 35476: void expr::simpl_new() ! 35477: /* ! 35478: change NEW or GNEW node to CALL node ! 35479: */ ! 35480: { ! 35481: Pname cln; ! 35482: Pname ctor; ! 35483: int sz = 1; ! 35484: // int esz; ! 35485: Pexpr var_expr = 0; ! 35486: Pexpr const_expr = 0; ! 35487: Ptype tt = tp2; ! 35488: Pexpr arg; ! 35489: Pexpr szof; ! 35490: Pname nf; ! 35491: Pexpr init = e1; ! 35492: ! 35493: if (init && init->base) init = 0; // only non-ctor init ! 35494: // error('d',"simpl_new %k e1 %k e2 %k init %k",base, e1?e1->base:0,e2?e2->base:0,init?init->base:0); ! 35495: ! 35496: if ((cln=tt->is_cl_obj()) && init == 0) { ! 35497: Pclass cl = Pclass(cln->tp); ! 35498: Pexpr p; ! 35499: ctor=cl->has_ctor(); ! 35500: // error('d',"cl %t ctor %n",cl, ctor); ! 35501: if (e2 // placement ! 35502: || ctor==0 // no constructor ! 35503: || ctor->n_table!=cl->memtbl // inherited constructor??? ! 35504: || (base==GNEW && cl->has_oper(NEW)) ) ! 35505: p = mk_new_with_args( this, tt, cl ); // new(sizeof(cl),args1) ! 35506: else { ! 35507: p = zero; // 0->ctor(args) ! 35508: // check visibility anyway... ! 35509: (void)mk_new_with_args(this,tt,cl); ! 35510: } ! 35511: ! 35512: if (ctor) { ! 35513: Pexpr c = e1; // ctor call generated in expr::typ ! 35514: Ptype ttt = tp; ! 35515: c->e1->e1 = p; // p->ctor ! 35516: c->simpl(); ! 35517: *this = *c; ! 35518: tp = ttt; ! 35519: delete c; ! 35520: } ! 35521: else { // (tp)new(args) ! 35522: base = CAST; ! 35523: tp2 = tp; ! 35524: e1 = p; ! 35525: e2 = 0; ! 35526: simpl(); ! 35527: } ! 35528: return; ! 35529: } else if ( cln ) { ! 35530: Pclass cl = Pclass(cln->tp); ! 35531: // check visibility anyway... ! 35532: (void)mk_new_with_args(this,tt,cl); ! 35533: } ! 35534: ! 35535: Pclass covn = 0; ! 35536: if (cl_obj_vec) { ! 35537: covn = Pclass(cl_obj_vec->tp); ! 35538: ctor = covn->has_ictor(); ! 35539: if (ctor == 0) { ! 35540: if (covn->has_ctor()) error("new %s[], no defaultK",covn->string); ! 35541: cl_obj_vec = 0; ! 35542: } ! 35543: } ! 35544: ! 35545: xxx: ! 35546: //error('d',"xxx %t",tt); ! 35547: switch (tt->base) { ! 35548: case TYPE: ! 35549: tt = Pbase(tt)->b_name->tp; ! 35550: goto xxx; ! 35551: ! 35552: default: ! 35553: (void) tt->tsizeof(); ! 35554: szof = new texpr(SIZEOF,tt,0); ! 35555: szof->tp = uint_type; ! 35556: break; ! 35557: ! 35558: case VEC: ! 35559: { Pvec v = Pvec(tt); ! 35560: //error('d',"v %d %d",v->size,v->dim); ! 35561: if (v->size) ! 35562: sz *= v->size; ! 35563: else if (v->dim) ! 35564: var_expr = v->dim; ! 35565: else ! 35566: sz = 0; ! 35567: tt = v->typ; ! 35568: goto xxx; ! 35569: } ! 35570: } ! 35571: ! 35572: if (cl_obj_vec) { // _vec_new(0,no_of_elements,element_size,ctor) ! 35573: const_expr = new ival(sz); ! 35574: Pexpr noe = (var_expr) ? (sz!=1) ? new expr(MUL,const_expr,var_expr) : var_expr : const_expr; ! 35575: const_expr = szof; ! 35576: const_expr->tp = uint_type; ! 35577: base = CALL; ! 35578: arg = new expr(ELIST,ctor,0); ! 35579: /*ctor->take_addr();*/ ! 35580: ctor->lval(ADDROF); ! 35581: Pexpr sub=0; ! 35582: if (e2 && e2->e1 && ! 35583: e2->e1->tp && ! 35584: e2->e1->tp->base != PTR ) ! 35585: { // new(size_t, args) ! 35586: Pexpr vec_sz = new expr(MUL, noe, const_expr); ! 35587: sub = mk_new_with_args( this, tt, covn, vec_sz ); ! 35588: } ! 35589: arg = new expr(ELIST,const_expr,arg); ! 35590: arg = new expr(ELIST,noe,arg); ! 35591: // arg = new expr(ELIST,e2?e2:zero,arg); // may be preallocated ! 35592: arg = new expr(ELIST,e2?(sub?sub:e2):zero,arg); // may be preallocated ! 35593: base = CAST; ! 35594: tp2 = tp; ! 35595: e1 = new expr(G_CALL,vec_new_fct,arg); ! 35596: e1->fct_name = vec_new_fct; ! 35597: e1->tp = Pfct(vec_new_fct->tp)->returns; ! 35598: simpl(); ! 35599: return; ! 35600: } ! 35601: ! 35602: /* call _new(element_size*no_of_elements) */ ! 35603: //error('d',"sz %d var %d",sz,var_expr); ! 35604: if (sz == 1) ! 35605: arg = (var_expr) ? new expr(MUL,szof,var_expr) : szof; ! 35606: else { ! 35607: const_expr = new ival(sz); ! 35608: const_expr->tp = uint_type; ! 35609: const_expr = new expr(MUL,const_expr,szof); ! 35610: const_expr->tp = uint_type; ! 35611: arg = (var_expr) ? new expr(MUL,const_expr,var_expr) : const_expr; ! 35612: } ! 35613: ! 35614: arg->tp = uint_type; ! 35615: base = CAST; ! 35616: tp2 = tp; ! 35617: arg = new expr(ELIST,arg,e2); ! 35618: nf = gtbl->look(oper_name(NEW),0); // always global, ! 35619: // all class object handled above ! 35620: e1 = new expr(G_CALL,nf,arg); ! 35621: (void) e1->call_fct(gtbl); ! 35622: simpl(); ! 35623: ! 35624: if (init) { // alloc(sz) => (p=alloc(sz),*p=init,p); ! 35625: Pexpr p = init->e1; ! 35626: Pexpr ee = new expr(0,0,0); ! 35627: *ee = *this; ! 35628: ee = new expr(ASSIGN,p,ee); // ee: p = alloc(sz); ! 35629: init->base = ASSIGN; ! 35630: init->e1 = p->contents(); // init: *p = init_val ! 35631: ee = new expr(CM,ee,init); ! 35632: ee->simpl(); ! 35633: base = CM; ! 35634: e1 = ee; ! 35635: e2 = p; ! 35636: } ! 35637: } ! 35638: ! 35639: void expr::simpl_delete() ! 35640: /* ! 35641: delete p => _delete(p); ! 35642: or cl::~cl(p,1); ! 35643: delete[s]p => _delete(p); ! 35644: or vec_del_fct(p,vec_sz,elem_sz,~cl,1); ! 35645: */ ! 35646: { ! 35647: for (Ptype tt = e1->tp; tt->base==TYPE; tt=Pbase(tt)->b_name->tp); ! 35648: tt = Pptr(tt)->typ; ! 35649: //error('d',"simpl_delete() %t",e1->tp); ! 35650: Pname cln = tt->is_cl_obj(); ! 35651: Pname n; ! 35652: Pclass cl; ! 35653: ! 35654: if (cln) { ! 35655: cl = Pclass(cln->tp); ! 35656: if ((cl->defined&DEFINED) == 0) error('w',"delete%t (%t not defined)",cl,cl); ! 35657: } ! 35658: else ! 35659: cl = 0; ! 35660: ! 35661: if (cl && (n=cl->has_dtor())) { // ~cl() might be virtual ! 35662: //xxx check for private/protected op delete ! 35663: { ! 35664: Pexpr ee = new expr(ELIST,e1,0); ! 35665: char* s = oper_name(DELETE); ! 35666: Pname n; ! 35667: //error('d',"%s( %k )",s,e1->base); ! 35668: if (base!=GDELETE) { ! 35669: n = new name(s); ! 35670: n = (Pname)find_name(n,cl,scope,CALL,curr_fct); ! 35671: //error('d',"found%n %t",n,n->tp); ! 35672: if (n->tp->base==OVERLOAD ! 35673: || Pfct(n->tp)->nargs==2) { ! 35674: Pexpr ss = new texpr(SIZEOF,cl,0); ! 35675: ss->tp = size_t_type; ! 35676: ee->e2 = new expr(ELIST,ss,0); ! 35677: } ! 35678: } ! 35679: else ! 35680: n = gtbl->look(s,0); ! 35681: //error('d',"found%n %t",n,n->tp); ! 35682: ee = new call(n,ee); ! 35683: ee->base = G_CALL; ! 35684: //error('d',"delete..."); display_expr(ee); ! 35685: // following commented out to avoid typ::checking problems ! 35686: //overFound=0; // set in call_fct ! 35687: //(void) ee->call_fct(cl->memtbl); ! 35688: //if (overFound && overFound->n_scope != EXTERN) ! 35689: //check_visibility(overFound,0,cl,cc->ftbl,cc->nof); ! 35690: //overFound=0; ! 35691: } ! 35692: ! 35693: //if ( base!=GDELETE ) (void) cl->has_oper(DELETE); ! 35694: ! 35695: if(base==GDELETE && e2==0 || Pfct(n->tp)->f_virtual) { // may need temp ! 35696: nin=1; ! 35697: int needtemp = e1->not_simple(); ! 35698: nin=0; ! 35699: if(needtemp) { ! 35700: // convert: delete [e2] e1 ! 35701: // to: (T=e1), delete [e2] T ! 35702: // where T is a new temporary. ! 35703: Pname tnx = new name(make_name('K')); ! 35704: tnx->tp = e1->tp; ! 35705: Pname tn = tnx->dcl(scope,FCT); ! 35706: delete tnx; ! 35707: tn->assign(); ! 35708: e1 = new expr(ASSIGN,tn,e1); ! 35709: e2 = new expr(base,tn,e2); ! 35710: base=CM; ! 35711: ! 35712: simpl(); ! 35713: return; ! 35714: } ! 35715: } ! 35716: Pexpr r = e1; ! 35717: ! 35718: // handle delete p, where p has a private destructor ! 35719: if (n->n_scope != PUBLIC) check_visibility(n,0,cl,cc->ftbl,cc->nof); ! 35720: //error('d',"e2 %d %k",e2,base); ! 35721: if (e2 == 0) { // e1->cl::~cl(1) ! 35722: Pexpr ee = call_dtor(r,n,base==GDELETE?0:one,REF,one); ! 35723: if (Pfct(n->tp)->f_virtual) { ! 35724: if (ansi_opt) { // q?void:int would be an error ! 35725: ee = new expr(G_CM,ee,zero); ! 35726: ee->tp = zero_type; ! 35727: } ! 35728: ee = new expr(QUEST,ee,zero); ! 35729: ee->tp = ee->e1->tp; ! 35730: ee->cond = r; ! 35731: } ! 35732: if (base == GDELETE) { ! 35733: char* s = oper_name(DELETE); ! 35734: Pexpr p = gtbl->look(s,0); ! 35735: e2 = new call(p,new expr(ELIST,e1,0)); ! 35736: base = CM; ! 35737: e1 = ee; ! 35738: } ! 35739: else { ! 35740: *this = *ee; ! 35741: delete ee; ! 35742: } ! 35743: simpl(); ! 35744: return; ! 35745: } ! 35746: else { // del_cl_vec(e1,e2,elem_size,~cl,1); ! 35747: Pexpr sz = new texpr(SIZEOF,tt,0); ! 35748: (void)tt->tsizeof(); ! 35749: Pfct f = Pfct(n->tp); ! 35750: int i = 0; ! 35751: Pname nn = f->f_args->n_list; ! 35752: for (; nn && nn->n_list; nn=nn->n_list) i++; ! 35753: //error('d',"n %n i %d",n,i); ! 35754: Pexpr arg = new ival(i); ! 35755: sz->tp = uint_type; ! 35756: // Pexpr arg = one; ! 35757: arg = new expr(ELIST,one,arg); ! 35758: if (Pfct(n->tp)->f_virtual) { ! 35759: Pexpr a = new ref(REF,e1,n); ! 35760: a = a->address(); ! 35761: a = new mdot( "f", a ); ! 35762: a->i1 = 9; ! 35763: arg = new expr(ELIST,a,arg); ! 35764: } ! 35765: else { ! 35766: arg = new expr(ELIST,n,arg); ! 35767: n->lval(ADDROF); // n->take_addr(); ! 35768: } ! 35769: ! 35770: arg = new expr(ELIST,sz,arg); ! 35771: if (e2->base==DUMMY) { ! 35772: e2 = new ival(-1); // handle `delete[]p' ! 35773: } ! 35774: ! 35775: arg = new expr(ELIST,e2,arg); ! 35776: arg = new expr(ELIST,e1,arg); ! 35777: Pexpr ee = new expr(G_CALL,vec_del_fct,arg); ! 35778: ee->fct_name = vec_del_fct; ! 35779: ee->tp = tp; ! 35780: // if (ansi_opt) { // q?void:int would be an error ! 35781: // ee = new expr(G_CM,ee,zero); ! 35782: // ee->tp = zero_type; ! 35783: // } ! 35784: // ee = new expr(QUEST,ee,zero); ! 35785: // ee->tp = tp; ! 35786: // ee->cond = r; ! 35787: *this = *ee; ! 35788: simpl(); ! 35789: return; ! 35790: } ! 35791: } ! 35792: else if (cl_obj_vec) { ! 35793: error("delete array of arrays"); ! 35794: } ! 35795: else { // _delete(e1) ! 35796: Pexpr ee = new expr(ELIST,e1,0); ! 35797: char* s = oper_name(DELETE); ! 35798: if (cl && base!=GDELETE) { ! 35799: Pname n = new name(s); ! 35800: e1 = find_name(n,cl,scope,CALL,curr_fct); ! 35801: if (e1->tp->base==OVERLOAD || Pfct(e1->tp)->nargs==2) { ! 35802: Pexpr ss = new texpr(SIZEOF,cl,0); ! 35803: ss->tp = size_t_type; ! 35804: ee->e2 = new expr(ELIST,ss,0); ! 35805: } ! 35806: } ! 35807: else ! 35808: e1 = gtbl->look(s,0); ! 35809: base = G_CALL; ! 35810: e2 = ee; ! 35811: overFound=0; // set in call_fct ! 35812: (void) call_fct(scope); ! 35813: if (overFound && overFound->n_scope != EXTERN) ! 35814: check_visibility(overFound,0,cl,cc->ftbl,cc->nof); ! 35815: overFound=0; ! 35816: } ! 35817: ! 35818: Pcall(this)->simpl(); ! 35819: } ! 35820: 0707071010112045371004440001630000160000010207600466055410400000700000013461size.c /*ident "@(#)ctrans:src/size.c 1.3" */ ! 35821: /********************************************************************* ! 35822: ! 35823: C++ source for cfront, the C++ compiler front-end ! 35824: written in the computer science research center of Bell Labs ! 35825: ! 35826: Copyright (c) 1984 AT&T, Inc. All rigths Reserved ! 35827: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 35828: ! 35829: size.c: ! 35830: ! 35831: initialize alignment and sizeof "constants" ! 35832: ! 35833: **********************************************************************/ ! 35834: ! 35835: #include "cfront.h" ! 35836: #include "size.h" ! 35837: ! 35838: int BI_IN_WORD = DBI_IN_WORD; ! 35839: int BI_IN_BYTE = DBI_IN_BYTE; ! 35840: int SZ_CHAR = DSZ_CHAR; ! 35841: int AL_CHAR = DAL_CHAR; ! 35842: int SZ_SHORT = DSZ_SHORT; ! 35843: int AL_SHORT = DAL_SHORT; ! 35844: int SZ_INT = DSZ_INT; ! 35845: int AL_INT = DAL_INT; ! 35846: int SZ_LONG = DSZ_LONG; ! 35847: int AL_LONG = DAL_LONG; ! 35848: int SZ_FLOAT = DSZ_FLOAT; ! 35849: int AL_FLOAT = DAL_FLOAT; ! 35850: int SZ_DOUBLE = DSZ_DOUBLE; ! 35851: int AL_DOUBLE = DAL_DOUBLE; ! 35852: int SZ_LDOUBLE = DSZ_LDOUBLE; ! 35853: int AL_LDOUBLE = DAL_LDOUBLE; ! 35854: int SZ_STRUCT = DSZ_STRUCT; ! 35855: int AL_STRUCT = DAL_STRUCT; ! 35856: //int SZ_FRAME = DSZ_FRAME; ! 35857: //int AL_FRAME = DAL_FRAME; ! 35858: int SZ_WORD = DSZ_WORD; ! 35859: int SZ_WPTR = DSZ_WPTR; ! 35860: int AL_WPTR = DAL_WPTR; ! 35861: int SZ_BPTR = DSZ_BPTR; ! 35862: int AL_BPTR = DAL_BPTR; ! 35863: //int SZ_TOP = DSZ_TOP; ! 35864: //int SZ_BOTTOM = DSZ_BOTTOM; ! 35865: char* LARGEST_INT = DLARGEST_INT; ! 35866: int F_SENSITIVE = DF_SENSITIVE; ! 35867: int F_OPTIMIZED = DF_OPTIMIZED; ! 35868: ! 35869: int arg1 = 0; ! 35870: ! 35871: int get_line(FILE* fp) ! 35872: { ! 35873: char s[32]; ! 35874: char s2[32]; ! 35875: ! 35876: if (fscanf(fp,"%s %s",s2,s) == EOF) return 0; ! 35877: ! 35878: if (strcmp("DLARGEST_INT",s) == 0) { ! 35879: if (fscanf(fp," %s",s2)==EOF) return 0; ! 35880: //// get rid of quotes ! 35881: for(int i=0;i<=strlen(s2)+1;i++) ! 35882: if (s2[i]== '"') { ! 35883: for (int j=i;j<=strlen(s2)+1;j++) ! 35884: s2[j]=s2[j+1]; ! 35885: } ! 35886: } ! 35887: else ! 35888: if (fscanf(fp,"%d ",&arg1) == EOF) return 0; ! 35889: ! 35890: if (strcmp("DSZ_CHAR",s) == 0) { ! 35891: SZ_CHAR = arg1; ! 35892: return 1; ! 35893: } ! 35894: ! 35895: if (strcmp("DAL_CHAR",s) == 0) { ! 35896: AL_CHAR = arg1; ! 35897: return 1; ! 35898: } ! 35899: ! 35900: if (strcmp("DSZ_SHORT",s) == 0) { ! 35901: SZ_SHORT = arg1; ! 35902: return 1; ! 35903: } ! 35904: ! 35905: if (strcmp("DAL_SHORT",s) == 0) { ! 35906: AL_SHORT = arg1; ! 35907: return 1; ! 35908: } ! 35909: ! 35910: if (strcmp("DSZ_INT",s) == 0) { ! 35911: SZ_INT = arg1; ! 35912: return 1; ! 35913: } ! 35914: ! 35915: if (strcmp("DAL_INT",s) == 0) { ! 35916: AL_INT=arg1; ! 35917: return 1; ! 35918: } ! 35919: ! 35920: if (strcmp("DLARGEST_INT",s) == 0) { ! 35921: LARGEST_INT = new char[strlen(s2)+1]; ! 35922: strcpy(LARGEST_INT,s2); ! 35923: return 1; ! 35924: } ! 35925: ! 35926: if (strcmp("DSZ_LONG",s) == 0) { ! 35927: SZ_LONG = arg1; ! 35928: return 1; ! 35929: } ! 35930: ! 35931: if (strcmp("DAL_LONG",s) == 0) { ! 35932: AL_LONG = arg1; ! 35933: return 1; ! 35934: } ! 35935: ! 35936: if (strcmp("DSZ_FLOAT",s) == 0) { ! 35937: SZ_FLOAT = arg1; ! 35938: return 1; ! 35939: } ! 35940: ! 35941: if (strcmp("DAL_FLOAT",s) == 0) { ! 35942: AL_FLOAT = arg1; ! 35943: return 1; ! 35944: } ! 35945: ! 35946: if (strcmp("DSZ_DOUBLE",s) == 0) { ! 35947: SZ_DOUBLE = arg1; ! 35948: return 1; ! 35949: } ! 35950: ! 35951: if (strcmp("DAL_DOUBLE",s) == 0) { ! 35952: AL_DOUBLE = arg1; ! 35953: return 1; ! 35954: } ! 35955: ! 35956: if (strcmp("DSZ_LDOUBLE",s) == 0) { ! 35957: SZ_LDOUBLE = arg1; ! 35958: return 1; ! 35959: } ! 35960: ! 35961: if (strcmp("DAL_LDOUBLE",s) == 0) { ! 35962: AL_LDOUBLE = arg1; ! 35963: return 1; ! 35964: } ! 35965: ! 35966: if (strcmp("DBI_IN_BYTE",s) == 0) { ! 35967: BI_IN_BYTE = arg1; ! 35968: return 1; ! 35969: } ! 35970: ! 35971: if (strcmp("DBI_IN_WORD",s) == 0) { ! 35972: BI_IN_WORD= arg1; ! 35973: return 1; ! 35974: } ! 35975: ! 35976: if (strcmp("DSZ_STRUCT",s) == 0) { ! 35977: SZ_STRUCT = arg1; ! 35978: return 1; ! 35979: } ! 35980: ! 35981: if (strcmp("DAL_STRUCT",s) == 0) { ! 35982: AL_STRUCT = arg1; ! 35983: return 1; ! 35984: } ! 35985: ! 35986: if (strcmp("DF_SENSITIVE",s) == 0) { ! 35987: F_SENSITIVE = arg1; ! 35988: return 1; ! 35989: } ! 35990: ! 35991: if (strcmp("DF_OPTIMIZED",s) == 0) { ! 35992: F_OPTIMIZED = arg1; ! 35993: return 1; ! 35994: } ! 35995: ! 35996: if (strcmp("frame",s) == 0) { ! 35997: // SZ_FRAME = arg1; ! 35998: // AL_FRAME = arg2; ! 35999: return 1; ! 36000: } ! 36001: ! 36002: if (strcmp("DSZ_WORD",s) == 0) { ! 36003: SZ_WORD = arg1; ! 36004: return 1; ! 36005: } ! 36006: ! 36007: if (strcmp("DSZ_WPTR",s) == 0) { ! 36008: SZ_WPTR = arg1; ! 36009: return 1; ! 36010: } ! 36011: ! 36012: if (strcmp("DAL_WPTR",s) == 0) { ! 36013: AL_WPTR = arg1; ! 36014: return 1; ! 36015: } ! 36016: ! 36017: if (strcmp("DSZ_BPTR",s) == 0) { ! 36018: SZ_BPTR = arg1; ! 36019: return 1; ! 36020: } ! 36021: ! 36022: if (strcmp("DAL_BPTR",s) == 0) { ! 36023: AL_BPTR = arg1; ! 36024: return 1; ! 36025: } ! 36026: ! 36027: if (strcmp("top",s) == 0) { ! 36028: // SZ_TOP = arg1; ! 36029: // SZ_BOTTOM = arg2; ! 36030: return 1; ! 36031: } ! 36032: return 0; ! 36033: } ! 36034: ! 36035: int read_align(char* f) ! 36036: { ! 36037: char* p = f; ! 36038: if (*p == 0) { ! 36039: fprintf(stderr,"size/align file missing\n"); ! 36040: ext(1); ! 36041: } ! 36042: FILE* fp = fopen(f,"r"); ! 36043: if (fp == 0) return 1; ! 36044: while (get_line(fp)) ; ! 36045: return 0; ! 36046: } ! 36047: /* ! 36048: print_align(char* s) ! 36049: { ! 36050: fprintf(stderr,"%s sizes and alignments\n\n",s); ! 36051: ! 36052: fprintf(stderr," size align largest\n"); ! 36053: fprintf(stderr,"char %d %d\n",SZ_CHAR,AL_CHAR); ! 36054: fprintf(stderr,"short %d %d\n",SZ_SHORT,AL_SHORT); ! 36055: fprintf(stderr,"int %d %d %s\n",SZ_INT,AL_INT,LARGEST_INT); ! 36056: fprintf(stderr,"long %d %d\n",SZ_LONG,AL_LONG); ! 36057: fprintf(stderr,"float %d %d\n",SZ_FLOAT,AL_FLOAT); ! 36058: fprintf(stderr,"double %d %d\n",SZ_DOUBLE,AL_DOUBLE); ! 36059: fprintf(stderr,"ldouble %d %d\n",SZ_LDOUBLE,AL_LDOUBLE); ! 36060: fprintf(stderr,"bptr %d %d\n",SZ_BPTR,AL_BPTR); ! 36061: fprintf(stderr,"wptr %d %d\n",SZ_WPTR,AL_WPTR); ! 36062: fprintf(stderr,"struct %d %d\n",SZ_STRUCT,AL_STRUCT); ! 36063: fprintf(stderr,"struct2 %d %d\n",F_SENSITIVE,F_OPTIMIZED); ! 36064: // fprintf(stderr,"frame %d %d\n",SZ_FRAME,AL_FRAME); ! 36065: ! 36066: fprintf(stderr,"%d bits in a byte, %d bits in a word, %d bytes in a word\n", ! 36067: BI_IN_BYTE, BI_IN_WORD, SZ_WORD); ! 36068: return 1; ! 36069: } ! 36070: */ ! 36071: ! 36072: int c_strlen(const char* s) ! 36073: /* ! 36074: return sizeof(s) with escapes processed ! 36075: sizeof("") == 1 the terminating 0 ! 36076: sizeof("a") == 2 ! 36077: sizeof("\0x") == 3 0 x 0 ! 36078: sizeof("\012") == 2 '\012' ! 36079: sizeof("\01") '\001' ! 36080: sizeof("\x") == 2 \ ignored ! 36081: ! 36082: */ ! 36083: { ! 36084: int i = 1; ! 36085: for (const char* p = s; *p; i++,p++) { ! 36086: if (*p == '\\') { // '\? ! 36087: switch (*++p) { ! 36088: case '0': ! 36089: switch (p[1]) { // '\01' or '\012' ! 36090: case '0': case '1': case '2': case '3': ! 36091: case '4': case '5': case '6': case '7': ! 36092: break; ! 36093: default: ! 36094: continue; // '\0' ! 36095: } ! 36096: /* no break */ ! 36097: case '1': case '2': case '3': ! 36098: case '4': case '5': case '6': case '7': // '\123' ! 36099: switch (*++p) { ! 36100: case '0': case '1': case '2': case '3': ! 36101: case '4': case '5': case '6': case '7': ! 36102: switch (*++p) { ! 36103: case '0': case '1': case '2': case '3': ! 36104: case '4': case '5': case '6': case '7': ! 36105: break; ! 36106: default: ! 36107: --p; ! 36108: } ! 36109: break; ! 36110: default: ! 36111: --p; ! 36112: break; ! 36113: } ! 36114: break; ! 36115: case '\n': // \newline doesn't count ! 36116: i--; ! 36117: break; ! 36118: } ! 36119: } ! 36120: } ! 36121: return i; ! 36122: } ! 36123: 0707071010112045661004440001630000160000010207700466055411000000700000020157size.h /*ident "@(#)ctrans:src/size.h 1.2" */ ! 36124: /************************************************************************* ! 36125: ! 36126: C++ source for cfront, the C++ compiler front-end ! 36127: written in the computer science research center of Bell Labs ! 36128: ! 36129: Copyright (c) 1984 AT&T, Inc. All rigths Reserved ! 36130: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 36131: ! 36132: size.h: ! 36133: sizes and alignments used to calculate sizeofs ! 36134: ! 36135: table and butffer sizes ! 36136: ! 36137: ***************************************************************************/ ! 36138: #ifndef GRAM ! 36139: extern BI_IN_WORD; ! 36140: extern BI_IN_BYTE; ! 36141: /* byte sizes */ ! 36142: extern SZ_CHAR; ! 36143: extern AL_CHAR; ! 36144: ! 36145: extern SZ_SHORT; ! 36146: extern AL_SHORT; ! 36147: ! 36148: extern SZ_INT; ! 36149: extern AL_INT; ! 36150: ! 36151: extern SZ_LONG; ! 36152: extern AL_LONG; ! 36153: ! 36154: extern SZ_FLOAT; ! 36155: extern AL_FLOAT; ! 36156: ! 36157: extern SZ_DOUBLE; ! 36158: extern AL_DOUBLE; ! 36159: ! 36160: extern SZ_LDOUBLE; ! 36161: extern AL_LDOUBLE; ! 36162: ! 36163: extern SZ_STRUCT; /* minimum struct size */ ! 36164: extern AL_STRUCT; ! 36165: ! 36166: //extern SZ_FRAME; ! 36167: //extern AL_FRAME; ! 36168: ! 36169: extern SZ_WORD; ! 36170: ! 36171: extern SZ_WPTR; ! 36172: extern AL_WPTR; ! 36173: ! 36174: extern SZ_BPTR; ! 36175: extern AL_BPTR; ! 36176: ! 36177: //extern SZ_TOP; ! 36178: //extern SZ_BOTTOM; ! 36179: ! 36180: extern char* LARGEST_INT; ! 36181: extern int F_SENSITIVE; // is field alignment sensitive to the type of the field? ! 36182: extern int F_OPTIMIZED; // can the compiler fit a small int field into a char? ! 36183: #endif ! 36184: // default sizes: ! 36185: // Note: #if doesn't work on all systems ! 36186: #ifdef u3b ! 36187: #define Abbb ! 36188: #endif ! 36189: #ifdef u3b2 ! 36190: #define Abbb ! 36191: #endif ! 36192: #ifdef u3b5 ! 36193: #define Abbb ! 36194: #endif ! 36195: #ifdef u3b15 ! 36196: #define Abbb ! 36197: #endif ! 36198: #ifdef pyr ! 36199: #define Abbb ! 36200: #endif ! 36201: ! 36202: ! 36203: #ifdef alliant ! 36204: #define Am68 ! 36205: #endif ! 36206: #ifdef apollo ! 36207: #define Am68 ! 36208: #endif ! 36209: #if defined(sun2) || defined(mc68010) ! 36210: #define Am68 ! 36211: #endif ! 36212: #if defined(sun3) || defined(mc68020) ! 36213: #define Am68 ! 36214: #endif ! 36215: #if defined(mc68k) || defined(hp9000s200) || defined(hp9000s300) ! 36216: #define Am68 ! 36217: #endif ! 36218: ! 36219: #ifdef iAPX286 ! 36220: #ifdef LARGE ! 36221: #define Ai286l ! 36222: #endif ! 36223: #endif ! 36224: ! 36225: #ifdef Abbb ! 36226: /* AT&T 3Bs */ ! 36227: #define DBI_IN_WORD 32 ! 36228: #define DBI_IN_BYTE 8 ! 36229: #define DSZ_CHAR 1 ! 36230: #define DAL_CHAR 1 ! 36231: #define DSZ_SHORT 2 ! 36232: #define DAL_SHORT 2 ! 36233: #define DSZ_INT 4 ! 36234: #define DAL_INT 4 ! 36235: #define DSZ_LONG 4 ! 36236: #define DAL_LONG 4 ! 36237: #define DSZ_FLOAT 4 ! 36238: #define DAL_FLOAT 4 ! 36239: #define DSZ_DOUBLE 8 ! 36240: #define DAL_DOUBLE 4 ! 36241: #define DSZ_LDOUBLE 8 ! 36242: #define DAL_LDOUBLE 4 ! 36243: #define DSZ_STRUCT 4 ! 36244: #define DAL_STRUCT 4 ! 36245: //#define DSZ_FRAME 4 ! 36246: //#define DAL_FRAME 4 ! 36247: #define DSZ_WORD 4 ! 36248: #define DSZ_WPTR 4 ! 36249: #define DAL_WPTR 4 ! 36250: #define DSZ_BPTR 4 ! 36251: #define DAL_BPTR 4 ! 36252: //#define DSZ_TOP 0 ! 36253: //#define DSZ_BOTTOM 0 ! 36254: #define DLARGEST_INT "2147483647" /* 2**31 - 1 */ ! 36255: #define DF_SENSITIVE 0 ! 36256: #define DF_OPTIMIZED 1 ! 36257: #else ! 36258: #ifdef Am68 ! 36259: /* most M68K boxes */ ! 36260: #if defined(hp9000s200) || defined(hp9000s300) ! 36261: #define DBI_IN_WORD 32 ! 36262: #else ! 36263: #define DBI_IN_WORD 16 ! 36264: #endif ! 36265: #define DBI_IN_BYTE 8 ! 36266: #define DSZ_CHAR 1 ! 36267: #define DAL_CHAR 1 ! 36268: #define DSZ_SHORT 2 ! 36269: #define DAL_SHORT 2 ! 36270: #define DSZ_INT 4 ! 36271: #define DAL_INT 2 ! 36272: #define DSZ_LONG 4 ! 36273: #define DAL_LONG 2 ! 36274: #define DSZ_FLOAT 4 ! 36275: #define DAL_FLOAT 2 ! 36276: #define DSZ_DOUBLE 8 ! 36277: #define DAL_DOUBLE 2 ! 36278: #define DSZ_LDOUBLE 8 ! 36279: #define DAL_LDOUBLE 2 ! 36280: #define DSZ_STRUCT 2 ! 36281: #define DAL_STRUCT 2 ! 36282: //#define DSZ_FRAME 4 ! 36283: //#define DAL_FRAME 4 ! 36284: #define DSZ_WORD 2 ! 36285: #define DSZ_WPTR 4 ! 36286: #define DAL_WPTR 2 ! 36287: #define DSZ_BPTR 4 ! 36288: #define DAL_BPTR 2 ! 36289: //#define DSZ_TOP 0 ! 36290: //#define DSZ_BOTTOM 0 ! 36291: #define DLARGEST_INT "2147483647" /* 2**31 - 1 */ ! 36292: #define DF_SENSITIVE 0 ! 36293: #define DF_OPTIMIZED 1 ! 36294: #else ! 36295: #ifdef Ai286l ! 36296: /* Intel 80286 large model */ ! 36297: #define DBI_IN_WORD 16 ! 36298: #define DBI_IN_BYTE 8 ! 36299: #define DSZ_CHAR 1 ! 36300: #define DAL_CHAR 1 ! 36301: #define DSZ_SHORT 2 ! 36302: #define DAL_SHORT 2 ! 36303: #define DSZ_INT 2 ! 36304: #define DAL_INT 2 ! 36305: #define DSZ_LONG 4 ! 36306: #define DAL_LONG 2 ! 36307: #define DSZ_FLOAT 4 ! 36308: #define DAL_FLOAT 2 ! 36309: #define DSZ_DOUBLE 8 ! 36310: #define DAL_DOUBLE 2 ! 36311: #define DSZ_LDOUBLE 8 ! 36312: #define DAL_LDOUBLE 2 ! 36313: #define DSZ_STRUCT 2 ! 36314: #define DAL_STRUCT 2 ! 36315: //#define DSZ_FRAME 4 ! 36316: //#define DAL_FRAME 4 ! 36317: #define DSZ_WORD 2 ! 36318: #define DSZ_WPTR 4 ! 36319: #define DAL_WPTR 2 ! 36320: #define DSZ_BPTR 4 ! 36321: #define DAL_BPTR 2 ! 36322: //#define DSZ_TOP 0 ! 36323: //#define DSZ_BOTTOM 0 ! 36324: #define DLARGEST_INT "32767" /* 2**15 - 1 */ ! 36325: #define DF_SENSITIVE 0 ! 36326: #define DF_OPTIMIZED 1 ! 36327: #else ! 36328: #if defined(uts) || defined(hp9000s800) || defined(sun4) || defined(sparc) ! 36329: /* Amdahl running UTS, HP RISC */ ! 36330: #define DBI_IN_WORD 32 ! 36331: #define DBI_IN_BYTE 8 ! 36332: #define DSZ_CHAR 1 ! 36333: #define DAL_CHAR 1 ! 36334: #define DSZ_SHORT 2 ! 36335: #define DAL_SHORT 2 ! 36336: #define DSZ_INT 4 ! 36337: #define DAL_INT 4 ! 36338: #define DSZ_LONG 4 ! 36339: #define DAL_LONG 4 ! 36340: #define DSZ_FLOAT 4 ! 36341: #define DAL_FLOAT 4 ! 36342: #define DSZ_DOUBLE 8 ! 36343: #define DAL_DOUBLE 8 ! 36344: #define DSZ_LDOUBLE 8 ! 36345: #define DAL_LDOUBLE 8 ! 36346: #define DSZ_STRUCT 1 ! 36347: #define DAL_STRUCT 1 ! 36348: #define DSZ_WORD 4 ! 36349: #define DSZ_WPTR 4 ! 36350: #define DAL_WPTR 4 ! 36351: #define DSZ_BPTR 4 ! 36352: #define DAL_BPTR 4 ! 36353: #define DLARGEST_INT "2147483647" /* 2**31 - 1 */ ! 36354: #if defined(uts) ! 36355: #define DF_SENSITIVE 1 ! 36356: #else ! 36357: #define DF_SENSITIVE 0 ! 36358: #endif ! 36359: #define DF_OPTIMIZED 1 ! 36360: #else ! 36361: #ifdef hpux ! 36362: /* hp */ ! 36363: #define DBI_IN_WORD 32 ! 36364: #define DBI_IN_BYTE 8 ! 36365: #define DSZ_CHAR 1 ! 36366: #define DAL_CHAR 1 ! 36367: #define DSZ_SHORT 2 ! 36368: #define DAL_SHORT 2 ! 36369: #define DSZ_INT 4 ! 36370: #define DAL_INT 4 ! 36371: #define DSZ_LONG 4 ! 36372: #define DAL_LONG 4 ! 36373: #define DSZ_FLOAT 4 ! 36374: #define DAL_FLOAT 4 ! 36375: #define DSZ_DOUBLE 8 ! 36376: #define DAL_DOUBLE 8 ! 36377: #define DSZ_LDOUBLE 8 ! 36378: #define DAL_LDOUBLE 8 ! 36379: #define DSZ_STRUCT 1 ! 36380: #define DAL_STRUCT 1 ! 36381: #define DSZ_WORD 4 ! 36382: #define DSZ_WPTR 4 ! 36383: #define DAL_WPTR 4 ! 36384: #define DSZ_BPTR 4 ! 36385: #define DAL_BPTR 4 ! 36386: #define DLARGEST_INT "2147483647" /* 2**31 - 1 */ ! 36387: #define DF_SENSITIVE 1 ! 36388: #define DF_OPTIMIZED 1 ! 36389: #else ! 36390: #if defined(vax) || defined(ibm032) || defined(i386) ! 36391: /* VAX, IBM 32, Intel 386 */ ! 36392: #define DBI_IN_WORD 32 ! 36393: #define DBI_IN_BYTE 8 ! 36394: #define DSZ_CHAR 1 ! 36395: #define DAL_CHAR 1 ! 36396: #define DSZ_SHORT 2 ! 36397: #define DAL_SHORT 2 ! 36398: #define DSZ_INT 4 ! 36399: #define DAL_INT 4 ! 36400: #define DSZ_LONG 4 ! 36401: #define DAL_LONG 4 ! 36402: #define DSZ_FLOAT 4 ! 36403: #define DAL_FLOAT 4 ! 36404: #define DSZ_DOUBLE 8 ! 36405: #define DAL_DOUBLE 4 ! 36406: #define DSZ_LDOUBLE 8 ! 36407: #define DAL_LDOUBLE 4 ! 36408: #define DSZ_STRUCT 1 ! 36409: #define DAL_STRUCT 1 ! 36410: //#define DSZ_FRAME 4 ! 36411: //#define DAL_FRAME 4 ! 36412: #define DSZ_WORD 4 ! 36413: #define DSZ_WPTR 4 ! 36414: #define DAL_WPTR 4 ! 36415: #define DSZ_BPTR 4 ! 36416: #define DAL_BPTR 4 ! 36417: //#define DSZ_TOP 0 ! 36418: //#define DSZ_BOTTOM 0 ! 36419: #define DLARGEST_INT "2147483647" /* 2**31 - 1 */ ! 36420: #define DF_SENSITIVE 0 ! 36421: #define DF_OPTIMIZED 1 ! 36422: #else ! 36423: #ifdef mc300 ! 36424: #define DBI_IN_WORD 32 ! 36425: #define DBI_IN_BYTE 8 ! 36426: #define DSZ_CHAR 1 ! 36427: #define DAL_CHAR 1 ! 36428: #define DSZ_SHORT 2 ! 36429: #define DAL_SHORT 2 ! 36430: #define DSZ_INT 4 ! 36431: #define DAL_INT 4 ! 36432: #define DSZ_LONG 4 ! 36433: #define DAL_LONG 4 ! 36434: #define DSZ_FLOAT 4 ! 36435: #define DAL_FLOAT 4 ! 36436: #define DSZ_DOUBLE 8 ! 36437: #define DAL_DOUBLE 4 ! 36438: #define DSZ_LDOUBLE 8 ! 36439: #define DAL_LDOUBLE 4 ! 36440: #define DSZ_STRUCT 2 ! 36441: #define DAL_STRUCT 2 ! 36442: //#define DSZ_FRAME 4 ! 36443: //#define DAL_FRAME 4 ! 36444: #define DSZ_WORD 4 ! 36445: #define DSZ_WPTR 4 ! 36446: #define DAL_WPTR 4 ! 36447: #define DSZ_BPTR 4 ! 36448: #define DAL_BPTR 4 ! 36449: //#define DSZ_TOP 0 ! 36450: //#define DSZ_BOTTOM 0 ! 36451: #define DLARGEST_INT "2147483647" /* 2**31 - 1 */ ! 36452: #define DF_SENSITIVE 0 ! 36453: #define DF_OPTIMIZED 1 ! 36454: #else ! 36455: #ifdef mips ! 36456: #define DBI_IN_BYTE 8 ! 36457: #define DBI_IN_WORD 32 ! 36458: #define DSZ_WORD 4 ! 36459: #define DSZ_CHAR 1 ! 36460: #define DAL_CHAR 1 ! 36461: #define DSZ_SHORT 2 ! 36462: #define DAL_SHORT 2 ! 36463: #define DSZ_INT 4 ! 36464: #define DAL_INT 4 ! 36465: #define DLARGEST_INT "2147483647" ! 36466: #define DSZ_LONG 4 ! 36467: #define DAL_LONG 4 ! 36468: #define DSZ_FLOAT 4 ! 36469: #define DAL_FLOAT 4 ! 36470: #define DSZ_DOUBLE 8 ! 36471: #define DAL_DOUBLE 8 ! 36472: #define DSZ_LDOUBLE 8 ! 36473: #define DAL_LDOUBLE 8 ! 36474: #define DSZ_BPTR 4 ! 36475: #define DAL_BPTR 4 ! 36476: #define DSZ_WPTR 4 ! 36477: #define DAL_WPTR 4 ! 36478: #define DSZ_STRUCT 1 ! 36479: #define DAL_STRUCT 1 ! 36480: #define DF_SENSITIVE 0 ! 36481: #define DF_OPTIMIZED 1 ! 36482: #else ! 36483: /* defaults: 0 => error */ ! 36484: #define DBI_IN_WORD 0 ! 36485: #define DBI_IN_BYTE 0 ! 36486: #define DSZ_CHAR 1 ! 36487: #define DAL_CHAR 1 ! 36488: #define DSZ_SHORT 0 ! 36489: #define DAL_SHORT 0 ! 36490: #define DSZ_INT 0 ! 36491: #define DAL_INT 0 ! 36492: #define DSZ_LONG 0 ! 36493: #define DAL_LONG 0 ! 36494: #define DSZ_FLOAT 0 ! 36495: #define DAL_FLOAT 0 ! 36496: #define DSZ_DOUBLE 0 ! 36497: #define DAL_DOUBLE 0 ! 36498: #define DSZ_LDOUBLE 0 ! 36499: #define DAL_LDOUBLE 0 ! 36500: #define DSZ_STRUCT 0 ! 36501: #define DAL_STRUCT 0 ! 36502: #define DSZ_WORD 0 ! 36503: #define DSZ_WPTR 0 ! 36504: #define DAL_WPTR 0 ! 36505: #define DSZ_BPTR 0 ! 36506: #define DAL_BPTR 0 ! 36507: #define DLARGEST_INT "0" ! 36508: #define DF_SENSITIVE 0 ! 36509: #define DF_OPTIMIZED 0 ! 36510: #endif ! 36511: #endif ! 36512: #endif ! 36513: #endif ! 36514: #endif ! 36515: #endif ! 36516: #endif ! 36517: #endif ! 36518: ! 36519: #define KTBLSIZE 123 /* initial keyword table size */ ! 36520: #define GTBLSIZE 257 /* initial global name table size */ ! 36521: #define CTBLSIZE 12 /* initial class table size */ ! 36522: #define TBLSIZE 20 /* initial block table size */ ! 36523: #define BLMAX 50 /* max block nesting */ ! 36524: #define MAXFILE 127 /* max include file nesting */ ! 36525: #define MAXERR 13 /* maximum number of errors before terminating */ ! 36526: ! 36527: #ifndef GRAM ! 36528: const CHUNK = 8*1024; ! 36529: void* chunk(int); ! 36530: #endif ! 36531: 0707071010112045671004440001630000160000010210000466055411300001000000015476table.c /*ident "@(#)ctrans:src/table.c 1.3" */ ! 36532: /************************************************************************** ! 36533: ! 36534: C++ source for cfront, the C++ compiler front-end ! 36535: written in the computer science research center of Bell Labs ! 36536: ! 36537: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 36538: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 36539: ! 36540: table.c: ! 36541: ! 36542: *****************************************************************************/ ! 36543: ! 36544: #include "cfront.h" ! 36545: #include "size.h" ! 36546: ! 36547: #ifdef DBG ! 36548: extern long node_id; ! 36549: #define DBCHECK() if(node::allocated) error('i',"allocated node (id %d, base%k) on free list! (src: \"%s\", %d",node::id,node::base,__FILE__,__LINE__); ! 36550: #else ! 36551: #define DBCHECK() /**/ ! 36552: #endif ! 36553: ! 36554: table::table(short sz, Ptable nx, Pname n) ! 36555: /* ! 36556: create a symbol table with "size" entries ! 36557: the scope of table is enclosed in the scope of "nx" ! 36558: ! 36559: both the vector of class name pointers and the hash table ! 36560: are initialized containing all zeroes ! 36561: ! 36562: to simplify hashed lookup entries[0] is never used ! 36563: so the size of "entries" must be "size+1" to hold "size" entries ! 36564: */ ! 36565: { ! 36566: DBCHECK(); ! 36567: base = TABLE; ! 36568: t_name = n; ! 36569: size = sz = (sz<=0) ? 2 : sz+1; ! 36570: //fprintf(stderr,"table::table %d %s %d (%d %d)\n", this, (n)?n->string:"?", sz,(sz*3)/2); ! 36571: entries = new Pname[sz]; ! 36572: hashsize = sz = (sz*3)/2; ! 36573: hashtbl = new short[sz]; ! 36574: next = nx; ! 36575: free_slot = 1; ! 36576: DBID(); ! 36577: } ! 36578: ! 36579: table::~table() ! 36580: { ! 36581: delete entries; ! 36582: delete hashtbl; ! 36583: } ! 36584: ! 36585: Pname table::look(char* s, TOK k) ! 36586: /* ! 36587: look for "s" in table, ignore entries which are not of "k" type ! 36588: look and insert MUST be the same lookup algorithm ! 36589: */ ! 36590: { ! 36591: Ptable t; ! 36592: register char * p; ! 36593: register char * q; ! 36594: register int i; ! 36595: Pname n; ! 36596: int rr; ! 36597: ! 36598: // if (s == 0) error('i',"%d->look(0)",this); ! 36599: // if (this == 0) error('i',"0->look(%s)",s); ! 36600: // if (base != TABLE) error('i',"(%d,%d)->look(%s)",this,base,s); ! 36601: ! 36602: /* use simple hashing with linear search for overflow */ ! 36603: ! 36604: p = s; ! 36605: i = 0; ! 36606: while (*p) i += (i + *p++); /* i<<1 ^ *p++ better?*/ ! 36607: rr = (0<=i) ? i : -i; ! 36608: ! 36609: for (t=this; t; t=t->next) { ! 36610: /* in this and all enclosing scopes look for name "s" */ ! 36611: Pname* np = t->entries; ! 36612: int mx = t->hashsize; ! 36613: short* hash = t->hashtbl; ! 36614: int firsti = i = rr%mx; ! 36615: ! 36616: do { ! 36617: if (hash[i] == 0) goto not_found; ! 36618: n = np[hash[i]]; ! 36619: if (n == 0) error('i',"hashed lookup"); ! 36620: p = n->string; /* strcmp(n->n_string,s) */ ! 36621: q = s; ! 36622: while (*p && *q) ! 36623: if (*p++ != *q++) goto nxt; ! 36624: if (*p == *q) goto found; ! 36625: nxt: ! 36626: if (mx <= ++i) i = 0; /* wrap around */ ! 36627: } while (i != firsti); ! 36628: ! 36629: found: ! 36630: for (; n; n=n->n_tbl_list){ /* for all name "s"s look for a key match */ ! 36631: if (n->n_key == k) return n; ! 36632: } ! 36633: ! 36634: not_found:; ! 36635: } ! 36636: ! 36637: return 0; /* not found && no enclosing scope */ ! 36638: } ! 36639: ! 36640: bit Nold; /* non-zero if last insert() failed */ ! 36641: ! 36642: Pname table::insert(Pname nx, TOK k) ! 36643: /* ! 36644: the lookup algorithm MUST be the same as look ! 36645: if nx is found return the older entry otherwise a copy of nx; ! 36646: Nold = (nx found) ? 1 : 0; ! 36647: */ ! 36648: { ! 36649: register char * p; ! 36650: register int i; ! 36651: Pname n; ! 36652: Pname* np = entries; ! 36653: Pname* link; ! 36654: int firsti; ! 36655: int mx = hashsize; ! 36656: short* hash = hashtbl; ! 36657: char* s = nx->string; ! 36658: ! 36659: if (s==0) error('i',"%p->insert(0,%k)",this,k); ! 36660: nx->n_key = k; ! 36661: if (nx->n_tbl_list || nx->n_table) error('i',"%n in two tables",nx); ! 36662: /* use simple hashing with linear search for overflow */ ! 36663: ! 36664: p = s; ! 36665: i = 0; ! 36666: while (*p) i += (i + *p++); ! 36667: if (i<0) i = -i; ! 36668: firsti = i = i%mx; ! 36669: ! 36670: do { /* look for name "s" */ ! 36671: if (hash[i] == 0) { ! 36672: hash[i] = free_slot; ! 36673: goto add_np; ! 36674: } ! 36675: n = np[hash[i]]; ! 36676: if (n == 0) error('i',"hashed lookup"); ! 36677: if (strcmp(n->string,s) == 0) goto found; ! 36678: /* ! 36679: p = n->string; ! 36680: q = s; ! 36681: while (*p && *q) if (*p++ != *q++) goto nxt; ! 36682: if (*p == *q) goto found; ! 36683: nxt: ! 36684: */ ! 36685: if (mx <= ++i) i = 0; /* wrap around */ ! 36686: } while (i != firsti); ! 36687: ! 36688: error("N table full"); ! 36689: ! 36690: found: ! 36691: ! 36692: ! 36693: for(;;) { ! 36694: if ( k!=NESTED && n->n_key==k) { Nold = 1; return n; } ! 36695: ! 36696: if (n->n_tbl_list) ! 36697: n = n->n_tbl_list; ! 36698: else { ! 36699: link = &(n->n_tbl_list); ! 36700: goto re_allocate; ! 36701: } ! 36702: } ! 36703: ! 36704: add_np: ! 36705: if (size <= free_slot) { ! 36706: grow(2*size); ! 36707: return insert(nx,k); ! 36708: } ! 36709: ! 36710: link = &(np[free_slot++]); ! 36711: ! 36712: re_allocate: ! 36713: { ! 36714: Pname nw = new name; ! 36715: *nw = *nx; ! 36716: char* ps = new char[strlen(s)+1]; // copy string to safer store ! 36717: strcpy(ps,s); ! 36718: // Nstr++; ! 36719: nw->string = ps; ! 36720: nw->n_table = this; ! 36721: *link = nw; ! 36722: Nold = 0; ! 36723: // Nname++; ! 36724: return nw; ! 36725: } ! 36726: } ! 36727: ! 36728: void table::grow(int g) ! 36729: { ! 36730: short* hash; ! 36731: register int j; ! 36732: int mx; ! 36733: register Pname* np; ! 36734: Pname n; ! 36735: ! 36736: if (g <= free_slot) error('i',"table.grow(%d,%d)",g,free_slot); ! 36737: if (g <= size) return; ! 36738: //error('d',"grow %d %s %d->%d", this, (t_name)?t_name->string:"?", size, g+1); ! 36739: size = mx = g+1; ! 36740: ! 36741: np = new Pname[mx]; ! 36742: for (j=0; j<free_slot; j++) np[j] = entries[j]; ! 36743: delete entries; ! 36744: entries = np; ! 36745: ! 36746: delete hashtbl; ! 36747: hashsize = mx = (g*3)/2; ! 36748: hash = hashtbl = new short[mx]; ! 36749: ! 36750: for (j=1; j<free_slot; j++) { /* rehash(np[j]); */ ! 36751: char * s = np[j]->string; ! 36752: register char * p; ! 36753: char * q; ! 36754: register int i; ! 36755: int firsti; ! 36756: ! 36757: p = s; ! 36758: i = 0; ! 36759: while (*p) i += (i + *p++); ! 36760: if (i<0) i = -i; ! 36761: firsti = i = i%mx; ! 36762: ! 36763: do { /* look for name "s" */ ! 36764: if (hash[i] == 0) { ! 36765: hash[i] = j; ! 36766: goto add_np; ! 36767: } ! 36768: n = np[hash[i]]; ! 36769: if (n == 0) error('i',"hashed lookup"); ! 36770: p = n->string; /* strcmp(n->n_string,s) */ ! 36771: q = s; ! 36772: while (*p && *q) if (*p++ != *q++) goto nxt; ! 36773: if (*p == *q) goto found; ! 36774: nxt: ! 36775: if (mx <= ++i) i = 0; /* wrap around */ ! 36776: } while (i != firsti); ! 36777: ! 36778: error('i',"rehash??"); ! 36779: ! 36780: found: ! 36781: error('i',"rehash failed"); ! 36782: ! 36783: add_np:; ! 36784: } ! 36785: } ! 36786: ! 36787: Pname table::get_mem(int i) ! 36788: /* ! 36789: return a pointer to the i'th entry, or 0 if it does not exist ! 36790: */ ! 36791: { ! 36792: return (i<=0 || free_slot<=i) ? 0 : entries[i]; ! 36793: } ! 36794: ! 36795: void table_delete(char* s, TOK k, int ll ) ! 36796: /* ! 36797: deletes local class entry from keyword table ! 36798: adjusts pointers if multiple entries ! 36799: uses same lookup as table::look and table::insert ! 36800: */ ! 36801: { ! 36802: Ptable t = ktbl; ! 36803: register char * p; ! 36804: register char * q; ! 36805: register int i; ! 36806: Pname n; ! 36807: int rr; ! 36808: ! 36809: p = s; ! 36810: i = 0; ! 36811: while (*p) i += (i + *p++); /* i<<1 ^ *p++ better?*/ ! 36812: rr = (0<=i) ? i : -i; ! 36813: ! 36814: // error ('d', "table_delete: %s ll: %d", s, ll ); ! 36815: ! 36816: Pname* np = t->entries; ! 36817: int mx = t->hashsize; ! 36818: short* hash = t->hashtbl; ! 36819: int firsti = i = rr%mx; ! 36820: ! 36821: do { ! 36822: if (hash[i] == 0) error('i',"table delete: not found: %s", s ); ! 36823: n = np[hash[i]]; ! 36824: if (n == 0) error('i',"table delete: hashed lookup"); ! 36825: p = n->string; /* strcmp(n->n_string,s) */ ! 36826: q = s; ! 36827: // error( 'd', "table_delete: %s", p ); ! 36828: while (*p && *q) ! 36829: if (*p++ != *q++) goto nxt; ! 36830: if (*p == *q) goto found; ! 36831: nxt: ! 36832: if (mx <= ++i) i = 0; /* wrap around */ ! 36833: } while (i != firsti); ! 36834: ! 36835: found: ! 36836: for (Pname prev = n; n; prev = n, n=n->n_tbl_list){ ! 36837: // error( 'd', "table_delete: found: %s %k lex: %d", n->string, n->n_key, n->lex_level ); ! 36838: if (n->n_key == k && n->lex_level == ll ) { ! 36839: // error( 'd', "table_delete: prev: %d n: %d n->tbl_list: %d", prev, n, n->n_tbl_list); ! 36840: if ( prev == n && n->n_tbl_list == 0 ) ! 36841: hash[i] = 0; ! 36842: else ! 36843: prev->n_tbl_list = n->n_tbl_list; ! 36844: return; ! 36845: } ! 36846: } ! 36847: } ! 36848: 0707071010112046031004440001630000160000010211300466055416400001300000206556template.c /* ident "@(#)ctrans:src/template.c 1.3" */ ! 36849: /******************************************************************* ! 36850: * template.c ! 36851: * ! 36852: * This file contains most of the implementation for a subset of ! 36853: * parametrized types as defined by the 1989 Stroustrup JOOP paper. ! 36854: * The subset chosen here was the subset relevant to the ! 36855: * implementation of aggregates in ObjectStore. ! 36856: * ! 36857: * The following is a list of features supported by the ! 36858: * implementation. The list of features parallels the ! 36859: * description of templates in the JOOP paper. ! 36860: * ! 36861: * a) Class templates supported. ! 36862: * ! 36863: * b) Member function templates supported. ! 36864: * Type-specific member functions as described at the ! 36865: * end of the "Outline of an implementation" section ! 36866: * are also supported. ! 36867: * ! 36868: * Non-member function templates are not supported. ! 36869: * ! 36870: * c) Template arguments may be of type "type" or ! 36871: * simple integral, real, double and pointer types ! 36872: * that are compile-time constants. ! 36873: * ! 36874: * Default arguments are not suported. ! 36875: * ! 36876: * ! 36877: * Restrictions: ! 36878: * ! 36879: * a) template definitions may not be nested. ! 36880: * ! 36881: * b) enums, or class definitions may not be ! 36882: * nested within a template class definition. ! 36883: * ! 36884: * This file also supports an internal template facility ! 36885: * to facilitate the implementation of ObjectStore data ! 36886: * model features. The internal template facility is ! 36887: * only used by compiler implementors, and is not user visible. ! 36888: * ! 36889: ************************************************************/ ! 36890: ! 36891: ! 36892: /*********************************************************** ! 36893: * ! 36894: * TBD ! 36895: * ! 36896: * 1) Error recovery, a never ending task, could stand improvement. ! 36897: * ! 36898: * 2) The template copying process could probably be speeded up ! 36899: * substantially, by only placing "graph-like" nodes in the hash ! 36900: * table. The current implementation plays it safe, and places ! 36901: * all nodes in the hash table. ! 36902: * ! 36903: * 3) Clean up $name processing, it needs to be remodularized ! 36904: * so that class templates and tree templates share the code. ! 36905: * ! 36906: * 4) Permit parametrized name default names within member ! 36907: * functions. ! 36908: * ! 36909: ****************************************************************/ ! 36910: ! 36911: #include "tree_copy.h" ! 36912: #include "cfront.h" ! 36913: #include <string.h> ! 36914: #include "tree_dump.h" ! 36915: #include "template.h" ! 36916: #include <stdlib.h> ! 36917: #include <ctype.h> ! 36918: #include "hash.h" ! 36919: ! 36920: extern int bound ; // is not mentioned in the header file ! 36921: ! 36922: const int max_string_size = 1024 ; ! 36923: ! 36924: const int default_copy_hash_size = 1000 ; ! 36925: ! 36926: // Save and restore global state around a template instantiation ! 36927: void state::save() { ! 36928: ! 36929: Cdcl = ::Cdcl ; ! 36930: Cstmt = ::Cstmt ; ! 36931: curloc = ::curloc ; ! 36932: ! 36933: curr_file = ::curr_file ; ! 36934: curr_expr = ::curr_expr ; ! 36935: curr_icall = ::curr_icall ; ! 36936: curr_loop = ::curr_loop; ! 36937: curr_block = ::curr_block; ! 36938: curr_switch = ::curr_switch; ! 36939: ! 36940: bound = ::bound ; ! 36941: inline_restr = ::inline_restr ; ! 36942: last_line = ::last_line ; ! 36943: ! 36944: no_of_badcall = ::no_of_badcall; ! 36945: no_of_undcl = ::no_of_undcl ; ! 36946: ! 36947: badcall = ::badcall ; ! 36948: undcl = ::undcl ; ! 36949: } ; ! 36950: ! 36951: ! 36952: void state::restore() { ! 36953: ::Cdcl = Cdcl ; ! 36954: ::Cstmt = Cstmt ; ! 36955: ::curloc = curloc ; ! 36956: ! 36957: ::curr_file = curr_file ; ! 36958: ::curr_expr = curr_expr ; ! 36959: ::curr_icall = curr_icall ; ! 36960: ::curr_loop = curr_loop; ! 36961: ::curr_block = curr_block; ! 36962: ::curr_switch = curr_switch; ! 36963: ! 36964: ::bound = bound ; ! 36965: ::inline_restr = inline_restr ; ! 36966: ::last_line = last_line ; ! 36967: ! 36968: ::no_of_badcall = no_of_badcall; ! 36969: ::no_of_undcl = no_of_undcl ; ! 36970: ! 36971: ::badcall = badcall ; ! 36972: ::undcl = undcl ; ! 36973: } ; ! 36974: ! 36975: ! 36976: void state::init() { ! 36977: ::bound = 0 ; ! 36978: ::inline_restr = 0 ; ! 36979: ::no_of_badcall = ::no_of_undcl = 0 ; ! 36980: ::undcl = ::badcall = NULL ; ! 36981: // lastline needs to be initialized probaly via a call to putline ! 36982: ! 36983: } ! 36984: ! 36985: ! 36986: bit basetype::parametrized_class() ! 36987: { return ((base == COBJ) && ! 36988: Ptclass(Pbase(this)->b_name->tp)->class_base == uninstantiated_template_class) ; ! 36989: } ! 36990: ! 36991: class_type_enum get_class_base (Pbase b) { ! 36992: if (b->base != COBJ) error('i', "badA top ::get_class_type") ; ! 36993: return Ptclass(Pbase(b)->b_name->tp)->class_base ; ! 36994: } ! 36995: ! 36996: Ptclass get_template_class (Pbase b) { ! 36997: class_type_enum t = get_class_base(b) ; ! 36998: ! 36999: if (! ((t == instantiated_template_class) || ! 37000: (t == uninstantiated_template_class))) ! 37001: error ('i', "C is not aYC") ; ! 37002: ! 37003: return Ptclass(Pbase(b)->b_name->tp) ; ! 37004: } ! 37005: ! 37006: ! 37007: Ptempl_inst get_templ_inst(Pbase b) { ! 37008: ! 37009: return (get_template_class(b))->inst ; ! 37010: } ! 37011: ! 37012: ! 37013: bit classdef::parametrized_class() ! 37014: { return (class_base == uninstantiated_template_class) ; ! 37015: } ! 37016: ! 37017: // Predicate to determine whether two classes are indeed the same. cfront ! 37018: // normally relies on pointer identity, however this test is insufficient when ! 37019: // parametrized class instantiationa are involved, since there are potentially ! 37020: // many instances of a COBJ and CLASS for a given instantiation. ! 37021: bit classdef::same_class(Pclass pc) ! 37022: { ! 37023: if (this == pc) return true ; ! 37024: ! 37025: // An intermediate test to compensate for the fact that instantiations do ! 37026: // not cause a copy of the syntax tree to be generated. This kludge should ! 37027: // not be necessary once the template implementation is complete, and tree ! 37028: // copying is implemented. ! 37029: // Later, Sam: tree copying is now implemented, i need to remove the ! 37030: // following two statements and rerun the test suite. ! 37031: ! 37032: if ((this->class_base == template_class) && ! 37033: (pc->class_base == instantiated_template_class) && ! 37034: (Ptclass(pc)->inst->def_basetype()->b_name->tp == this)) ! 37035: return true ; ! 37036: // The inverse symmetric test ! 37037: if ((pc->class_base == template_class) && ! 37038: (this->class_base == instantiated_template_class) && ! 37039: (Ptclass(this)->inst->def_basetype()->b_name->tp == pc)) ! 37040: return true ; ! 37041: ! 37042: // Check whether the templates were determined to be identical after ! 37043: // instantiation. ! 37044: if ((pc->class_base == instantiated_template_class) && ! 37045: (this->class_base == instantiated_template_class) && ! 37046: (Ptclass(this)->inst->same(Ptclass(pc)->inst))) ! 37047: return true ; ! 37048: return false ; ! 37049: } ! 37050: ! 37051: // determine whether two instantiations are identical; the test asumes that ! 37052: // the templates have been instantiated. ! 37053: bool templ_inst::same(Ptempl_inst t) ! 37054: { ! 37055: return ((forward && (forward == t->forward)) || ! 37056: (forward == t) || (t->forward == this)) ? true : false ; ! 37057: } ! 37058: ! 37059: ! 37060: /* Template parsing support */ ! 37061: ! 37062: // The canonical template compilation instance. ! 37063: ! 37064: templ_compilation *templp ; ! 37065: ! 37066: templ_compilation::templ_compilation() ! 37067: { templates = new table(128, NULL, NULL) ; ! 37068: any_type = new basetype(ANY, NULL); ! 37069: PERM(any_type) ; ! 37070: } ! 37071: ! 37072: ! 37073: // determine whether the string corresponds to a tree formal parameter ! 37074: Pname templ_compilation::tree_parameter(char *s) { ! 37075: for (Plist formal = params ; formal ; formal = formal->l) ! 37076: if (strcmp(formal->f->string, s) == 0) { ! 37077: formal->f->n_used++ ; ! 37078: return formal->f ; ! 37079: } ! 37080: return 0 ; ! 37081: } ! 37082: ! 37083: ! 37084: // Determine whether the name refers to the canonical template class during ! 37085: // syntax analysis. ! 37086: Ptempl templ_compilation::is_template(Pname p) { ! 37087: if (p->tp && (p->tp->base == COBJ) && ! 37088: (get_class_base(Pbase(p->tp)) == template_class)) ! 37089: { Pname n = templates->look(p->string, 0) ; ! 37090: return (n ? Ptempl(n->tp) : 0) ; ! 37091: } ! 37092: return 0 ; ! 37093: } ! 37094: ! 37095: ! 37096: // determine whether the string names a template ! 37097: Ptempl templ_compilation::is_template(char *s) { ! 37098: Pname n = templates->look(s,0) ; ! 37099: return (n ? Ptempl(n->tp) : 0) ; ! 37100: } ! 37101: ! 37102: ! 37103: // Set up the environment for parsing a template. This involves setting up a ! 37104: // new nesting level into which the "type type" parameters of the template can ! 37105: // be entered, so that the lexer can find them as TNAMES. The scope is ! 37106: // deallocated by end(). ! 37107: void templ_compilation::start() ! 37108: { templp->in_progress = true ; ! 37109: // Reinitialize the state. ! 37110: params = param_end = NULL ; owner = NULL ; ! 37111: modified_tn = 0 ; // Initialize it here, since ::collect adds new types ! 37112: } ! 37113: ! 37114: ! 37115: ! 37116: // Collect each parameter as it is parsed, and add it to the list of parms. ! 37117: // Validate each parameter to make sure that it is one of the acceptable ! 37118: // types. ! 37119: void templ_compilation::collect(TOK parm_type, Pname n) ! 37120: { ! 37121: switch (parm_type) { ! 37122: case CLASS: ! 37123: // A "type type" parameter, give it the "ANY" type normally used as a ! 37124: // wildcard match internally by the compiler in cases of error. ! 37125: n->tp = new basetype(ANY, 0); ! 37126: n = n->tdef() ; // Set it up to be a typedef. ! 37127: n->lex_level = bl_level + 1 ; // Inner scope, so restore() can hack it ! 37128: n->n_template_arg = template_type_formal ; ! 37129: PERM(n) ; PERM(n->tp) ; ! 37130: break ; ! 37131: case STATEMENT: ! 37132: case EXPRESSION: ! 37133: // the argument is a post-syntax expression tree ! 37134: n->n_template_arg = ! 37135: ((parm_type == EXPRESSION) ? ! 37136: template_expr_tree_formal : template_stmt_tree_formal) ; ! 37137: // canonical any_type is ok here ! 37138: n->tp = any_type ; ! 37139: PERM(n) ; ! 37140: break ; ! 37141: default: ! 37142: error("theZT for%n must be CLASS, not %k", n,parm_type); ! 37143: } ! 37144: append_parameter(n) ; ! 37145: } ! 37146: ! 37147: // append the "non-type" parameter to the end of the list ! 37148: void templ_compilation::append_parameter(Pname n) ! 37149: { ! 37150: if (params){ ! 37151: param_end->l = new name_list(n, NULL) ; ! 37152: param_end = param_end->l ; ! 37153: }else params = param_end = new name_list(n, NULL) ; ! 37154: PERM(n) ; PERM(n->tp) ; ! 37155: } ! 37156: ! 37157: ! 37158: // collect non "type type" parameters. The tp field of the name ! 37159: // indicates the type of the formal parameter. ! 37160: void templ_compilation::collect(Pname n) ! 37161: { ! 37162: // The grammar alone should be sufficient to protect against undesirable ! 37163: // types. Any additional checks go here. ! 37164: n->n_template_arg = template_expr_formal ; ! 37165: append_parameter(n) ; ! 37166: } ! 37167: ! 37168: ! 37169: ! 37170: // validate the type for a non-type formal, and make it a const. ! 37171: static void check_non_type_formal(Pname n) { ! 37172: ! 37173: switch (n->tp->base) { ! 37174: case ZTYPE: ! 37175: case CHAR: ! 37176: case SHORT: ! 37177: case INT: ! 37178: case LONG: ! 37179: case FLOAT: ! 37180: case DOUBLE: ! 37181: case FIELD: ! 37182: case EOBJ: ! 37183: case COBJ: ! 37184: case TYPE: ! 37185: case ANY: ! 37186: { // a basetype node ! 37187: TOK bad_base = 0 ; ! 37188: ! 37189: if (Pbase(n->tp)->b_volatile) ! 37190: bad_base = VOLATILE ; ! 37191: if (Pbase(n->tp)->b_typedef) ! 37192: bad_base = TYPEDEF ; ! 37193: if (Pbase(n->tp)->b_inline) ! 37194: bad_base = INLINE ; ! 37195: if (Pbase(n->tp)->b_virtual) ! 37196: bad_base = VIRTUAL ; ! 37197: if (bad_base) ! 37198: error ("bad %k declarator forY formal %n", bad_base,n); ! 37199: ! 37200: Pbase b = new basetype(0, 0) ; ! 37201: *b= *Pbase(n->tp) ; ! 37202: b->b_const = 1 ; ! 37203: n->tp = b ; ! 37204: break ; ! 37205: } ! 37206: case PTR: ! 37207: { Pptr b = new ptr(0,0) ; ! 37208: *b = *Pptr(n->tp) ; ! 37209: ! 37210: b->rdo = 1; ! 37211: n->tp = b ; ! 37212: break ; ! 37213: } ! 37214: case RPTR: ! 37215: case VEC: ! 37216: break; // constant by definition ! 37217: default: ! 37218: error ("badZT %t for formalZ %n", n->tp, n); ! 37219: } ! 37220: return ; ! 37221: } ! 37222: ! 37223: ! 37224: ! 37225: // The template parameters if any, have been parsed. Member function templates ! 37226: // may choose to default their template arguments to the class arguments, if ! 37227: // so, make the defaulting happen. ! 37228: void templ_compilation::enter_parameters() ! 37229: { ! 37230: for (Plist list = params ; list ; list = list->l) { ! 37231: Pname n = list->f ; ! 37232: switch(n->n_template_arg) { ! 37233: case template_type_formal: ! 37234: // Set them up for restoration ! 37235: modified_tn = new name_list(n,modified_tn); ! 37236: // Bring the names out of hiding ! 37237: n->n_key = 0 ; ! 37238: break ; ! 37239: case template_expr_formal: ! 37240: check_non_type_formal(n) ; ! 37241: n->tp->dcl(gtbl) ; ! 37242: break ; ! 37243: case template_expr_tree_formal: ! 37244: case template_stmt_tree_formal: ! 37245: // simply note it, the guts of the processing takes place when the ! 37246: // copy of the syntax tree is generated. ! 37247: break ; ! 37248: default: ! 37249: error ('i', "badY formal" ) ; ! 37250: } ! 37251: } ! 37252: // Save away the list of modified_tn, since the body processing will clobber ! 37253: // it. ! 37254: param_tn = modified_tn ; ! 37255: modified_tn = 0 ; ! 37256: } ! 37257: ! 37258: ! 37259: ! 37260: // Resolve the forward declaration of a template to its true definition. The ! 37261: // template and class type data structures must be reused, since there may be ! 37262: // outstanding references to them. ! 37263: void templ::resolve_forward_decl(Plist params, Pclass c) { ! 37264: check_formals(params) ; ! 37265: formals = params ; ! 37266: defined = true ; ! 37267: definition_number = ++ definition_tick ; ! 37268: members = c->mem_list ; ! 37269: } ! 37270: ! 37271: void templ::instantiate_forward_decl() { ! 37272: for (Ptempl_inst i = insts ; i ; i = i->next) ! 37273: if (Ptclass(Pbase(i->tname->tp)->b_name->tp)->class_base == ! 37274: instantiated_template_class && ! 37275: ! i->forward) ! 37276: { // reinstantiate it ! 37277: i->instantiate(true) ; ! 37278: } ! 37279: } ! 37280: ! 37281: ! 37282: ! 37283: // verify thet the qualifier used to declare the member function matches the ! 37284: // template arguments in name, ie. ! 37285: // template <class P, class Q, ..> c<P,Q,..>::member_function() {} ! 37286: // match it's Ps and Qs. ! 37287: bool templ_inst::check_qualifier(Plist formals) ! 37288: { ! 37289: Pexpr actual = actuals ; ! 37290: for (Plist formal = formals ; formal && actual ; formal = formal->l, ! 37291: actual = actual->e2) ! 37292: ! 37293: switch (formal->f->n_template_arg) { ! 37294: ! 37295: case template_type_formal: ! 37296: { Pbase b = Pbase(actual->e1->tp) ; ! 37297: ! 37298: if (! ((b->base == TYPE) && ! 37299: (b->b_name->base == TNAME) && ! 37300: (strcmp (Pname(b->b_name)->string, formal->f->string) == 0))) ! 37301: return false ; ! 37302: break ; ! 37303: } ! 37304: ! 37305: case template_expr_formal: ! 37306: if (! ((actual->e1->base == NAME) && ! 37307: (strcmp(Pname(actual->e1)->string, formal->f->string) == 0))) ! 37308: return false ; ! 37309: break ; ! 37310: ! 37311: case template_expr_tree_formal: ! 37312: case template_stmt_tree_formal: ! 37313: default: ! 37314: error ('i',"badY formal") ; ! 37315: } ! 37316: ! 37317: return true ; ! 37318: } ! 37319: ! 37320: ! 37321: // make the class template visible when compiling the template class ! 37322: // defintion, so that it can be refernced while compiling the class body. ! 37323: void templ_compilation::introduce_class_templ(Pname namep) ! 37324: { ! 37325: owner = is_template(namep) ; ! 37326: // create a template definition if one did not already exist, due to a ! 37327: // forward declaration ! 37328: if (!owner){ ! 37329: owner = new templ(params, namep) ; ! 37330: Pname lookup_name = templp->templates->insert(new name(namep->string), 0); ! 37331: lookup_name->tp = Ptype(owner) ; // lie, to permit use of the table ! 37332: } ! 37333: } ! 37334: ! 37335: ! 37336: // The body of the template has been parsed. Finish the definition of the ! 37337: // template class. ! 37338: void templ_compilation::end(Pname p) ! 37339: { ! 37340: bool forward_definition = false ; ! 37341: // Restore the name environment to the state before the template parameters ! 37342: // were processed. ! 37343: modified_tn = param_tn ; ! 37344: restore() ; ! 37345: modified_tn = 0 ; ! 37346: ! 37347: if (curr_tree_template) { ! 37348: // create an expression template ! 37349: new tree_template(curr_tree_template, ! 37350: p->string, params, p->n_initializer, templ_refs) ; ! 37351: }else { ! 37352: if (!p->tp) { ! 37353: error ("aC, orMF definition wasX") ; ! 37354: return ; ! 37355: } ! 37356: switch(p->tp->base){ ! 37357: ! 37358: case CLASS: ! 37359: // Create the template type to represent the parsed template, and enter it ! 37360: // into the global table. This is achieved simply by modifying the TNAME ! 37361: // that was entered into ktbl to represent the class definition. ! 37362: Pname namep = ktbl->look(p->string, 0) ; ! 37363: ! 37364: // check for nested definitions, they aren't supported currently. 2.1 is ! 37365: // a good time to start supporting them, since they are nested for real. ! 37366: for (Pname nn = Pclass(p->tp)->mem_list ; nn ; nn = nn->n_list) ! 37367: switch (nn->base) { ! 37368: case NAME: ! 37369: switch(nn->tp->base) { ! 37370: case CLASS: ! 37371: error("CD %s not permitted within a ZizedC", nn->string) ; ! 37372: break ; ! 37373: case ENUM: ! 37374: error("enumD %s not permitted within a ZizedC", nn->string) ; ! 37375: break ; ! 37376: } ! 37377: break ; ! 37378: ! 37379: case TNAME: ! 37380: error("typedef %s not permitted within a ZizedC", nn->string) ; ! 37381: break ; ! 37382: } ! 37383: ! 37384: owner = is_template(namep); ! 37385: if (owner) { ! 37386: Pclass c = Pclass(owner->basetype()->b_name->tp) ; ! 37387: // ignore it, if it is a forward declaration following a real ! 37388: // definition ! 37389: if (owner->defined && (Pclass(p->tp)->mem_list != owner->members)) ! 37390: error("YC %s multiply defined", p->string) ; ! 37391: ! 37392: forward_definition=bool((c->defined & DEF_SEEN) && (!owner->defined)); ! 37393: if (forward_definition) owner->resolve_forward_decl(params, c) ; ! 37394: }else ! 37395: // a forward declaration ! 37396: introduce_class_templ(namep) ; ! 37397: ! 37398: if (templ_refs) owner->templ_refs = templ_refs ; ! 37399: break ; ! 37400: ! 37401: case FCT: ! 37402: { Pname qual = p->n_qualifier ; ! 37403: // the function must belong to a declared template class ! 37404: if (! qual) { ! 37405: error('s', "onlyYMFs may beZized currently") ; ! 37406: return ; ! 37407: } ! 37408: if (qual->tp && (qual->tp->base == COBJ)) ! 37409: switch (get_class_base(Pbase(qual->tp))) { ! 37410: case uninstantiated_template_class: ! 37411: owner = Ptclass(Pbase(qual->tp)->b_name->tp)->inst->def ; ! 37412: // verify that the formals specified, match the template formals ! 37413: // in name, note that the length was already matched when the ! 37414: // instantiation was generated. ! 37415: if (!get_template_class ! 37416: (Pbase(qual->tp))->inst->check_qualifier(params)) ! 37417: error ("QrZs must match theY formals") ; ! 37418: break ; ! 37419: case template_class: ! 37420: // the template reference was without any of the formals ! 37421: owner = is_template(qual) ; ! 37422: if (! owner->has_tree_expr_formals()) ! 37423: error('w',"Qr %n for %n must specifyYZs", qual, p) ; ! 37424: break ; ! 37425: default: ! 37426: error ("Qr %n for %n wasn't aYC", qual, p) ; ! 37427: return ; ! 37428: } ! 37429: Pfunt ft= owner->collect_function_member(p) ; ! 37430: if (! Pfct(p->tp)->body) ! 37431: error ("theYFM %n must have a body", p) ; ! 37432: ft->templ_refs = templ_refs ; ! 37433: ft->formals = params ; ! 37434: owner->check_formals(params) ; ! 37435: break ; ! 37436: } ! 37437: default: error ("C, or MF definitionX.") ; ! 37438: } ! 37439: } ! 37440: // Note the template references from this definition ! 37441: ! 37442: clear_ref_templ() ; ! 37443: param_end = params = 0; // Indicates the end of template processing. ! 37444: curr_tree_template = 0 ; ! 37445: ! 37446: if (forward_definition) owner->instantiate_forward_decl() ; ! 37447: owner = 0 ; ! 37448: } ! 37449: ! 37450: ! 37451: ! 37452: ! 37453: // Clear the list of templates referenced during the syntax analysis of a top ! 37454: // level definition. Note that since this list is produced during syntax ! 37455: // analysis, it does not recognize instantiations that may actualy turn out to ! 37456: // be identical at instantiation after the substitution of actual parameters. ! 37457: // Thus, the list may be longer than it would be after actual argument ! 37458: // substitution. ! 37459: void templ_compilation::clear_ref_templ() { ! 37460: for (Pcons p = templ_refs ; p ; p = p->cdr) ! 37461: Ptempl_inst(p->car)->refp = false ; ! 37462: templ_refs = 0 ; last_cons = 0 ; ! 37463: } ! 37464: ! 37465: ! 37466: // Instantiate templates that were referenced by a non-template definition, ! 37467: // after syntax analysis has been completed on it. ! 37468: void templ_compilation::instantiate_ref_templ() { ! 37469: for (Pcons p = templ_refs ; p ; p = p->cdr) ! 37470: Ptempl_inst(p->car)->instantiate() ; ! 37471: clear_ref_templ() ; ! 37472: } ! 37473: ! 37474: ! 37475: ! 37476: ! 37477: // Compile all template member body instantiations. Set in motion the ! 37478: // compilation of the graph of instantiation bodies. Note that compilation of ! 37479: // a body may in turn initiate the instantiation of templates that had not ! 37480: // previously been instantiated. ! 37481: void templ_compilation::end_of_compilation() { ! 37482: bool change = false ; ! 37483: do { ! 37484: change = false ; ! 37485: for (Ptempl p = list ; p ; p = p->next) ! 37486: change = ( change | p->instantiate_bodies() ? true : false); ! 37487: } while (change) ; ! 37488: } ! 37489: ! 37490: ! 37491: // A predicate to validate that a tname without template parameters is legit ! 37492: // in the scope, ie. that it does not need actual template arguments. ! 37493: // Currently, a tname without parameters is ok within the class definition, ! 37494: // but parameters are required within the member definition. They should not ! 37495: // be required within the member function either to be consonance with their ! 37496: // use in the class definition. ! 37497: Pname templ_compilation::check_tname(Pname p) { ! 37498: Ptempl t = is_template(p) ; ! 37499: ! 37500: if (p->n_template_arg) p->n_used++ ; ! 37501: if (!t) return p ; ! 37502: if (in_progress && ((owner && (owner->namep == p)) || ! 37503: (!owner && t->basetype()->b_name->tp == ccl))) ! 37504: return p ; ! 37505: error ("%n needs Y instantiationAs.", p) ; ! 37506: return p ; ! 37507: } ! 37508: ! 37509: ! 37510: // This function determine when the parameters specified to a template are ! 37511: // redundant, and really refer to the current template class. Thus, ! 37512: // ! 37513: // template c<class p1, class p2> c<p1,p2>::foo { ... } ; ! 37514: // has the redundant template specification c<p1, p2> and can simply be a ! 37515: // reference to a "c" instead, ! 37516: bool templ_compilation::current_template(Pname p, Pexpr actuals) { ! 37517: if (in_progress && ! 37518: ((owner && (owner->namep == p)) || ! 37519: (!owner && ((p->tp->base == COBJ) && ! 37520: (Pbase(p->tp)->b_name->tp == ccl))))) ! 37521: { // Check whether the formal and actual types are identical ! 37522: Pexpr actual = actuals; ! 37523: for (Plist formal = params ; formal && actual ; formal = formal->l, ! 37524: actual = actual->e2) ! 37525: if ((formal->f->tp == actual->e1->tp) || ! 37526: ((actual->e1->tp && (actual->e1->tp->base == TYPE)) && ! 37527: (Pbase(actual->e1->tp)->b_name->tp == formal->f->tp))) ! 37528: continue ; ! 37529: else break ; ! 37530: if (!formal && !actual) return true ; ! 37531: } ! 37532: return false ; ! 37533: } ! 37534: ! 37535: ! 37536: ! 37537: // Add a new member function to the list of functions for the template class. ! 37538: Pfunt templ::collect_function_member(Pname fname) { ! 37539: PERM(fname) ; PERM(fname->tp) ; PERM(Pfct(fname->tp)->body) ; ! 37540: return new function_template (*this, templp->params, fname) ; ! 37541: } ! 37542: ! 37543: ! 37544: // Check the formals specified for a member function or a forward definition ! 37545: // of a class, against the formals for the class. ! 37546: void basic_template::check_formals(Plist f2) { ! 37547: ! 37548: for (Plist f1 = formals; f1 && f2 ; f1 = f1->l, f2 = f2->l) ! 37549: if (f1->f->base != f2->f->base) ! 37550: switch (f1->f->n_template_arg) { ! 37551: case template_type_formal: ! 37552: error ("Y formalZ mismatch,\ ! 37553: %n must be a type formal parameter.", f2->f) ; ! 37554: break ; ! 37555: case template_expr_formal: ! 37556: error ("formalZ mismatch, %n must be aZ ofT %t", ! 37557: f2->f, f2->f->tp) ; ! 37558: break ; ! 37559: case template_expr_tree_formal: ! 37560: case template_stmt_tree_formal: ! 37561: error ("formalZ mismatch, %n must be anE formalZ", ! 37562: f2->f) ; ! 37563: break ; ! 37564: default: ! 37565: error ("formalZ mismatch betweenC formal: %n andM formal: %n", f1->f, f2->f) ; ! 37566: }else if (f1->f->n_template_arg == template_expr_formal) { ! 37567: // the types should be identical ! 37568: if (f1->f->tp->check(f2->f->tp, 0) == 1) ! 37569: error ("type mismatch betweenM formal %n, andC formal %n", f2->f, f1->f) ; ! 37570: } ! 37571: if (f1) ! 37572: error ("insufficient formalZs,CZ parameter %n onwards are missing", f1->f) ; ! 37573: if (f2) ! 37574: error ("excess formalZs,Z %n onwards not defined forC", f2->f) ; ! 37575: ! 37576: } ! 37577: ! 37578: // predicate to determine whether the template has expression tree formals ! 37579: bool templ::has_tree_expr_formals() { ! 37580: ! 37581: for (Plist formal= formals; formal ; formal = formal->l) ! 37582: if (formal->f->n_template_arg == template_expr_tree_formal) ! 37583: return true ; ! 37584: ! 37585: return false ; ! 37586: } ! 37587: ! 37588: ! 37589: // Check that those formals that require class actual arguments, due to their ! 37590: // use in member function bodies get them. ! 37591: bool basic_template::check_constraints(Pexpr actual) ! 37592: ! 37593: { ! 37594: bool ret = true ; ! 37595: ! 37596: for (Plist formal = formals ; formal && actual ; formal = formal->l, ! 37597: actual = actual->e2) ! 37598: if ((formal->f->n_template_arg == template_type_formal) && ! 37599: formal->f->n_template_formal_must_be_class) { ! 37600: ! 37601: Pname n = Pname(actual->e1) ; ! 37602: ! 37603: if (n && n->tp && n->tp->is_cl_obj()) ! 37604: continue ; ! 37605: error("expected aCT actual, not %t, for the \"TT\" formal %s", ! 37606: n->tp, formal->f->string); ! 37607: ret = false ; ! 37608: } ! 37609: return ret ; ! 37610: } ! 37611: ! 37612: ! 37613: // Check actual template arguments, against the formals. ! 37614: bool templ::check_actual_args(Pexpr actual) ! 37615: { ! 37616: for (Plist formal = formals ; formal && actual ; formal = formal->l, ! 37617: actual = actual->e2) ! 37618: switch (formal->f->n_template_arg) { ! 37619: case template_type_formal: ! 37620: { ! 37621: // A "type type" parameter, any actual type that was accepted by the ! 37622: // parse is acceptable here, just make sure that it is indeed a type. ! 37623: // If it was parsed as a type, the grammar should have created a name ! 37624: // node, and attached the type to it, having marked the name as a ! 37625: // template_actual_arg_dummy. ! 37626: ! 37627: Pname n = Pname(actual->e1) ; ! 37628: ! 37629: if (!((n->base == NAME) && ! 37630: (n->n_template_arg == template_actual_arg_dummy))) { ! 37631: error ("Y %s A mismatch, the Y formal:%n\ ! 37632: required aT actualZ.", namep->string, formal->f) ; ! 37633: // recover from the error with a safe expression ! 37634: n = new name("") ; ! 37635: n->tp = any_type ; ! 37636: actual->e1 = n ; ! 37637: } ! 37638: if ((formal->f->n_template_formal_must_be_class) && ! 37639: !(n->tp && n->tp->is_cl_obj())) ! 37640: error("expected aCT actual, not %t, for the \"TT\" formal %s", ! 37641: n->tp, formal->f->string) ; ! 37642: break ; ! 37643: } ! 37644: case template_expr_formal: ! 37645: // checking can only be done at instantiation, so postpone it ! 37646: break ; ! 37647: case template_expr_tree_formal: ! 37648: case template_stmt_tree_formal: ! 37649: // anything is acceptable, it is a case of "implementor beware". Any ! 37650: // illegalities will only be detected when dcl processing takes place. ! 37651: break ; ! 37652: default: ! 37653: error ('i',"badY formal") ; ! 37654: } ! 37655: // If we provide for optionals, this is where the processing should get done. ! 37656: if (formal) ! 37657: error ("too fewAs supplied forY %s", namep->string) ; ! 37658: if (actual && actual->e1) { ! 37659: error ("too manyAs supplied forY %s", namep->string) ; ! 37660: } ! 37661: return bool(~(formal || actual)) ; ! 37662: } ! 37663: ! 37664: ! 37665: ! 37666: ! 37667: // Append to the list of references. ! 37668: void templ_compilation::append_ref(Ptempl_inst ref) ! 37669: { cons *p = new cons(ref,0) ; ! 37670: if (last_cons) ! 37671: last_cons->cdr = p ; ! 37672: else templ_refs = p ; ! 37673: last_cons = p ; ! 37674: } ; ! 37675: ! 37676: ! 37677: // Note the reference by a definition to the template, so that the template ! 37678: // can be instantiated before the definition is processed. ! 37679: Ptempl_inst templ_inst::note_ref() ! 37680: { if ((! refp)) { ! 37681: refp = true ; ! 37682: templp->append_ref(this) ; ! 37683: } ! 37684: return this ; ! 37685: } ! 37686: ! 37687: ! 37688: ! 37689: // Get an instantiation for the template with the given set of actuals. If one ! 37690: // exists, return it, otherwise create a new one. ! 37691: Ptempl_inst templ::get_inst(Pexpr actuals, Ptempl_inst exclude) ! 37692: { Ptempl_inst inst = get_match(actuals, exclude, false) ; ! 37693: ! 37694: return (inst ? inst : new templ_inst(actuals, this))->note_ref() ; ! 37695: } ! 37696: ! 37697: ! 37698: // Find an instantiation that has the same set of actuals, exclude the ! 37699: // instantaition passed in from the set of candidates ! 37700: Ptempl_inst templ::get_match(Pexpr actuals, ! 37701: Ptempl_inst exclude, // don't match this one ! 37702: // Only instantiated templates match ! 37703: bool match_instantiated_only) ! 37704: { ! 37705: for (Ptempl_inst p = insts ; p ; p = p->next) ! 37706: if ((p != exclude) && ! 37707: (p->actuals_match(actuals)) && ! 37708: (match_instantiated_only ? ! 37709: (Pclass(Pbase(p->tname->tp)->b_name->tp)->class_base == ! 37710: instantiated_template_class) ! 37711: : true)) ! 37712: return (p->forward ? p->forward : p) ; ! 37713: return NULL ; ! 37714: } ! 37715: ! 37716: ! 37717: // provides the basetype created for a given set of actuals. ! 37718: Pbase templ::inst_basetype(Pexpr actuals) ! 37719: { ! 37720: return (check_actual_args(actuals) ? ! 37721: Pbase(get_inst(actuals)->tname->tp) : basep) ; ! 37722: } ! 37723: ! 37724: ! 37725: // Validate that the name denotes a parametrized type, and prodouce a TNAME ! 37726: // for the instantiation. ! 37727: Pname parametrized_typename (Pname p, Pexpr actuals) ! 37728: { ! 37729: Ptempl t = templp->is_template(p) ; ! 37730: // A template instantiation with redundant actuals identical to the formals ! 37731: // of the current template ! 37732: if (templp->current_template(p, actuals)) return p ; ! 37733: if (t) { ! 37734: Pname tname = t->typename(actuals) ; ! 37735: return (tname ? tname : p) ; ! 37736: } ! 37737: error ("%n hasTAs but is not aZizedC", p) ; ! 37738: return p ; ! 37739: } ! 37740: ! 37741: ! 37742: Pbase parametrized_basetype (Pname p, Pexpr actuals) ! 37743: { Ptempl t = templp->is_template(p) ; ! 37744: // A template instantiation with redundant actuals identical to the formals ! 37745: // of the current template ! 37746: if (templp->current_template(p, actuals)) return Pbase(p->tp) ; ! 37747: if (t) return t->inst_basetype(actuals) ; ! 37748: error ("%n is not aZizedC", p) ; ! 37749: return new basetype(TYPE, p); ! 37750: } ! 37751: ! 37752: ! 37753: // Similar primitive for obtaining the typename associated with an ! 37754: // instantiation. ! 37755: Pname templ::typename(Pexpr actuals) ! 37756: { ! 37757: return (check_actual_args(actuals) ? get_inst(actuals)->tname : 0) ; ! 37758: } ! 37759: ! 37760: // predicate to get past all the type nodes ! 37761: static Ptype real_type (Ptype t) ! 37762: { ! 37763: while (t->base == TYPE) t = Pbase(t)->b_name->tp ; ! 37764: return t ; ! 37765: } ! 37766: ! 37767: static int expr_match(Pexpr a1, Pexpr a2) ; ! 37768: ! 37769: // Check whether the actuals provided match the actuals for this instantiation. ! 37770: // The actuals match the formals, iff they are the same type or parametrized ! 37771: // type. ! 37772: bool templ_inst::actuals_match(Pexpr check_actuals) ! 37773: { Pexpr ae1, ae2 ; // the cons cells ! 37774: Plist formal = def->formals ; ! 37775: ! 37776: // The lists should be the same length, since check_actuals will have taken ! 37777: // appropriate action. ! 37778: for (ae1=actuals, ae2=check_actuals ; formal && ae1 && ae2 ; ! 37779: ae1=ae1->e2, ae2=ae2->e2, formal = formal->l) ! 37780: ! 37781: switch (formal->f->n_template_arg) { ! 37782: ! 37783: case template_type_formal: ! 37784: { Ptype t1 = ae1->e1->tp, t2 = ae2->e1->tp ; ! 37785: if (t1->check(t2,255) == 1) ! 37786: return false ; ! 37787: break ; ! 37788: } ! 37789: case template_expr_formal: ! 37790: if (! expr_match(ae1->e1, ae2->e1)) return false ; ! 37791: break ; ! 37792: ! 37793: case template_expr_tree_formal: ! 37794: case template_stmt_tree_formal: ! 37795: // these are internal instantiations and consequently never match ! 37796: return false ; ! 37797: ! 37798: default: ! 37799: error ('i', "bad template formal") ; ! 37800: } ! 37801: return true ; ! 37802: } ! 37803: ! 37804: ! 37805: extern char emode ; ! 37806: ! 37807: ! 37808: // This set of overloaded fuctions are used to accumulate name strings ! 37809: void stradd(char *&target, char *source) { ! 37810: while (*target++ = *source++) ; ! 37811: target-- ; ! 37812: } ! 37813: ! 37814: void stradd(char *&p, long i) { ! 37815: if (!emode) { ! 37816: *p++ = 'L' ; ! 37817: } ! 37818: char s[16] ; ! 37819: ! 37820: sprintf(s,"%ld", i) ; ! 37821: stradd(p,s) ; ! 37822: } ! 37823: ! 37824: void stradd(char *&p, Pname n) { ! 37825: if (!emode){ ! 37826: char s[256] ; ! 37827: ! 37828: sprintf(s,"%d", strlen(n->string)) ; ! 37829: stradd(p,s) ; ! 37830: } ! 37831: stradd(p, n->string) ; ! 37832: } ! 37833: ! 37834: ! 37835: ! 37836: // produce a unique string suitable for use within a name; if in emode ie. ! 37837: // printing in the context of an error, print a pretty name instead. ! 37838: char * mangled_expr(char *p, Pexpr e, bool mangle_for_address = false) ! 37839: { ! 37840: static int mangle_address = 0 ; ! 37841: if (e == 0) return p; ! 37842: ! 37843: switch (e->base) { ! 37844: case ADDROF: ! 37845: case G_ADDROF: ! 37846: // unary using e2 ! 37847: // rely on the ! 37848: mangle_address++ ; ! 37849: p = mangled_expr(p, e->e2) ; ! 37850: mangle_address -- ; ! 37851: break ; ! 37852: ! 37853: case NAME: ! 37854: if (mangle_address || mangle_for_address) ! 37855: stradd(p, Pname(e)) ; ! 37856: else if (Pname(e)->n_evaluated) ! 37857: stradd(p, Pname(e)->n_val) ; ! 37858: else if (Pname(e)->n_initializer) ! 37859: p = mangled_expr(p, Pname(e)->n_initializer, mangle_for_address) ; ! 37860: else error ('i', "couldn't mangle %n", e) ; ! 37861: break ; ! 37862: ! 37863: case IVAL: ! 37864: stradd(p, ((ival *)e)->i1) ; ! 37865: break ; ! 37866: ! 37867: case CAST: ! 37868: { // an IVAL hiding below the cast ? ! 37869: if (e->e1->base == IVAL) ! 37870: stradd(p, ((ival *)e->e1)->i1) ; ! 37871: else error ('i', "unexpected cast") ; ! 37872: break ; ! 37873: } ! 37874: case ICON: ! 37875: case CCON: ! 37876: case FCON: ! 37877: *p++ = 'L' ; ! 37878: strcpy(p, e->string) ; ! 37879: // Sam: there needs to be a better encoding scheme, but it can wait. ! 37880: if (!emode) ! 37881: while (*p) ! 37882: if (! (isalnum(*p))) ! 37883: switch(*p) { ! 37884: case '+': ! 37885: *p++ = 'p' ; ! 37886: break ; ! 37887: ! 37888: case '-': ! 37889: *p++ = 'm' ; ! 37890: break ; ! 37891: ! 37892: case '.': ! 37893: *p++ = 'D' ; ! 37894: break ; ! 37895: ! 37896: case 'e': ! 37897: *p++ = 'E' ; ! 37898: break ; ! 37899: ! 37900: default: ! 37901: error ('i', "bad character in constant") ; ! 37902: break ; ! 37903: } else p++ ; ! 37904: break ; ! 37905: ! 37906: case ZERO: ! 37907: *p++ = '0' ; ! 37908: break ; ! 37909: ! 37910: default: ! 37911: error ('i', "can't mangle %k", e->base) ; ! 37912: } ! 37913: return p ; ! 37914: } ! 37915: ! 37916: // this function is invoked once at the top level ! 37917: char *mangled_expr(char *p, Pname n) { ! 37918: if (n->n_evaluated) { ! 37919: stradd(p, n->n_val) ; ! 37920: return p ; ! 37921: } ! 37922: return mangled_expr(p, n->n_initializer, ! 37923: (real_type(n->tp)->base == PTR ? true : false)) ; ! 37924: } ! 37925: ! 37926: // Generate a template instantiation name suitable for printing when it is ! 37927: // presented to the user. ! 37928: void templ_inst::print_pretty_name() ! 37929: { ! 37930: extern char emode ; ! 37931: ! 37932: fprintf(out_file, " %s<", (def->namep ? def->namep->string : "?")) ; ! 37933: Plist formal = inst_formals ; ! 37934: emode ++ ; // so that dcl_print generates c++ rather than c names ! 37935: ! 37936: for (Pexpr ae1=actuals; formal && ae1 ; ae1=ae1->e2, formal = formal->l) { ! 37937: switch (formal->f->n_template_arg) { ! 37938: case template_type_formal: ! 37939: ae1->e1->tp->dcl_print(0) ; ! 37940: break ; ! 37941: case template_expr_formal: ! 37942: { char buff[256] ; ! 37943: ! 37944: mangled_expr(buff, ae1->e1) ; ! 37945: fprintf(out_file, "%s", buff) ; ! 37946: break ; ! 37947: } ! 37948: case template_expr_tree_formal: ! 37949: case template_stmt_tree_formal: ! 37950: // doesn't participate in the name generation ! 37951: break ; ! 37952: default: ! 37953: error ('i', "unexpected formal") ; ! 37954: } ! 37955: ! 37956: // this comma is unfortunately misplaced, since it follows a space printed ! 37957: // out by dcl_print ! 37958: if (formal->l) fprintf(out_file, ", ") ; ! 37959: } ! 37960: fprintf(out_file, ">") ; ! 37961: emode -- ; ! 37962: } ! 37963: ! 37964: ! 37965: ! 37966: // there are different representations for ICON based upon whether it has been ! 37967: // evaluated. ! 37968: int check_for_const(Pexpr a1, Pexpr a2) { ! 37969: Neval = 0 ; ! 37970: if ((a1->base == NAME) && ! 37971: ((a2->base == ICON) || (a2->base == IVAL) || (a2->base == ZERO))) ! 37972: { Pname n = Pname(a1) ; ! 37973: return (n->n_evaluated && (n->n_val == a2->eval())) ; ! 37974: }else if (((a1->base == ICON) || (a1->base == IVAL) || (a1->base == ZERO)) ! 37975: && (a2->base == NAME)) ! 37976: { Pname n = Pname(a2) ; ! 37977: return (n->n_evaluated && (n->n_val == a1->eval())) ; ! 37978: } ! 37979: return false ; ! 37980: } ! 37981: ! 37982: ! 37983: // get past the template parameter names to get the the real expression ! 37984: static Pexpr real_expression(Pexpr e) ! 37985: { ! 37986: while (e && (e->base == NAME) && ! 37987: (Pname(e)->n_template_arg == template_expr_formal) && ! 37988: (! Pname(e)->n_evaluated) && Pname(e)->n_initializer) ! 37989: e = Pname(e)->n_initializer ; ! 37990: return e ; ! 37991: } ! 37992: ! 37993: ! 37994: // determine whether two expressions supplied as actual arguments to ! 37995: // a "template_expr_formal" formal argument match. ! 37996: static int expr_match(Pexpr a1, Pexpr a2) ! 37997: { ! 37998: static int addr_of = 0 ; ! 37999: ! 38000: a1 = (addr_of ? a1 : real_expression(a1)) ; ! 38001: a2 = (addr_of ? a2 : real_expression(a2)) ; ! 38002: ! 38003: if (a1 == a2) return true; ! 38004: ! 38005: // ! 38006: if (a1->base != a2->base) return check_for_const(a1, a2) ; ! 38007: ! 38008: switch (a1->base) { ! 38009: case QUEST: ! 38010: // a ternary operator ! 38011: return ( expr_match(a1->cond, a2->cond) && ! 38012: expr_match(a1->e1, a2->e1) && ! 38013: expr_match(a1->e2, a2->e2)) ; ! 38014: ! 38015: case PLUS: case MINUS: case MUL: case DIV: case MOD: ! 38016: case ER: case OR: case ANDAND: case OROR: ! 38017: case LS: case RS: ! 38018: case EQ: case NE: case LT: case LE: case GT: case GE: ! 38019: // binary operator ! 38020: return (expr_match(a1->e1, a2->e1) && ! 38021: expr_match(a1->e2, a2->e2)) ; ! 38022: case UMINUS: case UPLUS: ! 38023: case NOT: case COMPL: ! 38024: return (expr_match(a1->e2, a2->e2)) ; ! 38025: case ADDROF: ! 38026: { ! 38027: // unary using e2 ! 38028: addr_of ++ ; ! 38029: int result = (expr_match(a1->e2, a2->e2)) ; ! 38030: addr_of -- ; ! 38031: return result ; ! 38032: } ! 38033: case CAST: ! 38034: return (expr_match(a1->e1, a2->e1)) ; ! 38035: case NAME: ! 38036: if (! addr_of) { ! 38037: Pname n1 = Pname(a1), n2 = Pname(a2) ; ! 38038: ! 38039: if ((n1->n_evaluated) && n2->n_evaluated && (n1->n_val == n2->n_val)) ! 38040: return true ; ! 38041: if (n1->n_initializer && (! n2->n_initializer)) ! 38042: return check_for_const(n2, n1->n_initializer) ; ! 38043: if (n2->n_initializer && (! n1->n_initializer)) ! 38044: return check_for_const(n1, n2->n_initializer) ; ! 38045: if (n1->n_initializer && n2->n_initializer) ! 38046: return expr_match(n1->n_initializer, n2->n_initializer) ; ! 38047: } ! 38048: return false ; ! 38049: case DOT: ! 38050: return (expr_match(a1->e1, a2->e1)) ; ! 38051: case REF: ! 38052: return (expr_match(a1->e1, a2->e1)) ; ! 38053: case IVAL: ! 38054: return (ival *)a1->i1 == (ival *)a2->i1 ; ! 38055: case ICON: ! 38056: case CCON: ! 38057: case FCON: ! 38058: case STRING: ! 38059: return (strcmp (a1->string, a2->string) == 0) ; ! 38060: case ZERO: ! 38061: return true ; ! 38062: case SIZEOF: ! 38063: { long l1 = a1->eval(), l2 = a2->eval() ; ! 38064: return (l1 == l2) ; ! 38065: } ! 38066: } ! 38067: return false ; ! 38068: } ! 38069: ! 38070: ! 38071: static char * non_type_argument_signature(Pexpr e, char *p) { ! 38072: p = e->tp->signature(p) ; ! 38073: return mangled_expr(p, e) ; ! 38074: } ! 38075: ! 38076: ! 38077: ! 38078: // generate array suffix information for an array signature. cfront does not ! 38079: // normally generate this as part of the type signature, since it only deals ! 38080: // with argument signatures, and arrays can't be arguments. ! 38081: static void add_array_type_suffix(char *&s, Ptype t) { ! 38082: t = real_type(t) ; ! 38083: if (t->base == VEC) { ! 38084: Pvec v = Pvec(t); ! 38085: int dim; ! 38086: char a[32] ; ! 38087: Neval = 0 ; ! 38088: if(v->dim == 0) ! 38089: dim = v->size / v->typ->tsizeof(); ! 38090: else dim = (int)v->dim->eval(); ! 38091: sprintf(a, "A%d", dim) ; ! 38092: stradd(s,a) ; ! 38093: add_array_type_suffix(s, Pvec(t)->typ); ! 38094: } ! 38095: } ! 38096: ! 38097: ! 38098: ! 38099: // Generate a mangled template instantiation name. The syntax of as template ! 38100: // mangled class name is of the form: ! 38101: // original_name__<argument type signatures>__unique_id ! 38102: // Each non-type argument is replaced by a unique id. ! 38103: char *templ_inst::mangled_name(char *ip) ! 38104: { static tree_formal_id = 0 ; ! 38105: ! 38106: char *start = ip ; ! 38107: ip = start ; ! 38108: strcpy(ip, (def->namep ? def->namep->string : "?")) ; ! 38109: ip= start + strlen(start) ; ! 38110: stradd(ip, "__pt__") ; ! 38111: ! 38112: { ! 38113: char a [max_string_size], *p = a ; ! 38114: ! 38115: Plist formal = inst_formals ; ! 38116: ! 38117: for (Pexpr ae1=actuals ; ae1 ; ae1=ae1->e2, formal = formal->l) ! 38118: switch (formal->f->n_template_arg) { ! 38119: case template_expr_formal: ! 38120: *p++ = 'X' ; ! 38121: // the formal must have been bound ! 38122: p = non_type_argument_signature(formal->f, p) ; ! 38123: break ; ! 38124: ! 38125: case template_type_formal: ! 38126: p = ae1->e1->tp->signature(p) ; ! 38127: add_array_type_suffix(p,ae1->e1->tp) ; ! 38128: break ; ! 38129: ! 38130: case template_expr_tree_formal: ! 38131: case template_stmt_tree_formal: ! 38132: *p++ = 'Y' ; ! 38133: stradd(p, tree_formal_id++) ; ! 38134: break ; ! 38135: ! 38136: default: ! 38137: error ("bad template formal:%d", formal->f->base) ; ! 38138: break ; ! 38139: } ! 38140: ! 38141: *p = 0 ; ! 38142: sprintf(ip, "%d_", strlen(a)+1) ; ! 38143: ip = start + strlen(start) ; ! 38144: strcpy(ip,a) ; ! 38145: } ! 38146: ! 38147: return start ; ! 38148: } ! 38149: ! 38150: ! 38151: ! 38152: // The C compiler barfs when it is passed on through C++ as an automatic ! 38153: // variable ! 38154: const char leader[]= "\t" ; ! 38155: ! 38156: // Explain the location of an instantiation in greater detail, since it may be ! 38157: // far removed from it's textual definition. ! 38158: void templ_inst::print_error_loc() { ! 38159: if (! head) return ; // No active instantiations ! 38160: ! 38161: extern void print_loc() ; ! 38162: state current_state ; ! 38163: char buffer[max_string_size] ; ! 38164: ! 38165: for (int i = 0 ; i < max_string_size; i++) buffer[i] = 0 ; ! 38166: ! 38167: current_state.save() ; ! 38168: fprintf (out_file, "%sanomaly detected during the instantiation of", ! 38169: leader) ; ! 38170: print_pretty_name() ; ! 38171: fprintf(out_file, "\n") ; ! 38172: if (!head->next_active) { ! 38173: // A more compact message for a single level of instantiation ! 38174: context.restore() ; ! 38175: fprintf (out_file, leader) ; ! 38176: print_loc() ; ! 38177: fprintf (out_file, "was the site of the instantiation\n") ; ! 38178: }else { ! 38179: // The instantiation chain is longer than one ! 38180: fprintf (out_file, "%sthe instantiation path was:\n", leader) ; ! 38181: for (Ptempl_inst p = head ; p ; p = p->next_active) { ! 38182: p->context.restore() ; ! 38183: print_loc() ; ! 38184: fprintf (out_file, " template:") ; ! 38185: p->print_pretty_name() ; ! 38186: fprintf(out_file, "\n") ; ! 38187: } ! 38188: } ! 38189: current_state.restore() ; ! 38190: } ! 38191: ! 38192: ! 38193: ! 38194: // Generate a class name for the instantiated class. It is constructed in a ! 38195: // manner similar to the names used in the construction of overloaded functions ! 38196: char *templ_inst::instantiation_string() { ! 38197: char inst_name[max_string_size] ; ! 38198: for (int i = 0 ; i < max_string_size; i++) inst_name[i] = 0 ; ! 38199: mangled_name(inst_name) ; ! 38200: return strdup(inst_name) ; ! 38201: } ! 38202: ! 38203: ! 38204: ! 38205: // Change the names for the class, constructors, and destructors to reflect ! 38206: // the new class instantiation name. ! 38207: void classdef::modify_inst_names(char *s) ! 38208: { ! 38209: char *old = string ; ! 38210: string = s ; // Change the class name ! 38211: // Change the constructor names ! 38212: for (Pname p=mem_list; p; p=p->n_list) ! 38213: if (p->tp && (p->tp->base==FCT) && (!strcmp(old, p->string))) ! 38214: p->string = s ; ! 38215: } ! 38216: ! 38217: // Get past the fake template argument name typename types ! 38218: Ptype non_template_arg_type(Pbase t) { ! 38219: if ((t->base == TYPE) && ! 38220: (t->b_name->n_template_arg == template_type_formal)) ! 38221: return non_template_arg_type(Pbase(t->b_name->tp)) ; ! 38222: else return t ; ! 38223: } ! 38224: ! 38225: // follow the chain until we hit a non ! 38226: void non_template_arg_non_type(Pname n) { ! 38227: Pexpr i = n->n_initializer; ! 38228: while (i && ! 38229: (i->base == NAME) && ! 38230: (Pname(i)->n_template_arg == template_expr_formal)) ! 38231: { ! 38232: if (Pname(i)->n_initializer) { ! 38233: n->n_initializer = Pname(i)->n_initializer ; ! 38234: i = n->n_initializer ; ! 38235: continue ; ! 38236: } ! 38237: if (Pname(i)->n_evaluated) { ! 38238: n->n_evaluated = 1 ; ! 38239: n->n_val = Pname(i)->n_val ; ! 38240: return ; ! 38241: } ! 38242: } ! 38243: return ; ! 38244: } ! 38245: ! 38246: ! 38247: ! 38248: // Now that the actuals are truly resolved, ie. semantics is complete, and the ! 38249: // template is about to be instantiated. ! 38250: void forward_template_arg_types(Plist formal, Pexpr actuals) ! 38251: { ! 38252: for (Pexpr actual = actuals ; formal && actual ; ! 38253: formal = formal->l, actual = actual->e2) ! 38254: switch(formal->f->n_template_arg){ ! 38255: case template_type_formal: ! 38256: actual->e1->tp = non_template_arg_type(Pbase(actual->e1->tp)) ; ! 38257: break ; ! 38258: case template_expr_formal: ! 38259: break ; ! 38260: case template_expr_tree_formal: ! 38261: case template_stmt_tree_formal: ! 38262: break ; ! 38263: default: ! 38264: error ('i', "bad template formal") ; ! 38265: } ! 38266: } ! 38267: ! 38268: // determine whether the expression supplied as an actual argument to ! 38269: // atemplate formal of type "template_expr_formal" is suitable. We are nore ! 38270: // restrictive than we need to be, simply so that the debugger can have an ! 38271: // easier time. All expressions must be of the form constant integer ! 38272: // expression, a float or double literal, or the address of a variable, or an ! 38273: // array, or function ! 38274: static int suitable_const_expr(Pname n) ! 38275: { ! 38276: if (n->n_evaluated) return 1 ; ! 38277: ! 38278: if (!n->n_initializer) return 0 ; ! 38279: ! 38280: switch (n->n_initializer->base) { ! 38281: ! 38282: case CAST: ! 38283: { // if it is a cast of an integer value, it's fine. ! 38284: if (n->n_initializer->e1->base == IVAL) ! 38285: return 1 ; ! 38286: else return 0 ; ! 38287: } ! 38288: ! 38289: case FCON: ! 38290: case ZERO: ! 38291: return 1 ; ! 38292: ! 38293: case ADDROF: ! 38294: case G_ADDROF: ! 38295: { ! 38296: Pname an = Pname(n->n_initializer->e2) ; ! 38297: if (an->base != NAME) return 0 ; ! 38298: if (an->n_stclass == STATIC) return 1 ; ! 38299: return 0 ; ! 38300: } ! 38301: case NAME: ! 38302: { ! 38303: Pname an = Pname(n->n_initializer) ; ! 38304: if ((an->n_stclass == STATIC) && ! 38305: (an->tp->base == VEC)) ! 38306: // assumes that decl processing won, so that the formal could only ! 38307: // have been apointer ! 38308: return 1 ; ! 38309: return 0 ; ! 38310: } ! 38311: default: ! 38312: return 0 ; ! 38313: } ! 38314: } ! 38315: ! 38316: ! 38317: ! 38318: static bool is_stmt_node(Pnode p) { ! 38319: if (!p) return false ; ! 38320: switch(p->base) { ! 38321: case BREAK: case CONTINUE: case DEFAULT: ! 38322: case SM: case WHILE: case DO: case SWITCH: case RETURN: case CASE: ! 38323: case FOR: ! 38324: case IF: ! 38325: case BLOCK: ! 38326: case PAIR: // ? ! 38327: return true ; ! 38328: } ! 38329: return false ; ! 38330: } ! 38331: ! 38332: ! 38333: ! 38334: static void bind_tree_expr_formal(Pname f, Pexpr actual) ! 38335: { ! 38336: if (actual->e1->base == TNAME) ! 38337: error ('i', "a TNAME is not a valid argument for the formal %n", ! 38338: f) ; ! 38339: if (is_stmt_node(actual->e1)) { ! 38340: error ("an expression node was expected for the expression formal parameter %n", f) ; ! 38341: actual->e1 = zero ; ! 38342: } ! 38343: // bind the formal to the expression, it will be accessed from here by ! 38344: // the hook function during the copy ! 38345: f->n_initializer = actual->e1 ; ! 38346: } ! 38347: ! 38348: ! 38349: ! 38350: // Bind the formals to the types passed in as the actuals, for the ! 38351: // instantiation, bind the non-type names to their expressions. ! 38352: void templ_inst::bind_formals() ! 38353: { Pexpr actual ; ! 38354: Plist formal ; ! 38355: ! 38356: for (formal = inst_formals, actual = actuals ; ! 38357: formal && actual ; formal = formal->l, actual = actual->e2) ! 38358: switch (formal->f->n_template_arg) { ! 38359: case template_type_formal: ! 38360: { ! 38361: formal->f->tp = non_template_arg_type(Pbase(actual->e1->tp)) ; ! 38362: PERM(formal->f->tp) ; ! 38363: break ; ! 38364: } ! 38365: ! 38366: case template_expr_formal: ! 38367: { ! 38368: actual->e1 = actual->e1->typ(gtbl); ! 38369: if (formal->f->tp->check(actual->e1->tp,ASSIGN) == 1) ! 38370: error("template argument mismatch, expected %t for formal %n, not %t", ! 38371: formal->f->tp, formal->f, actual->e1->tp) ; ! 38372: // hide the global name around decl processing of the formal name ! 38373: Pname g = gtbl->look (formal->f->string, 0) ; ! 38374: if (g) g->n_key = HIDDEN ; ! 38375: // bind the non type arguments to their expressions ! 38376: // parameters that are bound at syntax analysis, these parameters are ! 38377: // bound during dcl processing, so ensure that they can be found. ! 38378: formal->f->n_initializer = actual->e1 ; ! 38379: formal->f->simpl() ; ! 38380: formal->f = formal->f->dcl(gtbl, STATIC) ; ! 38381: formal->f->n_key = HIDDEN ; ! 38382: ! 38383: PERM(formal->f) ; ! 38384: non_template_arg_non_type(formal->f) ; ! 38385: if (!suitable_const_expr(formal->f)) ! 38386: error("template argument for formal:%s, is not a suitable constant.", ! 38387: formal->f->string) ; ! 38388: if (g) g->n_key = 0 ; ! 38389: break ; ! 38390: } ! 38391: ! 38392: case template_expr_tree_formal: ! 38393: { ! 38394: bind_tree_expr_formal(formal->f, actual) ; ! 38395: break ; ! 38396: } ! 38397: case template_stmt_tree_formal: ! 38398: { ! 38399: error("a statement tree may not be specified for a class template") ; ! 38400: break ; ! 38401: } ! 38402: ! 38403: default: ! 38404: error ('i', "bad template formal") ; ! 38405: } ! 38406: ! 38407: // now that the formals are bound, compute the instantiation string ! 38408: char *inst_name = instantiation_string() ; ! 38409: tname->string = instantiation_string() ; ! 38410: ! 38411: for (formal = inst_formals; formal ; formal = formal->l) ! 38412: if (formal->f->n_template_arg_string) ! 38413: error('i', "attempt to bind a template parameter multiple times") ; ! 38414: else ! 38415: formal->f->n_template_arg_string = ! 38416: strcat(strcpy(calloc(strlen(formal->f->string)+strlen(inst_name)+1,1), ! 38417: formal->f->string), inst_name) ; ! 38418: } ! 38419: ! 38420: ! 38421: // Expose the non-type parameter names so that they are visible during decl ! 38422: // processing. Conflicting global names are hidden, so that they are not ! 38423: // found. ! 38424: void templ_inst::expose_parameter_names() { ! 38425: ! 38426: if (hidden_globals) ! 38427: error ('i', "an expose without a hide of global names") ; ! 38428: ! 38429: for (Plist formal = inst_formals ; formal ; formal = formal->l) ! 38430: if (formal->f->n_template_arg == template_expr_formal) { ! 38431: // Hide any visible globals ! 38432: Pname gname = gtbl->look(formal->f->string, 0) ; ! 38433: if (gname) { ! 38434: // an existing global name, hide it ! 38435: gname->n_key = HIDDEN ; ! 38436: // note them for future restoration ! 38437: hidden_globals = new name_list(gname,hidden_globals); ! 38438: } ! 38439: formal->f->n_key = 0 ; // bring it out of hiding ! 38440: if (formal->f != gtbl->look(formal->f->string,0)) ! 38441: error('i', "parameter could not be located in the global table") ; ! 38442: } ! 38443: } ! 38444: ! 38445: ! 38446: // Hide the non-type parameter names after an instantiation, and restore any ! 38447: // globals that may have been hidden during the process. ! 38448: void templ_inst::hide_parameter_names() { ! 38449: ! 38450: for (Plist formal = inst_formals ; formal ; formal = formal->l) ! 38451: if (formal->f->n_template_arg == template_expr_formal) { ! 38452: formal->f->n_key = HIDDEN ; ! 38453: } ! 38454: for (; hidden_globals; hidden_globals= hidden_globals->l) ! 38455: hidden_globals->f->n_key= 0 ; ! 38456: hidden_globals = 0 ; ! 38457: } ! 38458: ! 38459: ! 38460: ! 38461: // Primitives for saving and restoring the compilation state around a template ! 38462: // instantiation. It also maintains the stack of template instantiations. ! 38463: void templ_inst::save_state(Pname p) { ! 38464: if (next_active) error ('i', "circular instantiation of a template") ; ! 38465: context.save() ; ! 38466: if (templ_inst::head) ! 38467: templ_inst::head->hide_parameter_names() ; ! 38468: next_active = templ_inst::head ; templ_inst::head = this ; ! 38469: context.init() ; ! 38470: Cdcl = p ; Cstmt = NULL ; ! 38471: curr_file = (Cdcl) ? Cdcl->where.file : 0; ! 38472: expose_parameter_names() ; ! 38473: } ! 38474: ! 38475: ! 38476: void templ_inst::restore_state() { ! 38477: context.restore() ; ! 38478: hide_parameter_names() ; ! 38479: templ_inst::head = next_active ; next_active = NULL ; ! 38480: if (templ_inst::head) ! 38481: templ_inst::head->expose_parameter_names() ; ! 38482: } ! 38483: ! 38484: ! 38485: // Copy over the class definition subtree starting from COBJ down to the ! 38486: // CLASSDEF node. This minimal subtree has to exist during syntax analysis, ! 38487: // and already contains pointers into it. ! 38488: void templ_inst::kludge_copy(Pbase pbc) ! 38489: { ! 38490: // copy just the COBJ ->b_name NAME ->tp CLASS path for now, note that the ! 38491: // preceding path of the tree is pre-allocated, since syntax analysis needs ! 38492: // to generate pointers to these objects. ! 38493: Pbase pb = Pbase(tname->tp) ; ! 38494: Pname save_b_name = pb->b_name ; ! 38495: Ptype save_tp = pb->b_name->tp ; ! 38496: ! 38497: if ((pb->base != COBJ) || (pbc->base != COBJ)) ! 38498: error ('i', "cobj nodes were expected here") ; ! 38499: ! 38500: *pb = *pbc ; ! 38501: pb->b_name = save_b_name ; ! 38502: *pb->b_name = *pbc->b_name ; ! 38503: pb->b_name->tp = save_tp ; ! 38504: *Pclass(pb->b_name->tp) = *Pclass(pbc->b_name->tp) ; ! 38505: Pclass(pb->b_name->tp)->class_base = instantiated_template_class ; ! 38506: ! 38507: } ! 38508: ! 38509: ! 38510: // these statics probably belong in templ_inst and shouldn't be dangling ! 38511: // around ! 38512: ! 38513: static Pbase cobj_node ; ! 38514: static Pname cname_node ; ! 38515: static Pclass class_node ; ! 38516: ! 38517: static void syntax_tree_copy_hook(void *, ! 38518: Pnode &, ! 38519: node_class, ! 38520: tree_node_action &action, ! 38521: int& never_see_again) ! 38522: { ! 38523: never_see_again = 1; ! 38524: action = tna_continue; ! 38525: return; ! 38526: } ! 38527: ! 38528: ! 38529: // create a copy of the expression tree ! 38530: static Pnode copy_syntax_tree(Pnode n, int no_types = 0) { ! 38531: pointer_hash cht(default_copy_hash_size) ; ! 38532: ! 38533: tree_copy_info info ; ! 38534: ! 38535: if(no_types) info.node_hook = syntax_tree_copy_hook; ! 38536: ! 38537: copy_tree (n, info, &cht); ! 38538: ! 38539: return n ; ! 38540: } ! 38541: ! 38542: ! 38543: ! 38544: // hook to perform the copying of the pre-allocated class subtree ! 38545: bool templ_inst::copy_hook(Pnode &node) ! 38546: { ! 38547: switch (node->base) { ! 38548: case COBJ: ! 38549: if (node == cobj_node) return false ; ! 38550: ! 38551: if (node == def->namep->tp) { ! 38552: *cobj_node = *Pbase(node) ; ! 38553: node = cobj_node ; ! 38554: } ! 38555: break ; ! 38556: case NAME: ! 38557: if (node == cname_node) return false ; ! 38558: if (node == sta_name) return false ; ! 38559: ! 38560: if (node == Pbase(def->namep->tp)->b_name) { ! 38561: *cname_node= *Pname(node) ; ! 38562: node = cname_node ; ! 38563: }else { // check for tree expression formals ! 38564: char *s = Pname(node)->string ; ! 38565: Pname f = 0 ; ! 38566: if (s && (*s == '$') && (f = get_parameter(s+1))) ! 38567: { ! 38568: if(Pname(node)->n_list) ! 38569: error ('i', "n_list set in tree template formal."); ! 38570: node = copy_syntax_tree(Pname(f)->n_initializer) ; ! 38571: return false ; ! 38572: } ! 38573: } ! 38574: break ; ! 38575: case CLASS: ! 38576: if (node == class_node) return false ; ! 38577: ! 38578: if (node == Pbase(def->namep->tp)->b_name->tp) { ! 38579: *class_node = *Pclass(node) ; ! 38580: node = class_node ; ! 38581: } ! 38582: break ; ! 38583: } ! 38584: return true ; ! 38585: } ! 38586: ! 38587: ! 38588: /* ! 38589: ! 38590: This hook function used during a class copy. ! 38591: ! 38592: */ ! 38593: static void copy_hook(void /* Ptempl_inst */ *p, Pnode &node, ! 38594: node_class, tree_node_action &action, ! 38595: int& never_see_again) ! 38596: { ! 38597: action = (Ptempl_inst(p)->copy_hook(node) ? tna_continue : tna_stop ) ; ! 38598: never_see_again = (action != tna_stop); ! 38599: return ; ! 38600: } ! 38601: ! 38602: ! 38603: ! 38604: void establish_class_subtree_correspondence(pointer_hash &h, Pname key_tname, ! 38605: Pname value_tname) ! 38606: { ! 38607: h[int(key_tname)] = int(value_tname) ; ! 38608: h[int(key_tname->tp)] = int(value_tname->tp) ; ! 38609: h[int(Pbase(key_tname->tp)->b_name)] = ! 38610: int(Pbase(value_tname->tp)->b_name) ; ! 38611: h[int(Pbase(key_tname->tp)->b_name->tp)] = ! 38612: int(Pbase(value_tname->tp)->b_name->tp) ; ! 38613: } ! 38614: ! 38615: ! 38616: ! 38617: ! 38618: Pcons make_ref_copy(pointer_hash &h, tree_copy_info &info, Pcons old_templ_refs) ! 38619: { ! 38620: cons dummy(0,0), *last = &dummy ; ! 38621: ! 38622: for (Pcons pc = old_templ_refs ; pc ; pc = pc->cdr) { ! 38623: ! 38624: Ptempl_inst t = Ptempl_inst(pc->car) ; ! 38625: // +**** this doesn't work without class instances of new and delete ! 38626: // +**** dtor places this onto free_list: ugh ! 38627: // +**** want to restore this once new/delete isntances are restored ! 38628: // expr dummy(ELIST, 0, 0) ; ! 38629: // elist list(&dummy) ; ! 38630: Pexpr dummy = new expr(ELIST, 0, 0); ! 38631: elist list(dummy); ! 38632: ! 38633: // copy the trees corresponding to the actuals ! 38634: for (Pexpr actual = t->actuals ; actual ; actual = actual->e2) { ! 38635: Pnode root = actual->e1 ; ! 38636: copy_tree (root, info, &h); ! 38637: // make sure that references to enclosing formals are resolved ! 38638: root = Pexpr(root)->typ(gtbl); ! 38639: list.add(new expr(ELIST, Pexpr(root), 0)) ; ! 38640: } ! 38641: Pexpr new_actuals = list.head->e2 ; ! 38642: ! 38643: // get one if it exists, create one otherwise. ! 38644: Ptempl_inst treal = t->def->get_inst(new_actuals, t) ; ! 38645: Pname new_tname = treal->tname ; ! 38646: ! 38647: last = last->cdr = new cons(treal,0); ! 38648: ! 38649: establish_class_subtree_correspondence(h, t->tname, new_tname) ; ! 38650: } ! 38651: ! 38652: return dummy.cdr ; ! 38653: } ! 38654: ! 38655: ! 38656: ! 38657: ! 38658: /* ! 38659: Remap the template references from within the body of the template. This ! 38660: action is similar to the normal tree copy operation; it would normally have ! 38661: been done during the syntax phase, that produced the tree, but since there ! 38662: isn't one, for the instantiated body, it must be done here. ! 38663: ! 38664: */ ! 38665: Pcons templ_inst::ref_copy(pointer_hash &h, tree_copy_info &info, Pcons old_templ_refs) ! 38666: { ! 38667: expose_parameter_names() ; ! 38668: Pcons new_refs = make_ref_copy(h,info,old_templ_refs) ; ! 38669: hide_parameter_names() ; ! 38670: return new_refs ; ! 38671: } ! 38672: ! 38673: static bool is_forward_instantiation(Pbase b_base, Pbase f_base) ! 38674: { ! 38675: return bool(b_base->b_name->tp->defined && f_base->b_name->tp->defined) ; ! 38676: } ! 38677: ! 38678: ! 38679: /***************************************************************************** ! 38680: * * ! 38681: * If the template instantiation is found to be unique after the decl * ! 38682: * processing of the actuals, create a copy of the post syntax graph for the * ! 38683: * class. The edges of the graph are determined by "type nodes" that have * ! 38684: * already been defined, and TNAME nodes that are in the global keyword * ! 38685: * table. Special care is also taken to avoid copying nodes whose identity * ! 38686: * must be maintained, since cfront uses them for fast type checks, these * ! 38687: * nodes always have the "defined" flag turned on and so are never copied. * ! 38688: * * ! 38689: * Copying of the pre-allocated class sub-tree for the template: COBJ * ! 38690: * ->b_name NAME ->tp CLASS * ! 38691: * * ! 38692: * is handled by the class_copy hook above, that is invoked during the course * ! 38693: * of the copy. * ! 38694: * * ! 38695: * * ! 38696: * Template references from within the class need special handling, since * ! 38697: * each instantiation of the class, results in a potentially new template * ! 38698: * instantiation. * ! 38699: * * ! 38700: *****************************************************************************/ ! 38701: Ptempl_inst templ_inst::class_copy(Pcons &templ_refs, bool recopy) ! 38702: { ! 38703: bool forward = false ; // a forward class is instantiated twice ! 38704: ! 38705: // associate the formals with their types, and their expressions ! 38706: if (recopy) { ! 38707: // remove the class def node from the table, so that it's attributes are ! 38708: // copied. ! 38709: corr->del(int(Pbase(def->namep->tp)->b_name->tp)) ; ! 38710: corr->del(int(Pbase(def->namep->tp)->b_name)) ; ! 38711: corr->del(int(def->namep->tp)) ; ! 38712: ! 38713: corr->del(int(tname->tp)) ; ! 38714: corr->del(int(Pbase(tname->tp)->b_name)) ; ! 38715: corr->del(int(Pbase(tname->tp)->b_name->tp)) ; ! 38716: }else corr = new pointer_hash(default_copy_hash_size) ; ! 38717: ! 38718: { // copy the formals & install them in the correspondence table ! 38719: name_list dummy_formal(0,0) ; ! 38720: Plist last = &dummy_formal ; ! 38721: ! 38722: for (Plist formal = def->formals ; formal ; formal = formal->l) { ! 38723: Pname copy_name = new name("") ; ! 38724: *copy_name = *formal->f ; ! 38725: copy_name->n_tbl_list = 0 ; ! 38726: last = last->l = new name_list(copy_name, 0) ; ! 38727: (*corr)[int(formal->f)] = (int)copy_name ; ! 38728: } ! 38729: inst_formals = dummy_formal.l ; ! 38730: } ! 38731: ! 38732: bind_formals() ; ! 38733: if ( ! recopy && ktbl->look(tname->string, 0)) { ! 38734: // formal binding may result in detecting identical instantiations ! 38735: Ptempl_inst ti = def->get_match(actuals, this, true) ; ! 38736: if (ti) return ti ; ! 38737: error('i', "Generated template instantiation name %swas not unique", ! 38738: tname->string) ; ! 38739: } ! 38740: ! 38741: { ! 38742: tree_copy_info info ; ! 38743: info.node_hook = ::copy_hook ; ! 38744: info.hook_info = this ; ! 38745: ! 38746: (*corr)[int(def->namep)] = int(tname) ; // make the tnames correspond ! 38747: ! 38748: templ_refs = ref_copy(*corr, info, templ_refs) ; ! 38749: Pnode root = def->basep ; // start the copy at the cobj node ! 38750: ! 38751: // deal with these nodes differently during the copy, ie. the nodes ! 38752: // themselves are not copied, but their attributes are. ! 38753: cobj_node = (Pbase)tname->tp ; ! 38754: cname_node = Pbase( tname->tp)->b_name ; ! 38755: class_node = Pclass(Pbase( tname->tp)->b_name->tp) ; ! 38756: ! 38757: copy_tree (root, info, corr); ! 38758: ! 38759: { // dump the tree if the flag is set ! 38760: extern int dump_tree ; ! 38761: extern dcn_arg dump_tree_arg; ! 38762: ! 38763: if (dump_tree) display_cfront_node (dump_tree_arg, root); ! 38764: } ! 38765: } ! 38766: // Perform name modifications for the class, so that it is an ! 38767: // instantiation-specific name. ! 38768: cname_node->string = tname->string ; ! 38769: if (!recopy) ! 38770: namep = ktbl->insert(tname, 0) ; ! 38771: else class_node->defined &= ~(DEFINED|SIMPLIFIED) ; ! 38772: namep->tp = cobj_node; ! 38773: ! 38774: class_node->modify_inst_names(cname_node->string) ; ! 38775: return 0 ; ! 38776: } ! 38777: ! 38778: ! 38779: /* ! 38780: This hook function is responsible for the replacement of references to ! 38781: expression when copying function bodies ! 38782: */ ! 38783: static void function_copy_hook(void *current_templ_inst, ! 38784: Pnode &node, ! 38785: node_class, ! 38786: tree_node_action &action, ! 38787: int& never_see_again) ! 38788: { ! 38789: never_see_again = 1; ! 38790: ! 38791: switch (node->base) { ! 38792: case SM_PARAM: ! 38793: error ('i', "statement parameters not permitted for member functions") ; ! 38794: break ; ! 38795: ! 38796: case NAME: ! 38797: { ! 38798: if(node == sta_name) { ! 38799: action = tna_stop; ! 38800: return; ! 38801: } ! 38802: char *s = Pname(node)->string ; ! 38803: Pname f = 0 ; ! 38804: if (s && (*s == '$') && ! 38805: (f = Ptempl_inst(current_templ_inst)->get_parameter(s+1))) { ! 38806: if(Pname(node)->n_list) ! 38807: error ('i', "n_list set in tree template formal."); ! 38808: node = copy_syntax_tree(Pname(f)->n_initializer) ; ! 38809: action = tna_stop ; ! 38810: never_see_again = 0; ! 38811: }else action = tna_continue ; ! 38812: return ; ! 38813: } ! 38814: default: ! 38815: action = tna_continue ; ! 38816: return ; ! 38817: } ! 38818: } ! 38819: ! 38820: ! 38821: ! 38822: /* ! 38823: ! 38824: Create a copy of a function member, as part of the instantiation of a function ! 38825: body. The correspondence table is first initialized with the contents of the ! 38826: correspondence table used to instantiate the class. Copying is initiated ! 38827: in this context. ! 38828: ! 38829: */ ! 38830: ! 38831: Pname templ_inst::function_copy(Pfunt fnt, Pcons &templ_refs) ! 38832: { ! 38833: pointer_hash fcorr(*corr) ; // initialize it with the old hash table ! 38834: ! 38835: { ! 38836: tree_copy_info info ; ! 38837: Pnode root = fnt->fn ; ! 38838: ! 38839: // establish a correspondence between the formals used for the class ! 38840: // template, andthe formals used for the function template, all references ! 38841: // to the function template formals will be replaced by references to the ! 38842: // instantiated class template formals after the copy has been completed. ! 38843: ! 38844: for (Plist fformal = fnt->formals, cformal = inst_formals ; ! 38845: fformal ; fformal = fformal->l, cformal = cformal->l) ! 38846: { ! 38847: fcorr[int(fformal->f)] = int(cformal->f) ; ! 38848: if (fcorr[int(fformal->f)] != int(cformal->f)) ! 38849: error ('i', "hash table bug") ; ! 38850: } ! 38851: ! 38852: info.node_hook = ::function_copy_hook ; ! 38853: info.hook_info = this ; ! 38854: ! 38855: templ_refs = ref_copy(fcorr, info, templ_refs) ; ! 38856: if (fcorr[int(def->namep)] != int(tname)) ! 38857: error ('i', "template to instantiation typename correspondence is missing") ; ! 38858: ! 38859: copy_tree (root, info, &fcorr); ! 38860: ! 38861: { // dump the tree if the flag is set ! 38862: extern int dump_tree ; ! 38863: extern dcn_arg dump_tree_arg; ! 38864: ! 38865: if (dump_tree) ! 38866: display_cfront_node (dump_tree_arg, root); ! 38867: } ! 38868: return Pname(root) ; ! 38869: } ! 38870: } ! 38871: ! 38872: ! 38873: /***************************************************************************** ! 38874: * * ! 38875: * A matching template was found at instantiation time, which was not * ! 38876: * detected at syntax analysis time. This can happen, when an instantiation * ! 38877: * has as its arguments not real types but template arguments, so that * ! 38878: * matches cannot be detected until the templates are bound. Note that it is * ! 38879: * also possible to match a template that is in the process of being * ! 38880: * instantiated further up the instantiation call chain. In such cases, the * ! 38881: * kludge_copy operation will copy over an incomplete class subtree, which * ! 38882: * will be recopied with the completed one after the instantiation is * ! 38883: * completed, in templ_inst::instantiate. * ! 38884: * * ! 38885: *****************************************************************************/ ! 38886: void templ_inst::instantiate_match(Ptempl_inst match) ! 38887: { Pbase pb = Pbase(match->tname->tp) ; ! 38888: kludge_copy(pb) ; ! 38889: forward = match ; // Note the fact that this template was matched ! 38890: } ! 38891: ! 38892: ! 38893: Pclass current_instantiation = 0 ; ! 38894: ! 38895: // Do the class declaration instantiation. ! 38896: void templ_inst::instantiate(bool reinstantiate) ! 38897: { ! 38898: Pcons templ_refs = def->templ_refs ; ! 38899: if (! reinstantiate) { ! 38900: switch (Ptclass(Pbase(tname->tp)->b_name->tp)->class_base) { ! 38901: case instantiated_template_class: ! 38902: return ; ! 38903: case uninstantiated_template_class: ! 38904: break ; ! 38905: case vanilla_class: ! 38906: case template_class: // the canonical template class ! 38907: default: ! 38908: error ('i', "attempt to instantiate a non-template class") ; ! 38909: } ! 38910: status = class_instantiated ; ! 38911: // Check whether, the template has already been instantiated, if so use it. ! 38912: forward_template_arg_types(def->formals, actuals) ; ! 38913: Ptempl_inst match = def->get_match(actuals, this, true) ; ! 38914: ! 38915: if (match || (match = class_copy(templ_refs, false))){ ! 38916: instantiate_match(match) ; ! 38917: return ; ! 38918: } ! 38919: }else class_copy(templ_refs, true) ; ! 38920: ! 38921: Pbase pb = Pbase(tname->tp) ; ! 38922: ! 38923: // Save the state around decl processing ! 38924: { save_state(def->namep) ; ! 38925: ! 38926: if (def->open_instantiations++ > 1) { ! 38927: error ("an infinite instantiation sequence was initiated") ; ! 38928: def->open_instantiations-- ; ! 38929: return ; ! 38930: } ! 38931: // Mark the class as instantiated so that there are no circular ! 38932: // instantiations. ! 38933: Pclass(pb->b_name->tp)->class_base = instantiated_template_class ; ! 38934: ! 38935: // if it is a forward reference, rely on the usual compilation to ! 38936: // provide an error message, if indeed it is an error, and not a ! 38937: // benign forward reference such as: friend class foo<X,Y> ! 38938: ! 38939: if (def->basep->b_name->tp->defined) { ! 38940: ! 38941: // Put out the typedefs for the template parameters do this before the ! 38942: // call to name::dcl below, since dcl processing will emit c declarations ! 38943: // that make use of the type ! 38944: for (Plist formal = inst_formals; formal ; formal = formal->l) ! 38945: switch(formal->f->n_template_arg) { ! 38946: case template_expr_tree_formal: ! 38947: case template_stmt_tree_formal: ! 38948: break ; ! 38949: default: ! 38950: formal->f->dcl_print(0) ; ! 38951: } ! 38952: // Instantiate the parametrized types referenced by this template ! 38953: for (Pcons pc = templ_refs ; pc ; pc = pc->cdr) ! 38954: Ptempl_inst(pc->car)->instantiate() ; ! 38955: ! 38956: if (!((pb->b_name->dcl(gtbl, EXTERN) == 0 ) || error_count)) { ! 38957: pb->b_name->simpl() ; ! 38958: ! 38959: if (pb->b_name->tp->base != CLASS) ! 38960: error('i', "a classdef was expected in templ_inst::instantiate") ; ! 38961: ! 38962: current_instantiation = Pclass(pb->b_name->tp) ; ! 38963: pb->b_name->dcl_print(0) ; ! 38964: if (! (pb->b_name->tp->defined & DEFINED)) ! 38965: error ('i', "dcl class is not yet defined") ; ! 38966: current_instantiation = 0 ; ! 38967: } ! 38968: } ! 38969: ! 38970: // bash every template instantiation class that has been forwarded to ! 38971: // it, with the decl processed version. ! 38972: for (Ptempl_inst clone = def->insts ; clone ; clone = clone->next) ! 38973: if (clone != this) { ! 38974: if (clone->forward == this) ! 38975: clone->kludge_copy(Pbase(tname->tp)) ; ! 38976: else { ! 38977: // resolve references to forward declarations ! 38978: if (this == def->get_match(clone->actuals, clone, true)) { ! 38979: clone->kludge_copy(Pbase(tname->tp)) ; ! 38980: clone->forward = this ; ! 38981: } ! 38982: } ! 38983: } ! 38984: Pclass result = Pclass(pb->b_name->tp); ! 38985: ! 38986: // dcl_print the member functions, so that they can be referenced ! 38987: int i = 0 ; ! 38988: for (Pname fn= Pclass(pb->b_name->tp)->memtbl->get_mem(i=1); fn; ! 38989: fn=Pclass(pb->b_name->tp)->memtbl->get_mem(++i)) ! 38990: if ((fn->base == NAME) && (fn->tp->base == FCT)) ! 38991: fn->dcl_print(0) ; ! 38992: ! 38993: restore_state() ; ! 38994: def->open_instantiations-- ; ! 38995: } ! 38996: } ! 38997: ! 38998: /* Template Constructors */ ! 38999: ! 39000: ! 39001: templ::templ(Plist parms, Pname p) { ! 39002: namep = p ; ! 39003: formals = parms ; ! 39004: ! 39005: if (!formals) error ("a parametrized type must have parameters !") ; ! 39006: ! 39007: basep = Pbase(namep->tp) ; ! 39008: ! 39009: Pclass(basep->b_name->tp)->class_base = template_class ; ! 39010: defined = ((basep->b_name->tp->defined & DEF_SEEN) ? true : false) ; ! 39011: if (defined) ! 39012: members = Pclass(basep->b_name->tp)->mem_list ; ! 39013: ! 39014: PERM(namep) ; PERM(namep->tp) ; ! 39015: // Chain on to the list of templates for the compilation. ! 39016: next = templp->list ; ! 39017: templp->list = this ; ! 39018: } ! 39019: ! 39020: ! 39021: templ_inst::templ_inst (Pexpr act, Ptempl owner) ! 39022: { ! 39023: // Set up the basetype for the class, so that nodes that need to point to it ! 39024: // during syntax processing can do so. Theese objects are merely ! 39025: // place-holders during syntax analysis, and are actually filled in during ! 39026: // the copy phase of instantiation. ! 39027: Pclass c ; ! 39028: ! 39029: def = owner ; ! 39030: tname = new name(def->namep->string) ; ! 39031: tname->base = TNAME ; ! 39032: tname->tp = new basetype(COBJ, new name(def->namep->string)) ; ! 39033: Pbase(tname->tp)->b_name->tp = c = new templ_classdef(this) ; ! 39034: PERM(tname) ; PERM(tname->tp) ; PERM(Pbase(tname->tp)->b_name) ; ! 39035: PERM(Pbase(tname->tp)->b_name->tp) ; ! 39036: ! 39037: // initialize the member list so that set_scope can do the right thing ! 39038: c->mem_list = Pclass(def->basetype()->b_name->tp)->mem_list ; ! 39039: ! 39040: actuals = act ; ! 39041: next = owner->insts ; ! 39042: owner->insts = this ; ! 39043: } ! 39044: ! 39045: ! 39046: templ_classdef::templ_classdef(Ptempl_inst i): classdef(CLASS) { ! 39047: inst = i ; ! 39048: class_base = uninstantiated_template_class ; ! 39049: string = unparametrized_tname()->string ; ! 39050: } ! 39051: ! 39052: ! 39053: // Create a new function template. ! 39054: function_template::function_template (templ &owner, Plist params, Pname n) ! 39055: { ! 39056: definition_number = ++definition_tick ; ! 39057: ! 39058: if (owner.fns_end) ! 39059: owner.fns_end->next = this ; ! 39060: else owner.fns = this ; ! 39061: owner.fns_end = this ; ! 39062: formals = params ; ! 39063: fn = n ; ! 39064: PERM(n) ; PERM(n->tp) ; ! 39065: } ! 39066: ! 39067: ! 39068: // create the tree template ! 39069: tree_template::tree_template(TOK tree_kind, char *s, Plist params, Pnode tree, ! 39070: Pcons references) ! 39071: { ! 39072: string = s ; ! 39073: formals = params; ! 39074: e = tree ; ! 39075: if (!e) ! 39076: error('w', "the internal template %s does not have an associated body", s); ! 39077: templ_refs = references ; ! 39078: kind = tree_kind ; ! 39079: ! 39080: // add the expression template too the list of known templates ! 39081: if (get(s)) { ! 39082: error ("duplicate definition of the internal template %s", s) ; ! 39083: return ; ! 39084: } ! 39085: // link it in ! 39086: next = templ_compilation::tree_templates ; ! 39087: templ_compilation::tree_templates = this ; ! 39088: ! 39089: // check that formals weren't misspelt ! 39090: for (Plist formal = formals ; formal ; formal = formal->l) ! 39091: if (! formal->f->n_used) ! 39092: error('w', "the formal parameter %n was not referenced within the template body",formal->f) ; ! 39093: } ! 39094: ! 39095: ! 39096: // lookup an internal expression template ! 39097: Ptreet tree_template::get(char *s) { ! 39098: for (Ptreet o = templ_compilation::tree_templates ; o ; o = o->next) ! 39099: if (strcmp(o->string, s) == 0) return o ; ! 39100: return 0 ; ! 39101: } ! 39102: ! 39103: ! 39104: Pname tree_template::get_parameter(char *s) { ! 39105: for (Plist formal = formals ; formal ; formal = formal->l) { ! 39106: if (strcmp(formal->f->string, s)== 0) ! 39107: return formal->f ; ! 39108: } ! 39109: return 0 ; ! 39110: } ! 39111: ! 39112: ! 39113: ! 39114: // Sam: some remodularization seems to be in order here, so that this method ! 39115: // can be shared ! 39116: Pname templ_inst::get_parameter(char *s) { ! 39117: for (Plist formal = inst_formals ; formal ; formal = formal->l) { ! 39118: if (strcmp(formal->f->string, s)== 0) ! 39119: return formal->f ; ! 39120: } ! 39121: return 0 ; ! 39122: } ! 39123: ! 39124: Pexpr tree_template::expand(Pexpr) ! 39125: { ! 39126: error('i', "no support for tree templates") ; ! 39127: return 0 ; ! 39128: } ! 39129: ! 39130: ! 39131: // Instantiate each function member body. It assumes that the class ! 39132: // declaration has been instantiated. The return value indicates whether an ! 39133: // instantiation of bodies actually took place. This function is only invoked ! 39134: // at the end of a file compilation, after all source text has been processed. ! 39135: bool templ::instantiate_bodies(){ ! 39136: bool change = false ; ! 39137: // Perform the instantiation of the member function bodies. ! 39138: if (!fns) return change ; ! 39139: ! 39140: for (Ptempl_inst inst = insts ; inst ; inst = inst->next) ! 39141: if (!inst->forward && (inst->status == class_instantiated)) { ! 39142: // Set up the environment for the declaration, and subsequent compilation ! 39143: // of the function bodies. ! 39144: inst->status = body_instantiated ; change = true ; ! 39145: ! 39146: { Pclass ic = inst->get_class() ; int i ; ! 39147: // note all the overriding definitions explicitly provided by the user ! 39148: for (Pname fn= ic->memtbl->get_mem(i=1); fn; fn=ic->memtbl->get_mem(++i)) ! 39149: if ((fn->base == NAME) && (fn->tp->base == FCT) && Pfct(fn->tp)->body) ! 39150: fn->n_redefined = 1 ; ! 39151: } ! 39152: ! 39153: for (Pfunt fnt = fns; fnt ; fnt = fnt->next) { ! 39154: Pcons templ_ref_copy = fnt->templ_refs ; ! 39155: Pname fn = inst->function_copy(fnt, templ_ref_copy) ; ! 39156: ! 39157: // Change the qualifier to be the name of the instantiated, rather than ! 39158: // the parametrized class name ! 39159: fn->n_qualifier = inst->namep ; ! 39160: if (fn->n_oper != TYPE ) // cond contains type information ! 39161: fn->n_table = 0; ! 39162: fn->n_tbl_list = 0 ; ! 39163: ! 39164: // Note that the formals were bound to the actuals when the class decl ! 39165: // was instantiated, so the binding is not redone. ! 39166: ! 39167: // Modify constructor and destructor names. ! 39168: if (!strcmp(fn->string, namep->string)) ! 39169: fn->string = inst->namep->string ; ! 39170: { inst->save_state(fn) ; ! 39171: // Instantiate the parametrized types referenced by this template ! 39172: for (Pcons pc = templ_ref_copy ; pc ; pc = pc->cdr) ! 39173: Ptempl_inst(pc->car)->instantiate() ; ! 39174: ! 39175: // ensure that "type type" formals constrained to be class definitions are ! 39176: if (!fnt->check_constraints(inst->actuals))continue ; ! 39177: ! 39178: if ( ((fn = fn->dcl(gtbl, EXTERN)) == 0) || error_count) { ! 39179: inst->restore_state() ; ! 39180: continue ; ! 39181: } ! 39182: fn->simpl() ; ! 39183: fn->dcl_print(0) ; ! 39184: inst->restore_state() ; ! 39185: } ! 39186: } ! 39187: } ! 39188: return change ; ! 39189: } ! 39190: 0707071010112046121004440001630000160000010212600466055421700001300000040045template.h /* ident "@(#)ctrans:src/template.h 1.2" */ ! 39191: /* -*- Mode:C++ -*- */ ! 39192: /* ! 39193: $Source: /usr3/lang/benson/work/stripped_cfront/RCS/template.h,v $ $RCSfile: template.h,v $ ! 39194: $Revision: 1.4 $ $Date: 90/04/02 11:31:35 $ ! 39195: $Author: sam $ $Locker: $ ! 39196: $State: Exp $ ! 39197: */ ! 39198: /* ! 39199: $Header: /usr3/lang/benson/work/stripped_cfront/RCS/template.h,v 1.4 90/04/02 11:31:35 sam Exp $ ! 39200: ! 39201: Copyright 1989 by Object Design, Inc., Burlington, Mass. ! 39202: All rights reserved. ! 39203: ! 39204: */ ! 39205: ! 39206: ! 39207: /***************************************************************************** ! 39208: * * ! 39209: * This file contains types pertinent to the implementation of the * ! 39210: * parametrized type facility. * ! 39211: * * ! 39212: *****************************************************************************/ ! 39213: ! 39214: enum bool { true = 1, false = 0 } ; ! 39215: ! 39216: typedef class templ *Ptempl ; ! 39217: ! 39218: typedef class templ_inst *Ptempl_inst ; ! 39219: ! 39220: typedef class function_template *Pfunt ; ! 39221: ! 39222: typedef class templ_classdef *Ptclass ; ! 39223: ! 39224: typedef class tree_template *Ptreet ; ! 39225: ! 39226: ! 39227: // A Lisp style cons cell to help build lists. The parametrized type facility, ! 39228: // should obviate the need for this type-unsafe nonsense. ! 39229: class cons { ! 39230: public: ! 39231: void *car ; ! 39232: cons *cdr ; ! 39233: cons (void *pcar, cons *pcdr) { car = pcar ; cdr = pcdr ; } ; ! 39234: } ; ! 39235: ! 39236: typedef cons *Pcons ; ! 39237: ! 39238: ! 39239: ! 39240: /***************************************************************************** ! 39241: * * ! 39242: * The class template_compilation holds the state, and the associated methods * ! 39243: * used during template compilation. There is exactly one instance of the * ! 39244: * type, it is mainly a device used to enforce modularity. In reality, it * ! 39245: * would never need to be instantiated since all it's members are static. * ! 39246: * However, since the type::mem for of reference is not supported as * ! 39247: * yet(cfront 1.2), we need an instantiation to get to the members via * ! 39248: * pointer syntax instead. * ! 39249: * * ! 39250: * A templ_compilation holds the state relevant to the syntax analysis of a * ! 39251: * class or member function template definition. * ! 39252: * * ! 39253: *****************************************************************************/ ! 39254: ! 39255: class templ_compilation { ! 39256: static Plist param_end, // make append easier ! 39257: param_tn ; // The type names introduced by the parameters ! 39258: ! 39259: public: ! 39260: static Ptempl list ; // The list of templates for the compilation ! 39261: static Plist params ; // The list of parameters to the template ! 39262: static Ptempl owner ; // The template when compiling a member ! 39263: // function. ! 39264: static table *templates ; // The templates defined during this compilation ! 39265: ! 39266: static Ptreet tree_templates; // The list of tree templates ! 39267: ! 39268: static bool in_progress; // a template compilation is in progress ! 39269: // instantiation parameter parsing in progress. Used in the lexer to ensure ! 39270: // that name string are consed in the heap, rather than being retained as ! 39271: // pointers into the lex buffer. ! 39272: static int parameters_in_progress ; ! 39273: ! 39274: // the list of templates referenced by the top level definition being compiled. ! 39275: static Pcons templ_refs ; ! 39276: static Pcons last_cons ; ! 39277: static Ptype any_type ; // canonical "ANY" type for formal parms ! 39278: ! 39279: // true, if currently compiling an expression tree template ! 39280: static TOK curr_tree_template ; ! 39281: ! 39282: void append_ref(Ptempl_inst ref) ; ! 39283: void start() ; ! 39284: ! 39285: void collect(TOK parm_type, Pname namep) ; ! 39286: void collect(Pname namep) ; ! 39287: ! 39288: void enter_parameters() ; ! 39289: void introduce_class_templ(Pname cnamep) ; ! 39290: void end(Pname class_name) ; ! 39291: Pname forward_declaration(Pname class_name) ; ! 39292: void instantiate_ref_templ() ; ! 39293: void clear_ref_templ() ; ! 39294: ! 39295: Pname check_tname(Pname p) ; ! 39296: bool current_template(Pname p, Pexpr actuals) ; ! 39297: Ptempl is_template(Pname p) ; ! 39298: Ptempl is_template(char *s); ! 39299: void end_of_compilation() ; // Done with compilation, instantiate bodies ! 39300: templ_compilation() ; ! 39301: ! 39302: static Pname tree_parameter(char *s) ; // return true if the name is a tree parameter ! 39303: ! 39304: private: ! 39305: void append_parameter(Pname p) ; ! 39306: ! 39307: } ; ! 39308: ! 39309: ! 39310: ! 39311: // The canonical template_compilation instance. templ_compilation exists as a ! 39312: // class simply to provide a code and data packaging mechanism. There is ! 39313: // exactly one generated instance of it. ! 39314: ! 39315: extern templ_compilation *templp ; ! 39316: ! 39317: // should actually be static member functions of templ_compilation ! 39318: Pname parametrized_typename (Pname p, Pexpr actuals) ; ! 39319: Pbase parametrized_basetype (Pname p, Pexpr actuals) ; ! 39320: ! 39321: ! 39322: ! 39323: ! 39324: // the basis for class and member function templates ! 39325: class basic_template { ! 39326: friend templ_compilation ; ! 39327: protected: ! 39328: Plist formals ; // The formal arguments to the template ! 39329: Pcons templ_refs ; // The templates referenced by this template ! 39330: ! 39331: // check class constraints placed on formals while processing member ! 39332: // function bodies. ! 39333: bool check_constraints(Pexpr actuals) ; ! 39334: ! 39335: // ensure that use of formals is consistent across, class, member and ! 39336: // forward declarations ! 39337: void check_formals(Plist formals) ; ! 39338: ! 39339: public: ! 39340: // used to order template class definitions for instantiations. Not being ! 39341: // used as yet. ! 39342: int definition_number ; ! 39343: ! 39344: // used to generate the definition numbers, used by the above member. ! 39345: static int definition_tick ; ! 39346: ! 39347: Plist get_formals() {return formals ;} ! 39348: } ; ! 39349: ! 39350: ! 39351: ! 39352: // the template for a class ! 39353: class templ : public basic_template { ! 39354: Pbase basep ; // COBJ basetype for the template ! 39355: Ptempl_inst insts ; // instantiations of the template ! 39356: Pfunt fns ; // member function declarations ! 39357: Pfunt fns_end ; // last fun in the above list ! 39358: ! 39359: // Use these state variables to set up the correct state for error ! 39360: // processing. They are used by the "error" routines for statement numbers. ! 39361: Pname Cdcl ; ! 39362: Pstmt Cstmt ; ! 39363: ! 39364: friend templ_inst ; ! 39365: friend function_template ; ! 39366: ! 39367: // used to detect loops during instantiation; a count greater than two is ! 39368: // indicative of a non-terminating instantiation sequence ! 39369: int open_instantiations ; ! 39370: ! 39371: Ptempl_inst get_match(Pexpr actuals, ! 39372: Ptempl_inst exclude, ! 39373: bool match_instantiated_only) ; ! 39374: bool check_actual_args (Pexpr actuals) ; ! 39375: ! 39376: public: ! 39377: Ptempl next ; // connects all the class templates in the comp ! 39378: Pname namep ; // the TNAME for the template class ! 39379: bool defined ; // the actual definition, not just a forward ! 39380: // declaration has been seen. ! 39381: ! 39382: Pname members ; // note the members to catch redefinition errors ! 39383: ! 39384: Ptempl_inst get_inst(Pexpr actuals, Ptempl_inst exclude = 0) ; ! 39385: templ(Plist parms, Pname p) ; ! 39386: void resolve_forward_decl(Plist parms, Pclass c) ; ! 39387: void instantiate_forward_decl() ; ! 39388: ! 39389: // The uninstantiated base type ! 39390: Pbase basetype() {return basep; } ! 39391: // The basetype for a specific instantiation ! 39392: Pbase inst_basetype(Pexpr actuals) ; ! 39393: ! 39394: Pname typename(Pexpr actuals) ; ! 39395: ! 39396: Pfunt collect_function_member(Pname fname) ; ! 39397: bool has_tree_expr_formals() ; ! 39398: bool instantiate_bodies() ; ! 39399: } ; ! 39400: ! 39401: ! 39402: ! 39403: // Member function templates ! 39404: class function_template : public basic_template { ! 39405: Pname fn ; // The name of the member function ! 39406: Pfunt next ; // connects the list of member functions ! 39407: ! 39408: friend templ ; ! 39409: friend templ_inst ; ! 39410: ! 39411: public: ! 39412: function_template (templ & owner, Plist params, Pname n) ; ! 39413: } ; ! 39414: ! 39415: ! 39416: ! 39417: // compiler internal expression templates, used to implement Objectstore constructs ! 39418: class tree_template : public basic_template { ! 39419: TOK kind ; // STATEMENT or EXPRESSION ! 39420: Pnode e ; // the post-syntax tree representing the ! 39421: // expression or statement constituting the ! 39422: // template. ! 39423: Ptreet next ; // the next expression template ! 39424: static int count ; // the number of instantiations ! 39425: ! 39426: public: ! 39427: char *string ; // the name used for template lookup ! 39428: tree_template(TOK tree_kind, char *s, Plist params, Pnode tree, ! 39429: Pcons references) ; ! 39430: static Ptreet get(char *s) ; ! 39431: Pname get_parameter(char *s) ; ! 39432: static void test() ; ! 39433: Pexpr expand(Pexpr actuals) ; ! 39434: } ; ! 39435: ! 39436: ! 39437: ! 39438: ! 39439: // Global state variables that must be saved around an instantiation. The ! 39440: // saving of state was required in the implementstion that interspersed decl ! 39441: // processing and instantiation, rather than the current strategy, which only ! 39442: // forces instantiations at the top level outside of any dcl-processing ! 39443: // context. It is retained in case we ever go back to the "interspersed" style ! 39444: // of instantiation. ! 39445: class state { ! 39446: ! 39447: public: ! 39448: Pname Cdcl ; // the global variables used by the error routines ! 39449: Pstmt Cstmt ; ! 39450: Pname dcl_list ; // Holds the list of typedef names that are hidden ! 39451: Loc curloc ; ! 39452: ! 39453: int curr_file ; ! 39454: Pexpr curr_expr ; ! 39455: Pin curr_icall ; ! 39456: Pstmt curr_loop; ! 39457: Pblock curr_block; ! 39458: Pstmt curr_switch; ! 39459: ! 39460: int bound ; ! 39461: int inline_restr ; ! 39462: Loc last_line ; ! 39463: ! 39464: int no_of_badcall; ! 39465: int no_of_undcl ; ! 39466: ! 39467: Pname badcall ; ! 39468: Pname undcl ; ! 39469: ! 39470: state() {} ; // prevent used before set warnings. ! 39471: void save() ; ! 39472: ! 39473: void init() ; ! 39474: void restore() ; ! 39475: } ; ! 39476: ! 39477: ! 39478: class pointer_hash ; ! 39479: class tree_copy_info ; ! 39480: ! 39481: ! 39482: // A template starts out being uninstantiated, and is class_instantiated when ! 39483: // there is a refrence to it with actual arguments. It is body_instantiated at ! 39484: // the end of compilation, when all its function members are instantiated. ! 39485: enum inst_status { uninstantiated, class_instantiated, body_instantiated }; ! 39486: ! 39487: // templ_inst captures the arguments used in the instantiation of a template. ! 39488: // These instantiations are rooted in the templ object. ! 39489: class templ_inst { ! 39490: ! 39491: friend class template_instantiation ; ! 39492: ! 39493: Pname tname ; // The instantiation name, it is the TNAME that ! 39494: // leads up to an actual instantiation of the class ! 39495: Pname namep ; // The version of TNAME in the ktbl ! 39496: Pexpr actuals ; // instantiation arguments, chained using ELIST ! 39497: // as an expression "cons" node, e1 is the car ! 39498: // and e2 the cdr. The car points to a name node. ! 39499: Ptempl_inst next ; // The linked list of instantiations for this ! 39500: // template. ! 39501: Ptempl_inst next_active ; // The list of currently active instantiations. ! 39502: state context ; // the context of this instantiation ! 39503: Ptempl_inst forward ; // This instantiation is the same as the one ! 39504: // pointed to. ! 39505: ! 39506: // Contains the list of global names that are hidden during an ! 39507: // instantiation. ! 39508: Plist hidden_globals ; ! 39509: ! 39510: // The class correspondence table. This table is initialized ! 39511: // when the class definition is instantiated. Subsequently, it is used to ! 39512: // initial member correspondence tables before the copy process is ! 39513: // initiated. ! 39514: pointer_hash *corr ; ! 39515: ! 39516: // the instantiation's copy of the formals ! 39517: Plist inst_formals ; ! 39518: ! 39519: inst_status status ; ! 39520: ! 39521: friend class templ ; ! 39522: friend class templ_classdef ; ! 39523: friend class tree_template ; ! 39524: friend Pcons make_ref_copy(pointer_hash &h, tree_copy_info &info, ! 39525: Pcons old_templ_refs); ! 39526: ! 39527: templ_inst (Pexpr act, Ptempl owner) ; ! 39528: bool actuals_match(Pexpr check_actuals) ; ! 39529: void instantiate_match(Ptempl_inst match) ; ! 39530: void kludge_copy(Pbase source_base) ; ! 39531: // create a copy of the class type subtree preparatory to the ensuing ! 39532: // instantiation. Return a non-zero value, only if there was no need to ! 39533: // create a copy, ie. an identical instantiation already existed. ! 39534: Ptempl_inst class_copy(Pcons &templ_refs, bool recopy) ; ! 39535: Pcons ref_copy(pointer_hash &h, tree_copy_info &info, Pcons old_templ_refs) ; ! 39536: ! 39537: // save and restore state around the template instantiation ! 39538: void save_state(Pname p) ; ! 39539: void restore_state() ; ! 39540: ! 39541: // Used to collect references to this template by a definition ! 39542: Ptempl_inst note_ref() ; ! 39543: char *instantiation_string() ; ! 39544: ! 39545: void expose_parameter_names() ; ! 39546: void hide_parameter_names() ; ! 39547: ! 39548: public: ! 39549: Ptempl def ; // The template definition, for which this is an ! 39550: // instantiation. ! 39551: bool refp ; // A flag used to note template references during ! 39552: // a C++ definition ! 39553: void print_error_loc() ; // Wants to be a static function ! 39554: // Bind the formals before an instantiation ! 39555: void bind_formals() ; ! 39556: ! 39557: Ptempl_inst canonical_instantiation() { ! 39558: return ( forward ? forward : this ) ; ! 39559: } ! 39560: ! 39561: // get the class associated with this instantiation ! 39562: Pclass get_class() { return Pclass(Pbase(tname->tp)->b_name->tp) ;} ! 39563: ! 39564: void instantiate(bool reinstantiate = false) ; ! 39565: static Ptempl_inst head ; // Head of the list of active instantiations. ! 39566: void print_pretty_name() ; ! 39567: char *mangled_name(char *buffer) ; ! 39568: // The uninstantiated basetype ! 39569: Pbase def_basetype() { return def->basep ; } ; ! 39570: // A general way of determining whether two template instantiations are ! 39571: // the same ! 39572: bool same(Ptempl_inst t) ; ! 39573: bool copy_hook(Pnode&) ; ! 39574: // return a copy of the function tree starting with it's name ! 39575: Pname function_copy(Pfunt fnt, Pcons &templ_refs) ; ! 39576: ! 39577: // special check for instantiations used in qualifiers for template function ! 39578: // member declarations. ! 39579: bool check_qualifier(Plist formals) ; ! 39580: Pname get_parameter(char *s) ; ! 39581: } ; ! 39582: ! 39583: ! 39584: ! 39585: // Experimental debugging toggle ! 39586: extern int zdebug ; ! 39587: ! 39588: ! 39589: // The class node used for template classes. ! 39590: // Rep invariant: ! 39591: // class_base == uninstantiated_template_class || ! 39592: // class_base == instantiated_template_class ! 39593: ! 39594: class templ_classdef : public classdef { ! 39595: public: ! 39596: Ptempl_inst inst ; // a pointer to the instantiation; the ! 39597: // instantiation also points back to it via ! 39598: // the tname ->cobj->name->class path ! 39599: templ_classdef(Ptempl_inst i) ; ! 39600: Pname unparametrized_tname() { return inst->def->namep ; } ! 39601: void instantiate() { inst->instantiate() ; } ! 39602: ! 39603: } ; ! 39604: ! 39605: ! 39606: // Safe accessor functions for navigating through COBJ base classes ! 39607: ! 39608: extern class_type_enum get_class_base (Pbase b) ; ! 39609: ! 39610: extern Ptclass get_template_class (Pbase b) ; ! 39611: ! 39612: extern Ptempl_inst get_templ_inst(Pbase b) ; ! 39613: ! 39614: ! 39615: /* ! 39616: $Log: template.h,v $ ! 39617: * Revision 1.4 90/04/02 11:31:35 sam ! 39618: * Made comments current. ! 39619: * ! 39620: * Revision 1.3 90/03/30 18:50:55 sam ! 39621: * 1) Added the introduce_class_templ member function to the templ_compilation ! 39622: * class. ! 39623: * 2) Rationalized the definition of class templ. Made basic_template be it's ! 39624: * base class, instead of type. The latter was the base type, simply so that ! 39625: * it could be stored in a table associating strings with types. Don't have ! 39626: * to resolve to such kludgery in the PT world. ! 39627: * 3) Added the member open_instantiations to detect non-terminating ! 39628: * instantiations ! 39629: * ! 39630: * Revision 1.2 90/03/27 10:16:27 sam ! 39631: * > Merged in revision 1.13 from the main line of development ! 39632: * ! 39633: * Revision 1.1 89/11/20 08:50:58 benson ! 39634: * Initial revision ! 39635: * ! 39636: * Revision 1.11 89/10/16 15:25:00 sam ! 39637: * use pointer_hash rather than Hash as the type of the correspondence table. ! 39638: * ! 39639: * Revision 1.10 89/09/26 16:44:34 sam ! 39640: * fix the forward declaration of template classes ! 39641: * ! 39642: * Revision 1.9 89/09/18 16:37:37 sam ! 39643: * provide for error recovery upon argument mismatch in a template instantiation ! 39644: * ! 39645: * ! 39646: * Revision 1.8 89/09/15 09:31:50 benson ! 39647: * move tree_template.string into the public section. ! 39648: * ! 39649: * Revision 1.7 89/08/30 13:02:12 sam ! 39650: * added support for dealing with __expressions in class formal templates ! 39651: * ! 39652: * Revision 1.6 89/08/28 09:42:05 sam ! 39653: * Support for nested references in internal templates. These nested ! 39654: * references are instantiated whenever an expansion takes place. ! 39655: * ! 39656: * Revision 1.5 89/08/23 10:26:00 sam ! 39657: * support for BS style formal syntax. refer to 1.5 templates.c for more ! 39658: * detailed comments. ! 39659: * ! 39660: * Revision 1.4 89/08/11 14:57:09 sam ! 39661: * implementation of multiple instantiation templates. ! 39662: * ! 39663: * Revision 1.3 89/07/27 11:33:40 sam ! 39664: * the comments in template.c 1.3 describe the modifications. ! 39665: * ! 39666: * Revision 1.2 89/07/07 14:34:11 sam ! 39667: * Added the templ_classdef::unparametrized_type_name() function member, as part ! 39668: * of the base init fix. ! 39669: * ! 39670: * Revision 1.1 89/06/29 09:21:32 benson ! 39671: * Initial revision ! 39672: * ! 39673: * Revision 1.1 89/06/22 16:29:29 sam ! 39674: * Initial revision ! 39675: * ! 39676: ! 39677: ! 39678: end_log ! 39679: */ ! 39680: ! 39681: ! 39682: ! 39683: /* ! 39684: $Log $ ! 39685: ! 39686: ! 39687: end_log ! 39688: */ ! 39689: 0707071010112045701004440001630000160000010210100466055411600001000000012452token.h /*ident "@(#)ctrans:src/token.h 1.4" */ ! 39690: /************************************************************************** ! 39691: ! 39692: C++ source for cfront, the C++ compiler front-end ! 39693: written in the computer science research center of Bell Labs ! 39694: ! 39695: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 39696: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 39697: ! 39698: token.h: ! 39699: ! 39700: *****************************************************************************/ ! 39701: /* ! 39702: #ifndef PRESAFE ! 39703: extern "C" { ! 39704: #endif ! 39705: ! 39706: extern void free(char*); // alloc.h ! 39707: extern char* malloc(unsigned); ! 39708: extern char* calloc(unsigned, unsigned); ! 39709: ! 39710: extern strncmp(const char*, const char*, const); // string.h ! 39711: extern strcmp(const char*, const char*); ! 39712: extern int strlen(const char*); ! 39713: extern char* strcpy(char*, const char*); ! 39714: ! 39715: #ifdef apollo ! 39716: extern void set_sbrk_size(int); ! 39717: #endif ! 39718: ! 39719: #ifndef PRESAFE ! 39720: } ! 39721: #endif ! 39722: */ ! 39723: ! 39724: #include <malloc.h> ! 39725: #include <string.h> ! 39726: #include <stdio.h> ! 39727: ! 39728: extern void lex_clear(); ! 39729: extern void otbl_init(); ! 39730: ! 39731: //#define yylex() lalex() ! 39732: ! 39733: #define putstring(s) fputs(s,out_file) ! 39734: #define putst(s) (fputs(s,out_file),putc(' ',out_file)) ! 39735: #define putch(c) putc(c,out_file) ! 39736: #define putcat(c,s) (putc(c,out_file),fputs(s,out_file)) ! 39737: ! 39738: /* token numbers for C parser */ ! 39739: ! 39740: #define MAXTOK 255 ! 39741: extern char* keys[MAXTOK+1]; ! 39742: ! 39743: #define EOFTOK 0 /* EOF */ ! 39744: /* keywords in alphabetical order */ ! 39745: #define ASM 1 ! 39746: #define AUTO 2 ! 39747: #define BREAK 3 ! 39748: #define CASE 4 ! 39749: #define CHAR 5 ! 39750: #define CLASS 6 ! 39751: #define CONTINUE 7 ! 39752: #define DEFAULT 8 ! 39753: #define DELETE 9 ! 39754: #define DO 10 ! 39755: #define DOUBLE 11 ! 39756: #define ELSE 12 ! 39757: #define ENUM 13 ! 39758: #define EXTERN 14 ! 39759: #define FLOAT 15 ! 39760: #define FOR 16 ! 39761: #define FORTRAN 17 ! 39762: #define FRIEND 18 ! 39763: #define GOTO 19 ! 39764: #define IF 20 ! 39765: #define INT 21 ! 39766: #define LONG 22 ! 39767: #define NEW 23 ! 39768: #define OPERATOR 24 ! 39769: #define PUBLIC 25 ! 39770: #define CONST 26 ! 39771: #define REGISTER 27 ! 39772: #define RETURN 28 ! 39773: #define SHORT 29 ! 39774: #define SIZEOF 30 ! 39775: #define STATIC 31 ! 39776: #define STRUCT 32 ! 39777: #define SWITCH 33 ! 39778: #define THIS 34 ! 39779: #define TYPEDEF 35 ! 39780: #define UNION 36 ! 39781: #define UNSIGNED 37 ! 39782: #define VOID 38 ! 39783: #define WHILE 39 ! 39784: ! 39785: /* operators in priority order (sort of) */ ! 39786: #define LP 40 ! 39787: #define RP 41 ! 39788: #define LB 42 ! 39789: #define RB 43 ! 39790: #define REF 44 ! 39791: #define DOT 45 ! 39792: #define NOT 46 ! 39793: #define COMPL 47 ! 39794: #define INCR 48 ! 39795: #define DECR 49 ! 39796: #define MUL 50 ! 39797: #define DIV 51 ! 39798: #define AND 52 ! 39799: #define MOD 53 ! 39800: #define PLUS 54 ! 39801: #define MINUS 55 ! 39802: #define LS 56 ! 39803: #define RS 57 ! 39804: #define LT 58 ! 39805: #define LE 59 ! 39806: #define GT 60 ! 39807: #define GE 61 ! 39808: #define EQ 62 ! 39809: #define NE 63 ! 39810: #define ER 64 ! 39811: #define OR 65 ! 39812: #define ANDAND 66 ! 39813: #define OROR 67 ! 39814: #define QUEST 68 ! 39815: #define COLON 69 ! 39816: #define ASSIGN 70 ! 39817: #define CM 71 ! 39818: #define SM 72 ! 39819: #define LC 73 ! 39820: #define RC 74 ! 39821: ! 39822: #define INLINE 75 ! 39823: #define OVERLOAD 76 ! 39824: #define VIRTUAL 77 ! 39825: #define COERCE 78 ! 39826: #define PROTECTED 79 ! 39827: ! 39828: /* constants etc. */ ! 39829: #define ID 80 ! 39830: #define STRING 81 ! 39831: #define ICON 82 ! 39832: #define FCON 83 ! 39833: #define CCON 84 ! 39834: #define NAME 85 ! 39835: #define ZERO 86 ! 39836: ! 39837: /* groups of tokens */ ! 39838: #define ASOP 90 /* op= */ ! 39839: #define RELOP 91 /* LE GE LT GT */ ! 39840: #define EQUOP 92 /* EQ NE */ ! 39841: #define DIVOP 93 /* DIV MOD */ ! 39842: #define SHIFTOP 94 /* LS RS */ ! 39843: #define ICOP 95 /* INCR DECR */ ! 39844: #define UNOP 96 /* NOT COMPL */ ! 39845: #define TYPE 97 ! 39846: /* TYPE = INT FLOAT CHAR DOUBLE REGISTER STATIC EXTERN AUTO ! 39847: LONG SHORT UNSIGNED INLINE FRIEND VIRTUAL */ ! 39848: ! 39849: /* new tokens generated by syn() */ ! 39850: #define UMINUS 107 ! 39851: #define FCT 108 ! 39852: #define CALL 109 ! 39853: #define VEC 110 ! 39854: #define DEREF 111 ! 39855: #define ADDROF 112 ! 39856: #define CAST 113 ! 39857: //#define ENDCAST 122 ! 39858: #define FIELD 114 ! 39859: #define LABEL 115 ! 39860: #define BLOCK 116 ! 39861: //#define QUA 117 ! 39862: #define DCL 118 /* local declaration statement */ ! 39863: #define COBJ 119 ! 39864: #define EOBJ 121 ! 39865: #define TNAME 123 ! 39866: #define ILIST 124 ! 39867: #define PTR 125 ! 39868: ! 39869: #define ASPLUS 126 ! 39870: #define ASMINUS 127 ! 39871: #define ASMUL 128 ! 39872: #define ASDIV 129 ! 39873: #define ASMOD 130 ! 39874: #define ASAND 131 ! 39875: #define ASOR 132 ! 39876: #define ASER 133 ! 39877: #define ASLS 134 ! 39878: #define ASRS 135 ! 39879: ! 39880: #define ARG 136 ! 39881: #define ARGS 137 ! 39882: #define ZTYPE 138 ! 39883: #define ARGT 139 ! 39884: #define ELIST 140 ! 39885: #define ANY 141 ! 39886: #define TABLE 142 ! 39887: #define LOC 143 ! 39888: #define DUMMY 144 ! 39889: #define G_ADDROF 145 ! 39890: #define G_CALL 146 ! 39891: #define G_CM 147 ! 39892: #define IVAL 150 ! 39893: //#define FVAL 151 ! 39894: //#define LVAL 152 ! 39895: #define ELLIPSIS 155 ! 39896: #define AGGR 156 ! 39897: #define VALUE 157 /* constructor call */ ! 39898: #define RPTR 158 /* reference */ ! 39899: #define HIDDEN 159 ! 39900: #define MEM 160 ! 39901: #define CTOR 161 ! 39902: #define DTOR 162 ! 39903: #define CONST_PTR 163 ! 39904: #define CONST_RPTR 164 ! 39905: #define TEXT 165 ! 39906: #define PAIR 166 ! 39907: #define ANON 167 ! 39908: #define ICALL 168 ! 39909: #define ANAME 169 ! 39910: #define VOLATILE 170 ! 39911: #define SIGNED 171 ! 39912: #define UPLUS 172 ! 39913: #define MEMPTR 173 ! 39914: #define PRIVATE 174 ! 39915: #define PR 175 /* PUBLIC PRIVATE or PROTECTED */ ! 39916: #define MDOT 177 ! 39917: #define TSCOPE 178 ! 39918: #define DECL_MARKER 179 ! 39919: #define REFMUL 180 ! 39920: #define LDOUBLE 181 ! 39921: #define LINKAGE 182 ! 39922: #define LOCAL 183 ! 39923: #define GNEW 184 ! 39924: #define TEMPLATE 185 ! 39925: #define STAT_INIT 186 ! 39926: #define CATCH 187 ! 39927: #define GDELETE 188 ! 39928: //#define CONVERT 189 ! 39929: #define NESTED 190 ! 39930: #define TRY 191 ! 39931: ! 39932: // class parameterized types constants ! 39933: #define XVIRT 200 /* class virt */ ! 39934: #define XNLIST 201 /* struct name_list */ ! 39935: #define XILINE 202 ! 39936: #define XIA 203 ! 39937: #define STATEMENT 205 ! 39938: #define EXPRESSION 206 ! 39939: #define SM_PARAM 207 ! 39940: #define TEMPLATE_TEST 208 ! 39941: #define PTNAME 209 ! 39942: #define NEW_INIT_KLUDGE 210 ! 39943: #define XDELETED_NODE 211 ! 39944: #define DUMMY_LAST_NODE 212 ! 39945: ! 39946: //#define SYN 1 ! 39947: //#define TYP 2 ! 39948: //#define SIMPL 3 ! 39949: //#define ERROR 4 ! 39950: ! 39951: //#define ICTOR 88 ! 39952: //#define IDTOR 89 ! 39953: 0707071010112046131004440001630000160000010212340466055422200001600000006724token_names.h /* ident "@(#)ctrans:src/token_names.h 1.2" */ ! 39954: struct _token_name { char * string; int val; } token_names [] = { ! 39955: { "EOFTOK", 0 }, ! 39956: { "ASM", 1 }, ! 39957: { "AUTO", 2 }, ! 39958: { "BREAK", 3 }, ! 39959: { "CASE", 4 }, ! 39960: { "CHAR", 5 }, ! 39961: { "CLASS", 6 }, ! 39962: { "CONTINUE", 7 }, ! 39963: { "DEFAULT", 8 }, ! 39964: { "DELETE", 9 }, ! 39965: { "DO", 10 }, ! 39966: { "DOUBLE", 11 }, ! 39967: { "ELSE", 12 }, ! 39968: { "ENUM", 13 }, ! 39969: { "EXTERN", 14 }, ! 39970: { "FLOAT", 15 }, ! 39971: { "FOR", 16 }, ! 39972: { "FORTRAN", 17 }, ! 39973: { "FRIEND", 18 }, ! 39974: { "GOTO", 19 }, ! 39975: { "IF", 20 }, ! 39976: { "INT", 21 }, ! 39977: { "LONG", 22 }, ! 39978: { "NEW", 23 }, ! 39979: { "OPERATOR", 24 }, ! 39980: { "RETURN", 28 }, ! 39981: { "PUBLIC", 25 }, ! 39982: { "CONST", 26 }, ! 39983: { "REGISTER", 27 }, ! 39984: { "RETURN", 28 }, ! 39985: { "SHORT", 29 }, ! 39986: { "SIZEOF", 30 }, ! 39987: { "STATIC", 31 }, ! 39988: { "STRUCT", 32 }, ! 39989: { "SWITCH", 33 }, ! 39990: { "THIS", 34 }, ! 39991: { "TYPEDEF", 35 }, ! 39992: { "UNION", 36 }, ! 39993: { "UNSIGNED", 37 }, ! 39994: { "VOID", 38 }, ! 39995: { "WHILE", 39 }, ! 39996: { "LP", 40 }, ! 39997: { "RP", 41 }, ! 39998: { "LB", 42 }, ! 39999: { "RB", 43 }, ! 40000: { "REF", 44 }, ! 40001: { "DOT", 45 }, ! 40002: { "NOT", 46 }, ! 40003: { "COMPL", 47 }, ! 40004: { "INCR", 48 }, ! 40005: { "DECR", 49 }, ! 40006: { "MUL", 50 }, ! 40007: { "DIV", 51 }, ! 40008: { "AND", 52 }, ! 40009: { "MOD", 53 }, ! 40010: { "PLUS", 54 }, ! 40011: { "MINUS", 55 }, ! 40012: { "LS", 56 }, ! 40013: { "RS", 57 }, ! 40014: { "LT", 58 }, ! 40015: { "LE", 59 }, ! 40016: { "GT", 60 }, ! 40017: { "GE", 61 }, ! 40018: { "EQ", 62 }, ! 40019: { "NE", 63 }, ! 40020: { "ER", 64 }, ! 40021: { "OR", 65 }, ! 40022: { "ANDAND", 66 }, ! 40023: { "OROR", 67 }, ! 40024: { "QUEST", 68 }, ! 40025: { "COLON", 69 }, ! 40026: { "ASSIGN", 70 }, ! 40027: { "CM", 71 }, ! 40028: { "SM", 72 }, ! 40029: { "LC", 73 }, ! 40030: { "RC", 74 }, ! 40031: { "INLINE", 75 }, ! 40032: { "OVERLOAD", 76 }, ! 40033: { "VIRTUAL", 77 }, ! 40034: { "COERCE", 78 }, ! 40035: { "PROTECTED", 79 }, ! 40036: { "ID", 80 }, ! 40037: { "STRING", 81 }, ! 40038: { "ICON", 82 }, ! 40039: { "FCON", 83 }, ! 40040: { "CCON", 84 }, ! 40041: { "NAME", 85 }, ! 40042: { "ZERO", 86 }, ! 40043: { "ICTOR", 88 }, ! 40044: { "IDTOR", 89 }, ! 40045: { "ASOP", 90 }, ! 40046: { "RELOP", 91 }, ! 40047: { "EQUOP", 92 }, ! 40048: { "DIVOP", 93 }, ! 40049: { "SHIFTOP", 94 }, ! 40050: { "ICOP", 95 }, ! 40051: { "UNOP", 96 }, ! 40052: { "TYPE", 97 }, ! 40053: { "UMINUS", 107 }, ! 40054: { "FCT", 108 }, ! 40055: { "CALL", 109 }, ! 40056: { "VEC", 110 }, ! 40057: { "DEREF", 111 }, ! 40058: { "ADDROF", 112 }, ! 40059: { "CAST", 113 }, ! 40060: { "FIELD", 114 }, ! 40061: { "LABEL", 115 }, ! 40062: { "BLOCK", 116 }, ! 40063: { "QUA", 117 }, ! 40064: { "DCL", 118 }, ! 40065: { "COBJ", 119 }, ! 40066: { "EOBJ", 121 }, ! 40067: { "TNAME", 123 }, ! 40068: { "ILIST", 124 }, ! 40069: { "PTR", 125 }, ! 40070: { "ASPLUS", 126 }, ! 40071: { "ASMINUS", 127 }, ! 40072: { "ASMUL", 128 }, ! 40073: { "ASDIV", 129 }, ! 40074: { "ASMOD", 130 }, ! 40075: { "ASAND", 131 }, ! 40076: { "ASOR", 132 }, ! 40077: { "ASER", 133 }, ! 40078: { "ASLS", 134 }, ! 40079: { "ASRS", 135 }, ! 40080: { "ARG", 136 }, ! 40081: { "KNOWN", 137 }, ! 40082: { "ZTYPE", 138 }, ! 40083: { "ARGT", 139 }, ! 40084: { "ELIST", 140 }, ! 40085: { "ANY", 141 }, ! 40086: { "TABLE", 142 }, ! 40087: { "LOC", 143 }, ! 40088: { "DUMMY", 144 }, ! 40089: { "G_ADDROF", 145 }, ! 40090: { "G_CALL", 146 }, ! 40091: { "G_CM", 147 }, ! 40092: { "IVAL", 150 }, ! 40093: { "FVAL", 151 }, ! 40094: { "LVAL", 152 }, ! 40095: { "ELLIPSIS", 155 }, ! 40096: { "AGGR", 156 }, ! 40097: { "VALUE", 157 }, ! 40098: { "RPTR", 158 }, ! 40099: { "HIDDEN", 159 }, ! 40100: { "MEM", 160 }, ! 40101: { "CTOR", 161 }, ! 40102: { "DTOR", 162 }, ! 40103: { "CONST_PTR", 163 }, ! 40104: { "CONST_RPTR", 164 }, ! 40105: { "TEXT", 165 }, ! 40106: { "PAIR", 166 }, ! 40107: { "ANON", 167 }, ! 40108: { "ICALL", 168 }, ! 40109: { "ANAME", 169 }, ! 40110: { "VOLATILE", 170 }, ! 40111: { "SIGNED", 171 }, ! 40112: { "UPLUS", 172 }, ! 40113: { "MEMPTR", 173 }, ! 40114: { "PRIVATE", 174 }, ! 40115: { "PR", 175 }, ! 40116: { "MDOT", 177 }, ! 40117: { "TSCOPE", 178 }, ! 40118: { "DECL_MARKER", 179 }, ! 40119: { "REFMUL", 180 }, ! 40120: { "LDOUBLE", 181 }, ! 40121: { "LINKAGE", 182 }, ! 40122: { "LOCAL", 183 }, ! 40123: { "GNEW", 184 }, ! 40124: { "TEMPLATE", 185 }, ! 40125: { "STAT_INIT", 186 }, ! 40126: { "CATCH", 187 }, ! 40127: { "GDELETE", 188 }, ! 40128: { "CONVERT", 189 }, ! 40129: { "XVIRT", 200 }, ! 40130: { "XNLIST", 201 }, ! 40131: { "XILINE", 202 }, ! 40132: { "XIA", 203 }, ! 40133: { "STATEMENT", 205 }, ! 40134: { "EXPRESSION", 206 }, ! 40135: { "SM_PARAM", 207 }, ! 40136: { "TEMPLATE_TEST", 208 }, ! 40137: { "PTNAME", 209 }, ! 40138: { "NEW_INIT_KLUDGE", 210 }, ! 40139: { "XDELETED_NODE", 211 }, ! 40140: { "DUMMY_LAST_TOKEN", 212 }, ! 40141: }; ! 40142: 0707071010112045711004440001630000160000010156650466055412200001100000002515tqueue.h /*ident "@(#)ctrans:src/tqueue.h 1.3" */ ! 40143: /************************************************************************** ! 40144: ! 40145: C++ source for cfront, the C++ compiler front-end ! 40146: written in the computer science research center of Bell Labs ! 40147: ! 40148: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 40149: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 40150: ! 40151: tqueue.h: ! 40152: ! 40153: *****************************************************************************/ ! 40154: ! 40155: #ifndef EOF ! 40156: #include <stdio.h> ! 40157: #endif ! 40158: ! 40159: struct toknode { ! 40160: TOK tok; /* token for parser */ ! 40161: bit used; /* token has been processed by lalex() */ ! 40162: YYSTYPE retval; /* $arg */ ! 40163: loc place; ! 40164: toknode* next; ! 40165: toknode* last; ! 40166: static toknode* free_toks; ! 40167: void* operator new(size_t); ! 40168: void operator delete(void*,size_t); ! 40169: toknode(TOK,YYSTYPE,loc); ! 40170: }; ! 40171: extern toknode* front; ! 40172: extern toknode* rear; ! 40173: ! 40174: extern void addtok(TOK,YYSTYPE,loc); /* add tok to rear of Q */ ! 40175: extern TOK deltok(int); /* take tok from front of Q */ ! 40176: extern TOK tlex(); ! 40177: ! 40178: // interface to parser ! 40179: extern TOK lalex(); ! 40180: extern int yychar; ! 40181: extern YYSTYPE yylval; ! 40182: extern TOK la_look(); ! 40183: extern void la_backup( TOK, YYSTYPE ); ! 40184: extern int la_cast(); ! 40185: extern void check_decl(); ! 40186: extern void check_cast(); ! 40187: extern TOK lalex(); ! 40188: ! 40189: // save / restore implicit inline functions ! 40190: extern toknode* save_text(); ! 40191: extern void restore_text(); ! 40192: 0707071010112046041004440001630000160000010211700466055416700001400000014274tree_copy.c /* ident "@(#)ctrans:src/tree_copy.c 1.3" */ ! 40193: /* ! 40194: $Source: /usr3/lang/benson/work/stripped_cfront/RCS/tree_copy.c,v $ $RCSfile: tree_copy.c,v $ ! 40195: $Revision: 1.1 $ $Date: 89/11/20 08:51:04 $ ! 40196: $Author: benson $ $Locker: $ ! 40197: $State: Exp $ ! 40198: */ ! 40199: ! 40200: /* utilities to copy pieces of cfront trees. ! 40201: what we have here is a somewhat parameterizable ! 40202: action procedure for the tree walker. ! 40203: ! 40204: We may make more versions of this for template expansion ! 40205: and saving things in files, or we may just make it possible ! 40206: for this to swing more ways. ! 40207: */ ! 40208: ! 40209: #include "cfront.h" ! 40210: #include "tree_walk.h" ! 40211: #include "tree_copy.h" ! 40212: #include <memory.h> ! 40213: ! 40214: /* determine whether "n" is a an already defined type */ ! 40215: static unsigned int type_is_defined(Pnode n) { ! 40216: return (Ptype(n)->defined & DEFINED) ; ! 40217: } ! 40218: ! 40219: void ! 40220: copy_walker (Pnode& node, node_class cl, void * info, ! 40221: tree_node_action& action, int, Pnode, tree_walk_tree&, ! 40222: int& register_in_hash) ! 40223: { ! 40224: union { ! 40225: Pnode node; ! 40226: Pvirt vr; ! 40227: Plist list; ! 40228: Pgen g; ! 40229: Pvec vc; ! 40230: Pfct f; ! 40231: Ptable t; ! 40232: Pbase bt; ! 40233: Pexpr x; ! 40234: Pstmt s; ! 40235: Penum e; ! 40236: Pclass c; ! 40237: Pbcl bcl; ! 40238: Pin iline; ! 40239: ia * ia; ! 40240: Pname n; ! 40241: Pptr p; ! 40242: } n; ! 40243: Pnode original_node = node; ! 40244: ! 40245: tree_copy_info * tci = (tree_copy_info *)info; ! 40246: action = tna_continue; ! 40247: ! 40248: /* first, give an application-specific hook a shot at the node. */ ! 40249: ! 40250: tci->check_node(node, cl, action, register_in_hash); ! 40251: if(action != tna_continue) return; ! 40252: ! 40253: if(node != original_node) { /* a replacement */ ! 40254: n.node = node; ! 40255: } else /* ok, nothing funny, we just go ahead and copy */ ! 40256: switch (cl) { ! 40257: default: ! 40258: break; ! 40259: case nc_eof: ! 40260: n.node = Pnode(tci->malloc(sizeof (node))); ! 40261: *n.node = *node; ! 40262: goto Replace; ! 40263: ! 40264: case nc_virt: ! 40265: n.vr = Pvirt(tci->malloc(sizeof(virt))); ! 40266: *n.vr = *Pvirt(node); ! 40267: goto Replace; ! 40268: ! 40269: case nc_nlist: ! 40270: n.list = Plist(tci->malloc(sizeof(name_list))); ! 40271: *n.list = *Plist(node); ! 40272: goto Replace; ! 40273: ! 40274: case nc_gen: ! 40275: n.g = Pgen(tci->malloc(sizeof(gen))); ! 40276: *n.g = *Pgen(node); ! 40277: goto Replace; ! 40278: ! 40279: case nc_vec: ! 40280: n.vc = Pvec(tci->malloc(sizeof(vec))); ! 40281: *n.vc = *Pvec(node); ! 40282: goto Replace; ! 40283: ! 40284: case nc_ptr: ! 40285: n.p = Pptr(tci->malloc(sizeof(ptr))); ! 40286: *n.p = *Pptr(node); ! 40287: goto Replace; ! 40288: ! 40289: case nc_fct: ! 40290: n.f = Pfct(tci->malloc(sizeof(fct))); ! 40291: *n.f = *Pfct(node); ! 40292: if(n.f->f_signature) { ! 40293: n.f->f_signature = ! 40294: (char *)tci->malloc(strlen(Pfct(node)->f_signature)+1); ! 40295: strcpy(n.f->f_signature, Pfct(node)->f_signature); ! 40296: }; ! 40297: goto Replace; ! 40298: ! 40299: case nc_table: ! 40300: n.t = Ptable(tci->malloc(sizeof(table))); ! 40301: *n.t = *Ptable(node); ! 40302: n.t->entries = (Pname *)tci->malloc(sizeof(Pname) * n.t->size); ! 40303: memcpy((char *)n.t->entries, (char *)Ptable(node)->entries, n.t->size * sizeof(Pname)); ! 40304: n.t->hashtbl = (short *)tci->malloc(sizeof(short) * n.t->hashsize); ! 40305: memcpy((char *)n.t->hashtbl, (char *)Ptable(node)->hashtbl, n.t->hashsize * sizeof (short)); ! 40306: goto Replace; ! 40307: ! 40308: case nc_basetype: ! 40309: // Don't copy types that have already been dealt with ! 40310: if (type_is_defined(node)) { ! 40311: action = tna_stop ; ! 40312: return ; ! 40313: } ! 40314: n.bt = Pbase(tci->malloc(sizeof(basetype))); ! 40315: *n.bt = *Pbase(node); ! 40316: if(n.bt->discriminator(0) == 2 && n.bt->b_linkage) { ! 40317: n.bt->b_linkage = tci->malloc(strlen(n.bt->b_linkage) + 1); ! 40318: strcpy(n.bt->b_linkage, Pbase(node)->b_linkage); ! 40319: } ! 40320: goto Replace; ! 40321: ! 40322: case nc_expr: ! 40323: // cfront needs identity maintaied for these nodes ! 40324: if ((node == dummy) || (node == zero)) { ! 40325: action = tna_stop ; ! 40326: return ; ! 40327: } ! 40328: n.x = Pexpr(tci->malloc(sizeof(expr))); ! 40329: *n.x = *Pexpr(node); ! 40330: if(n.x->discriminator(1) == 3 && n.x->string) { ! 40331: n.x->string = tci->malloc(strlen(n.x->string) + 1); ! 40332: strcpy(n.x->string, Pexpr(node)->string); ! 40333: } ! 40334: if(n.x->discriminator(2) == 3 && n.x->string2) { ! 40335: n.x->string2 = tci->malloc(strlen(n.x->string2) + 1); ! 40336: strcpy(n.x->string2, Pexpr(node)->string2); ! 40337: } ! 40338: goto Replace; ! 40339: ! 40340: case nc_stmt: ! 40341: n.s = Pstmt(tci->malloc(sizeof(stmt))); ! 40342: *n.s = *Pstmt(node); ! 40343: goto Replace; ! 40344: ! 40345: case nc_enumdef: ! 40346: if (type_is_defined(node)) { ! 40347: action = tna_stop ; ! 40348: return ; ! 40349: } ! 40350: n.e = Penum(tci->malloc(sizeof(enumdef))); ! 40351: *n.e = *Penum(node); ! 40352: if(n.e->string) { ! 40353: n.e->string = tci->malloc(n.e->strlen+1); ! 40354: strcpy(n.e->string, Penum(node)->string); ! 40355: } ! 40356: goto Replace; ! 40357: ! 40358: case nc_classdef: ! 40359: // Don't copy types that have already been dealt with ! 40360: if (type_is_defined(node)) { ! 40361: action = tna_stop ; ! 40362: return ; ! 40363: } ! 40364: n.c = Pclass(tci->malloc(sizeof(classdef))); ! 40365: *n.c = *Pclass(node); ! 40366: if(n.c->string) { ! 40367: n.c->string = tci->malloc(strlen(n.c->string)+1); ! 40368: strcpy(n.c->string, Pclass(node)->string); ! 40369: } ! 40370: goto Replace; ! 40371: ! 40372: case nc_baseclass: ! 40373: n.bcl = Pbcl(tci->malloc(sizeof(struct basecl))); ! 40374: *n.bcl = *Pbcl(node); ! 40375: goto Replace; ! 40376: ! 40377: case nc_iline: ! 40378: n.iline = Pin(tci->malloc(sizeof(iline))); ! 40379: *n.iline = *Pin(node); ! 40380: goto Replace; ! 40381: ! 40382: case nc_ia: ! 40383: n.ia = (ia *)tci->malloc(sizeof(ia)); ! 40384: *n.ia = *(ia *)node; ! 40385: goto Replace; ! 40386: ! 40387: case nc_name: ! 40388: /* check for globalosity */ ! 40389: if(Pname(node)->string && (node == (node->base == TNAME ? ktbl : gtbl)->look(Pname(node)->string, 0))) { ! 40390: action = tna_stop; ! 40391: return; ! 40392: } ! 40393: n.n = Pname(tci->malloc(sizeof(name))); ! 40394: *n.n = *Pname(node); ! 40395: /* First, hack exprosity */ ! 40396: if(n.x->discriminator(1) == 3 && n.n->string) { ! 40397: n.n->string = tci->malloc(strlen(n.n->string) + 1); ! 40398: strcpy(n.n->string, Pexpr(node)->string); ! 40399: } ! 40400: if(n.x->discriminator(2) == 3 && n.n->string2) { ! 40401: n.n->string2 = tci->malloc(strlen(n.n->string2) + 1); ! 40402: strcpy(n.n->string2, Pexpr(node)->string2); ! 40403: /* ok, name stuff */ ! 40404: } ! 40405: if(n.n->n_anon) { ! 40406: n.n->n_anon = tci->malloc(strlen(n.n->n_anon)+1); ! 40407: strcpy(n.n->n_anon, Pname(node)->n_anon); ! 40408: } ! 40409: if(n.n->n_template_arg_string) { ! 40410: n.n->n_template_arg_string = ! 40411: tci->malloc(strlen(n.n->n_template_arg_string)+1); ! 40412: strcpy(n.n->n_template_arg_string, Pname(node)->n_template_arg_string); ! 40413: } ! 40414: } ! 40415: Replace: ! 40416: node = n.node; ! 40417: action = tna_continue; ! 40418: return; ! 40419: } ! 40420: ! 40421: static int call_error (int i, const char * s) ! 40422: { ! 40423: return error (i, s); ! 40424: } ! 40425: ! 40426: void ! 40427: copy_tree (Pnode& node, tree_copy_info& tci, Hash * cht) ! 40428: { ! 40429: tree_walk_control twc; ! 40430: ! 40431: twc.call_i_error = 1; ! 40432: twc.i_error = call_error; /* ... in type of error confuses compiler */ ! 40433: twc.action_proc = copy_walker; ! 40434: twc.nodes_seen_hash = cht; ! 40435: twc.callback_info = (void *)&tci; ! 40436: ! 40437: walk_tree (twc, node); ! 40438: } ! 40439: ! 40440: 0707071010112046141004440001630000160000010210160466055422600001400000003011tree_copy.h /* ident "@(#)ctrans:src/tree_copy.h 1.2" */ ! 40441: /* -*- Mode: C -*- begin include file tree_copy.H ! 40442: argument class for copying trees. */ ! 40443: ! 40444: #include "hash.h" ! 40445: #include "tree_walk.h" ! 40446: ! 40447: /* The copier procedure expects one of these as its ! 40448: info pointer */ ! 40449: ! 40450: class tree_copy_info { ! 40451: public: ! 40452: /* If non-zero, this procedure is called at each node. ! 40453: it returns an action. It cannot currently return ! 40454: a node of a different class and also return an ! 40455: action other than tna_stop, since the walker won't ! 40456: notice that the rug has been removed from beneath its feet. ! 40457: The procedure must set the last argument to indicate whether ! 40458: or not to register the node in the hash table and use the ! 40459: replacement every future time it is encountered. ! 40460: */ ! 40461: ! 40462: void (* node_hook) (void * info, Pnode&, node_class, tree_node_action&, ! 40463: int&); ! 40464: ! 40465: /* if this is nonzero it is used to allocate space for ! 40466: the copies. We don't run constructors since we always ! 40467: bit copy over the new copy. */ ! 40468: char * (* malloc_hook) (void * info, size_t); ! 40469: void * hook_info; ! 40470: tree_copy_info () ! 40471: { ! 40472: hook_info = 0; ! 40473: node_hook = 0; ! 40474: malloc_hook = 0; ! 40475: }; ! 40476: char * malloc (size_t s) { ! 40477: return malloc_hook ? malloc_hook(hook_info, s) : ::malloc (s); ! 40478: }; ! 40479: void check_node (Pnode& n, ! 40480: node_class cl, ! 40481: tree_node_action& action, ! 40482: int& never_see_again) { ! 40483: if(node_hook) ! 40484: node_hook(hook_info, n, cl, action, never_see_again); ! 40485: }; ! 40486: }; ! 40487: ! 40488: void copy_tree (Pnode& n, tree_copy_info& tci, Hash * cht = 0); ! 40489: ! 40490: /* End tree_copy.H */ ! 40491: ! 40492: 0707071010112046161004440001630000160000010213300466055423500001400000061200tree_dump.c /* ident "@(#)ctrans:src/tree_dump.c 1.2" */ ! 40493: /* -*- Mode:C++ -*- */ ! 40494: /* tree_dump.C -- utilities for displaying the cfront tree. */ ! 40495: /* BIM 890530 */ ! 40496: /* rewritten 890712 to use the tree-walking facilities */ ! 40497: ! 40498: /* ! 40499: $Source: /usr3/lang/benson/work/stripped_cfront/RCS/tree_dump.c,v $ $RCSfile: tree_dump.c,v $ ! 40500: $Revision: 1.1 $ $Date: 89/11/20 08:50:22 $ ! 40501: $Author: benson $ $Locker: $ ! 40502: $State: Exp $ ! 40503: ! 40504: ! 40505: */ ! 40506: ! 40507: #include "tree_dump.h" ! 40508: #include <stdio.h> ! 40509: #include <malloc.h> ! 40510: #include "template.h" ! 40511: #include "token_names.h" ! 40512: ! 40513: const int Indent_Increment = 4; ! 40514: static char badnamebuf[100]; ! 40515: ! 40516: char * ! 40517: token_name(TOK t) ! 40518: { ! 40519: char * bnb = badnamebuf; ! 40520: ! 40521: if((int) t == -1) return "-1"; ! 40522: if(t > DUMMY_LAST_NODE) { ! 40523: bad: ! 40524: printf_to_string(bnb, sizeof(badnamebuf), ! 40525: "<unknown token %d>", (int) t); ! 40526: return bnb; ! 40527: } ! 40528: int x; ! 40529: for (x = 0; x < DUMMY_LAST_NODE; x++) { ! 40530: if(token_names[x].val == t) return token_names[x].string; ! 40531: } ! 40532: goto bad; ! 40533: } ! 40534: ! 40535: class displayer{ ! 40536: public: ! 40537: dcn_arg * arg; ! 40538: Pnode node; ! 40539: Pnode node_address; ! 40540: displayer (dcn_arg& d) { arg = &d; indent = 0; print_null_values = 0; }; ! 40541: void do_node (Pnode& node, node_class cl, tree_node_action& action, int depth, Pnode); ! 40542: private: ! 40543: enum ppc {print_ptr_copy = 0, print_ptr_copied = 1}; ! 40544: int indent; ! 40545: int err; ! 40546: int print_null_values; ! 40547: void printf (const char *, ...); ! 40548: void catprintf (const char *, ...); ! 40549: void print_ptr (const char *, Pnode); ! 40550: void print_ptr (Pnode, ppc = print_ptr_copy); ! 40551: void minimal (); ! 40552: void a_basetype (); ! 40553: void a_basecl() ; ! 40554: void a_type() ; ! 40555: void a_node() ; ! 40556: void a_name (); ! 40557: void a_expr (int from_name = 0); ! 40558: void a_fct (); ! 40559: void a_stmt (); ! 40560: void a_enumdef (); ! 40561: void a_table(); ! 40562: void a_classdef (); ! 40563: void a_gen (); ! 40564: void a_vec (); ! 40565: void a_ptr (); ! 40566: void a_virt (); ! 40567: void a_nlist (); ! 40568: void a_iline (); ! 40569: void a_elist (); ! 40570: void a_ia (); ! 40571: void a_by_name (); ! 40572: void print_loc(loc&); ! 40573: void * display_address () { return node_address; } ! 40574: void fetch (void * addr, unsigned long length, void *& taddr); ! 40575: void fetch_string (void * addr, unsigned long length, void *& taddr); ! 40576: void free_fetched(void *); ! 40577: void flag (int, const char *); ! 40578: void print_string (const char *, void *); ! 40579: void print_string_brief (void *); ! 40580: void null_field (const char *); ! 40581: void nz_printf(const char *format, const int i) ; ! 40582: void nz_printf(const char *format, const char *p) ; ! 40583: void nz_printf(const char *format, const long l) ; ! 40584: void ind(); ! 40585: }; ! 40586: ! 40587: const char many_spaces[] = " "; ! 40588: ! 40589: inline void ! 40590: displayer::ind() ! 40591: { ! 40592: arg->output_stream->write(many_spaces, indent); ! 40593: } ! 40594: ! 40595: /* call me for full lines */ ! 40596: ! 40597: void ! 40598: displayer::printf (const char * format, ...) ! 40599: { ! 40600: va_list args; ! 40601: va_start(args, format); ! 40602: ! 40603: ind(); ! 40604: vostream_printf (format, args, *arg->output_stream); ! 40605: arg->output_stream->write("\n", 1); ! 40606: va_end (args); ! 40607: } ! 40608: ! 40609: void ! 40610: displayer::catprintf (const char * format, ...) ! 40611: { ! 40612: va_list args; ! 40613: va_start(args, format); ! 40614: ! 40615: vostream_printf (format, args, *arg->output_stream); ! 40616: va_end (args); ! 40617: } ! 40618: ! 40619: void ! 40620: displayer::minimal () ! 40621: { ! 40622: print_ptr(node, print_ptr_copied); ! 40623: } ! 40624: ! 40625: void ! 40626: displayer::print_ptr(const char * label, Pnode node) ! 40627: { ! 40628: if(node || print_null_values) { ! 40629: ind(); ! 40630: catprintf("%s:\t", label); ! 40631: print_ptr(node); ! 40632: catprintf("\n"); ! 40633: } ! 40634: } ! 40635: ! 40636: ! 40637: void ! 40638: displayer::print_ptr(Pnode node, ppc copy_ptr) ! 40639: { ! 40640: void * string = 0; ! 40641: void * ncopy; ! 40642: void * na = (void *)node; ! 40643: ! 40644: if(node) { ! 40645: ! 40646: if(copy_ptr == print_ptr_copy) { ! 40647: fetch(na, sizeof(node), ncopy); ! 40648: node = Pnode(ncopy); ! 40649: } else ncopy = node; ! 40650: ! 40651: switch(node->base) { ! 40652: case CLASS: ! 40653: free_fetched(ncopy); ! 40654: fetch(na, sizeof(classdef),ncopy); ! 40655: node = Pnode(ncopy); ! 40656: string = Pclass(node)->string; ! 40657: break; ! 40658: case ENUM: ! 40659: free_fetched(ncopy); ! 40660: fetch(na, sizeof(enumdef),ncopy); ! 40661: node = Pnode(ncopy); ! 40662: string = Penum(node)->string; ! 40663: break; ! 40664: case NAME: ! 40665: case TNAME: ! 40666: case PUBLIC: ! 40667: case PROTECTED: ! 40668: if(!node->baseclass) { ! 40669: free_fetched(ncopy); ! 40670: fetch(na, sizeof(name),ncopy); ! 40671: node = Pnode(ncopy); ! 40672: string = Pname(node)->string; ! 40673: } ! 40674: break; ! 40675: } ! 40676: if(string) { ! 40677: catprintf("<%s |0x%p ", token_name(node->base), na); ! 40678: print_string_brief(string); ! 40679: catprintf(">"); ! 40680: } ! 40681: else catprintf("<%s |0x%p>", token_name(node->base), na); ! 40682: free_fetched (ncopy); ! 40683: } ! 40684: else catprintf("Null"); ! 40685: } ! 40686: ! 40687: void ! 40688: displayer::do_node (Pnode& n, node_class cl, tree_node_action& action, ! 40689: int depth, Pnode na) ! 40690: { ! 40691: int forced_min = 0; ! 40692: int printed_min = 0; ! 40693: int prune = 0; ! 40694: ! 40695: switch(cl) { ! 40696: case nc_table: ! 40697: if(depth > 0 && !arg->walk_tables)prune = 1; ! 40698: case nc_fct: ! 40699: case nc_classdef: ! 40700: case nc_enumdef: ! 40701: if(arg->stop_at_top && depth > 1) prune = 1; ! 40702: break; ! 40703: } ! 40704: ! 40705: if((arg->max_depth > 0) && (depth >= arg->max_depth)) ! 40706: prune = 1; ! 40707: ! 40708: if(prune || arg->max_depth == 0) ! 40709: action = tna_stop; ! 40710: else action = tna_continue; ! 40711: ! 40712: node = n; ! 40713: node_address = na; ! 40714: ! 40715: if(arg->verbose == dt_brief || prune) { ! 40716: printed_min = 1; ! 40717: minimal(); ! 40718: } ! 40719: else { ! 40720: switch(cl) ! 40721: { ! 40722: default: ! 40723: case nc_unused: ! 40724: ostream_printf(*arg->error_stream, "Unknown node %d\n", node->base); ! 40725: forced_min = 1; ! 40726: ! 40727: case nc_eof: ! 40728: minimal(); ! 40729: printed_min = 1; ! 40730: break; ! 40731: ! 40732: case nc_virt: ! 40733: a_virt (); ! 40734: break; ! 40735: ! 40736: case nc_nlist: ! 40737: a_nlist(); ! 40738: break; ! 40739: ! 40740: case nc_gen: ! 40741: a_gen(); ! 40742: break; ! 40743: ! 40744: case nc_vec: ! 40745: a_vec(); ! 40746: break; ! 40747: ! 40748: case nc_ptr: ! 40749: a_ptr(); ! 40750: break; ! 40751: ! 40752: case nc_fct: ! 40753: a_fct(); ! 40754: break; ! 40755: ! 40756: case nc_table: ! 40757: a_table(); ! 40758: break; ! 40759: ! 40760: case nc_basetype: ! 40761: a_basetype(); ! 40762: break; ! 40763: ! 40764: case nc_name: ! 40765: a_name(); ! 40766: break; ! 40767: ! 40768: case nc_expr: ! 40769: a_expr(); ! 40770: break; ! 40771: ! 40772: case nc_stmt: ! 40773: a_stmt(); ! 40774: break; ! 40775: ! 40776: case nc_enumdef: ! 40777: a_enumdef(); ! 40778: break; ! 40779: ! 40780: case nc_classdef: ! 40781: a_classdef(); ! 40782: break; ! 40783: ! 40784: case nc_baseclass: ! 40785: a_basecl (); ! 40786: break; ! 40787: ! 40788: case nc_iline: ! 40789: a_iline(); ! 40790: break; ! 40791: ! 40792: case nc_ia: ! 40793: a_ia(); ! 40794: break; ! 40795: ! 40796: } ! 40797: if(printed_min) catprintf(">"); ! 40798: } ! 40799: } ! 40800: ! 40801: ! 40802: void ! 40803: displayer::flag(int f, const char * n) ! 40804: { ! 40805: if(f)catprintf("%s", n); ! 40806: } ! 40807: ! 40808: void ! 40809: displayer::free_fetched (void * addr) ! 40810: { ! 40811: if (arg->fetcher != null_tfp) /* not in the same address space. */ ! 40812: free ((char *)addr); ! 40813: } ! 40814: ! 40815: ! 40816: void ! 40817: displayer::fetch (void * addr, unsigned long length, void *& taddr) ! 40818: { ! 40819: if (arg->fetcher == null_tfp) { /* in the same address space. */ ! 40820: taddr = addr; ! 40821: err = 0; ! 40822: } else { ! 40823: taddr = (void *)malloc ((unsigned int)length); ! 40824: err = arg->fetcher (arg->fetcher_info, ! 40825: addr, ! 40826: length, ! 40827: 0, ! 40828: taddr); ! 40829: } ! 40830: } ! 40831: ! 40832: void ! 40833: displayer::fetch_string (void * addr, unsigned long length, void *& taddr) ! 40834: { ! 40835: if (arg->fetcher == null_tfp) { /* in the same address space. */ ! 40836: taddr = addr; ! 40837: err = 0; ! 40838: } else { ! 40839: taddr = (void *)malloc ((unsigned int)length); ! 40840: err = arg->fetcher (arg->fetcher_info, ! 40841: addr, ! 40842: length, ! 40843: 1, ! 40844: taddr); ! 40845: } ! 40846: } ! 40847: ! 40848: /* Print the field, only if it has a non_zero value, or requested to print */ ! 40849: /* always */ ! 40850: void ! 40851: displayer::nz_printf(const char *format, const int i) ! 40852: { ! 40853: if (i || print_null_values) { ! 40854: printf(format, i) ; ! 40855: } ! 40856: } ! 40857: ! 40858: void ! 40859: displayer::nz_printf(const char *format, const char *p) ! 40860: { ! 40861: if (p || print_null_values) { ! 40862: printf(format, (p ? p : "0")) ; ! 40863: } ! 40864: } ! 40865: ! 40866: ! 40867: void ! 40868: displayer::nz_printf(const char *format, const long i) ! 40869: { ! 40870: if (i || print_null_values) { ! 40871: printf(format, i) ; ! 40872: } ! 40873: } ! 40874: ! 40875: void ! 40876: displayer::a_node() ! 40877: { ! 40878: struct node &n = *node ; ! 40879: ! 40880: nz_printf("$node", n.permanent); ! 40881: // nz_printf("n_key:\t%d", (int)n.n_key) ; ! 40882: nz_printf("permanent:\t%d", n.permanent) ; ! 40883: nz_printf("baseclass:\t%d", n.baseclass) ; ! 40884: } ! 40885: ! 40886: ! 40887: ! 40888: void ! 40889: displayer::a_type() ! 40890: { ! 40891: struct type& t = *Ptype(node); ! 40892: int show_up = t.defined /* || t.inline_temp_index != 0 */; ! 40893: ! 40894: if(show_up) { ! 40895: printf("$type") ; ! 40896: nz_printf("defined:\t%d", t.defined) ; ! 40897: // nz_printf("inline_temp_index:\t%d", t.inline_temp_index); ! 40898: indent += Indent_Increment; ! 40899: } ! 40900: a_node(); ! 40901: if(show_up) indent -= Indent_Increment; ! 40902: } ! 40903: ! 40904: ! 40905: ! 40906: ! 40907: ! 40908: void ! 40909: displayer::null_field(const char * name) ! 40910: { ! 40911: nz_printf( "%s:\t0", name); ! 40912: } ! 40913: ! 40914: ! 40915: void ! 40916: displayer::a_basecl() ! 40917: { ! 40918: struct basecl& bc = *Pbcl(node); ! 40919: ! 40920: printf("$basecl %s |0x%p", ! 40921: token_name(node->base), ! 40922: node_address); ! 40923: ! 40924: nz_printf ("ppp:\t%s", token_name(bc.ppp)) ; ! 40925: nz_printf ("allocated:\t%d", bc.allocated) ; ! 40926: nz_printf ("promoted:\t%d", bc.promoted) ; ! 40927: print_ptr("bclass", bc.bclass); ! 40928: nz_printf ("ptr_offset:\t%d", bc.ptr_offset) ; ! 40929: nz_printf ("obj_offset:\t%d", bc.obj_offset) ; ! 40930: indent += Indent_Increment; ! 40931: a_node(); /* do the supertype. */ ! 40932: indent -= Indent_Increment; ! 40933: } ! 40934: ! 40935: ! 40936: ! 40937: ! 40938: void ! 40939: displayer::a_basetype () ! 40940: { ! 40941: struct basetype& bt = *Pbase(node); ! 40942: ! 40943: printf("$basetype %s |0x%p", ! 40944: token_name(node->base), ! 40945: node_address); ! 40946: ! 40947: ind(); ! 40948: catprintf("Flags:\t"); ! 40949: flag(bt.b_unsigned, "unsigned "); ! 40950: flag(bt.b_signed, "signed "); ! 40951: flag(bt.b_volatile, "volatile "); ! 40952: flag(bt.b_const, "const "); ! 40953: flag(bt.b_typedef, "typedef "); ! 40954: flag(bt.b_virtual, "virtual "); ! 40955: flag(bt.b_short, "short "); ! 40956: flag(bt.b_long, "long "); ! 40957: catprintf("\n"); ! 40958: nz_printf( "b_bits:\t%d", bt.b_bits); ! 40959: nz_printf( "b_offset:\t%d", bt.b_offset); ! 40960: nz_printf( "b_sto:\t%s", bt.b_sto ? token_name(bt.b_sto) : 0); ! 40961: switch(bt.discriminator(0)) { ! 40962: case 1: ! 40963: print_ptr("b_fieldtype", bt.b_fieldtype); ! 40964: break; ! 40965: case 2: ! 40966: nz_printf( "b_linkage:\t%s", bt.b_linkage ? "C" : "0(C++)"); ! 40967: } ! 40968: ! 40969: print_ptr("b_name", bt.b_name); ! 40970: print_ptr("b_table", bt.b_table); ! 40971: // print_ptr("b_field", bt.b_field); ! 40972: print_ptr("b_xname", bt.b_xname); ! 40973: ! 40974: indent += Indent_Increment; ! 40975: a_type(); /* do the supertype. */ ! 40976: indent -= Indent_Increment; ! 40977: ! 40978: } ! 40979: ! 40980: void ! 40981: displayer::print_loc(loc& loc) ! 40982: { ! 40983: catprintf("file %d line %d", (int)loc.file, (int)loc.line); ! 40984: } ! 40985: ! 40986: ! 40987: void ! 40988: displayer::print_string_brief(void * addr) ! 40989: { ! 40990: void * tmp; ! 40991: ! 40992: fetch_string (addr, 1000, tmp); ! 40993: *arg->output_stream << (char *)tmp; ! 40994: free_fetched (tmp); ! 40995: } ! 40996: ! 40997: void ! 40998: displayer::print_string(const char * label, void * addr) ! 40999: { ! 41000: ind(); ! 41001: catprintf("%s:\t", label); ! 41002: print_string_brief(addr); ! 41003: *arg->output_stream << "\n"; ! 41004: } ! 41005: ! 41006: void ! 41007: displayer::a_expr(int from_name) ! 41008: { ! 41009: struct expr& e = *Pexpr(node); ! 41010: ! 41011: if(from_name) printf("$expr"); ! 41012: else printf("$expr %s |0x%p", ! 41013: token_name(node->base), ! 41014: node_address); ! 41015: ! 41016: print_ptr("tp", e.tp); ! 41017: ! 41018: switch(e.discriminator(1)) { ! 41019: case 0: break; ! 41020: case 1: ! 41021: print_ptr("e1", e.e1); ! 41022: break; ! 41023: case 2: ! 41024: printf("i1:\t%ld", e.i1); ! 41025: break; ! 41026: case 3: ! 41027: print_string("string", (void *)e.string); ! 41028: } ! 41029: ! 41030: switch(e.discriminator(2)) { ! 41031: case 0: break; ! 41032: case 1: ! 41033: print_ptr("e2", e.e2); ! 41034: break; ! 41035: case 2: ! 41036: printf("i2:\t%ld", e.i2); ! 41037: break; ! 41038: case 3: ! 41039: print_string("string2", (void *)e.string2); ! 41040: break; ! 41041: case 4: ! 41042: print_ptr("n_initializer", e.n_initializer); ! 41043: } ! 41044: ! 41045: switch(e.discriminator(3)) { ! 41046: case 0: ! 41047: break; ! 41048: case 1: print_ptr ("tp2", e.tp2); break; ! 41049: case 2: print_ptr ("fct_name", e.fct_name); break; ! 41050: case 3: print_ptr ("cond", e.cond); break; ! 41051: case 4: print_ptr ("mem", e.mem); break; ! 41052: case 5: print_ptr ("as_type", e.as_type); break; ! 41053: case 6: print_ptr ("n_table", e.n_table); break; ! 41054: case 7: print_ptr ("il", e.il); break; ! 41055: case 8: print_ptr ("query_this", e.query_this); break; ! 41056: } ! 41057: ! 41058: indent += Indent_Increment; ! 41059: a_node(); ! 41060: indent -= Indent_Increment; ! 41061: ! 41062: } ! 41063: ! 41064: void ! 41065: displayer::a_name() ! 41066: { ! 41067: struct name& n = *Pname(node); ! 41068: ! 41069: ! 41070: ind(); ! 41071: catprintf("$name %s |0x%p ", ! 41072: token_name(node->base), ! 41073: node_address); ! 41074: print_string_brief((void *)n.string); ! 41075: *arg->output_stream << "\n"; ! 41076: ! 41077: nz_printf("n_key:\t%d", (int)n.n_key) ; ! 41078: nz_printf( "n_oper:\t\t%s", n.n_oper ? ! 41079: token_name(n.n_oper) : 0); ! 41080: nz_printf( "n_sto:\t\t%s", n.n_sto ? ! 41081: token_name(n.n_sto) : 0); ! 41082: nz_printf( "n_stclass:\t%s", n.n_stclass ? ! 41083: token_name(n.n_stclass) : 0); ! 41084: nz_printf( "n_scope:\t%s", n.n_scope ? ! 41085: token_name(n.n_scope) : 0); ! 41086: nz_printf( "n_union:\t%d", n.n_union); ! 41087: nz_printf( "n_evaluated:\t%d", n.n_evaluated); ! 41088: nz_printf( "n_xref:\t\t%d", n.n_xref); ! 41089: nz_printf( "lex_level:\t%d", n.lex_level); ! 41090: nz_printf( "n_protect:\t%s", n.n_protect ? ! 41091: token_name(n.n_protect) : 0); ! 41092: if (n.n_dcl_printed || print_null_values) { ! 41093: ind(); ! 41094: catprintf("n_dcl_printed:\t%d", n.n_dcl_printed); ! 41095: ! 41096: switch(n.n_dcl_printed) ! 41097: { ! 41098: case 0: ! 41099: catprintf("(not)\n"); ! 41100: break; ! 41101: case 1: ! 41102: printf("(declaration)\n"); ! 41103: break; ! 41104: case 2: ! 41105: printf("(definition)\n"); ! 41106: break; ! 41107: } ! 41108: ! 41109: } ! 41110: if(n.n_template_arg) { ! 41111: ind(); ! 41112: catprintf( "n_template_arg:\t"); ! 41113: switch(n.n_template_arg) ! 41114: { ! 41115: case template_type_formal: ! 41116: catprintf("template_type_formal\n"); ! 41117: break; ! 41118: case template_expr_formal: ! 41119: catprintf("template_expr_formal\n"); ! 41120: break; ! 41121: case template_stmt_tree_formal: ! 41122: catprintf("template_stmt_formal\n"); ! 41123: break; ! 41124: case template_expr_tree_formal: ! 41125: catprintf("template_expr_tree_formal\n"); ! 41126: break; ! 41127: case template_actual_arg_dummy: ! 41128: catprintf("template_actual_arg_dummy\n"); ! 41129: break; ! 41130: } ; ! 41131: } ! 41132: nz_printf( "n_addr_taken:\t%d", n.n_addr_taken); ! 41133: nz_printf( "n_used:\t\t%d", n.n_used); ! 41134: nz_printf( "n_assigned_to:\t%d", n.n_assigned_to); ! 41135: ind(); ! 41136: catprintf("loc:\t\t"); ! 41137: print_loc(n.where); ! 41138: catprintf("\n"); ! 41139: nz_printf( "n_offset:\t%d", n.n_offset); ! 41140: // if(n.output_string) { print_string("output_string", (void *)n.output_string); } ! 41141: nz_printf( "n_val:\t\t%ld", n.n_val); ! 41142: ! 41143: print_ptr("n_list", n.n_list); ! 41144: print_ptr("n_tbl_list", n.n_tbl_list); ! 41145: if(n.n_gen_fct_name) ! 41146: print_string("n_gen_fct_name", n.n_gen_fct_name); ! 41147: if(n.n_template_arg_string) { ! 41148: print_string("n_template_arg_string", ! 41149: n.n_template_arg_string); ! 41150: } ! 41151: switch(n.discriminator(0)) { ! 41152: case 2: print_ptr("n_realscope", n.n_realscope); break; ! 41153: case 1: print_ptr("n_qualifier", n.n_qualifier); break; ! 41154: } ! 41155: nz_printf("n_val:\t%ld", n.n_val); ! 41156: ! 41157: indent += Indent_Increment; ! 41158: a_expr(1); /* do the supertype. */ ! 41159: indent -= Indent_Increment; ! 41160: } ! 41161: ! 41162: void ! 41163: displayer::a_fct() ! 41164: { ! 41165: struct fct& f = *Pfct(node); ! 41166: ! 41167: printf("$fct %s |0x%p", ! 41168: token_name(node->base), ! 41169: node_address); ! 41170: ! 41171: ! 41172: printf("nargs:\t\t%d", f.nargs); ! 41173: printf("nargs_known:\t%d%s", f.nargs_known, ! 41174: f.nargs_known == 0 ? " UNKNOWN" : ! 41175: (f.nargs_known == 1 ? " KNOWN" : ! 41176: (f.nargs_known == ELLIPSIS ? "ELLIPSIS" : "" ))); ! 41177: nz_printf( "f_vdef:\t\t%d", f.f_vdef); ! 41178: printf("f_inline:\t%d%s", f.f_inline, ! 41179: f.f_inline == 0 ? "" : ! 41180: f.f_inline == 1 ? " inline" : ! 41181: f.f_inline == 2 ? " inline in expansion" : ""); ! 41182: nz_printf( "f_const:\t\t%d", f.f_const); ! 41183: nz_printf( "f_static:\t\t%d", f.f_static); ! 41184: nz_printf( "f_virtual:\t%d", f.f_virtual); ! 41185: nz_printf( "f_imeasure:\t%d", f.f_imeasure); ! 41186: print_string("f_signature", (void *)f.f_signature); ! 41187: ! 41188: print_ptr("returns", f.returns); ! 41189: print_ptr("argtype", f.argtype); ! 41190: print_ptr("s_returns", f.s_returns); ! 41191: print_ptr("f_this", f.f_this); ! 41192: print_ptr("memof", f.memof); ! 41193: print_ptr("body", f.body); ! 41194: print_ptr("f_init", f.f_init); ! 41195: print_ptr("f_expr", f.f_expr); ! 41196: print_ptr("last_expanded", f.last_expanded); ! 41197: print_ptr("f_result", f.f_result); ! 41198: print_ptr("f_args", f.f_args); ! 41199: print_ptr("local_classes", f.local_class); ! 41200: ! 41201: indent += Indent_Increment; ! 41202: a_type(); /* do the supertype. */ ! 41203: indent -= Indent_Increment; ! 41204: } ! 41205: ! 41206: void ! 41207: displayer::a_stmt () ! 41208: { ! 41209: struct stmt& s = *Pstmt(node); ! 41210: ! 41211: ind(); ! 41212: catprintf("$stmt %s |0x%p ", ! 41213: token_name(node->base), ! 41214: node_address); ! 41215: print_loc(s.where); ! 41216: *arg->output_stream << "\n"; ! 41217: ! 41218: ind(); ! 41219: *arg->output_stream << "where:\t"; ! 41220: print_loc(s.where); ! 41221: *arg->output_stream << "\n"; ! 41222: ! 41223: print_ptr("s", s.s); ! 41224: print_ptr("s_list", s.s_list); ! 41225: print_ptr("memtbl", s.memtbl); ! 41226: switch(s.discriminator(0)) { ! 41227: case 1: print_ptr("d", s.d); break; ! 41228: case 2: print_ptr("e2", s.e2); break; ! 41229: case 3: print_ptr("has_default", s.has_default); break; ! 41230: case 4: nz_printf("case_value:\t0x%x", s.case_value); ! 41231: case 5: print_ptr("ret_tp", s.ret_tp); break; ! 41232: } ! 41233: switch(s.discriminator(1)) { ! 41234: case 1: print_ptr("e", s.e); break; ! 41235: case 2: nz_printf("own_tbl:\t%d", s.own_tbl); break; ! 41236: case 3: print_ptr("s2", s.s2); break; ! 41237: } ! 41238: ! 41239: switch(s.discriminator(2)) { ! 41240: case 1: print_ptr("for_init", s.for_init); break; ! 41241: case 2: print_ptr("else_stmt",s.for_init); break; ! 41242: case 3: print_ptr("case_list", s.case_list); break; ! 41243: } ! 41244: } ! 41245: ! 41246: void ! 41247: displayer::a_enumdef () ! 41248: { ! 41249: struct enumdef& e = *Penum(node); ! 41250: ! 41251: printf("$enumdef %s |0x%p", ! 41252: token_name(node->base), ! 41253: node_address); ! 41254: ! 41255: nz_printf( "e_body:\t\t%d", e.e_body); ! 41256: nz_printf( "no_of_enumerators: %d", ! 41257: e.no_of_enumerators); ! 41258: nz_printf( "strlen:\t%d", e.strlen); ! 41259: print_string ("string", (void *)e.string); ! 41260: ! 41261: print_ptr("mem", e.mem); ! 41262: print_ptr("e_type", e.e_type); ! 41263: indent += Indent_Increment; ! 41264: a_type(); /* do the supertype. */ ! 41265: indent -= Indent_Increment; ! 41266: } ! 41267: ! 41268: void ! 41269: displayer::a_classdef () ! 41270: { ! 41271: struct classdef& c = *Pclass(node); ! 41272: ! 41273: ind(); ! 41274: catprintf("$classdef %s |0x%p ", ! 41275: token_name(node->base), ! 41276: node_address); ! 41277: print_string_brief(c.string); ! 41278: *arg->output_stream << "\n"; ! 41279: ind(); ! 41280: catprintf("class_base:\t"); ! 41281: switch(c.class_base) ! 41282: { ! 41283: case vanilla_class: ! 41284: *arg->output_stream << "vanilla_class\n"; ! 41285: break; ! 41286: case template_class: ! 41287: *arg->output_stream << "template_class\n"; ! 41288: Template_Class: ! 41289: nz_printf("inst:\t\t%p", (int)Ptclass(&c)->inst); ! 41290: break; ! 41291: case instantiated_template_class: ! 41292: *arg->output_stream << "instantiated_template_class\n"; ! 41293: goto Template_Class; ! 41294: case uninstantiated_template_class: ! 41295: *arg->output_stream << "uninstantiated_template_class\n"; ! 41296: goto Template_Class; ! 41297: case relationship_class: ! 41298: *arg->output_stream << "relationship_class\n"; ! 41299: break; ! 41300: case defining_class: ! 41301: *arg->output_stream << "defining_class\n"; ! 41302: break; ! 41303: } ! 41304: ! 41305: nz_printf( "c_body:\t\t%d", c.c_body); ! 41306: printf("csu:\t\t%s", ! 41307: token_name(c.csu)); ! 41308: nz_printf( "obj_align:\t%d", c.obj_align); ! 41309: if(c.c_xref) { ! 41310: ind(); ! 41311: catprintf( "c_xref:\t%x", c.c_xref); ! 41312: flag(c.c_xref & 1, "has-vptr "); ! 41313: flag(c.c_xref & 2, "X(X&)-defined "); ! 41314: flag(c.c_xref & 4, "operator=(X&)-defined "); ! 41315: flag(c.c_xref & 8, "has-vbaseptr(s) "); ! 41316: *arg->output_stream << "\n"; ! 41317: } ! 41318: nz_printf( "virt_count:\t%d", c.virt_count); ! 41319: nz_printf( "virt_merge:\t%d", c.virt_merge); ! 41320: nz_printf( "c_abstract:\t%d", c.c_abstract); ! 41321: nz_printf( "has_vvtab:\t%d", c.has_vvtab); ! 41322: nz_printf( "strlen:\t%d", c.strlen); ! 41323: print_string ("string", (void *)c.string); ! 41324: nz_printf( "obj_size:\t%d", c.obj_size); ! 41325: nz_printf( "real_size:\t%d", c.real_size); ! 41326: nz_printf("lex_level:\t%d", c.lex_level); ! 41327: if(c.lcl)print_string("lcl", c.lcl); ! 41328: ! 41329: print_ptr("baselist", c.baselist); ! 41330: print_ptr("mem_list", c.mem_list); ! 41331: print_ptr("memtbl", c.memtbl); ! 41332: print_ptr("friend_list", c.friend_list); ! 41333: print_ptr("pubdef", c.pubdef); ! 41334: print_ptr("tn_list", c.tn_list); /* not brief */ ! 41335: print_ptr("in_class", c.in_class); ! 41336: print_ptr("in_fct", c.in_fct); ! 41337: print_ptr("this_type", c.this_type); ! 41338: print_ptr("virt_list", c.virt_list); ! 41339: print_ptr("c_ctor", c.c_ctor); ! 41340: print_ptr("c_dtor", c.c_dtor); ! 41341: print_ptr("c_itor", c.c_itor); ! 41342: print_ptr("conv", c.conv); ! 41343: indent += Indent_Increment; ! 41344: a_type(); /* do the supertype. */ ! 41345: indent -= Indent_Increment; ! 41346: } ! 41347: ! 41348: ! 41349: void ! 41350: displayer::a_virt() ! 41351: { ! 41352: virt& v = *Pvirt(node); ! 41353: void * vna; ! 41354: void * vna_e; ! 41355: int vx; ! 41356: ! 41357: printf("$virt %s |0x%p ", ! 41358: token_name(node->base), ! 41359: node_address); ! 41360: ! 41361: print_ptr("next", v.next); ! 41362: if(v.n_init) { ! 41363: printf("n_init:\t%d", v.n_init); ! 41364: printf("virt_init:"); ! 41365: for (vna = v.virt_init, vx = 0; vx < (v.n_init - 1); ! 41366: vna = (char *)vna + sizeof (velem), vx++) ! 41367: { ! 41368: fetch(vna, sizeof (velem), vna_e); ! 41369: struct velem * ve = (struct velem *) vna_e; ! 41370: ind(); ! 41371: catprintf("%d offset %d\t", vx, ve->offset); ! 41372: print_ptr(ve->n); ! 41373: free_fetched(vna_e); ! 41374: } ! 41375: } ! 41376: print_ptr("vclass", v.vclass); ! 41377: nz_printf( "\nis_vbase:\t %d", v.is_vbase); ! 41378: nz_printf( "\nprinted:\t %d", v.printed); ! 41379: } ! 41380: ! 41381: void ! 41382: displayer::a_table () ! 41383: { ! 41384: struct table& t = *Ptable(node); ! 41385: int x; ! 41386: int y; ! 41387: void * nlist; ! 41388: void * slist; ! 41389: ! 41390: printf("$table %s |0x%p", ! 41391: token_name(node->base), ! 41392: node_address); ! 41393: ! 41394: printf("init_stat:\t%d%s", t.init_stat, ! 41395: t.init_stat == 0 ? " not simplified" : ! 41396: t.init_stat == 1 ? " simplified, no inits" : ! 41397: t.init_stat == 2 ? " simplified, inits" : ! 41398: ""); ! 41399: printf("size:\t%d", t.size); ! 41400: printf("hashsize:\t%d", t.hashsize); ! 41401: printf("free_slot:\t%d", t.free_slot); ! 41402: ! 41403: /* it looks like there is an array of Pnames here ... */ ! 41404: *arg->output_stream << "\n"; ! 41405: ind(); ! 41406: *arg->output_stream << "entries:\n"; ! 41407: fetch((void *)t.entries, t.size * sizeof(Pname), nlist); ! 41408: Pname * tmp_nlist = (Pname *)nlist; ! 41409: for(x = 0; x < t.size; x ++) { ! 41410: if(tmp_nlist[x]) { ! 41411: ind(); ! 41412: *arg->output_stream << x; ! 41413: *arg->output_stream << "\t"; ! 41414: print_ptr(tmp_nlist[x]); ! 41415: unsigned char tmp_name_s[sizeof(name)]; ! 41416: void * tmp_name; ! 41417: tmp_name = (void *)&tmp_name_s[0]; ! 41418: fetch(tmp_nlist[x], sizeof(name), tmp_name); ! 41419: catprintf(" key %d\n", Pname(tmp_name)->n_key); ! 41420: } ! 41421: } ! 41422: free_fetched(nlist); ! 41423: /* and then an array of shorts for the hash table. */ ! 41424: /* we really need a tabular format here, alright. */ ! 41425: ind(); ! 41426: *arg->output_stream << "hashtbl:\n"; ! 41427: fetch(t.hashtbl, t.hashsize * sizeof(short), slist); ! 41428: short * tmp_slist = (short *)slist; ! 41429: for(x = 0;; x++ ) { ! 41430: for (y = 0; y < 11; y ++) { ! 41431: if(((x * 12) + y) > t.hashsize) break; ! 41432: catprintf("%6d ", tmp_slist[(x*12)+y]); ! 41433: } ! 41434: *arg->output_stream << "\n"; ! 41435: if(((x * 12) + y) > t.hashsize) break; ! 41436: } ! 41437: ! 41438: free_fetched (slist); ! 41439: ! 41440: print_ptr("t_name", t.t_name); ! 41441: print_ptr("real_block", t.real_block); ! 41442: print_ptr("name", t.t_name); ! 41443: print_ptr("next", t.next); ! 41444: } ! 41445: ! 41446: void ! 41447: displayer::a_gen () ! 41448: { ! 41449: struct gen& g = *Pgen(node); ! 41450: ! 41451: printf("$gen %s |0x%p", ! 41452: token_name(node->base), ! 41453: node_address); ! 41454: ! 41455: print_ptr ("fct_list", g.fct_list); ! 41456: indent += Indent_Increment; ! 41457: a_type(); /* do the supertype. */ ! 41458: indent -= Indent_Increment; ! 41459: } ! 41460: ! 41461: void ! 41462: displayer::a_vec () ! 41463: { ! 41464: struct vec& v = *Pvec(node); ! 41465: ! 41466: printf("$vec %s |0x%p", ! 41467: token_name(node->base), ! 41468: node_address); ! 41469: printf("size:\t\t%d", v.size); ! 41470: print_ptr ("typ", v.typ); ! 41471: print_ptr ("dim", v.dim); ! 41472: } ! 41473: ! 41474: void ! 41475: displayer::a_ptr () ! 41476: { ! 41477: struct ptr& p = *Pptr(node); ! 41478: ! 41479: printf("$ptr %s |0x%p", ! 41480: token_name(node->base), ! 41481: node_address); ! 41482: ind(); ! 41483: printf("rdo:\t\t%d", p.rdo); ! 41484: ind(); ! 41485: ! 41486: print_ptr ("typ", p.typ); ! 41487: print_ptr ("memof", p.memof); ! 41488: } ! 41489: ! 41490: ! 41491: void ! 41492: displayer::a_nlist() ! 41493: { ! 41494: name_list& n = *Plist(node); ! 41495: ! 41496: printf("$name_list %s |0x%p ", ! 41497: token_name(node->base), ! 41498: node_address); ! 41499: ! 41500: print_ptr("f", n.f); ! 41501: print_ptr("l", n.l); ! 41502: } ! 41503: ! 41504: void ! 41505: displayer::a_iline() ! 41506: { ! 41507: struct iline& i = *(struct iline *)node; ! 41508: ! 41509: printf("$iline %s |0x%p ", ! 41510: token_name(node->base), ! 41511: node_address); ! 41512: ! 41513: print_ptr("fct_name", i.fct_name); ! 41514: print_ptr("i_next", i.i_next); ! 41515: print_ptr("i_table", i.i_table); ! 41516: nz_printf("i_slots:\t%d", i.i_slots); ! 41517: print_ptr("i_args", i.i_args); ! 41518: } ! 41519: ! 41520: void ! 41521: displayer::a_ia() ! 41522: { ! 41523: struct ia& i = *(struct ia *)node; ! 41524: ! 41525: printf("$ia %s |0x%p ", ! 41526: token_name(node->base), ! 41527: node_address); ! 41528: ! 41529: print_ptr("local", i.local); ! 41530: print_ptr("arg", i.arg); ! 41531: print_ptr("tp", i.tp); ! 41532: } ! 41533: ! 41534: static int fetcher (void * info, ! 41535: void * pointer, ! 41536: unsigned long length, ! 41537: int zero_stop, /* for character strings.*/ ! 41538: void * target) ! 41539: { ! 41540: displayer * d = (displayer *)info; ! 41541: if(d->arg->fetcher) ! 41542: return d->arg->fetcher(d->arg->fetcher_info, pointer, length, ! 41543: zero_stop, target); ! 41544: } ! 41545: ! 41546: static void ! 41547: do_node (Pnode& node, node_class cl, void * info, tree_node_action& action, ! 41548: int depth, Pnode na, tree_walk_tree&, int&) ! 41549: { ! 41550: displayer * d = (displayer *)info; ! 41551: d->do_node(node, cl, action, depth, na); ! 41552: d->arg->output_stream->write("\n", 1); ! 41553: } ! 41554: ! 41555: ! 41556: /* Note -- declared extern "C" in tree_dump.h. */ ! 41557: ! 41558: void ! 41559: display_cfront_node (dcn_arg& arg, Pnode n) ! 41560: { ! 41561: tree_walk_control twc; ! 41562: displayer d (arg); ! 41563: ! 41564: if(arg.verbose == dt_normal)arg.max_depth = 0; ! 41565: twc.callback_info = (void *)&d; ! 41566: if(arg.fetcher) twc.fetcher = fetcher; ! 41567: twc.action_proc = do_node; ! 41568: twc.error_stream = arg.error_stream; ! 41569: twc.nodes_seen_hash = arg.nodes_seen_hash; ! 41570: twc.resolve_by_name = 0; /* we want to display the by_name nodes */ ! 41571: twc.dont_chase_lists_top = 1; /* don't display n_list or s_list peers ! 41572: at the top level. */ ! 41573: ! 41574: walk_tree(twc, n); ! 41575: ! 41576: arg.error_stream->flush(); ! 41577: arg.output_stream->flush(); ! 41578: } ! 41579: ! 41580: ! 41581: extern "C" void _fcout(); ! 41582: void _fcout () { cout.flush(); } ! 41583: 0707071010112046001004440001630000160000010207660466055415100001400000003407tree_dump.h /* ident "@(#)ctrans:src/tree_dump.h 1.2" */ ! 41584: /* -*- Mode: C -*- Begin tree_dump.h */ ! 41585: ! 41586: #ifndef _DUMP_TREE ! 41587: #define _DUMP_TREE ! 41588: ! 41589: #include "tree_walk.h" ! 41590: #include <iostream.h> ! 41591: #include "hash.h" ! 41592: ! 41593: enum dump_tree_verbosity { ! 41594: dt_brief = 1, /* minimal identification */ ! 41595: dt_normal = 2, /* all data, outpointers Brief (one level) */ ! 41596: dt_recursive_0 = 3, /* minimal, but recurse down. ! 41597: (outpointers Recursive_0) */ ! 41598: dt_recursive_1 = 4, /* all data, outpointers Recursive_2. */ ! 41599: }; ! 41600: ! 41601: class dcn_arg { ! 41602: public: ! 41603: int version; ! 41604: dump_tree_verbosity verbose; ! 41605: tree_fetch_proc fetcher; ! 41606: void * fetcher_info; ! 41607: ostream* output_stream; ! 41608: ostream* error_stream; ! 41609: int max_depth; ! 41610: Hash * nodes_seen_hash; ! 41611: /* end of version 1 */ ! 41612: int walk_tables; ! 41613: /* end of version 2 */ ! 41614: int stop_at_top; ! 41615: dcn_arg () { version = 2; ! 41616: nodes_seen_hash = 0; ! 41617: fetcher = null_tfp; ! 41618: output_stream = &cout; ! 41619: error_stream = &cerr; ! 41620: max_depth = -1; ! 41621: walk_tables = 1; ! 41622: stop_at_top = 0; ! 41623: }; ! 41624: }; ! 41625: ! 41626: ! 41627: extern "C" { ! 41628: void display_cfront_node (dcn_arg&, Pnode); ! 41629: } ! 41630: #else ! 41631: ! 41632: typedef enum dump_tree_verbosity { ! 41633: dt_brief = 1, /* minimal identification */ ! 41634: dt_normal = 2, /* all data, outpointers Brief (one level) */ ! 41635: dt_recursive_0 = 3, /* minimal, but recurse down. ! 41636: (outpointers Recursive_0) */ ! 41637: dt_recursive_1 = 4, /* all data, outpointers Recursive_2. */ ! 41638: } dump_tree_verbosity; ! 41639: ! 41640: struct dcn_arg { ! 41641: int version; /* must be 1 for now. */ ! 41642: dump_tree_verbosity verbose; ! 41643: int (*fetcher) (); ! 41644: void * fetcher_info; ! 41645: void * output_stream; /* these are c++ streams */ ! 41646: void * error_stream; ! 41647: int max_depth; ! 41648: void * nodes_seen_hash; ! 41649: int walk_tables; ! 41650: int stop_at_top; ! 41651: }; ! 41652: ! 41653: void display_cfront_node (); ! 41654: #endif ! 41655: ! 41656: /* End tree_dump.h */ ! 41657: 0707071010112046051004440001630000160000010212000466055417300001400000066517tree_walk.c /* ident "@(#)ctrans:src/tree_walk.c 1.2" */ ! 41658: /* ! 41659: tree_walk.c ! 41660: Utilities for tree-walking ! 41661: */ ! 41662: ! 41663: #include "cfront.h" ! 41664: #include "tree_walk.h" ! 41665: #include <stdarg.h> ! 41666: #include "hash.h" ! 41667: // #include <alloca.h> ! 41668: // ************ need to add an explicit call of free ! 41669: // ************ make it an ifdef ! 41670: // ??? #include <streamdefs.h> ! 41671: #include <malloc.h> ! 41672: ! 41673: class walker { ! 41674: tree_walk_control control; ! 41675: Pnode orig_addr; ! 41676: Hash *nodes_seen_hash; ! 41677: int depth; ! 41678: int made_ht; ! 41679: tree_walk_tree * cur_tree; ! 41680: public: ! 41681: walker(tree_walk_control& c) ; ! 41682: ! 41683: ~walker () { ! 41684: if(made_ht) delete nodes_seen_hash; ! 41685: } ! 41686: tree_node_action walk (Pnode&); ! 41687: tree_node_action walk_ (Pnode& n) ! 41688: { ! 41689: if(n) { ! 41690: int save_depth = depth; ! 41691: tree_walk_tree * save_cur_tree = cur_tree; ! 41692: ! 41693: depth ++; ! 41694: if(control.alloc_stack_bytes) { ! 41695: cur_tree = (tree_walk_tree *) ! 41696: // alloca (control.alloc_stack_bytes + sizeof (tree_walk_tree)); ! 41697: malloc(control.alloc_stack_bytes + sizeof (tree_walk_tree)); ! 41698: cur_tree->parent = save_cur_tree; ! 41699: } ! 41700: tree_node_action r = walk(n); ! 41701: depth = save_depth; ! 41702: return r; ! 41703: } else return tna_continue; ! 41704: } ! 41705: ! 41706: tree_node_action walk(Pgen& n) ! 41707: { return walk_ ((struct node * &)n); }; ! 41708: tree_node_action walk(Pvec& n) ! 41709: { return walk_ ((struct node * &)n); }; ! 41710: tree_node_action walk(Pptr& n) ! 41711: { return walk_ ((struct node * &)n); }; ! 41712: tree_node_action walk(Ptype& n) ! 41713: { return walk_ ((struct node * &)n); }; ! 41714: tree_node_action walk(Pfct& n) ! 41715: { return walk_ ((struct node * &)n); }; ! 41716: tree_node_action walk(Ptable& n) ! 41717: { return walk_ ((struct node * &)n); }; ! 41718: tree_node_action walk(Pbase& n) ! 41719: { return walk_ ((struct node * &)n); }; ! 41720: tree_node_action walk(Pname& n) ! 41721: { return walk_ ((struct node * &)n); }; ! 41722: tree_node_action walk(Pexpr& n) ! 41723: { return walk_ ((struct node * &)n); }; ! 41724: tree_node_action walk(Pstmt& n) ! 41725: { return walk_ ((struct node * &)n); }; ! 41726: tree_node_action walk(Pblock& n) ! 41727: { return walk_ ((struct node * &)n); }; ! 41728: tree_node_action walk(Penum& n) ! 41729: { return walk_ ((struct node * &)n); }; ! 41730: tree_node_action walk(Pclass& n) ! 41731: { return walk_ ((struct node * &)n); }; ! 41732: tree_node_action walk(Pvirt& n) ! 41733: { return walk_ ((struct node * &)n); }; ! 41734: tree_node_action walk(Plist& n) ! 41735: { return walk_ ((struct node * &)n); }; ! 41736: tree_node_action walk(Pin& n) ! 41737: { return walk_ ((struct node * &)n); }; ! 41738: tree_node_action walk(struct ia * & n) ! 41739: { return walk_ ((struct node * &)n); }; ! 41740: tree_node_action walk(Pbcl& n) ! 41741: { return walk_ ((struct node * &)n); }; ! 41742: private: ! 41743: int fetching () { return (control.fetcher != null_tfp); } ; ! 41744: void free_fetched (void *); ! 41745: int fetch (void *, unsigned long, void *&); ! 41746: int fetch (void * a, unsigned long l, Pnode& p) ! 41747: { ! 41748: int ret; ! 41749: void * t; /* this is an output argument */ ! 41750: ret = fetch(a,l,t); ! 41751: if(!ret) { ! 41752: p = Pnode(t); ! 41753: } ! 41754: return ret; ! 41755: }; ! 41756: // void error (const char *,...); ?? at&t -- to get it up quick, line 155 ! 41757: void error ( char *, unsigned long=0 ); ! 41758: tree_node_action pre_act_on_node (Pnode node, node_class nc, ! 41759: Pnode node_copy, Pnode& replacement); ! 41760: ! 41761: tree_node_action a_gen (Pnode, Pgen, Pnode&); ! 41762: tree_node_action a_vec (Pnode, Pvec, Pnode&); ! 41763: tree_node_action a_ptr (Pnode, Pptr, Pnode&); ! 41764: tree_node_action a_fct (Pnode, Pfct, Pnode&); ! 41765: tree_node_action a_table (Pnode, Ptable, Pnode&); ! 41766: tree_node_action a_basetype (Pnode, Pbase, Pnode&); ! 41767: tree_node_action a_name(Pnode, Pname, Pnode&); ! 41768: tree_node_action a_expr (Pnode, Pexpr, Pnode&); ! 41769: tree_node_action a_stmt (Pnode, Pstmt, Pnode&); ! 41770: tree_node_action a_enumdef (Pnode, Penum, Pnode&); ! 41771: tree_node_action a_classdef (Pnode, Pclass, Pnode&); ! 41772: tree_node_action a_virt (Pnode, Pvirt, Pnode&); ! 41773: tree_node_action a_name_list (Pnode, Plist, Pnode&); ! 41774: tree_node_action a_iline (Pnode, Pin, Pnode&); ! 41775: tree_node_action a_ia (Pnode, struct ia *, Pnode&); ! 41776: tree_node_action a_baseclass (Pnode, Pbcl, Pnode&); ! 41777: tree_node_action a_expr_guts (Pexpr); ! 41778: }; ! 41779: ! 41780: ! 41781: walker::walker(tree_walk_control& c) ! 41782: { control = c; ! 41783: made_ht = 0; ! 41784: if (c.nodes_seen_hash) ! 41785: nodes_seen_hash = c.nodes_seen_hash; ! 41786: else { ! 41787: nodes_seen_hash = new pointer_hash (100); ! 41788: made_ht = 1; ! 41789: } ! 41790: depth = 0; ! 41791: cur_tree = 0; ! 41792: } ! 41793: ! 41794: ! 41795: tree_node_action ! 41796: walk_tree (tree_walk_control& c, Pnode& n) ! 41797: { ! 41798: walker w (c); ! 41799: return w.walk(n); ! 41800: } ! 41801: ! 41802: ! 41803: /* error messages are of finite length, so no need to run ! 41804: around mallocing strings */ ! 41805: ! 41806: // void walker::error (const char * format, ...) ! 41807: void walker::error (char *format, unsigned long v) ! 41808: { ! 41809: va_list args; ! 41810: va_start(args, format); ! 41811: if(control.call_i_error) { ! 41812: char buf[1000]; ! 41813: // vsprintf(buf, format, args); ! 41814: // vsprintf not universal: by inspection ! 41815: // all calls are currently of 1 or 0 arguments ! 41816: sprintf(buf, format, v); ! 41817: (*control.i_error)('i', buf); ! 41818: } else { ! 41819: vostream_printf (format, args, *control.error_stream); ! 41820: *control.error_stream << "\n"; ! 41821: control.error_stream->flush(); ! 41822: } ! 41823: va_end (args); ! 41824: } ! 41825: ! 41826: ! 41827: void ! 41828: walker::free_fetched (void * addr) ! 41829: { ! 41830: if (control.fetcher != null_tfp) /* null indicates no cross-address-space */ ! 41831: free ((char *)addr); ! 41832: } ! 41833: ! 41834: int ! 41835: walker::fetch (void * addr, unsigned long length, void*& taddr) ! 41836: { ! 41837: int err; ! 41838: ! 41839: if (control.fetcher == null_tfp) { ! 41840: taddr = addr; ! 41841: return 0; ! 41842: } else { ! 41843: taddr = (void *)malloc ((unsigned int)length); ! 41844: if(taddr == 0) { ! 41845: error ("walker::fetch: failed to malloc %d bytes.", length); ! 41846: return 1; ! 41847: } ! 41848: ! 41849: err = (*control.fetcher) (control.callback_info, addr, length, 0, taddr); ! 41850: if(err) { ! 41851: error("walker::fetch: fetcher returned %d.", err); ! 41852: return 1; ! 41853: } ! 41854: } ! 41855: } ! 41856: ! 41857: /* ::walk is called with a node pointer and a reference to ! 41858: a replacement node pointer. When it returns, ! 41859: replacement will be set if the action procedure ! 41860: called on the node decided to copy it or replace it. ! 41861: There are two possible modularities. ! 41862: In case there is cross-address-space action, ! 41863: ::walk can't call the action procedure until it has ! 41864: entered the case on node bases. Once it has, ! 41865: it calls the per-structure-type procedure, ! 41866: which calls the action proc. If the action ! 41867: proc supplies a replacement, then that replacement ! 41868: will be returned up via the reference parameters to ! 41869: the per-structure procedures. ! 41870: ! 41871: It the action procedure returns tna_continue, ! 41872: then the walk continues against the new copy of the node ! 41873: so that further replacements are reflected in the new copies. ! 41874: This prevents replacement from being meaningful cross-address-space, ! 41875: since the new copy will presumably be in the current ! 41876: (and not the cross) address space. That is, if the node ! 41877: is replaced by the action proc, the pointers in the new ! 41878: node will drive the subsequent tree walk. Usually one ! 41879: would just bitcopy, and then they would be replaced in turn. ! 41880: */ ! 41881: ! 41882: tree_node_action ! 41883: walker::walk (Pnode& top) ! 41884: { ! 41885: Pnode replacement = 0; ! 41886: tree_node_action err; ! 41887: int class_err; ! 41888: node_class nclass; ! 41889: Pnode node = 0; /* assign to shut up compiler, ! 41890: which dosen't recognize pass-by-reference as a set */ ! 41891: ! 41892: orig_addr = top; ! 41893: ! 41894: if(fetching ()) { ! 41895: if(fetch((void *)top, sizeof (struct node), node)) ! 41896: return tna_error; ! 41897: } else node = top; ! 41898: ! 41899: /* This has a complete catalog of bases, rather than just a list ! 41900: of those associated with data structures. Its important ! 41901: to detect the errs. ! 41902: */ ! 41903: ! 41904: nclass = classify_node (node, class_err); ! 41905: ! 41906: if(class_err) { ! 41907: error("walker::walk: unknown node type %d.", node->base); ! 41908: free_fetched ((void *)node); ! 41909: err = tna_error; ! 41910: goto Return; ! 41911: } ! 41912: ! 41913: switch(nclass) ! 41914: { ! 41915: default: ! 41916: case nc_unused: ! 41917: error("walker::walk: unused node type %d.", node->base); ! 41918: err = tna_error; ! 41919: goto Return; ! 41920: ! 41921: case nc_eof: ! 41922: break; ! 41923: ! 41924: case nc_virt: ! 41925: fetch((void *)top, sizeof (struct virt), node); ! 41926: err = a_virt(top, Pvirt (node), replacement); ! 41927: break; ! 41928: ! 41929: case nc_nlist: ! 41930: fetch((void *)top, sizeof (struct name_list), node); ! 41931: err = a_name_list(top, (struct name_list *)node, replacement); ! 41932: break; ! 41933: ! 41934: case nc_iline: ! 41935: fetch((void *)top, sizeof (struct iline), node); ! 41936: err = a_iline(top, (struct iline *)node, replacement); ! 41937: break; ! 41938: ! 41939: case nc_gen: ! 41940: fetch((void *)top, sizeof (struct gen), node); ! 41941: err = a_gen(top, Pgen (node), replacement); ! 41942: break; ! 41943: ! 41944: case nc_vec: ! 41945: fetch((void *)top, sizeof (struct vec), node); ! 41946: err = a_vec(top, Pvec(node), replacement); ! 41947: break; ! 41948: ! 41949: case nc_ptr: ! 41950: fetch((void *)top, sizeof (struct ptr), node); ! 41951: err = a_ptr(top, Pptr(node), replacement); ! 41952: break; ! 41953: ! 41954: case nc_fct: ! 41955: fetch((void *)top, sizeof (struct fct), node); ! 41956: err = a_fct(top, Pfct(node), replacement); ! 41957: break; ! 41958: ! 41959: case nc_table: ! 41960: fetch((void *)top, sizeof (struct table), node); ! 41961: err = a_table(top, Ptable(node), replacement); ! 41962: break; ! 41963: ! 41964: case nc_basetype: ! 41965: fetch((void *)top, sizeof (struct basetype), node); ! 41966: err = a_basetype(top, Pbase(node), replacement); ! 41967: break; ! 41968: ! 41969: case nc_name: ! 41970: fetch((void *)top, sizeof (struct name), node); ! 41971: err = a_name(top, Pname(node), replacement); ! 41972: break; ! 41973: ! 41974: case nc_expr: ! 41975: fetch((void *)top, sizeof (struct expr), node); ! 41976: err = a_expr(top, Pexpr(node), replacement); ! 41977: break; ! 41978: ! 41979: case nc_stmt: ! 41980: fetch((void *)top, sizeof (struct stmt), node); ! 41981: err = a_stmt(top, Pstmt(node), replacement); ! 41982: break; ! 41983: ! 41984: case nc_enumdef: ! 41985: fetch((void *)top, sizeof (struct enumdef), node); ! 41986: err = a_enumdef(top, Penum(node), replacement); ! 41987: break; ! 41988: ! 41989: case nc_classdef: ! 41990: fetch((void *)top, sizeof (struct classdef), node); ! 41991: err = a_classdef(top, Pclass(node), replacement); ! 41992: break; ! 41993: ! 41994: case nc_ia: ! 41995: fetch((void *)top, sizeof (struct ia), node); ! 41996: err = a_ia(top, (struct ia *)node, replacement); ! 41997: break; ! 41998: ! 41999: case nc_baseclass: ! 42000: fetch((void *)top, sizeof (struct basecl), node); ! 42001: err = a_baseclass(top, Pbcl(node), replacement); ! 42002: break; ! 42003: ! 42004: } ! 42005: ! 42006: if(replacement) { ! 42007: if (fetching ()) { ! 42008: error ! 42009: ("walker::walk: Attempt to replace tree in cross-address space mode."); ! 42010: err = tna_error; ! 42011: } ! 42012: else top = replacement; ! 42013: } ! 42014: ! 42015: if (control.post_action_proc && err != tna_error) { ! 42016: tree_node_action post_err; ! 42017: Pnode& post_repl = node; ! 42018: ! 42019: (*control.post_action_proc) (post_repl, nclass, control.callback_info, post_err, ! 42020: depth, orig_addr, *cur_tree); ! 42021: if(post_err != tna_continue) err = post_err; ! 42022: if(post_repl != node) { ! 42023: if (fetching ()) { ! 42024: error ! 42025: ("walker::walk: Attempt to replace tree in cross-address space mode."); ! 42026: err = tna_error; ! 42027: } ! 42028: else top = post_repl; ! 42029: } ! 42030: } ! 42031: ! 42032: free_fetched((void *) node); ! 42033: ! 42034: Return: ! 42035: return err; ! 42036: } ! 42037: ! 42038: /* This is called in pre-order for each node. Then ! 42039: post_act_on_node is called after whatever recursive ! 42040: processing ensues. ! 42041: ! 42042: This is called from each of the structure-specific procedures ! 42043: to give the action procedure an opportunity to act. ! 42044: It can return a replacement pointer and control ! 42045: whether to examine the insides of the node. ! 42046: */ ! 42047: ! 42048: tree_node_action ! 42049: walker::pre_act_on_node (Pnode node, node_class nc, ! 42050: Pnode node_copy, Pnode& replacement) ! 42051: { ! 42052: /* If we have been here before, then we never proceed */ ! 42053: /* node_copy is != node when a fetcher is in use */ ! 42054: ! 42055: int found; ! 42056: int old_node; ! 42057: tree_node_action action; ! 42058: Pnode new_node; ! 42059: int register_in_hash = 1; ! 42060: ! 42061: nodes_seen_hash->action((int)node, 0, Hash::probe, found, old_node); ! 42062: ! 42063: if(found) { ! 42064: new_node = Pnode(old_node); ! 42065: if(new_node != node) replacement = new_node; ! 42066: return tna_stop; /* no need to proceed */ ! 42067: } ! 42068: ! 42069: /* OK, we don't know from a previous pass. Call our actor */ ! 42070: ! 42071: new_node = fetching () && node_copy ? node_copy : node; ! 42072: ! 42073: (*control.action_proc)(new_node, nc, control.callback_info, action, ! 42074: depth, orig_addr, *cur_tree, ! 42075: register_in_hash); ! 42076: ! 42077: if(action != tna_error && !fetching () && new_node != node) { ! 42078: replacement = new_node; ! 42079: if(register_in_hash) ! 42080: nodes_seen_hash->action((int)node, ! 42081: (int)new_node, ! 42082: Hash::insert, 0, 0); ! 42083: } ! 42084: else { ! 42085: if(register_in_hash) ! 42086: nodes_seen_hash->action((int)node, (int) node, Hash::insert, 0, 0); ! 42087: } ! 42088: return action; ! 42089: } ! 42090: ! 42091: tree_node_action walker::a_table(Pnode ta, Ptable t, Pnode& replacement) ! 42092: { ! 42093: /* no unions */ ! 42094: ! 42095: tree_node_action action; ! 42096: action = pre_act_on_node(ta, nc_table, Pnode(t), replacement); ! 42097: if(action != tna_continue) return action; ! 42098: ! 42099: /* -----------------------------*/ ! 42100: /* For Now, Never Walk a Table. */ ! 42101: ! 42102: action = tna_stop; return action; ! 42103: ! 42104: /* An array of pointers. ! 42105: * The action procedure is responsible for allocating a new one ! 42106: * of those if it replaced and continued. ! 42107: * *** end of comment ! 42108: ! 42109: if(!fetching () && replacement) ! 42110: t = Ptable(replacement); ! 42111: ! 42112: Pname * t_entries; ! 42113: ! 42114: if(fetching ()) { ! 42115: void * temp; ! 42116: fetch((void *)t->entries, t->size * sizeof(Pname), temp); ! 42117: t_entries = (Pname *)temp; ! 42118: } ! 42119: else t_entries = t->entries; ! 42120: ! 42121: for(int nx = 0; nx < t->size; nx ++) { ! 42122: action = walk(t_entries[nx]); ! 42123: if(action == tna_error) return action; ! 42124: } ! 42125: ! 42126: if(fetching ()) free_fetched ((void *)t_entries); ! 42127: ! 42128: Pnode n = Pnode(t->real_block); ! 42129: ! 42130: action = walk(t->real_block); ! 42131: if(action == tna_error) return action; ! 42132: ! 42133: action = walk(t->next); ! 42134: action = walk(t->t_name); ! 42135: return tna_continue; ! 42136: */ // don't walk table ! 42137: } ! 42138: ! 42139: tree_node_action walker::a_enumdef (Pnode ta, Penum e, Pnode& replacement) ! 42140: { ! 42141: tree_node_action action = pre_act_on_node(ta, nc_enumdef, Pnode(e), replacement); ! 42142: ! 42143: action = walk(e->mem); ! 42144: if(action == tna_error) return action; ! 42145: ! 42146: action = walk(e->e_type); ! 42147: ! 42148: return tna_continue; ! 42149: } ! 42150: ! 42151: tree_node_action walker::a_virt(Pnode ta, Pvirt v, Pnode& replacement) ! 42152: { ! 42153: /* no unions */ ! 42154: ! 42155: int nx; ! 42156: tree_node_action action = pre_act_on_node(ta, nc_enumdef, Pnode(v), replacement); ! 42157: ! 42158: if(action != tna_continue) return action; ! 42159: ! 42160: if(!fetching () && replacement) ! 42161: v = Pvirt(replacement); ! 42162: ! 42163: /* an array of velem structures. */ ! 42164: ! 42165: velem * v_virt_init; ! 42166: ! 42167: if(fetching ()) { ! 42168: void * t; ! 42169: fetch((void *)v->virt_init, v->n_init * sizeof(velem), t); ! 42170: v_virt_init = (velem *)t; ! 42171: } ! 42172: else v_virt_init = v->virt_init; ! 42173: ! 42174: for(nx = 0; nx < v->n_init; nx ++) { ! 42175: action = walk(v_virt_init[nx].n); ! 42176: if(action == tna_error) return action; ! 42177: } ! 42178: ! 42179: if(fetching ()) free_fetched ((void *)v_virt_init); ! 42180: ! 42181: action = walk(v->vclass); ! 42182: ! 42183: return tna_continue; ! 42184: } ! 42185: ! 42186: tree_node_action walker::a_classdef(Pnode ta, Pclass c, Pnode& replacement) ! 42187: { ! 42188: ! 42189: tree_node_action action = pre_act_on_node(ta, nc_classdef, Pnode(c), replacement); ! 42190: ! 42191: if(action != tna_continue) return action; ! 42192: ! 42193: if(!fetching () && replacement) ! 42194: c = Pclass(replacement); ! 42195: ! 42196: action = walk(c->baselist); ! 42197: if(action == tna_error) return action; ! 42198: ! 42199: action=walk(c->mem_list); ! 42200: if(action == tna_error) return action; ! 42201: ! 42202: action=walk(c->memtbl); ! 42203: if(action == tna_error) return action; ! 42204: ! 42205: action=walk(c->friend_list); ! 42206: if(action == tna_error) return action; ! 42207: ! 42208: action=walk(c->pubdef); ! 42209: if(action == tna_error) return action; ! 42210: ! 42211: action=walk(c->tn_list); ! 42212: if(action == tna_error) return action; ! 42213: ! 42214: action=walk(c->in_class); ! 42215: if(action == tna_error) return action; ! 42216: ! 42217: action=walk(c->in_fct); ! 42218: if(action == tna_error) return action; ! 42219: ! 42220: action=walk(c->this_type); ! 42221: if(action == tna_error) return action; ! 42222: ! 42223: action=walk(c->virt_list); ! 42224: if(action == tna_error) return action; ! 42225: ! 42226: action=walk(c->c_ctor); ! 42227: if(action == tna_error) return action; ! 42228: action=walk(c->c_dtor); ! 42229: if(action == tna_error) return action; ! 42230: action=walk(c->c_itor); ! 42231: if(action == tna_error) return action; ! 42232: ! 42233: action=walk(c->conv); ! 42234: if(action == tna_error) return action; ! 42235: ! 42236: return tna_continue; ! 42237: } ! 42238: ! 42239: tree_node_action walker::a_basetype(Pnode ta, Pbase b, Pnode& replacement) ! 42240: { ! 42241: ! 42242: tree_node_action action = pre_act_on_node(ta, nc_basetype, Pnode(b), replacement); ! 42243: int derr; ! 42244: ! 42245: if(action != tna_continue) return action; ! 42246: ! 42247: if(!fetching () && replacement) ! 42248: b = Pbase(replacement); ! 42249: ! 42250: action = walk(b->b_name); ! 42251: if(action == tna_error) return action; ! 42252: ! 42253: action = walk(b->b_table); ! 42254: if(action == tna_error) return action; ! 42255: ! 42256: // action = walk(b->b_field); ! 42257: // if(action == tna_error) return action; ! 42258: ! 42259: action = walk(b->b_xname); ! 42260: if(action == tna_error) return action; ! 42261: ! 42262: switch(derr = b->discriminator(0)) { ! 42263: case 0: break; ! 42264: case 1: ! 42265: action = walk(b->b_fieldtype); ! 42266: if(action == tna_error) return action; ! 42267: break; ! 42268: case 2: break; ! 42269: default: ! 42270: error ("a_basetype: discrim error %d.", derr); ! 42271: return tna_error; ! 42272: } ! 42273: ! 42274: return tna_continue; ! 42275: } ! 42276: ! 42277: tree_node_action walker::a_fct(Pnode ta, Pfct f, Pnode& replacement) ! 42278: { ! 42279: ! 42280: tree_node_action action = pre_act_on_node(ta, nc_fct, Pnode(f), replacement); ! 42281: ! 42282: if(action != tna_continue) return action; ! 42283: ! 42284: if(!fetching () && replacement) ! 42285: f = Pfct(replacement); ! 42286: ! 42287: action = walk(f->returns); ! 42288: if(action == tna_error) return action; ! 42289: ! 42290: action = walk(f->argtype); ! 42291: if(action == tna_error) return action; ! 42292: ! 42293: action = walk(f->s_returns); ! 42294: if(action == tna_error) return action; ! 42295: ! 42296: action = walk(f->f_this); ! 42297: if(action == tna_error) return action; ! 42298: ! 42299: action = walk(f->memof); ! 42300: if(action == tna_error) return action; ! 42301: ! 42302: action = walk(f->body); ! 42303: if(action == tna_error) return action; ! 42304: ! 42305: action = walk(f->f_init); ! 42306: if(action == tna_error) return action; ! 42307: ! 42308: action = walk(f->f_expr); ! 42309: if(action == tna_error) return action; ! 42310: ! 42311: action = walk(f->last_expanded); ! 42312: if(action == tna_error) return action; ! 42313: ! 42314: action = walk(f->f_result); ! 42315: if(action == tna_error) return action; ! 42316: ! 42317: action = walk(f->f_args); ! 42318: if(action == tna_error) return action; ! 42319: ! 42320: return tna_continue; ! 42321: } ! 42322: ! 42323: tree_node_action walker::a_name_list(Pnode ta, Plist l, Pnode& replacement) ! 42324: { ! 42325: ! 42326: int cl_error; ! 42327: tree_node_action action = pre_act_on_node(ta, nc_nlist, Pnode(l), replacement); ! 42328: ! 42329: if(action == tna_stop) { ! 42330: if(!fetching () && replacement) ! 42331: l = Plist(replacement); ! 42332: cl_error = 0; ! 42333: if((classify_node(Pnode(l), cl_error) == nc_nlist) && !cl_error) { ! 42334: action = walk(l->l); ! 42335: if(action == tna_error) return action; ! 42336: } ! 42337: } ! 42338: ! 42339: if(action != tna_continue) return action; ! 42340: ! 42341: if(!fetching () && replacement) ! 42342: l = Plist(replacement); ! 42343: ! 42344: action = walk(l->f); ! 42345: if(action == tna_error) return action; ! 42346: ! 42347: action = walk(l->l); ! 42348: if(action == tna_error) return action; ! 42349: ! 42350: return tna_continue; ! 42351: } ! 42352: ! 42353: tree_node_action walker::a_gen(Pnode ta, Pgen g, Pnode& replacement) ! 42354: { ! 42355: ! 42356: tree_node_action action = pre_act_on_node(ta, nc_gen, Pnode(g), replacement); ! 42357: ! 42358: if(action != tna_continue) return action; ! 42359: ! 42360: if(!fetching () && replacement) ! 42361: g = Pgen(replacement); ! 42362: ! 42363: action = walk(g->fct_list); ! 42364: if(action == tna_error) return action; ! 42365: ! 42366: return tna_continue; ! 42367: } ! 42368: ! 42369: tree_node_action walker::a_vec(Pnode ta, Pvec v, Pnode& replacement) ! 42370: { ! 42371: ! 42372: tree_node_action action = pre_act_on_node(ta, nc_vec, Pnode(v), replacement); ! 42373: ! 42374: if(action != tna_continue) return action; ! 42375: ! 42376: if(!fetching () && replacement) ! 42377: v = Pvec(replacement); ! 42378: ! 42379: action = walk(v->typ); ! 42380: if(action == tna_error) return action; ! 42381: ! 42382: action = walk(v->dim); ! 42383: if(action == tna_error) return action; ! 42384: ! 42385: return tna_continue; ! 42386: } ! 42387: ! 42388: tree_node_action walker::a_ptr(Pnode ta, Pptr p, Pnode& replacement) ! 42389: { ! 42390: ! 42391: tree_node_action action = pre_act_on_node(ta, nc_ptr, Pnode(p), replacement); ! 42392: ! 42393: if(action != tna_continue) return action; ! 42394: ! 42395: if(!fetching () && replacement) ! 42396: p = Pptr(replacement); ! 42397: ! 42398: action = walk(p->typ); ! 42399: if(action == tna_error) return action; ! 42400: ! 42401: action = walk(p->memof); ! 42402: if(action == tna_error) return action; ! 42403: ! 42404: return tna_continue; ! 42405: } ! 42406: ! 42407: ! 42408: tree_node_action walker::a_expr_guts(Pexpr e) ! 42409: { ! 42410: int derr; ! 42411: tree_node_action action; ! 42412: ! 42413: switch(derr = e->discriminator (0)) { ! 42414: case 1: ! 42415: action = walk(e->tp); ! 42416: if(action == tna_error) return action; ! 42417: break; ! 42418: case 0: ! 42419: break; ! 42420: default: ! 42421: error ("a_expr: discrim error %d on union 0.", derr); ! 42422: return tna_error; ! 42423: } ! 42424: ! 42425: switch(derr = e->discriminator (1)) { ! 42426: case 0: ! 42427: break; ! 42428: default: ! 42429: error ("a_expr: discrim error %d on union 1.", derr); ! 42430: return tna_error; ! 42431: case 1: ! 42432: action = walk(e->e1); ! 42433: if(action == tna_error) return action; ! 42434: break; ! 42435: case 2: ! 42436: break; ! 42437: case 3: ! 42438: break; ! 42439: } ! 42440: ! 42441: switch(derr = e->discriminator (2)) { ! 42442: case 0: ! 42443: break; ! 42444: default: ! 42445: error ("a_expr: discrim error %d on union 2.", derr); ! 42446: return tna_error; ! 42447: case 1: ! 42448: /* elists are special. e2 for an elist is a peer, not ! 42449: a child. */ ! 42450: if(e->base != ELIST) { ! 42451: action = walk(e->e2); ! 42452: if(action == tna_error) return action; ! 42453: } ! 42454: break; ! 42455: case 2: ! 42456: break; ! 42457: case 3: ! 42458: break; ! 42459: case 4: ! 42460: action = walk(e->n_initializer); ! 42461: if(action == tna_error) return action; ! 42462: break; ! 42463: } ! 42464: ! 42465: switch(derr = e->discriminator (3)) { ! 42466: case 0: ! 42467: break; ! 42468: default: ! 42469: error ("a_expr: discrim error %d on union 3.", derr); ! 42470: return tna_error; ! 42471: case 1: ! 42472: action = walk(e->tp2); ! 42473: if(action == tna_error) return action; ! 42474: break; ! 42475: case 2: ! 42476: action = walk(e->fct_name); ! 42477: if(action == tna_error) return action; ! 42478: break; ! 42479: case 3: ! 42480: action = walk(e->cond); ! 42481: if(action == tna_error) return action; ! 42482: break; ! 42483: case 4: ! 42484: action = walk(e->mem); ! 42485: if(action == tna_error) return action; ! 42486: break; ! 42487: case 5: ! 42488: action = walk(e->as_type); ! 42489: if(action == tna_error) return action; ! 42490: break; ! 42491: case 6: ! 42492: action = walk(e->n_table); ! 42493: if(action == tna_error) return action; ! 42494: break; ! 42495: case 7: ! 42496: action = walk(e->il); ! 42497: if(action == tna_error) return action; ! 42498: break; ! 42499: case 8: ! 42500: action = walk(e->query_this); ! 42501: if(action == tna_error) return action; ! 42502: break; ! 42503: } ! 42504: return tna_continue; ! 42505: } ! 42506: ! 42507: ! 42508: tree_node_action walker::a_expr(Pnode ta, Pexpr e, Pnode& replacement) ! 42509: { ! 42510: tree_node_action action = pre_act_on_node(ta, nc_expr, Pnode(e), replacement); ! 42511: ! 42512: if(action == tna_stop) { ! 42513: if(!fetching () && replacement) ! 42514: e = Pexpr(replacement); ! 42515: /* ELIST implies that e2 is a peer, not a child */ ! 42516: if(e->base == ELIST) { ! 42517: action = walk(e->e2); ! 42518: return action; ! 42519: } ! 42520: } ! 42521: ! 42522: if(action != tna_continue) return action; ! 42523: ! 42524: if(!fetching () && replacement) ! 42525: e = Pexpr(replacement); ! 42526: ! 42527: action = a_expr_guts(e); ! 42528: if (action == tna_error) return action; ! 42529: if(e->base == ELIST) ! 42530: action = walk(e->e2); ! 42531: return action; ! 42532: } ! 42533: ! 42534: tree_node_action walker::a_baseclass(Pnode ta, Pbcl b, Pnode& replacement) ! 42535: { ! 42536: tree_node_action action = pre_act_on_node(ta, nc_baseclass, Pnode(b), replacement); ! 42537: ! 42538: if(action != tna_continue) return action; ! 42539: ! 42540: if(!fetching () && replacement) ! 42541: b = Pbcl(replacement); ! 42542: ! 42543: action = walk(b->bclass); ! 42544: if(action == tna_error) return action; ! 42545: ! 42546: action = walk(b->init); ! 42547: if(action == tna_error) return action; ! 42548: ! 42549: action = walk(b->next); ! 42550: if(action == tna_error) return action; ! 42551: ! 42552: return tna_continue; ! 42553: } ! 42554: ! 42555: ! 42556: /* a name is also an expr. */ ! 42557: ! 42558: ! 42559: tree_node_action walker::a_name(Pnode ta, Pname n, Pnode& replacement) ! 42560: { ! 42561: int derr; ! 42562: int cl_error; ! 42563: tree_node_action action = pre_act_on_node(ta, nc_name, Pnode(n), replacement); ! 42564: ! 42565: /* n_list is a sibling, not a child. We always process it ! 42566: except in case of an error. */ ! 42567: if(action == tna_stop) { ! 42568: cl_error = 0; ! 42569: if(!fetching () && replacement) ! 42570: n = Pname(replacement); ! 42571: if((classify_node(Pnode(n), cl_error) == nc_name) && !cl_error) { ! 42572: if(depth > 0 || !control.dont_chase_lists_top) { ! 42573: action = walk(n->n_list); ! 42574: if(action == tna_error) return action; ! 42575: } ! 42576: } ! 42577: return tna_stop; ! 42578: } ! 42579: ! 42580: if(action != tna_continue) return action; ! 42581: ! 42582: if(!fetching () && replacement) ! 42583: n = Pname(replacement); ! 42584: ! 42585: /* We don't walk n_tbl_list. Its not part of the graph. ! 42586: */ ! 42587: ! 42588: switch(derr = n->discriminator(0)) { ! 42589: case 0: ! 42590: break; ! 42591: case 1: ! 42592: action = walk(n->n_qualifier); ! 42593: if(action == tna_error) return action; ! 42594: break; ! 42595: case 2: ! 42596: action = walk(n->n_realscope); ! 42597: if(action == tna_error) return action; ! 42598: break; ! 42599: default: ! 42600: error ("a_name: discrim error %d on union 0.", derr); ! 42601: return tna_error; ! 42602: } ! 42603: ! 42604: action = a_expr_guts(Pexpr(n)); ! 42605: if(action == tna_error) return action; ! 42606: ! 42607: if(depth > 0 || !control.dont_chase_lists_top) { ! 42608: action = walk(n->n_list); ! 42609: if(action == tna_error) return action; ! 42610: } ! 42611: ! 42612: return action; ! 42613: } ! 42614: ! 42615: /* --- NOTE: s_list should be deferred until AFTER the post-action ! 42616: procedure is called, if there is one. Since no one uses ! 42617: post-actions yet I haven't bothered to make this fix. ! 42618: --benson */ ! 42619: ! 42620: tree_node_action walker::a_stmt(Pnode ta, Pstmt s, Pnode& replacement) ! 42621: { ! 42622: int cl_error; ! 42623: int derr; ! 42624: tree_node_action action = pre_act_on_node(ta, nc_stmt, Pnode(s), replacement); ! 42625: ! 42626: if(action == tna_stop) { ! 42627: if(!fetching () && replacement) ! 42628: s = Pstmt(replacement); ! 42629: cl_error = 0; ! 42630: if((classify_node(Pnode(s), cl_error) == nc_stmt) && !cl_error) { ! 42631: /* s_list is not our subordinate, it is our peer */ ! 42632: if(depth > 0 || !control.dont_chase_lists_top) { ! 42633: action = walk(s->s_list); /* continue walk of sibs */ ! 42634: if (action == tna_error) return tna_error; ! 42635: } ! 42636: } ! 42637: return tna_stop; ! 42638: } ! 42639: ! 42640: if(action != tna_continue) return action; ! 42641: ! 42642: if(!fetching () && replacement) ! 42643: s = Pstmt(replacement); ! 42644: ! 42645: action = walk(s->s); ! 42646: if(action == tna_error) return action; ! 42647: ! 42648: action = walk(s->memtbl); ! 42649: if(action == tna_error) return action; ! 42650: ! 42651: switch(derr = s->discriminator(0)) { ! 42652: default: ! 42653: error ("a_stmt: discrim error %d on union 0.", derr); ! 42654: return tna_error; ! 42655: case 4: ! 42656: case 0: break; ! 42657: case 1: ! 42658: action = walk(s->d); ! 42659: if(action == tna_error) return action; ! 42660: break; ! 42661: case 2: ! 42662: action = walk(s->e2); ! 42663: if(action == tna_error) return action; ! 42664: break; ! 42665: case 3: ! 42666: action = walk(s->has_default); ! 42667: if(action == tna_error) return action; ! 42668: break; ! 42669: case 5: ! 42670: action = walk(s->ret_tp); ! 42671: if(action == tna_error) return action; ! 42672: break; ! 42673: } ! 42674: ! 42675: switch(derr = s->discriminator(1)) { ! 42676: default: ! 42677: error ("a_stmt: discrim error %d on union 1.", derr); ! 42678: return tna_error; ! 42679: case 2: ! 42680: case 0: break; ! 42681: case 1: ! 42682: action = walk(s->e); ! 42683: if(action == tna_error) return action; ! 42684: break; ! 42685: case 3: ! 42686: action = walk(s->s2); ! 42687: if(action == tna_error) return action; ! 42688: break; ! 42689: } ! 42690: ! 42691: switch(derr = s->discriminator(2)) { ! 42692: default: ! 42693: error ("a_stmt: discrim error %d on union 2.", derr); ! 42694: return tna_error; ! 42695: case 0: break; ! 42696: case 1: ! 42697: action = walk(s->for_init); ! 42698: if(action == tna_error) return action; ! 42699: break; ! 42700: case 2: ! 42701: action = walk(s->else_stmt); ! 42702: if(action == tna_error) return action; ! 42703: break; ! 42704: case 3: ! 42705: action = walk(s->case_list); ! 42706: if(action == tna_error) return action; ! 42707: break; ! 42708: } ! 42709: ! 42710: if(depth > 0 || !control.dont_chase_lists_top) { ! 42711: action = walk(s->s_list); ! 42712: if(action == tna_error) return action; ! 42713: } ! 42714: ! 42715: return tna_continue; ! 42716: } ! 42717: ! 42718: tree_node_action walker::a_ia(Pnode ta, struct ia * ia, Pnode& replacement) ! 42719: { ! 42720: tree_node_action action = pre_act_on_node(ta, nc_ia, Pnode(ia), replacement); ! 42721: ! 42722: if(action != tna_continue) return action; ! 42723: ! 42724: if(!fetching () && replacement) ! 42725: ia = (struct ia *)&replacement; ! 42726: ! 42727: action = walk(ia->local); ! 42728: if(action == tna_error) return action; ! 42729: ! 42730: action = walk(ia->arg); ! 42731: if(action == tna_error) return action; ! 42732: ! 42733: action = walk(ia->tp); ! 42734: if(action == tna_error) return action; ! 42735: ! 42736: return tna_continue; ! 42737: } ! 42738: ! 42739: tree_node_action walker::a_iline(Pnode ta, Pin iline, Pnode& replacement) ! 42740: { ! 42741: tree_node_action action = pre_act_on_node(ta, nc_iline, Pnode(iline), replacement); ! 42742: ! 42743: if(action != tna_continue) return action; ! 42744: ! 42745: if(!fetching () && replacement) ! 42746: iline = Pin(replacement); ! 42747: ! 42748: action = walk(iline->fct_name); ! 42749: if(action == tna_error) return action; ! 42750: ! 42751: action = walk(iline->i_next); ! 42752: if(action == tna_error) return action; ! 42753: ! 42754: action = walk(iline->i_table); ! 42755: if(action == tna_error) return action; ! 42756: ! 42757: action = walk(iline->i_args); ! 42758: if(action == tna_error) return action; ! 42759: ! 42760: return tna_continue; ! 42761: } ! 42762: 0707071010112046151004440001630000160000010107200466055423100001400000004551tree_walk.h /* ident "@(#)ctrans:src/tree_walk.h 1.2" */ ! 42763: /* -*- Mode: C -*- Begin include file tree_walk.H */ ! 42764: /* ! 42765: $Source: /usr3/lang/benson/work/stripped_cfront/RCS/tree_walk.H,v $ $RCSfile: tree_walk.H,v $ ! 42766: $Revision: 1.1 $ $Date: 89/11/20 08:51:05 $ ! 42767: $Author: benson $ $Locker: $ ! 42768: $State: Exp $ ! 42769: */ ! 42770: ! 42771: #ifndef _TREE_WALK ! 42772: #define _TREE_WALK ! 42773: ! 42774: #include "cfront.h" ! 42775: #include "node_classes.h" ! 42776: #include <iostream.h> ! 42777: #include "ios_printf.h" ! 42778: #include "hash.h" ! 42779: ! 42780: enum tree_node_action { ! 42781: tna_continue = 0, /* plain vanilla */ ! 42782: tna_stop = 1, /* don't proceed */ ! 42783: tna_error = 2, /* stop entire walk now. */ ! 42784: }; ! 42785: ! 42786: /* procedural interface to indirect via a pointer. */ ! 42787: typedef int (*tree_fetch_proc) (void * info, ! 42788: void * pointer, ! 42789: unsigned long length, ! 42790: int zero_stop, /* for character strings.*/ ! 42791: void * target); ! 42792: ! 42793: ! 42794: const tree_fetch_proc null_tfp = (tree_fetch_proc) 0; ! 42795: ! 42796: class tree_walk_tree { ! 42797: public: ! 42798: tree_walk_tree * parent; ! 42799: char storage[1]; /* variable amt, specified by caller. */ ! 42800: }; ! 42801: ! 42802: /* The trailing int here controls whether to remember the ! 42803: node in the hash table to short-circuit meeting it again */ ! 42804: ! 42805: typedef void (*tree_pre_action) ! 42806: (Pnode&, node_class, void *, tree_node_action&, int, Pnode, ! 42807: tree_walk_tree&, int&); ! 42808: ! 42809: ! 42810: typedef void (*tree_post_action) ! 42811: (Pnode&, node_class, void *, tree_node_action&, int, Pnode, ! 42812: tree_walk_tree&); ! 42813: ! 42814: typedef void (*errorp) (char, const char *); ! 42815: ! 42816: class tree_walk_control { ! 42817: public: ! 42818: int version; ! 42819: void * callback_info; ! 42820: tree_fetch_proc fetcher; ! 42821: tree_pre_action action_proc; ! 42822: tree_post_action post_action_proc; ! 42823: int (*i_error) (int, const char *); /* usually part of cfront */ ! 42824: int call_i_error; /* if 0, just use the following */ ! 42825: ostream * error_stream; ! 42826: Hash * nodes_seen_hash; /* allows this to be global over ! 42827: more than one call to the walker. */ ! 42828: int resolve_by_name; ! 42829: int alloc_stack_bytes; ! 42830: /* if on, n_list and s_list are ignored for the very top node. ! 42831: this is for the benefit of the printer. */ ! 42832: int dont_chase_lists_top; ! 42833: tree_walk_control () { ! 42834: version = 1; ! 42835: callback_info = 0; ! 42836: fetcher = null_tfp; ! 42837: call_i_error = 0; ! 42838: error_stream = &cerr; ! 42839: nodes_seen_hash = 0; ! 42840: resolve_by_name = 1; /* the dumper turns this off */ ! 42841: alloc_stack_bytes = 0; ! 42842: post_action_proc = 0; ! 42843: dont_chase_lists_top = 0; ! 42844: } ! 42845: }; ! 42846: ! 42847: tree_node_action walk_tree (tree_walk_control& c, Pnode& n); ! 42848: ! 42849: #endif ! 42850: 0707071010112045721004440001630000160000010210200466055412600000600000054504typ.c /*ident "@(#)ctrans:src/typ.c 1.4" */ ! 42851: /************************************************************************** ! 42852: ! 42853: C++ source for cfront, the C++ compiler front-end ! 42854: written in the computer science research center of Bell Labs ! 42855: ! 42856: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 42857: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 42858: ! 42859: typ.c: ! 42860: ! 42861: ! 42862: ***************************************************************************/ ! 42863: ! 42864: #include "cfront.h" ! 42865: #include "size.h" ! 42866: ! 42867: Pbase short_type; ! 42868: Pbase int_type; ! 42869: Pbase char_type; ! 42870: Pbase long_type; ! 42871: ! 42872: Pbase uchar_type; ! 42873: Pbase ushort_type; ! 42874: Pbase uint_type; ! 42875: Pbase ulong_type; ! 42876: ! 42877: Pbase zero_type; ! 42878: Pbase float_type; ! 42879: Pbase double_type; ! 42880: Pbase ldouble_type; ! 42881: Pbase void_type; ! 42882: Pbase any_type; ! 42883: ! 42884: Ptype Pint_type; ! 42885: Ptype Pchar_type; ! 42886: Ptype Pvoid_type; ! 42887: Ptype Pfctvec_type; ! 42888: ! 42889: Ptable gtbl; ! 42890: Ptable ptbl; ! 42891: ! 42892: Pname Cdcl; ! 42893: Pstmt Cstmt; ! 42894: ! 42895: bit new_type; ! 42896: ! 42897: void echeck(Ptype t1, Ptype t2) ! 42898: /* ! 42899: t1 is an enum, t2 is assigned to it ! 42900: */ ! 42901: { ! 42902: if (t1 == t2) return; ! 42903: ! 42904: //error('d',"echeck(%t,%t) %d %d",t1,t2,t1->base,t2->base); ! 42905: //error('d',"se %d promote: %d",suppress_error, enum_promote); ! 42906: if (t1->base==EOBJ ! 42907: && t2->base==EOBJ ! 42908: && Pbase(t1)->b_name->tp == Pbase(t2)->b_name->tp) return; ! 42909: ! 42910: if (enum_promote) return; ! 42911: error(strict_opt?0:'w',"%t assigned to %t (anachronism)",t2,t1); ! 42912: } ! 42913: ! 42914: ! 42915: Ptype np_promote(TOK oper, TOK r1, TOK r2, Ptype t1, Ptype t2, TOK p) ! 42916: /* ! 42917: an arithmetic operator "oper" is applied to "t1" and "t2", ! 42918: types t1 and t2 has been checked and belongs to catagories ! 42919: "r1" and "r2", respectively: ! 42920: A ANY ! 42921: Z ZERO ! 42922: I CHAR, SHORT, INT, LONG, FIELD, or EOBJ ! 42923: F FLOAT DOUBLE LDOUBLE ! 42924: P PTR (to something) or VEC (of something) ! 42925: test for compatability of the operands, ! 42926: if (p) return the promoted result type ! 42927: */ ! 42928: { ! 42929: if (r2 == 'A') return t1; ! 42930: ! 42931: //error('d',"promote(%t,%t,%k)",t1,t2,oper); ! 42932: ! 42933: switch (r1) { ! 42934: case 'A': return t2; ! 42935: case 'Z': ! 42936: switch (r2) { ! 42937: case 'Z': return int_type; ! 42938: case 'I': ! 42939: case 'F': ! 42940: if(oper==DEREF) return any_type; ! 42941: return (p) ? Pbase(t2)->arit_conv(0) : 0; ! 42942: case 'P': switch (oper) { ! 42943: case PLUS: ! 42944: case ASPLUS: if(t2!=Pvoid_type) break; ! 42945: default: return any_type; ! 42946: } ! 42947: return t2; ! 42948: case FCT: error("zero%kF",oper); return any_type; ! 42949: default: error('i',"zero(%d)",r2); ! 42950: } ! 42951: case 'I': ! 42952: switch (r2) { ! 42953: case 'Z': t2 = 0; ! 42954: case 'I': ! 42955: case 'F': ! 42956: if(oper==DEREF) return any_type; ! 42957: return (p) ? Pbase(t1)->arit_conv(Pbase(t2)) : 0; ! 42958: case 'P': switch (oper) { ! 42959: case PLUS: ! 42960: case ASPLUS: if(t2!=Pvoid_type) break; ! 42961: default: error("int%kP",oper); return any_type; ! 42962: } ! 42963: return t2; ! 42964: case FCT: error("int%kF",oper); return any_type; ! 42965: default: error('i',"int(%d)",r2); return any_type; ! 42966: } ! 42967: case 'F': ! 42968: switch (r2) { ! 42969: case 'Z': t2 = 0; ! 42970: case 'I': ! 42971: case 'F': ! 42972: if(oper==DEREF) return any_type; ! 42973: return (p) ? Pbase(t1)->arit_conv(Pbase(t2)) : 0; ! 42974: case 'P': error("float%kP",oper); return any_type; ! 42975: case FCT: error("float%kF",oper); return any_type; ! 42976: default: error('i',"float(%d)",r2); return any_type; ! 42977: } ! 42978: case 'P': ! 42979: switch (r2) { ! 42980: case 'Z': return t1; ! 42981: case 'I': ! 42982: switch (oper) { ! 42983: case PLUS: ! 42984: case MINUS: ! 42985: case ASPLUS: ! 42986: case ASMINUS: ! 42987: if (t1->check(Pvoid_type,0)==0) { ! 42988: return any_type; ! 42989: } ! 42990: break; ! 42991: default: error("P%k int",oper); return any_type; ! 42992: } ! 42993: return t1; ! 42994: case 'F': error("P%k float",oper); return any_type; ! 42995: case 'P': ! 42996: if (t1->check(t2,ASSIGN)) { ! 42997: switch (oper) { ! 42998: case EQ: ! 42999: case NE: ! 43000: case LE: ! 43001: case GE: ! 43002: case GT: ! 43003: case LT: ! 43004: case QUEST: ! 43005: if (t2->check(t1,ASSIGN) == 0) goto zz; ! 43006: } ! 43007: error("T mismatch:%t %k%t",t1,oper,t2); ! 43008: return any_type; ! 43009: } ! 43010: zz: ! 43011: switch (oper) { ! 43012: case MINUS: ! 43013: return (t2!=Pvoid_type) ? int_type : any_type; ! 43014: case ASMINUS: error("P -=P"); return any_type; ! 43015: case PLUS: error("P +P"); return any_type; ! 43016: case ASPLUS: error("P +=P"); return any_type; ! 43017: case LS: ! 43018: case RS: return any_type; ! 43019: default: return (t1!=Pvoid_type) ? t1 : any_type; ! 43020: } ! 43021: case FCT: return t1; ! 43022: default: error('i',"P(%d)",r2); ! 43023: } ! 43024: case FCT: ! 43025: if(oper == QUEST) { ! 43026: switch (r2) { ! 43027: case 'Z': ! 43028: return any_type; ! 43029: case 'P': ! 43030: return t2; ! 43031: case 'I': ! 43032: case 'F': ! 43033: error("F%k%t",oper,t2); ! 43034: default: ! 43035: return t1; ! 43036: } ! 43037: } ! 43038: error("F%k%t",oper,t2); ! 43039: return any_type; ! 43040: default: ! 43041: error('i',"np_promote(%d,%d)",r1,r2); ! 43042: } ! 43043: } ! 43044: ! 43045: TOK type::kind(TOK oper, TOK v) ! 43046: /* v == 'I' integral ! 43047: 'N' numeric ! 43048: 'P' numeric or pointer ! 43049: */ ! 43050: { ! 43051: Ptype t = this; ! 43052: if (this == 0) error('i',"type::kind(): this==0"); ! 43053: xx: ! 43054: switch (t->base) { ! 43055: case ANY: return 'A'; ! 43056: case ZTYPE: return 'Z'; ! 43057: case FIELD: ! 43058: case CHAR: ! 43059: case SHORT: ! 43060: case INT: ! 43061: case LONG: ! 43062: case EOBJ: return 'I'; ! 43063: case FLOAT: ! 43064: case LDOUBLE: ! 43065: case DOUBLE: if (v == 'I') error("float operand for %k",oper); return 'F'; ! 43066: case VEC: ! 43067: case PTR: if (v != 'P') error("P operand for %k",oper); ! 43068: switch (oper) { ! 43069: case INCR: ! 43070: case DECR: ! 43071: case MINUS: ! 43072: case PLUS: ! 43073: case ASMINUS: ! 43074: case ASPLUS: ! 43075: if (t->base==PTR ! 43076: && (Pptr(t)->memof || Pptr(t)->typ->base==FCT)) ! 43077: error("%t operand of%k",this,oper); ! 43078: else ! 43079: Pptr(t)->typ->tsizeof(); // get increment ! 43080: break; ! 43081: default: ! 43082: if (t->base==PTR ! 43083: && (Pptr(t)->memof || Pptr(t)->typ->base==FCT)) ! 43084: error("%t operand of%k",this,oper); ! 43085: case ANDAND: ! 43086: case OROR: ! 43087: case ASSIGN: ! 43088: case NE: ! 43089: case EQ: ! 43090: case IF: ! 43091: case WHILE: ! 43092: case DO: ! 43093: case FOR: ! 43094: case QUEST: ! 43095: case NOT: ! 43096: break; ! 43097: } ! 43098: return 'P'; ! 43099: case RPTR: error("R operand for %k",oper); return 'A'; ! 43100: case TYPE: t = Pbase(t)->b_name->tp; goto xx; ! 43101: case FCT: if (v != 'P') error("F operand for %k",oper); return FCT; ! 43102: case OVERLOAD: error("overloaded operand for %k",oper); return 'A'; ! 43103: case CLASS: ! 43104: case ENUM: error("%k operand for %k",base,oper); return 'A'; ! 43105: default: error("%t operand for %k",this,oper); return 'A'; ! 43106: } ! 43107: } ! 43108: ! 43109: void type::dcl(Ptable tbl) ! 43110: /* ! 43111: go through the type (list) and ! 43112: (1) evaluate vector dimensions ! 43113: (2) evaluate field sizes ! 43114: (3) lookup struct tags, etc. ! 43115: (4) handle implicit tag declarations ! 43116: */ ! 43117: { ! 43118: static arg_fudge; ! 43119: ! 43120: Ptype t = this; ! 43121: ! 43122: if (this == 0) error('i',"T::dcl(this==0)"); ! 43123: if (tbl->base != TABLE) error('i',"T::dcl(%d)",tbl->base); ! 43124: ! 43125: xx: ! 43126: //error('d',"type::dcl %k",t->base); ! 43127: switch (t->base) { ! 43128: case TYPE: ! 43129: t = Pbase(t)->b_name->tp; ! 43130: goto xx; ! 43131: case PTR: ! 43132: case RPTR: ! 43133: { Pptr p = Pptr(t); ! 43134: t = p->typ; ! 43135: if (t->base == TYPE) { ! 43136: Ptype tt = Pbase(t)->b_name->tp; ! 43137: if (tt->base == FCT) p->typ = tt; ! 43138: return; ! 43139: } ! 43140: goto xx; ! 43141: } ! 43142: ! 43143: case VEC: ! 43144: { Pvec v = Pvec(t); ! 43145: Pexpr e = v->dim; ! 43146: if (e) { ! 43147: Ptype et; ! 43148: v->dim = e = e->typ(tbl); ! 43149: et = e->tp; ! 43150: if (et->integral(0) == 'A') { ! 43151: error("UN in array dimension"); ! 43152: } ! 43153: else { ! 43154: long i; ! 43155: Neval = 0; ! 43156: i = e->eval(); ! 43157: if (Neval == 0) { ! 43158: if (largest_int<i) ! 43159: error("array dimension too large"); ! 43160: v->size = int(i); ! 43161: ! 43162: if ( lcl_tbl == 0 ) ! 43163: ! 43164: DEL(v->dim); ! 43165: v->dim = 0; ! 43166: } ! 43167: ! 43168: if (new_type) { ! 43169: if (Neval) ! 43170: ; ! 43171: else if (i == 0) ! 43172: v->dim = zero; ! 43173: else if (i < 0) { ! 43174: error("negative array dimension"); ! 43175: i = 1; ! 43176: } ! 43177: } ! 43178: else { ! 43179: if (Neval) ! 43180: error("%s",Neval); ! 43181: else if (i == 0) ! 43182: error('w',"array dimension == 0"); ! 43183: else if (i < 0) { ! 43184: error("negative array dimension"); ! 43185: i = 1; ! 43186: } ! 43187: } ! 43188: } ! 43189: } ! 43190: t = v->typ; ! 43191: llx: ! 43192: switch (t->base) { ! 43193: case TYPE: ! 43194: t = Pbase(t)->b_name->tp; ! 43195: goto llx; ! 43196: case FCT: ! 43197: v->typ = t; ! 43198: break; ! 43199: case VEC: ! 43200: if (Pvec(t)->dim==0 && Pvec(t)->size==0) error("null dimension (something like [][] seen)"); ! 43201: if (arg_fudge) { ! 43202: v->base = PTR; // X[12][10] ==> X(*)[10] ! 43203: Pptr(v)->rdo = 0; ! 43204: Pptr(v)->memof = 0; ! 43205: } ! 43206: } ! 43207: goto xx; ! 43208: } ! 43209: ! 43210: case FCT: ! 43211: { Pfct f = Pfct(t); ! 43212: void dargs(Pname, Pfct, Ptable); ! 43213: if (f->argtype) dargs(0,f,tbl); ! 43214: for (Pname n=f->argtype; n; n = n->n_list) { ! 43215: arg_fudge++; ! 43216: n->tp->dcl(tbl); ! 43217: arg_fudge--; ! 43218: } ! 43219: Pname cn = f->returns->is_cl_obj(); ! 43220: if (cn && Pclass(cn->tp)->has_itor()) ! 43221: make_res(f); ! 43222: else if (f->f_this == 0) ! 43223: f->f_args = f->argtype; ! 43224: t = f->returns; ! 43225: goto xx; ! 43226: } ! 43227: ! 43228: case FIELD: ! 43229: { Pbase f = Pbase(t); ! 43230: Pexpr e = Pexpr(f->b_name); ! 43231: long i; ! 43232: Ptype et; ! 43233: e = e->typ(tbl); ! 43234: f->b_name = Pname(e); ! 43235: et = e->tp; ! 43236: if (et->integral(0) == 'A') { ! 43237: error("UN in field size"); ! 43238: i = 1; ! 43239: } ! 43240: else { ! 43241: Neval = 0; ! 43242: i = e->eval(); ! 43243: if (Neval) ! 43244: error("%s",Neval); ! 43245: else if (i < 0) { ! 43246: error("negative field size"); ! 43247: i = 1; ! 43248: } ! 43249: else if (f->b_fieldtype->tsizeof()*BI_IN_BYTE < i) ! 43250: error("field size > sizeof(%t)",f->b_fieldtype); ! 43251: DEL(e); ! 43252: } ! 43253: f->b_bits = int(i); ! 43254: f->b_name = 0; ! 43255: break; ! 43256: } ! 43257: } ! 43258: } ! 43259: ! 43260: bit vrp_equiv; // vector == pointer equivalence used in check() ! 43261: bit const_problem; // types differs only in const ! 43262: int Vcheckerror; ! 43263: ! 43264: bit type::check(Ptype t, TOK oper) ! 43265: /* ! 43266: check if "this" can be combined with "t" by the operator "oper" ! 43267: ! 43268: used for check of ! 43269: assignment types (oper==ASSIGN) ! 43270: declaration compatability (oper==0) ! 43271: parameterized type formals (oper==255) ! 43272: as for (oper==0) but ! 43273: special checking for ANY types ! 43274: argument types (oper==ARG) ! 43275: return types (oper==RETURN) ! 43276: overloaded function name match (oper==OVERLOAD) ! 43277: overloaded function coercion (oper==COERCE) ! 43278: virtual function match (oper==VIRTUAL) ! 43279: ! 43280: NOT for arithmetic operators ! 43281: ! 43282: return 1 if the check failed ! 43283: ! 43284: checking of const const* and *const is a mess ! 43285: */ ! 43286: { ! 43287: const unsigned int strict_any_check = (oper == 255); ! 43288: ! 43289: Ptype t1 = this; ! 43290: Ptype t2 = t; ! 43291: Ptype tt1 = this; ! 43292: Ptype tt2 = t; ! 43293: int cnst1 = 0; ! 43294: int cnst2 = 0; ! 43295: TOK b1, b2; ! 43296: bit first = 1; ! 43297: TOK r; ! 43298: int vv; ! 43299: int ptr_count = 0; ! 43300: int fct_seen = 0; ! 43301: int over; ! 43302: Pptr p1 = 0; ! 43303: Pptr p2 = 0; ! 43304: int p_count = 0; ! 43305: ! 43306: if (strict_any_check) oper = 0; ! 43307: ! 43308: //error('d',"check %k %t %t",oper,t1,t2); ! 43309: if (t1==0 || t2==0) error('i',"check(%p,%p,%d)",t1,t2,oper); ! 43310: ! 43311: if (oper==VIRTUAL) { ! 43312: vv = 1; ! 43313: Vcheckerror = 0; ! 43314: oper = 0; ! 43315: } ! 43316: else ! 43317: vv = 0; ! 43318: ! 43319: if (oper == OVERLOAD) { ! 43320: over = 1; ! 43321: oper = 0; ! 43322: } ! 43323: else ! 43324: over = 0; ! 43325: ! 43326: const_problem = 0; ! 43327: ! 43328: while (t1 && t2) { ! 43329: top: ! 43330: //error('d',"top: %t (%d) %t (%d)",t1,t1->base,t2,t2->base); ! 43331: if (t1 == t2) { ! 43332: if (cnst1==cnst2) return 0; ! 43333: if (oper) { ! 43334: //error('d',"oper %d cnst1 %d cnst2 %d ptr %d",oper,cnst1,cnst2,tt1->is_ptr()); ! 43335: if (tt1 = tt1->is_ptr()) { ! 43336: ! 43337: // const* = int* ! 43338: if (cnst2<cnst1) return 0; ! 43339: ! 43340: // int* = int *const ! 43341: if (cnst2==1 && tt2->tconst()) { ! 43342: // check for int* = const *const ! 43343: tt2 = tt2->is_ptr(); ! 43344: if (tt2->tconst()) return 1; ! 43345: return 0; ! 43346: } ! 43347: } ! 43348: else { // int = const allowed ! 43349: if (oper==ARG || cnst1<cnst2) return 0; ! 43350: } ! 43351: } ! 43352: else { ! 43353: if (p_count) { ! 43354: int pr1 = p1->rdo ? 1 : 0; ! 43355: int pr2 = p2->rdo ? 1 : 0; ! 43356: if (pr1+cnst1==pr2+cnst2) ! 43357: return 0; ! 43358: } ! 43359: // const_problem = 1; ! 43360: } ! 43361: ! 43362: const_problem = 1; ! 43363: return 1; ! 43364: } ! 43365: ! 43366: if ((t1->base == ANY || t2->base == ANY)) { ! 43367: if (! strict_any_check) return 0; ! 43368: // Perform the check for strict_any, ie. the ! 43369: return ((t1 == t2) ? 0 : 1) ; ! 43370: } ! 43371: ! 43372: b1 = t1->base; ! 43373: switch (b1) { ! 43374: case TYPE: ! 43375: if (Pbase(t1)->b_const) cnst1++; ! 43376: t1 = Pbase(t1)->b_name->tp; ! 43377: goto top; ! 43378: } ! 43379: ! 43380: b2 = t2->base; ! 43381: switch (b2) { ! 43382: case TYPE: ! 43383: if (Pbase(t2)->b_const) cnst2++; ! 43384: t2 = Pbase(t2)->b_name->tp; ! 43385: goto top; ! 43386: } ! 43387: ! 43388: //error('d',"oper %k b1 %k b2 %k",oper,b1,b2); ! 43389: if (b1 != b2) { ! 43390: switch (b1) { ! 43391: case PTR: ! 43392: switch (b2) { ! 43393: case VEC: ! 43394: if (ptr_count) return 1; ! 43395: // ptr/vec equivalence does not ! 43396: // apply to declaration matching ! 43397: t1 = Pptr(t1)->typ; ! 43398: t2 = Pvec(t2)->typ; ! 43399: if (oper == 0 && over==0) return 1; ! 43400: ptr_count++; ! 43401: first = 0; ! 43402: goto top; ! 43403: case FCT: ! 43404: t1 = Pptr(t1)->typ; ! 43405: if (t1->base!=VOID) ! 43406: if (first==0 || t1->base!=b2) return 1; ! 43407: first = 0; ! 43408: goto top; ! 43409: } ! 43410: first = 0; ! 43411: break; ! 43412: ! 43413: case FCT: ! 43414: switch( b2 ) { ! 43415: case PTR: ! 43416: t2 = Pptr(t2)->typ; ! 43417: if (t1->base!=VOID ! 43418: && (first==0||t2->base!=b1)) return 1; ! 43419: first = 0; ! 43420: goto top; ! 43421: } ! 43422: first = 0; ! 43423: break; ! 43424: ! 43425: case VEC: ! 43426: switch (b2) { ! 43427: case PTR: ! 43428: if (ptr_count) return 1; ! 43429: t1 = Pvec(t1)->typ; ! 43430: t2 = Pptr(t2)->typ; ! 43431: switch (oper) { ! 43432: case ARG: ! 43433: case ASSIGN: ! 43434: case COERCE: ! 43435: break; ! 43436: case 0: ! 43437: if (over) break; ! 43438: default: ! 43439: return 1; ! 43440: } ! 43441: ptr_count++; ! 43442: first = 0; ! 43443: goto top; ! 43444: } ! 43445: first = 0; ! 43446: break; ! 43447: } ! 43448: goto base_check; ! 43449: } ! 43450: ! 43451: switch (b1) { ! 43452: case VEC: ! 43453: //error('d',"vec %k %d %d",oper,Pvec(t1)->size,Pvec(t2)->size); ! 43454: if (first==0 && Pvec(t1)->size!=Pvec(t2)->size) return 1; ! 43455: first = 0; ! 43456: t1 = Pvec(t1)->typ; ! 43457: t2 = Pvec(t2)->typ; ! 43458: ptr_count++; ! 43459: break; ! 43460: ! 43461: case PTR: ! 43462: case RPTR: ! 43463: first = 0; ! 43464: p1 = Pptr(t1); ! 43465: p2 = Pptr(t2); ! 43466: p_count++; ! 43467: ! 43468: if (p1->memof != p2->memof) { ! 43469: ! 43470: if(p1->memof!=0 && p2->memof!=0 ! 43471: && p1->memof->baseof(p2->memof)==0) ! 43472: return 1; ! 43473: ! 43474: int flag1=0,flag2=0; ! 43475: t1 = p1->typ; ! 43476: t2 = p2->typ; ! 43477: while (t1->base == TYPE) { ! 43478: flag1++; ! 43479: t1 = Pbase(t1)->b_name->tp; ! 43480: } ! 43481: while (t2->base == TYPE) { ! 43482: flag2++; ! 43483: t2 = Pbase(t2)->b_name->tp; ! 43484: } ! 43485: if (t1 != t2 || (!flag1 && !flag2)) { ! 43486: if (p1->memof==0 ! 43487: || p2->memof==0 ! 43488: || p1->memof->baseof(p2->memof)==0) ! 43489: return 1; ! 43490: Nstd++; ! 43491: } ! 43492: } ! 43493: ! 43494: t1 = p1->typ; ! 43495: t2 = p2->typ; ! 43496: ptr_count++; ! 43497: ! 43498: if (oper==0) { ! 43499: int pr1 = p1->rdo ? 1 : 0; ! 43500: int pr2 = p2->rdo ? 1 : 0; ! 43501: if (pr1+cnst1!=pr2+cnst2 ! 43502: && cnst1+Pbase(t1)->b_const!=cnst2+Pbase(t2)->b_const) { ! 43503: // const_problem only if nothing ! 43504: // more serious is wrong ! 43505: if (t1->check(t2,0) == 0) const_problem = 1; ! 43506: return 1; ! 43507: } ! 43508: ! 43509: if (b1==RPTR && t1->tconst()!=t2->tconst()) ! 43510: const_problem = 1; ! 43511: } ! 43512: break; ! 43513: ! 43514: case FCT: ! 43515: first = 0; ! 43516: { Pfct f1 = Pfct(t1); ! 43517: Pfct f2 = Pfct(t2); ! 43518: Pname a1 = f1->argtype; ! 43519: Pname a2 = f2->argtype; ! 43520: TOK k1 = f1->nargs_known; ! 43521: TOK k2 = f2->nargs_known; ! 43522: int n1 = f1->nargs; ! 43523: int n2 = f2->nargs; ! 43524: //error('d',"f1%t f2%t",f1,f2); ! 43525: if (f1->memof != f2->memof) { ! 43526: if (f1->memof==0 && f2->f_this==0) //SSS ! 43527: goto sss; ! 43528: if (vv == 0) // match even if private base class ! 43529: if (f1->memof==0 ! 43530: || f2->memof==0 ! 43531: || f1->memof->baseof(f2->memof)==0) return 1; ! 43532: Nstd++; ! 43533: sss:; //SSS ! 43534: } ! 43535: ! 43536: if (k1 != k2) return 1; ! 43537: ! 43538: if (n1!=n2 && k1 && k2) { ! 43539: goto aaa; ! 43540: } ! 43541: else if (a1 && a2) { ! 43542: int i = 0; ! 43543: while (a1 && a2) { ! 43544: i++; ! 43545: if (a1->tp->check(a2->tp,over?OVERLOAD:0)) return 1; ! 43546: a1 = a1->n_list; ! 43547: a2 = a2->n_list; ! 43548: } ! 43549: if (a1 || a2) goto aaa; ! 43550: } ! 43551: else if (a1 || a2) { ! 43552: aaa: ! 43553: //error('d',"aaa k1 %d k2 %d",k1,k2); ! 43554: if (k1 == ELLIPSIS) { ! 43555: switch (oper) { ! 43556: case 0: ! 43557: if (a2 && k2==0) break; ! 43558: return 1; ! 43559: case ASSIGN: ! 43560: if (a2 && k2==0) break; ! 43561: return 1; ! 43562: case ARG: ! 43563: if (a1) return 1; ! 43564: break; ! 43565: // case OVERLOAD: ! 43566: case COERCE: ! 43567: return 1; ! 43568: } ! 43569: } ! 43570: else if (k2 == ELLIPSIS) { ! 43571: return 1; ! 43572: } ! 43573: else if (k1 || k2) { ! 43574: return 1; ! 43575: } ! 43576: } ! 43577: ! 43578: t1 = f1->returns; ! 43579: t2 = f2->returns; ! 43580: fct_seen = 1; ! 43581: ! 43582: switch (oper) { //CCC ! 43583: case 0: ! 43584: if (f1->f_const!=f2->f_const) { ! 43585: if (t1->check(t2,0)==0) const_problem = 1; ! 43586: return 1; ! 43587: // if (vv == 0) return 1; ! 43588: // Vcheckerror = 1; ! 43589: } ! 43590: break; ! 43591: default: // really pointer to function ! 43592: if (f1->f_const && f2->f_const==0) return 1; ! 43593: } ! 43594: ! 43595: ! 43596: if (vv && t1->check(t2,0)) { Vcheckerror = 1; return 1; } ! 43597: } ! 43598: break; ! 43599: ! 43600: case FIELD: ! 43601: goto field_check; ! 43602: case CHAR: ! 43603: case SHORT: ! 43604: case INT: ! 43605: case LONG: ! 43606: goto int_check; ! 43607: case FLOAT: ! 43608: case DOUBLE: ! 43609: case LDOUBLE: ! 43610: goto float_check; ! 43611: case EOBJ: ! 43612: goto enum_check; ! 43613: case COBJ: ! 43614: goto cla_check; ! 43615: case ZTYPE: ! 43616: case VOID: ! 43617: return 0; ! 43618: default: ! 43619: error('i',"T::check(o=%d %d %d)",oper,b1,b2); ! 43620: } ! 43621: } ! 43622: ! 43623: if (t1 || t2) { ! 43624: const_problem = 0; // not a problem: the type itself is bad ! 43625: return 1; ! 43626: } ! 43627: return 0; ! 43628: ! 43629: field_check: ! 43630: switch (oper) { ! 43631: case 0: ! 43632: case ARG: ! 43633: error('i',"check field?"); ! 43634: } ! 43635: return 0; ! 43636: ! 43637: enum_check: ! 43638: //error('d',"enum check %t %t",t1,t2); ! 43639: if (Pbase(t1)->b_name->tp != Pbase(t2)->b_name->tp) goto base_check; ! 43640: goto const_check; ! 43641: ! 43642: float_check: ! 43643: if (first==0 && b1!=b2 && b2!=ZTYPE) return 1; ! 43644: // no break ! 43645: ! 43646: int_check: ! 43647: //error('d',"int_check"); ! 43648: if (Pbase(t1)->b_unsigned != Pbase(t2)->b_unsigned) { ! 43649: if (first == 0) return 1; ! 43650: if (oper /*&& oper!=OVERLOAD*/) ! 43651: Nstd++; ! 43652: else ! 43653: return 1; ! 43654: } ! 43655: // no break ! 43656: ! 43657: const_check: ! 43658: //error('d',"const_check %t (%d) %t (%d)",t1,t1->tconst(),t2,t2->tconst()); ! 43659: if (oper==0) { ! 43660: //error('d',"oper==0: t1 %t t2 %t cnst1 %d cnst2 %d",t1,t2,cnst1,cnst2); ! 43661: if (t1->tconst()+cnst1!=t2->tconst()+cnst2) { ! 43662: const_problem = 1; ! 43663: return 1; ! 43664: } ! 43665: } ! 43666: else if (first==0) { ! 43667: if (t1->tconst()+cnst1==0 && t2->tconst()+cnst2) { ! 43668: //error('d',"t1 %t t2 %t cnst1 %d cnst2 %d",t1,t2,cnst1,cnst2); ! 43669: //error('d',"tt1 %t %d cnst1 %d cnst2 %d",tt1,tt1->is_ptr(),cnst1,cnst2); ! 43670: //error('d',"tt2 %t",tt2); ! 43671: if (tt1->is_ptr()) { ! 43672: if (fct_const || vec_const) cnst2--; ! 43673: ! 43674: // const* = int* ! 43675: if (cnst2-tt2->tconst()<cnst1-tt1->tconst()) return 0; ! 43676: ! 43677: // int* = *const ! 43678: //if (cnst2==1 && tt2->tconst()) return 0; ! 43679: ! 43680: // const T* = const T* ! 43681: if (t2->tconst()+cnst2==t1->tconst()+cnst1) return 0; ! 43682: } ! 43683: else { // int = const allowed ! 43684: if (cnst1<cnst2) return 0; ! 43685: } ! 43686: const_problem = 1; ! 43687: return 1; ! 43688: } ! 43689: else { // const* vs int *const ! 43690: /* ! 43691: //error('d',"t1 %t cnst1 %d t2 %t cnst2 %d",t1,cnst1,t2,cnst2); ! 43692: if (tt1->is_ptr()) { ! 43693: int tt1c = tt1->tconst(); ! 43694: int tt2c = tt2->tconst() - fct_const - vec_const; ! 43695: //error('d',"tt1c %d tt2c %d",tt1c,tt2c); ! 43696: if (tt1c<tt2c) return 1; ! 43697: int t1c = t1->tconst(); ! 43698: int t2c = t2->tconst() - fct_const - vec_const; ! 43699: //error('d',"t1c %d t2c %d",t1c,t2c); ! 43700: if (cnst1+t1c<cnst2+t2c) return 1; ! 43701: if (tt2c<tt1c // *const = * ! 43702: && cnst1+t1c>cnst2+t2c) // T = constT ! 43703: return 1; ! 43704: } ! 43705: */ ! 43706: ! 43707: } ! 43708: } ! 43709: else { ! 43710: //error('d',"first t1 %t t2 %t cnst1 %d cnst2 %d",t1,t2,cnst1,cnst2); ! 43711: } ! 43712: //error('d',"return 0"); ! 43713: return 0; ! 43714: ! 43715: cla_check: ! 43716: { Pname n1 = Pbase(t1)->b_name; ! 43717: Pname n2 = Pbase(t2)->b_name; ! 43718: //error('d',"cla_check %n %n ptr_count %d",n1,n2,ptr_count); ! 43719: if (n1 == n2) goto const_check; ! 43720: ! 43721: // once again, a more comprehensive check for classes, ! 43722: // since they may be parametrized. ! 43723: if ((t1->base == COBJ) && (t2->base == COBJ) && ! 43724: ((Pclass(n1->tp)->same_class(Pclass(n2->tp))))) ! 43725: goto const_check; ! 43726: ! 43727: if (/*first || */1<ptr_count || fct_seen) return 1; ! 43728: ! 43729: switch (oper) { ! 43730: case ARG: ! 43731: case ASSIGN: ! 43732: case RETURN: ! 43733: case COERCE: ! 43734: { ! 43735: ppbase = PUBLIC; ! 43736: if (Pclass(n2->tp)->is_base(n1->string)) { ! 43737: if (ppbase!=PUBLIC) { ! 43738: const_problem = 0; ! 43739: // vrp_equiv = 0; ! 43740: return 1; // private or protected base ! 43741: } ! 43742: Nstd++; ! 43743: goto const_check; ! 43744: } ! 43745: } ! 43746: // no break ! 43747: case 0: ! 43748: case OVERLOAD: ! 43749: const_problem = 0; ! 43750: // vrp_equiv = 0; ! 43751: return 1; ! 43752: } ! 43753: ! 43754: goto const_check; ! 43755: } ! 43756: ! 43757: base_check: ! 43758: //error('d',"base_check t1=%t t2=%t oper=%d %s",t1,t2,oper,first?"first":""); ! 43759: //error('d',"ptr_count %d",ptr_count); ! 43760: if (oper) ! 43761: if (first || 1!=ptr_count) { ! 43762: if (b1==VOID || b2==VOID) return 1; ! 43763: } ! 43764: else { ! 43765: if (b1 == VOID) { // check for void* = T* ! 43766: register Ptype tpx = this; ! 43767: tpxloop: ! 43768: switch (tpx->base) { // t1 == void* ! 43769: default: ! 43770: const_problem = 0; ! 43771: return 1; ! 43772: case VOID: break; ! 43773: case PTR: ! 43774: case VEC: tpx = Pvec(tpx)->typ; ! 43775: goto tpxloop; ! 43776: case TYPE: tpx = Pbase(tpx)->b_name->tp; ! 43777: goto tpxloop; ! 43778: } ! 43779: ! 43780: tpx = t; ! 43781: bloop: ! 43782: switch (tpx->base) { // t2 == T* ! 43783: default: ! 43784: const_problem = 0; ! 43785: return 1; ! 43786: case VEC: ! 43787: case PTR: ! 43788: case FCT: Nstd++; ! 43789: // return 0; ! 43790: goto const_check; // prevent void* = const* ! 43791: case TYPE: tpx = Pbase(tpx)->b_name->tp; ! 43792: goto bloop; ! 43793: } ! 43794: } ! 43795: ! 43796: if (b2 != ZTYPE) { ! 43797: const_problem = 0; ! 43798: return 1; ! 43799: } ! 43800: } ! 43801: //error('d',"oper %d b1 %d b2 %d cp %d",oper,b1,b2,const_problem); ! 43802: switch (oper) { ! 43803: case 0: ! 43804: if (b1 != b2) { ! 43805: const_problem = 0; // we have a bigger problem ! 43806: // vrp_equiv = 0; ! 43807: } ! 43808: return 1; ! 43809: case COERCE: // could probably be merged with the cases below ! 43810: switch (b1) { ! 43811: case EOBJ: ! 43812: case ZTYPE: ! 43813: case CHAR: ! 43814: case SHORT: ! 43815: case INT: ! 43816: switch (b2) { ! 43817: case LONG: ! 43818: case FLOAT: ! 43819: case DOUBLE: ! 43820: case LDOUBLE: ! 43821: case EOBJ: ! 43822: case ZTYPE: ! 43823: case CHAR: ! 43824: case SHORT: ! 43825: case INT: ! 43826: case FIELD: ! 43827: Nstd++; ! 43828: suppress_error++; ! 43829: if (b1 == EOBJ) echeck(t1,t2); ! 43830: suppress_error--; ! 43831: goto const_check; ! 43832: } ! 43833: return 1; ! 43834: case LONG: // char, short, and int promotes to long ! 43835: switch (b2) { ! 43836: case FLOAT: ! 43837: case DOUBLE: ! 43838: case LDOUBLE: ! 43839: case ZTYPE: ! 43840: case EOBJ: ! 43841: case CHAR: ! 43842: case SHORT: ! 43843: case INT: ! 43844: case FIELD: ! 43845: Nstd++; ! 43846: goto const_check; ! 43847: } ! 43848: return 1; ! 43849: case FLOAT: ! 43850: // switch (b2) { ! 43851: // case ZTYPE: ! 43852: // Nstd++; ! 43853: // case FLOAT: ! 43854: // case DOUBLE: ! 43855: // goto const_check; ! 43856: // } ! 43857: // return 1; ! 43858: case DOUBLE: // char, short, int, and float promotes to double ! 43859: case LDOUBLE: ! 43860: switch (b2) { ! 43861: case LONG: ! 43862: case ZTYPE: ! 43863: case EOBJ: ! 43864: case CHAR: ! 43865: case SHORT: ! 43866: case INT: ! 43867: // Nstd++; ! 43868: case FLOAT: ! 43869: case DOUBLE: ! 43870: case LDOUBLE: ! 43871: Nstd++; ! 43872: goto const_check; ! 43873: } ! 43874: return 1; ! 43875: case PTR: ! 43876: switch (b2) { ! 43877: case ZTYPE: ! 43878: Nstd++; ! 43879: goto const_check; ! 43880: } ! 43881: case RPTR: ! 43882: case VEC: ! 43883: case COBJ: ! 43884: case FCT: ! 43885: return 1; ! 43886: } ! 43887: case ARG: ! 43888: case ASSIGN: ! 43889: case RETURN: ! 43890: switch (b1) { ! 43891: case COBJ: ! 43892: return 1; ! 43893: case EOBJ: ! 43894: case ZTYPE: ! 43895: case CHAR: ! 43896: case SHORT: ! 43897: case INT: ! 43898: case LONG: ! 43899: suppress_error++; ! 43900: r = t2->num_ptr(ASSIGN); ! 43901: suppress_error--; ! 43902: switch (r) { ! 43903: case 'F': ! 43904: // if (oper!=ARG) error('w',"%t assigned to%t",t2,t1); ! 43905: break; ! 43906: case 'A': ! 43907: case 'P': ! 43908: case FCT: return 1; ! 43909: } ! 43910: if (b1 == EOBJ) echeck(t1,t2); ! 43911: break; ! 43912: case FLOAT: ! 43913: case DOUBLE: ! 43914: case LDOUBLE: ! 43915: suppress_error++; ! 43916: r = t2->numeric(ASSIGN); ! 43917: suppress_error--; ! 43918: switch (r) { ! 43919: case 'A': ! 43920: case 'P': ! 43921: case FCT: return 1; ! 43922: } ! 43923: break; ! 43924: case VEC: ! 43925: if(oper==ARG && b2==ZTYPE) goto const_check; ! 43926: return 1; ! 43927: case PTR: ! 43928: suppress_error++; ! 43929: r = t2->num_ptr(ASSIGN); ! 43930: suppress_error--; ! 43931: switch (r) { ! 43932: case 'A': ! 43933: case 'I': ! 43934: case 'F': return 1; ! 43935: case FCT: if (Pptr(t1)->typ->base != FCT) return 1; ! 43936: } ! 43937: break; ! 43938: case RPTR: ! 43939: return 1; ! 43940: case FCT: ! 43941: switch (oper) { ! 43942: case ARG: ! 43943: case ASSIGN: ! 43944: return 1; ! 43945: } ! 43946: } ! 43947: break; ! 43948: } ! 43949: goto const_check; ! 43950: } ! 43951: ! 43952: 0707071010112045731004440001630000160000010210500466055413100000700000022542typ2.c /*ident "@(#)ctrans:src/typ2.c 1.3" */ ! 43953: /************************************************************************** ! 43954: ! 43955: C++ source for cfront, the C++ compiler front-end ! 43956: written in the computer science research center of Bell Labs ! 43957: ! 43958: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 43959: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 43960: ! 43961: typ2.c: ! 43962: ! 43963: ***************************************************************************/ ! 43964: ! 43965: #include "cfront.h" ! 43966: #include "size.h" ! 43967: ! 43968: extern int chars_in_largest; ! 43969: int largest_int; ! 43970: ! 43971: void typ_init() ! 43972: { ! 43973: chars_in_largest = strlen(LARGEST_INT); ! 43974: largest_int = int(str_to_long(LARGEST_INT)); ! 43975: ! 43976: defa_type = new basetype(INT,0); // note defa_type!=int_type ! 43977: int_type = new basetype(INT,0); // but they both represent `int' ! 43978: ! 43979: PERM(int_type); int_type->defined = DEFINED ; ! 43980: PERM(defa_type); defa_type->defined = DEFINED ; ! 43981: ! 43982: moe_type = new basetype(INT,0); ! 43983: PERM(moe_type); moe_type->defined = DEFINED ; ! 43984: moe_type->b_const = 1; ! 43985: moe_type->check(0); ! 43986: ! 43987: uint_type = new basetype(INT,0); ! 43988: PERM(uint_type); uint_type->defined = DEFINED ; ! 43989: uint_type->type_adj(UNSIGNED); ! 43990: uint_type->check(0); ! 43991: ! 43992: long_type = new basetype(LONG,0); ! 43993: PERM(long_type); long_type->defined = DEFINED ; ! 43994: long_type->check(0); ! 43995: ! 43996: ulong_type = new basetype(LONG,0); ! 43997: PERM(ulong_type); ulong_type->defined = DEFINED ; ! 43998: ulong_type->type_adj(UNSIGNED); ! 43999: ulong_type->check(0); ! 44000: ! 44001: short_type = new basetype(SHORT,0); ! 44002: PERM(short_type); short_type->defined = DEFINED ; ! 44003: short_type->check(0); ! 44004: ! 44005: ushort_type = new basetype(SHORT,0); ! 44006: PERM(ushort_type); ushort_type->defined = DEFINED ; ! 44007: ushort_type->type_adj(UNSIGNED); ! 44008: ushort_type->check(0); ! 44009: ! 44010: float_type = new basetype(FLOAT,0); ! 44011: PERM(float_type); float_type->defined = DEFINED ; ! 44012: ! 44013: double_type = new basetype(DOUBLE,0); ! 44014: PERM(double_type); double_type->defined = DEFINED ; ! 44015: ! 44016: ldouble_type = new basetype(LDOUBLE,0); ! 44017: PERM(ldouble_type); ldouble_type->defined = DEFINED ; ! 44018: ! 44019: zero_type = new basetype(ZTYPE,0); ! 44020: PERM(zero_type); zero_type->defined = DEFINED ; ! 44021: zero->tp = zero_type; ! 44022: ! 44023: void_type = new basetype(VOID,0); ! 44024: PERM(void_type); void_type->defined = DEFINED ; ! 44025: ! 44026: char_type = new basetype(CHAR,0); ! 44027: PERM(char_type); char_type->defined = DEFINED ; ! 44028: ! 44029: uchar_type = new basetype(CHAR,0); ! 44030: PERM(uchar_type); uchar_type->defined = DEFINED ; ! 44031: uchar_type->type_adj(UNSIGNED); ! 44032: uchar_type->check(0); ! 44033: ! 44034: Pchar_type = char_type->addrof(); ! 44035: PERM(Pchar_type); Pchar_type->defined = DEFINED ; ! 44036: ! 44037: Pint_type = int_type->addrof(); ! 44038: PERM(Pint_type); Pint_type->defined = DEFINED ; ! 44039: ! 44040: Pvoid_type = void_type->addrof(); ! 44041: PERM(Pvoid_type); Pvoid_type->defined = DEFINED ; ! 44042: ! 44043: Pfctvec_type = new fct(int_type,0,0); // must be last, see basetype::normalize() ! 44044: Pfctvec_type = Pfctvec_type->addrof(); ! 44045: Pfctvec_type = Pfctvec_type->addrof(); ! 44046: PERM(Pfctvec_type); Pfctvec_type->defined = DEFINED ; ! 44047: ! 44048: gtbl = new table(GTBLSIZE,0,0); ! 44049: gtbl->t_name = new name("global"); ! 44050: ptbl = new table(CTBLSIZE,0,0); ! 44051: ptbl->t_name = new name("ptbl"); ! 44052: } ! 44053: ! 44054: bit enum_promote; ! 44055: ! 44056: Pbase basetype::arit_conv(Pbase t) ! 44057: /* ! 44058: perform the "usual arithmetic conversions" C ref Manual 6.6 ! 44059: on "this" op "t" ! 44060: "this" and "t" are integral or floating ! 44061: "t" may be 0 ! 44062: */ ! 44063: { ! 44064: while (base == TYPE) this = Pbase(Pbase(this)->b_name->tp); ! 44065: // error('d', "arit_conv: this: %k %d %t %d", base, base, this, this ); ! 44066: ! 44067: bit l; ! 44068: bit u; ! 44069: bit f; ! 44070: bit l1 = (base == LONG); ! 44071: bit u1 = b_unsigned; ! 44072: bit f1 = (base==FLOAT || base==DOUBLE || base==LDOUBLE); ! 44073: if (t) { ! 44074: while (t->base == TYPE) t = Pbase(Pbase(t)->b_name->tp); ! 44075: // error('d', "arit_conv: t: %k %d %t %d", t->base, t->base, t, t ); ! 44076: ! 44077: bit l2 = (t->base == LONG); ! 44078: bit u2 = t->b_unsigned; ! 44079: bit f2 = (t->base==FLOAT || t->base==DOUBLE || base==LDOUBLE); ! 44080: l = l1 || l2; ! 44081: u = u1 || u2; ! 44082: f = f1 || f2; ! 44083: } ! 44084: else { ! 44085: l = l1; ! 44086: u = u1; ! 44087: f = f1; ! 44088: } ! 44089: ! 44090: if (f) { ! 44091: if (base==LDOUBLE || (t && t->base==LDOUBLE)) return ldouble_type; ! 44092: if (base==DOUBLE || (t && t->base==DOUBLE)) return double_type; ! 44093: return float_type; ! 44094: } ! 44095: if (l & u) return ulong_type; ! 44096: if (l & !u) return long_type; ! 44097: if (u) { ! 44098: if (base==INT || (t && t->base==INT)) return uint_type; ! 44099: if (SZ_SHORT==SZ_INT) // ANSIism ! 44100: if (base==SHORT || (t && t->base==SHORT)) return uint_type; ! 44101: return int_type; ! 44102: } ! 44103: ! 44104: if (t && t->base == EOBJ && base == EOBJ) enum_promote = 1; ! 44105: return int_type; ! 44106: } ! 44107: ! 44108: bit vec_const = 0; ! 44109: bit fct_const = 0; ! 44110: ! 44111: bit type::tconst() ! 44112: /* ! 44113: is this type a constant ! 44114: */ ! 44115: { ! 44116: Ptype t = this; ! 44117: vec_const = 0; ! 44118: fct_const = 0; ! 44119: //error('d',"tconst %t",t); ! 44120: xxx: ! 44121: switch (t->base) { ! 44122: case TYPE: ! 44123: if (Pbase(t)->b_const) return 1; ! 44124: t = Pbase(t)->b_name->tp; ! 44125: goto xxx; ! 44126: case VEC: ! 44127: vec_const = 1; ! 44128: return 1; ! 44129: case PTR: ! 44130: case RPTR: ! 44131: return Pptr(t)->rdo; ! 44132: case FCT: ! 44133: case OVERLOAD: ! 44134: fct_const = 1; ! 44135: return 1; ! 44136: default: ! 44137: return Pbase(t)->b_const; ! 44138: } ! 44139: } ! 44140: ! 44141: TOK type::set_const(bit mode) ! 44142: /* ! 44143: make someting a constant or variable, return old status ! 44144: */ ! 44145: { ! 44146: Ptype t = this; ! 44147: int m; ! 44148: xxx: ! 44149: switch (t->base) { ! 44150: case TYPE: ! 44151: m = Pbase(t)->b_const; ! 44152: Pbase(t)->b_const = mode; ! 44153: t = Pbase(t)->b_name->tp; ! 44154: goto xxx; ! 44155: case ANY: ! 44156: case RPTR: ! 44157: case VEC: ! 44158: return t->base; // constant by definition ! 44159: case PTR: ! 44160: m = Pptr(t)->rdo; ! 44161: Pptr(t)->rdo = mode; ! 44162: return m; ! 44163: default: ! 44164: m = Pbase(t)->b_const; ! 44165: Pbase(t)->b_const = mode; ! 44166: return m; ! 44167: } ! 44168: } ! 44169: ! 44170: Pptr type::is_ref() ! 44171: { ! 44172: Ptype t = this; ! 44173: xxx: ! 44174: switch (t->base) { ! 44175: case TYPE: t = Pbase(t)->b_name->tp; goto xxx; ! 44176: case RPTR: return Pptr(t); ! 44177: default: return 0; ! 44178: } ! 44179: } ! 44180: ! 44181: Pclass Mptr; ! 44182: ! 44183: Pptr type::is_ptr() ! 44184: { ! 44185: Ptype t = this; ! 44186: xxx: ! 44187: switch (t->base) { ! 44188: case TYPE: t = Pbase(t)->b_name->tp; goto xxx; ! 44189: case PTR: ! 44190: case VEC: Mptr = Pptr(t)->memof; ! 44191: return Pptr(t); ! 44192: default: return 0; ! 44193: } ! 44194: } ! 44195: ! 44196: Pptr type::is_ptr_or_ref() ! 44197: { ! 44198: Ptype t = this; ! 44199: xxx: ! 44200: switch (t->base) { ! 44201: case TYPE: t = Pbase(t)->b_name->tp; goto xxx; ! 44202: case PTR: ! 44203: case RPTR: ! 44204: case VEC: Mptr = Pptr(t)->memof; ! 44205: return Pptr(t); ! 44206: default: return 0; ! 44207: } ! 44208: } ! 44209: ! 44210: int type::align() ! 44211: { ! 44212: Ptype t = this; ! 44213: xx: ! 44214: /*fprintf(stderr,"align %d %d\n",t,t->base);*/ ! 44215: switch (t->base) { ! 44216: case TYPE: t = Pbase(t)->b_name->tp; goto xx; ! 44217: case COBJ: t = Pbase(t)->b_name->tp; goto xx; ! 44218: case VEC: t = Pvec(t)->typ; goto xx; ! 44219: case ANY: return 1; ! 44220: case CHAR: return AL_CHAR; ! 44221: case SHORT: return AL_SHORT; ! 44222: case INT: return AL_INT; ! 44223: case LONG: return AL_LONG; ! 44224: case FLOAT: return AL_FLOAT; ! 44225: case DOUBLE: return AL_DOUBLE; ! 44226: case LDOUBLE: return AL_LDOUBLE; ! 44227: case PTR: ! 44228: case RPTR: return AL_WPTR; ! 44229: case CLASS: return Pclass(t)->obj_align; ! 44230: case ENUM: ! 44231: case EOBJ: return AL_INT; ! 44232: case VOID: error("illegal use of void"); return AL_INT; ! 44233: default: error('i',"(%d,%k)->type::align",t,t->base); ! 44234: } ! 44235: } ! 44236: ! 44237: bit fake_sizeof; ! 44238: ! 44239: int type::tsizeof(int ptmc) ! 44240: /* ! 44241: the sizeof type operator ! 44242: return the size in bytes of the types representation ! 44243: */ ! 44244: { ! 44245: Ptype t = this; ! 44246: zx: ! 44247: //error('d',"zx %t %d",t,t->base); ! 44248: if (t == 0) error('i',"typ.tsizeof(t==0)"); ! 44249: switch (t->base) { ! 44250: case TYPE: ! 44251: t = Pbase(t)->b_name->tp; ! 44252: goto zx; ! 44253: case COBJ: ! 44254: t = Pbase(t)->b_name->tp; ! 44255: if (t == 0) return 0; // ``fake'' generated classes: _Sdd ! 44256: goto zx; ! 44257: ! 44258: case ANY: return 1; ! 44259: case VOID: return 0; ! 44260: case ZTYPE: return SZ_WPTR; /* assume pointer */ ! 44261: case CHAR: return SZ_CHAR; ! 44262: case SHORT: return SZ_SHORT; ! 44263: case INT: return SZ_INT; ! 44264: case LONG: return SZ_LONG; ! 44265: case FLOAT: return SZ_FLOAT; ! 44266: case DOUBLE: return SZ_DOUBLE; ! 44267: case LDOUBLE: return SZ_LDOUBLE; ! 44268: ! 44269: case VEC: ! 44270: { Pvec v = Pvec(t); ! 44271: if (v->size == 0) { ! 44272: if (fake_sizeof == 0) error('w',"sizeof array with undeclared dimension"); ! 44273: return SZ_WPTR; // vector argument has sizeof ptr ! 44274: } ! 44275: return v->size * v->typ->tsizeof(); ! 44276: } ! 44277: case RPTR: ! 44278: case PTR: ! 44279: { ! 44280: int k = (Pptr(t)->memof && !ptmc)?sizeof(short)+sizeof(short):0; ! 44281: t = Pptr(t)->typ; ! 44282: xxx: ! 44283: switch (t->base) { ! 44284: default: return SZ_WPTR; ! 44285: case CHAR: return SZ_BPTR; ! 44286: case FCT: return SZ_WPTR+k; ! 44287: case TYPE: t = Pbase(t)->b_name->tp; goto xxx; ! 44288: } ! 44289: } ! 44290: case FIELD: ! 44291: error("sizeof(field)"); ! 44292: return Pbase(t)->b_bits/BI_IN_BYTE+1; ! 44293: case FCT: ! 44294: error("sizeof(function)"); ! 44295: return 0; ! 44296: ! 44297: case CLASS: ! 44298: { ! 44299: Pclass cl = Pclass(t); ! 44300: if ((cl->defined&(DEFINED|SIMPLIFIED)) == 0) { ! 44301: error("%tU, size not known",cl); ! 44302: return SZ_INT; ! 44303: } ! 44304: if (cl->c_body == 1) // detect first allocation or sizeof ! 44305: cl->dcl_print(0); ! 44306: return cl->obj_size; ! 44307: } ! 44308: ! 44309: case EOBJ: ! 44310: case ENUM: return SZ_INT; ! 44311: ! 44312: default: return 0; // deref can be called for any type ! 44313: //error('i',"sizeof(%d)",t->base); ! 44314: } ! 44315: } ! 44316: ! 44317: bit type::vec_type() ! 44318: { ! 44319: Ptype t = this; ! 44320: xx: ! 44321: switch (t->base) { ! 44322: case ANY: ! 44323: case VEC: ! 44324: case PTR: ! 44325: case RPTR: return 1; ! 44326: case TYPE: t = Pbase(t)->b_name->tp; goto xx; ! 44327: default: return 0; ! 44328: } ! 44329: } ! 44330: ! 44331: int ref_initializer; ! 44332: ! 44333: Ptype type::deref() ! 44334: /* index==1: *p ! 44335: index==0: p[expr] ! 44336: */ ! 44337: { ! 44338: //error('d',"%t -> deref() refd %d",this,ref_initializer); ! 44339: Ptype t = this; ! 44340: xx: ! 44341: switch (t->base) { ! 44342: case TYPE: ! 44343: t = Pbase(t)->b_name->tp; ! 44344: goto xx; ! 44345: case PTR: ! 44346: case RPTR: ! 44347: case VEC: ! 44348: { if (t == Pvoid_type) error("void* dereferenced"); ! 44349: Ptype tt = t = Pvec(t)->typ; ! 44350: if (ref_initializer == 0) { ! 44351: while (tt->base == TYPE) tt = Pbase(tt)->b_name->tp; ! 44352: if (tt->base == COBJ) { ! 44353: tt = Pbase(tt)->b_name->tp; ! 44354: if (tt && Pclass(tt)->defined&(DEFINED|SIMPLIFIED)) ! 44355: (void) t->tsizeof(); ! 44356: } ! 44357: } ! 44358: // no break ! 44359: } ! 44360: case ANY: ! 44361: return t; ! 44362: default: ! 44363: error("nonP dereferenced"); ! 44364: return any_type; ! 44365: } ! 44366: } ! 44367: ! 44368: Pfct type::memptr() ! 44369: // is ``this'' a pointer to member function ! 44370: { ! 44371: Ptype t = this; ! 44372: while (t->base == TYPE) t = Pbase(t)->b_name->tp; ! 44373: if (t->base != PTR || Pptr(t)->memof==0) return 0; ! 44374: ! 44375: t = Pptr(t)->typ; ! 44376: while (t->base == TYPE) t = Pbase(t)->b_name->tp; ! 44377: return (t->base == FCT) ? Pfct(t) : 0; ! 44378: } ! 44379: 0707071010112045741004440001630000160000010177160466055413400001200000002731typedef.h /*ident "@(#)ctrans:src/typedef.h 1.2" */ ! 44380: /************************************************************************** ! 44381: ! 44382: C++ source for cfront, the C++ compiler front-end ! 44383: written in the computer science research center of Bell Labs ! 44384: ! 44385: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 44386: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 44387: ! 44388: typedef.h: ! 44389: ! 44390: *****************************************************************************/ ! 44391: ! 44392: typedef unsigned char TOK; ! 44393: typedef unsigned char bit; // sometimes used as bits ! 44394: typedef class node * PP; ! 44395: typedef int (*PFI)(); ! 44396: typedef void (*PFV)(); ! 44397: typedef class node * Pnode; ! 44398: typedef struct key * Pkey; ! 44399: typedef class name * Pname; ! 44400: typedef class basetype * Pbase; ! 44401: typedef class basecl* Pbcl; ! 44402: typedef class type * Ptype; ! 44403: typedef class fct * Pfct; ! 44404: typedef class field * Pfield; ! 44405: typedef class expr * Pexpr; ! 44406: typedef class qexpr * Pqexpr; ! 44407: typedef class texpr * Ptexpr; ! 44408: typedef class classdef * Pclass; ! 44409: typedef class enumdef * Penum; ! 44410: typedef class stmt * Pstmt; ! 44411: typedef class estmt * Pestmt; ! 44412: typedef class tstmt * Ptstmt; ! 44413: typedef class vec * Pvec; ! 44414: typedef class ptr * Pptr; ! 44415: typedef class block * Pblock; ! 44416: typedef class table * Ptable; ! 44417: typedef struct loc Loc; ! 44418: typedef class call * Pcall; ! 44419: typedef class gen* Pgen; ! 44420: typedef class ref * Pref; ! 44421: typedef class name_list * Plist; ! 44422: typedef class iline * Pin; ! 44423: typedef class nlist * Pnlist; ! 44424: typedef class slist * Pslist; ! 44425: typedef class elist * Pelist; ! 44426: typedef class virt * Pvirt; ! 44427: typedef char* Pchar; ! 44428: ! 44429: 0707071010112045751004440001630000160000010201670466055413700001200000001374yystype.h /*ident "@(#)ctrans:src/yystype.h 1.2" */ ! 44430: /************************************************************************** ! 44431: ! 44432: C++ source for cfront, the C++ compiler front-end ! 44433: written in the computer science research center of Bell Labs ! 44434: ! 44435: Copyright (c) 1984 AT&T, Inc. All Rights Reserved ! 44436: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC. ! 44437: ! 44438: yystype: ! 44439: ! 44440: *****************************************************************************/ ! 44441: ! 44442: typedef union { ! 44443: char* s; ! 44444: TOK t; ! 44445: int i; ! 44446: loc l; ! 44447: Pname pn; ! 44448: Ptype pt; ! 44449: Pexpr pe; ! 44450: Pstmt ps; ! 44451: Pbase pb; ! 44452: Pnlist nl; ! 44453: Pslist sl; ! 44454: Pelist el; ! 44455: Pbcl pbc; ! 44456: Pptr pp; ! 44457: PP p; // fudge: pointer to all class node objects ! 44458: Plist pl; // fudge: pointer to all class node objects ! 44459: } YYSTYPE; ! 44460: extern YYSTYPE yylval; ! 44461: 0707071010112045751004440001630000160000010201670466055413700001300000000000TRAILER!!! ss node objects ! 44462: } YYSTYPE; ! 44463: extern YYSTYPE yylval; ! 44464: 0707071010112045751004440001630000160000010201670466055413700001300000000000TRAILER!!! ss node objects ! 44465: } YYSTYPE; ! 44466: extern YYSTYPE yylval; ! 44467: 0707071010112045751004440001630000160000010201670466055413700001300000000000TRAILER!!! ss node objects ! 44468: } YYSTYPE; ! 44469: extern YYSTYPE yylval; ! 44470: 070707101011204575100444000163000016000001020167046
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.