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