📄 decl.cc
字号:
/* file "decl.cc" *//* Copyright (c) 1994 Stanford University All rights reserved. This software is provided under the terms described in the "suif_copyright.h" include file. */#include <suif_copyright.h>/* snoot declaration parsing */#include "c.h"Symbol cfunc = NULL; /* current function */char *fname = NULL; /* current function name */static boolean funcdclr; /* declarator has parameters */static int nglobals; /* number of external ids */static void checklab(Symbol p, Generic);static void checkparam(Symbol p, Generic);static void checkref(Symbol p, Generic);static Symbol dclglobal(int sclass, char *id, type_node *ty, Coordinate *pos);static Symbol dcllocal(int sclass, char *id, type_node *ty, Coordinate *pos);static Symbol dclparam(int sclass, char *id, type_node *ty, Coordinate *pos);static type_node *dclr(type_node *basety, char **id, int lev);static type_node *dclr1(char **id, int lev);static void decl(Symbol (*dcl)(int, char *, type_node *, Coordinate *), boolean eflag);static void doglobal(Symbol p, Generic);static void doextern(Symbol p, Generic);static enum_type *enumdecl(void);static void fields(struct_type *to_fill);static void funcdecl(int sclass, char *id, func_type *ftype, Coordinate pt);static func_type *newstyle(func_type *ty, type_node *caller_types[], Symbol callee[]);static void oldparam(Symbol p, Generic cl);static func_type *oldstyle(char *name, func_type *ty, type_node *caller_types[], Symbol callee[]);static type_node **parameters(int lev);static struct_type *structdcl(int op);static type_node *parse_type(int lev, int *sclass);static boolean control_reaches_list_end(tree_node_list *node_list);/* checklab - check for undefined labels; called at ends of functions */static void checklab(Symbol p, Generic) { if (!p->defined) error("undefined label `%s'\n", p->name); p->defined = 1; }/* checkref - check for unreferenced variables; called at ends of blocks */static void checkref(Symbol p, Generic) { if ((Aflag >= 2) && p->defined && (p->ref == 0)) { if (p->sclass == STATIC) warning("static `%t %s' is not referenced\n", p->type, p->name); else if (p->scope == PARAM) warning("parameter `%t %s' is not referenced\n", p->type, p->name); else if ((p->scope > PARAM) && (p->sclass != EXTERN)) warning("local `%t %s' is not referenced\n", p->type, p->name); } Symbol q; if ((p->scope > PARAM) && (q = lookup(p->name, externals))) { q->ref += p->ref; } else if ((p->sclass == STATIC) && !p->defined) { if (p->ref > 0) { error("undefined static `%t %s'\n", p->type, p->name); } else if (isfunc(p->type)) { warning("undefined static `%t %s'\n", p->type, p->name); /* * In SUIF it is illegal to have a procedure in the file symbol * table without a body, so we must remove this symbol. */ sym_node *the_symbol = p->suif_symbol; assert(the_symbol != NULL); the_symbol->parent()->remove_sym(the_symbol); delete the_symbol; p->suif_symbol = NULL; } } if (xref) annotate_with_refs(p); }/* compound - { ( decl ; )* statement* } */void compound(label_sym *continue_lab, label_sym *break_lab, struct swtch *swp, int lev) { enterscope(); ++bnumber; stabblock('{'); expect('{'); while ((kind[t] == CHAR) || (kind[t] == STATIC) || ((t == ID) && (tsym != NULL) && (tsym->sclass == TYPEDEF) && ((level < LOCAL) || (getchr() != ':')))) { decl(dcllocal, FALSE); } while ((kind[t] == IF) || (kind[t] == ID)) statement(continue_lab, break_lab, swp, lev); foreach(identifiers, level, checkref, NULL); stabblock('}'); if (level > LOCAL) { exitscope(); expect('}'); } }/* dclglobal - called from decl to declare a global */static Symbol dclglobal(int sclass, char *id, type_node *ty, Coordinate *pos) { if ((sclass == 0) || (sclass == REGISTER)) sclass = AUTO; Symbol p = lookup(id, identifiers); if ((p != NULL) && (p->scope == GLOBAL)) { if ((p->sclass != TYPEDEF) && eqtype(ty, p->type, TRUE)) { ty = composite(ty, p->type); } else { error("redeclaration of `%s' previously declared at %w\n", p->name, &p->src); } if (!isfunc(ty) && p->defined && (t == '=')) { error("redefinition of `%s' previously defined at %w\n", p->name, &p->src); } if (((p->sclass == STATIC) && (sclass == AUTO)) || ((p->sclass != STATIC) && (sclass == STATIC))) { warning("inconsistent linkage for `%s' previously declared at" " %w\n", p->name, &p->src); } } else if ((sclass == STATIC) && !isfunc(ty) && (ty->size() == 0) && (t != '=')) { warning("undefined size for static `%t %s'\n", ty, id); } if ((p == NULL) || (p->scope != GLOBAL)) p = install(id, &globals, 1); p->type = ty; Symbol q = lookup(p->name, externals); if (q != NULL) { p->ref += q->ref; p->suif_symbol = q->suif_symbol; } if (p->suif_symbol != NULL) { if (isfunc(ty)) { assert(p->suif_symbol->is_proc()); func_type *the_func_type = (func_type *)(ty->unqual()); proc_sym *the_proc = (proc_sym *)(p->suif_symbol); boolean vis = the_proc->parent()->make_type_visible(the_func_type); assert(vis); the_proc->set_type(the_func_type); } else { assert(p->suif_symbol->is_var()); var_sym *the_var = (var_sym *)(p->suif_symbol); boolean vis = the_var->parent()->make_type_visible(p->type); assert(vis); the_var->set_type(p->type); } } if ((p->sclass == 0) || ((sclass != EXTERN) && (p->sclass != STATIC))) { p->sclass = sclass; } if (p->sclass != STATIC) { nglobals++; if ((Aflag >= 2) && (nglobals == 512)) warning("more than 511 external identifiers\n"); } p->src = *pos; if ((!p->defined) && (p->suif_symbol == NULL)) defsymbol(p); if (q != NULL) { if ((((p->sclass == AUTO) ? (unsigned char)EXTERN : p->sclass) != q->sclass) || !eqtype(p->type, q->type, TRUE)) { warning("declaration of `%s' does not match previous declaration" " at %w\n", p->name, &q->src); } } if (!isfunc(p->type)) { initglobal(p, FALSE); } else if (t == '=') { error("illegal initialization for `%s'\n", p->name); t = gettok(); initializer(NULL, p->type, 0); } return p; }/* dcllocal - called from decl to declare a local */static Symbol dcllocal(int sclass, char *id, type_node *ty, Coordinate *pos) { if (isfunc(ty)) { if ((sclass != 0) && (sclass != EXTERN)) error("invalid storage class `%k' for `%t %s'\n", sclass, ty, id); sclass = EXTERN; } else if (sclass == 0) { sclass = AUTO; } if ((sclass == REGISTER) && (isvolatile(ty) || isstruct_or_union(ty) || isarray(ty))) { warning("register declaration ignored for `%t %s'\n", ty, id); sclass = AUTO; } Symbol q = lookup(id, identifiers); if ((q != NULL) && ((q->scope >= level) || ((q->scope == PARAM) && (level == PARAM+1)))) { if ((sclass == EXTERN) && (q->sclass == EXTERN) && eqtype(q->type, ty, TRUE)) { ty = composite(ty, q->type); } else { error("redeclaration of `%s' previously declared at %w\n", q->name, &q->src); } } assert(level >= LOCAL); Symbol p = install(id, &identifiers, 0); p->type = ty; p->sclass = sclass; p->src = *pos; switch (sclass) { case EXTERN: { if ((q != NULL) && (q->scope == GLOBAL) && (q->sclass == STATIC)) { p->sclass = STATIC; p->scope = level; } defsymbol(p); Symbol r = lookup(id, externals); if (r == NULL) { r = install(p->name, &externals, 1); r->src = p->src; r->type = p->type; r->sclass = p->sclass; r->suif_symbol = p->suif_symbol; q = lookup(id, globals); if ((q != NULL) && (q->sclass != TYPEDEF) && (q->sclass != ENUM)) { r = q; } } if ((r != NULL) && ((((r->sclass == AUTO) ? (unsigned char)EXTERN : r->sclass) != p->sclass) || !eqtype(r->type, p->type, TRUE))) { warning("declaration of `%s' does not match previous " "declaration at %w\n", r->name, &r->src); } break; } case STATIC: defsymbol(p); initglobal(p, FALSE); if (!p->defined) { if (p->type->size() > 0) (void)defglobal(p); else error("undefined size for `%t %s'\n", p->type, p->name); } p->defined = 1; break; case REGISTER: case AUTO: { var_sym *the_var_sym = get_current_symtab()->new_var(p->type, p->name); if (sclass == REGISTER) the_var_sym->append_annote(k_is_declared_reg, new immed_list); the_var_sym->set_userdef(); p->suif_symbol = the_var_sym; p->defined = 1; break; } default: assert(FALSE); } if (t == '=') { if (sclass == EXTERN) error("illegal initialization of `extern %s'\n", id); t = gettok(); definept(NULL); genop e; if (isscalar(p->type) || (isstruct_or_union(p->type) && (t != '{'))) { if (t == '{') { t = gettok(); e = constexpr(0); (void)genconst(NULL, e, FALSE); expect('}'); } else { e = expr1(0); } e = pointer(e); type_node *new_type = assign(p->type, e); if (new_type != NULL) { e = cast(e, new_type); } else { error("invalid initialization type; found `%t' expected " "`%t'\n", e.type(), p->type); } } else { type_node *ty = p->type; boolean constified = FALSE; if (!isconst(ty) && (!isarray(ty) || !isconst(base_from_array(ty)))) { ty = qual(CONST, ty); constified = TRUE; } var_sym *new_var = gen_static_global(ty); var_def *the_def = begin_initialization(new_var); ty = initializer(the_def, new_var->type(), 0); if (isarray(new_var->type()) && new_var->type()->size() == 0) new_var->set_type(ty); if (isarray(p->type) && (p->type->size() == 0) && (new_var->type()->size() > 0)) { int new_size = new_var->type()->size() / base_from_array(new_var->type())->size(); assert(p->suif_symbol != NULL); assert(p->suif_symbol->is_var()); var_sym *p_var = (var_sym *)(p->suif_symbol); p_var->set_type(build_array(base_from_array(p->type), new_size)); p->type = p_var->type(); } /* If it's an array and we changed the type to be an array * of constant elements, we can't do a simple copy because * the types will conflict, so we do an explicit load in * that case. */ if (isarray(ty) && constified) { operand address_op = operand(new in_ldc(ty->ptr_to(), operand(), immed(new_var))); operand convert_op = operand(new in_rrr(io_cvt, p->type->ptr_to(), operand(), address_op)); in_rrr *new_load = new in_rrr(io_lod, p->type, operand(), convert_op); e = genop(operand(new_load), new tree_node_list); } else { e = sym_node_to_genop(new_var); } } e.clean_up_bit_field_refs(); tree_node_list *precomputation = e.precomputation(); operand r_op = e.suif_operand(); curr_list->append(precomputation); delete precomputation; assert(p->suif_symbol->is_var()); tree_node *new_assignment = create_assignment(((var_sym *)p->suif_symbol), r_op); curr_list->append(new_assignment); p->initialized = 1; p->ref = 0; } if (!isfunc(p->type) && p->defined && (p->type->size() <= 0)) error("undefined size for `%t %s'\n", p->type, id); return p; }/* dclparam - called from decl to declare a parameter */static Symbol dclparam(int sclass, char *id, type_node *ty, Coordinate *pos) { Symbol p = lookup(id, identifiers); if ((p != NULL) && (p->scope == level) && (p->defined || ((p->type == NULL) && (ty == NULL)))) { error("duplicate definition for `%s' previously declared at %w\n", id, &p->src); } else if ((p == NULL) || (p->scope < level)) { p = install(id, &identifiers, 0); } if ((ty != NULL) && isfunc(ty)) ty = ty->ptr_to(); else if ((ty != NULL) && isarray(ty)) ty = atop(ty); if (sclass == 0) sclass = AUTO; if ((sclass == REGISTER) && (ty != NULL) && (isvolatile(ty) || isstruct_or_union(ty))) { warning("register declaration ignored for `%t%s\n", ty, stringf(id ? (char *) " %s'" : (char *) "' parameter", id)); sclass = AUTO; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -