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