📄 dcl.c
字号:
/* @(#) dcl.c 1.6 1/27/86 17:48:35 */ /*ident "@(#)cfront:src/dcl.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. dcl.c: ``declare'' all names, that is insert them in the appropriate symbol tables. Calculate the size for all objects (incl. stack frames), and find store the offsets for all members (incl. auto variables). "size.h" holds the constants needed for calculating sizes. Note that (due to errors) functions may nest*****************************************************************************/#include "cfront.h"#include "size.h"class dcl_context ccvec[MAXCONT], * cc = ccvec;int byte_offset;int bit_offset;int max_align;int stack_size;int enum_count;int friend_in_class = 0;void name.check_oper(Pname cn)/* check declarations of operators, ctors, dtors*/{ switch (n_oper) { case CALL: if (cn == 0) error("operator() must be aM"); break; case DEREF: if (cn == 0) error("operator[] must be aM"); break; case 0: case TNAME: /* may be a constructor */ if (cn && strcmp(cn->string,string)==0) { if (tp->base == FCT) { Pfct f = (Pfct)tp; if (f->returns!=defa_type && fct_void==0) error("%s::%s() with returnT",string,string); f->returns = void_type; string = "_ctor"; n_oper = CTOR; } else error('s',"struct%cnM%n",cn,cn); } else n_oper = 0; break; case DTOR: /* must be a destructor */ if (cn == 0) { n_oper = 0; error("destructor ~%s() not inC",string); } else if (strcmp(cn->string,string) == 0) { Pfct f = (Pfct)tp; string = "_dtor"; if (tp->base != FCT) { error("%s::~%s notF",cn->string,cn->string); tp = new fct(void_type,0,1); } else if (f->returns!=defa_type && fct_void==0) error("%s::~%s() with returnT",cn->string,cn->string); if (f->argtype) { if (fct_void==0) error("%s::~%s() withAs",cn->string,cn->string); f->nargs = 0; f->nargs_known = 1; f->argtype = 0; } f->returns = void_type; } else { error("~%s in %s",string,cn->string); n_oper = 0; } break; case TYPE: if (cn == 0) { error("operator%t() not aM",(Ptype)n_initializer); n_oper = 0; n_initializer = 0; } else { Pfct f = (Pfct)tp; Ptype tx = (Ptype)n_initializer;/*error('d',"operator%t()",tx);*/ n_initializer = 0; if (f->base != FCT) error("badT for%n::operator%t()",cn,tx); if (f->returns != defa_type) { if (f->returns->check(tx,0)) error("bad resultT for%n::operator%t()",cn,tx); DEL(f->returns); } if (f->argtype) { error("%n::operator%t() withAs",cn,tx); f->argtype = 0; } f->returns = tx; Pname nx = tx->is_cl_obj(); if (nx && can_coerce(tx,cn->tp)) error("both %n::%n(%n) and %n::operator%t()",cn,cn,nx,tx); char buf[128]; char* bb = tx->signature(buf); int l2 = bb-buf-1; char* p = new char[l2+3]; p[0] = '_'; p[1] = 'O'; strcpy(p+2,buf); string = p; } break; }}Pname name.dcl(Ptable tbl, TOK scope)/* enter a copy of this name into symbol table "tbl"; - create local symbol tables as needed "scope" gives the scope in which the declaration was found - EXTERN, FCT, ARG, PUBLIC, or 0 Compare "scope" with the specified storage class "n_sto" - AUTO, STATIC, REGISTER, EXTERN, OVERLOAD, FRIEND, or 0 After name.dcl() n_stclass == 0 class or enum member REGISTER auto variables declared register AUTO auto variables not registers STATIC statically allocated object n_scope == 0 private class member PUBLIC public class member EXTERN name valid in this and other files STATIC name valid for this file only FCT name local to a function ARG name of a function argument ARGT name of a type defined in an argument list typecheck function bodies; typecheck initializers; note that functions (error recovery) and classes (legal) nest The return value is used to chain symbol table entries, but cannot be used for printout because it denotes the sum of all type information for the name names of typenames are marked with n_oper==TNAME WARNING: The handling of scope and storage class is cursed!*/{ Pname nn; Ptype nnt = 0; Pname odcl = Cdcl; if (this == 0) error('i',"0->name.dcl()"); if (tbl == 0) error('i',"%n->name.dcl(tbl=0,%k)",this,scope); if (tbl->base != TABLE) error('i',"%n->name.dcl(tbl=%d,%k)",this,tbl->base,scope); if (tp == 0) error('i',"name.dcl(%n,%k)T missing",this,scope);/*fprintf(stderr,"(%d %s)->dcl(tbl=%d,scope=%d) tp = (%d %d)\n",this,string,tbl,scope,tp,tp->base); fflush(stderr);*/ Cdcl = this; switch (base) { case TNAME: tp->dcl(tbl); PERM(tp); nn = new name(string); nn->base = TNAME; nn->tp = tp; tbl->insert(nn,0); delete nn; Cdcl = odcl; return this; case NAME: switch (n_oper) { case TNAME: if (tp->base != FCT) n_oper = 0; break; case COMPL: if (tp->base != FCT) { error("~%s notF",string); n_oper = 0; } break; } break; default: error('i',"NX in name.dcl()"); } if (n_qualifier) { /* class function: c::f(); */ if (tp->base != FCT) { error("QdN%n inD of nonF",this); Cdcl = odcl; return 0; } Pname cn = n_qualifier; switch (cn->base) { case TNAME: break; case NAME: cn = gtbl->look(cn->string,0); if (cn && cn->base==TNAME) break; default: error("badQr%n for%n",n_qualifier,this); Cdcl = odcl; return 0; } cn = Pbase(cn->tp)->b_name; if (n_oper) check_oper(cn); Pclass cl = (Pclass)cn->tp; if (cl == cc->cot) { n_qualifier = 0; goto xdr; } else if ((cl->defined&(DEFINED|SIMPLIFIED)) == 0) { error("C%nU",cn); Cdcl = odcl; return 0; } Ptable etbl = cl->memtbl; Pname x = etbl->look(string,0); if(x==0 || x->n_table!=etbl) { error("%n is not aM of%n",this,cn); Cdcl = odcl; return 0; } }xdr: if (n_oper && tp->base!=FCT && n_sto!=OVERLOAD) error("operator%k not aF",n_oper); /* if a storage class was specified check that it is legal in the scope else provide default storage class some details must be left until the type of the object is known */ n_stclass = n_sto; n_scope = scope; /* default scope & storage class */ switch (n_sto) { default: error('i',"unX %k",n_sto); case FRIEND: { Pclass cl = cc->cot; switch (scope) { case 0: case PUBLIC: break; default: error("friend%n not in classD(%k)",this,scope); base = 0; Cdcl = odcl; return 0; } switch (n_oper) { case 0: case NEW: case DELETE: case CTOR: case DTOR: case TYPE: n_sto = 0; break; default: n_sto = OVERLOAD; } switch (tp->base) { /* case INT: undefined: implicitly define as class nn = tname(CLASS); nn->tp->dcl(gtbl); break; */ case COBJ: nn = Pbase(tp)->b_name; break; case CLASS: nn = this; break; case FCT: cc->stack(); cc->not = 0; cc->tot = 0; cc->cot = 0; friend_in_class++; n_sto = EXTERN; nn = dcl(gtbl,EXTERN); friend_in_class--;/*fprintf(stderr,"ff %s %d\n",nn->string,nn->tp->base);*/ cc->unstack(); if (nn->tp->base == OVERLOAD) { Pgen g = (Pgen)nn->tp; nn = g->find( (Pfct)tp ); } break; default: error("badT%t of friend%n",tp,this); } PERM(nn); cl->friend_list = new name_list(nn,cl->friend_list); Cdcl = odcl; return nn; } case OVERLOAD: n_sto = 0; switch (scope) { case 0: case PUBLIC: error('w',"overload inCD (ignored)"); switch (tp->base) { case INT: base = 0; Cdcl = odcl; return this; case FCT: return dcl(tbl,scope); } } if (n_oper && tp->base==FCT) break; nn = tbl->insert(this,0); if (Nold) { if (nn->tp->base != OVERLOAD) { error("%n redefined as overloaded",this); nn->tp = new gen(string); } } else { nn->tp = new gen(string); } switch (tp->base) { case INT: base = 0; Cdcl = odcl; return nn; case FCT: break; default: error("N%n ofT%k cannot be overloaded",this,tp->base); Cdcl = odcl; return nn; } break; case REGISTER: if (tp->base == FCT) { error('w',"%n: register (ignored)",this); goto ddd; } case AUTO: switch (scope) { case 0: case PUBLIC: case EXTERN: error("%k not inF",n_sto); goto ddd; } break; case EXTERN: switch (scope) { case ARG: error("externA"); goto ddd; case 0: case PUBLIC: /* extern is provided as a default for functions without body */ if (tp->base != FCT) error("externM%n",this); goto ddd; } n_stclass = STATIC; n_scope = EXTERN; /* avoid FCT scoped externs to allow better checking */ break; case STATIC: switch (scope) { case ARG: error("static used forA%n",this); goto ddd; case 0: case PUBLIC: n_stclass = STATIC; n_scope = scope; break; default: n_scope = STATIC; } break; case 0: ddd: switch (scope) { /* default storage classes */ case EXTERN: n_scope = EXTERN; n_stclass = STATIC; break; case FCT: if (tp->base == FCT) { n_stclass = STATIC; n_scope = EXTERN; } else n_stclass = AUTO; break; case ARG: n_stclass = AUTO; break; case 0: case PUBLIC: n_stclass = 0; break; } } /* now insert the name into the appropriate symbol table, and compare types with previous declarations of that name do type dependent adjustments of the scope */ switch (tp->base) { case ASM: { Pbase b = (Pbase)tp; Pname n = tbl->insert(this,0); n->assign(); n->use(); return this; } case CLASS: { Pclass cl; Pbase bt; Pname bn; // Pclass nest; Pname nx = ktbl->look(string,0); // TNAME//error('d',"%s: nx%n",string,nx); if (nx == 0) { /* search for hidden name for (1) nested class declaration (2) local class declaration */ int tn = 0; for (nx=ktbl->look(string,HIDDEN); nx; nx=nx->n_tbl_list) {//error('d',"%s: nxi%n key%d base%d",string,nx,nx->n_key,nx->tp->base); if (nx->n_key != HIDDEN) continue; if (nx->tp->base != COBJ) { tn = 1; continue; } bt = (Pbase)nx->tp; bn = bt->b_name; cl = (Pclass)bn->tp; if (cl == 0) continue; // if ((nest=cl->in_class) && nest==cc->cot) // goto bbb; // else // if (cc->nof /* fudge */ // && cc->nof->where.line<nx->where.line) goto bbb; } if (tn) error("%n redefined using typedef"); else error('i',"%n is not aCN",this); } else { if (tbl != gtbl) { // careful: local class def//error('d',"%n: local lex level %d",nx->lex_level); if (nx->lex_level == 0) // imperfect error('s',"localC%n and globalC%n",this,nx); } bt = (Pbase)nx->tp; // COBJ bn = bt->b_name; // nest = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -