/* * Get memory for a new tree node. */ tnode_t * getnode(void) { return (tgetblk(sizeof (tnode_t))); }
/* * T_RETURN T_SEMI * T_RETURN expr T_SEMI */ void doreturn(tnode_t *tn) { tnode_t *ln, *rn; cstk_t *ci; op_t op; for (ci = cstk; ci->c_nxt != NULL; ci = ci->c_nxt) continue; if (tn != NULL) { ci->c_retval = 1; } else { ci->c_noretval = 1; } if (tn != NULL && funcsym->s_type->t_subt->t_tspec == VOID) { /* void function %s cannot return value */ error(213, funcsym->s_name); tfreeblk(); tn = NULL; } else if (tn == NULL && funcsym->s_type->t_subt->t_tspec != VOID) { /* * Assume that the function has a return value only if it * is explicitly declared. */ if (!funcsym->s_rimpl) /* function %s expects to return value */ warning(214, funcsym->s_name); } if (tn != NULL) { /* Create a temporary node for the left side */ ln = tgetblk(sizeof (tnode_t)); ln->tn_op = NAME; ln->tn_type = tduptyp(funcsym->s_type->t_subt); ln->tn_type->t_const = 0; ln->tn_lvalue = 1; ln->tn_sym = funcsym; /* better than nothing */ tn = build(RETURN, ln, tn); if (tn != NULL) { rn = tn->tn_right; while ((op = rn->tn_op) == CVT || op == PLUS) rn = rn->tn_left; if (rn->tn_op == AMPER && rn->tn_left->tn_op == NAME && rn->tn_left->tn_sym->s_scl == AUTO) { /* %s returns pointer to automatic object */ warning(302, funcsym->s_name); } } expr(tn, 1, 0); } else { chkreach(); } reached = rchflg = 0; }
void mkinit(tnode_t *tn) { ptrdiff_t offs; sym_t *sym; tspec_t lt, rt; tnode_t *ln; struct mbl *tmem; scl_t sc; if (initerr || tn == NULL) goto end; sc = initsym->s_scl; /* * Do not test for automatic aggregat initialisation. If the * initializer starts with a brace we have the warning already. * If not, an error will be printed that the initializer must * be enclosed by braces. */ /* * Local initialisation of non-array-types with only one expression * without braces is done by ASSIGN */ if ((sc == AUTO || sc == REG) && initsym->s_type->t_tspec != ARRAY && initstk->i_nxt == NULL) { ln = getnnode(initsym, 0); ln->tn_type = tduptyp(ln->tn_type); ln->tn_type->t_const = 0; tn = build(ASSIGN, ln, tn); expr(tn, 0, 0); goto end; } /* * Remove all entries which cannot be used for further initializers * and do not require a closing brace. */ popinit(0); /* Initialisations by strings are done in strginit(). */ if (strginit(tn)) goto end; nextinit(0); if (initerr || tn == NULL) goto end; initstk->i_cnt--; /* Create a temporary node for the left side. */ ln = tgetblk(sizeof (tnode_t)); ln->tn_op = NAME; ln->tn_type = tduptyp(initstk->i_type); ln->tn_type->t_const = 0; ln->tn_lvalue = 1; ln->tn_sym = initsym; /* better than nothing */ tn = cconv(tn); lt = ln->tn_type->t_tspec; rt = tn->tn_type->t_tspec; if (!issclt(lt)) lerror("mkinit() 1"); if (!typeok(INIT, 0, ln, tn)) goto end; /* * Store the tree memory. This is nessesary because otherwise * expr() would free it. */ tmem = tsave(); expr(tn, 1, 0); trestor(tmem); if (isityp(lt) && ln->tn_type->t_isfield && !isityp(rt)) { /* * Bit-fields can be initialized in trad. C only by integer * constants. */ if (tflag) /* bit-field initialisation is illegal in trad. C */ warning(186); } if (lt != rt || (initstk->i_type->t_isfield && tn->tn_op == CON)) tn = convert(INIT, 0, initstk->i_type, tn); if (tn != NULL && tn->tn_op != CON) { sym = NULL; offs = 0; if (conaddr(tn, &sym, &offs) == -1) { if (sc == AUTO || sc == REG) { /* non-constant initializer */ (void)gnuism(177); } else { /* non-constant initializer */ error(177); } } } end: tfreeblk(); }