📄 dcl2.c
字号:
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();}void enumdef.dcl(Pname, Ptable tbl){#define FIRST_ENUM 0 int nmem = mem->no_of_names(); Pname p; Pname ns = 0; Pname nl; int enum_old = enum_count; no_of_enumerators = nmem; enum_count = FIRST_ENUM; if (this == 0) error('i',"0->enumdef.dcl(%d)",tbl); for(p=mem, mem=0; p; p=p->n_list) { Pname nn; if (p->n_initializer) { Pexpr i = p->n_initializer->typ(tbl); Neval = 0; enum_count = i->eval(); if (Neval) error("%s",Neval); DEL(i); p->n_initializer = 0; } p->n_evaluated = 1; p->n_val = enum_count++; nn = tbl->insert(p,0); /* ??? */ if (Nold) { if (nn->n_stclass == ENUM) error( (p->n_val!=nn->n_val)?0:'w',"enumerator%n declared twice",nn); else error("incompatibleDs of%n",nn); } else { nn->n_stclass = ENUM; // no store will be allocated if (ns) nl->n_list = nn; else ns = nn; nl = nn; } delete p; } mem = ns; enum_count = enum_old; defined |= DEFINED;}Pstmt curr_loop;Pstmt curr_switch;Pblock curr_block;void stmt.reached(){ register Pstmt ss = s_list; if (ss == 0) return; switch (ss->base) { case LABEL: case CASE: case DEFAULT: break; default: error('w',"statement not reached"); /* delete unreacheable code */ for (; ss; ss=ss->s_list) { switch (ss->base) { case LABEL: case CASE: case DEFAULT: /* reachable */ s_list = ss; return; case IF: case DO: case WHILE: case SWITCH: case FOR: case BLOCK: /* may hide a label */ s_list = ss; return; } } s_list = 0; }}bit arg_err_suppress;Pexpr check_cond(Pexpr e, TOK b, Ptable tbl){//error('d',"check_cond(%k %k) tbl %d",e->base,b,tbl); Pname cn; if (cn = e->tp->is_cl_obj()) { Pclass cl = (Pclass)cn->tp; int i = 0; Pname found = 0; for (Pname on = cl->conv; on; on=on->n_list) { Pfct f = (Pfct)on->tp; Ptype t = f->returns; xx: switch (t->base) { case TYPE: t = Pbase(t)->b_name->tp; goto xx; case CHAR: case SHORT: case INT: case LONG: case EOBJ: case FLOAT: case DOUBLE: case PTR: i++; found = on; } } switch (i) { case 0: error("%nO in%kE",cn,b); return e; case 1: {//error('d',"cond%t<-%t:%n",Pfct(found->tp)->returns,e->tp,found); Pclass cl = (Pclass)cn->tp; Pref r = new ref(DOT,e,found); r->tp = found->tp; Pexpr c = new expr(G_CALL,r,0); c->fct_name = found; // c->tp = Pfct(found->tp)->returns; return c->typ(tbl); } default: error("%d possible conversions for%nO in%kE",i,cn,b); return e; } } e->tp->num_ptr(b); return e;}void stmt.dcl()/* typecheck statement "this" in scope "curr_block->tbl"*/{ Pstmt ss; Pname n; Pname nn; Pstmt ostmt = Cstmt; for (ss=this; ss; ss=ss->s_list) { Pstmt old_loop, old_switch; Cstmt = ss; Ptable tbl = curr_block->memtbl;/*error('d',"ss %d%k tbl %d e %d%k s %d%k sl %d%k", ss, ss->base, tbl, ss->e, (ss->e)?ss->e->base:0, ss->s, (ss->s)?ss->s->base:0, ss->s_list, (ss->s_list)?ss->s_list->base:0);*/ switch (ss->base) { case BREAK: if (curr_loop==0 && curr_switch==0) error("%k not in loop or switch",BREAK); ss->reached(); break; case CONTINUE: if (curr_loop == 0) error("%k not in loop",CONTINUE); ss->reached(); break; case DEFAULT: if (curr_switch == 0) { error("default not in switch"); break; } if (curr_switch->has_default) error("two defaults in switch"); curr_switch->has_default = ss; ss->s->s_list = ss->s_list; ss->s_list = 0; ss->s->dcl(); break; case SM: switch (ss->e->base) { case DUMMY: ss->e = 0; break; // check for unused results // don't check operators that are likely // to be overloaded to represent "actions": // ! ~ < <= > >= << >> case EQ: case NE: case PLUS: case MINUS: case REF: case DOT: case MUL: case DIV: case ADDROF: case AND: case OR: case ER: case DEREF: case ANDAND: case OROR: case NAME: if (ss->e->tp) break; // avoid looking at generated code ss->e = ss->e->typ(tbl); if (ss->e->tp->base != VOID) error('w',"result of%kE not used",ss->e->base); break; default: ss->e = ss->e->typ(tbl); } // ss->e = (ss->e != dummy) ? ss->e->typ(tbl) : 0; break; case RETURN: { Pname fn = cc->nof; Ptype rt = Pfct(fn->tp)->returns; Pexpr v = ss->e; if (v != dummy) { if (rt->base == VOID) { error('w',"unX return value"); /*refuse to return the value:*/ ss->e = dummy; } else { v = v->typ(tbl); lx://error('d',"return %t",rt); switch (rt->base) { case TYPE: rt = Pbase(rt)->b_name->tp; goto lx; case RPTR: ss->e = ref_init(Pptr(rt),v,tbl); if (v->lval(0)==0 && v->tp->tconst()==0) error('w',"reference to non-lvalue returned"); else if (v->base==NAME && Pname(v)->n_scope==FCT) error('w',"reference to local variable returned"); break; case COBJ: { Pname rv = tbl->look("_result",0); ss->e = class_init(rv,rt,v,tbl);//error('d',"ss->e %t %d",ss->e->tp,ss->e->base); break; } case ANY: break; case INT: case CHAR: case LONG: case SHORT: if (Pbase(rt)->b_unsigned && v->base==UMINUS && v->e2->base==ICON) error('w',"negative retured fromF returning unsigned"); default: { Pname cn; int i; if ((cn=v->tp->is_cl_obj()) && (i=can_coerce(rt,v->tp)) && Ncoerce) { if (1 < i) error("%d possible conversions for return value",i); Pclass cl = (Pclass)cn->tp; Pref r = new ref(DOT,v,Ncoerce); Pexpr c = new expr(G_CALL,r,0); c->fct_name = Ncoerce; c->tp = rt; ss->e = c; break; } } ss->e = v; if (rt->check(v->tp,ASSIGN)) error("bad return valueT for%n:%t (%tX)",fn,v->tp,rt); } } } else { if (rt->base != VOID) error('w',"return valueX"); } ss->reached(); break; } case DO: /* in DO the stmt is before the test */ inline_restr |= 8; old_loop = curr_loop; curr_loop = ss; if (ss->s->base == DCL) error('s',"D as onlyS in do-loop"); ss->s->dcl(); /* tbl = curr_block->memtbl;*/ ss->e = ss->e->typ(tbl); ss->e = check_cond(ss->e,DO,tbl); curr_loop = old_loop; break; case WHILE: inline_restr |= 8; old_loop = curr_loop; curr_loop = ss; ss->e = ss->e->typ(tbl); /*ss->e->tp->num_ptr(ss->base);*/ ss->e = check_cond(ss->e,WHILE,tbl); if (ss->s->base == DCL) error('s',"D as onlyS in while-loop"); ss->s->dcl(); curr_loop = old_loop; break; case SWITCH: { int ne = 0; inline_restr |= 4; old_switch = curr_switch; curr_switch = ss; ss->e = ss->e->typ(tbl); /* ss->e->tp->num_ptr(SWITCH);*/ ss->e = check_cond(ss->e,SWITCH,tbl); { Ptype tt = ss->e->tp; sii: switch (tt->base) { case TYPE: tt = ((Pbase)tt)->b_name->tp; goto sii; case EOBJ: ne = Penum(Pbase(tt)->b_name->tp)->no_of_enumerators; case ZTYPE: case ANY: case CHAR: case SHORT: case INT: case LONG: case FIELD: break; default: error('s',"%t switchE",ss->e->tp); } } ss->s->dcl(); if (ne) { /* see if the number of cases is "close to" but not equal to the number of enumerators */ int i = 0; Pstmt cs; for (cs=ss->case_list; cs; cs=cs->case_list) i++; if (i && i!=ne) { if (ne < i) { ee: error('w',"switch (%t) with %d cases (%d enumerators)",ss->e->tp,i,ne); } else { switch (ne-i) { case 1: if (3<ne) goto ee; case 2: if (7<ne) goto ee; case 3: if (23<ne) goto ee; case 4: if (60<ne) goto ee; case 5: if (99<ne) goto ee; } } } } curr_switch = old_switch; break; } case CASE: if (curr_switch == 0) { error("case not in switch"); break; } ss->e = ss->e->typ(tbl); ss->e->tp->num_ptr(CASE); { Ptype tt = ss->e->tp; iii: switch (tt->base) { case TYPE: tt = Pbase(tt)->b_name->tp; goto iii; case ZTYPE: case ANY: case CHAR: case SHORT: case INT: case LONG: break; default: error('s',"%t caseE",ss->e->tp); } } if (1) { Neval = 0; int i = ss->e->eval(); if (Neval == 0) { Pstmt cs; for (cs=curr_switch->case_list; cs; cs=cs->case_list) { if (cs->case_value == i) error("case %d used twice in switch",i); } ss->case_value = i; ss->case_list = curr_switch->case_list; curr_switch->case_list = ss; } else error("bad case label: %s",Neval); } if (ss->s->s_list) error('i',"case%k",ss->s->s_list->base); ss->s->s_list = ss->s_list; ss->s_list = 0; ss->s->dcl(); break; case GOTO: inline_restr |= 2; ss->reached(); case LABEL: /* Insert label in function mem table; labels have function scope. */ n = ss->d; nn = cc->ftbl->insert(n,LABEL); /* Set a ptr to the mem table corresponding to the scope in which the label actually occurred. This allows the processing of goto's in the presence of ctors and dtors */ if(ss->base == LABEL) { nn->n_realscope = curr_block->memtbl; inline_restr |= 1; } if (Nold) { if (ss->base == LABEL) { if (nn->n_initializer) error("twoDs of label%n",n); nn->n_initializer = (Pexpr)1; } if (n != nn) ss->d = nn; } else { if (ss->base == LABEL) nn->n_initializer = (Pexpr)1; nn->where = ss->where; } if (ss->base == GOTO) nn->use(); else { if (ss->s->s_list) error('i',"label%k",ss->s->s_list->base); ss->s->s_list = ss->s_list; ss->s_list = 0; nn->assign(); } if (ss->s) ss->s->dcl(); break; case IF: { Pexpr ee = ss->e->typ(tbl); if (ee->base == ASSIGN) { Neval = 0; (void)ee->e2->eval(); if (Neval == 0) error('w',"constant assignment in condition"); } ss->e = ee = check_cond(ee,IF,tbl);//error('d',"if (%t)",ee->tp); switch (ee->tp->base) { case INT: case ZTYPE:
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -