static void compile_cplus_convert_struct_or_union_methods (compile_cplus_instance *instance, struct type *type, gcc_type class_type) { for (int i = 0; i < TYPE_NFN_FIELDS (type); ++i) { struct fn_field *methods = TYPE_FN_FIELDLIST1 (type, i); gdb::unique_xmalloc_ptr<char> overloaded_name = compile_cplus_instance::decl_name (TYPE_FN_FIELDLIST_NAME (type, i)); /* Loop through the fieldlist, adding decls to the compiler's representation of the class. */ for (int j = 0; j < TYPE_FN_FIELDLIST_LENGTH (type, i); ++j) { /* Skip artificial methods. */ if (TYPE_FN_FIELD_ARTIFICIAL (methods, j)) continue; gcc_cp_symbol_kind_flags sym_kind = GCC_CP_SYMBOL_FUNCTION; gcc_type method_type; struct block_symbol sym = lookup_symbol (TYPE_FN_FIELD_PHYSNAME (methods, j), instance->block (), VAR_DOMAIN, nullptr); if (sym.symbol == nullptr) { if (TYPE_FN_FIELD_VIRTUAL_P (methods, j)) { /* This is beyond hacky, and is really only a workaround for detecting pure virtual methods. */ method_type = compile_cplus_convert_method (instance, type, TYPE_FN_FIELD_TYPE (methods, j)); instance->plugin ().build_decl ("pure virtual method", overloaded_name.get (), (sym_kind | get_method_access_flag (type, i, j) | GCC_CP_FLAG_VIRTUAL_FUNCTION | GCC_CP_FLAG_PURE_VIRTUAL_FUNCTION), method_type, nullptr, 0, nullptr, 0); continue; } /* This can happen if we have a DW_AT_declaration DIE for the method, but no "definition"-type DIE (with DW_AT_specification referencing the decl DIE), i.e., the compiler has probably optimized the method away. In this case, all we can hope to do is issue a warning to the user letting him know. If the user has not actually requested using this method, things should still work. */ warning (_("Method %s appears to be optimized out.\n" "All references to this method will be undefined."), TYPE_FN_FIELD_PHYSNAME (methods, j)); continue; } const char *filename = symbol_symtab (sym.symbol)->filename; unsigned int line = SYMBOL_LINE (sym.symbol); CORE_ADDR address = BLOCK_START (SYMBOL_BLOCK_VALUE (sym.symbol)); const char *kind; if (TYPE_FN_FIELD_STATIC_P (methods, j)) { kind = "static method"; method_type = compile_cplus_convert_func (instance, TYPE_FN_FIELD_TYPE (methods, j), true); } else { kind = "method"; method_type = (compile_cplus_convert_method (instance, type, TYPE_FN_FIELD_TYPE (methods, j))); } if (TYPE_FN_FIELD_VIRTUAL_P (methods, j)) sym_kind |= GCC_CP_FLAG_VIRTUAL_FUNCTION; instance->plugin ().build_decl (kind, overloaded_name.get (), sym_kind | get_method_access_flag (type, i, j), method_type, nullptr, address, filename, line); } } }
static void convert_one_symbol (struct compile_c_instance *context, struct symbol *sym, int is_global, int is_local) { gcc_type sym_type; const char *filename = symbol_symtab (sym)->filename; unsigned short line = SYMBOL_LINE (sym); error_symbol_once (context, sym); if (SYMBOL_CLASS (sym) == LOC_LABEL) sym_type = 0; else sym_type = convert_type (context, SYMBOL_TYPE (sym)); if (SYMBOL_DOMAIN (sym) == STRUCT_DOMAIN) { /* Binding a tag, so we don't need to build a decl. */ C_CTX (context)->c_ops->tagbind (C_CTX (context), SYMBOL_NATURAL_NAME (sym), sym_type, filename, line); } else { gcc_decl decl; enum gcc_c_symbol_kind kind; CORE_ADDR addr = 0; char *symbol_name = NULL; switch (SYMBOL_CLASS (sym)) { case LOC_TYPEDEF: kind = GCC_C_SYMBOL_TYPEDEF; break; case LOC_LABEL: kind = GCC_C_SYMBOL_LABEL; addr = SYMBOL_VALUE_ADDRESS (sym); break; case LOC_BLOCK: kind = GCC_C_SYMBOL_FUNCTION; addr = BLOCK_START (SYMBOL_BLOCK_VALUE (sym)); if (is_global && TYPE_GNU_IFUNC (SYMBOL_TYPE (sym))) addr = gnu_ifunc_resolve_addr (target_gdbarch (), addr); break; case LOC_CONST: if (TYPE_CODE (SYMBOL_TYPE (sym)) == TYPE_CODE_ENUM) { /* Already handled by convert_enum. */ return; } C_CTX (context)->c_ops->build_constant (C_CTX (context), sym_type, SYMBOL_NATURAL_NAME (sym), SYMBOL_VALUE (sym), filename, line); return; case LOC_CONST_BYTES: error (_("Unsupported LOC_CONST_BYTES for symbol \"%s\"."), SYMBOL_PRINT_NAME (sym)); case LOC_UNDEF: internal_error (__FILE__, __LINE__, _("LOC_UNDEF found for \"%s\"."), SYMBOL_PRINT_NAME (sym)); case LOC_COMMON_BLOCK: error (_("Fortran common block is unsupported for compilation " "evaluaton of symbol \"%s\"."), SYMBOL_PRINT_NAME (sym)); case LOC_OPTIMIZED_OUT: error (_("Symbol \"%s\" cannot be used for compilation evaluation " "as it is optimized out."), SYMBOL_PRINT_NAME (sym)); case LOC_COMPUTED: if (is_local) goto substitution; /* Probably TLS here. */ warning (_("Symbol \"%s\" is thread-local and currently can only " "be referenced from the current thread in " "compiled code."), SYMBOL_PRINT_NAME (sym)); /* FALLTHROUGH */ case LOC_UNRESOLVED: /* 'symbol_name' cannot be used here as that one is used only for local variables from compile_dwarf_expr_to_c. Global variables can be accessed by GCC only by their address, not by their name. */ { struct value *val; struct frame_info *frame = NULL; if (symbol_read_needs_frame (sym)) { frame = get_selected_frame (NULL); if (frame == NULL) error (_("Symbol \"%s\" cannot be used because " "there is no selected frame"), SYMBOL_PRINT_NAME (sym)); } val = read_var_value (sym, frame); if (VALUE_LVAL (val) != lval_memory) error (_("Symbol \"%s\" cannot be used for compilation " "evaluation as its address has not been found."), SYMBOL_PRINT_NAME (sym)); kind = GCC_C_SYMBOL_VARIABLE; addr = value_address (val); } break; case LOC_REGISTER: case LOC_ARG: case LOC_REF_ARG: case LOC_REGPARM_ADDR: case LOC_LOCAL: substitution: kind = GCC_C_SYMBOL_VARIABLE; symbol_name = symbol_substitution_name (sym); break; case LOC_STATIC: kind = GCC_C_SYMBOL_VARIABLE; addr = SYMBOL_VALUE_ADDRESS (sym); break; case LOC_FINAL_VALUE: default: gdb_assert_not_reached ("Unreachable case in convert_one_symbol."); } /* Don't emit local variable decls for a raw expression. */ if (context->base.scope != COMPILE_I_RAW_SCOPE || symbol_name == NULL) { decl = C_CTX (context)->c_ops->build_decl (C_CTX (context), SYMBOL_NATURAL_NAME (sym), kind, sym_type, symbol_name, addr, filename, line); C_CTX (context)->c_ops->bind (C_CTX (context), decl, is_global); } xfree (symbol_name); } }
static void compile_cplus_convert_struct_or_union_members (compile_cplus_instance *instance, struct type *type, gcc_type comp_type) { for (int i = TYPE_N_BASECLASSES (type); i < TYPE_NFIELDS (type); ++i) { const char *field_name = TYPE_FIELD_NAME (type, i); if (TYPE_FIELD_IGNORE (type, i) || TYPE_FIELD_ARTIFICIAL (type, i)) continue; /* GDB records unnamed/anonymous fields with empty string names. */ if (*field_name == '\0') field_name = nullptr; gcc_type field_type = instance->convert_type (TYPE_FIELD_TYPE (type, i)); if (field_is_static (&TYPE_FIELD (type, i))) { CORE_ADDR physaddr; switch (TYPE_FIELD_LOC_KIND (type, i)) { case FIELD_LOC_KIND_PHYSADDR: { physaddr = TYPE_FIELD_STATIC_PHYSADDR (type, i); instance->plugin ().build_decl ("field physaddr", field_name, (GCC_CP_SYMBOL_VARIABLE | get_field_access_flag (type, i)), field_type, nullptr, physaddr, nullptr, 0); } break; case FIELD_LOC_KIND_PHYSNAME: { const char *physname = TYPE_FIELD_STATIC_PHYSNAME (type, i); struct block_symbol sym = lookup_symbol (physname, instance->block (), VAR_DOMAIN, nullptr); if (sym.symbol == nullptr) { /* We didn't actually find the symbol. There's little we can do but ignore this member. */ continue; } const char *filename = symbol_symtab (sym.symbol)->filename; unsigned int line = SYMBOL_LINE (sym.symbol); physaddr = SYMBOL_VALUE_ADDRESS (sym.symbol); instance->plugin ().build_decl ("field physname", field_name, (GCC_CP_SYMBOL_VARIABLE| get_field_access_flag (type, i)), field_type, nullptr, physaddr, filename, line); } break; default: gdb_assert_not_reached ("unexpected static field location kind"); } } else { unsigned long bitsize = TYPE_FIELD_BITSIZE (type, i); enum gcc_cp_symbol_kind field_flags = GCC_CP_SYMBOL_FIELD | get_field_access_flag (type, i); if (bitsize == 0) bitsize = 8 * TYPE_LENGTH (TYPE_FIELD_TYPE (type, i)); instance->plugin ().build_field (field_name, field_type, field_flags, bitsize, TYPE_FIELD_BITPOS (type, i)); } } }