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