|
|
1.1 root 1: /*ident "@(#)ctrans:src/find.c 1.1.5.23" */
2: /******************************************************************
3:
4: C++ source for cfront, the C++ compiler front-end
5: written in the computer science research center of Bell Labs
6:
7: Copyright (c) 1986 AT&T, Inc. All rigths Reserved
8: THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.
9:
10: find.c:
11:
12: name lookup and visibility checks
13:
14: *******************************************************************/
15:
16: #include "cfront.h"
17:
18: Pname undef(Pname n, Ptable tbl, TOK f)
19: {
20: switch (f) {
21: case 0: error("%nU",n); break;
22: case CALL: error("UF%n called",n); break;
23: case REF:
24: case DOT: error("M%nU",n); break;
25: case ADDROF: error("address ofU%n",n); break;
26: }
27:
28: if (tbl == gtbl) {
29: Pname nn = tbl->insert(n,0);
30: if (f == CALL) {
31: nn->tp = new fct(defa_type,0,0);
32: nn->n_sto = nn->n_scope = EXTERN;
33: }
34: else
35: nn->tp = any_type;
36: delete n;
37: return nn;
38: }
39:
40: n->tp = any_type;
41: return n;
42: }
43:
44:
45:
46: // static int ref_seen;
47: static int mptr; // &C::m
48: //static int mqua; // C::m
49: Pname me; // name of fct requesting access to name using find_name()
50: Pfct mef; // fct requesting access to name using find_name()
51: Pclass tcl; // class of original ``this''
52: int mex;
53: Pclass mec; // class requesting access to name using find_name()
54: // int no_ambig; // suppress ambiguity checking after virtual seen
55:
56: Ptable lcl_tbl = 0; // handle local function reference of local const for dimen size
57:
58:
59: Pexpr find_name(Pname n, Pclass cl, Ptable tbl, int f, Pname m)
60: /*
61: in function ``m'' find the true name for "n",
62: implicitly define if undefined
63:
64: f==CALL: n() cl == cc->cot
65: f==REF: p->n cl == class of *p
66: f==DOT: obj.n cl == class of obj
67: f==ADDROF: &n cl == cc->cot
68: f==0 n (none of the above)
69:
70: "tbl" defines local scope (block or global)
71:
72: */
73: {
74: Pname q = n->n_qualifier;
75: char* s = n->string;
76: Pexpr ee;
77: //error('d',"find_name %s cl %t f %d m %n",s,cl,f,m);
78:
79: tcl = cl;
80: // no_ambig = 0;
81:
82: if (n) {
83: mex = 1;
84: if (me = m) {
85: mef = Pfct(me->tp);
86: if (mef->base!=FCT)
87: error('i',"mef %d %k",mef,mef->base);
88: mec = mef->memof;
89: }
90: else {
91: mef = 0;
92: mec = cl;
93: }
94: }
95: else
96: mex = 0;
97:
98: if (n->base == MDOT) error('i',"find (mdot %n)",n);
99:
100: if (n->n_table) return n;
101:
102: // ref_seen = f;
103: //error('d',"q %n %t f %k",q,q?q->tp:0,f);
104: if (q) { // qualified name: q::s
105:
106: if (q == sta_name) { // explicitly global: ::s
107: Pname nn = gtbl->look(s,0);
108: if (nn == 0) return undef(n,gtbl,f);
109: nn->use();
110: delete n;
111: return nn;
112: }
113:
114: Pclass qcl =0 ;
115:
116: if (q->tp->base == COBJ)
117: qcl = Pclass(Pbase(q->tp)->b_name->tp);
118: else if ((q->n_template_arg) &&
119: (Pbase(q->tp)->b_name->tp) &&
120: (Pbase(q->tp)->b_name->tp->base == COBJ))
121: // get past the TYPE to the COBJ node
122: qcl = Pclass(Pbase(Pbase(q->tp)->b_name->tp)->b_name->tp);
123: else {
124: //error('d',"Qr%nnot aCN",q);
125: return undef(n,gtbl,f);
126: }
127:
128:
129: Pclass bcl = cl;
130:
131: if (cl==0 || f==ADDROF)
132: bcl = cl = qcl; // Pclass(Pbase(q->tp)->b_name->tp);
133: else {
134: // if (strcmp(q->string,cl->string)) { // really a base?
135: // bcl = cl->is_base(q->string);
136: if (strcmp(qcl->string,cl->string)) { // really a base?
137: bcl = cl->is_base(qcl->string);
138: if (bcl == 0) {
139: if (f==REF || f==DOT) {
140: error("%s is not aBC of %t",q->string,cl);
141: return undef(n,cl->memtbl,7);
142: }
143: goto sss;
144: }
145: // else try in base or for static
146: }
147: }
148:
149: if (f == ADDROF) mptr = 1; // &C::m
150: // mqua = 1;
151: ee = cl->find_name(s,bcl==cl?0:bcl); // really a member?
152: mptr = 0;
153: // mqua = 0;
154:
155: if (ee == 0) {
156: sss:
157: //error('d',"sss %k",f);
158: if (f!=REF && f!=DOT) {
159: // try for static member of other class:
160: // Sam: qcl ash been computed correctly above
161: // Pclass qcl = Pclass(Pbase(q->tp)->b_name->tp);
162: mptr = 1;
163: ee = qcl->find_name(s,qcl);
164: mptr = 0;
165: if (ee && ee->base==NAME) {
166: // switch (ee->tp->base) {
167: // case FCT:
168: // case OVERLOAD:
169: // break;
170: // default:
171: delete n;
172: return ee;
173: // }
174: }
175: }
176: error("QdN%n::%n not found in %t",q,n,cl);
177: return undef(n,bcl?bcl->memtbl:cl->memtbl,7);
178: }
179:
180: if (ee->base==REF && ee->e1==0) { // &C::f, no ``this''
181: //error('d',"ee %k %d f %k",ee->base,ee->e1,f);
182: switch (f) {
183: case 0:
184: case CALL: //SSS
185: { Pexpr mm = ee->mem;
186: while (mm->base==REF || mm->base==MDOT) mm = mm->mem;
187: if (mm->base==NAME)
188: switch (mm->tp->base) {
189: case FCT:
190: case OVERLOAD:
191: goto addrof;
192: default:
193: if (Pname(mm)->n_stclass == STATIC) goto addrof;
194: }
195: }
196: error("O orOP missing forM%n",n);
197:
198: case ADDROF:
199: addrof:
200: Pexpr x = ee;
201: ee = ee->mem;
202: delete x;
203: case REF:
204: case DOT:
205: break;
206: default:
207: error("QdN%n::%n used in nonC context",q,n);
208: }
209: }
210:
211: delete n;
212: return ee;
213: }
214:
215: if (f!=DOT && f!=REF) { // not .s or ->s: look for local, global, and member
216:
217: Pname nn = tbl->look(s,0);
218: // error('d',"nn %n f %k",nn,f);
219:
220: if (nn) { // local, global, or member
221: if (nn->n_table->t_name) { // global or member
222: if (cl) { // might be member
223: if (ee = cl->find_name(s,0)) {
224: if (ee->base==REF && ee->e1==0) {
225: Pexpr mm = ee->mem;
226: while (mm->base==REF || mm->base==MDOT) mm = mm->mem;
227: if (mm->base==NAME)
228: switch (mm->tp->base) {
229: default:
230: if (Pname(mm)->n_stclass != STATIC)
231: break;
232: case FCT:
233: case OVERLOAD:
234: delete n;
235: return mm;
236:
237: }
238: error("O orOP missing for%n",Pref(ee)->mem);
239: }
240: delete n;
241: return ee;
242: }
243: }
244: } // else local
245:
246: nn->use();
247: delete n;
248: return nn;
249: }
250:
251: if (cl) {
252: if (ee = cl->find_name(s,0)) {
253: if (ee->base==REF && ee->e1==0) {
254: Pexpr mm = ee->mem;
255: while (mm->base==REF || mm->base==MDOT) mm = mm->mem;
256: if (mm->base==NAME)
257: switch (mm->tp->base) {
258: default:
259: if (Pname(mm)->n_stclass != STATIC)
260: break;
261: case FCT:
262: case OVERLOAD:
263: delete n;
264: return mm;
265:
266: }
267: error("O orOP missing for%n",Pref(ee)->mem);
268: }
269: delete n;
270: return ee;
271: }
272: }
273:
274: if ( lcl_tbl && (nn=lcl_tbl->look(s,0)) ) {
275: nn->use();
276: delete n;
277: return nn;
278: }
279:
280: if (nn = gtbl->look(s,0)) { // global
281: nn->use();
282: delete n;
283: return nn;
284: }
285:
286: return undef(n,gtbl,f);
287: }
288:
289: if (ee = cl->find_name(s,cl)) { // .s or ->s
290: delete n;
291: return ee;
292: }
293:
294: return undef(n,gtbl,f);
295: }
296:
297: int classdef::check_dup(Pclass cl, TOK bb)
298: /*
299: see if cl is a base of this; return 0 if no clash
300: */
301: {
302: for (Pbcl b = baselist; b; b=b->next) {
303: if (cl == b->bclass) {
304: if (bb!=VIRTUAL) {
305: if (b->base==VIRTUAL)
306: error("%t inaccessible because of virtual %t in %t",cl,cl,this);
307: else
308: error("%t inaccessible because of %t in %t",cl,cl,this);
309: return 1;
310: }
311: else if (b->base!=VIRTUAL) {
312: error("virtual %t inaccessible because of %t in %t",cl,cl,this);
313: return 1;
314: }
315: }
316: if (b->bclass->check_dup(cl,bb)) return 1;
317: }
318: return 0;
319: }
320:
321:
322: int Nvis;
323: TOK Nvirt;
324: TOK ppbase;
325:
326: Pclass classdef::is_base(char* s)
327: /*
328: is "s" a public base class of this?
329: */
330: {
331: //error('d',"%s->is_base(%s) %k",string,s,ppbase);
332: TOK pp = ppbase;
333: for (Pbcl b = baselist; b; b=b->next) {
334: /*
335: if (b->ppp!=PUBLIC
336: && cc->cot!=this
337: && (cc->nof==0 || this->has_friend(Pfct(cc->nof->tp))==0))
338: ppbase = b->ppp<pp?pp:b->ppp; // PUBLIC<PROTECTED<PRIVATE
339: */
340: if (strcmp(s,b->bclass->string) == 0) {
341: if (b->ppp!=PUBLIC
342: && cc->cot!=this
343: && (cc->nof==0 || this->has_friend(Pfct(cc->nof->tp))==0))
344: ppbase = b->ppp<pp?pp:b->ppp; // PUBLIC<PROTECTED<PRIVATE
345: Nvirt = b->base;
346: return b->bclass;
347: }
348: else {
349: Pclass bc = b->bclass->is_base(s);
350: if (bc) {
351: if (b->ppp!=PUBLIC
352: && cc->cot!=this
353: && (cc->nof==0 || this->has_friend(Pfct(cc->nof->tp))==0))
354: ppbase = b->ppp<pp?pp:b->ppp; // PUBLIC<PROTECTED<PRIVATE
355: return bc;
356: }
357: }
358: }
359: ppbase = pp;
360: return 0;
361: }
362:
363: bit classdef::has_base(Pclass cl)
364: /*
365: is "cl" a base of this?
366: */
367: {
368: if (this == 0) return 0;
369: for (Pbcl b = baselist; b; b=b->next) {
370: if (b->bclass==cl) {
371: if (b->ppp!=PUBLIC
372: && cc->cot!=this
373: && (cc->nof==0 || this->has_friend(Pfct(cc->nof->tp))==0))
374: Nvis = 1; // no standard coercion
375: Nvirt = b->base;
376: return 1;
377: }
378: if (b->bclass->has_base(cl)) return 1;
379: }
380: return 0;
381: }
382:
383: int Noffset;
384: Pexpr Nptr;
385: clist* vcllist;
386:
387: int clist::onlist(Pclass c)
388: {
389: for (clist* p = this; p; p = p->next)
390: if (p->cl == c) return 1;
391: return 0;
392: }
393:
394: void clist::clear()
395: {
396: if (this == 0) return;
397: clist* p = next;
398: while (p) {
399: clist* q = p->next;
400: delete p;
401: p = q;
402: };
403: delete this;
404: }
405:
406: int is_unique_base(Pclass cl, char* s, int offset, int in_base)
407:
408: // is "s" a unique base class of this?
409:
410: {
411: int i = 0;
412: //error('d',"is_unique_base(%t,%s,%d,%d)",cl,s,offset,in_base);
413: for (Pbcl b = cl->baselist; b; b=b->next) {
414: int no = 0;
415: if (b->base!=VIRTUAL)
416: no = offset + b->obj_offset;
417: else if (in_base)
418: continue;
419: if (strcmp(s,b->bclass->string) == 0) {
420: Noffset = no;
421: i++;
422: if (b->ppp!=PUBLIC
423: && cc->cot!=cl
424: && (cc->nof==0 || cl->has_friend(Pfct(cc->nof->tp))==0))
425: Nvis = 1; // no standard coercion
426: if (b->base==VIRTUAL)
427: Nptr = new mdot(s,0);
428: }
429: else {
430: if (b->base==VIRTUAL) {
431: if (vcllist->onlist(b->bclass) )continue;
432: vcllist = new clist(b->bclass,vcllist);
433: }
434: int ii = is_unique_base(b->bclass,s,no,1);
435: //error('d',"base %t i %d ii %d",b->bclass,i,ii);
436: i += ii;
437: if (ii==1 && b->base==VIRTUAL)
438: Nptr = new mdot(b->bclass->string,0);
439: }
440: }
441:
442: return i;
443: }
444:
445: /*
446: int classdef::has_allocated_base(Pclass bcl)
447:
448: search the list of !first base classes for this virtual base
449: space will have been allocated in !first bases for virtual bases
450: declared in !first classes
451:
452: in addition bcl may bave been specified explicitly as a base
453:
454: {
455: int off;
456: for (Pbcl l = baselist; l; l=l->next) {
457: if (l->base == VIRTUAL) continue; // another non-allocated virtual base
458: if (l==baselist) continue; // first base
459:
460: Pclass bc = l->bclass;
461: off = l->obj_offset;
462:
463: for (Pbcl ll = bc->baselist; ll; ll=ll->next) {
464: // cannot share non-virtual base
465: if (ll->base != VIRTUAL) continue;
466: if (ll->bclass==bcl) return off + ll->obj_offset;
467: }
468: }
469: return 0;
470: }
471: */
472:
473: int classdef::has_allocated_base(Pclass bcl)
474: /*
475: search the list of base classes for this virtual base
476: space will be allocated in first virtual version found.
477: return offset.
478:
479: A virtual base cannot have offset 0 (its pointer at least is ahead)
480: */
481: {
482: //error('d',"%t->has_allocated_base(%t) ",this,bcl);
483: for (Pbcl l = baselist; l; l=l->next) {
484: //error('d',"l %k %t %d",l->base,l->bclass,l->obj_offset);
485: if (l->base==VIRTUAL
486: && l->bclass==bcl
487: && l->obj_offset)
488: return l->obj_offset;
489:
490: if (l->base==VIRTUAL || l!=baselist) {
491: // allocated as an object,
492: // not unravelled as a set of members
493: int i = l->bclass->has_allocated_base(bcl);
494: //error('d',"i %d",i);
495: if (i) return l->obj_offset + i;
496: }
497: }
498: //error('d',"return 0");
499: return 0;
500: }
501:
502: /*
503: int allocated_base(Pclass cl,Pclass bcl)
504: {
505: static second;
506: int s2 = second;
507: //error('d',"allocated_base(%t,%t) %d",cl,bcl,second);
508: for (Pbcl l = cl->baselist; l; l=l->next) {
509: //error('d',"find %t: %k %t %d",bcl,l->base,l->bclass,l->obj_offset);
510: //error('d',"s %d first %d",second,l!=cl->baselist);
511: if (l->base==VIRTUAL
512: && l->bclass==bcl
513: && l->obj_offset
514: && (second || l!=cl->baselist)) return (second=s2,1);
515: int i = allocated_base(l->bclass,bcl);
516: //error('d',"i %d",i);
517: if (i) return (second=s2,1);
518: second = 1;
519: }
520: second = s2;
521: //error('d',"s2 %d",s2);
522: return 0;
523: }
524: */
525: Pname vfct(Pclass cl, char* s)
526: /*
527: Called for each name "s" in a vtbl for "cl"
528: Find the "s" to go in the vtbl.
529: The "s" that caused the vtbl entry to be created
530: is found if nothing else is
531: */
532: {
533: Pname n = cl->memtbl->look(s,0);
534: if (n) return n;
535:
536: for (Pbcl b = cl->baselist; b; b=b->next) {
537: Pname nn = vfct(b->bclass,s);
538: if (nn) {
539: //error('d',"nn %nn",nn);
540: if (n && n!=nn) {
541: Pclass ncl = Pclass(n->n_table->t_name->tp);
542: Pclass nncl = Pclass(nn->n_table->t_name->tp);
543: //error('d',"ncl %t nncl %t",ncl,nncl);
544: if (nncl->is_base(ncl->string))
545: n = nn; // use nn
546: }
547: else
548: n = nn;
549: }
550: }
551:
552: // if (n == 0) error('i',"vfct(%t,%s)",cl,s);
553:
554: return n;
555: }
556:
557: Pexpr rptr(Ptype t, Pexpr p, int offset)
558: /*
559: return rvalue of offset off pointer:
560: (t)((char*)p+offset)
561: */
562: {
563: Pexpr pp = p;
564: //error('d',"rptr %t %d",t,offset);
565: if (offset) {
566: Pexpr i = new ival(offset);
567: // pp = new texpr(CAST,Pchar_type,pp);
568: pp = new cast(Pchar_type,pp);
569: pp = new expr(PLUS,pp,i);
570: }
571: // pp = new texpr(CAST,t,pp);
572: // pp->tp = t;
573: pp = new cast(t,pp);
574: return pp;
575: }
576: /*
577: Pexpr lptr(Ptype t, Pexpr p, int offset)
578:
579: return lvalue of offset off pointer:
580: *(t*)((char*)p+offset)
581:
582: {
583: Pexpr pp = p;
584: if (offset) {
585: Pexpr i = new ival(offset);
586: // pp = new texpr(CAST,Pchar_type,pp);
587: pp = new cast(Pchar_type,pp);
588: pp = new expr(PLUS,pp,i);
589: }
590: // pp = new texpr(CAST,t->addrof(),pp);
591: pp = new cast(t->addrof(),pp);
592: pp = new expr(DEREF,pp,0);
593: pp->tp = t;
594: return pp;
595: }
596: */
597: int friend_check(Pclass start,Pclass stop, Pfct f)
598: /*
599: is `f' a friend of a class between `start' and `stop'
600: in a class DAG?
601: */
602: {
603: //error('d',"friend_check(%t,%t)",start,stop);
604:
605: if (start->has_friend(f)) return 1;
606: if (stop == start) return 0;
607: for (Pbcl b = start->baselist; b; b = b->next) {
608: if (b->bclass->has_friend(f)) return 1;
609: if (friend_check(b->bclass,stop,f)) return 1;
610: }
611: return 0;
612: }
613:
614: bit classdef::has_friend(Pfct f)
615: /*
616: does this class have function "f" as its friend?
617: */
618: {
619: //error('d',"%t->has_friend(%t) %d %d ",this,f,f,f->base);
620:
621: for (Plist l=friend_list; l; l=l->l) {
622: Pname fr = l->f;
623: Ptype frt = fr->tp;
624: //error('d',"frt %t %d %d",frt,frt,frt->base);
625: switch (frt->base) {
626: case FCT:
627: if (f == frt) return 1;
628: break;
629: case OVERLOAD:
630: l->f = fr = Pgen(frt)->fct_list->f; // first fct
631: if (fr->tp == f) return 1;
632: case CLASS:
633: break;
634: default:
635: error('i',"bad friend %k",fr->tp->base);
636: }
637: }
638: return 0;
639: }
640:
641: bit classdef::has_friend(Pclass cl)
642: /*
643: does this class have class "cl" as its friend?
644: */
645: {
646: for (Plist l=friend_list; l; l=l->l) {
647: Pname fr = l->f;
648: Ptype frt = fr->tp;
649: switch (frt->base) {
650: case CLASS:
651: if ((frt == cl) || cl->same_class(Pclass(frt)))
652: return 1;
653: case FCT:
654: case OVERLOAD:
655: break;
656: default:
657: {error('i',"bad friend %k",frt->base);}
658: }
659: }
660: return 0;
661: }
662:
663: Pname find_virtual(Pclass cl, Pname s)
664: /*
665: does ``cl'' have a virtual function ``s'' in some base class
666: */
667: {
668: for (Pbcl b = cl->baselist; b; b = b->next) {
669: Pclass bcl = b->bclass;
670: Pname n;
671: if (n = bcl->memtbl->look(s->string,0)) {
672: Pfct f = Pfct(n->tp);
673: if (f->base == OVERLOAD) {
674: for (Plist gl=Pgen(f)->fct_list; gl; gl=gl->l) {
675: n = gl->f;
676: // if (f != s->tp) continue;
677: // Replaced by:
678: if (n->tp->check(s->tp,VIRTUAL)) continue;
679: if (Pfct(n->tp)->f_virtual) return n;
680: }
681: }
682: // else if (f->f_virtual)
683: else if (f->f_virtual && n->tp->check(s->tp,VIRTUAL)==0)
684: return n;
685: }
686: else if (n = find_virtual(bcl,s))
687: return n;
688: }
689: return 0;
690: }
691:
692: Pexpr classdef::find_name(char* s, Pclass cl)
693: /*
694: look for "s" in "this" class and its base classes
695: if (cl)
696: accept only a member of "cl" or "cl"'s base classes
697: (that is cl::s was seen)
698:
699: complicated by hiding rules: private, protected, friend
700:
701: */
702: {
703: //error('d',"%s->find_name(%s,%s) memtbl %d",string,s,cl?cl->string:"",memtbl);
704: // int ambig_set = 0;
705:
706: Pname n = memtbl->look(s,0);
707:
708: if (n) {
709: //error('d',"n %n tp %t",n,n->tp);
710: if (n->tp) {
711: switch (n->tp->base) {
712: case OVERLOAD:
713: break;
714: case FCT:
715: if (Pfct(n->tp)->f_virtual==0) {
716: if (n->n_dcl_printed==0) n->dcl_print(0);
717: break;
718: }
719: default:
720: if (c_body==1 /*&& n->n_stclass!=ENUM*/) dcl_print(0);
721: }
722: }
723:
724: if (n->base == PUBLIC) {
725: if (mex && n->n_scope==0) {
726: if (this==mec
727: || (mec && has_friend(mec))
728: || (mef && has_friend(mef))
729: || (n->n_protect
730: && mec
731: && mec->has_base(this)
732: && tcl
733: && (tcl==mec || tcl->has_base(mec)))
734: || (n->n_protect
735: && mec
736: && tcl
737: && tcl->has_friend(mec))
738: || (n->n_protect
739: && mef
740: && tcl
741: && tcl->has_base(this)
742: // && tcl->has_friend(mef))
743: && friend_check(tcl,this,mef))
744:
745: // static member can be initializer with
746: // private member of its class
747: || ( Cdcl
748: && Cdcl->base == NAME
749: && Cdcl->n_stclass == STATIC
750: && Cdcl->n_initializer
751: && Cdcl->n_qualifier
752: && (Pclass(Pbase(Cdcl->n_qualifier->tp)->b_name->tp) == this
753: || (n->n_protect && Pclass(Pbase(Cdcl->n_qualifier->tp)->b_name->tp)->has_base(this))
754: || Pclass(Pbase(Cdcl->n_qualifier->tp)->b_name->tp)->has_friend(this)
755: )))
756: ;
757: else {
758: //error('d',"ee1");
759: error("%n cannot access%n: %sM",me,n,n->n_protect?"protected":"private");
760: mex = 0; // suppress further error messages
761: }
762: }
763: n = n->n_qualifier;
764: mex = 0;
765: }
766:
767: if (cl==0 || cl==this) {
768: if (mptr==0
769: && n->n_stclass!=STATIC
770: && n->n_stclass!=ENUM) {
771: Ptype t = n->tp;
772: //error('d',"cl %d this %d",cl,this);
773: //error('d',"%n: %k mef %t",n,n->n_protect,mef);
774: //error('d'," this %d %t",this,this);
775: //error('d'," mec %d %t",mec,mec);
776: //error('d'," tcl %d %t",tcl,tcl);
777: //error('d',"mec->has_base(this) %d",mec?mec->has_base(this):0);
778: //error('d',"tcl->has_base(mec) %d",tcl?tcl->has_base(mec):0);
779: //error('d',"tcl->has_base(this) %d",tcl?tcl->has_base(this):0);
780: //error('d',"tcl->has_friend(mef) %d",tcl?tcl->has_friend(mef):0);
781: if (mex && n->n_scope==0 && n->tp->base!=OVERLOAD) {
782: if (this==mec
783: || (mec && has_friend(mec))
784: || (mef && has_friend(mef))
785: || (n->n_protect
786: && mec
787: && mec->has_base(this)
788: && tcl
789: && (tcl==mec || tcl->has_base(mec)))
790: || (n->n_protect
791: && mec
792: && tcl
793: && tcl->has_friend(mec))
794: || (n->n_protect
795: && mef
796: && tcl
797: && tcl->has_base(this)
798: // && tcl->has_friend(mef))
799: && friend_check(tcl,this,mef))
800: // static member can be initializer with
801: // private member of its class
802: ||
803: (Cdcl && Cdcl->base == NAME
804: && Cdcl->n_stclass == STATIC
805: && Cdcl->n_initializer
806: && Cdcl->n_qualifier
807: && (
808: Pclass(Pbase(Cdcl->n_qualifier->tp)->b_name->tp) == this
809: || (n->n_protect && Pclass(Pbase(Cdcl->n_qualifier->tp)->b_name->tp)->has_base(this))
810: || Pclass(Pbase(Cdcl->n_qualifier->tp)->b_name->tp)->has_friend(this)
811: )))
812: ;
813: else {
814: //error('d',"ee2");
815: error("%n cannot access%n: %sM",me,n,n->n_protect?"protected":"private");
816: mex = 0; // suppress further error messages
817: }
818: }
819: //error('d',"n %n %k %d",n,n->n_stclass,cc->c_this);
820: Pname th = cc->c_this;
821: Pexpr r = new ref(REF,th,n);
822: if (th) th->use();
823: n->use();
824: r->tp = t;
825: return r;
826: }
827: //error('d',"mex %d",mex);
828: if (mex && n->n_scope==0 && n->tp->base!=OVERLOAD) {
829: if (this==mec
830: || (mec && has_friend(mec))
831: || (mef && has_friend(mef))
832: || (n->n_protect
833: && mec
834: && mec->has_base(this)
835: && tcl
836: && (tcl==mec || tcl->has_base(mec)))
837: || (n->n_protect
838: && mec
839: && tcl
840: && tcl->has_friend(mec))
841: || (n->n_protect
842: && mef
843: && tcl
844: && tcl->has_base(this)
845: // && tcl->has_friend(mef))
846: && friend_check(tcl,this,mef))
847:
848: // static member can be initializer with
849: // private member of its class
850: ||
851: ( Cdcl
852: && Cdcl->base==NAME
853: && Cdcl->n_stclass==STATIC
854: && Cdcl->n_initializer
855: && Cdcl->n_qualifier
856: && (
857: Pclass(Pbase(Cdcl->n_qualifier->tp)->b_name->tp)==this
858: || (n->n_protect
859: && Pclass(Pbase(Cdcl->n_qualifier->tp)->b_name->tp)->has_base(this))
860: || Pclass(Pbase(Cdcl->n_qualifier->tp)->b_name->tp)->has_friend(this)
861: ))
862:
863: )
864: ;
865: else {
866: //error('d',"ee3");
867: error("%n cannot access%n: %sM",me,n,n->n_protect?"protected":"private");
868: mex = 0; // suppress further error messages
869: }
870: }
871: n->use();
872: return n;
873: }
874: }
875:
876: if ((cl==0 || cl==this) // not qualified to a base class
877: && csu!=UNION
878: && csu!=ANON
879: && strcmp(s,"__as")==0) { // assignment is special: you cannot inherit it
880: if (baselist==0
881: || (baselist && baselist->bclass->obj_size!=obj_size)) {
882: Pname cn = ktbl->look(string,0);
883: if (cn->tp->base == COBJ) cn = Pbase(cn->tp)->b_name;
884: Pname x = gtbl->look("__as",0);
885: if (x) { // what if there is an (illegal) global assignment operation?
886: // hack hack don't declare global assignment operations!
887: Pfct f = Pfct(x->tp);
888: if (f->base == FCT) {
889: Pptr r = f->argtype->tp->is_ref();
890: if (r) {
891: Pname cnn = r->typ->is_cl_obj();
892: if (cnn && cn==cnn) return 0;
893: }
894: } else {
895: for (Plist gl = Pgen(f)->fct_list; gl; gl=gl->l) {
896: Pptr r = Pfct(gl->f)->argtype->tp->is_ref();
897: if (r) {
898: Pname cnn = r->typ->is_cl_obj();
899: if (cnn &&cn==cnn) return 0;
900: }
901: }
902: }
903: }
904: return make_assignment(cn) ? find_name(s,cl) : 0;
905: }
906: }
907:
908: return find_in_base(s, cl);
909: }
910:
911: Pexpr classdef::find_in_base(char* s, Pclass cl)
912: {
913: Pbcl bc = 0;
914: Pexpr e = 0;
915: //error('d',"%s->find_in_base(%s)",string,s);
916: for (Pbcl b=baselist; b; b=b->next) {
917: Pclass ccl = cl==this?0:cl;
918:
919: //error('d',"try %t %s",b->bclass,b->bclass?b->bclass->string:"?");
920: Pexpr ee = b->bclass->find_name(s,ccl);
921:
922: if (ee) {
923: if (c_body == 1) { // look for first use (through this)
924: if (b!=baselist || b->base==VIRTUAL)
925: dcl_print(0);
926: else {
927: Pexpr ex = ee;
928: while ((ex->base==MDOT && ex->i1==1)
929: || (ex->base==REF && ex->e1==cc->c_this)) ex = ex->mem;
930: switch (ex->tp->base) {
931: case OVERLOAD:
932: break;
933: case FCT:
934: if (Pfct(ex->tp)->f_virtual==0) break;
935: default:
936: dcl_print(0);
937: }
938: }
939: }
940:
941: if (e) {
942: //error( 'd', "find_in_base: b: %k e %k etp %t",b->base,e->base,e->tp);
943: Pexpr ex = e;
944: int evb = 0; // number of vbase indirections
945: int eb = 0;
946: // note that this does not catch enum members
947: while (ex->base == MDOT
948: || (ex->base==REF && ex->e1==cc->c_this)) {
949: if (ex->base==MDOT) evb += int(ex->i1);
950: ex = ex->mem;
951: }
952:
953: Pexpr eex = ee;
954: int eevb = b->base==VIRTUAL; // number of vbase indirections (incl. possibly this one)
955: int eeb = b->base!=VIRTUAL;
956:
957: while (eex->base == MDOT
958: || (eex->base==REF && eex->e1==cc->c_this)) {
959: if (eex->base==MDOT) eevb += int(eex->i1);
960: eex = eex->mem;
961: }
962:
963: //error('d', "find_in_base: ex: %k eex: %k, eevb: %d evb: %d", ex->base, eex->base, eevb, evb );
964: // relying on simple counts for sub-object identification isn't good enough
965:
966: if (ex != eex) {
967: //error('d',"diff %n eb %d eeb %d mqua %d",ex,eb,eeb,mqua);
968: // if (!mqua) {
969: Pclass ocl = Pfct(ex->tp)->memof;
970: Pclass ncl = Pfct(eex->tp)->memof;
971: int eb = ocl->has_base(ncl);
972: int eeb = ncl->has_base(ocl);
973: //error('d',"eb %d eeb %d evb %d eevb %d",eb,eeb,evb,eevb);
974: if (eb==0 && eeb==0) {
975: // different
976: error("ambiguous%n and%n",ex,eex);
977: break;
978: }
979: else if (eb) { // ex dominates
980: if (eevb<evb) error("ambiguous%n and%n (different sub-objects)",ex,eex);
981: }
982: else { // eex dominates
983: e = ee;
984: bc = b;
985: if (evb<eevb) error("ambiguous%n and%n (different sub-objects)",ex,eex);
986: }
987: if (evb==0 && eevb==0) {
988: error("ambiguous%n and%n (different sub-objects)",ex,eex);
989: }
990: // }
991: // else {
992: // // different
993: // error("ambiguous%n and%n",ex,eex);
994: // break;
995: // }
996: }
997: else if (ex->base==NAME
998: && (Pname(ex)->n_evaluated || Pname(ex)->n_sto==EXTERN)) {
999: //error('d',"enum");
1000: }
1001: else if (evb==0 && eevb==0) {
1002: //error('d',"e %k",e->base);
1003: // no virtual base => different
1004: error("ambiguous%n and%n (no virtualB)",ex,eex);
1005: break;
1006: }
1007: else if ((evb && eevb==0) || (eevb && evb==0)) {
1008: // only one virtual base => different
1009: error("ambiguous%n and%n (one not in virtualB)",ex,eex);
1010: break;
1011: }
1012: }
1013: else {
1014: e = ee;
1015: bc = b;
1016: }
1017: }
1018: }
1019:
1020: if (e == 0) return 0;
1021:
1022: if (mex && bc->ppp==PRIVATE) { // private base
1023: if (this==mec
1024: || (mec && has_friend(mec))
1025: || (mef && has_friend(mef)))
1026: ;
1027: else {
1028: error("%n cannot access %s: %s is a privateBC",me,s,bc->bclass->string);
1029: mex = 0;
1030: }
1031: }
1032:
1033: if (e->base==NAME
1034: && Pname(e)->n_stclass==STATIC) { // static member
1035: Pname(e)->use();
1036: return e;
1037: }
1038: if (e->base != NAME)
1039: if (bc->base == VIRTUAL) { // this->mem => this->Pbclass->mem
1040: e->mem = new mdot(bc->bclass->string,e->mem);
1041: e->mem->i1 = 1;
1042: e->mem->tp = e->mem->mem->tp;
1043: }
1044: else if (bc!=baselist) { // not first base
1045: if (e->e1 == cc->c_this) { // this->mem => this->Obcl.mem
1046: e->mem = new mdot(bc->bclass->string,e->mem);
1047: e->mem->tp = e->mem->mem->tp;
1048: }
1049: else { // this->p->mem => this->Obcl.p->mem
1050: Pexpr ee = e;
1051: while (ee->e1->base == REF) ee = ee->e1;
1052: ee->mem = new mdot(bc->bclass->string,ee->mem);
1053: ee->mem->tp = ee->mem->mem->tp;
1054: }
1055: }
1056:
1057: return e;
1058: }
1059:
1060: int has_virt(Pclass cl)
1061: {
1062: if (cl->virt_count) return 1;
1063: for (Pbcl b = cl->baselist; b; b = b->next)
1064: if (b->bclass->virt_count || has_virt(b->bclass)) return 1;
1065: return 0;
1066: }
1067:
1068: Pname find_vptr(Pclass cl)
1069: /*
1070: find virtual function table
1071: in memtbl or memtbl of ``first bases''
1072: */
1073: {
1074: //error('d',"find_vptr %t",cl);
1075: while (cl) {
1076: Pname vp = cl->memtbl->look("__vptr",0);
1077: if (vp) return vp;
1078: Pbcl b = cl->baselist;
1079: cl = 0;
1080: for (; b; b = b->next)
1081: if (b->base == NAME) {
1082: cl = b->bclass;
1083: break;
1084: }
1085: }
1086: //error('d',"return 0");
1087: return 0;
1088: }
1089:
1090: Pname dummy_fct;
1091: void make_dummy()
1092: // a function with no special priviledges
1093: {
1094: Pname x = new name(".." /*"__static_initializer"*/);
1095: x->tp = new fct(Pvoid_type,0,1);
1096: dummy_fct = x->dcl(gtbl,EXTERN);
1097: // dummy_fct->string = "";
1098: delete x;
1099: }
1100:
1101: void check_visibility(Pname n, Pname q, Pclass cl, Ptable tbl, Pname fn)
1102: /*
1103: "fn" calls "n" a member function of "cl"
1104: fn can be zero (for functions called in arguments to static constructors)
1105: */
1106: {
1107: //error('d',"check_visibility(%n, %t, %d, %n)",n,cl,tbl,fn);
1108: if (fn==0) {
1109: if (dummy_fct == 0) make_dummy();
1110: fn = dummy_fct;
1111: }
1112: Pname nn = new name;
1113: char* s = n->n_gen_fct_name; // overloaded name
1114: nn->string = s?s:n->string;
1115: nn->n_qualifier = q;
1116: Pname nx = Pname(find_name(nn,cl,tbl,REF,fn)); // nn deleted by find_name
1117: if (nx->tp->base != OVERLOAD) return;
1118:
1119: // can we get here?
1120:
1121:
1122: // overloaded not checked by find_name()
1123: // (since it looks for NAMEs not functions)
1124:
1125: for (Plist gl=Pgen(nx->tp)->fct_list; gl; gl=gl->l) {
1126: Pname nn = gl->f;
1127: if (n == nn) {
1128: if (nn->n_scope) return; // public member
1129:
1130: if (fn) {
1131: Pclass ncl = Pclass(nn->n_table->t_name->tp);
1132: Pname fncn = fn->n_table->t_name;
1133: Pclass mec = fncn?Pclass(fncn->tp):0;
1134: Pfct f = Pfct(fn->tp);
1135: if (ncl==mec
1136: || (mec && ncl->has_friend(mec))
1137: || ncl->has_friend(f)
1138: || (n->n_protect
1139: && mec
1140: && mec->has_base(ncl)
1141: )
1142: // && (cl==mec || cl->has_base(mec)))
1143: || (n->n_protect
1144: && mec
1145: && cl->has_friend(mec))
1146: || (n->n_protect
1147: && cl->has_base(ncl)
1148: && cl->has_friend(f)
1149: && friend_check(cl,ncl,f))
1150: )
1151: return;
1152: }
1153:
1154: //error('d',"ee4");
1155: error("%n cannot access%n: %sM",fn,nn,nn->n_protect?"protected":"private");
1156: return;
1157: }
1158: }
1159: error('i',"visibility check failed");
1160: }
1161:
1162: /* ODI notes -
1163:
1164: template class changes
1165:
1166: n_gen_fct_name instead of a char * hifing in n_tbl_list
1167:
1168: */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.