void fold_expr_if(expr *e, symtable *stab) { enum constyness is_const; intval dummy; fold_expr(e->expr, stab); const_fold(e->expr, &dummy, &is_const); if(is_const != CONST_NO) POSSIBLE_OPT(e->expr, "constant ?: expression"); fold_need_expr(e->expr, "?: expr", 1); fold_disallow_st_un(e->expr, "?: expr"); if(e->lhs){ fold_expr(e->lhs, stab); fold_disallow_st_un(e->lhs, "?: lhs"); } fold_expr(e->rhs, stab); fold_disallow_st_un(e->rhs, "?: rhs"); e->tree_type = decl_copy(e->rhs->tree_type); /* TODO: check they're the same */ e->freestanding = (e->lhs ? e->lhs : e->expr)->freestanding || e->rhs->freestanding; }
void fold_expr_cast(expr *e, symtable *stab) { fold_expr(e->expr, stab); fold_disallow_st_un(e->expr, "cast-expr"); /* * if we don't have a valid tree_type, get one * this is only the case where we're involving a tdef or typeof */ if(e->tree_type->type->primitive == type_unknown) { decl_free(e->tree_type); e->tree_type = decl_copy(e->expr->tree_type); } fold_decl(e->tree_type, stab); /* struct lookup, etc */ fold_disallow_st_un(e, "cast-target"); #ifdef CAST_COLLAPSE if(expr_kind(e->expr, cast)) { /* get rid of e->expr, replace with e->expr->rhs */ expr *del = e->expr; e->expr = e->expr->expr; /*decl_free(del->tree_type); XXX: memleak */ expr_free(del); fold_expr_cast(e, stab); } #endif }
void fold_expr_sizeof(expr *e, symtable *stab) { if(!e->expr->expr_is_sizeof) fold_expr(e->expr, stab); e->tree_type = decl_new(); e->tree_type->type->primitive = type_int; }
void fold_stmt_case_range(stmt *s) { intval lval, rval; fold_expr(s->expr, s->symtab); fold_expr(s->expr2, s->symtab); const_fold_need_val(s->expr, &lval); const_fold_need_val(s->expr2, &rval); fold_need_expr(s->expr, "case", 0); fold_need_expr(s->expr2, "case", 0); if(lval.val >= rval.val) DIE_AT(&s->where, "case range equal or inverse"); s->expr->spel = asm_label_case(CASE_RANGE, lval.val); fold_stmt_and_add_to_curswitch(s); }
void fold_stmt_case(stmt *t) { intval val; fold_expr(t->expr, t->symtab); fold_need_expr(t->expr, "case", 0); const_fold_need_val(t->expr, &val); t->expr->spel = asm_label_case(CASE_CASE, val.val); fold_stmt_and_add_to_curswitch(t); }
void fold_stmt_if(stmt *s) { symtable *test_symtab = fold_stmt_test_init_expr(s, "if"); fold_expr(s->expr, test_symtab); fold_need_expr(s->expr, s->f_str(), 1); OPT_CHECK(s->expr, "constant expression in if"); fold_stmt(s->lhs); if(s->rhs) fold_stmt(s->rhs); }
void fold_expr_funcall(expr *e, symtable *stab) { decl *df; funcargs *args_exp; if(expr_kind(e->expr, identifier) && e->expr->spel){ char *const sp = e->expr->spel; e->sym = symtab_search(stab, sp); if(!e->sym){ df = decl_new_where(&e->where); df->type->primitive = type_int; df->type->spec |= spec_extern; cc1_warn_at(&e->where, 0, WARN_IMPLICIT_FUNC, "implicit declaration of function \"%s\"", sp); df->spel = sp; df->funcargs = funcargs_new(); if(e->funcargs) /* set up the funcargs as if it's "x()" - i.e. any args */ function_empty_args(df->funcargs); e->sym = symtab_add(symtab_root(stab), df, sym_global, SYMTAB_WITH_SYM, SYMTAB_PREPEND); }else{ df = e->sym->decl; } fold_expr(e->expr, stab); }else{ fold_expr(e->expr, stab); /* * convert int (*)() to remove the deref */ if(decl_is_func_ptr(e->expr->tree_type)){ /* XXX: memleak */ e->expr = e->expr->lhs; fprintf(stderr, "FUNCPTR\n"); }else{ fprintf(stderr, "decl %s\n", decl_to_str(e->expr->tree_type)); } df = e->expr->tree_type; if(!decl_is_callable(df)){ die_at(&e->expr->where, "expression %s (%s) not callable", e->expr->f_str(), decl_to_str(df)); } } e->tree_type = decl_copy(df); /* * int (*x)(); * (*x)(); * evaluates to tree_type = int; */ decl_func_deref(e->tree_type); if(e->funcargs){ expr **iter; for(iter = e->funcargs; *iter; iter++) fold_expr(*iter, stab); } /* func count comparison, only if the func has arg-decls, or the func is f(void) */ args_exp = decl_funcargs(e->tree_type); UCC_ASSERT(args_exp, "no funcargs for decl %s", df->spel); if(args_exp->arglist || args_exp->args_void){ expr **iter_arg; decl **iter_decl; int count_decl, count_arg; count_decl = count_arg = 0; for(iter_arg = e->funcargs; iter_arg && *iter_arg; iter_arg++, count_arg++); for(iter_decl = args_exp->arglist; iter_decl && *iter_decl; iter_decl++, count_decl++); if(count_decl != count_arg && (args_exp->variadic ? count_arg < count_decl : 1)){ die_at(&e->where, "too %s arguments to function %s (got %d, need %d)", count_arg > count_decl ? "many" : "few", df->spel, count_arg, count_decl); } if(e->funcargs){ funcargs *argument_decls = funcargs_new(); for(iter_arg = e->funcargs; *iter_arg; iter_arg++) dynarray_add((void ***)&argument_decls->arglist, (*iter_arg)->tree_type); fold_funcargs_equal(args_exp, argument_decls, 1, &e->where, "argument", df->spel); funcargs_free(argument_decls, 0); } } }