OLD | NEW |
1 /* Abstraction of GNU v3 abi. | 1 /* Abstraction of GNU v3 abi. |
2 Contributed by Jim Blandy <jimb@redhat.com> | 2 Contributed by Jim Blandy <jimb@redhat.com> |
3 | 3 |
4 Copyright (C) 2001-2003, 2005-2012 Free Software Foundation, Inc. | 4 Copyright (C) 2001-2003, 2005-2012 Free Software Foundation, Inc. |
5 | 5 |
6 This file is part of GDB. | 6 This file is part of GDB. |
7 | 7 |
8 This program is free software; you can redistribute it and/or modify | 8 This program is free software; you can redistribute it and/or modify |
9 it under the terms of the GNU General Public License as published by | 9 it under the terms of the GNU General Public License as published by |
10 the Free Software Foundation; either version 3 of the License, or | 10 the Free Software Foundation; either version 3 of the License, or |
11 (at your option) any later version. | 11 (at your option) any later version. |
12 | 12 |
13 This program is distributed in the hope that it will be useful, | 13 This program is distributed in the hope that it will be useful, |
14 but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 GNU General Public License for more details. | 16 GNU General Public License for more details. |
17 | 17 |
18 You should have received a copy of the GNU General Public License | 18 You should have received a copy of the GNU General Public License |
19 along with this program. If not, see <http://www.gnu.org/licenses/>. */ | 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
20 | 20 |
21 #include "defs.h" | 21 #include "defs.h" |
22 #include "value.h" | 22 #include "value.h" |
23 #include "cp-abi.h" | 23 #include "cp-abi.h" |
24 #include "cp-support.h" | 24 #include "cp-support.h" |
25 #include "demangle.h" | 25 #include "demangle.h" |
26 #include "objfiles.h" | 26 #include "objfiles.h" |
27 #include "valprint.h" | 27 #include "valprint.h" |
28 #include "c-lang.h" | 28 #include "c-lang.h" |
| 29 #include "exceptions.h" |
29 | 30 |
30 #include "gdb_assert.h" | 31 #include "gdb_assert.h" |
31 #include "gdb_string.h" | 32 #include "gdb_string.h" |
32 | 33 |
33 static struct cp_abi_ops gnu_v3_abi_ops; | 34 static struct cp_abi_ops gnu_v3_abi_ops; |
34 | 35 |
35 static int | 36 static int |
36 gnuv3_is_vtable_name (const char *name) | 37 gnuv3_is_vtable_name (const char *name) |
37 { | 38 { |
38 return strncmp (name, "_ZTV", 4) == 0; | 39 return strncmp (name, "_ZTV", 4) == 0; |
(...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
122 | 123 |
123 /* Build the field list. */ | 124 /* Build the field list. */ |
124 field_list = xmalloc (sizeof (struct field [4])); | 125 field_list = xmalloc (sizeof (struct field [4])); |
125 memset (field_list, 0, sizeof (struct field [4])); | 126 memset (field_list, 0, sizeof (struct field [4])); |
126 field = &field_list[0]; | 127 field = &field_list[0]; |
127 offset = 0; | 128 offset = 0; |
128 | 129 |
129 /* ptrdiff_t vcall_and_vbase_offsets[0]; */ | 130 /* ptrdiff_t vcall_and_vbase_offsets[0]; */ |
130 FIELD_NAME (*field) = "vcall_and_vbase_offsets"; | 131 FIELD_NAME (*field) = "vcall_and_vbase_offsets"; |
131 FIELD_TYPE (*field) = lookup_array_range_type (ptrdiff_type, 0, -1); | 132 FIELD_TYPE (*field) = lookup_array_range_type (ptrdiff_type, 0, -1); |
132 FIELD_BITPOS (*field) = offset * TARGET_CHAR_BIT; | 133 SET_FIELD_BITPOS (*field, offset * TARGET_CHAR_BIT); |
133 offset += TYPE_LENGTH (FIELD_TYPE (*field)); | 134 offset += TYPE_LENGTH (FIELD_TYPE (*field)); |
134 field++; | 135 field++; |
135 | 136 |
136 /* ptrdiff_t offset_to_top; */ | 137 /* ptrdiff_t offset_to_top; */ |
137 FIELD_NAME (*field) = "offset_to_top"; | 138 FIELD_NAME (*field) = "offset_to_top"; |
138 FIELD_TYPE (*field) = ptrdiff_type; | 139 FIELD_TYPE (*field) = ptrdiff_type; |
139 FIELD_BITPOS (*field) = offset * TARGET_CHAR_BIT; | 140 SET_FIELD_BITPOS (*field, offset * TARGET_CHAR_BIT); |
140 offset += TYPE_LENGTH (FIELD_TYPE (*field)); | 141 offset += TYPE_LENGTH (FIELD_TYPE (*field)); |
141 field++; | 142 field++; |
142 | 143 |
143 /* void *type_info; */ | 144 /* void *type_info; */ |
144 FIELD_NAME (*field) = "type_info"; | 145 FIELD_NAME (*field) = "type_info"; |
145 FIELD_TYPE (*field) = void_ptr_type; | 146 FIELD_TYPE (*field) = void_ptr_type; |
146 FIELD_BITPOS (*field) = offset * TARGET_CHAR_BIT; | 147 SET_FIELD_BITPOS (*field, offset * TARGET_CHAR_BIT); |
147 offset += TYPE_LENGTH (FIELD_TYPE (*field)); | 148 offset += TYPE_LENGTH (FIELD_TYPE (*field)); |
148 field++; | 149 field++; |
149 | 150 |
150 /* void (*virtual_functions[0]) (); */ | 151 /* void (*virtual_functions[0]) (); */ |
151 FIELD_NAME (*field) = "virtual_functions"; | 152 FIELD_NAME (*field) = "virtual_functions"; |
152 FIELD_TYPE (*field) = lookup_array_range_type (ptr_to_void_fn_type, 0, -1); | 153 FIELD_TYPE (*field) = lookup_array_range_type (ptr_to_void_fn_type, 0, -1); |
153 FIELD_BITPOS (*field) = offset * TARGET_CHAR_BIT; | 154 SET_FIELD_BITPOS (*field, offset * TARGET_CHAR_BIT); |
154 offset += TYPE_LENGTH (FIELD_TYPE (*field)); | 155 offset += TYPE_LENGTH (FIELD_TYPE (*field)); |
155 field++; | 156 field++; |
156 | 157 |
157 /* We assumed in the allocation above that there were four fields. */ | 158 /* We assumed in the allocation above that there were four fields. */ |
158 gdb_assert (field == (field_list + 4)); | 159 gdb_assert (field == (field_list + 4)); |
159 | 160 |
160 t = arch_type (arch, TYPE_CODE_STRUCT, offset, NULL); | 161 t = arch_type (arch, TYPE_CODE_STRUCT, offset, NULL); |
161 TYPE_NFIELDS (t) = field - field_list; | 162 TYPE_NFIELDS (t) = field - field_list; |
162 TYPE_FIELDS (t) = field_list; | 163 TYPE_FIELDS (t) = field_list; |
163 TYPE_TAG_NAME (t) = "gdb_gnu_v3_abi_vtable"; | 164 TYPE_TAG_NAME (t) = "gdb_gnu_v3_abi_vtable"; |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 struct type *ptr_type; | 423 struct type *ptr_type; |
423 struct value *vtable; | 424 struct value *vtable; |
424 struct value *vbase_array; | 425 struct value *vbase_array; |
425 long int cur_base_offset, base_offset; | 426 long int cur_base_offset, base_offset; |
426 | 427 |
427 /* Determine architecture. */ | 428 /* Determine architecture. */ |
428 gdbarch = get_type_arch (type); | 429 gdbarch = get_type_arch (type); |
429 ptr_type = builtin_type (gdbarch)->builtin_data_ptr; | 430 ptr_type = builtin_type (gdbarch)->builtin_data_ptr; |
430 | 431 |
431 /* If it isn't a virtual base, this is easy. The offset is in the | 432 /* If it isn't a virtual base, this is easy. The offset is in the |
432 type definition. */ | 433 type definition. Likewise for Java, which doesn't really have |
433 if (!BASETYPE_VIA_VIRTUAL (type, index)) | 434 virtual inheritance in the C++ sense. */ |
| 435 if (!BASETYPE_VIA_VIRTUAL (type, index) || TYPE_CPLUS_REALLY_JAVA (type)) |
434 return TYPE_BASECLASS_BITPOS (type, index) / 8; | 436 return TYPE_BASECLASS_BITPOS (type, index) / 8; |
435 | 437 |
436 /* To access a virtual base, we need to use the vbase offset stored in | 438 /* To access a virtual base, we need to use the vbase offset stored in |
437 our vtable. Recent GCC versions provide this information. If it isn't | 439 our vtable. Recent GCC versions provide this information. If it isn't |
438 available, we could get what we needed from RTTI, or from drawing the | 440 available, we could get what we needed from RTTI, or from drawing the |
439 complete inheritance graph based on the debug info. Neither is | 441 complete inheritance graph based on the debug info. Neither is |
440 worthwhile. */ | 442 worthwhile. */ |
441 cur_base_offset = TYPE_BASECLASS_BITPOS (type, index) / 8; | 443 cur_base_offset = TYPE_BASECLASS_BITPOS (type, index) / 8; |
442 if (cur_base_offset >= - vtable_address_point_offset (gdbarch)) | 444 if (cur_base_offset >= - vtable_address_point_offset (gdbarch)) |
443 error (_("Expected a negative vbase offset (old compiler?)")); | 445 error (_("Expected a negative vbase offset (old compiler?)")); |
(...skipping 168 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
612 fputs_filtered (") ", stream); | 614 fputs_filtered (") ", stream); |
613 } | 615 } |
614 | 616 |
615 /* We didn't find it; print the raw data. */ | 617 /* We didn't find it; print the raw data. */ |
616 if (vbit) | 618 if (vbit) |
617 { | 619 { |
618 fprintf_filtered (stream, "&virtual table offset "); | 620 fprintf_filtered (stream, "&virtual table offset "); |
619 print_longest (stream, 'd', 1, ptr_value); | 621 print_longest (stream, 'd', 1, ptr_value); |
620 } | 622 } |
621 else | 623 else |
622 print_address_demangle (gdbarch, ptr_value, stream, demangle); | 624 { |
| 625 struct value_print_options opts; |
| 626 |
| 627 get_user_print_options (&opts); |
| 628 print_address_demangle (&opts, gdbarch, ptr_value, stream, demangle); |
| 629 } |
623 | 630 |
624 if (adjustment) | 631 if (adjustment) |
625 { | 632 { |
626 fprintf_filtered (stream, ", this adjustment "); | 633 fprintf_filtered (stream, ", this adjustment "); |
627 print_longest (stream, 'd', 1, adjustment); | 634 print_longest (stream, 'd', 1, adjustment); |
628 } | 635 } |
629 } | 636 } |
630 | 637 |
631 /* GNU v3 implementation of cplus_method_ptr_size. */ | 638 /* GNU v3 implementation of cplus_method_ptr_size. */ |
632 | 639 |
(...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
718 LONGEST voffset; | 725 LONGEST voffset; |
719 | 726 |
720 voffset = ptr_value / TYPE_LENGTH (vtable_ptrdiff_type (gdbarch)); | 727 voffset = ptr_value / TYPE_LENGTH (vtable_ptrdiff_type (gdbarch)); |
721 return gnuv3_get_virtual_fn (gdbarch, value_ind (*this_p), | 728 return gnuv3_get_virtual_fn (gdbarch, value_ind (*this_p), |
722 method_type, voffset); | 729 method_type, voffset); |
723 } | 730 } |
724 else | 731 else |
725 return value_from_pointer (lookup_pointer_type (method_type), ptr_value); | 732 return value_from_pointer (lookup_pointer_type (method_type), ptr_value); |
726 } | 733 } |
727 | 734 |
| 735 /* Objects of this type are stored in a hash table and a vector when |
| 736 printing the vtables for a class. */ |
| 737 |
| 738 struct value_and_voffset |
| 739 { |
| 740 /* The value representing the object. */ |
| 741 struct value *value; |
| 742 |
| 743 /* The maximum vtable offset we've found for any object at this |
| 744 offset in the outermost object. */ |
| 745 int max_voffset; |
| 746 }; |
| 747 |
| 748 typedef struct value_and_voffset *value_and_voffset_p; |
| 749 DEF_VEC_P (value_and_voffset_p); |
| 750 |
| 751 /* Hash function for value_and_voffset. */ |
| 752 |
| 753 static hashval_t |
| 754 hash_value_and_voffset (const void *p) |
| 755 { |
| 756 const struct value_and_voffset *o = p; |
| 757 |
| 758 return value_address (o->value) + value_embedded_offset (o->value); |
| 759 } |
| 760 |
| 761 /* Equality function for value_and_voffset. */ |
| 762 |
| 763 static int |
| 764 eq_value_and_voffset (const void *a, const void *b) |
| 765 { |
| 766 const struct value_and_voffset *ova = a; |
| 767 const struct value_and_voffset *ovb = b; |
| 768 |
| 769 return (value_address (ova->value) + value_embedded_offset (ova->value) |
| 770 == value_address (ovb->value) + value_embedded_offset (ovb->value)); |
| 771 } |
| 772 |
| 773 /* qsort comparison function for value_and_voffset. */ |
| 774 |
| 775 static int |
| 776 compare_value_and_voffset (const void *a, const void *b) |
| 777 { |
| 778 const struct value_and_voffset * const *ova = a; |
| 779 CORE_ADDR addra = (value_address ((*ova)->value) |
| 780 + value_embedded_offset ((*ova)->value)); |
| 781 const struct value_and_voffset * const *ovb = b; |
| 782 CORE_ADDR addrb = (value_address ((*ovb)->value) |
| 783 + value_embedded_offset ((*ovb)->value)); |
| 784 |
| 785 if (addra < addrb) |
| 786 return -1; |
| 787 if (addra > addrb) |
| 788 return 1; |
| 789 return 0; |
| 790 } |
| 791 |
| 792 /* A helper function used when printing vtables. This determines the |
| 793 key (most derived) sub-object at each address and also computes the |
| 794 maximum vtable offset seen for the corresponding vtable. Updates |
| 795 OFFSET_HASH and OFFSET_VEC with a new value_and_voffset object, if |
| 796 needed. VALUE is the object to examine. */ |
| 797 |
| 798 static void |
| 799 compute_vtable_size (htab_t offset_hash, |
| 800 VEC (value_and_voffset_p) **offset_vec, |
| 801 struct value *value) |
| 802 { |
| 803 int i; |
| 804 struct type *type = check_typedef (value_type (value)); |
| 805 void **slot; |
| 806 struct value_and_voffset search_vo, *current_vo; |
| 807 CORE_ADDR addr = value_address (value) + value_embedded_offset (value); |
| 808 |
| 809 /* If the object is not dynamic, then we are done; as it cannot have |
| 810 dynamic base types either. */ |
| 811 if (!gnuv3_dynamic_class (type)) |
| 812 return; |
| 813 |
| 814 /* Update the hash and the vec, if needed. */ |
| 815 search_vo.value = value; |
| 816 slot = htab_find_slot (offset_hash, &search_vo, INSERT); |
| 817 if (*slot) |
| 818 current_vo = *slot; |
| 819 else |
| 820 { |
| 821 current_vo = XNEW (struct value_and_voffset); |
| 822 current_vo->value = value; |
| 823 current_vo->max_voffset = -1; |
| 824 *slot = current_vo; |
| 825 VEC_safe_push (value_and_voffset_p, *offset_vec, current_vo); |
| 826 } |
| 827 |
| 828 /* Update the value_and_voffset object with the highest vtable |
| 829 offset from this class. */ |
| 830 for (i = 0; i < TYPE_NFN_FIELDS (type); ++i) |
| 831 { |
| 832 int j; |
| 833 struct fn_field *fn = TYPE_FN_FIELDLIST1 (type, i); |
| 834 |
| 835 for (j = 0; j < TYPE_FN_FIELDLIST_LENGTH (type, i); ++j) |
| 836 { |
| 837 if (TYPE_FN_FIELD_VIRTUAL_P (fn, j)) |
| 838 { |
| 839 int voffset = TYPE_FN_FIELD_VOFFSET (fn, j); |
| 840 |
| 841 if (voffset > current_vo->max_voffset) |
| 842 current_vo->max_voffset = voffset; |
| 843 } |
| 844 } |
| 845 } |
| 846 |
| 847 /* Recurse into base classes. */ |
| 848 for (i = 0; i < TYPE_N_BASECLASSES (type); ++i) |
| 849 compute_vtable_size (offset_hash, offset_vec, value_field (value, i)); |
| 850 } |
| 851 |
| 852 /* Helper for gnuv3_print_vtable that prints a single vtable. */ |
| 853 |
| 854 static void |
| 855 print_one_vtable (struct gdbarch *gdbarch, struct value *value, |
| 856 int max_voffset, |
| 857 struct value_print_options *opts) |
| 858 { |
| 859 int i; |
| 860 struct type *type = check_typedef (value_type (value)); |
| 861 struct value *vtable; |
| 862 CORE_ADDR vt_addr; |
| 863 |
| 864 vtable = gnuv3_get_vtable (gdbarch, type, |
| 865 value_address (value) |
| 866 + value_embedded_offset (value)); |
| 867 vt_addr = value_address (value_field (vtable, |
| 868 vtable_field_virtual_functions)); |
| 869 |
| 870 printf_filtered (_("vtable for '%s' @ %s (subobject @ %s):\n"), |
| 871 TYPE_SAFE_NAME (type), |
| 872 paddress (gdbarch, vt_addr), |
| 873 paddress (gdbarch, (value_address (value) |
| 874 + value_embedded_offset (value)))); |
| 875 |
| 876 for (i = 0; i <= max_voffset; ++i) |
| 877 { |
| 878 /* Initialize it just to avoid a GCC false warning. */ |
| 879 CORE_ADDR addr = 0; |
| 880 struct value *vfn; |
| 881 volatile struct gdb_exception ex; |
| 882 |
| 883 printf_filtered ("[%d]: ", i); |
| 884 |
| 885 vfn = value_subscript (value_field (vtable, |
| 886 vtable_field_virtual_functions), |
| 887 i); |
| 888 |
| 889 if (gdbarch_vtable_function_descriptors (gdbarch)) |
| 890 vfn = value_addr (vfn); |
| 891 |
| 892 TRY_CATCH (ex, RETURN_MASK_ERROR) |
| 893 { |
| 894 addr = value_as_address (vfn); |
| 895 } |
| 896 if (ex.reason < 0) |
| 897 printf_filtered (_("<error: %s>"), ex.message); |
| 898 else |
| 899 print_function_pointer_address (opts, gdbarch, addr, gdb_stdout); |
| 900 printf_filtered ("\n"); |
| 901 } |
| 902 } |
| 903 |
| 904 /* Implementation of the print_vtable method. */ |
| 905 |
| 906 static void |
| 907 gnuv3_print_vtable (struct value *value) |
| 908 { |
| 909 struct gdbarch *gdbarch; |
| 910 struct type *type; |
| 911 struct value *vtable; |
| 912 struct value_print_options opts; |
| 913 htab_t offset_hash; |
| 914 struct cleanup *cleanup; |
| 915 VEC (value_and_voffset_p) *result_vec = NULL; |
| 916 struct value_and_voffset *iter; |
| 917 int i, count; |
| 918 |
| 919 value = coerce_ref (value); |
| 920 type = check_typedef (value_type (value)); |
| 921 if (TYPE_CODE (type) == TYPE_CODE_PTR) |
| 922 { |
| 923 value = value_ind (value); |
| 924 type = check_typedef (value_type (value)); |
| 925 } |
| 926 |
| 927 get_user_print_options (&opts); |
| 928 |
| 929 /* Respect 'set print object'. */ |
| 930 if (opts.objectprint) |
| 931 { |
| 932 value = value_full_object (value, NULL, 0, 0, 0); |
| 933 type = check_typedef (value_type (value)); |
| 934 } |
| 935 |
| 936 gdbarch = get_type_arch (type); |
| 937 vtable = gnuv3_get_vtable (gdbarch, type, |
| 938 value_as_address (value_addr (value))); |
| 939 |
| 940 if (!vtable) |
| 941 { |
| 942 printf_filtered (_("This object does not have a virtual function table\n")
); |
| 943 return; |
| 944 } |
| 945 |
| 946 offset_hash = htab_create_alloc (1, hash_value_and_voffset, |
| 947 eq_value_and_voffset, |
| 948 xfree, xcalloc, xfree); |
| 949 cleanup = make_cleanup_htab_delete (offset_hash); |
| 950 make_cleanup (VEC_cleanup (value_and_voffset_p), &result_vec); |
| 951 |
| 952 compute_vtable_size (offset_hash, &result_vec, value); |
| 953 |
| 954 qsort (VEC_address (value_and_voffset_p, result_vec), |
| 955 VEC_length (value_and_voffset_p, result_vec), |
| 956 sizeof (value_and_voffset_p), |
| 957 compare_value_and_voffset); |
| 958 |
| 959 count = 0; |
| 960 for (i = 0; VEC_iterate (value_and_voffset_p, result_vec, i, iter); ++i) |
| 961 { |
| 962 if (iter->max_voffset >= 0) |
| 963 { |
| 964 if (count > 0) |
| 965 printf_filtered ("\n"); |
| 966 print_one_vtable (gdbarch, iter->value, iter->max_voffset, &opts); |
| 967 ++count; |
| 968 } |
| 969 } |
| 970 |
| 971 do_cleanups (cleanup); |
| 972 } |
| 973 |
728 /* Determine if we are currently in a C++ thunk. If so, get the address | 974 /* Determine if we are currently in a C++ thunk. If so, get the address |
729 of the routine we are thunking to and continue to there instead. */ | 975 of the routine we are thunking to and continue to there instead. */ |
730 | 976 |
731 static CORE_ADDR | 977 static CORE_ADDR |
732 gnuv3_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc) | 978 gnuv3_skip_trampoline (struct frame_info *frame, CORE_ADDR stop_pc) |
733 { | 979 { |
734 CORE_ADDR real_stop_pc, method_stop_pc; | 980 CORE_ADDR real_stop_pc, method_stop_pc; |
735 struct gdbarch *gdbarch = get_frame_arch (frame); | 981 struct gdbarch *gdbarch = get_frame_arch (frame); |
736 struct minimal_symbol *thunk_sym, *fn_sym; | 982 struct minimal_symbol *thunk_sym, *fn_sym; |
737 struct obj_section *section; | 983 struct obj_section *section; |
738 char *thunk_name, *fn_name; | 984 const char *thunk_name, *fn_name; |
739 | 985 |
740 real_stop_pc = gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc); | 986 real_stop_pc = gdbarch_skip_trampoline_code (gdbarch, frame, stop_pc); |
741 if (real_stop_pc == 0) | 987 if (real_stop_pc == 0) |
742 real_stop_pc = stop_pc; | 988 real_stop_pc = stop_pc; |
743 | 989 |
744 /* Find the linker symbol for this potential thunk. */ | 990 /* Find the linker symbol for this potential thunk. */ |
745 thunk_sym = lookup_minimal_symbol_by_pc (real_stop_pc); | 991 thunk_sym = lookup_minimal_symbol_by_pc (real_stop_pc); |
746 section = find_pc_section (real_stop_pc); | 992 section = find_pc_section (real_stop_pc); |
747 if (thunk_sym == NULL || section == NULL) | 993 if (thunk_sym == NULL || section == NULL) |
748 return 0; | 994 return 0; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
797 if (TYPE_CODE (type) != TYPE_CODE_STRUCT | 1043 if (TYPE_CODE (type) != TYPE_CODE_STRUCT |
798 && TYPE_CODE (type) != TYPE_CODE_CLASS | 1044 && TYPE_CODE (type) != TYPE_CODE_CLASS |
799 && TYPE_CODE (type) != TYPE_CODE_UNION) | 1045 && TYPE_CODE (type) != TYPE_CODE_UNION) |
800 return 0; | 1046 return 0; |
801 | 1047 |
802 for (fieldnum = 0; fieldnum < TYPE_NFN_FIELDS (type); fieldnum++) | 1048 for (fieldnum = 0; fieldnum < TYPE_NFN_FIELDS (type); fieldnum++) |
803 for (fieldelem = 0; fieldelem < TYPE_FN_FIELDLIST_LENGTH (type, fieldnum); | 1049 for (fieldelem = 0; fieldelem < TYPE_FN_FIELDLIST_LENGTH (type, fieldnum); |
804 fieldelem++) | 1050 fieldelem++) |
805 { | 1051 { |
806 struct fn_field *fn = TYPE_FN_FIELDLIST1 (type, fieldnum); | 1052 struct fn_field *fn = TYPE_FN_FIELDLIST1 (type, fieldnum); |
807 » char *name = TYPE_FN_FIELDLIST_NAME (type, fieldnum); | 1053 » const char *name = TYPE_FN_FIELDLIST_NAME (type, fieldnum); |
808 struct type *fieldtype = TYPE_FN_FIELD_TYPE (fn, fieldelem); | 1054 struct type *fieldtype = TYPE_FN_FIELD_TYPE (fn, fieldelem); |
809 | 1055 |
810 /* If this function is marked as artificial, it is compiler-generated, | 1056 /* If this function is marked as artificial, it is compiler-generated, |
811 and we assume it is trivial. */ | 1057 and we assume it is trivial. */ |
812 if (TYPE_FN_FIELD_ARTIFICIAL (fn, fieldelem)) | 1058 if (TYPE_FN_FIELD_ARTIFICIAL (fn, fieldelem)) |
813 continue; | 1059 continue; |
814 | 1060 |
815 /* If we've found a destructor, we must pass this by reference. */ | 1061 /* If we've found a destructor, we must pass this by reference. */ |
816 if (name[0] == '~') | 1062 if (name[0] == '~') |
817 return 1; | 1063 return 1; |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
866 (enum ctor_kinds (*) (const char *))is_gnu_v3_mangled_ctor; | 1112 (enum ctor_kinds (*) (const char *))is_gnu_v3_mangled_ctor; |
867 gnu_v3_abi_ops.is_vtable_name = gnuv3_is_vtable_name; | 1113 gnu_v3_abi_ops.is_vtable_name = gnuv3_is_vtable_name; |
868 gnu_v3_abi_ops.is_operator_name = gnuv3_is_operator_name; | 1114 gnu_v3_abi_ops.is_operator_name = gnuv3_is_operator_name; |
869 gnu_v3_abi_ops.rtti_type = gnuv3_rtti_type; | 1115 gnu_v3_abi_ops.rtti_type = gnuv3_rtti_type; |
870 gnu_v3_abi_ops.virtual_fn_field = gnuv3_virtual_fn_field; | 1116 gnu_v3_abi_ops.virtual_fn_field = gnuv3_virtual_fn_field; |
871 gnu_v3_abi_ops.baseclass_offset = gnuv3_baseclass_offset; | 1117 gnu_v3_abi_ops.baseclass_offset = gnuv3_baseclass_offset; |
872 gnu_v3_abi_ops.print_method_ptr = gnuv3_print_method_ptr; | 1118 gnu_v3_abi_ops.print_method_ptr = gnuv3_print_method_ptr; |
873 gnu_v3_abi_ops.method_ptr_size = gnuv3_method_ptr_size; | 1119 gnu_v3_abi_ops.method_ptr_size = gnuv3_method_ptr_size; |
874 gnu_v3_abi_ops.make_method_ptr = gnuv3_make_method_ptr; | 1120 gnu_v3_abi_ops.make_method_ptr = gnuv3_make_method_ptr; |
875 gnu_v3_abi_ops.method_ptr_to_value = gnuv3_method_ptr_to_value; | 1121 gnu_v3_abi_ops.method_ptr_to_value = gnuv3_method_ptr_to_value; |
| 1122 gnu_v3_abi_ops.print_vtable = gnuv3_print_vtable; |
876 gnu_v3_abi_ops.skip_trampoline = gnuv3_skip_trampoline; | 1123 gnu_v3_abi_ops.skip_trampoline = gnuv3_skip_trampoline; |
877 gnu_v3_abi_ops.pass_by_reference = gnuv3_pass_by_reference; | 1124 gnu_v3_abi_ops.pass_by_reference = gnuv3_pass_by_reference; |
878 } | 1125 } |
879 | 1126 |
880 extern initialize_file_ftype _initialize_gnu_v3_abi; /* -Wmissing-prototypes */ | 1127 extern initialize_file_ftype _initialize_gnu_v3_abi; /* -Wmissing-prototypes */ |
881 | 1128 |
882 void | 1129 void |
883 _initialize_gnu_v3_abi (void) | 1130 _initialize_gnu_v3_abi (void) |
884 { | 1131 { |
885 init_gnuv3_ops (); | 1132 init_gnuv3_ops (); |
886 | 1133 |
887 register_cp_abi (&gnu_v3_abi_ops); | 1134 register_cp_abi (&gnu_v3_abi_ops); |
888 } | 1135 } |
OLD | NEW |