123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474 |
- /*
- * (c) copyright 1987 by the Vrije Universiteit, Amsterdam, The Netherlands.
- * See the copyright notice in the ACK home directory, in the file "Copyright".
- */
- /* $Id$ */
- /* P R O T O T Y P E F I D D L I N G */
- #include "lint.h"
- #include "debug.h"
- #include "idfsize.h"
- #include "nparams.h"
- #include "botch_free.h"
- #include <alloc.h>
- #include "Lpars.h"
- #include "level.h"
- #include <flt_arith.h>
- #include "arith.h"
- #include "align.h"
- #include "stack.h"
- #include "idf.h"
- #include "def.h"
- #include "type.h"
- #include "struct.h"
- #include "label.h"
- #include "expr.h"
- #include "declar.h"
- #include "decspecs.h"
- #include "proto.h"
- #include "assert.h"
- extern char options[];
- check_for_void(pl)
- register struct proto *pl;
- {
- register int errcnt = 0;
- if (!pl) return;
- if ((pl->pl_flag & PL_VOID) && !(pl->next)) return;
- while (pl) {
- if (pl->pl_flag & PL_VOID) {
- if (!errcnt && !(pl->pl_flag & PL_ERRGIVEN))
- error("illegal use of void in argument list");
- pl->pl_flag |= PL_ERRGIVEN;
- errcnt++;
- }
- pl = pl->next;
- }
- }
- add_proto(pl, ds, dc, lvl)
- struct proto *pl;
- struct decspecs *ds;
- struct declarator *dc;
- int lvl;
- {
- /* The full typed identifier or abstract type, described
- by the structures decspecs and declarator are turned
- a into parameter type list structure.
- The parameters will be declared at level L_FORMAL2,
- later on it's decided whether they were prototypes
- or actual declarations.
- */
- register struct idf *idf = dc->dc_idf;
- register struct def *def = idf ? idf->id_def : (struct def *)0;
- register int sc = ds->ds_sc;
- register struct type *type;
- char formal_array = 0;
- ASSERT(ds->ds_type != (struct type *)0);
- pl->pl_flag = PL_FORMAL;
- type = declare_type(ds->ds_type, dc);
- if (type->tp_size < (arith)0 && actual_declaration(sc, type)) {
- extern char *symbol2str();
- if (type->tp_fund != VOID)
- error("unknown %s-type", symbol2str(type->tp_fund));
- else {
- if (idf != (struct idf *)0
- || ds->ds_sc_given
- || ds->ds_typequal) {
- error("illegal use of void in argument list");
- pl->pl_flag |= PL_ERRGIVEN;
- }
- /* set PL_VOID anyway */
- pl->pl_flag |= PL_VOID;
- }
- }
- if (ds->ds_sc_given && ds->ds_sc != REGISTER) {
- if (!(pl->pl_flag & PL_ERRGIVEN)) {
- if (ds->ds_sc != AUTO) {
- error("illegal storage class in parameter declaration");
- } else {
- warning("illegal storage class in parameter declaration");
- }
- }
- }
- /* Perform some special conversions for parameters.
- */
- if (type->tp_fund == FUNCTION) {
- type = construct_type(POINTER, type, 0, (arith) 0, NO_PROTO);
- } else if (type->tp_fund == ARRAY) {
- type = construct_type(POINTER, type->tp_up, 0, (arith) 0, NO_PROTO);
- formal_array = 1;
- }
- /* According to the standard we should ignore the storage
- class of a parameter, unless it's part of a function
- definition.
- However, in the routine declare_protos we don't know decspecs,
- and therefore we can't complain up there. So we build up the
- storage class, and keep quiet until we reach declare_protos.
- */
- sc = (ds->ds_sc_given && ds->ds_sc != REGISTER) ?
- 0 : sc == 0 ? FORMAL : REGISTER;
- if (def && (def->df_level == lvl /* || def->df_level < L_PROTO */ )) {
- /* redeclaration at the same level */
- error("parameter %s redeclared", idf->id_text);
- } else if (idf != (struct idf *)0) {
- /* New definition, redefinition hides earlier one
- */
- register struct def *newdef = new_def();
-
- newdef->next = def;
- newdef->df_level = lvl;
- newdef->df_sc = sc;
- newdef->df_type = type;
- newdef->df_formal_array = formal_array;
- newdef->df_file = idf->id_file;
- newdef->df_line = idf->id_line;
- #ifdef LINT
- newdef->df_set = (type->tp_fund == ARRAY);
- /* newdef->df_firstbrace = 0; */
- #endif
- /* We can't put the idf onto the stack, since these kinds
- of declaration may occurs at any level, and the idf
- does not necessarily go at this level. E.g.
- f() {
- ...
- { int func(int a, int b);
- ...
- }
- }
- The idf's a and b declared in the prototype declaration
- do not go at any level, they are simply ignored.
- However, in
- f(int a, int b) {
- ...
- }
- They should go at level L_FORMAL2. But at this stage
- we don't know whether we have a prototype or function
- definition. So, this process is postponed.
- */
- idf->id_def = newdef;
- update_ahead(idf);
- }
- pl->pl_idf = idf;
- pl->pl_type = type;
- }
- struct tag *
- gettag(tp, idpp)
- struct type *tp;
- struct idf **idpp;
- {
- struct tag *tg = (struct tag *)0;
- register int fund = tp->tp_fund;
- while (fund == FIELD || fund == POINTER
- || fund == ARRAY || fund == FUNCTION) {
- tp = tp->tp_up;
- fund = tp->tp_fund;
- }
- *idpp = tp->tp_idf;
- switch(tp->tp_fund) {
- case ENUM:
- case UNION:
- case STRUCT: tg = tp->tp_idf->id_tag; break;
- }
- return tg;
- }
- declare_protos(dc)
- register struct declarator *dc;
- {
- /* At this points we know that the idf's in protolist are formal
- parameters. So it's time to declare them at level L_FORMAL2.
- */
- struct stack_level *stl = stack_level_of(L_FORMAL1);
- register struct decl_unary *du;
- register struct type *type;
- register struct proto *pl;
- register struct def *def;
- #ifdef DEBUG
- if (options['t'])
- dumpidftab("start declare_protos", 0);
- #endif /* DEBUG */
- du = dc->dc_decl_unary;
- while (du) {
- if (du->du_fund == FUNCTION) {
- if (du->next != (struct decl_unary *) 0) {
- remove_proto_idfs(du->du_proto);
- du->du_proto = 0;
- } else break;
- }
- du = du->next;
- }
- pl = du ? du->du_proto : NO_PROTO;
- if (pl) {
- #if 0 /* the id_proto member is deleted (???) */
- idf->id_proto = 0;
- #endif /* 0 */
- do {
- struct tag *tg;
- struct idf *idp = 0;
- type = pl->pl_type;
- /* `...' only for type checking */
- if (pl->pl_flag & PL_ELLIPSIS) {
- pl = pl->next;
- continue;
- }
- /* special case: int f(void) { ; } */
- if (type->tp_fund == VOID)
- break;
- if (!pl->pl_idf || !(def = pl->pl_idf->id_def)) {
- error("no parameter identifier supplied");
- pl = pl->next;
- continue;
- }
- /* Postponed storage class checking.
- */
- if (def->df_sc == 0)
- error("illegal storage class in parameter declaration");
- def->df_level = L_FORMAL2;
- stack_idf(pl->pl_idf, stl);
- pl = pl->next;
- tg = gettag(type, &idp);
- if (tg && tg->tg_level <= L_PROTO) {
- tg->tg_level = L_FORMAL2;
- stack_idf(idp, stl);
- }
- } while (pl);
- }
- #ifdef DEBUG
- if (options['t'])
- dumpidftab("end declare_protos", 0);
- #endif /* DEBUG */
- }
- update_proto(tp, otp)
- register struct type *tp, *otp;
- {
- /* This routine performs the proto type updates.
- Consider the following code:
- int f(double g());
- int f(double g(int f(), int));
- int f(double g(int f(long double), int));
- The most accurate definition is the third line.
- This routine will silently update all lists,
- and removes the redundant occupied space.
- */
- register struct proto *pl, *opl;
- if (tp == otp) return;
- if (!tp || !otp) return;
- while (tp->tp_fund != FUNCTION) {
- if (tp->tp_fund != POINTER && tp->tp_fund != ARRAY) return;
- tp = tp->tp_up;
- otp = otp->tp_up;
- if (!tp) return;
- }
- pl = tp->tp_proto;
- opl = otp->tp_proto;
- if (pl && opl) {
- /* both have prototypes */
- while (pl && opl) {
- update_proto(pl->pl_type, opl->pl_type);
- pl = pl->next;
- opl = opl->next;
- }
- /* Do not free the old prototype list. It might be part of
- * a typedef.
- */
- otp->tp_proto = tp->tp_proto;
- } else if (opl) {
- /* old decl has type */
- } else if (pl) {
- otp->tp_proto = pl;
- }
- update_proto(tp->tp_up, otp->tp_up);
- }
- /* struct/union and enum tags can be declared inside prototypes
- * remove them from the symbol-table
- */
- remove_proto_tag(tp)
- struct type *tp;
- {
- register struct idf *ident;
- register struct tag *tgp, **tgpp;
- register int fund = tp->tp_fund;
- while (fund == FIELD || fund == POINTER
- || fund == ARRAY || fund == FUNCTION) {
- tp = tp->tp_up;
- fund = tp->tp_fund;
- }
- ident = tp->tp_idf;
- switch (tp->tp_fund) {
- case ENUM:
- case STRUCT:
- case UNION: tgpp = &(ident->id_tag); break;
- default: return;
- }
- while((*tgpp) && (*tgpp)->tg_type != tp) {
- tgpp = &((*tgpp)->next);
- }
- if (!*tgpp) return;
- tgp = *tgpp;
- if (tgp->tg_level > L_PROTO) return;
- #ifdef DEBUG
- if (options['t'])
- print("Removing idf %s from list\n",
- ident->id_text);
- #endif
- (*tgpp) = tgp->next;
- free_tag(tgp);
- }
- remove_proto_idfs(pl)
- register struct proto *pl;
- {
- /* Remove all the identifier definitions from the
- prototype list.
- */
- register struct def *def;
- while (pl) {
- if (pl->pl_idf) {
- #ifdef DEBUG
- if (options['t'])
- print("Removing idf %s from list\n",
- pl->pl_idf->id_text);
- #endif
- def = pl->pl_idf->id_def;
- if (def && def->df_level <= L_PROTO) {
- pl->pl_idf->id_def = def->next;
- free_def(def);
- }
- pl->pl_idf = (struct idf *) 0;
- }
- if (pl->pl_type) {
- remove_proto_tag(pl->pl_type);
- }
- pl = pl->next;
- }
- }
- call_proto(expp)
- register struct expr **expp;
- {
- /* If the function specified by (*expp)->OP_LEFT has a prototype,
- the parameters are converted according the rules specified in
- par. 3.3.2.2. E.i. the parameters are converted to the prototype
- counter parts as if by assignment. For the parameters falling
- under ellipsis clause the old parameters conversion stuff
- applies.
- */
- register struct expr *left = (*expp)->OP_LEFT;
- register struct expr *right = (*expp)->OP_RIGHT;
- register struct proto *pl = NO_PROTO;
- static struct proto ellipsis = { 0, 0, 0, PL_ELLIPSIS };
- if (left != NILEXPR) { /* in case of an error */
- register struct type *tp = left->ex_type;
- while (tp && tp->tp_fund != FUNCTION && tp != error_type)
- tp = tp->tp_up;
- if (tp && tp->tp_proto)
- pl = tp->tp_proto;
- }
- if (right != NILEXPR) { /* function call with parameters */
- register struct expr **ep = &((*expp)->OP_RIGHT);
- register int ecnt = 0, pcnt = 0;
- struct expr **estack[NPARAMS];
- struct proto *pstack[NPARAMS];
- /* stack up the parameter expressions */
- while (right->ex_class == Oper && right->OP_OPER == PARCOMMA) {
- if (ecnt == STDC_NPARAMS)
- expr_strict(right, "number of parameters exceeds ANSI limit");
- if (ecnt >= NPARAMS-1) {
- expr_error(right, "too many parameters");
- return;
- }
- estack[ecnt++] = &(right->OP_RIGHT);
- ep = &(right->OP_LEFT);
- right = right->OP_LEFT;
- }
- estack[ecnt] = ep;
- /* Declarations like int f(void) do not expect any
- parameters.
- */
- if (pl && pl->pl_flag & PL_VOID) {
- expr_strict(*expp, "no parameters expected");
- pl = NO_PROTO;
- }
- /* stack up the prototypes */
- if (pl) {
- pcnt--;
- do {
- /* stack prototypes */
- pstack[++pcnt] = pl;
- pl = pl->next;
- } while (pl);
- }
- else {
- pstack[0] = &ellipsis;
- }
- for (ecnt; ecnt >= 0; ecnt--) {
- /* Only the parameters specified in the prototype
- are checked and converted. The parameters that
- fall under the ellipsis clause are neither
- checked nor converted !
- */
- if (pcnt < 0) {
- expr_error(*expp, "more parameters than specified in prototype");
- break;
- }
- else if (!(pstack[pcnt]->pl_flag & PL_ELLIPSIS)) {
- ch3cast(estack[ecnt],CASTAB,pstack[pcnt]->pl_type);
- pcnt--;
- } else
- any2parameter(estack[ecnt]);
- }
- if (pcnt > 0 || (pcnt == 0 && !(pstack[0]->pl_flag & PL_ELLIPSIS)))
- expr_error(*expp, "fewer parameters than specified in prototype");
- } else {
- if (pl && !(pl->pl_flag & PL_VOID))
- expr_error(*expp, "fewer parameters than specified in prototype");
- }
- }
|