📄 expr.c
字号:
/* @(#) expr.c 1.6 1/27/86 17:48:51 */ /*ident "@(#)cfront:src/expr.c 1.6" *//*************************************************************************** C++ source for cfront, the C++ compiler front-end written in the computer science research center of Bell Labs Copyright (c) 1984 AT&T, Inc. All Rights Reserved THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF AT&T, INC.expr.c: type check expressions************************************************************************/#include "cfront.h"#include "size.h"int const_save;Pexpr expr.address(){ if (base==DEREF && e2==0) return e1; /* &* */ if (base == CM) { e2 = e2->address(); return this; } register Pexpr ee = new expr(G_ADDROF,0,this); ee->tp = new ptr(PTR,tp,0); if (base == NAME) Pname(this)->take_addr(); return ee;}Pexpr expr.contents(){ if (base==ADDROF || base==G_ADDROF) return e2; /* *& */ register Pexpr ee = new expr(DEREF,this,0); if (tp) ee->tp = Pptr(tp)->typ; /* tp==0 ??? */ return ee;}Pexpr table.find_name(register Pname n, bit f, Pexpr/* args*/)/* find the true name for "n", implicitly define if undefined if "n" was called f==1 and "args" were its argument list if n was qualified r->n or o.n f==2*/{ Pname q = n->n_qualifier; register Pname qn = 0; register Pname nn; Pclass cl; /* class specified by q */ if (n->n_table) { nn = n; n = 0; goto xx; } if (q) { Ptable tbl;//error('d',"qq %n %n",q,n); if (q == sta_name) tbl = gtbl; else { Ptype t = Pclass(q->tp); if (t == 0) error('i',"Qr%n'sT missing",q); if (q->base == TNAME) { if (t->base != COBJ) { error("badT%k forQr%n",t->base,q); goto nq; } t = Pbase(t)->b_name->tp; } if (t->base != CLASS) { error("badQr%n(%k)",q,t->base); goto nq; } cl = Pclass(t); tbl = cl->memtbl; } qn = tbl->look(n->string,0);//error('d',"qn == %d",qn); if (qn == 0) { n->n_qualifier = 0; nn = 0; goto def; } if (q == sta_name) { /* explicitly global */ qn->use(); delete n; return qn; } /* else check visibility */ }nq: if (cc->tot) { { for (Ptable tbl = this;;) { // loop necessary to get past // local re-definitions nn = tbl->lookc(n->string,0);//error('d',"cc->tot:%n nn=%n sto%k sco%k tbl=%d",n,nn,nn->n_stclass,nn->n_scope,tbl); if (nn == 0) goto qq; /* try for friend */ switch (nn->n_scope) { case 0: case PUBLIC: if (nn->n_stclass == ENUM) break; if (nn->tp->base == OVERLOAD) break; if (Ebase && cc->cot->clbase && Ebase!=cc->cot->clbase->tp && !Ebase->has_friend(cc->nof)) error("%n is from a privateBC",n); if (Epriv && Epriv!=cc->cot && !Epriv->has_friend(cc->nof)) error("%n is private",n); } if (qn==0 || qn==nn) break; if ((tbl=tbl->next) == 0) { /* qn/cl test necessary? */ if (/* (qn->n_stclass==STATIC || qn->tp->base==FCT || qn->tp->base==OVERLOAD) && */ ( qn->n_scope==PUBLIC || cl->has_friend(cc->nof)) ) { /*qn->use(); delete n; return qn; */ nn = qn; break; } else { error("QdN%n not in scope",n); goto def; } } } } xx://error('d',"xx: nn=%n qn=%n n=%n f=%d",nn,qn,n,f); if (nn == 0) goto def; nn->use(); if (f == 2) { if (qn && nn->n_stclass==0) switch (nn->n_scope) { case 0: case PUBLIC: /* suppress virtual */ switch (qn->tp->base) { case FCT: case OVERLOAD: *n = *qn; n->n_qualifier = q; return n; } } if (nn->n_table == gtbl) error("MF%n not found",n); if (n) delete n; return nn; } switch (nn->n_scope) { case 0: case PUBLIC://error('d',"st %d th %d",nn->n_stclass,cc->c_this); if (nn->n_stclass == 0) { if (qn) { /* suppress virtual */ switch (qn->tp->base) { case FCT: case OVERLOAD: *n = *qn; n->n_qualifier = q; /*return n; */ nn = n; n = 0; } } if (cc->c_this == 0) { switch (nn->n_oper) { case CTOR: case DTOR: break; default: /* in static member initializer */ error("%n cannot be used here",nn); return nn; } } Pref r = new ref(REF,cc->c_this,nn); cc->c_this->use(); r->tp = nn->tp; if (n) delete n; return r; } default: if (n) delete n; return nn; } }qq://error('d',"qq: n%n qn%d",n,qn); if (qn) { // check for p->base::mem : // nasty where derived::mem is public // and base::mem is private // NOT DONE /* static member? */ if (qn->n_scope==0 && !cl->has_friend(cc->nof) ) { error("%n is private",qn); if (n) delete n; return qn; } switch (qn->n_stclass) { case STATIC: break; default: switch (qn->tp->base) { case FCT: case OVERLOAD: /* suppress virtual */ if (f == 1) error("O missing for%n",qn); *n = *qn; n->n_qualifier = q; return n; default: if (f != 2) error("O missing for%n",qn); } } if (n) delete n; return qn; } if ( nn = lookc(n->string,0) ) { switch (nn->n_scope) { case 0: case PUBLIC: if (nn->n_stclass == ENUM) break; if (nn->tp->base == OVERLOAD) break; if (Ebase && !Ebase->has_friend(cc->nof) ) error("%n is from privateBC",n); if (Epriv && !Epriv->has_friend(cc->nof) ) error("%n is private",n); } } if (nn) {//error('d',"found %n",nn); if (f==2 && nn->n_table==gtbl) error("MF%n not found",n); nn->use(); if (n) delete n; return nn; }def: /* implicit declaration *///error('d',"implicit f %d",f); n->n_qualifier = 0; if (f == 1) { /* function */ if (n->tp) error('i',"find_name(fct_type?)"); n->tp = new fct(defa_type,0,0); n->n_sto = EXTERN; /* if (fct_void) { n->tp = new fct(defa_type,0,0); } else { Pexpr e; Pname at = 0; Pname att; for (e=args; e; e=e->e2) { Pname ar = new name; if (e->base != ELIST) error('i',"badA %k",e->base); e->e1 = e->e1->typ(this); ar->tp = e->e1->base==STRING ? Pchar_type : e->e1->tp; switch (ar->tp->base) { case ZTYPE: ar->tp = defa_type; break; case FIELD: ar->tp = int_type; break; case ANY: default: PERM(ar->tp); } if (at) att->n_list = ar; else at = ar; att = ar; } n->tp = new fct(defa_type,at,1); } */ } else { n->tp = any_type; if (this != any_tbl) if (cc->not && (cc->cot->defined&(DEFINED|SIMPLIFIED)) == 0) error("C%n isU",cc->not); else error("%n isU",n); } nn = n->dcl(gtbl,EXTERN); nn->n_list = 0; nn->use(); nn->use(); /* twice to cope with "undef = 1;" */ if (n) delete n; if (f==1) if (fct_void) { if (no_of_undcl++ == 0) undcl = nn; } else error('w',"undeclaredF%n called",nn); return nn;}Pexpr expr.typ(Ptable tbl)/* find the type of "this" and place it in tp; return the typechecked version of the expression: "tbl" provides the scope for the names in "this"*/{if (this == 0) error('i',"0->expr.typ"); Pname n; Ptype t = 0; Ptype t1, t2; TOK b = base; TOK r1, r2;#define nppromote(b) t=np_promote(b,r1,r2,t1,t2,1)#define npcheck(b) (void)np_promote(b,r1,r2,t1,t2,0) if (tbl->base != TABLE) error('i',"expr.typ(%d)",tbl->base);//if (b == NAME) error('d',"name %d %d %s",this,string,string?string:"?"); if (tp) {/*error('d',"expr.typ %d (checked) tbl=%d",this,tbl);*/ if (b == NAME) Pname(this)->use(); return this; }//error('d',"expr.typ %d%k e1 %d%k e2 %d%k tbl %d\n",this,base,e1,e1?e1->base:0,e2,e2?e2->base:0,tbl); switch (b) { /* is it a basic type */ case DUMMY: error("emptyE"); tp = any_type; return this; case ZERO: tp = zero_type; return this; case IVAL: tp = int_type; return this; case FVAL: tp = float_type; return this; case ICON: /* is it long? explicit long? decimal larger than largest signed int octal or hexadecimal larger than largest unsigned int */ { int ll = strlen(string); switch (string[ll-1]) { case 'l': case 'L': lng: tp = long_type; goto save; } if (string[0] == '0') { /* assume 8 bits in byte */ switch (string[1]) { case 'x': case 'X': if (SZ_INT+SZ_INT < ll-2) goto lng; goto nrm; default: if (BI_IN_BYTE*SZ_INT < (ll-1)*3) goto lng; goto nrm; } } else { if (ll</*sizeof(LARGEST_INT)-1*/10) { nrm: tp = int_type; goto save; } if (ll>10) goto lng; char* p = string; char* q = LARGEST_INT; do if (*p++>*q++) goto lng; while (*p); } goto nrm; } case CCON: tp = char_type; goto save; case FCON: tp = double_type; goto save; case STRING: // type of "as\tdf" is char[6] // c_strlen counts the terminating '\0' { int ll = c_strlen(string); Pvec v = new vec(char_type,0); v->size = ll; tp = v; goto save; } save:/*error('d',"%s const_save %d",string,const_save);*/ if (const_save) { int ll = c_strlen(string); char* p = new char[ll]; strcpy(p,string); string = p; } return this; case THIS: delete this; if (cc->tot) { cc->c_this->use(); return cc->c_this; } error("this used in nonC context"); n = new name("this"); n->tp = any_type; return tbl->insert(n,0); case NAME:/*error('d',"name %s",string);*/ { Pexpr ee = tbl->find_name((Pname)this,0,0); if (ee->tp->base == RPTR) return ee->contents(); return ee; } case SIZEOF: t = tp2; if (t) { t->dcl(tbl); if (e1 && e1!=dummy) { e1 = e1->typ(tbl); DEL(e1); e1 = dummy; } } else { e1 = e1->typ(tbl); tp2 = e1->tp; } tp = int_type; return this; case CAST: { Ptype tt = t = tp2; tt->dcl(tbl); zaq: /* is the cast legal? *///error('d',"tt %d %d",tt,tt?tt->base:0); switch (tt->base) { case TYPE: tt = Pbase(tt)->b_name->tp; goto zaq; case RPTR: // necessary? case PTR: if (Pptr(tt)->rdo) error("*const in cast"); tt = Pptr(tt)->typ; goto zaq; case VEC: tt = Pvec(tt)->typ; goto zaq; case FCT: tt = Pfct(tt)->returns; goto zaq; default: if (Pbase(tt)->b_const) error("const in cast"); } /* now check cast against value, INCOMPLETE *///error('d',"cast e1 %d %k",e1,e1->base); tt = t; if (e1 == dummy) { error("expression missing for cast"); tp = any_type; return this; } e1 = e1->typ(tbl); Ptype etp = e1->tp; while (etp->base == TYPE) etp = Pbase(etp)->b_name->tp; if (etp->base == COBJ) { int i = can_coerce(tt,etp);//error('d',"cast%t->%t -- %d%n",tt,etp,i,Ncoerce); if (i==1 && Ncoerce) { Pname cn = Pbase(etp)->b_name; Pclass cl = Pclass(cn->tp); Pref r = new ref(DOT,e1,Ncoerce); Pexpr rr = r->typ(tbl); Pexpr c = new expr(G_CALL,rr,0); c->fct_name = Ncoerce; c->tp = tt; *this = *Pexpr(c);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -