void classdef.dcl(Pname cname, Ptable tbl) { int nmem; Pname p; Pptr cct; Pbase bt; Pname px; Ptable btbl; int bvirt; Pclass bcl; int i; int fct_seen = 0; int static_seen = 0; int local = tbl!=gtbl; int byte_old = byte_offset; int bit_old = bit_offset; int max_old = max_align; int boff; int in_union; int usz; int make_ctor = 0; int make_dtor = 0; /* this is the place for paranoia */ if (this == 0) error('i',"0->Cdef.dcl(%d)",tbl); if (base != CLASS) error('i',"Cdef.dcl(%d)",base); if (cname == 0) error('i',"unNdC"); if (cname->tp != this) error('i',"badCdef"); if (tbl == 0) error('i',"Cdef.dcl(%n,0)",cname); if (tbl->base != TABLE) error('i',"Cdef.dcl(%n,tbl=%d)",cname,tbl->base); nmem = pubmem->no_of_names() + privmem->no_of_names() + pubdef->no_of_names(); in_union = (csu==UNION || csu==ANON); if (clbase) { if (clbase->base != TNAME) error("BC%nU",clbase); clbase = Pbase(clbase->tp)->b_name; bcl = (Pclass)clbase->tp; if ((bcl->defined&SIMPLIFIED) == 0) error("BC%nU",clbase); tbl = bcl->memtbl; if (tbl->base != TABLE) error('i',"badBC table %d",tbl); btbl = tbl; bvirt = bcl->virt_count; if (bcl->csu == UNION) error('s',"C derived from union"); if (in_union) error("derived union"); else if (pubbase == 0) csu = CLASS; boff = bcl->real_size; max_align = bcl->align(); bit_ass = bcl->bit_ass; } else { btbl = 0; bvirt = 0; boff = 0; if (!in_union) csu = (virt_count) ? CLASS : STRUCT; while (tbl!=gtbl && tbl->t_name) tbl = tbl->next; // nested classes max_align = AL_STRUCT; bit_ass = 1; // can be bitwise copied } memtbl->set_scope(tbl); memtbl->set_name(cname); if (nmem) memtbl->grow((nmem<=2)?3:nmem); cc->stack(); cc->not = cname; cc->cot = this; //error('d',"classdef%n",cname); byte_offset = usz = boff; bit_offset = 0; bt = new basetype(COBJ,cname); bt->b_table = memtbl; this_type = cc->tot = cct = new ptr(PTR,bt,0); PERM(cct); PERM(bt); for (p=privmem; p; p=px) { Pname m; px = p->n_list; //error('d',"privmem%n %d",p,p->tp->base); if (p->tp->base==FCT) { Pfct f = (Pfct)p->tp; Pblock b = f->body; f->body = 0; switch( p->n_sto ) { case AUTO: case STATIC: case REGISTER: case EXTERN: error("M%n cannot be%k",p,p->n_sto); p->n_sto = 0; } m = p->dcl(memtbl,0); if (b) { if (m->tp->defined&(DEFINED|SIMPLIFIED)) error("two definitions of%n",m); else if (p->where.line!=m->where.line) error('s',"previously declared%n cannot be defined inCD",p); else Pfct(m->tp)->body = b; } fct_seen = 1; } else { m = p->dcl(memtbl,0); if (m) { if (m->n_stclass==STATIC) { static_seen = 1; m->n_sto = (tbl == gtbl) ? 0 : STATIC; if (m->n_initializer) error('s',"staticM%n withIr",m); } if (in_union) { if (usz < byte_offset) usz = byte_offset; byte_offset = 0; } } } } if (privmem && csu==STRUCT) csu = CLASS; for (p=pubmem; p; p=px) { Pname m; px = p->n_list; //error('d',"pubmem%n %d",p,p->tp->base); if (p->tp->base == FCT) { Pfct f = (Pfct)p->tp; Pblock b = f->body; f->body = 0; switch(p->n_sto) { case AUTO: case STATIC: case REGISTER: case EXTERN: error("M%n cannot be%k",p,p->n_sto); p->n_sto = 0; } m = p->dcl(memtbl,PUBLIC); if (b) { if (m->tp->defined&(DEFINED|SIMPLIFIED)) error("two definitions of%n",m); else if (p->where.line!=m->where.line) error('s',"previously declared%n cannot be defined inCD",p); else Pfct(m->tp)->body = b; } fct_seen = 1; } else { m = p->dcl(memtbl,PUBLIC); if (m) { if (m->n_stclass==STATIC) { m->n_sto = (tbl == gtbl) ? 0 : STATIC; static_seen = 1; if (m->n_initializer) error('s',"staticM%n withIr",m); } if (in_union) { if (usz < byte_offset) usz = byte_offset; byte_offset = 0; } } } /*delete p;*/ } /* pubmem = 0; */ // if (local && fct_seen) error("FM of local%k %s",csu,string); if (in_union) byte_offset = usz; if (virt_count || bvirt) { /* assign virtual indices */ Pname vp[100]; Pname nn; nn = has_ctor(); if (nn==0 || nn->n_table!=memtbl) make_ctor = 1; { // FUDGE vtbl char* s = new char[20]; sprintf(s,"%s__vtbl",string); Pname n = new name(s); n->tp = Pfctvec_type; Pname nn = gtbl->insert(n,0); nn->use(); } if (virt_count = bvirt) for (i=0; i<bvirt; i++) vp[i] = bcl->virt_init[i]; for ( nn=memtbl->get_mem(i=1); nn; nn=memtbl->get_mem(++i) ) { switch (nn->tp->base) { case FCT: { Pfct f = (Pfct)nn->tp; if (bvirt) { Pname vn = btbl->look(nn->string,0); if (vn) { /* match up with base class */ if (vn->n_table==gtbl) goto vvv; Pfct vnf; switch (vn->tp->base) { case FCT: vnf = (Pfct)vn->tp; if (vnf->f_virtual) { if (vnf->check(f,0)) error("virtual%nT mismatch:%t and%t",nn,f,vnf); f->f_virtual = vnf->f_virtual; vp[f->f_virtual-1] = nn; } else goto vvv; break; case OVERLOAD: { Pgen g = (Pgen)vn->tp; if (f->f_virtual || Pfct(g->fct_list->f->tp)->f_virtual) error('s',"virtual%n overloaded inBC but not in derivedC",nn); break; } default: goto vvv; } } else goto vvv; } else { vvv: /*error('d',"vvv: %n f_virtual %d virt_count %d",nn,f->f_virtual,virt_count);*/ if (f->f_virtual) { f->f_virtual = ++virt_count; switch (f->f_virtual) { case 1: { Pname vpn = new name("_vptr"); vpn->tp = Pfctvec_type; (void) vpn->dcl(memtbl,PUBLIC); delete vpn; } default: vp[f->f_virtual-1] = nn; } } } break; } case OVERLOAD: { Plist gl; Pgen g = (Pgen)nn->tp; /*error('d',"overload%n bvirt==%d",nn,bvirt);*/ if (bvirt) { Pname vn = btbl->look(nn->string,0); Pgen g2; Pfct f2; if (vn) { /*error('d',"vn%n tp%k",vn,vn->tp->base);*/ if (vn->n_table == gtbl) goto ovvv; switch (vn->tp->base) { default: goto ovvv; case FCT: f2 = (Pfct)vn->tp; if (f2->f_virtual || Pfct(g->fct_list->f->tp)->f_virtual) error('s',"virtual%n overloaded in derivedC but not inBC",nn); break; case OVERLOAD: g2 = (Pgen)vn->tp; for (gl=g->fct_list; gl; gl=gl->l) { Pname fn = gl->f; Pfct f = (Pfct)fn->tp; Pname vn2 = g2->find(f); if (vn2 == 0) { if (f->f_virtual) error('s',"virtual overloaded%n not found inBC",fn); } else { Pfct vn2f = (Pfct)vn2->tp; if (vn2f->f_virtual) { f->f_virtual = vn2f->f_virtual; vp[f->f_virtual-1] = fn; } } } break; } } else goto ovvv; } else { ovvv: for (gl=g->fct_list; gl; gl=gl->l) { Pname fn = gl->f; Pfct f = (Pfct)fn->tp; /*fprintf(stderr,"fn %s f %d %d %d count %d\n",fn->string,f,f->base,f->f_virtual,virt_count+1);*/ if (f->f_virtual) { f->f_virtual = ++virt_count; switch (f->f_virtual) { case 1: { Pname vpn = new name("_vptr"); vpn->tp = Pfctvec_type; (void) vpn->dcl(memtbl,0); delete vpn; } default: vp[f->f_virtual-1] = fn; } } } } break; } } } virt_init = new Pname[virt_count]; for (i=0; i<virt_count; i++) virt_init[i] = vp[i]; } Pname pnx; for (p=pubdef; p; p=pnx) { char* qs = p->n_qualifier->string; char* ms = p->string; Pname cx; Ptable ctbl; Pname mx; pnx = p->n_list; //error('d',"dcl: pubdef %s::%s",qs,ms); if (strcmp(ms,qs)==0) ms = "_ctor"; for (cx = clbase; cx; cx = Pclass(cx->tp)->clbase) { if (strcmp(cx->string,qs) == 0) goto ok; } error("publicQr %s not aBC",qs); continue; ok: ctbl = Pclass(cx->tp)->memtbl; mx = ctbl->lookc(ms,0); //error('d',"ms %d %d %d",mx,Ebase,Epriv); if (Ebase) { // cc->nof ?? if (!Ebase->has_friend(cc->nof)) error("QdMN%n is in privateBC",p); } else if (Epriv) { if (!Epriv->has_friend(cc->nof)) error("QdMN%n is private",p); } if (mx == 0) { error("C%n does not have aM %s",cx,p->string); p->tp = any_type; } else { if (mx->tp->base==OVERLOAD) error('s',"public specification of overloaded%n",mx); p->base = PUBLIC; } p->n_qualifier = mx; (void) memtbl->insert(p,0); //error('d',"bbb"); if (Nold) error("twoDs of CM%n",p); } pubdef = 0; if (bit_offset) byte_offset += (bit_offset/BI_IN_BYTE+1); real_size = byte_offset; //error('d',"%s: rz=%d (bits %d)",string,byte_offset,bit_offset); if (byte_offset < SZ_STRUCT) byte_offset = SZ_STRUCT; int waste = byte_offset%max_align; if (waste) byte_offset += max_align-waste; //error('d',"%s: sz=%d al=%d",string,byte_offset,max_align); obj_size = byte_offset; obj_align = max_align; if ( has_dtor() && has_ctor()==0) error('w',"%s has destructor but no constructor",string); { // now look look at the members Pname m; Pclass oc = in_class; int ct = has_ctor()==0; int dt = has_dtor()==0; int un = csu==UNION; Pname statc = 0; Pname statd = 0; for (m=memtbl->get_mem(i=1); m; m=memtbl->get_mem(++i) ) { if (m->base == PUBLIC) continue; Ptype t = m->tp; switch (t->base) { default: if (ct && make_ctor==0) { if (t->is_ref()) error("reference%n inC %s without constructor",m,string); if (t->tconst() && vec_const==0) error("constant%n inC %s without constructor",m,string); } break; case FCT: case OVERLOAD: case CLASS: case ENUM: continue; case VEC: break; } Pname cn = t->is_cl_obj(); if (cn == 0) cn = cl_obj_vec; if (cn) { Pclass cl = (Pclass)cn->tp; if (cl->bit_ass == 0) bit_ass = 0; // no bit copy if (ct || dt || un) { Pname ctor = cl->has_ctor(); Pname dtor = cl->has_dtor(); if (ctor) { if (m->n_stclass==STATIC) { error('s',"staticM%n ofC%n with constructor",m,cn); statc = m; } else if (un) error("M%n ofC%n with constructor in union",m,cn); else if (ct) { if (statc) error('s',"staticM%n ofC%t with constructor",statc,statc->tp); make_ctor = 1; ct = 0; } } if (dtor) { if (m->n_stclass==STATIC) { error('s',"staticM%n ofC%n with destructor",m,cn); statd = m; } else if (un) error("M%n ofC%n with destructor in union",m,cn); else if (dt) { if (statd) error('s',"staticM%n ofC%t with constructor",statd,statd->tp); make_dtor = 1; dt = 0; } } } } } } if (make_ctor) { Pname ct = has_ctor(); if (ct==0 || ct->n_table!=memtbl) { // make a constructor for the class: x::x() {} // a base class's constructor is not good enough if (ct && has_ictor()==0) error("%k %s needs a constructor",csu,string); Pname n = new name(string); Pfct f = new fct(defa_type,0,1); n->tp = f; n->n_oper = TNAME; Pname m = n->dcl(memtbl,PUBLIC); Pfct(m->tp)->body = new block(curloc,0,0); } } if (make_dtor && has_dtor()==0) { // make a destructor for the class: x::x() {} Pname n = new name(string); Pfct f = new fct(defa_type,0,1); n->tp = f; n->n_oper = DTOR; Pname m = n->dcl(memtbl,PUBLIC); Pfct(m->tp)->body = new block(curloc,0,0); } defined |= DEFINED; for (p=memtbl->get_mem(i=1); p; p=memtbl->get_mem(++i)) { /* define members defined inline */ //error('d',"member %n",p); switch (p->tp->base) { case FCT: { Pfct f = (Pfct)p->tp; if (f->body) { f->f_inline = 1; p->n_sto = STATIC; f->dcl(p); } break; } case OVERLOAD: { Pgen g = (Pgen)p->tp; Plist gl; for (gl=g->fct_list; gl; gl=gl->l) { Pname n = gl->f; Pfct f = (Pfct)n->tp; if (f->body) { f->f_inline = 1; n->n_sto = STATIC; f->dcl(n); } } } } } Plist fl; /* define friends defined inline */ for (fl=friend_list; fl; fl=fl->l) { Pname p = fl->f; switch (p->tp->base) { case FCT: { Pfct f = (Pfct)p->tp; if (f->body && (f->defined&(DEFINED|SIMPLIFIED)) == 0) { f->f_inline = 1; p->n_sto = STATIC; f->dcl(p); } break; } case OVERLOAD: { Pgen g = (Pgen)p->tp; Plist gl; for (gl=g->fct_list; gl; gl=gl->l) { Pname n = gl->f; Pfct f = (Pfct)n->tp; if (f->body && (f->defined&(DEFINED|SIMPLIFIED)) == 0) { f->f_inline = 1; n->n_sto = STATIC; f->dcl(n); } } } } } byte_offset = byte_old; bit_offset = bit_old; max_align = max_old; cc->unstack(); }
bit type::check(Ptype t, TOK oper, bit level) /* check if "this" can be combined with "t" by the operator "oper" used for check of assignment types (oper==ASSIGN) declaration compatability (oper==0) decl. compatibility without "const"ness (oper=254) (oper == IGNORE_CONST) parameterized type formals (oper==255) as for (oper==0) but special checking for ANY types argument types (oper==ARG) return types (oper==RETURN) overloaded function name match (oper==OVERLOAD) overloaded function coercion (oper==COERCE) virtual function match (oper==VIRTUAL) NOT for arithmetic operators return 1 if the check failed */ { register Ptype t1 = this, t2 = t; bit cnst1 = 0, cnst2 = 0; TOK b1, b2; bit vv=0, over=0, strict_any_check = 0; TOK rec_oper; // value of oper for recursive calls to type::check // oper, 255, or PT_OVERLOAD TOK rec_oper0; // value of oper for recursive calls to type::check // 0, 255, or PT_OVERLOAD if (t1==0 || t2==0) error('i',"check(%p,%p,%d)",t1,t2,oper); if(t1==t2) return 0; switch(oper) { case VIRTUAL: vv = 1; Vcheckerror = 0; oper = 0; break; case OVERLOAD: over = 1; oper = 0; break; case PT_OVERLOAD: over = 1; // no break case 255: oper = 0; strict_any_check=1; break; } if(level==0) { const_problem = 0; return_error = 0; pt_ptm = 0; pt_over = over; } rec_oper = strict_any_check ? ( over ? PT_OVERLOAD : 255 ) : oper; rec_oper0 = strict_any_check ? ( over ? PT_OVERLOAD : 255 ) : 0; t1 = t1->skiptypedefs(cnst1); /* ** GLOG: the following test on ANY must be done before unrolling ** t2, to accommodate templates (in a way I don't yet understand) */ if (t1->base == ANY || t2->base == ANY) if (over==0 || strict_any_check==0) return strict_any_check ? t1!=t2 : 0; t2 = t2->skiptypedefs(cnst2); if(t1==t2) goto const_check; b1 = t1->base; b2 = t2->base; if (b1 != b2) { switch (b1) { case PTR: switch (b2) { case VEC: if ( level>0 || (oper == 0 || oper == IGNORE_CONST) && over==0 || Pptr(t1)->memof || Pptr(t1)->ptname || Pptr(t1)->typ->check(Pvec(t2)->typ,rec_oper,level+1) ) return 1; goto const_check; case FCT: if ( level>0 || Pptr(t1)->typ->check(t2,rec_oper,level+1) ) return 1; goto const_check; } break; case FCT: if( b2==PTR ) { if ( level>0 || t1->check(Pptr(t2)->typ,rec_oper,level+1) ) return 1; goto const_check; } break; case VEC: if (b2==PTR) { if ( level>0 || (oper==0 || oper == IGNORE_CONST) && over==0 || Pptr(t2)->memof || Pptr(t2)->ptname || Pvec(t1)->typ->check(Pptr(t2)->typ,rec_oper,level+1) ) return 1; goto const_check; } break; } if(level>0) { if((oper != 0 && oper != IGNORE_CONST) && b1==VOID && level==1) { if(b2==FCT) { Pfct f = Pfct(t2); if(f->memof && f->f_static==0) return 1; } goto const_check; } return 1; } switch (oper) { case 0: case IGNORE_CONST: if ( b2 == ZTYPE && b1==INT && Pbase(t1)->b_unsigned==0 || b1 == ZTYPE && b2==INT && Pbase(t2)->b_unsigned==0 ) goto const_check; return 1; case ARG: case ASSIGN: case RETURN: case COERCE: switch (b1) { case ZTYPE: case CHAR: case SHORT: case INT: case LONG: case LLONG: case FLOAT: case DOUBLE: case LDOUBLE: case FIELD: switch (b2) { case LONG: case LLONG: case FLOAT: case DOUBLE: case LDOUBLE: case EOBJ: case ZTYPE: case CHAR: case SHORT: case INT: case FIELD: if(oper==COERCE) Nstd++; goto const_check; } return 1; case PTR: case VEC: if (b2==ZTYPE) { if(oper==COERCE) Nstd++; goto const_check; } case RPTR: case COBJ: case FCT: case EOBJ: default: return 1; } } goto const_check; } switch (b1) { case VEC: if ( Pvec(t1)->size!=Pvec(t2)->size && ( level>0 || (oper==0 || oper==IGNORE_CONST) && strict_any_check==0 && Pvec(t1)->size && Pvec(t2)->size ) ) return 1; if(Pvec(t1)->typ->check(Pvec(t2)->typ,rec_oper,level+1)) return 1; break; case PTR: case RPTR: { Pptr p1 = Pptr(t1); Pptr p2 = Pptr(t2); if ((p1->ptname && p2->ptname) && (!p1->memof || !p2->memof)) return 1; if (!same_class(p1->memof,p2->memof)) { // T::* requires we defer setting up memof // until instantiation of the Template type T // ptname holds the formal parameter T // can't merge with other if because of memof usage if( p1->memof==0 && p1->ptname || p2->memof==0 && p2->ptname ) pt_ptm = 1; else if( p1->memof==0 || p2->memof==0 || (p1->memof->baseof(p2->memof)==0 && same_class(p1->memof,p2->memof,1)==0) ) return 1; if (pt_ptm == 0 && (oper==0 || oper==IGNORE_CONST) && same_class(p1->memof,p2->memof)==0) return 1; if(oper==COERCE) Nstd++; } #if 0 if (!level && (oper == 0 || oper == ASSIGN || oper == COERCE || oper == ARG || oper == RETURN)) { Ptype t11; Ptype t22; Ptype ta; Ptype tb; int i = 0; int j = 0; int k = 0; ta = t1; while ((ta->base == PTR || ta->base == RPTR) && (tb = ta->is_ptr_or_ref())) { ta = Pptr(tb)->typ; i++; k += ta->tconst(); } t11 = ta; ta = t2; while ((ta->base == PTR || ta->base == RPTR) && (tb = ta->is_ptr_or_ref())) { ta = Pptr(tb)->typ; j++; } t22 = ta; if (i >= 2 && j == i && t11->tconst() && !t22->tconst() && k != i) return const_problem = 1; } #endif if(p1->typ->check(p2->typ,rec_oper,level+1)) return 1; break; } case FCT: { Pfct f1 = Pfct(t1); Pfct f2 = Pfct(t2); Pname a1 = f1->argtype; Pname a2 = f2->argtype; TOK k1 = f1->nargs_known; TOK k2 = f2->nargs_known; int n1 = f1->nargs; int n2 = f2->nargs; // if pt_ptm, want to check arguments and return type // but template ptm has no memof until instantiation if (!same_class(f1->memof,f2->memof) && pt_ptm == 0) { if (f1->memof==0 && f2->f_static) goto sss; if (vv == 0) // match even if private base class if ( f1->memof==0 || f2->memof==0 || ( level > 1 || f1->memof->baseof(f2->memof)==0 ) && same_class(f1->memof,f2->memof)==0 ) return 1; if(oper==COERCE) Nstd++; sss:; //SSS } if (k1 != k2) return 1; if (n1!=n2 && k1 && k2) { goto aaa; } else if (a1 && a2) { while (a1 && a2) { if (a1->tp->check(a2->tp,rec_oper0,level+1)) return 1; a1 = a1->n_list; a2 = a2->n_list; } if (a1 || a2) goto aaa; } else if (a1 || a2) { aaa: if (k1 == ELLIPSIS) { switch (oper) { case 0: case IGNORE_CONST: if (a2 && k2==0) break; return 1; case ASSIGN: if (a2 && k2==0) break; return 1; case ARG: if (a1) return 1; break; case COERCE: return 1; } } else if (k2 == ELLIPSIS) { return 1; } else if (k1 || k2) { return 1; } } cnst1 = f2->f_const; cnst2 = f1->f_const; if(f1->returns->check(f2->returns,rec_oper0,level+1)) { if(vv && cnst1==cnst2) { bit fail = 1; Ptype t1 = f1->returns; Ptype t2 = f2->returns; if ((t1->is_ptr() && t2->is_ptr()) || (t1->is_ref() && t2->is_ref())) { t1 = Pptr(t1->is_ptr_or_ref())->typ; t2 = Pptr(t2->is_ptr_or_ref())->typ; if (!t1->is_ptr_or_ref() && !t2->is_ptr_or_ref()) { t1 = t1->skiptypedefs(); t2 = t2->skiptypedefs(); if (t1->base == COBJ && t2->base == COBJ) { Pclass c1 = t1->classtype(); Pclass c2 = t2->classtype(); Nvis = 0; if (c2->has_base(c1,0,1) && !Nvis) fail = 0; } } } if (fail) Vcheckerror = 1; else break; } if (rec_oper0 == PT_OVERLOAD && level == 0) return_error = 1; return 1; } break; } case FIELD: switch (oper) { case 0: case IGNORE_CONST: case ARG: error('i',"check field?"); } return 0; case FLOAT: case DOUBLE: case LDOUBLE: case CHAR: case SHORT: case INT: case LONG: case LLONG: if (Pbase(t1)->b_unsigned != Pbase(t2)->b_unsigned) { if (level>0 || (oper==0 || oper==IGNORE_CONST)) return 1; if (oper==COERCE) Nstd++; } goto const_check; case EOBJ: if (Pbase(t1)->b_name->tp != Pbase(t2)->b_name->tp) return 1; goto const_check; case CLASS: case COBJ: { Pname n1, n2; if (b1 == COBJ) { n1 = Pbase(t1)->b_name; n2 = Pbase(t2)->b_name; if (n1 == n2) goto const_check; } // once again, a more comprehensive check for classes, // since they may be parameterized. // same_class: handles class templates: instantiated // fm_same_class: handles matching uninstantiated templates // used as formal arguments for template functions // hack: see comment on classdef::same_class in template.c extern int is_arg; int access = template_hier || pt_over; if ( same_class(Pclass(b1==COBJ?n1->tp:t1),Pclass(b1==COBJ?n2->tp:t2),access||is_arg) || rec_oper==PT_OVERLOAD && fm_same_class(Pclass(b1==COBJ?n1->tp:t1),Pclass(b1==COBJ?n2->tp:t2)) ) goto const_check; // permit a derived class to match public base class if (template_hier != 0) goto pt_hack; switch (oper) { case ARG: case ASSIGN: case RETURN: case COERCE: { pt_hack: ppbase = PUBLIC; if (level<=1 && ((Pclass(b1==COBJ?n2->tp:t2))->is_base(b1==COBJ?n1->string:Pclass(t1)->string))) { if (ppbase!=PUBLIC) { const_problem = 0; return 1; // private or protected base } if(oper==COERCE) Nstd++; goto const_check; } } // no break case 0: case IGNORE_CONST: const_problem = 0; return 1; } goto const_check; } case ZTYPE: case VOID: goto const_check; default: error('i',"T::check(o=%d %d %d)",oper,b1,b2); } const_check: if(cnst1==cnst2) return 0; switch(oper) { case IGNORE_CONST: return 0;//ignore "const"ness for oper=IGNORE_CONST case 0: const_problem=1; return 1; case ASSIGN: case COERCE: case ARG: case RETURN: if(level>0) { if(cnst2) const_problem=1; return cnst2; } return 0; default: error('i',"oper = %k in type::check()",oper); } return 0; }