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