void fold_stmt_label(stmt *s) { label *l = symtab_label_find_or_new( s->symtab, s->bits.lbl.spel, &s->where); /* update its where */ memcpy_safe(&l->where, &s->where); /* update its scope */ l->scope = s->symtab; /* update code the label uses */ l->next_stmt = s; if(l->complete){ warn_at_print_error(&s->where, "duplicate label '%s'", s->bits.lbl.spel); fold_had_error = 1; }else{ l->complete = 1; } s->bits.lbl.label = l; l->unused = s->bits.lbl.unused; fold_stmt(s->lhs); /* compound */ }
void fold_expr_addr(expr *e, symtable *stab) { if(e->bits.lbl.spel){ decl *in_func = symtab_func(stab); if(!in_func) die_at(&e->where, "address-of-label outside a function"); if(e->bits.lbl.static_ctx) in_func->bits.func.contains_static_label_addr = 1; (e->bits.lbl.label = symtab_label_find_or_new( stab, e->bits.lbl.spel, &e->where)) ->uses++; /* address of label - void * */ e->tree_type = type_ptr_to(type_nav_btype(cc1_type_nav, type_void)); }else{ /* if it's an identifier, act as a read */ fold_inc_writes_if_sym(e->lhs, stab); fold_expr_nodecay(e->lhs, stab); e->tree_type = type_ptr_to(e->lhs->tree_type); /* can address: lvalues, arrays and functions */ if(!expr_is_addressable(e->lhs)){ warn_at_print_error(&e->where, "can't take the address of %s (%s)", expr_str_friendly(e->lhs), type_to_str(e->lhs->tree_type)); fold_had_error = 1; return; } if(expr_kind(e->lhs, identifier)){ sym *sym = e->lhs->bits.ident.bits.ident.sym; if(sym){ decl *d = sym->decl; if((d->store & STORE_MASK_STORE) == store_register) die_at(&e->lhs->where, "can't take the address of register"); } } fold_check_expr(e->lhs, FOLD_CHK_ALLOW_VOID | FOLD_CHK_NO_BITFIELD, "address-of"); } }
void fold_stmt_goto(stmt *s) { if(!symtab_func(s->symtab)) die_at(&s->where, "goto outside of a function"); if(s->expr){ FOLD_EXPR(s->expr, s->symtab); }else{ (s->bits.lbl.label = symtab_label_find_or_new( s->symtab, s->bits.lbl.spel, &s->where)) ->uses++; dynarray_add(&s->bits.lbl.label->jumpers, s); } }