1f08c3bdfSopenharmony_ci/* 2f08c3bdfSopenharmony_ci * sparse/dissect.c 3f08c3bdfSopenharmony_ci * 4f08c3bdfSopenharmony_ci * Started by Oleg Nesterov <oleg@redhat.com> 5f08c3bdfSopenharmony_ci * 6f08c3bdfSopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a copy 7f08c3bdfSopenharmony_ci * of this software and associated documentation files (the "Software"), to deal 8f08c3bdfSopenharmony_ci * in the Software without restriction, including without limitation the rights 9f08c3bdfSopenharmony_ci * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10f08c3bdfSopenharmony_ci * copies of the Software, and to permit persons to whom the Software is 11f08c3bdfSopenharmony_ci * furnished to do so, subject to the following conditions: 12f08c3bdfSopenharmony_ci * 13f08c3bdfSopenharmony_ci * The above copyright notice and this permission notice shall be included in 14f08c3bdfSopenharmony_ci * all copies or substantial portions of the Software. 15f08c3bdfSopenharmony_ci * 16f08c3bdfSopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17f08c3bdfSopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18f08c3bdfSopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19f08c3bdfSopenharmony_ci * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20f08c3bdfSopenharmony_ci * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21f08c3bdfSopenharmony_ci * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 22f08c3bdfSopenharmony_ci * THE SOFTWARE. 23f08c3bdfSopenharmony_ci */ 24f08c3bdfSopenharmony_ci 25f08c3bdfSopenharmony_ci#include "dissect.h" 26f08c3bdfSopenharmony_ci 27f08c3bdfSopenharmony_ci#define U_VOID 0x00 28f08c3bdfSopenharmony_ci#define U_SELF ((1 << U_SHIFT) - 1) 29f08c3bdfSopenharmony_ci#define U_MASK (U_R_VAL | U_W_VAL | U_R_AOF) 30f08c3bdfSopenharmony_ci 31f08c3bdfSopenharmony_ci#define DO_LIST(l__, p__, expr__) \ 32f08c3bdfSopenharmony_ci do { \ 33f08c3bdfSopenharmony_ci typeof(l__->list[0]) p__; \ 34f08c3bdfSopenharmony_ci FOR_EACH_PTR(l__, p__) \ 35f08c3bdfSopenharmony_ci expr__; \ 36f08c3bdfSopenharmony_ci END_FOR_EACH_PTR(p__); \ 37f08c3bdfSopenharmony_ci } while (0) 38f08c3bdfSopenharmony_ci 39f08c3bdfSopenharmony_ci#define DO_2_LIST(l1__,l2__, p1__,p2__, expr__) \ 40f08c3bdfSopenharmony_ci do { \ 41f08c3bdfSopenharmony_ci typeof(l1__->list[0]) p1__; \ 42f08c3bdfSopenharmony_ci typeof(l2__->list[0]) p2__; \ 43f08c3bdfSopenharmony_ci PREPARE_PTR_LIST(l1__, p1__); \ 44f08c3bdfSopenharmony_ci FOR_EACH_PTR(l2__, p2__) \ 45f08c3bdfSopenharmony_ci expr__; \ 46f08c3bdfSopenharmony_ci NEXT_PTR_LIST(p1__); \ 47f08c3bdfSopenharmony_ci END_FOR_EACH_PTR(p2__); \ 48f08c3bdfSopenharmony_ci FINISH_PTR_LIST(p1__); \ 49f08c3bdfSopenharmony_ci } while (0) 50f08c3bdfSopenharmony_ci 51f08c3bdfSopenharmony_ci 52f08c3bdfSopenharmony_citypedef unsigned usage_t; 53f08c3bdfSopenharmony_ci 54f08c3bdfSopenharmony_cistruct symbol *dissect_ctx; 55f08c3bdfSopenharmony_ci 56f08c3bdfSopenharmony_cistatic struct reporter *reporter; 57f08c3bdfSopenharmony_ci 58f08c3bdfSopenharmony_cistatic void do_sym_list(struct symbol_list *list); 59f08c3bdfSopenharmony_ci 60f08c3bdfSopenharmony_cistatic struct symbol 61f08c3bdfSopenharmony_ci *base_type(struct symbol *sym), 62f08c3bdfSopenharmony_ci *do_initializer(struct symbol *type, struct expression *expr), 63f08c3bdfSopenharmony_ci *do_expression(usage_t mode, struct expression *expr), 64f08c3bdfSopenharmony_ci *do_statement(usage_t mode, struct statement *stmt); 65f08c3bdfSopenharmony_ci 66f08c3bdfSopenharmony_cistatic inline int is_ptr(struct symbol *type) 67f08c3bdfSopenharmony_ci{ 68f08c3bdfSopenharmony_ci return type->type == SYM_PTR || type->type == SYM_ARRAY; 69f08c3bdfSopenharmony_ci} 70f08c3bdfSopenharmony_ci 71f08c3bdfSopenharmony_cistatic inline usage_t u_rval(usage_t mode) 72f08c3bdfSopenharmony_ci{ 73f08c3bdfSopenharmony_ci return mode & (U_R_VAL | (U_MASK << U_SHIFT)) 74f08c3bdfSopenharmony_ci ? U_R_VAL : 0; 75f08c3bdfSopenharmony_ci} 76f08c3bdfSopenharmony_ci 77f08c3bdfSopenharmony_cistatic inline usage_t u_addr(usage_t mode) 78f08c3bdfSopenharmony_ci{ 79f08c3bdfSopenharmony_ci return mode = mode & U_MASK 80f08c3bdfSopenharmony_ci ? U_R_AOF | (mode & U_W_AOF) : 0; 81f08c3bdfSopenharmony_ci} 82f08c3bdfSopenharmony_ci 83f08c3bdfSopenharmony_cistatic usage_t u_lval(struct symbol *type) 84f08c3bdfSopenharmony_ci{ 85f08c3bdfSopenharmony_ci int wptr = is_ptr(type) && !(type->ctype.modifiers & MOD_CONST); 86f08c3bdfSopenharmony_ci return wptr || type == &bad_ctype 87f08c3bdfSopenharmony_ci ? U_W_AOF | U_R_VAL : U_R_VAL; 88f08c3bdfSopenharmony_ci} 89f08c3bdfSopenharmony_ci 90f08c3bdfSopenharmony_cistatic usage_t fix_mode(struct symbol *type, usage_t mode) 91f08c3bdfSopenharmony_ci{ 92f08c3bdfSopenharmony_ci mode &= (U_SELF | (U_SELF << U_SHIFT)); 93f08c3bdfSopenharmony_ci 94f08c3bdfSopenharmony_ci switch (type->type) { 95f08c3bdfSopenharmony_ci case SYM_BASETYPE: 96f08c3bdfSopenharmony_ci if (!type->ctype.base_type) 97f08c3bdfSopenharmony_ci break; 98f08c3bdfSopenharmony_ci case SYM_ENUM: 99f08c3bdfSopenharmony_ci case SYM_BITFIELD: 100f08c3bdfSopenharmony_ci if (mode & U_MASK) 101f08c3bdfSopenharmony_ci mode &= U_SELF; 102f08c3bdfSopenharmony_ci default: 103f08c3bdfSopenharmony_ci 104f08c3bdfSopenharmony_ci break; case SYM_FN: 105f08c3bdfSopenharmony_ci if (mode & U_R_VAL) 106f08c3bdfSopenharmony_ci mode |= U_R_AOF; 107f08c3bdfSopenharmony_ci mode &= ~(U_R_VAL | U_W_AOF); 108f08c3bdfSopenharmony_ci 109f08c3bdfSopenharmony_ci break; case SYM_ARRAY: 110f08c3bdfSopenharmony_ci if (mode & (U_MASK << U_SHIFT)) 111f08c3bdfSopenharmony_ci mode >>= U_SHIFT; 112f08c3bdfSopenharmony_ci else if (mode != U_W_VAL) 113f08c3bdfSopenharmony_ci mode = u_addr(mode); 114f08c3bdfSopenharmony_ci } 115f08c3bdfSopenharmony_ci 116f08c3bdfSopenharmony_ci if (!(mode & U_R_AOF)) 117f08c3bdfSopenharmony_ci mode &= ~U_W_AOF; 118f08c3bdfSopenharmony_ci 119f08c3bdfSopenharmony_ci return mode; 120f08c3bdfSopenharmony_ci} 121f08c3bdfSopenharmony_ci 122f08c3bdfSopenharmony_cistatic struct symbol *report_member(usage_t mode, struct position *pos, 123f08c3bdfSopenharmony_ci struct symbol *type, struct symbol *mem) 124f08c3bdfSopenharmony_ci{ 125f08c3bdfSopenharmony_ci struct symbol *ret = mem->ctype.base_type; 126f08c3bdfSopenharmony_ci 127f08c3bdfSopenharmony_ci if (mem->ident || mem->type == SYM_BAD) 128f08c3bdfSopenharmony_ci reporter->r_member(fix_mode(ret, mode), pos, type, mem); 129f08c3bdfSopenharmony_ci 130f08c3bdfSopenharmony_ci return ret; 131f08c3bdfSopenharmony_ci} 132f08c3bdfSopenharmony_ci 133f08c3bdfSopenharmony_cistatic void report_implicit(usage_t mode, struct position *pos, struct symbol *type) 134f08c3bdfSopenharmony_ci{ 135f08c3bdfSopenharmony_ci if (type->type != SYM_STRUCT && type->type != SYM_UNION) 136f08c3bdfSopenharmony_ci return; 137f08c3bdfSopenharmony_ci 138f08c3bdfSopenharmony_ci if (type->ident != NULL) 139f08c3bdfSopenharmony_ci reporter->r_member(mode, pos, type, NULL); 140f08c3bdfSopenharmony_ci 141f08c3bdfSopenharmony_ci DO_LIST(type->symbol_list, mem, 142f08c3bdfSopenharmony_ci report_implicit(mode, pos, base_type(mem))); 143f08c3bdfSopenharmony_ci} 144f08c3bdfSopenharmony_ci 145f08c3bdfSopenharmony_cistatic inline struct symbol *expr_symbol(struct expression *expr) 146f08c3bdfSopenharmony_ci{ 147f08c3bdfSopenharmony_ci struct symbol *sym = expr->symbol; 148f08c3bdfSopenharmony_ci 149f08c3bdfSopenharmony_ci if (!sym) { 150f08c3bdfSopenharmony_ci sym = lookup_symbol(expr->symbol_name, NS_SYMBOL); 151f08c3bdfSopenharmony_ci 152f08c3bdfSopenharmony_ci if (!sym) { 153f08c3bdfSopenharmony_ci sym = alloc_symbol(expr->pos, SYM_BAD); 154f08c3bdfSopenharmony_ci bind_symbol(sym, expr->symbol_name, NS_SYMBOL); 155f08c3bdfSopenharmony_ci sym->kind = expr->op ?: 'v'; /* see EXPR_CALL */ 156f08c3bdfSopenharmony_ci } 157f08c3bdfSopenharmony_ci } 158f08c3bdfSopenharmony_ci 159f08c3bdfSopenharmony_ci if (!sym->ctype.base_type) 160f08c3bdfSopenharmony_ci sym->ctype.base_type = &bad_ctype; 161f08c3bdfSopenharmony_ci 162f08c3bdfSopenharmony_ci return sym; 163f08c3bdfSopenharmony_ci} 164f08c3bdfSopenharmony_ci 165f08c3bdfSopenharmony_cistatic struct symbol *report_symbol(usage_t mode, struct expression *expr) 166f08c3bdfSopenharmony_ci{ 167f08c3bdfSopenharmony_ci struct symbol *sym = expr_symbol(expr); 168f08c3bdfSopenharmony_ci struct symbol *ret = base_type(sym); 169f08c3bdfSopenharmony_ci 170f08c3bdfSopenharmony_ci if (0 && ret->type == SYM_ENUM) 171f08c3bdfSopenharmony_ci return report_member(mode, &expr->pos, ret, expr->symbol); 172f08c3bdfSopenharmony_ci 173f08c3bdfSopenharmony_ci reporter->r_symbol(fix_mode(ret, mode), &expr->pos, sym); 174f08c3bdfSopenharmony_ci 175f08c3bdfSopenharmony_ci return ret; 176f08c3bdfSopenharmony_ci} 177f08c3bdfSopenharmony_ci 178f08c3bdfSopenharmony_cistatic bool deanon(struct symbol *base, struct ident *node, struct symbol *parent) 179f08c3bdfSopenharmony_ci{ 180f08c3bdfSopenharmony_ci struct ident *pi = parent ? parent->ident : NULL; 181f08c3bdfSopenharmony_ci char name[256]; 182f08c3bdfSopenharmony_ci 183f08c3bdfSopenharmony_ci if (!node) { 184f08c3bdfSopenharmony_ci base->ident = pi; 185f08c3bdfSopenharmony_ci return false; 186f08c3bdfSopenharmony_ci } 187f08c3bdfSopenharmony_ci 188f08c3bdfSopenharmony_ci snprintf(name, sizeof(name), "%.*s:%.*s", 189f08c3bdfSopenharmony_ci pi ? pi->len : 0, pi ? pi->name : NULL, node->len, node->name); 190f08c3bdfSopenharmony_ci 191f08c3bdfSopenharmony_ci base->ident = built_in_ident(name); 192f08c3bdfSopenharmony_ci return true; 193f08c3bdfSopenharmony_ci} 194f08c3bdfSopenharmony_ci 195f08c3bdfSopenharmony_cistatic void report_memdef(struct symbol *sym, struct symbol *mem) 196f08c3bdfSopenharmony_ci{ 197f08c3bdfSopenharmony_ci mem->kind = 'm'; 198f08c3bdfSopenharmony_ci if (sym && mem->ident) 199f08c3bdfSopenharmony_ci reporter->r_memdef(sym, mem); 200f08c3bdfSopenharmony_ci} 201f08c3bdfSopenharmony_ci 202f08c3bdfSopenharmony_cistatic void examine_sym_node(struct symbol *node, struct symbol *parent) 203f08c3bdfSopenharmony_ci{ 204f08c3bdfSopenharmony_ci struct ident *name = node->ident; 205f08c3bdfSopenharmony_ci struct symbol *base, *dctx; 206f08c3bdfSopenharmony_ci 207f08c3bdfSopenharmony_ci if (node->visited) 208f08c3bdfSopenharmony_ci return; 209f08c3bdfSopenharmony_ci node->visited = 1; 210f08c3bdfSopenharmony_ci node->kind = 'v'; 211f08c3bdfSopenharmony_ci 212f08c3bdfSopenharmony_ci while ((base = node->ctype.base_type) != NULL) 213f08c3bdfSopenharmony_ci switch (base->type) { 214f08c3bdfSopenharmony_ci case SYM_TYPEOF: 215f08c3bdfSopenharmony_ci node->ctype.base_type = 216f08c3bdfSopenharmony_ci do_expression(U_VOID, base->initializer); 217f08c3bdfSopenharmony_ci break; 218f08c3bdfSopenharmony_ci 219f08c3bdfSopenharmony_ci case SYM_ARRAY: 220f08c3bdfSopenharmony_ci do_expression(U_R_VAL, base->array_size); 221f08c3bdfSopenharmony_ci case SYM_PTR: 222f08c3bdfSopenharmony_ci node = base; 223f08c3bdfSopenharmony_ci break; 224f08c3bdfSopenharmony_ci 225f08c3bdfSopenharmony_ci case SYM_FN: 226f08c3bdfSopenharmony_ci node->kind = 'f'; 227f08c3bdfSopenharmony_ci node = base; 228f08c3bdfSopenharmony_ci break; 229f08c3bdfSopenharmony_ci 230f08c3bdfSopenharmony_ci case SYM_STRUCT: case SYM_UNION: //case SYM_ENUM: 231f08c3bdfSopenharmony_ci if (base->inspected) 232f08c3bdfSopenharmony_ci return; 233f08c3bdfSopenharmony_ci base->inspected = 1; 234f08c3bdfSopenharmony_ci base->kind = 's'; 235f08c3bdfSopenharmony_ci 236f08c3bdfSopenharmony_ci if (!base->symbol_list) 237f08c3bdfSopenharmony_ci return; 238f08c3bdfSopenharmony_ci 239f08c3bdfSopenharmony_ci dctx = dissect_ctx; 240f08c3bdfSopenharmony_ci if (toplevel(base->scope)) 241f08c3bdfSopenharmony_ci dissect_ctx = NULL; 242f08c3bdfSopenharmony_ci 243f08c3bdfSopenharmony_ci if (base->ident || deanon(base, name, parent)) 244f08c3bdfSopenharmony_ci reporter->r_symdef(base); 245f08c3bdfSopenharmony_ci 246f08c3bdfSopenharmony_ci if (base->ident) 247f08c3bdfSopenharmony_ci parent = base; 248f08c3bdfSopenharmony_ci DO_LIST(base->symbol_list, mem, 249f08c3bdfSopenharmony_ci examine_sym_node(mem, parent); 250f08c3bdfSopenharmony_ci report_memdef(parent, mem)); 251f08c3bdfSopenharmony_ci dissect_ctx = dctx; 252f08c3bdfSopenharmony_ci default: 253f08c3bdfSopenharmony_ci return; 254f08c3bdfSopenharmony_ci } 255f08c3bdfSopenharmony_ci} 256f08c3bdfSopenharmony_ci 257f08c3bdfSopenharmony_cistatic struct symbol *base_type(struct symbol *sym) 258f08c3bdfSopenharmony_ci{ 259f08c3bdfSopenharmony_ci if (!sym) 260f08c3bdfSopenharmony_ci return &bad_ctype; 261f08c3bdfSopenharmony_ci 262f08c3bdfSopenharmony_ci if (sym->type == SYM_NODE) 263f08c3bdfSopenharmony_ci examine_sym_node(sym, NULL); 264f08c3bdfSopenharmony_ci 265f08c3bdfSopenharmony_ci return sym->ctype.base_type // builtin_fn_type 266f08c3bdfSopenharmony_ci ?: &bad_ctype; 267f08c3bdfSopenharmony_ci} 268f08c3bdfSopenharmony_ci 269f08c3bdfSopenharmony_cistatic struct symbol *__lookup_member(struct symbol *type, struct ident *name, int *p_addr) 270f08c3bdfSopenharmony_ci{ 271f08c3bdfSopenharmony_ci struct symbol *node; 272f08c3bdfSopenharmony_ci int addr = 0; 273f08c3bdfSopenharmony_ci 274f08c3bdfSopenharmony_ci FOR_EACH_PTR(type->symbol_list, node) 275f08c3bdfSopenharmony_ci if (!name) { 276f08c3bdfSopenharmony_ci if (addr == *p_addr) 277f08c3bdfSopenharmony_ci return node; 278f08c3bdfSopenharmony_ci } 279f08c3bdfSopenharmony_ci else if (node->ident == NULL) { 280f08c3bdfSopenharmony_ci node = __lookup_member(node->ctype.base_type, name, NULL); 281f08c3bdfSopenharmony_ci if (node) 282f08c3bdfSopenharmony_ci goto found; 283f08c3bdfSopenharmony_ci } 284f08c3bdfSopenharmony_ci else if (node->ident == name) { 285f08c3bdfSopenharmony_cifound: 286f08c3bdfSopenharmony_ci if (p_addr) 287f08c3bdfSopenharmony_ci *p_addr = addr; 288f08c3bdfSopenharmony_ci return node; 289f08c3bdfSopenharmony_ci } 290f08c3bdfSopenharmony_ci addr++; 291f08c3bdfSopenharmony_ci END_FOR_EACH_PTR(node); 292f08c3bdfSopenharmony_ci 293f08c3bdfSopenharmony_ci return NULL; 294f08c3bdfSopenharmony_ci} 295f08c3bdfSopenharmony_ci 296f08c3bdfSopenharmony_cistatic struct symbol *lookup_member(struct symbol *type, struct ident *name, int *addr) 297f08c3bdfSopenharmony_ci{ 298f08c3bdfSopenharmony_ci struct symbol *mem = __lookup_member(type, name, addr); 299f08c3bdfSopenharmony_ci 300f08c3bdfSopenharmony_ci if (!mem) { 301f08c3bdfSopenharmony_ci static struct symbol bad_member = { 302f08c3bdfSopenharmony_ci .type = SYM_BAD, 303f08c3bdfSopenharmony_ci .ctype.base_type = &bad_ctype, 304f08c3bdfSopenharmony_ci .kind = 'm', 305f08c3bdfSopenharmony_ci }; 306f08c3bdfSopenharmony_ci 307f08c3bdfSopenharmony_ci if (!type->symbol_list) 308f08c3bdfSopenharmony_ci type->scope = file_scope; 309f08c3bdfSopenharmony_ci 310f08c3bdfSopenharmony_ci mem = &bad_member; 311f08c3bdfSopenharmony_ci mem->ident = name; 312f08c3bdfSopenharmony_ci } 313f08c3bdfSopenharmony_ci 314f08c3bdfSopenharmony_ci return mem; 315f08c3bdfSopenharmony_ci} 316f08c3bdfSopenharmony_ci 317f08c3bdfSopenharmony_cistatic struct expression *peek_preop(struct expression *expr, int op) 318f08c3bdfSopenharmony_ci{ 319f08c3bdfSopenharmony_ci do { 320f08c3bdfSopenharmony_ci if (expr->type != EXPR_PREOP) 321f08c3bdfSopenharmony_ci break; 322f08c3bdfSopenharmony_ci if (expr->op == op) 323f08c3bdfSopenharmony_ci return expr->unop; 324f08c3bdfSopenharmony_ci if (expr->op == '(') 325f08c3bdfSopenharmony_ci expr = expr->unop; 326f08c3bdfSopenharmony_ci else 327f08c3bdfSopenharmony_ci break; 328f08c3bdfSopenharmony_ci } while (expr); 329f08c3bdfSopenharmony_ci 330f08c3bdfSopenharmony_ci return NULL; 331f08c3bdfSopenharmony_ci} 332f08c3bdfSopenharmony_ci 333f08c3bdfSopenharmony_cistatic struct symbol *do_expression(usage_t mode, struct expression *expr) 334f08c3bdfSopenharmony_ci{ 335f08c3bdfSopenharmony_ci struct symbol *ret = &int_ctype; 336f08c3bdfSopenharmony_ci 337f08c3bdfSopenharmony_ciagain: 338f08c3bdfSopenharmony_ci if (expr) switch (expr->type) { 339f08c3bdfSopenharmony_ci default: 340f08c3bdfSopenharmony_ci warning(expr->pos, "bad expr->type: %d", expr->type); 341f08c3bdfSopenharmony_ci 342f08c3bdfSopenharmony_ci case EXPR_TYPE: // [struct T]; Why ??? 343f08c3bdfSopenharmony_ci case EXPR_VALUE: 344f08c3bdfSopenharmony_ci case EXPR_FVALUE: 345f08c3bdfSopenharmony_ci 346f08c3bdfSopenharmony_ci break; case EXPR_LABEL: 347f08c3bdfSopenharmony_ci ret = &label_ctype; 348f08c3bdfSopenharmony_ci 349f08c3bdfSopenharmony_ci break; case EXPR_STRING: 350f08c3bdfSopenharmony_ci ret = &string_ctype; 351f08c3bdfSopenharmony_ci 352f08c3bdfSopenharmony_ci break; case EXPR_STATEMENT: 353f08c3bdfSopenharmony_ci ret = do_statement(mode, expr->statement); 354f08c3bdfSopenharmony_ci 355f08c3bdfSopenharmony_ci break; case EXPR_SIZEOF: case EXPR_ALIGNOF: case EXPR_PTRSIZEOF: 356f08c3bdfSopenharmony_ci do_expression(U_VOID, expr->cast_expression); 357f08c3bdfSopenharmony_ci 358f08c3bdfSopenharmony_ci break; case EXPR_COMMA: 359f08c3bdfSopenharmony_ci do_expression(U_VOID, expr->left); 360f08c3bdfSopenharmony_ci ret = do_expression(mode, expr->right); 361f08c3bdfSopenharmony_ci 362f08c3bdfSopenharmony_ci break; case EXPR_CAST: case EXPR_FORCE_CAST: //case EXPR_IMPLIED_CAST: 363f08c3bdfSopenharmony_ci ret = base_type(expr->cast_type); 364f08c3bdfSopenharmony_ci do_initializer(ret, expr->cast_expression); 365f08c3bdfSopenharmony_ci 366f08c3bdfSopenharmony_ci break; case EXPR_COMPARE: case EXPR_LOGICAL: 367f08c3bdfSopenharmony_ci mode = u_rval(mode); 368f08c3bdfSopenharmony_ci do_expression(mode, expr->left); 369f08c3bdfSopenharmony_ci do_expression(mode, expr->right); 370f08c3bdfSopenharmony_ci 371f08c3bdfSopenharmony_ci break; case EXPR_CONDITIONAL: //case EXPR_SELECT: 372f08c3bdfSopenharmony_ci do_expression(expr->cond_true 373f08c3bdfSopenharmony_ci ? U_R_VAL : U_R_VAL | mode, 374f08c3bdfSopenharmony_ci expr->conditional); 375f08c3bdfSopenharmony_ci ret = do_expression(mode, expr->cond_true); 376f08c3bdfSopenharmony_ci ret = do_expression(mode, expr->cond_false); 377f08c3bdfSopenharmony_ci 378f08c3bdfSopenharmony_ci break; case EXPR_CALL: 379f08c3bdfSopenharmony_ci if (expr->fn->type == EXPR_SYMBOL) 380f08c3bdfSopenharmony_ci expr->fn->op = 'f'; /* for expr_symbol() */ 381f08c3bdfSopenharmony_ci ret = do_expression(U_R_PTR, expr->fn); 382f08c3bdfSopenharmony_ci if (is_ptr(ret)) 383f08c3bdfSopenharmony_ci ret = ret->ctype.base_type; 384f08c3bdfSopenharmony_ci DO_2_LIST(ret->arguments, expr->args, arg, val, 385f08c3bdfSopenharmony_ci do_expression(u_lval(base_type(arg)), val)); 386f08c3bdfSopenharmony_ci ret = ret->type == SYM_FN ? base_type(ret) 387f08c3bdfSopenharmony_ci : &bad_ctype; 388f08c3bdfSopenharmony_ci 389f08c3bdfSopenharmony_ci break; case EXPR_ASSIGNMENT: 390f08c3bdfSopenharmony_ci mode |= U_W_VAL | U_R_VAL; 391f08c3bdfSopenharmony_ci if (expr->op == '=') 392f08c3bdfSopenharmony_ci mode &= ~U_R_VAL; 393f08c3bdfSopenharmony_ci ret = do_expression(mode, expr->left); 394f08c3bdfSopenharmony_ci report_implicit(mode, &expr->pos, ret); 395f08c3bdfSopenharmony_ci mode = expr->op == '=' 396f08c3bdfSopenharmony_ci ? u_lval(ret) : U_R_VAL; 397f08c3bdfSopenharmony_ci do_expression(mode, expr->right); 398f08c3bdfSopenharmony_ci 399f08c3bdfSopenharmony_ci break; case EXPR_BINOP: { 400f08c3bdfSopenharmony_ci struct symbol *l, *r; 401f08c3bdfSopenharmony_ci mode |= u_rval(mode); 402f08c3bdfSopenharmony_ci l = do_expression(mode, expr->left); 403f08c3bdfSopenharmony_ci r = do_expression(mode, expr->right); 404f08c3bdfSopenharmony_ci if (expr->op != '+' && expr->op != '-') 405f08c3bdfSopenharmony_ci ; 406f08c3bdfSopenharmony_ci else if (!is_ptr_type(r)) 407f08c3bdfSopenharmony_ci ret = l; 408f08c3bdfSopenharmony_ci else if (!is_ptr_type(l)) 409f08c3bdfSopenharmony_ci ret = r; 410f08c3bdfSopenharmony_ci } 411f08c3bdfSopenharmony_ci 412f08c3bdfSopenharmony_ci break; case EXPR_PREOP: case EXPR_POSTOP: { 413f08c3bdfSopenharmony_ci struct expression *unop = expr->unop; 414f08c3bdfSopenharmony_ci 415f08c3bdfSopenharmony_ci switch (expr->op) { 416f08c3bdfSopenharmony_ci case SPECIAL_INCREMENT: 417f08c3bdfSopenharmony_ci case SPECIAL_DECREMENT: 418f08c3bdfSopenharmony_ci mode |= U_W_VAL | U_R_VAL; 419f08c3bdfSopenharmony_ci default: 420f08c3bdfSopenharmony_ci mode |= u_rval(mode); 421f08c3bdfSopenharmony_ci case '(': 422f08c3bdfSopenharmony_ci ret = do_expression(mode, unop); 423f08c3bdfSopenharmony_ci 424f08c3bdfSopenharmony_ci break; case '&': 425f08c3bdfSopenharmony_ci if ((expr = peek_preop(unop, '*'))) 426f08c3bdfSopenharmony_ci goto again; 427f08c3bdfSopenharmony_ci ret = alloc_symbol(unop->pos, SYM_PTR); 428f08c3bdfSopenharmony_ci ret->ctype.base_type = 429f08c3bdfSopenharmony_ci do_expression(u_addr(mode), unop); 430f08c3bdfSopenharmony_ci 431f08c3bdfSopenharmony_ci break; case '*': 432f08c3bdfSopenharmony_ci if ((expr = peek_preop(unop, '&'))) 433f08c3bdfSopenharmony_ci goto again; 434f08c3bdfSopenharmony_ci if (mode & (U_MASK << U_SHIFT)) 435f08c3bdfSopenharmony_ci mode |= U_R_VAL; 436f08c3bdfSopenharmony_ci mode <<= U_SHIFT; 437f08c3bdfSopenharmony_ci if (mode & (U_R_AOF << U_SHIFT)) 438f08c3bdfSopenharmony_ci mode |= U_R_VAL; 439f08c3bdfSopenharmony_ci if (mode & (U_W_VAL << U_SHIFT)) 440f08c3bdfSopenharmony_ci mode |= U_W_AOF; 441f08c3bdfSopenharmony_ci ret = do_expression(mode, unop); 442f08c3bdfSopenharmony_ci ret = is_ptr(ret) ? base_type(ret) 443f08c3bdfSopenharmony_ci : &bad_ctype; 444f08c3bdfSopenharmony_ci } 445f08c3bdfSopenharmony_ci } 446f08c3bdfSopenharmony_ci 447f08c3bdfSopenharmony_ci break; case EXPR_DEREF: { 448f08c3bdfSopenharmony_ci struct symbol *p_type; 449f08c3bdfSopenharmony_ci usage_t p_mode; 450f08c3bdfSopenharmony_ci 451f08c3bdfSopenharmony_ci p_mode = mode & U_SELF; 452f08c3bdfSopenharmony_ci if (!(mode & U_MASK) && (mode & (U_MASK << U_SHIFT))) 453f08c3bdfSopenharmony_ci p_mode = U_R_VAL; 454f08c3bdfSopenharmony_ci p_type = do_expression(p_mode, expr->deref); 455f08c3bdfSopenharmony_ci 456f08c3bdfSopenharmony_ci ret = report_member(mode, &expr->pos, p_type, 457f08c3bdfSopenharmony_ci lookup_member(p_type, expr->member, NULL)); 458f08c3bdfSopenharmony_ci } 459f08c3bdfSopenharmony_ci 460f08c3bdfSopenharmony_ci break; case EXPR_OFFSETOF: { 461f08c3bdfSopenharmony_ci struct symbol *in = base_type(expr->in); 462f08c3bdfSopenharmony_ci 463f08c3bdfSopenharmony_ci do { 464f08c3bdfSopenharmony_ci if (expr->op == '.') { 465f08c3bdfSopenharmony_ci in = report_member(U_VOID, &expr->pos, in, 466f08c3bdfSopenharmony_ci lookup_member(in, expr->ident, NULL)); 467f08c3bdfSopenharmony_ci } else { 468f08c3bdfSopenharmony_ci do_expression(U_R_VAL, expr->index); 469f08c3bdfSopenharmony_ci in = in->ctype.base_type; 470f08c3bdfSopenharmony_ci } 471f08c3bdfSopenharmony_ci } while ((expr = expr->down)); 472f08c3bdfSopenharmony_ci } 473f08c3bdfSopenharmony_ci 474f08c3bdfSopenharmony_ci break; case EXPR_GENERIC: { 475f08c3bdfSopenharmony_ci struct type_expression *map; 476f08c3bdfSopenharmony_ci 477f08c3bdfSopenharmony_ci do_expression(U_VOID, expr->control); 478f08c3bdfSopenharmony_ci 479f08c3bdfSopenharmony_ci for (map = expr->map; map; map = map->next) 480f08c3bdfSopenharmony_ci ret = do_expression(mode, map->expr); 481f08c3bdfSopenharmony_ci if (expr->def) 482f08c3bdfSopenharmony_ci ret = do_expression(mode, expr->def); 483f08c3bdfSopenharmony_ci } 484f08c3bdfSopenharmony_ci 485f08c3bdfSopenharmony_ci break; case EXPR_SYMBOL: 486f08c3bdfSopenharmony_ci ret = report_symbol(mode, expr); 487f08c3bdfSopenharmony_ci } 488f08c3bdfSopenharmony_ci 489f08c3bdfSopenharmony_ci return ret; 490f08c3bdfSopenharmony_ci} 491f08c3bdfSopenharmony_ci 492f08c3bdfSopenharmony_cistatic void do_asm_xputs(usage_t mode, struct asm_operand_list *xputs) 493f08c3bdfSopenharmony_ci{ 494f08c3bdfSopenharmony_ci DO_LIST(xputs, op, do_expression(U_W_AOF | mode, op->expr)); 495f08c3bdfSopenharmony_ci} 496f08c3bdfSopenharmony_ci 497f08c3bdfSopenharmony_cistatic struct symbol *do_statement(usage_t mode, struct statement *stmt) 498f08c3bdfSopenharmony_ci{ 499f08c3bdfSopenharmony_ci struct symbol *ret = &void_ctype; 500f08c3bdfSopenharmony_ci 501f08c3bdfSopenharmony_ci if (stmt) switch (stmt->type) { 502f08c3bdfSopenharmony_ci default: 503f08c3bdfSopenharmony_ci warning(stmt->pos, "bad stmt->type: %d", stmt->type); 504f08c3bdfSopenharmony_ci 505f08c3bdfSopenharmony_ci case STMT_NONE: 506f08c3bdfSopenharmony_ci case STMT_RANGE: 507f08c3bdfSopenharmony_ci case STMT_CONTEXT: 508f08c3bdfSopenharmony_ci 509f08c3bdfSopenharmony_ci break; case STMT_DECLARATION: 510f08c3bdfSopenharmony_ci do_sym_list(stmt->declaration); 511f08c3bdfSopenharmony_ci 512f08c3bdfSopenharmony_ci break; case STMT_EXPRESSION: 513f08c3bdfSopenharmony_ci ret = do_expression(mode, stmt->expression); 514f08c3bdfSopenharmony_ci 515f08c3bdfSopenharmony_ci break; case STMT_RETURN: { 516f08c3bdfSopenharmony_ci struct symbol *type = dissect_ctx->ctype.base_type; 517f08c3bdfSopenharmony_ci do_expression(u_lval(base_type(type)), stmt->expression); 518f08c3bdfSopenharmony_ci } 519f08c3bdfSopenharmony_ci 520f08c3bdfSopenharmony_ci break; case STMT_ASM: 521f08c3bdfSopenharmony_ci do_expression(U_R_VAL, stmt->asm_string); 522f08c3bdfSopenharmony_ci do_asm_xputs(U_W_VAL, stmt->asm_outputs); 523f08c3bdfSopenharmony_ci do_asm_xputs(U_R_VAL, stmt->asm_inputs); 524f08c3bdfSopenharmony_ci 525f08c3bdfSopenharmony_ci break; case STMT_COMPOUND: { 526f08c3bdfSopenharmony_ci int count; 527f08c3bdfSopenharmony_ci 528f08c3bdfSopenharmony_ci count = statement_list_size(stmt->stmts); 529f08c3bdfSopenharmony_ci DO_LIST(stmt->stmts, st, 530f08c3bdfSopenharmony_ci ret = do_statement(--count ? U_VOID : mode, st)); 531f08c3bdfSopenharmony_ci } 532f08c3bdfSopenharmony_ci 533f08c3bdfSopenharmony_ci break; case STMT_ITERATOR: 534f08c3bdfSopenharmony_ci do_sym_list(stmt->iterator_syms); 535f08c3bdfSopenharmony_ci do_statement(U_VOID, stmt->iterator_pre_statement); 536f08c3bdfSopenharmony_ci do_expression(U_R_VAL, stmt->iterator_pre_condition); 537f08c3bdfSopenharmony_ci do_statement(U_VOID, stmt->iterator_post_statement); 538f08c3bdfSopenharmony_ci do_statement(U_VOID, stmt->iterator_statement); 539f08c3bdfSopenharmony_ci do_expression(U_R_VAL, stmt->iterator_post_condition); 540f08c3bdfSopenharmony_ci 541f08c3bdfSopenharmony_ci break; case STMT_IF: 542f08c3bdfSopenharmony_ci do_expression(U_R_VAL, stmt->if_conditional); 543f08c3bdfSopenharmony_ci do_statement(U_VOID, stmt->if_true); 544f08c3bdfSopenharmony_ci do_statement(U_VOID, stmt->if_false); 545f08c3bdfSopenharmony_ci 546f08c3bdfSopenharmony_ci break; case STMT_SWITCH: 547f08c3bdfSopenharmony_ci do_expression(U_R_VAL, stmt->switch_expression); 548f08c3bdfSopenharmony_ci do_statement(U_VOID, stmt->switch_statement); 549f08c3bdfSopenharmony_ci 550f08c3bdfSopenharmony_ci break; case STMT_CASE: 551f08c3bdfSopenharmony_ci do_expression(U_R_VAL, stmt->case_expression); 552f08c3bdfSopenharmony_ci do_expression(U_R_VAL, stmt->case_to); 553f08c3bdfSopenharmony_ci do_statement(U_VOID, stmt->case_statement); 554f08c3bdfSopenharmony_ci 555f08c3bdfSopenharmony_ci break; case STMT_GOTO: 556f08c3bdfSopenharmony_ci do_expression(U_R_PTR, stmt->goto_expression); 557f08c3bdfSopenharmony_ci 558f08c3bdfSopenharmony_ci break; case STMT_LABEL: 559f08c3bdfSopenharmony_ci do_statement(mode, stmt->label_statement); 560f08c3bdfSopenharmony_ci 561f08c3bdfSopenharmony_ci } 562f08c3bdfSopenharmony_ci 563f08c3bdfSopenharmony_ci return ret; 564f08c3bdfSopenharmony_ci} 565f08c3bdfSopenharmony_ci 566f08c3bdfSopenharmony_cistatic struct symbol *do_initializer(struct symbol *type, struct expression *expr) 567f08c3bdfSopenharmony_ci{ 568f08c3bdfSopenharmony_ci struct symbol *m_type; 569f08c3bdfSopenharmony_ci struct expression *m_expr; 570f08c3bdfSopenharmony_ci int m_addr; 571f08c3bdfSopenharmony_ci 572f08c3bdfSopenharmony_ci if (expr) switch (expr->type) { 573f08c3bdfSopenharmony_ci default: 574f08c3bdfSopenharmony_ci do_expression(u_lval(type), expr); 575f08c3bdfSopenharmony_ci 576f08c3bdfSopenharmony_ci break; case EXPR_INDEX: 577f08c3bdfSopenharmony_ci do_initializer(base_type(type), expr->idx_expression); 578f08c3bdfSopenharmony_ci 579f08c3bdfSopenharmony_ci break; case EXPR_INITIALIZER: 580f08c3bdfSopenharmony_ci m_addr = 0; 581f08c3bdfSopenharmony_ci FOR_EACH_PTR(expr->expr_list, m_expr) { 582f08c3bdfSopenharmony_ci if (type->type == SYM_ARRAY) { 583f08c3bdfSopenharmony_ci m_type = base_type(type); 584f08c3bdfSopenharmony_ci if (m_expr->type == EXPR_INDEX) 585f08c3bdfSopenharmony_ci m_expr = m_expr->idx_expression; 586f08c3bdfSopenharmony_ci } else { 587f08c3bdfSopenharmony_ci int *m_atop = &m_addr; 588f08c3bdfSopenharmony_ci 589f08c3bdfSopenharmony_ci m_type = type; 590f08c3bdfSopenharmony_ci while (m_expr->type == EXPR_IDENTIFIER) { 591f08c3bdfSopenharmony_ci m_type = report_member(U_W_VAL, &m_expr->pos, m_type, 592f08c3bdfSopenharmony_ci lookup_member(m_type, m_expr->expr_ident, m_atop)); 593f08c3bdfSopenharmony_ci m_expr = m_expr->ident_expression; 594f08c3bdfSopenharmony_ci m_atop = NULL; 595f08c3bdfSopenharmony_ci } 596f08c3bdfSopenharmony_ci 597f08c3bdfSopenharmony_ci if (m_atop) { 598f08c3bdfSopenharmony_ci m_type = report_member(U_W_VAL, &m_expr->pos, m_type, 599f08c3bdfSopenharmony_ci lookup_member(m_type, NULL, m_atop)); 600f08c3bdfSopenharmony_ci } 601f08c3bdfSopenharmony_ci 602f08c3bdfSopenharmony_ci if (m_expr->type != EXPR_INITIALIZER) 603f08c3bdfSopenharmony_ci report_implicit(U_W_VAL, &m_expr->pos, m_type); 604f08c3bdfSopenharmony_ci } 605f08c3bdfSopenharmony_ci do_initializer(m_type, m_expr); 606f08c3bdfSopenharmony_ci m_addr++; 607f08c3bdfSopenharmony_ci } END_FOR_EACH_PTR(m_expr); 608f08c3bdfSopenharmony_ci } 609f08c3bdfSopenharmony_ci 610f08c3bdfSopenharmony_ci return type; 611f08c3bdfSopenharmony_ci} 612f08c3bdfSopenharmony_ci 613f08c3bdfSopenharmony_cistatic inline struct symbol *do_symbol(struct symbol *sym) 614f08c3bdfSopenharmony_ci{ 615f08c3bdfSopenharmony_ci struct symbol *type = base_type(sym); 616f08c3bdfSopenharmony_ci struct symbol *dctx = dissect_ctx; 617f08c3bdfSopenharmony_ci struct statement *stmt; 618f08c3bdfSopenharmony_ci 619f08c3bdfSopenharmony_ci reporter->r_symdef(sym); 620f08c3bdfSopenharmony_ci 621f08c3bdfSopenharmony_ci switch (type->type) { 622f08c3bdfSopenharmony_ci default: 623f08c3bdfSopenharmony_ci if (!sym->initializer) 624f08c3bdfSopenharmony_ci break; 625f08c3bdfSopenharmony_ci reporter->r_symbol(U_W_VAL, &sym->pos, sym); 626f08c3bdfSopenharmony_ci if (!dctx) 627f08c3bdfSopenharmony_ci dissect_ctx = sym; 628f08c3bdfSopenharmony_ci do_initializer(type, sym->initializer); 629f08c3bdfSopenharmony_ci dissect_ctx = dctx; 630f08c3bdfSopenharmony_ci 631f08c3bdfSopenharmony_ci break; case SYM_FN: 632f08c3bdfSopenharmony_ci stmt = sym->ctype.modifiers & MOD_INLINE 633f08c3bdfSopenharmony_ci ? type->inline_stmt : type->stmt; 634f08c3bdfSopenharmony_ci if (!stmt) 635f08c3bdfSopenharmony_ci break; 636f08c3bdfSopenharmony_ci 637f08c3bdfSopenharmony_ci if (dctx) 638f08c3bdfSopenharmony_ci sparse_error(dctx->pos, "dissect_ctx change %s -> %s", 639f08c3bdfSopenharmony_ci show_ident(dctx->ident), show_ident(sym->ident)); 640f08c3bdfSopenharmony_ci 641f08c3bdfSopenharmony_ci dissect_ctx = sym; 642f08c3bdfSopenharmony_ci do_sym_list(type->arguments); 643f08c3bdfSopenharmony_ci do_statement(U_VOID, stmt); 644f08c3bdfSopenharmony_ci dissect_ctx = dctx; 645f08c3bdfSopenharmony_ci } 646f08c3bdfSopenharmony_ci 647f08c3bdfSopenharmony_ci return type; 648f08c3bdfSopenharmony_ci} 649f08c3bdfSopenharmony_ci 650f08c3bdfSopenharmony_cistatic void do_sym_list(struct symbol_list *list) 651f08c3bdfSopenharmony_ci{ 652f08c3bdfSopenharmony_ci DO_LIST(list, sym, do_symbol(sym)); 653f08c3bdfSopenharmony_ci} 654f08c3bdfSopenharmony_ci 655f08c3bdfSopenharmony_civoid dissect(struct reporter *rep, struct string_list *filelist) 656f08c3bdfSopenharmony_ci{ 657f08c3bdfSopenharmony_ci reporter = rep; 658f08c3bdfSopenharmony_ci 659f08c3bdfSopenharmony_ci DO_LIST(filelist, file, do_sym_list(__sparse(file))); 660f08c3bdfSopenharmony_ci} 661