static void print_struct(struct_union_enum_st *sue) { sue_member **iter; if(!sue_complete(sue)){ idt_printf("incomplete %s %s\n", sue_str(sue), sue->spel); return; } idt_printf("%s %s (size %d):\n", sue_str(sue), sue->spel, sue_size(sue, &sue->where)); gen_str_indent++; for(iter = sue->members; iter && *iter; iter++){ decl *d = (*iter)->struct_member; idt_printf("decl %s:\n", d->spel ? d->spel : "<anon>"); gen_str_indent++; print_decl(d, PDECL_INDENT | PDECL_NEWLINE | PDECL_ATTR); if(!type_is(d->ref, type_func)){ #define SHOW_FIELD(nam) idt_printf("." #nam " = %u\n", d->bits.var.nam) SHOW_FIELD(struct_offset); if(d->bits.var.field_width){ integral_t v = const_fold_val_i(d->bits.var.field_width); gen_str_indent++; idt_printf(".field_width = %" NUMERIC_FMT_D "\n", v); SHOW_FIELD(struct_offset_bitfield); gen_str_indent--; } } gen_str_indent--; } gen_str_indent--; }
void fold_expr_struct(expr *e, symtable *stab) { /* * lhs = any ptr-to-struct expr * rhs = struct member ident */ const int ptr_expect = !e->expr_is_st_dot; struct_union_enum_st *sue; char *spel; fold_expr_no_decay(e->lhs, stab); /* don't fold the rhs - just a member name */ if(e->rhs){ UCC_ASSERT(expr_kind(e->rhs, identifier), "struct/union member not identifier (%s)", e->rhs->f_str()); UCC_ASSERT(!e->bits.struct_mem.d, "already have a struct-member"); spel = e->rhs->bits.ident.spel; }else{ UCC_ASSERT(e->bits.struct_mem.d, "no member specified already?"); spel = NULL; } /* we access a struct, of the right ptr depth */ { type *r = e->lhs->tree_type; if(ptr_expect){ type *rtest = type_is(r, type_ptr); if(!rtest && !(rtest = type_is(r, type_array))) goto err; r = rtest->ref; /* safe - rtest is an array */ } if(!(sue = type_is_s_or_u(r))){ err: die_at(&e->lhs->where, "'%s' (%s-expr) is not a %sstruct or union (member %s)", type_to_str(e->lhs->tree_type), e->lhs->f_str(), ptr_expect ? "pointer to " : "", spel); } } if(!sue_complete(sue)){ char wbuf[WHERE_BUF_SIZ]; die_at(&e->lhs->where, "%s incomplete type (%s)\n" "%s: note: forward declared here", ptr_expect ? "dereferencing pointer to" : "accessing member of", type_to_str(e->lhs->tree_type), where_str_r(wbuf, &sue->where)); } if(spel){ /* found the struct, find the member */ decl *d_mem = struct_union_member_find(sue, spel, &e->bits.struct_mem.extra_off, NULL); if(!d_mem) die_at(&e->where, "%s %s has no member named \"%s\"", sue_str(sue), sue->spel, spel); e->rhs->tree_type = (e->bits.struct_mem.d = d_mem)->ref; }/* else already have the member */ /* * if it's a.b, convert to (&a)->b for asm gen * e = { lhs = "a", rhs = "b", type = dot } * e = { * type = ptr, * lhs = { cast<void *>, expr = { expr = "a", type = addr } }, * rhs = "b", * } */ if(!ptr_expect){ expr *cast, *addr; addr = expr_new_addr(e->lhs); cast = expr_new_cast(addr, type_ptr_to(type_nav_btype(cc1_type_nav, type_void)), 1); e->lhs = cast; e->expr_is_st_dot = 0; FOLD_EXPR(e->lhs, stab); } /* pull qualifiers from the struct to the member */ e->tree_type = type_qualify( e->bits.struct_mem.d->ref, type_qual(e->lhs->tree_type)); }