|
|
1.1 root 1: /*ident "@(#)ctrans:src/expr.c 1.1.5.38" */
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 rigths Reserved
8: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
9:
10: expr.c:
11:
12: type check expressions
13:
14: ************************************************************************/
15:
16: #include "cfront.h"
17: #include "size.h"
18:
19: int const_save;
20: int const_ptr;
21: extern Ptype Pfct_type;
22:
23: Pexpr expr::address()
24: {
25: // error('d',"address %k %d %s",base,base,base==NAME||base==ANAME?string:"?");
26: // error('d',"address e1 %d %k e2 %d %k", e1, e1?e1->base:0, e2, e2?e2->base:0);
27: switch (base) {
28: case DEREF:
29: if (e2 == 0) return e1; // &*e => e
30: break;
31: case QUEST: // &(a?b:c) => a?&b:&c
32: e1 = e1->address();
33: // no break;
34: case G_CM:
35: if ( e1 && e1->base == G_CALL &&
36: e2 && e2->base == G_ADDROF)
37: return this;
38: case CM:
39: e2 = e2->address(); // &(e1,e2) => (e1,&e2)
40: tp = e2->tp; //LLL
41: return this;
42: case INCR:
43: case DECR: // &(++a) => (++a,&a)
44: if (e1) break;
45: nin++;
46: if (e2->not_simple()) error('s',"& of%k",base);
47: nin--;
48: e1 = new expr(base,0,e2);
49: e2 = e2->address();
50: base = G_CM;
51: tp = e2->tp;
52: return this;
53: case ASSIGN: // &(a=b) => ((a=b),&a)
54: case ASPLUS:
55: case ASMINUS:
56: case ASMUL:
57: case ASDIV:
58: case ASMOD:
59: case ASAND:
60: case ASOR:
61: case ASER:
62: case ASLS:
63: case ASRS:
64: nin++;
65: if (e1->not_simple()) error('s',"& of%k",base);
66: nin--;
67: Pexpr a = new expr(base,e1,e2);
68: a->tp = a->e1->tp;
69: base = G_CM;
70: e1 = a;
71: e2 = a->e1->address();
72: tp = e2->tp;
73: return this;
74:
75: case NAME:
76: if (Pname(this)->n_stclass == REGISTER) error("& register%n",Pname(this));
77: Pname(this)->take_addr();
78: break;
79: case CALL:
80: case CAST:
81: case NEW:
82: case GNEW:
83: if (tp && tp->is_ptr_or_ref()) { // hack?
84: return this;
85: }
86: break;
87: }
88:
89: register Pexpr ee = new expr(G_ADDROF,0,this);
90: if (tp) { // tp==0 ???
91: ee->tp = tp->addrof();
92:
93: switch (tp->base) {
94: case PTR:
95: Pptr(ee->tp)->memof = Pptr(tp)->memof;
96: break;
97: case FCT:
98: if (Pfct(tp)->f_static==0)
99: Pptr(ee->tp)->memof = Pfct(tp)->memof;
100: break;
101: case OVERLOAD:
102: if (Pfct(Pgen(tp)->fct_list->f->tp)->f_static==0)
103: Pptr(ee->tp)->memof = Pfct(Pgen(tp)->fct_list->f->tp)->memof;
104: }
105: }
106:
107: return ee;
108: }
109:
110: Pexpr expr::contents()
111: {
112: //error('d',"deref %k %d %t",base,base,tp);
113: // if (base==ADDROF || base==G_ADDROF) return e2; // *&
114: switch (base) {
115: case ADDROF:
116: case G_ADDROF:
117: return e2; // *&
118: case ELIST:
119: //error('d',"contents of elist");
120: e1 = e1->contents();
121: tp = e1->tp;
122: return this;
123: };
124:
125: register Pexpr ee = new expr(DEREF,this,0);
126: if (tp) { // tp==0 ???
127: Ptype tt = tp;
128: while (tt->base == TYPE) tt = Pbase(tt)->b_name->tp;
129: ee->tp = Pptr(tt)->typ;
130: Pname cn = ee->tp->is_cl_obj();
131: if (cn) {
132: Pclass cl = Pclass(cn->tp);
133: if (cl->c_body==1) cl->dcl_print(0); // look for first use of cl
134: }
135: }
136: return ee;
137: }
138:
139: int bound;
140: int chars_in_largest; // no of characters in largest int
141: static Pclass mpglob;
142:
143: Pexpr expr::typ(Ptable tbl)
144: /*
145: find the type of "this" and place it in tp;
146: return the typechecked version of the expression:
147: "tbl" provides the scope for the names in "this"
148: */
149: {
150: //if (this == 0) error('i',"0->expr::typ");
151: Pname n;
152: Ptype t = 0;
153: Ptype t1, t2;
154: TOK b = base;
155: TOK r1, r2;
156: #define nppromote(b) t=np_promote(b,r1,r2,t1,t2,1)
157: #define npcheck(b) (void)np_promote(b,r1,r2,t1,t2,0)
158: if (tbl->base != TABLE) error('i',"expr::typ(%d)",tbl->base);
159:
160: DB( if(Tdebug>=1) {
161: error('d',"%d->expr::typ(%d) %k %t",this,tbl,b,tp);
162: display_expr(this);
163: });
164: // error('d',"%k->typ %n tp: %t", b,b==NAME?this:0,tp);
165: // error('d'," e1 %d %k e1 %d %k",e1,e1?e1->base:0,e2,e2?e2->base:0);
166: if (tp) {
167: switch (b) {
168: case NAME:
169: //?? Pname(this)->use();
170: break;
171: case MDOT:
172: mem = mem->typ(tbl);
173: } ;
174: // if (b == NAME) Pname(this)->use();
175: return this;
176: }
177:
178: extern Pname Ntmp;
179:
180: switch (b) { // is it a basic type
181: case MDOT:
182: error('i',"mdot %s",string2);
183: case DUMMY:
184: error("emptyE");
185: tp = any_type;
186: return this;
187:
188: case ZERO:
189: tp = zero_type;
190: return this;
191:
192: case IVAL:
193: tp = int_type;
194: return this;
195:
196: //case FVAL:
197: // tp = float_type;
198: // return this;
199:
200: case ICON:
201: /* is it long?
202: explicit long?
203: decimal larger than largest signed int
204: octal or hexadecimal larger than largest unsigned int
205: */
206: { int ll = strlen(string);
207: switch (string[ll-1]) {
208: case 'l':
209: case 'L':
210: switch (string[ll-2]) {
211: case 'u':
212: case 'U':
213: string[ll-2] = 0;
214: tp = ulong_type;
215: goto cast_n_save;
216: }
217: lng:
218: tp = long_type;
219: goto save;
220: case 'u':
221: case 'U': // 1u => unsigned(1)
222: switch (string[ll-2]) {
223: case 'l':
224: case 'L':
225: string[ll-2] = 0;
226: ulng:
227: tp = ulong_type;
228: goto cast_n_save;
229: default:
230: string[ll-1] = 0;
231: uint:
232: tp = uint_type;
233: goto cast_n_save;
234: }
235: }
236:
237: // no suffix - see if we can figure it out
238: if (string[0] == '0') { // assume 8 bits in byte
239: register index = 1;
240: switch (string[1]) {
241: case 'x':
242: case 'X':
243: while(string[++index]=='0') ;
244: ll -= index;
245: int HSZ = SZ_INT+SZ_INT;
246: if(ll < HSZ) goto nrm;
247: if(ll == HSZ)
248: if(string[2]>='8') goto uint;
249: else goto nrm;
250: if(SZ_INT==SZ_LONG) break;
251: HSZ = SZ_LONG+SZ_LONG;
252: if(ll < HSZ) goto lng;
253: if(ll == HSZ)
254: if(string[2]>='8') goto ulng;
255: else goto lng;
256: break;
257: default: // OCTAL
258: register IBITS = BI_IN_BYTE*SZ_INT;
259: while(string[index]=='0') index++;
260: register char x = string[index];
261: int lbt = x=='1' ? 1 :
262: ( x=='2' || x=='3' ? 2 : 3 );
263: int nbits = (ll-index-1)*3 + lbt;
264: if(nbits < IBITS) goto nrm;
265: if(nbits == IBITS) goto uint;
266: if(nbits < BI_IN_BYTE*SZ_LONG) goto lng;
267: }
268: goto ulng;
269: }
270: else { // DECIMAL
271: if (ll<chars_in_largest) {
272: nrm:
273: tp = int_type;
274: goto save;
275: }
276: if (ll>chars_in_largest) {
277: if(SZ_INT==SZ_LONG || ll>2*chars_in_largest)
278: goto ulng;
279: goto lng;
280: }
281: // ll == chars_in_largest
282: char* p = string;
283: char* q = LARGEST_INT;
284: do if (*p>*q) {
285: if(SZ_INT==SZ_LONG) goto ulng;
286: goto lng;
287: } while (*p++==*q++ && *p);
288: }
289:
290: goto nrm;
291: }
292: case CCON:
293: tp = c_strlen(string)<5 ? char_type : int_type; // stored as 'a'
294: goto save;
295:
296: case FCON:
297: { int ll = strlen(string);
298: int last = string[ll-1];
299: tp = double_type;
300: if (last=='F' || last=='f') {
301: tp = float_type;
302: if (!ansi_opt) {
303: string[ll-1] = 0;
304: goto cast_n_save;
305: }
306: }
307: else if (last=='L' || last=='l') {
308: if (ansi_opt == 0) string[ll-1] = 0;
309: tp = ldouble_type;
310: }
311: goto save;
312: }
313: case STRING: // type of "as\tdf" is char[6]
314: // c_strlen counts the terminating '\0'
315: { Pvec v = new vec(char_type,0);
316: v->size = c_strlen(string);
317: tp = v;
318: }
319: save:
320: if (const_save) { // "as\tdf" needs 7 chars for storage
321: char* p = new char[strlen(string)+1];
322: strcpy(p,string);
323: string = p;
324: }
325:
326: return this;
327:
328: cast_n_save:
329: if (const_save) { // "as\tdf" needs 7 chars for storage
330: char* p = new char[strlen(string)+1];
331: strcpy(p,string);
332: string = p;
333: }
334:
335: return new cast(tp,this);
336:
337: case THIS:
338: delete this;
339: if (cc->c_this) {
340: cc->c_this->use();
341: return cc->c_this;
342: }
343: error("``this'' used in nonC context");
344: n = new name("this");
345: n->tp = any_type;
346: return tbl->insert(n,0);
347:
348: case NAME:
349: {
350: Pname q = Pname(this)->n_qualifier; // suppress virtual iff x::
351: Pexpr ee = find_name(Pname(this),cc->cot,tbl,0,cc->nof);
352: if (q && (ee->base==REF || ee->base==DOT))
353: ee->n_initializer = Pexpr(q);
354: //error('d',"ee %k %t %n",ee->base,ee->tp,ee->base==NAME?ee:ee->base==REF?ee->mem:0);
355: // if (ee->tp->base == RPTR) return ee->contents();
356: if (ee->tp->is_ref()) return ee->contents();
357:
358: if (ee->base==NAME && Pname(ee)->n_xref) {
359: // fudge to handle X(X&) args
360: ee = new expr(DEREF,ee,0);
361: ee->tp = ee->e1->tp; // !!
362: }
363:
364: return ee;
365: }
366:
367: case ADDROF:
368: case G_ADDROF: // handle lookup for &s::i
369: mpglob = 0;
370: if (e2->base == NAME) e2 = find_name(Pname(e2),cc->cot,tbl,ADDROF,cc->nof);
371: if (e2->base==NAME && Pname(e2)->n_xref) {
372: // fudge to handle X(X&) args
373: e2 = new expr(DEREF,e2,0);
374: e2->tp = e2->e1->tp; // !!
375: }
376: if (e2->base==DOT) { // &f().x = > &(tmp=f(),&tmp)->x
377: switch (e2->e1->base) {
378: case CALL:
379: case G_CALL:
380: case VALUE:
381: error("& non-lvalue");
382: }
383: }
384: break;
385:
386: case SIZEOF:
387: if (tp2) {
388: tp2->dcl(tbl);
389: switch (tp2->base) {
390: case VOID:
391: error("sizeof(void)");
392: break;
393: case CLASS:
394: {
395: Pclass cl = Pclass(tp2);
396: if (cl->c_body==1
397: && (cl->defined&(DEFINED|SIMPLIFIED)) == 0)
398: error('s',"class defined within sizeof");
399: }
400: }
401:
402: if (e1 && e1!=dummy) {
403: e1 = e1->typ(tbl);
404: DEL(e1);
405: e1 = dummy;
406: }
407: Pptr r = tp2->is_ref();
408: if (r) tp2 = r->typ; // sizeof(T&)==sizeof(T)
409: }
410: else if (e1 == dummy) {
411: error("sizeof emptyE");
412: tp = any_type;
413: return this;
414: }
415: else {
416: e1 = e1->typ(tbl);
417: tp2 = e1->tp;
418: if(tp2->base == VEC) tp2->permanent = 1;
419: if (e1->base==ILIST) // PtoM
420: e1 = dummy;
421: else if (tp2 == char_type) // sizeof ('a')
422: e1 = dummy;
423: }
424: (void) tp2->tsizeof();
425: tp = size_t_type;
426: return this;
427:
428: case CAST:
429: // return docast(tbl);
430:
431: { Pexpr ee = docast(tbl);
432: return ee->tp->is_ref() ? ee->contents() : ee;
433: }
434:
435:
436: case VALUE:
437: if ( tp2->base == COBJ ) {
438: char *s = Pbase(tp2)->b_name->string;
439: //Pname tn = gtbl->look( s, 0 );
440: //??? non type name apparently takes precedence
441: // Don't use global ftn if it hides local
442: // class ctor. (Note: More info is needed
443: // to detect all cases.)
444: Pname tn = tbl->look( s, 0 );
445: //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 );
446: if ( tn && tn->n_qualifier == 0
447: && tn->lex_level == Pbase(tp2)->b_name->lex_level
448: && (tn->tp->base==FCT || tn->tp->base==OVERLOAD))
449: {
450: Pexpr et = new expr( CALL, tn, e1 );
451: *this = *et;
452: b = CALL;
453: break;
454: }
455: }
456: return dovalue(tbl);
457:
458: case NEW:
459: case GNEW:
460: return donew(tbl);
461:
462: case DELETE: // delete e1 OR delete[e2] e1
463: case GDELETE:
464: { int i;
465: if (e1->base == ADDROF) error('w',"delete &E");
466: e1 = e1->typ(tbl);
467: i = e1->tp->num_ptr(DELETE);
468: if (i != 'P') error("nonP deleted");
469: if (e2) {
470: e2 = e2->typ(tbl);
471: e2->tp->integral(DELETE);
472: }
473: tp = void_type;
474: return this;
475: }
476:
477: case ILIST: /* an ILIST is pointer to an ELIST */
478: e1 = e1->typ(tbl);
479: tp = any_type;
480: return this;
481:
482: case ELIST:
483: { Pexpr e;
484: Pexpr ex;
485:
486: if (e1 == dummy && e2==0) {
487: error("emptyIrL");
488: tp = any_type;
489: return this;
490: }
491:
492: for (e=this; e; e=ex) {
493: Pexpr ee = e->e1;
494: //error('d',"e %d %d ee %d %d",e,e?e->base:0,ee,ee?ee->base:0);
495: if (e->base != ELIST) error('i',"elist%k",e->base);
496: if (ex = e->e2) { /* look ahead for end of list */
497: if (ee == dummy) error("EX in EL");
498: if (ex->e1 == dummy && ex->e2 == 0) {
499: /* { ... , } */
500: DEL(ex);
501: e->e2 = ex = 0;
502: }
503: }
504: e->e1 = ee->typ(tbl);
505: t = e->e1->tp;
506: if (t->base == FCT) { // yuk!
507: ee = new expr(G_ADDROF,0,e->e1);
508: e->e1 = ee->typ(tbl);
509: t = e->e1->tp;
510: }
511: }
512: tp = t;
513: return this;
514: }
515:
516: case DOT:
517: case REF:
518: { if (e2) { // *. or ->*
519: if (b == REF) b = base = REFMUL;
520: break;
521: }
522:
523: Pbase b;
524:
525: e1 = e1->typ(tbl);
526: t = e1->tp;
527:
528: // check that . (->) is applied to class object (pointer)
529: if (base == REF) {
530: xxx:
531: switch (t->base) {
532: case TYPE:
533: t = Pbase(t)->b_name->tp;
534: goto xxx;
535: case COBJ:
536: { Pname n = Pclass(Pbase(t)->b_name->tp)->has_oper(REF);
537: if (n) {
538: n->n_used += 2;
539: e1 = new call(new ref(DOT,e1,n),0);
540: return typ(tbl);
541: }
542: // no break;
543: }
544: default:
545: error("nonP ->%n",mem);
546: t = any_type;
547: // no break;
548: case ANY:
549: goto qqq;
550: case PTR:
551: case VEC:
552: b = Pbase(Pptr(t)->typ);
553: }
554: }
555: else { // base == DOT
556: qqq:
557: switch (t->base) {
558: case TYPE: t = Pbase(t)->b_name->tp; goto qqq;
559: default: error("nonO .%n",mem); t = any_type;
560: case ANY:
561: case COBJ: break;
562: }
563: //error('d',"dot %k",e1->base);
564: switch (e1->base) {
565: case QUEST:
566: case ASSIGN:
567: case INCR:
568: case DECR:
569: case ASPLUS:
570: case ASMINUS:
571: case ASMUL:
572: case ASDIV:
573: case ASMOD:
574: case ASAND:
575: case ASOR:
576: case ASER:
577: case ASLS:
578: case ASRS:
579: case CM:
580: case G_CM:
581: base = REF;
582: e1 = e1->address();
583: break;
584: case CALL:
585: case G_CALL:
586: //error('d'," f(). %n mem->tp %t",e1->fct_name,mem->tp);
587: #ifdef FDOTRIGHT
588: // this rewrite is only necessary on machines with broken C compilers
589: // there seems to be a lot of those
590: // and for inlines (a,b).c
591: if (e1->fct_name && Pfct(e1->fct_name->tp)->f_inline)
592: #endif
593: { // f(). => (tmp=f(),&tmp)->
594: Pname tmp = make_tmp('Q',e1->tp,tbl);
595: //error('d',"fdot2 %k",e1->base);
596: e1 = init_tmp(tmp,e1,tbl);
597: Pexpr aa = tmp->address();
598: e1 = new expr(G_CM,e1,aa);
599: e1->tp = aa->tp;
600: base = REF;
601: break;
602: }
603: }
604: b = Pbase(t);
605: }
606:
607: xxxx:
608: switch (b->base) {
609: case TYPE:
610: b = Pbase(b->b_name->tp);
611: goto xxxx;
612: default:
613: error("(%t) before %k%n (%n not aM)",e1->tp,base,mem,mem);
614: case ANY:
615: tp = any_type;
616: return this;
617: case COBJ:
618: { Pclass cl = Pclass(Pbase(b)->b_name->tp);
619: if (cl->c_body == 1) cl->dcl_print(0);
620: break;
621: }
622: }
623:
624: /*
625: x.m is not a const even if x is a const object, this case is handled
626: by lval() rejecting it
627: */
628:
629: if (mem->tp) {
630: tp = mem->tp;
631: for (Pexpr ee = mem; ee->base==REF; ee = ee->e1) {
632: if (ee->e1 == cc->c_this) { // this-> => p->
633: ee->e1 = e1;
634: ee->base = base;
635: return mem->tp->is_ref() ? mem->contents() : mem;
636: }
637: }
638:
639: // return tp->base==RPTR ? contents() : this;
640: return tp->is_ref() ? contents() : this;
641: }
642:
643:
644: Pname q = Pname(mem)->n_qualifier;
645: Pexpr e = find_name(Pname(mem),Pclass(b->b_name->tp),0,base,cc->nof);
646: if (q && (e->base==REF || e->base==DOT))
647: Pname(e)->n_initializer = Pexpr(q);
648: //error('d',"e %k %t %n",e->base,e->tp,e->base==NAME?e:e->base==REF?e->mem:0);
649:
650: for (Pexpr ee = e; ee->base==REF; ee = ee->e1) {
651: if (ee->e1 == cc->c_this) { // this-> => p->
652: ee->e1 = e1;
653: ee->base = base;
654: break;
655: }
656: }
657:
658: if (e->base == NAME) {
659: switch (e->tp->base) {
660: case FCT:
661: case OVERLOAD:
662: mem = e;
663: tp = e->tp;
664: e = this;
665: }
666: }
667:
668: // function or static member
669: return e->tp->is_ref() ? e->contents() : e;
670: }
671:
672: //?? case G_CALL:
673: case CALL: /* handle undefined function names */
674: //error('d',"call %k %t %k",e1->base,e1->tp,e2?e2->base:0);
675: if (e1->base==NAME && e1->tp==0) {
676: Pname q = Pname(e1)->n_qualifier;
677: e1 = find_name(Pname(e1),cc->cot,tbl,CALL,cc->nof);
678: //error('d',"e1 %k %t %n",e1->base,e1->tp,e1->base==NAME?e1:e1->base==REF?e1->mem:0);
679: if (q && (e1->base==REF ||e1->base==DOT)) // suppress virtual call
680: e1->n_initializer = Pexpr(q);
681: }
682:
683: if (e1->base==NAME && Pname(e1)->n_xref) {
684: // fudge to handle X(X&) args
685: e1 = new expr(DEREF,e1,0);
686: e1->tp = e1->e1->tp; // !!
687: }
688:
689: switch (e1->base) {
690: case DOT:
691: /*
692: #ifdef FDOTRIGHT
693: {
694: //error('d',"fdot1 %k",e1->e1->base);
695: switch (e1->e1->base) {
696: case CALL:
697: case G_CALL: // f().g() => (tmp=f(),tmp.g())
698: { Pexpr ee = e1->e1;
699: Pexpr ex = ee->typ(tbl);
700: Pname tmp = make_tmp('Q',ex->tp,tbl);
701: ex = init_tmp(tmp,ex,tbl);
702:
703: Pexpr ee2 = new expr(base,e1,e2);
704: e1->base = DOT;
705: e1->e1 = tmp;
706:
707: base = G_CM;
708: e1 = ex;
709: e2 = ee2;
710:
711: return typ(tbl);
712: }
713: }
714: break;
715: }
716: #endif
717: */
718: case REF: // becomes ob.x::~x(0) or
719: if (e2==0 // becomes p->x::~x(0)
720: && Pref(e1)->mem
721: && Pref(e1)->mem->base==NAME
722: && Pname(Pref(e1)->mem)->n_oper==DTOR) {
723: e1 = e1->typ(tbl);
724: Pexpr ee = call_dtor(e1->e1,Pref(e1)->mem,0,e1->base,one);
725: ee->tp = void_type;
726: return ee;
727: }
728: }
729: break;
730:
731: case QUEST:
732: cond = cond->typ(tbl);
733: case ANDAND:
734: case OROR:
735: Ntmp = 0;
736: }
737:
738: if (e1) {
739: e1 = e1->typ(tbl);
740: if (e1->tp->is_ref()) e1 = e1->contents();
741: t1 = e1->tp;
742: // if (t1->is_cl_obj()) t1->tsizeof();
743: }
744: else
745: t1 = 0;
746:
747: if (e2) {
748: e2 = e2->typ(tbl);
749: if (e2->tp->is_ref()) e2 = e2->contents();
750: t2 = e2->tp;
751: // if (t2->is_cl_obj()) t2->tsizeof();
752: }
753: else
754: t2 = 0;
755:
756: //error('d',"b %k t1 %t t2 %t",b,t1,t2);
757: switch (b) { // filter out non-overloadable operators
758: default:
759: { Pexpr x = try_to_overload(tbl);
760: if (x) return x;
761: }
762: case DOT:
763: case G_CM:
764: case G_ADDROF:
765: case G_CALL:
766: case QUEST:
767: break;
768: }
769:
770: switch (b) {
771: case QUEST:
772: case ANDAND:
773: case OROR:
774: if (Ntmp) error('s',"temporary ofC%n with destructor needed in%kE",Ntmp,b);
775: }
776:
777: t = (t1==0) ? t2 : (t2==0) ? t1 : 0;
778: // error('d', "expr::typ t %t", t );
779: // error('d',"b2 %d %k",b,b);
780: switch (b) { /* are the operands of legal types */
781: case REFMUL:
782: base = REF;
783: // no break;
784: case DOT:
785: { // a .* p => &a MEMPTR p => appropriate indirection
786: // to be considered: what happens if a .* expression
787: // is used except in a call/=?
788: Pexpr a = e1->typ(tbl);
789: Ptype at = a->tp;
790: if (base == DOT) {
791: a = a->address();
792: at = at->addrof(); // beware of n_xref
793: }
794:
795: while (at->base == TYPE) at = Pbase(at)->b_name->tp;
796: Pname cn = Pptr(at)->typ->is_cl_obj();
797: Pclass mm = cn ? Pclass(cn->tp) : 0;
798:
799: Pexpr p = e2->typ(tbl);
800: Ptype pt = p->tp;
801: Pname pcn = pt->is_cl_obj();
802:
803: //error('d',"mm %t pt %t",mm,pt);
804: if (pcn) {
805: Pclass cl = Pclass(pcn->tp);
806: Pname found = 0;
807: for (Pname on=cl->conv; on; on=on->n_list) {
808: Pfct f = Pfct(on->tp);
809: Pptr frt = Pptr(f->returns);
810: while (frt->base == TYPE) frt = Pptr(Pbase(frt)->b_name->tp);
811: if (frt->base!=PTR || Pptr(frt)->memof==0) break;
812: if (Pptr(frt)->memof==mm || mm->has_base(Pptr(frt)->memof)) {
813: if (found)
814: error("two possible conversions forP toM: %n and %n",found,on);
815: else
816: found = on;
817: }
818: }
819: //error('d',"found %n",found);
820: if (found) {
821: p = new ref(DOT,p,found);
822: p = new call(p,0);
823: p = p->typ(tbl);
824: pt = p->tp;
825: }
826:
827: }
828: while (pt->base == TYPE) pt = Pbase(pt)->b_name->tp;
829: if (pt->base!=PTR || Pptr(pt)->memof==0) {
830: error("P toMX in .*E: %t",pt);
831: tp = any_type;
832: base = DUMMY;
833: return this;
834: }
835: Pclass pm = Pptr(pt)->memof;
836:
837: // while (at->base == TYPE) at = Pbase(at)->b_name->tp;
838: // Pname cn = Pptr(at)->typ->is_cl_obj();
839: // Pclass mm = cn ? Pclass(cn->tp) : 0;
840: //error('d',"mm %t %t %d %d",mm,pm,pm->baseof(mm),mm->has_base(pm));
841:
842: // if (mm!=pm && pm->baseof(mm)==0 && mm->has_base(pm)==0) {
843: if (mm != pm) {
844: if (mm->has_base(pm) == 0) {
845: error("badOT in .*E: %t (%s*X)",a->tp,pm->string);
846: tp = any_type;
847: //return this;
848: }
849: a = new texpr(CAST,pm->this_type,a);
850: e1 = a = a->typ(tbl);
851: }
852:
853: Ptype tpx = Pptr(pt)->typ;
854: while (tpx->base == TYPE) tpx = Pbase(tpx)->b_name->tp;
855:
856: if (tpx->base == FCT) { // a.*p => (&a MEMPTR p)
857: base = MEMPTR;
858: tp2 = mm; // keep the class for simpl.c
859: e1 = a;
860: e2 = p;
861: }
862: else { // a .* p => *(typeof(p))((char*)&a + (int)p-1)
863: a = new cast(Pchar_type,a);
864: p = new cast(int_type,p);
865: p = new expr(MINUS,p,one);
866: p->tp = int_type;
867: Pexpr pl = new expr(PLUS,a,p);
868: pl->tp = Pchar_type;
869: base = DEREF;
870: pt = new ptr(PTR,tpx); // need a T* not a T C::*
871: Pptr(pt)->rdo = Pptr(tpx)->rdo;
872: mpglob = pm;
873: // PERM(pt);
874: e1 = new cast(pt,pl);
875: e2 = 0;
876: }
877: tp = tpx;
878: return tp->is_ref() ? contents() : this;
879: }
880:
881: case G_CALL:
882: case CALL:
883: tp = call_fct(tbl); /* two calls of use() for e1's names */
884: if (tp->is_ref()) return contents();
885: return this;
886:
887: case DEREF:
888: if (e1 == dummy) error("O missing before []\n");
889: if (e2 == dummy) error("subscriptE missing");
890:
891: if (t) { /* *t */
892: while (t->base == TYPE) t = Pbase(t)->b_name->tp;
893: // t->vec_type();
894: if (t->base==PTR && Pptr(t)->memof) error("P toM dereferenced");
895: tp = t->deref();
896: }
897: else { // e1[e2] that is *(e1+e2)
898: //error('d',"deref %t[%t]",t1,t2);
899: if (t1->vec_type()) { // e1[e2]
900: switch (t2->base) {
901: case CHAR:
902: case SHORT:
903: case INT:
904: case LONG:
905: case EOBJ:
906: break;
907: default:
908: { Pname cn = t2->is_cl_obj();
909: if (cn) // conversion to integral?
910: e2 = check_cond(e2,DEREF,tbl);
911: else
912: t2->integral(DEREF);
913: }
914: }
915: while (t1->base == TYPE) t1 = Pbase(t1)->b_name->tp;
916: if (t1->base==PTR && Pptr(t1)->memof) error("P toM dereferenced");
917: tp = t1->deref();
918: (void) tp->tsizeof();
919: }
920: else if (t2->vec_type()) { // really e2[e1]
921: t1->integral(DEREF);
922: while (t2->base == TYPE) t2 = Pbase(t2)->b_name->tp;
923: if (t2->base==PTR && Pptr(t2)->memof) error("P toM dereferenced");
924: tp = t2->deref();
925: (void) tp->tsizeof();
926: }
927: else {
928: error("[] applied to nonPT:%t[%t]",t1,t2);
929: tp = any_type;
930: }
931: }
932:
933: if (tp->is_ref()) return contents();
934:
935: return this;
936:
937: case G_ADDROF:
938: case ADDROF:
939: //error('d',"addrof(%d) %k %d",base,e2->base,e2->base);
940: switch (e2->base) { // potential lvalues
941: case G_CM:
942: if (base==ADDROF && e2->e2->base==NAME) {
943: // check for cfront generated result variable
944: char* s = e2->e2->string;
945: if (s[0]=='_' && s[1] && s[1]=='_') {
946: if (s[2] && (s[2]=='R' || s[2]=='V')) {
947: error("address of non-lvalue");
948: break;
949: }
950: }
951: }
952: case CM: // &(a,b) => (a,&b)
953: {
954: Pexpr ee = e2;
955: ee->tp = 0;
956: ee->e2 = new expr(base,0,ee->e2);
957: delete this;
958: return ee->typ(tbl);
959: }
960: case QUEST: // & (a?b:c) => (a?&b:&c)
961: {
962: Pexpr ee = e2;
963: ee->tp = 0;
964: ee->e1 = new expr(base,0,ee->e1);
965: ee->e2 = new expr(base,0,ee->e2);
966: delete this;
967: return ee->typ(tbl);
968: }
969: case INCR:
970: case DECR:
971: if (e2->e1) break;
972: case ASSIGN:
973: case ASPLUS:
974: case ASMINUS:
975: case ASMUL:
976: case ASDIV:
977: case ASMOD:
978: case ASAND:
979: case ASOR:
980: case ASER:
981: case ASLS:
982: case ASRS:
983: return e2->address();
984: }
985:
986: if (e2->lval(ADDROF) == 0) {
987: if (error_count) { // error_count == 0 possible
988: // in case of & const
989: tp = any_type;
990: return this;
991: }
992: }
993:
994: tp = t->addrof();
995:
996: if( base==ADDROF && mpglob)
997: Pptr(tp)->memof = mpglob;
998:
999: if (e2->tp->base == VEC) {
1000: base = CAST;
1001: tp2 = tp;
1002: e1 = e2;
1003: e2 = 0;
1004: return this;
1005: }
1006:
1007: // tp = t->addrof();
1008: if (t->base==FCT)
1009: Pptr(tp)->memof = Pfct(t)->memof;
1010:
1011: // if (t->tconst() && vec_const==0 && fct_const==0) Pptr(tp)->rdo = 1;
1012: // ??? & (const T) is NOT T*const but const T*
1013:
1014: switch (e2->base) {
1015: case NAME:
1016: mname: // check for &s::i
1017: { Pname n2 = Pname(e2);
1018: Pname cn = (n2->n_table && n2->n_table!=gtbl) ? n2->n_table->t_name : 0;
1019: // error('d',"n2 %k cn %n t %t",n2->base,cn,t);
1020: if (cn == 0) break;
1021: // Pptr(tp)->memof = Pclass(cn->tp);
1022:
1023: if (t->base==FCT && Pfct(t)->f_this==0) {
1024: Pptr(tp)->memof = 0;
1025: break;
1026: }
1027:
1028: switch (t->base) {
1029: case OVERLOAD:
1030: return e2;
1031: case FCT:
1032: // error('d', "cn->tp: %d, %k", cn->tp, cn->tp->base);
1033: Pptr(tp)->memof = Pclass(cn->tp); //SSS
1034:
1035: if (Pfct(t)->f_virtual) {
1036: // { 0,vtbl index,0 }
1037: e1 = new ival(Pfct(t)->f_virtual);
1038: e1 = new expr(ELIST,zero,e1);
1039: e2 = zero;
1040: base = ILIST;
1041: // tp = int_type;
1042: return this;
1043: } // use the pointer
1044:
1045: // { 0,-1,(int(*)())ptr }
1046: e1 = new ival(-1);
1047: e1 = new expr(ELIST,zero,e1);
1048: // e2 is the name
1049: e2 = new cast(Pfct_type,e2);
1050: base = ILIST;
1051: // tp = int_type;
1052: return this;
1053:
1054: // return e2;
1055:
1056: default:
1057: if (n2->n_stclass != STATIC) { // offset + 1
1058: //error('d',"n2 %n %d",n2,n2->n_offset);
1059: //error('d',"q %n cn %n",n2->n_qualifier,cn);
1060: e1 = new ival(n2->n_offset+1);
1061: Pptr(tp)->memof = Pclass(cn->tp);
1062: //error('d',"cl %d %s i %d",Pclass(cn->tp),Pclass(cn->tp)?Pclass(cn->tp)->string:"0",n2->n_offset);
1063: }
1064: else
1065: return this;
1066: }
1067: //error('d',"int_type");
1068: e1->tp = int_type;
1069: e2 = 0;
1070: tp2 = tp;
1071: base = CAST;
1072: return this;
1073: }
1074: case DOT:
1075: case REF:
1076: {
1077: Pname m = Pname(e2->mem);
1078: // error( 'd', "e2->mem->base: %k", e2->mem->base );
1079: // Pname m = (e2->mem->base == MDOT) ? Pname(e2->mem->mem) : Pname(e2->mem);
1080: while ( m->base == MDOT ) m = Pname(Pexpr(m)->mem);
1081:
1082: Pfct f = Pfct(m->tp);
1083:
1084: if (f->base == FCT || f->base == OVERLOAD) { // &p->f
1085: Pexpr q = Pname(e2)->n_initializer; // &p->x::f
1086:
1087: if (q && bound==0 && e2->e1==cc->c_this) {
1088: // FUDGE: &this->x::f => &x::f
1089: DEL(e2);
1090: e2 = m;
1091: goto mname;
1092: }
1093:
1094: bound = 1;
1095: if(!f->f_static) {
1096: error(strict_opt?0:'w',
1097: "address of boundF (try using ``%s::*'' forPT and ``&%s::%s'' for address) (anachronism)",
1098: m->n_table->t_name->string,
1099: m->n_table->t_name->string,
1100: m->string
1101: );
1102: }
1103:
1104: if (q || f->f_virtual==0) {
1105: // & x.f => & f
1106: DEL(e2);
1107: e2 = m;
1108: }
1109: }
1110: break;
1111:
1112: }
1113: case MEMPTR:
1114: // &(p->*q)
1115: error("& .* E");
1116: }
1117:
1118: return this;
1119:
1120: case UMINUS:
1121: t->numeric(UMINUS);
1122: tp = t;
1123: return this;
1124:
1125: case UPLUS:
1126: t->num_ptr(UPLUS);
1127: tp = t;
1128: base = PLUS;
1129: e1 = zero;
1130: return this;
1131:
1132: case NOT:
1133: e2 = check_cond(e2,NOT,tbl);
1134: tp = int_type;
1135: return this;
1136:
1137: case COMPL:
1138: t->integral(COMPL);
1139: tp = t;
1140: return this;
1141:
1142: case INCR:
1143: case DECR:
1144: {
1145: Pexpr e = e1?e1:e2; // e1!=0 ==> e++ or e--
1146: // e1==0 ==> ++e or --e
1147:
1148: e->lval(b);
1149:
1150: switch(e->base) {
1151: case QUEST:
1152: e->tp=0;
1153: e->e1 = e1 ? new expr(base,e->e1,0) : new expr(base,0,e->e1);
1154: e->e2 = e1 ? new expr(base,e->e2,0) : new expr(base,0,e->e2);
1155: delete this;
1156: return e->typ(tbl);
1157: case CM:
1158: case G_CM:
1159: e->tp=0;
1160: e->e2 = e1 ? new expr(base,e->e2,0) : new expr(base,0,e->e2);
1161: delete this;
1162: return e->typ(tbl);
1163: case INCR:
1164: case DECR:
1165: if(e->e1)
1166: break;
1167: nin++;
1168: if(e->e2->not_simple())
1169: error('s',"overly complex %k of %k",b,e->base);
1170: nin--;
1171: e = new expr(G_CM,e,e->e2->typ(tbl));
1172: if (e1) e1=e; else e2=e;
1173: // e1?e1:e2 = e;
1174: return typ(tbl);
1175: case ASSIGN:
1176: case ASPLUS:
1177: case ASMINUS:
1178: case ASMUL:
1179: case ASDIV:
1180: case ASMOD:
1181: case ASAND:
1182: case ASOR:
1183: case ASER:
1184: case ASLS:
1185: case ASRS:
1186: nin++;
1187: if(e->e1->not_simple())
1188: error('s',"overly complex %k of %k",b,e->base);
1189: nin--;
1190: e = new expr(G_CM,e,e->e1->typ(tbl));
1191: if (e1) e1=e; else e2=e;
1192: // e1?e1:e2 = e;
1193: return typ(tbl);
1194: }
1195: }
1196:
1197: r1 = t->num_ptr(b);
1198: if (r1='P' && t->check(Pvoid_type,0)==0) error("%k of void*",b);
1199: tp = t;
1200: return this;
1201:
1202: }
1203:
1204: if (e1==dummy || e2==dummy || e1==0 || e2==0) error("operand missing for%k",b);
1205: switch (b) {
1206: case MUL:
1207: case DIV:
1208: r1 = t1->numeric(b);
1209: r2 = t2->numeric(b);
1210: nppromote(b);
1211: break;
1212:
1213: case PLUS:
1214: r2 = t2->num_ptr(PLUS);
1215: r1 = t1->num_ptr(PLUS);
1216: if (r1=='P' && r2=='P') error("P +P");
1217: nppromote(PLUS);
1218: // tp = t;
1219: // break;
1220: goto void_check;
1221:
1222: case MINUS:
1223: r2 = t2->num_ptr(MINUS);
1224: r1 = t1->num_ptr(MINUS);
1225: if (r2=='P' && r1!='P' && r1!='A') error("P - nonP");
1226: nppromote(MINUS);
1227: void_check:
1228: if ((r1='P' && t1->check(Pvoid_type,0)==0)
1229: || (r2='P' && t2->check(Pvoid_type,0)==0))
1230: error("%k of void*",b);
1231: tp = t;
1232: break;
1233:
1234: case LS:
1235: case RS:
1236: case AND:
1237: case OR:
1238: case ER:
1239: switch (e1->base) {
1240: case LT:
1241: case LE:
1242: case GT:
1243: case GE:
1244: case EQ:
1245: case NE:
1246: error('w',"%kE as operand for%k",e1->base,b);
1247: }
1248: switch (e2->base) {
1249: case LT:
1250: case LE:
1251: case GT:
1252: case GE:
1253: case EQ:
1254: case NE:
1255: error('w',"%kE as operand for%k",e2->base,b);
1256: }
1257: case MOD:
1258: r1 = t1->integral(b);
1259: r2 = t2->integral(b);
1260: nppromote(b);
1261: break;
1262:
1263: case LT:
1264: case LE:
1265: case GT:
1266: case GE:
1267: case EQ:
1268: case NE:
1269: r1 = t1->num_ptr(b);
1270: r2 = t2->num_ptr(b);
1271: if (r1=='P' && r2=='I') { // allow things like:
1272: // if (p==2-2)
1273: // YUCK!
1274: Neval = 0;
1275: long i = e2->eval();
1276: if (Neval==0 && i==0) {
1277: DEL(e2);
1278: e2 = zero;
1279: r2 = 'Z';
1280: }
1281: }
1282: else if (r2=='P' && r1=='I') {
1283: Neval = 0;
1284: long i = e1->eval();
1285: if (Neval==0 && i==0) {
1286: DEL(e1);
1287: e1 = zero;
1288: r1 = 'Z';
1289: }
1290: }
1291:
1292: if (b!=EQ && b!=NE) {
1293: if (r1=='P' && r2=='Z') error("P%k 0",b);
1294: if (r2=='P' && r1=='Z') error("P%k 0",b);
1295: }
1296:
1297: // make sure functions are properly converted to pointers to
1298: // functions and make sure overloaded functions are rejected
1299: Pexpr ptof(Pfct ef, Pexpr e, Ptable tbl);
1300: if (r1 == FCT) e1 = ptof(0,e1,tbl);
1301: if (r2 == FCT) e2 = ptof(0,e2,tbl);
1302:
1303: npcheck(b);
1304:
1305: if (r1=='P') { // need cast for pointers to virtual and second bases
1306: Pptr p1 = t1->is_ptr();
1307: Pptr p2 = t2->is_ptr();
1308: Pname cn = p1?p1->typ->is_cl_obj():0;
1309: Pname cn2 = p2?p2->typ->is_cl_obj():0;
1310:
1311: if (cn && cn2) {
1312: Pclass cl = Pclass(cn->tp);
1313: Pclass cl2 = Pclass(cn2->tp);
1314:
1315: if (cl->has_base(cl2)) {
1316: e1 = cast_cptr(cl2,e1,tbl,0);
1317: e1 = new cast(p2,e1);
1318: }
1319: else if (cl2->has_base(cl)) {
1320: e2 = cast_cptr(cl,e2,tbl,0);
1321: e2 = new cast(p1,e2);
1322: }
1323: }
1324: }
1325:
1326: if (r1=='P' && t1->memptr()) {
1327: mpmp:
1328: if (r2=='Z') {
1329: e2 = zero;
1330: e1 = new mdot("i",e1);
1331: e1->i1 = 9;
1332: }
1333: else if (r2=='P' && t2->memptr()) {
1334: // ERROR: no check for sideeffects
1335: Pexpr i1 = new mdot("i",e1);
1336: Pexpr i2;
1337: i1->i1 = 9;
1338:
1339: i2 = e2;
1340: while ( i2->base == CAST )
1341: i2 = i2->e1;
1342: if ( i2->base == ILIST )
1343: e2 = i2;
1344:
1345: if (e2->base==ILIST)
1346: i2 = e2->e1->e2;
1347: else {
1348: i2 = new mdot("i",e2);
1349: i2->i1 = 9;
1350: }
1351:
1352: Pexpr f1 = new mdot("f",e1);
1353: Pexpr f2;
1354: f1->i1 = 9;
1355: if (e2->base == ILIST)
1356: // f2 = new cast(Pfct_type,e2->e2);
1357: f2 = e2->e2;
1358: else {
1359: f2 = new mdot("f",e2);
1360: f2->i1 = 9;
1361: }
1362:
1363: Pexpr ei = new expr(base,i1,i2);
1364: Pexpr fi = new expr(base,f1,f2);
1365:
1366: base = ANDAND;
1367: e1 = ei;
1368: e2 = fi;
1369: } else if (r2=='P') {
1370: error('s',"%t %k %t",t1,base,t2);
1371: }
1372: }
1373: else if (r2=='P' && t2->memptr()) {
1374: Pexpr ee = e1; // swap
1375: e1 = e2;
1376: e2 = ee;
1377: int rr = r1;
1378: r1 = r2;
1379: r2 = rr;
1380: Ptype tt = t1;
1381: t1 = t2;
1382: t2 = tt;
1383: goto mpmp;
1384: }
1385: t = int_type;
1386: break;
1387:
1388: case ANDAND:
1389: case OROR:
1390: e1 = check_cond(e1,b,tbl);
1391: e2 = check_cond(e2,b,tbl);
1392: t = int_type;
1393: break;
1394:
1395: case QUEST:
1396: {
1397: Pname c1, c2;
1398: cond = check_cond(cond,b,tbl);
1399: //error('d',"cond %k %t",cond->base,cond->tp);
1400: //error('d',"t1 %t t2 %t",t1,t2);
1401:
1402: // still doesn't do complete checking for possible conversions...
1403:
1404: bit MPTR = 0; // local hack
1405:
1406: extern int suppress_error; // global hack
1407: suppress_error++;
1408: r1 = t1->num_ptr(b);
1409: r2 = t2->num_ptr(b);
1410: suppress_error--;
1411: if (r1=='P' && r2=='P' && t1->memptr() && t2->memptr()) {
1412:
1413: ++MPTR; // prevent later sorry
1414:
1415: // watch for casts
1416: Pexpr tt = e1;
1417: while ( tt->base == CAST ) tt = tt->e1;
1418: if ( tt->base == ILIST ) e1 = tt;
1419:
1420: tt = e2;
1421: while ( tt->base == CAST ) tt = tt->e1;
1422: if ( tt->base == ILIST ) e2 = tt;
1423:
1424: // cannot have sides return (expr?{}:{})
1425: // reuse same temp for both sides ?:
1426: Pname temp = make_tmp( 'A', mptr_type, tbl );
1427:
1428: e1 = mptr_assign( temp, e1 );
1429: e1 = new expr( G_CM, e1, temp );
1430: e1->tp = temp->tp;
1431:
1432: e2 = mptr_assign( temp, e2 );
1433: e2 = new expr( G_CM, e2, temp );
1434: e2->tp = temp->tp;
1435: }
1436:
1437: if (t1==t2
1438: || ( (c1=t1->is_cl_obj())
1439: && (c2=t2->is_cl_obj())
1440: && (c1->tp==c2->tp)
1441: ))
1442: t = t1;
1443: else {
1444: r1 = t1->num_ptr(b);
1445: r2 = t2->num_ptr(b);
1446:
1447: if (r1=='P' && r2=='P') {
1448: Pptr p1 = t1->is_ptr();
1449: Pptr p2 = t2->is_ptr();
1450: //error('d',"p1 %t p2 %t",p1,p2);
1451: if ((c1 = p1->typ->is_cl_obj())
1452: && (c2 = p2->typ->is_cl_obj())) {
1453: Pclass cl1 = Pclass(c1->tp);
1454: Pclass cl2 = Pclass(c2->tp);
1455: if (cl1==cl2 || cl2->has_base(cl1)) {
1456: t = t1;
1457: goto caca;
1458: }
1459: else if (cl1->has_base(cl2)) {
1460: t = t2;
1461: goto caca;
1462: }
1463: }
1464: }
1465:
1466: if (r1==FCT && r2==FCT) { // fudge
1467: if (t1->check(t2,ASSIGN))
1468: error("badTs in ?:E: %t and %t",t1,t2);
1469: else if (Pfct(t1)->memof) error('s',"conditionalE with%t",t1);
1470: t = t1;
1471: }
1472: else
1473: nppromote(b);
1474: caca:
1475: //error('d',"?: t %t t1 %t t2 %t",t,t1,t2);
1476: if (t!=t1 && t->check(t1,0)) {
1477: PERM(t);
1478: e1 = new cast(t,e1);
1479: }
1480:
1481: if (t!=t2 && t->check(t2,0)) {
1482: PERM(t);
1483: e2 = new cast(t,e2);
1484: }
1485:
1486: Pptr pt = t->is_ptr();
1487: //if (pt && pt->base==PTR && pt->memof) error('s',"conditionalE with%t",t);
1488: if (pt && pt->base==PTR && pt->memof && MPTR == 0) error('s',"conditionalE with%t",t);
1489: }
1490: }
1491: break;
1492:
1493: case ASPLUS:
1494: r1 = t1->num_ptr(ASPLUS);
1495: r2 = t2->num_ptr(ASPLUS);
1496: if (r1=='P' && r2=='P') error("P +=P");
1497: nppromote(ASPLUS);
1498: goto ass;
1499:
1500: case ASMINUS:
1501: r1 = t1->num_ptr(ASMINUS);
1502: r2 = t2->num_ptr(ASMINUS);
1503: if (r2=='P' && r1!='P' && r1!='A') error("P -= nonP");
1504: nppromote(ASMINUS);
1505: goto ass;
1506:
1507: case ASMUL:
1508: case ASDIV:
1509: r1 = t1->numeric(b);
1510: r2 = t1->numeric(b);
1511: nppromote(b);
1512: goto ass;
1513:
1514: case ASMOD:
1515: r1 = t1->integral(ASMOD);
1516: r2 = t2->integral(ASMOD);
1517: nppromote(ASMOD);
1518: goto ass;
1519:
1520: case ASAND:
1521: case ASOR:
1522: case ASER:
1523: case ASLS:
1524: case ASRS:
1525: r1 = t1->integral(b);
1526: r2 = t2->integral(b);
1527: npcheck(b);
1528: t = int_type;
1529: goto ass;
1530: ass:
1531: if (r1='P' && t1->check(Pvoid_type,0)==0) error("%k of void*",b);
1532: tp = t;
1533: as_type = t; /* the type of the rhs */
1534: t2 = t;
1535:
1536: case ASSIGN:
1537: //error('d',"assign %k: %t %t %s",b,t1,t2,ignore_const?"ignore const":"");
1538: //error('d'," e1 %d %k e1 %d %k",e1,e1->base,e2,e2->base);
1539: if (ignore_const) { // handle static initializers
1540: // represented as assignments
1541: // ignore consts.
1542: tp = e1->tp;
1543: return this;
1544: }
1545:
1546: switch (e1->base) {
1547: case G_CM:
1548: case CM: // (a,b)=c => *(a,&b)=c
1549: {
1550: e1->e2 = new expr(G_ADDROF,0,e1->e2);
1551: e1->tp = 0;
1552: e1 = new expr(DEREF,e1,0);
1553: return typ(tbl);
1554: }
1555: case QUEST: // (a?b:c)=d => *(a?&b:&c)=c
1556: {
1557: e1->e1 = new expr(G_ADDROF,0,e1->e1);
1558: e1->e2 = new expr(G_ADDROF,0,e1->e2);
1559: e1->tp = 0;
1560: e1 = new expr(DEREF,e1,0);
1561: return typ(tbl);
1562: }
1563: case ASSIGN: // (a*=b)=c => a*=b,a=c
1564: case ASPLUS:
1565: case ASMINUS:
1566: case ASMUL:
1567: case ASDIV:
1568: case ASMOD:
1569: case ASAND:
1570: case ASOR:
1571: case ASER:
1572: case ASLS:
1573: case ASRS:
1574: {
1575: base = G_CM;
1576: nin++;
1577: if (e1->e1->not_simple()) error('s',"lvalue %k too complicated",b);
1578: nin--;
1579: Pexpr aa = new expr(e1->base,e1->e1,e1->e2);
1580: Pexpr bb = new expr(b,e1->e1,e2);
1581: e1 = aa;
1582: e2 = bb;
1583: return typ(tbl);
1584: }
1585: case INCR:
1586: case DECR: // ++a=b => ++a,a=b
1587: {
1588: if(!e1->e2) break ;
1589: base = G_CM;
1590: nin++;
1591: if (e1->e2->not_simple()) error('s',"lvalue %k too complicated",b);
1592: nin--;
1593: Pexpr aa = new expr(e1->base,0,e1->e2);
1594: Pexpr bb = new expr(b,e1->e2,e2);
1595: e1 = aa;
1596: e2 = bb;
1597: return typ(tbl);
1598: }
1599: case REF:
1600: {
1601: Pexpr r = e1;
1602: // hack to prevent
1603: // f().i = j
1604: // transformed into
1605: // ((t=f()),&t)->i = j
1606: if (r->e1->base==G_CM
1607: && r->e1->e2->base==G_ADDROF
1608: && r->e1->e2->e2->base==NAME) {
1609: char* s = r->e1->e2->e2->string;
1610: if (s[0]=='_' && s[1]=='_')
1611: error("left hand side not lvalue");
1612: }
1613: }
1614: }
1615:
1616: if (e1->lval(b) == 0) {
1617: tp = any_type;
1618: return this;
1619: }
1620: lkj:
1621: switch (t1->base) {
1622: case TYPE:
1623: t1 = Pbase(t1)->b_name->tp;
1624: goto lkj;
1625: case INT:
1626: case CHAR:
1627: case SHORT:
1628: // if (e2->base==ICON && e2->tp==long_type)
1629: // error('w',"long constant assigned to%k",t1->base);
1630: { Ptype t = e2->tp;
1631: csi:
1632: switch (t->base) {
1633: case TYPE:
1634: t = Pbase(t)->b_name->tp; goto csi;
1635: case LONG:
1636: case FLOAT:
1637: case DOUBLE:
1638: case LDOUBLE:
1639: error('w',"%t assigned to %t",e2->tp,t1);
1640: }
1641: }
1642: // no break
1643: case LONG:
1644: if (b==ASSIGN
1645: && Pbase(t1)->b_unsigned
1646: && e2->base==UMINUS
1647: && e2->e2->base==ICON)
1648: error('w',"negative assigned to unsigned");
1649: break;
1650: case PTR:
1651: if (b == ASSIGN) {
1652: //error('d',"ptr t1 %t %d %t",t1,t1->memptr(),t2);
1653: //?? if (t1->memptr() && t2->base!=OVERLOAD) break;
1654: e2 = ptr_init(Pptr(t1),e2,tbl);
1655: t2 = e2->tp;
1656: //error('d',"pchecked %d",Pchecked);
1657: if (Pchecked) {
1658: tp = e1->tp;
1659: return this;
1660: }
1661: }
1662: break;
1663: case COBJ:
1664: { Pname c1 = t1->is_cl_obj();
1665: // test of c1->tp necessary for ``fake classes''
1666: // _Sdd generated for vector assignemnts
1667: if (c1
1668: && c1->tp
1669: /* && Pclass(c1->tp)->memtbl->look("__as",0)==0*/) {
1670: //&& Pclass(c1->tp)->has_oper(ASSIGN)==0) {
1671: Pname c2 = t2->is_cl_obj();
1672: // error('d', "expr::typ: c1: %n c2: %n", c1, c2 );
1673: if (c1 != c2) {
1674: /*
1675: consider:
1676:
1677: struct A { A(B&); };
1678: struct B : A {};
1679:
1680: A aa;
1681: B bb;
1682:
1683: aa = bb; // aa.operator=(A(bb));
1684: // optimize to aa.A(bb) when possible
1685: // avoid temporary where aa = *(A*)&bb is legal
1686: */
1687: // error('d',"expr::typ c1 %n %d c2 %n %d",c1,c1?c1->tp:0,c2,c2?c2->tp:0);
1688: if (c2
1689: && c2->tp
1690: && can_coerce(t1,t2)==0
1691: //&& Pclass(c2->tp)->has_base(Pclass(c1->tp))
1692: //&& (1<is_unique_base(Pclass(c2->tp),c1->string,0))
1693: && (vcllist->clear(),vcllist=0,1<is_unique_base(Pclass(c2->tp),c1->string,0))
1694: && Pclass(c1->tp)->c_xref&(C_VBASE|C_VPTR|C_ASS)) {
1695: // error('d',"aaa");
1696: if (make_assignment(c1)) return try_to_overload(tbl);
1697: }
1698: // optimize
1699: else {
1700: e2 = new expr(ELIST,e2,0);
1701: e2 = new texpr(VALUE,t1,e2);
1702: if (Pclass(c1->tp)->has_dtor()==0 &&
1703: Pclass(c1->tp)->has_oper(ASSIGN)==0) {
1704: // optimize
1705: // error('d',"bbb");
1706: e2->e2 = e1;
1707: e2 = e2->typ(tbl);
1708: if (e2->base==DEREF && e2->e1->base==G_CALL ||
1709: e2->base==ASSIGN && e2->e1==e1) {
1710: // error('d',"ccc");
1711: *this = *e2;
1712: }
1713: tp = t1;
1714: return this;
1715: }
1716: return typ(tbl);
1717: }
1718: }
1719: // test of c1->tp necessary for ``fake classes''
1720: // _Sdd generated for vector assignemnts
1721: else if (c1->tp && Pclass(c1->tp)->c_xref&(C_VBASE|C_VPTR|C_ASS)) {
1722: if (make_assignment(c1)) return try_to_overload(tbl);
1723: }
1724: }
1725: (void) t1->tsizeof();
1726: break;
1727: }
1728: }
1729:
1730: //error('d',"check(%t,%t) -> %d",e1->tp,t2,try_to_coerce(t1,e2,"assignment",tbl));
1731: { Pexpr x = try_to_coerce(t1,e2,"assignment",tbl);
1732: if (x)
1733: e2 = x;
1734: else if (e1->tp->check(t2,ASSIGN))
1735: error("bad assignmentT:%t =%t",e1->tp,t2);
1736: else if ((t1 = t1->is_ptr()) && t1->memptr()) {
1737: if (t2 == zero_type) {
1738: Pexpr ee = new expr(ELIST,zero,zero);
1739: e2 = new expr(ILIST,ee,zero);
1740: }
1741: else if (t2->base==PTR && t2->memptr()) {
1742: // do nothing: structure assignment
1743: }
1744: else {
1745: Pexpr x = ptr_init(Pptr(t1),e2,tbl);
1746: if (x != e2) e2 = x;
1747: }
1748: }
1749: }
1750: t = e1->tp; // the type of the lhs
1751: break;
1752: case CM:
1753: case G_CM:
1754: t = t2;
1755: break;
1756: default:
1757: error('i',"unknown operator%k",b);
1758: }
1759:
1760: tp = t;
1761: return this;
1762: }
1763:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.