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