Variant gcc-13-14
Applies to 13.2.0, 14.2.0. Source flavors: linux, darwin_arm64.
+255 −4 2 files
gcc/c-family/c-ada-spec.cc
+116−4modified
| @@ -39 +39 @@static int dump_ada_declaration (pretty_printer *, tree, tree, int); | |||
| 39 | 39 | static void dump_ada_structure (pretty_printer *, tree, tree, bool, int); | |
| 40 | 40 | static void dump_nested_types (pretty_printer *, tree, int); | |
| 41 | 41 | static char *to_ada_name (const char *, bool *); | |
| 42 | Added line. static bool needs_empty_class_layout (tree); | ||
| 42 | 43 | | |
| 43 | 44 | #define INDENT(SPACE) \ | |
| 44 | 45 | do { int i; for (i = 0; i<SPACE; i++) pp_space (buffer); } while (0) | |
| @@ -2319 +2320 @@dump_ada_template (pretty_printer *buffer, tree t, int spc) | |||
| 2319 | 2320 | pp_string (buffer, " is limited "); | |
| 2320 | 2321 | | |
| 2321 | 2322 | dump_ada_node (buffer, instance, t, spc, false, false); | |
| 2322 | Removed line. if (!has_nontrivial_methods (instance) && !has_static_fields (instance)) | ||
| 2323 | Added line. if (!has_nontrivial_methods (instance) && !has_static_fields (instance) | ||
| 2324 | Added line. && !needs_empty_class_layout (instance)) | ||
| 2323 | 2325 | pp_semicolon (buffer); | |
| 2324 | 2326 | pp_newline (buffer); | |
| 2325 | 2327 | spc -= INDENT_INCR; | |
| @@ -2819 +2821 @@needs_tail_padding_layout (tree node) | |||
| 2819 | Removed line. return (data_size >= 0 && object_size > data_size) | ||
| 2820 | Removed line. || cpp_check (node, REUSES_BASE_TAIL_PADDING); | ||
| 2821 | Added line. if ((data_size >= 0 && object_size > data_size) | ||
| 2822 | Added line. || cpp_check (node, REUSES_BASE_TAIL_PADDING)) | ||
| 2823 | Added line. return true; | ||
| 2824 | Added line. | ||
| 2825 | Added line. for (tree field = TYPE_FIELDS (node); field; field = TREE_CHAIN (field)) | ||
| 2826 | Added line. if (TREE_CODE (field) == FIELD_DECL | ||
| 2827 | Added line. && DECL_NAME (field) | ||
| 2828 | Added line. && DECL_FIELD_ABI_IGNORED (field)) | ||
| 2829 | Added line. return true; | ||
| 2830 | Added line. | ||
| 2831 | Added line. return false; | ||
| 2821 | 2832 | } | |
| 2822 | 2833 | | |
| 2834 | Added line. /* Return true if NODE is a C++ empty class. Such a class has a nonzero | ||
| 2835 | Added line. complete-object size but contributes no storage as an empty base. */ | ||
| 2836 | Added line. | ||
| 2837 | Added line. static bool | ||
| 2838 | Added line. needs_empty_class_layout (tree node) | ||
| 2839 | Added line. { | ||
| 2840 | Added line. if (!cpp_check || !RECORD_OR_UNION_TYPE_P (node)) | ||
| 2841 | Added line. return false; | ||
| 2842 | Added line. | ||
| 2843 | Added line. const int data_size = cpp_check (node, GET_AS_BASE_SIZE); | ||
| 2844 | Added line. return data_size == 0 && int_size_in_bytes (node) > 0; | ||
| 2845 | Added line. } | ||
| 2846 | Added line. | ||
| 2847 | Added line. /* Return true if FIELD is an artificial empty C++ base, or a named empty | ||
| 2848 | Added line. [[no_unique_address]] member whose storage overlaps another field. Ada | ||
| 2849 | Added line. cannot expose two overlapping record components, so omit only the member | ||
| 2850 | Added line. that contributes no unique storage. */ | ||
| 2851 | Added line. | ||
| 2852 | Added line. static bool | ||
| 2853 | Added line. is_abi_ignored_empty_field (tree node, tree field) | ||
| 2854 | Added line. { | ||
| 2855 | Added line. if (!cpp_check || TREE_CODE (field) != FIELD_DECL | ||
| 2856 | Added line. || !DECL_FIELD_ABI_IGNORED (field) | ||
| 2857 | Added line. || !RECORD_OR_UNION_TYPE_P (TREE_TYPE (field)) | ||
| 2858 | Added line. || cpp_check (TREE_TYPE (field), GET_AS_BASE_SIZE) != 0) | ||
| 2859 | Added line. return false; | ||
| 2860 | Added line. | ||
| 2861 | Added line. if (!DECL_NAME (field)) | ||
| 2862 | Added line. return true; | ||
| 2863 | Added line. | ||
| 2864 | Added line. if (!DECL_FIELD_OFFSET (field) || !DECL_FIELD_BIT_OFFSET (field) | ||
| 2865 | Added line. || !tree_fits_uhwi_p (DECL_FIELD_OFFSET (field)) | ||
| 2866 | Added line. || !tree_fits_uhwi_p (DECL_FIELD_BIT_OFFSET (field))) | ||
| 2867 | Added line. return false; | ||
| 2868 | Added line. | ||
| 2869 | Added line. const unsigned HOST_WIDE_INT field_first | ||
| 2870 | Added line. = tree_to_uhwi (DECL_FIELD_OFFSET (field)) * BITS_PER_UNIT | ||
| 2871 | Added line. + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field)); | ||
| 2872 | Added line. const unsigned HOST_WIDE_INT field_last | ||
| 2873 | Added line. = field_first + int_size_in_bytes (TREE_TYPE (field)) * BITS_PER_UNIT; | ||
| 2874 | Added line. | ||
| 2875 | Added line. for (tree other = TYPE_FIELDS (node); other; other = TREE_CHAIN (other)) | ||
| 2876 | Added line. if (other != field && TREE_CODE (other) == FIELD_DECL | ||
| 2877 | Added line. && !DECL_VIRTUAL_P (other) && DECL_FIELD_OFFSET (other) | ||
| 2878 | Added line. && DECL_FIELD_BIT_OFFSET (other) && DECL_SIZE (other) | ||
| 2879 | Added line. && tree_fits_uhwi_p (DECL_FIELD_OFFSET (other)) | ||
| 2880 | Added line. && tree_fits_uhwi_p (DECL_FIELD_BIT_OFFSET (other)) | ||
| 2881 | Added line. && tree_fits_uhwi_p (DECL_SIZE (other))) | ||
| 2882 | Added line. { | ||
| 2883 | Added line. const unsigned HOST_WIDE_INT other_first | ||
| 2884 | Added line. = tree_to_uhwi (DECL_FIELD_OFFSET (other)) * BITS_PER_UNIT | ||
| 2885 | Added line. + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (other)); | ||
| 2886 | Added line. const unsigned HOST_WIDE_INT other_last | ||
| 2887 | Added line. = other_first + tree_to_uhwi (DECL_SIZE (other)); | ||
| 2888 | Added line. if (field_first < other_last && other_first < field_last) | ||
| 2889 | Added line. return true; | ||
| 2890 | Added line. } | ||
| 2891 | Added line. | ||
| 2892 | Added line. return false; | ||
| 2893 | Added line. } | ||
| 2894 | Added line. | ||
| 2895 | Added line. /* Dump the value and object sizes of an empty C++ class. Ada's value size is | ||
| 2896 | Added line. zero so an empty base consumes no storage, while Object_Size preserves the | ||
| 2897 | Added line. byte occupied by a complete C++ object. */ | ||
| 2898 | Added line. | ||
| 2899 | Added line. static void | ||
| 2900 | Added line. dump_ada_empty_class_layout (pretty_printer *buffer, tree node, tree type, | ||
| 2901 | Added line. int spc) | ||
| 2902 | Added line. { | ||
| 2903 | Added line. const HOST_WIDE_INT object_size = int_size_in_bytes (node); | ||
| 2904 | Added line. | ||
| 2905 | Added line. gcc_assert (object_size > 0); | ||
| 2906 | Added line. | ||
| 2907 | Added line. newline_and_indent (buffer, spc); | ||
| 2908 | Added line. pp_string (buffer, "for "); | ||
| 2909 | Added line. dump_ada_node (buffer, TYPE_NAME (node), type, spc, false, true); | ||
| 2910 | Added line. pp_string (buffer, "'Size use 0;"); | ||
| 2911 | Added line. | ||
| 2912 | Added line. newline_and_indent (buffer, spc); | ||
| 2913 | Added line. pp_string (buffer, "for "); | ||
| 2914 | Added line. dump_ada_node (buffer, TYPE_NAME (node), type, spc, false, true); | ||
| 2915 | Added line. pp_string (buffer, "'Object_Size use "); | ||
| 2916 | Added line. pp_wide_integer (buffer, object_size * BITS_PER_UNIT); | ||
| 2917 | Added line. pp_semicolon (buffer); | ||
| 2918 | Added line. } | ||
| 2919 | Added line. | ||
| 2823 | 2920 | /* Return true if all of NODE's fields that are visible in the generated Ada | |
| 2824 | 2921 | record have constant positions and sizes suitable for component clauses. */ | |
| 2825 | 2922 | | |
| @@ -3792 +3889 @@dump_ada_structure (pretty_printer *buffer, tree node, tree type, bool nested, | |||
| 3792 | 3889 | /* Print the non-static fields of the structure. */ | |
| 3793 | 3890 | for (tree tmp = TYPE_FIELDS (node); tmp; tmp = TREE_CHAIN (tmp)) | |
| 3794 | 3891 | { | |
| 3892 | Added line. if (is_abi_ignored_empty_field (node, tmp)) | ||
| 3893 | Added line. continue; | ||
| 3894 | Added line. | ||
| 3795 | 3895 | /* Add parent field if needed. */ | |
| 3796 | 3896 | if (!DECL_NAME (tmp)) | |
| 3797 | 3897 | { | |
| @@ -3912 +4012 @@dump_ada_structure (pretty_printer *buffer, tree node, tree type, bool nested, | |||
| 3912 | 4012 | | |
| 3913 | 4013 | need_semicolon = !dump_ada_methods (buffer, node, spc); | |
| 3914 | 4014 | | |
| 3915 | Removed line. if (needs_tail_padding_layout (node) && has_constant_field_layout (node)) | ||
| 4015 | Added line. if (needs_empty_class_layout (node)) | ||
| 4016 | Added line. { | ||
| 4017 | Added line. if (need_semicolon) | ||
| 4018 | Added line. { | ||
| 4019 | Added line. need_semicolon = false; | ||
| 4020 | Added line. pp_semicolon (buffer); | ||
| 4021 | Added line. } | ||
| 4022 | Added line. | ||
| 4023 | Added line. pp_newline (buffer); | ||
| 4024 | Added line. dump_ada_empty_class_layout (buffer, node, type, spc); | ||
| 4025 | Added line. } | ||
| 4026 | Added line. else if (needs_tail_padding_layout (node) | ||
| 4027 | Added line. && has_constant_field_layout (node)) | ||
| 3916 | 4028 | { | |
| 3917 | 4029 | if (need_semicolon) | |
| 3918 | 4030 | { | |
gcc/testsuite/g++.dg/ada-spec/empty-class-storage.C
+139−0new file
| @@ -0 +1 @@ | |||
| 1 | Added line. /* { dg-do compile } */ | ||
| 2 | Added line. /* { dg-require-effective-target lp64 } */ | ||
| 3 | Added line. /* { dg-options "-std=c++20 -fdump-ada-spec-slim" } */ | ||
| 4 | Added line. /* { dg-final { scan-file empty_class_storage_c.ads "for Empty'Size use 0;" } } */ | ||
| 5 | Added line. /* { dg-final { scan-file empty_class_storage_c.ads "for Empty'Object_Size use 8;" } } */ | ||
| 6 | Added line. /* { dg-final { scan-file-not empty_class_storage_c.ads "parent : aliased Empty_Base;" } } */ | ||
| 7 | Added line. /* { dg-final { scan-file-not empty_class_storage_c.ads "ignored : aliased Empty;" } } */ | ||
| 8 | Added line. /* { dg-final { scan-file empty_class_storage_c.ads "first : aliased Empty;" } } */ | ||
| 9 | Added line. /* { dg-final { scan-file empty_class_storage_c.ads "second : aliased Empty;" } } */ | ||
| 10 | Added line. | ||
| 11 | Added line. struct Empty | ||
| 12 | Added line. {}; | ||
| 13 | Added line. | ||
| 14 | Added line. struct Empty_Base | ||
| 15 | Added line. {}; | ||
| 16 | Added line. | ||
| 17 | Added line. struct With_Empty_Base : Empty_Base | ||
| 18 | Added line. { | ||
| 19 | Added line. int value; | ||
| 20 | Added line. }; | ||
| 21 | Added line. | ||
| 22 | Added line. struct With_Empty_Member | ||
| 23 | Added line. { | ||
| 24 | Added line. Empty member; | ||
| 25 | Added line. int value; | ||
| 26 | Added line. }; | ||
| 27 | Added line. | ||
| 28 | Added line. struct With_Empty_Array | ||
| 29 | Added line. { | ||
| 30 | Added line. Empty values[3]; | ||
| 31 | Added line. }; | ||
| 32 | Added line. | ||
| 33 | Added line. struct With_No_Unique_Address | ||
| 34 | Added line. { | ||
| 35 | Added line. [[no_unique_address]] Empty ignored; | ||
| 36 | Added line. int value; | ||
| 37 | Added line. }; | ||
| 38 | Added line. | ||
| 39 | Added line. struct With_Repeated_No_Unique_Address | ||
| 40 | Added line. { | ||
| 41 | Added line. [[no_unique_address]] Empty first; | ||
| 42 | Added line. [[no_unique_address]] Empty second; | ||
| 43 | Added line. }; | ||
| 44 | Added line. | ||
| 45 | Added line. struct Method_Empty | ||
| 46 | Added line. { | ||
| 47 | Added line. Method_Empty (); | ||
| 48 | Added line. void ping (); | ||
| 49 | Added line. }; | ||
| 50 | Added line. | ||
| 51 | Added line. Method_Empty::Method_Empty () {} | ||
| 52 | Added line. void Method_Empty::ping () {} | ||
| 53 | Added line. | ||
| 54 | Added line. extern "C" unsigned long cpp_empty_size () { return sizeof (Empty); } | ||
| 55 | Added line. extern "C" unsigned long cpp_empty_align () { return alignof (Empty); } | ||
| 56 | Added line. extern "C" unsigned long cpp_method_empty_size () | ||
| 57 | Added line. { | ||
| 58 | Added line. return sizeof (Method_Empty); | ||
| 59 | Added line. } | ||
| 60 | Added line. | ||
| 61 | Added line. extern "C" unsigned long | ||
| 62 | Added line. cpp_with_empty_base_size () | ||
| 63 | Added line. { | ||
| 64 | Added line. return sizeof (With_Empty_Base); | ||
| 65 | Added line. } | ||
| 66 | Added line. | ||
| 67 | Added line. extern "C" unsigned long | ||
| 68 | Added line. cpp_with_empty_base_value_offset () | ||
| 69 | Added line. { | ||
| 70 | Added line. return __builtin_offsetof (With_Empty_Base, value); | ||
| 71 | Added line. } | ||
| 72 | Added line. | ||
| 73 | Added line. extern "C" unsigned long | ||
| 74 | Added line. cpp_with_empty_member_size () | ||
| 75 | Added line. { | ||
| 76 | Added line. return sizeof (With_Empty_Member); | ||
| 77 | Added line. } | ||
| 78 | Added line. | ||
| 79 | Added line. extern "C" unsigned long | ||
| 80 | Added line. cpp_with_empty_member_member_offset () | ||
| 81 | Added line. { | ||
| 82 | Added line. return __builtin_offsetof (With_Empty_Member, member); | ||
| 83 | Added line. } | ||
| 84 | Added line. | ||
| 85 | Added line. extern "C" unsigned long | ||
| 86 | Added line. cpp_with_empty_member_value_offset () | ||
| 87 | Added line. { | ||
| 88 | Added line. return __builtin_offsetof (With_Empty_Member, value); | ||
| 89 | Added line. } | ||
| 90 | Added line. | ||
| 91 | Added line. extern "C" unsigned long | ||
| 92 | Added line. cpp_with_empty_array_size () | ||
| 93 | Added line. { | ||
| 94 | Added line. return sizeof (With_Empty_Array); | ||
| 95 | Added line. } | ||
| 96 | Added line. | ||
| 97 | Added line. extern "C" unsigned long | ||
| 98 | Added line. cpp_with_empty_array_values_offset () | ||
| 99 | Added line. { | ||
| 100 | Added line. return __builtin_offsetof (With_Empty_Array, values); | ||
| 101 | Added line. } | ||
| 102 | Added line. | ||
| 103 | Added line. extern "C" unsigned long | ||
| 104 | Added line. cpp_with_no_unique_address_size () | ||
| 105 | Added line. { | ||
| 106 | Added line. return sizeof (With_No_Unique_Address); | ||
| 107 | Added line. } | ||
| 108 | Added line. | ||
| 109 | Added line. extern "C" unsigned long | ||
| 110 | Added line. cpp_with_no_unique_address_value_offset () | ||
| 111 | Added line. { | ||
| 112 | Added line. return __builtin_offsetof (With_No_Unique_Address, value); | ||
| 113 | Added line. } | ||
| 114 | Added line. | ||
| 115 | Added line. extern "C" unsigned long | ||
| 116 | Added line. cpp_with_no_unique_address_ignored_offset () | ||
| 117 | Added line. { | ||
| 118 | Added line. return __builtin_offsetof (With_No_Unique_Address, ignored); | ||
| 119 | Added line. } | ||
| 120 | Added line. | ||
| 121 | Added line. extern "C" unsigned long | ||
| 122 | Added line. cpp_with_repeated_no_unique_address_size () | ||
| 123 | Added line. { | ||
| 124 | Added line. return sizeof (With_Repeated_No_Unique_Address); | ||
| 125 | Added line. } | ||
| 126 | Added line. | ||
| 127 | Added line. extern "C" unsigned long | ||
| 128 | Added line. cpp_with_repeated_no_unique_address_first_offset () | ||
| 129 | Added line. { | ||
| 130 | Added line. return __builtin_offsetof (With_Repeated_No_Unique_Address, first); | ||
| 131 | Added line. } | ||
| 132 | Added line. | ||
| 133 | Added line. extern "C" unsigned long | ||
| 134 | Added line. cpp_with_repeated_no_unique_address_second_offset () | ||
| 135 | Added line. { | ||
| 136 | Added line. return __builtin_offsetof (With_Repeated_No_Unique_Address, second); | ||
| 137 | Added line. } | ||
| 138 | Added line. | ||
| 139 | Added line. /* { dg-final { cleanup-ada-spec } } */ | ||
| 140 | | ||