📄 decl.cc
字号:
if (p->type->unqual() == floattype) caller_types[i] = doubletype; else caller_types[i] = promote(p->type); } unsigned num_params = i; if (((p = lookup(name, identifiers)) != NULL) && (p->scope == GLOBAL) && isfunc(p->type) && ((func_type *)(p->type->unqual()))->args_known()) { func_type *the_func_type = (func_type *)(p->type->unqual()); base_symtab *owning_symtab = the_func_type->parent(); the_func_type = (func_type *)(the_func_type->copy()); unsigned arg_num; for (arg_num = 0; (arg_num < num_params) && (arg_num < the_func_type->num_args()); arg_num++) { unsigned ft_arg_num = (num_params - arg_num) - 1; if (!eqtype(the_func_type->arg_type(ft_arg_num)->unqual(), caller_types[arg_num]->unqual(), TRUE)) { warning("conflicting declarations of argument %u of function " "`%s'\n", ft_arg_num + 1, name); caller_types[arg_num] = the_func_type->arg_type(ft_arg_num); } } if ((num_params < the_func_type->num_args()) || ((num_params > the_func_type->num_args()) && (!the_func_type->has_varargs()))) { error("conflicting argument declarations for function `%s'\n", name); } the_func_type->set_return_type(freturn(ty)); assert(((suif_object *)(the_func_type))->object_kind() == TYPE_OBJ); ty = (func_type *)(owning_symtab->install_type(the_func_type)); } else { base_symtab *owning_symtab = ty->parent(); ty = new func_type(freturn(ty)); ty = (func_type *)(owning_symtab->install_type(ty)); } return ty; }/* parameters - [id ( , id )* | type dclr ( , type dclr )*] */static type_node **parameters(int lev) { type_node **proto = NULL; enterscope(); if ((kind[t] == CHAR) || (kind[t] == STATIC) || ((t == ID) && (tsym != NULL) && (tsym->sclass == TYPEDEF))) { int sclass; int n = 0; type_node *last = NULL; type_node *ty; List list = NULL; for (;;) { char *id = NULL; n++; if ((last != NULL) && (t == ELLIPSIS)) { if (last == voidtype) error("illegal formal parameter types\n"); list = append(voidtype, list); t = gettok(); break; } if (((t == ID) && ((tsym == NULL) || (tsym->sclass != TYPEDEF))) || ((t != ID) && (t != REGISTER) && (kind[t] != CHAR))) { error("missing parameter type\n"); } ty = dclr(parse_type(PARAM, &sclass), &id, lev + 1); if ((Aflag >= 1) && !hasproto(ty)) warning("missing prototype\n"); if ((ty == voidtype) && ((last != NULL) || (id != NULL))) error("illegal formal parameter types\n"); if (id == NULL) id = stringd(n); if (ty == voidtype) { list = append(voidtype, list); } else { Symbol p = dclparam(sclass, id, ty, &src); list = append(p->type, list); } last = ty; if (t != ',') break; t = gettok(); } proto = new type_node *[n + 1]; proto = (type_node **)ltoa(list, (Generic *)proto); } else if (t == ID) { for (;;) { if (t != ID) { error("expecting an identifier\n"); break; } dclparam(0, token, NULL, &src); t = gettok(); if (t != ',') break; t = gettok(); } } if (t != ')') { static char follow[] = { CHAR, STATIC, IF, ')', 0 }; expect(')'); skipto('{', follow); } if (t == ')') t = gettok(); return proto; }/* checkparam - check for old-style param list; called at ends of parameters */static void checkparam(Symbol p, Generic) { if (p->type == NULL) error("extraneous specification for formal parameter `%s'\n", p->name); }/* program - decl* */void program(void) { int n; level = GLOBAL; for (n = 0; t != EOI; n++) { if ((kind[t] == CHAR) || (kind[t] == STATIC) || (t == ID)) { decl(dclglobal, FALSE); } else { if (t == ';') warning("empty declaration\n"); else error("unrecognized declaration\n"); t = gettok(); } } if (n == 0) warning("empty input file\n"); }/* structdcl - ( struct | union ) ( [ id ] { ( field; )+ } | id ) */static struct_type *structdcl(int op) { char *tag; struct_type *result; Symbol p; Coordinate pos; t = gettok(); if (t == ID) { tag = token; pos = src; t = gettok(); } else { tag = string(""); } if (t == '{') { static char follow[] = { IF, ',', 0 }; Symbol struct_sym = newstruct(op, tag); assert(struct_sym->type->is_struct()); result = (struct_type *)(struct_sym->type); if (*tag != 0) struct_sym->src = pos; t = gettok(); if ((kind[t] == CHAR) || ((t == ID) && (tsym != NULL) && (tsym->sclass == TYPEDEF))) { fields(result); } else { if (t == '}') error("empty %k declaration\n", op); else error("invalid %k field declarations\n", op); } test('}', follow); struct_sym->defined = 1; } else if ((*tag != 0) && ((p = lookup(tag, types)) != NULL) && (((p->type->op() == TYPE_STRUCT) && (op == STRUCT)) || ((p->type->op() == TYPE_UNION) && (op == UNION)))) { if ((t == ';') && (p->scope < level)) (void)newstruct(op, tag); if (xref) use(p, pos); assert(p->type->is_struct()); result = (struct_type *)(p->type); } else { if (*tag == 0) error("missing %k tag\n", op); Symbol struct_sym = newstruct(op, tag); assert(struct_sym->type->is_struct()); result = (struct_type *)(struct_sym->type); if ((*tag != 0) && xref) use(struct_sym, pos); } return result; }/* type - parse basic storage class and type specification */static type_node *parse_type(int lev, int *sclass) { int cls, cons, *p, sign, size, type, vol; tokencode tt; type_node *ty = NULL; boolean class_specifier_given = FALSE; boolean two_longs = FALSE; if (sclass == NULL) cls = AUTO; else *sclass = 0; for (vol = cons = sign = size = type = 0;;) { p = &type; tt = t; switch (t) { case AUTO: case REGISTER: case STATIC: case EXTERN: case TYPEDEF: p = (sclass ? sclass : &cls); if (class_specifier_given) error("only one storage class specifier is allowed"); class_specifier_given = TRUE; break; case CONST: p = &cons; break; case VOLATILE: p = &vol; break; case SIGNED: case UNSIGNED: p = &sign; break; case LONG: case SHORT: p = &size; break; case VOID: case CHAR: case INT: case FLOAT: case DOUBLE: ty = tsym->type; break; case ENUM: ty = enumdecl(); break; case STRUCT: case UNION: ty = structdcl(t); break; case ID: if ((tsym != NULL) && (tsym->sclass == TYPEDEF) && (type == 0) && (size == 0) && (sign == 0)) { use(tsym, src); ty = tsym->type; switch (ty->op()) { case TYPE_INT: tt = INT; break; case TYPE_FLOAT: tt = FLOAT; break; case TYPE_VOID: tt = VOID; break; case TYPE_PTR: tt = POINTER; break; case TYPE_ARRAY: tt = ARRAY; break; case TYPE_FUNC: tt = FUNCTION; break; case TYPE_STRUCT: tt = STRUCT; break; case TYPE_UNION: tt = UNION; break; case TYPE_ENUM: tt = ENUM; break; case TYPE_CONST: tt = CONST; break; case TYPE_VOLATILE: tt = VOLATILE; break; default: assert(FALSE); } t = tt; break; } /* fall through */ default: p = NULL; } if (p == NULL) break; if ((p == &size) && (size == LONG) && (t == LONG) && (!two_longs)) two_longs = TRUE; else if (*p != 0) error("invalid use of `%k'\n", tt); *p = tt; if (t == tt) t = gettok(); } if (two_longs) { static boolean warned = FALSE; if (!warned) { warning("non-ANSI type ``long long int'' used\n"); warned = TRUE; } } if ((sclass != NULL) && (*sclass != 0) && ((lev == 0) || ((lev == PARAM) && (*sclass != REGISTER)) || ((lev == GLOBAL) && (*sclass == REGISTER)))) { error("invalid use of `%k'\n", *sclass); } if (type == 0) { type = INT; ty = inttype; } if (((size == SHORT) && (type != INT)) || ((size == LONG) && (!two_longs) && (type != INT) && (type != DOUBLE)) || ((size == LONG) && two_longs && (type != INT)) || (sign && (type != INT) && (type != CHAR))) { error("invalid type specification\n"); } if ((type == CHAR) && sign) ty = ((sign == UNSIGNED) ? unsignedchar : signedchar); else if (size == SHORT) ty = ((sign == UNSIGNED) ? unsignedshort : shorttype); else if ((size == LONG) && (type == DOUBLE)) ty = longdouble; else if ((size == LONG) && (!two_longs)) ty = ((sign == UNSIGNED) ? unsignedlong : longtype); else if (size == LONG) ty = ((sign == UNSIGNED) ? unsignedlonglong : longlong); else if ((sign == UNSIGNED) && (type == INT)) ty = unsignedtype; if (cons == CONST) ty = qual(CONST, ty); if (vol == VOLATILE) ty = qual(VOLATILE, ty); return ty; }/* get_typename - type dclr */extern type_node *get_typename(void) { type_node *ty = parse_type(0, NULL); if ((t == '*') || (t == '(') || (t == '[')) { ty = dclr(ty, NULL, 1); if ((Aflag >= 1) && !hasproto(ty)) warning("missing prototype\n"); } return ty; }static boolean control_reaches_list_end(tree_node_list *node_list) { if (node_list == NULL) return TRUE; tree_node *last_active = last_action_node(node_list); if (last_active == NULL) return TRUE; switch (last_active->kind()) { case TREE_INSTR: { tree_instr *the_tree_instr = (tree_instr *)last_active; instruction *the_instr = the_tree_instr->instr(); assert(the_instr != NULL); if ((the_instr->opcode() == io_jmp) || (the_instr->opcode() == io_ret) || (the_instr->opcode() == io_mbr)) { return FALSE; } else { return TRUE; } } case TREE_LOOP: return TRUE; case TREE_FOR: return TRUE; case TREE_IF: { tree_if *the_if = (tree_if *)last_active; return (control_reaches_list_end(the_if->then_part()) || control_reaches_list_end(the_if->else_part())); } case TREE_BLOCK: { tree_block *the_block = (tree_block *)last_active; return control_reaches_list_end(the_block->body()); } default: assert(FALSE); } return TRUE; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -