static Node * comparecomplex(Flattenctx *s, Node *n, Op op) { Type *ty; Node *l, *r, *e; /* special case: unions with nullary constructors can be compared easily. */ ty = tybase(exprtype(n->expr.args[0])); if (ty->type == Tyunion && isenum(ty)) { l = mkexpr(n->loc, Outag, rval(s, n->expr.args[0]), NULL); r = mkexpr(n->loc, Outag, rval(s, n->expr.args[1]), NULL); l->expr.type = mktype(n->loc, Tyuint32); r->expr.type = mktype(n->loc, Tyuint32); if (op == Oeq) e = mkexpr(n->loc, Oueq, l, r, NULL); else if (op == One) e = mkexpr(n->loc, Oune, l, r, NULL); else fatal(n, "unsupported operator %s for enum union", opstr[op]); e->expr.type = mktype(n->loc, Tybool); return e; } fatal(n, "cannot compare values of type %s for equality\n", tystr(exprtype(n->expr.args[0]))); return NULL; }
/* dbxout - output .stabs entry for type ty */ static void dbxout(Type ty) { ty = unqual(ty); if (!ty->x.printed) { int col = 0; print(".stabs \""), col += 8; if (ty->u.sym && !(isfunc(ty) || isarray(ty) || isptr(ty))) print("%s", ty->u.sym->name), col += strlen(ty->u.sym->name); print(":%c", isstruct(ty) || isenum(ty) ? 'T' : 't'), col += 2; emittype(ty, 0, col); print("\",%d,0,0,0\n", N_LSYM); } }
Type assign(Type xty, Tree e) { Type yty = unqual(e->type); xty = unqual(xty); if (isenum(xty)) xty = xty->type; if (xty->size == 0 || yty->size == 0) return NULL; if ( isarith(xty) && isarith(yty) || isstruct(xty) && xty == yty) return xty; if (isptr(xty) && isnullptr(e)) return xty; if ((isvoidptr(xty) && isptr(yty) || isptr(xty) && isvoidptr(yty)) && ( (isconst(xty->type) || !isconst(yty->type)) && (isvolatile(xty->type) || !isvolatile(yty->type)))) return xty; if ((isptr(xty) && isptr(yty) && eqtype(unqual(xty->type), unqual(yty->type), 1)) && ( (isconst(xty->type) || !isconst(yty->type)) && (isvolatile(xty->type) || !isvolatile(yty->type)))) return xty; if (isptr(xty) && isptr(yty) && ( (isconst(xty->type) || !isconst(yty->type)) && (isvolatile(xty->type) || !isvolatile(yty->type)))) { Type lty = unqual(xty->type), rty = unqual(yty->type); if (isenum(lty) && rty == inttype || isenum(rty) && lty == inttype) { if (Aflag >= 1) warning("assignment between `%t' and `%t' is compiler-dependent\n", xty, yty); return xty; } } return NULL; }
Tree calltree(Tree f, Type ty, Tree args, Symbol t3) { Tree p; if (args) f = tree(RIGHT, f->type, args, f); if (isstruct(ty)) assert(t3), p = tree(RIGHT, ty, tree(CALL+B, ty, f, addrof(idtree(t3))), idtree(t3)); else { Type rty = ty; if (isenum(ty)) rty = unqual(ty)->type; if (!isfloat(rty)) rty = promote(rty); p = tree(mkop(CALL, rty), rty, f, NULL); if (isptr(ty) || p->type->size > ty->size) p = cast(p, ty); } return p; }
Tree call(Tree f, Type fty, Coordinate src) { int n = 0; Tree args = NULL, r = NULL, e; Type *proto, rty = unqual(freturn(fty)); Symbol t3 = NULL; if (fty->u.f.oldstyle) proto = NULL; else proto = fty->u.f.proto; if (hascall(f)) r = f; if (isstruct(rty)) { t3 = temporary(AUTO, unqual(rty)); if (rty->size == 0) error("illegal use of incomplete type `%t'\n", rty); } if (t != ')') for (;;) { Tree q = pointer(expr1(0)); if (proto && *proto && *proto != voidtype) { Type aty; q = value(q); aty = assign(*proto, q); if (aty) q = cast(q, aty); else error("type error in argument %d to %s; found `%t' expected `%t'\n", n + 1, funcname(f), q->type, *proto); if ((isint(q->type) || isenum(q->type)) && q->type->size != inttype->size) q = cast(q, promote(q->type)); ++proto; } else { if (!fty->u.f.oldstyle && *proto == NULL) error("too many arguments to %s\n", funcname(f)); q = value(q); if (isarray(q->type) || q->type->size == 0) error("type error in argument %d to %s; `%t' is illegal\n", n + 1, funcname(f), q->type); else q = cast(q, promote(q->type)); } if (!IR->wants_argb && isstruct(q->type)) if (iscallb(q)) q = addrof(q); else { Symbol t1 = temporary(AUTO, unqual(q->type)); q = asgn(t1, q); q = tree(RIGHT, ptr(t1->type), root(q), lvalue(idtree(t1))); } if (q->type->size == 0) q->type = inttype; if (hascall(q)) r = r ? tree(RIGHT, voidtype, r, q) : q; args = tree(mkop(ARG, q->type), q->type, q, args); n++; if (Aflag >= 2 && n == 32) warning("more than 31 arguments in a call to %s\n", funcname(f)); if (t != ',') break; t = gettok(); } expect(')'); if (proto && *proto && *proto != voidtype) error("insufficient number of arguments to %s\n", funcname(f)); if (r) args = tree(RIGHT, voidtype, r, args); e = calltree(f, rty, args, t3); if (events.calls) apply(events.calls, &src, &e); return e; }
static struct vector *decls(declfun_p * dcl) { struct vector *v = vec_new(); node_t *basety; int sclass, fspec; int level = SCOPE; int follow[] = {STATIC, INT, CONST, IF, '}', 0}; basety = specifiers(&sclass, &fspec); if (token->id == ID || token->id == '*' || token->id == '(') { struct token *id = NULL; node_t *ty = NULL; int params = 0; // for functioness // declarator if (level == GLOBAL) declarator(&ty, &id, ¶ms); else declarator(&ty, &id, NULL); attach_type(&ty, basety); if (level == GLOBAL && params) { if (first_funcdef(ty)) { vec_push(v, funcdef(id, ty, sclass, fspec)); return v; } else { exit_params(); } } for (;;) { if (id) { int kind; if (dcl == globaldecl) kind = GLOBAL; else if (dcl == paramdecl) kind = PARAM; else kind = LOCAL; node_t *decl = make_decl(id, ty, sclass, fspec, dcl); if (token->id == '=') decl_initializer(decl, sclass, kind); ensure_decl(decl, sclass, kind); vec_push(v, decl); } if (token->id != ',') break; expect(','); id = NULL; ty = NULL; // declarator declarator(&ty, &id, NULL); attach_type(&ty, basety); } } else if (isenum(basety) || isstruct(basety) || isunion(basety)) { // struct/union/enum int node_id; node_t *decl; if (isstruct(basety)) node_id = STRUCT_DECL; else if (isunion(basety)) node_id = UNION_DECL; else node_id = ENUM_DECL; decl = ast_decl(node_id); DECL_SYM(decl) = TYPE_TSYM(basety); vec_push(v, decl); } else { error("invalid token '%s' in declaration", token->name); } match(';', follow); return v; }