📄 expr2.c
字号:
} /* no break */ case PUBLIC: if (Ebase && (cc->cot==0 || ( Ebase!=cc->cot->clbase->tp && !Ebase->has_friend(cc->nof))) ) { error("%n is from a privateBC",found); } } } } else { error("badAL for overloaded%n",fn); return any_type; } break; } case FCT: case_fct: f = (Pfct)t1; if (fn) fct_name = fn; break; } if (no_virt) fct_name = 0; t = f->returns; x = f->nargs; k = f->nargs_known;//error('d',"fct_name%n",fct_name); if (k == 0) { if (fct_void && fn && x==0 && arg) if (no_of_badcall++ == 0) badcall = fn; return t; } for (e=arg, nn=f->argtype, argno=1; e||nn; nn=nn->n_list, e=etail->e2, argno++) { Pexpr a; if (e) { a = e->e1;//error('d',"e %d%k a %d%k e2 %d",e,e->base,a,a->base,e->e2); etail = e; if (nn) { /* type check */ Ptype t1 = nn->tp;//error('d',"argname %n (%t)",nn,nn->tp); lx:/*error('d',"lx: t1%t a->tp%t",t1,a->tp);*/ switch (t1->base) { case TYPE: t1 = Pbase(t1)->b_name->tp; goto lx; case RPTR: e->e1 = ref_init(Pptr(t1),a,tbl); break; case COBJ: e->e1 = class_init(0,t1,a,tbl); break; case ANY: return t; case PTR: { Pfct ef = (Pfct)Pptr(t1)->typ; if (ef->base == FCT) { Pfct f; Pname n = 0; switch (a->base) { case NAME: f = (Pfct)a->tp; switch (f->base) { case FCT: case OVERLOAD: e->e1 = new expr(G_ADDROF,0,a); e->e1->tp = f; } n = Pname(a); goto ad; case DOT: case REF: f = (Pfct)a->mem->tp; switch (f->base) { case FCT: case OVERLOAD: n = Pname(a->mem); a = new expr(G_ADDROF,0,a); e->e1 = a->typ(tbl); } goto ad; case ADDROF: case G_ADDROF: f = (Pfct)a->e2->tp; ad: if (f->base == OVERLOAD) { Pgen g = (Pgen)f; n = g->find(ef); if (n == 0) { error("cannot deduceT for &overloaded %s()",g->string); return any_type; } e->e1->e2 = n; } if (n) n->lval(ADDROF); } break; } goto def; } case CHAR: case SHORT: case INT: if (a->base==ICON && a->tp==long_type) error('w',"long constantA for%n,%kX",fn,t1->base); case LONG: if (((Pbase)t1)->b_unsigned && a->base==UMINUS && a->e2->base==ICON) error('w',"negativeA for%n, unsignedX",fn); default: def: { Pname cn; int i; if ((cn=a->tp->is_cl_obj()) && (i=can_coerce(t1,a->tp)) && Ncoerce) { if (1 < i) error("%d possible conversions for%nA%d",i,fn,argno);//error('d',"%t<-%t",t1,a->tp); Pclass cl = (Pclass)cn->tp; Pref r = new ref(DOT,a,Ncoerce); Pexpr rr = r->typ(tbl); Pexpr c = new expr(G_CALL,rr,0); c->fct_name = Ncoerce; c->tp = t1; e->e1 = c; break; } } if (t1->check(a->tp,ARG)) { if (arg_err_suppress==0) error("badA %dT for%n:%t (%tX)",argno,fn,a->tp,nn->tp); return any_type; } } } else { if (k != ELLIPSIS) { if (arg_err_suppress==0) error("unX %dA for%n",argno,fn); return any_type; } return t; } } else { /* default argument? */ a = nn->n_initializer;//error('d',"arg missing: %n %d as %d",nn,a,arg_err_suppress); if (a == 0) { if (arg_err_suppress==0) error("A %d ofT%tX for%n",argno,nn->tp,fn); return any_type; }//error('d',"%n: perm=%d",nn,a->permanent); a->permanent = 2; // ought not be necessary, but it is e = new expr(ELIST,a,0); if (etail) etail->e2 = e; else e2 = e; etail = e; } } return t;}int refd;Pexpr ref_init(Pptr p, Pexpr init, Ptable tbl)/* initialize the "p" with the "init"*/{ register Ptype it = init->tp; Ptype p1 = p->typ; Pname c1; Pexpr a;//error('d',"init %d",it->tconst());rloop://error('d',"rloop: %d%k",it,it->base); switch (it->base) { case TYPE: it = Pbase(it)->b_name->tp; goto rloop; default: { Ptype tt = it->addrof(); p->base = PTR; // allow &x for y& when y : public x // but not &char for int& int x = p->check(tt,COERCE); p->base = RPTR;//error('d',"p%t tt%t => %d (nstd %d)",p,tt,x,Nstd); if (x == 0) { if (init->lval(0)) return init->address(); if (init->base==G_CALL // &inline function call? && init->fct_name && Pfct(init->fct_name->tp)->f_inline ) return init->address(); p1 = p->typ; goto xxx; } } } c1 = p1->is_cl_obj(); if (c1) {//error('d',"c1%n",c1); refd = 1; /* disable itor */ a = class_init(0,p1,init,tbl); refd = 0;//error('d',"a %d init %d",a,init); if (a==init && init->tp!=any_type) goto xxx; switch (a->base) { case G_CALL: case CM: init = a; goto xxx; } return a->address(); } if (p1->check(it,0)) { error("badIrT:%t (%tX)",it,p); if (init->base != NAME) init->tp = any_type; return init; }xxx://error('d',"xxx: %k",init->base); switch (init->base) { case NAME: case DEREF: case REF: case DOT: // init => &init if (it->tconst() && vec_const==0) goto def; init->lval(ADDROF); return init->address(); case CM:/*error('d',"cm%k",init->e2->base);*/ switch (init->e2->base) { /* (a, b) => (a, &b) */ case NAME: case DEREF: return init->address(); } default: def: /* init = > ( temp=init, &temp) */ { Ptable otbl = tbl; if (Cstmt) { /* make Cstmt into a block */ if (Cstmt->memtbl == 0) Cstmt->memtbl = new table(4,tbl,0); tbl = Cstmt->memtbl; } char* s = make_name('I'); Pname n = new class name(s);//error('d',"ref_init tmp %s n=%d tbl %d init=%d%k",s,n,tbl,init,init->base); if (tbl == gtbl) error('s',"Ir for static reference not an lvaue"); n->tp = p1; n = n->dcl(tbl,ARG); /* no initialization! */ n->n_scope = FCT; n->assign(); a = n->address();//error('d',"tp %t init->tp %t",n->tp,init->tp); Pexpr as = new class expr(ASSIGN,n,init); a = new class expr(CM,as,a); a->tp = a->e2->tp; tbl = otbl; return a; } }}Pexpr class_init(Pexpr nn, Ptype tt, Pexpr init, Ptable tbl)/* initialize "nn" of type "tt" with "init" if nn==0 make a temporary, nn may not be a name*/{ Pname c1 = tt->is_cl_obj(); Pname c2 = init->tp->is_cl_obj();//error('d',"class_init%n%n%n refd=%d",nn,c1,c2,refd); if (c1) { if (c1!=c2 || (refd==0 && Pclass(c1->tp)->has_itor())) { /* really ought to make a temp if refd, but ref_init can do that */ int i = can_coerce(tt,init->tp);//error('d',"i %d Ncoerce %d",i,Ncoerce); switch (i) { default: error("%d ways of making a%n from a%t",i,c1,init->tp); init->tp = any_type; return init; case 0: error("cannot make a%n from a%t",c1,init->tp); init->tp = any_type; return init; case 1: if (Ncoerce == 0) { Pexpr a = new class expr(ELIST,init,0); a = new texpr(VALUE,tt,a); a->e2 = nn; return a->typ(tbl); } switch (init->base) {#ifdef BSD case CALL: case G_CALL:#endif case CM: case NAME: /* init.coerce() */ { Pref r = new ref(DOT,init,Ncoerce); Pexpr rr = r->typ(tbl); Pexpr c = new expr(G_CALL,rr,0); c->fct_name = Ncoerce; init = c; break; } default: /* (temp=init,temp.coerce()) */ { Ptable otbl = tbl; if (Cstmt) { /* make Cstmt into a block */ if (Cstmt->memtbl == 0) Cstmt->memtbl = new table(4,tbl,0); tbl = Cstmt->memtbl; } char* s = make_name('U'); Pname tmp = new name(s); tmp->tp = init->tp; tmp = tmp->dcl(tbl,ARG); /* no init! */ tmp->n_scope = FCT; Pexpr ass = new expr(ASSIGN,tmp,init); ass->tp = tt; Pref r = new ref(DOT,tmp,Ncoerce); Pexpr rr = r->typ(tbl); Pexpr c = new expr(G_CALL,rr,0); c->fct_name = Ncoerce; init = new expr(CM,ass,c); tbl = otbl; } } } return init->typ(tbl); } else if (refd==0) { // bitwise copy, check for dtor & operator= Pclass cl = Pclass(c1->tp); if (cl->itor==0) { if (cl->bit_ass == 0) error('w',"bitwise copy: %s has a member with operator=()",cl->string); else if (cl->has_dtor() && cl->has_oper(ASSIGN)) error('w',"bitwise copy: %s has assignment and destructor but not %s(%s&)",cl->string,cl->string,cl->string); } }//error('d',"class_init%n: init %d %d:%t",nn,init->tp,init->tp->base,init->tp); return init; } if (tt->check(init->tp,ASSIGN) && refd==0) { error("badIrT:%t (%tX)",init->tp,tt); init->tp = any_type; } return init;}int char_to_int(char* s)/* assume s points to a string: 'c' or '\c' or '\0' or '\ddd' or multi-character versions of the above (hex constants have been converted to octal by the parser)*/{ register int i = 0; register char c, d, e; switch (*s) { default: error('i',"char constant store corrupted"); case '`': error('s',"bcd constant"); return 0; case '\'': break; } forever /* also handle multi-character constants */ switch (c = *++s) { case '\'': return i; case '\\': /* special character */ switch (c = *++s) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': /* octal representation */ c -= '0'; switch (d = *++s) { /* try for 2 */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': d -= '0'; switch (e = *++s) { /* try for 3 */ case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': c = c*64+d*8+e-'0'; break; default: c = c*8+d; s--; } break; default: s--; } break; case 'b': c = '\b'; break; case 'f': c = '\f'; break; case 'n': c = '\n'; break; case 'r': c = '\r'; break; case 't': c = '\t'; break; case '\\': c = '\\'; break; case '\'': c = '\''; break; } /* no break */ default: if (i) i <<= BI_IN_BYTE; i += c; }}const A10 = 'A'-10;const a10 = 'a'-10;int str_to_int(register char* p)/* read decimal, octal, or hexadecimal integer*/{ register c; register i = 0; if ((c=*p++) == '0') { switch (c = *p++) { case 0: return 0; case 'l': case 'L': /* long zero */ return 0; case 'x': case 'X': /* hexadecimal */ while (c=*p++) switch (c) { case 'l': case 'L': return i; case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': i = i*16 + c-A10; break; case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': i = i*16 + c-a10; break; default: i = i*16 + c-'0'; } return i; default: /* octal */ do switch (c) { case 'l': case 'L': return i; default: i = i*8 + c-'0'; } while (c=*p++); return i; } } /* decimal */ i = c-'0'; while (c=*p++) switch (c) { case 'l': case 'L': return i; default: i = i*10 + c-'0'; } return i; }char* Neval;int expr.eval(){ if (Neval) return 1; switch (base) { case ZERO: return 0; case IVAL: return (int)e1; case ICON: return str_to_int(string); case CCON: return char_to_int(string); case FCON: Neval = "float in constant expression"; return 1; case STRING: Neval = "string in constant expression"; return 1; case EOBJ: return Pname(this)->n_val; case SIZEOF: return tp2->tsizeof(); case NAME: { Pname n = (Pname)this; if (n->n_evaluated && n->n_scope!=ARG) return n->n_val; Neval = "cannot evaluate constant"; return 1; } case ICALL: if (e1) { il->i_next = curr_icall; curr_icall = il; int i = e1->eval(); curr_icall = il->i_next; return i; } Neval = "void inlineF"; return 1; case ANAME: { Pname n = (Pname)this; int argno = n->n_val; Pin il; for (il=curr_icall; il; il=il->i_next) if (il->i_table == n->n_table) goto aok; goto bok; aok: if (il->local[argno]) { bok: Neval = "inlineF call too complicated for constant expression"; return 1; } Pexpr aa = il->arg[argno]; return aa->eval(); } case CAST: { int i = e1->eval(); /* ignore cast and rely on error message from evaluation. this will allow redundant casts only. In, particular: case (int)0: */ // Neval = "cast in constant expression"; return i; } case UMINUS: case UPLUS: case NOT: case COMPL: case PLUS: case MINUS: case MUL: case LS: case RS: case NE: case LT: case LE: case GT: case GE: case AND: case OR: case ER: case DIV: case MOD: case QUEST: case EQ: case ANDAND: case OROR: break; default: Neval = "bad operator in constant expression"; return 1; } int i1 = (e1) ? e1->eval() : 0; int i2 = (e2) ? e2->eval() : 0; switch (base) { case UMINUS: return -i2; case UPLUS: return i2; case NOT: return !i2; case COMPL: return ~i2; case CAST: return i1; case PLUS: return i1+i2; case MINUS: return i1-i2; case MUL: return i1*i2; case LS: return i1<<i2; case RS: return i1>>i2; case NE: return i1!=i2; case EQ: return i1==i2; case LT: return i1<i2; case LE: return i1<=i2; case GT: return i1>i2; case GE: return i1>=i2; case AND: return i1&i2; case OR: return i1|i2; case OROR: return i1||i2; case ER: return i1^i2; case MOD: return (i2==0) ? 1 : i1%i2; case QUEST: return (cond->eval()) ? i1 : i2; case DIV: if (i2==0) { Neval = "divide by zero"; error('w',"divide by zero"); return 1; } return i1/i2; }}bit classdef.has_friend(Pname f)/* does this class have function "f" as its friend?*/{ Plist l; Ptable ctbl = f->n_table;/*fprintf(stderr,"(%d %s)->has_friend(%d %s)\n",this,string,f,(f)?f->string:""); fflush(stderr);*/ for (l=friend_list; l; l=l->l) { Pname fr = l->f;/*fprintf(stderr,"fr %d %d %d\n",fr,fr->tp,fr->tp->base); fflush(stderr);*/ switch (fr->tp->base) { case CLASS: if (Pclass(fr->tp)->memtbl == ctbl) return 1; break; case COBJ: if (Pbase(fr->tp)->b_table == ctbl) return 1; break; case FCT: if (fr == f) return 1; break; case OVERLOAD: {/* Pgen g = (Pgen)fr->tp; Plist ll; for (ll=g->fct_list; ll; ll=ll->l) { if (ll->f == f) return 1; }*/ l->f = fr = ((Pgen)fr->tp)->fct_list->f; /* first fct */ if (fr == f) return 1; break; } default: error('i',"bad friend %k",fr->tp->base); } } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -