Variant gcc-13-14
Applies to 13.2.0, 14.2.0. Source flavors: linux, darwin_arm64.
+328 −2 2 files
gcc/c-family/c-ada-spec.cc
+214−2modified
| @@ -2856 +2856 @@is_ada_record_field (tree field) | |||
| 2856 | 2856 | return DECL_NAME (field) || !is_tagged_type (TREE_TYPE (field)); | |
| 2857 | 2857 | } | |
| 2858 | 2858 | | |
| 2859 | Added line. /* Return true if NODE needs a distinct storage type when used as a base | ||
| 2860 | Added line. subobject. A non-polymorphic class with virtual bases contains those bases | ||
| 2861 | Added line. as a complete object, but excludes them from its as-base size. */ | ||
| 2862 | Added line. | ||
| 2863 | Added line. static bool | ||
| 2864 | Added line. needs_virtual_as_base_type (tree node) | ||
| 2865 | Added line. { | ||
| 2866 | Added line. if (!cpp_check || !RECORD_OR_UNION_TYPE_P (node) || is_tagged_type (node) | ||
| 2867 | Added line. || !cpp_check (node, HAS_VIRTUAL_BASE)) | ||
| 2868 | Added line. return false; | ||
| 2869 | Added line. | ||
| 2870 | Added line. const int data_size = cpp_check (node, GET_AS_BASE_SIZE); | ||
| 2871 | Added line. const HOST_WIDE_INT object_size = int_size_in_bytes (node); | ||
| 2872 | Added line. return data_size > 0 && object_size > data_size; | ||
| 2873 | Added line. } | ||
| 2874 | Added line. | ||
| 2875 | Added line. /* Return true if FIELD stores only the as-base portion of a virtual-base | ||
| 2876 | Added line. class. The complete Ada type has a larger Object_Size and cannot be used | ||
| 2877 | Added line. for this component. */ | ||
| 2878 | Added line. | ||
| 2879 | Added line. static bool | ||
| 2880 | Added line. is_shortened_virtual_base_field (tree field) | ||
| 2881 | Added line. { | ||
| 2882 | Added line. if (TREE_CODE (field) != FIELD_DECL || DECL_NAME (field) | ||
| 2883 | Added line. || !needs_virtual_as_base_type (TREE_TYPE (field)) | ||
| 2884 | Added line. || !DECL_SIZE (field) || !tree_fits_uhwi_p (DECL_SIZE (field))) | ||
| 2885 | Added line. return false; | ||
| 2886 | Added line. | ||
| 2887 | Added line. const HOST_WIDE_INT object_size = int_size_in_bytes (TREE_TYPE (field)); | ||
| 2888 | Added line. return object_size > 0 | ||
| 2889 | Added line. && tree_to_uhwi (DECL_SIZE (field)) | ||
| 2890 | Added line. < (unsigned HOST_WIDE_INT) object_size * BITS_PER_UNIT; | ||
| 2891 | Added line. } | ||
| 2892 | Added line. | ||
| 2893 | Added line. /* Dump FIELD's named type, selecting the shortened storage type when FIELD | ||
| 2894 | Added line. is a base subobject that excludes its type's virtual bases. */ | ||
| 2895 | Added line. | ||
| 2896 | Added line. static void | ||
| 2897 | Added line. dump_ada_record_field_type (pretty_printer *buffer, tree field) | ||
| 2898 | Added line. { | ||
| 2899 | Added line. dump_ada_decl_name (buffer, TYPE_NAME (TREE_TYPE (field)), false); | ||
| 2900 | Added line. if (is_shortened_virtual_base_field (field)) | ||
| 2901 | Added line. pp_string (buffer, "_As_Base"); | ||
| 2902 | Added line. } | ||
| 2903 | Added line. | ||
| 2904 | Added line. /* Return true if FIELD lies wholly inside NODE's C++ as-base size. */ | ||
| 2905 | Added line. | ||
| 2906 | Added line. static bool | ||
| 2907 | Added line. field_fits_as_base (tree node, tree field) | ||
| 2908 | Added line. { | ||
| 2909 | Added line. const int data_size = cpp_check (node, GET_AS_BASE_SIZE); | ||
| 2910 | Added line. if (data_size < 0 || !is_ada_record_field (node, field) | ||
| 2911 | Added line. || !DECL_FIELD_OFFSET (field) || !DECL_FIELD_BIT_OFFSET (field) | ||
| 2912 | Added line. || !DECL_SIZE (field) | ||
| 2913 | Added line. || !tree_fits_uhwi_p (DECL_FIELD_OFFSET (field)) | ||
| 2914 | Added line. || !tree_fits_uhwi_p (DECL_FIELD_BIT_OFFSET (field)) | ||
| 2915 | Added line. || !tree_fits_uhwi_p (DECL_SIZE (field))) | ||
| 2916 | Added line. return false; | ||
| 2917 | Added line. | ||
| 2918 | Added line. const unsigned HOST_WIDE_INT bitpos | ||
| 2919 | Added line. = tree_to_uhwi (DECL_FIELD_OFFSET (field)) * BITS_PER_UNIT | ||
| 2920 | Added line. + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field)); | ||
| 2921 | Added line. const unsigned HOST_WIDE_INT size = tree_to_uhwi (DECL_SIZE (field)); | ||
| 2922 | Added line. return size > 0 && bitpos + size | ||
| 2923 | Added line. <= (unsigned HOST_WIDE_INT) data_size * BITS_PER_UNIT; | ||
| 2924 | Added line. } | ||
| 2925 | Added line. | ||
| 2926 | Added line. /* Return the strongest Ada alignment that divides NODE's as-base size. The | ||
| 2927 | Added line. complete C++ alignment can exceed that storage size because reusable tail | ||
| 2928 | Added line. padding is not part of a base subobject. */ | ||
| 2929 | Added line. | ||
| 2930 | Added line. static unsigned int | ||
| 2931 | Added line. virtual_as_base_alignment (tree node, unsigned int data_size) | ||
| 2932 | Added line. { | ||
| 2933 | Added line. unsigned int alignment = TYPE_ALIGN (node) / BITS_PER_UNIT; | ||
| 2934 | Added line. while (alignment > 1 && data_size % alignment != 0) | ||
| 2935 | Added line. alignment >>= 1; | ||
| 2936 | Added line. return alignment; | ||
| 2937 | Added line. } | ||
| 2938 | Added line. | ||
| 2939 | Added line. /* Dump a storage-only Ada type for NODE's C++ as-base representation. This | ||
| 2940 | Added line. keeps each direct field addressable while excluding shared virtual bases. */ | ||
| 2941 | Added line. | ||
| 2942 | Added line. static void | ||
| 2943 | Added line. dump_ada_virtual_as_base_type (pretty_printer *buffer, tree node, tree type, | ||
| 2944 | Added line. int spc) | ||
| 2945 | Added line. { | ||
| 2946 | Added line. const unsigned int data_size = cpp_check (node, GET_AS_BASE_SIZE); | ||
| 2947 | Added line. int field_num = 0; | ||
| 2948 | Added line. | ||
| 2949 | Added line. pp_newline (buffer); | ||
| 2950 | Added line. newline_and_indent (buffer, spc); | ||
| 2951 | Added line. pp_string (buffer, "type "); | ||
| 2952 | Added line. dump_ada_node (buffer, TYPE_NAME (node), type, spc, false, true); | ||
| 2953 | Added line. pp_string (buffer, "_As_Base is record"); | ||
| 2954 | Added line. pp_newline (buffer); | ||
| 2955 | Added line. | ||
| 2956 | Added line. for (tree field = TYPE_FIELDS (node); field; field = TREE_CHAIN (field)) | ||
| 2957 | Added line. if (field_fits_as_base (node, field)) | ||
| 2958 | Added line. { | ||
| 2959 | Added line. if (!DECL_NAME (field)) | ||
| 2960 | Added line. { | ||
| 2961 | Added line. if (is_tagged_type (TREE_TYPE (field))) | ||
| 2962 | Added line. continue; | ||
| 2963 | Added line. | ||
| 2964 | Added line. INDENT (spc + INDENT_INCR); | ||
| 2965 | Added line. if (field_num == 0) | ||
| 2966 | Added line. pp_string (buffer, "parent : "); | ||
| 2967 | Added line. else | ||
| 2968 | Added line. { | ||
| 2969 | Added line. char buf[32]; | ||
| 2970 | Added line. sprintf (buf, "field_%d : ", field_num + 1); | ||
| 2971 | Added line. pp_string (buffer, buf); | ||
| 2972 | Added line. } | ||
| 2973 | Added line. dump_ada_record_field_type (buffer, field); | ||
| 2974 | Added line. pp_semicolon (buffer); | ||
| 2975 | Added line. pp_newline (buffer); | ||
| 2976 | Added line. field_num++; | ||
| 2977 | Added line. } | ||
| 2978 | Added line. else | ||
| 2979 | Added line. { | ||
| 2980 | Added line. INDENT (spc + INDENT_INCR); | ||
| 2981 | Added line. dump_ada_node (buffer, field, type, spc, false, true); | ||
| 2982 | Added line. pp_string (buffer, " : "); | ||
| 2983 | Added line. dump_ada_record_field_type (buffer, field); | ||
| 2984 | Added line. pp_string (buffer, "; -- "); | ||
| 2985 | Added line. dump_sloc (buffer, field); | ||
| 2986 | Added line. pp_newline (buffer); | ||
| 2987 | Added line. field_num++; | ||
| 2988 | Added line. } | ||
| 2989 | Added line. } | ||
| 2990 | Added line. | ||
| 2991 | Added line. if (field_num == 0) | ||
| 2992 | Added line. { | ||
| 2993 | Added line. INDENT (spc + INDENT_INCR); | ||
| 2994 | Added line. pp_string (buffer, "null;"); | ||
| 2995 | Added line. pp_newline (buffer); | ||
| 2996 | Added line. } | ||
| 2997 | Added line. | ||
| 2998 | Added line. INDENT (spc); | ||
| 2999 | Added line. pp_string (buffer, "end record"); | ||
| 3000 | Added line. newline_and_indent (buffer, spc); | ||
| 3001 | Added line. pp_string (buffer, "with Convention => C_Pass_By_Copy;"); | ||
| 3002 | Added line. | ||
| 3003 | Added line. newline_and_indent (buffer, spc); | ||
| 3004 | Added line. pp_string (buffer, "for "); | ||
| 3005 | Added line. dump_ada_node (buffer, TYPE_NAME (node), type, spc, false, true); | ||
| 3006 | Added line. pp_string (buffer, "_As_Base'Size use "); | ||
| 3007 | Added line. pp_wide_integer (buffer, (HOST_WIDE_INT) data_size * BITS_PER_UNIT); | ||
| 3008 | Added line. pp_semicolon (buffer); | ||
| 3009 | Added line. | ||
| 3010 | Added line. newline_and_indent (buffer, spc); | ||
| 3011 | Added line. pp_string (buffer, "for "); | ||
| 3012 | Added line. dump_ada_node (buffer, TYPE_NAME (node), type, spc, false, true); | ||
| 3013 | Added line. pp_string (buffer, "_As_Base'Object_Size use "); | ||
| 3014 | Added line. pp_wide_integer (buffer, (HOST_WIDE_INT) data_size * BITS_PER_UNIT); | ||
| 3015 | Added line. pp_semicolon (buffer); | ||
| 3016 | Added line. | ||
| 3017 | Added line. newline_and_indent (buffer, spc); | ||
| 3018 | Added line. pp_string (buffer, "for "); | ||
| 3019 | Added line. dump_ada_node (buffer, TYPE_NAME (node), type, spc, false, true); | ||
| 3020 | Added line. pp_string (buffer, "_As_Base'Alignment use "); | ||
| 3021 | Added line. pp_decimal_int (buffer, virtual_as_base_alignment (node, data_size)); | ||
| 3022 | Added line. pp_semicolon (buffer); | ||
| 3023 | Added line. | ||
| 3024 | Added line. newline_and_indent (buffer, spc); | ||
| 3025 | Added line. pp_string (buffer, "for "); | ||
| 3026 | Added line. dump_ada_node (buffer, TYPE_NAME (node), type, spc, false, true); | ||
| 3027 | Added line. pp_string (buffer, "_As_Base use record"); | ||
| 3028 | Added line. | ||
| 3029 | Added line. int repr_field_num = 0; | ||
| 3030 | Added line. for (tree field = TYPE_FIELDS (node); field; field = TREE_CHAIN (field)) | ||
| 3031 | Added line. if (field_fits_as_base (node, field)) | ||
| 3032 | Added line. { | ||
| 3033 | Added line. if (!DECL_NAME (field) && is_tagged_type (TREE_TYPE (field))) | ||
| 3034 | Added line. continue; | ||
| 3035 | Added line. | ||
| 3036 | Added line. repr_field_num++; | ||
| 3037 | Added line. const unsigned HOST_WIDE_INT bitpos | ||
| 3038 | Added line. = tree_to_uhwi (DECL_FIELD_OFFSET (field)) * BITS_PER_UNIT | ||
| 3039 | Added line. + tree_to_uhwi (DECL_FIELD_BIT_OFFSET (field)); | ||
| 3040 | Added line. const unsigned HOST_WIDE_INT position = bitpos / BITS_PER_UNIT; | ||
| 3041 | Added line. const unsigned HOST_WIDE_INT first_bit = bitpos % BITS_PER_UNIT; | ||
| 3042 | Added line. const unsigned HOST_WIDE_INT last_bit | ||
| 3043 | Added line. = first_bit + tree_to_uhwi (DECL_SIZE (field)) - 1; | ||
| 3044 | Added line. | ||
| 3045 | Added line. newline_and_indent (buffer, spc + INDENT_INCR); | ||
| 3046 | Added line. if (DECL_NAME (field)) | ||
| 3047 | Added line. dump_ada_decl_name (buffer, field, false); | ||
| 3048 | Added line. else if (repr_field_num == 1) | ||
| 3049 | Added line. pp_string (buffer, "parent"); | ||
| 3050 | Added line. else | ||
| 3051 | Added line. { | ||
| 3052 | Added line. char buf[32]; | ||
| 3053 | Added line. sprintf (buf, "field_%d", repr_field_num); | ||
| 3054 | Added line. pp_string (buffer, buf); | ||
| 3055 | Added line. } | ||
| 3056 | Added line. pp_string (buffer, " at "); | ||
| 3057 | Added line. pp_unsigned_wide_integer (buffer, position); | ||
| 3058 | Added line. pp_string (buffer, " range "); | ||
| 3059 | Added line. pp_unsigned_wide_integer (buffer, first_bit); | ||
| 3060 | Added line. pp_string (buffer, " .. "); | ||
| 3061 | Added line. pp_unsigned_wide_integer (buffer, last_bit); | ||
| 3062 | Added line. pp_semicolon (buffer); | ||
| 3063 | Added line. } | ||
| 3064 | Added line. | ||
| 3065 | Added line. newline_and_indent (buffer, spc); | ||
| 3066 | Added line. pp_string (buffer, "end record;"); | ||
| 3067 | Added line. } | ||
| 3068 | Added line. | ||
| 2859 | 3069 | /* Dump the value and object sizes of an empty C++ class. Ada's value size is | |
| 2860 | 3070 | zero so an empty base consumes no storage, while Object_Size preserves the | |
| 2861 | 3071 | byte occupied by a complete C++ object. */ | |
| @@ -3929 +4133 @@dump_ada_structure (pretty_printer *buffer, tree node, tree type, bool nested, | |||
| 3929 | 4133 | sprintf (buf, "field_%d : aliased ", field_num + 1); | |
| 3930 | 4134 | pp_string (buffer, buf); | |
| 3931 | 4135 | } | |
| 3932 | Removed line. dump_ada_decl_name (buffer, TYPE_NAME (TREE_TYPE (tmp)), | ||
| 3933 | Removed line. false); | ||
| 4136 | Added line. dump_ada_record_field_type (buffer, tmp); | ||
| 3934 | 4137 | pp_semicolon (buffer); | |
| 3935 | 4138 | } | |
| 3936 | 4139 | | |
| @@ -4056 +4259 @@dump_ada_structure (pretty_printer *buffer, tree node, tree type, bool nested, | |||
| 4056 | 4259 | pp_newline (buffer); | |
| 4057 | 4260 | dump_ada_cpp_layout (buffer, node, type, spc, | |
| 4058 | 4261 | cpp_check (node, HAS_VIRTUAL_BASE)); | |
| 4262 | Added line. | ||
| 4263 | Added line. if (needs_virtual_as_base_type (node)) | ||
| 4264 | Added line. dump_ada_virtual_as_base_type (buffer, node, type, spc); | ||
| 4059 | 4265 | } | |
| 4060 | 4266 | | |
| 4061 | 4267 | /* Print the static fields of the structure, if any. */ | |
gcc/testsuite/g++.dg/ada-spec/virtual-diamond-layout.C
+114−0new file
| @@ -0 +1 @@ | |||
| 1 | Added line. /* { dg-do compile } */ | ||
| 2 | Added line. /* { dg-require-effective-target lp64 } */ | ||
| 3 | Added line. /* { dg-options "-fdump-ada-spec-slim" } */ | ||
| 4 | Added line. /* { dg-final { scan-file virtual_diamond_layout_c.ads "type Diamond_Left_As_Base" } } */ | ||
| 5 | Added line. /* { dg-final { scan-file virtual_diamond_layout_c.ads "for Diamond_Left_As_Base'Object_Size use 96;" } } */ | ||
| 6 | Added line. /* { dg-final { scan-file virtual_diamond_layout_c.ads "type Diamond_Right_As_Base" } } */ | ||
| 7 | Added line. /* { dg-final { scan-file virtual_diamond_layout_c.ads "for Diamond_Right_As_Base'Object_Size use 96;" } } */ | ||
| 8 | Added line. /* { dg-final { scan-file virtual_diamond_layout_c.ads "parent : aliased Diamond_Left_As_Base;" } } */ | ||
| 9 | Added line. /* { dg-final { scan-file virtual_diamond_layout_c.ads "field_2 : aliased Diamond_Right_As_Base;" } } */ | ||
| 10 | Added line. | ||
| 11 | Added line. struct Diamond_Root | ||
| 12 | Added line. { | ||
| 13 | Added line. int root_value; | ||
| 14 | Added line. }; | ||
| 15 | Added line. | ||
| 16 | Added line. struct Diamond_Left : virtual Diamond_Root | ||
| 17 | Added line. { | ||
| 18 | Added line. int left_value; | ||
| 19 | Added line. }; | ||
| 20 | Added line. | ||
| 21 | Added line. struct Diamond_Right : virtual Diamond_Root | ||
| 22 | Added line. { | ||
| 23 | Added line. int right_value; | ||
| 24 | Added line. }; | ||
| 25 | Added line. | ||
| 26 | Added line. struct Diamond : Diamond_Left, Diamond_Right | ||
| 27 | Added line. { | ||
| 28 | Added line. int diamond_value; | ||
| 29 | Added line. Diamond (int root, int left, int right, int diamond_arg); | ||
| 30 | Added line. }; | ||
| 31 | Added line. | ||
| 32 | Added line. Diamond::Diamond (int root, int left, int right, int diamond_arg) | ||
| 33 | Added line. : Diamond_Root {root}, Diamond_Left {}, Diamond_Right {}, | ||
| 34 | Added line. diamond_value {diamond_arg} | ||
| 35 | Added line. { | ||
| 36 | Added line. left_value = left; | ||
| 37 | Added line. right_value = right; | ||
| 38 | Added line. } | ||
| 39 | Added line. | ||
| 40 | Added line. extern "C" unsigned long cpp_diamond_root_size () | ||
| 41 | Added line. { | ||
| 42 | Added line. return sizeof (Diamond_Root); | ||
| 43 | Added line. } | ||
| 44 | Added line. | ||
| 45 | Added line. extern "C" unsigned long cpp_diamond_size () | ||
| 46 | Added line. { | ||
| 47 | Added line. return sizeof (Diamond); | ||
| 48 | Added line. } | ||
| 49 | Added line. | ||
| 50 | Added line. extern "C" unsigned long cpp_diamond_alignment () | ||
| 51 | Added line. { | ||
| 52 | Added line. return alignof (Diamond); | ||
| 53 | Added line. } | ||
| 54 | Added line. | ||
| 55 | Added line. extern "C" unsigned long cpp_diamond_left_offset () | ||
| 56 | Added line. { | ||
| 57 | Added line. Diamond object (0, 0, 0, 0); | ||
| 58 | Added line. return reinterpret_cast<char *> (&object.left_value) | ||
| 59 | Added line. - reinterpret_cast<char *> (&object); | ||
| 60 | Added line. } | ||
| 61 | Added line. | ||
| 62 | Added line. extern "C" unsigned long cpp_diamond_right_offset () | ||
| 63 | Added line. { | ||
| 64 | Added line. Diamond object (0, 0, 0, 0); | ||
| 65 | Added line. return reinterpret_cast<char *> (&object.right_value) | ||
| 66 | Added line. - reinterpret_cast<char *> (&object); | ||
| 67 | Added line. } | ||
| 68 | Added line. | ||
| 69 | Added line. extern "C" unsigned long cpp_diamond_value_offset () | ||
| 70 | Added line. { | ||
| 71 | Added line. Diamond object (0, 0, 0, 0); | ||
| 72 | Added line. return reinterpret_cast<char *> (&object.diamond_value) | ||
| 73 | Added line. - reinterpret_cast<char *> (&object); | ||
| 74 | Added line. } | ||
| 75 | Added line. | ||
| 76 | Added line. extern "C" unsigned long cpp_diamond_root_offset () | ||
| 77 | Added line. { | ||
| 78 | Added line. Diamond object (0, 0, 0, 0); | ||
| 79 | Added line. return reinterpret_cast<char *> (&object.root_value) | ||
| 80 | Added line. - reinterpret_cast<char *> (&object); | ||
| 81 | Added line. } | ||
| 82 | Added line. | ||
| 83 | Added line. extern "C" Diamond *cpp_diamond_create | ||
| 84 | Added line. (int root, int left, int right, int diamond_arg) | ||
| 85 | Added line. { | ||
| 86 | Added line. return new Diamond (root, left, right, diamond_arg); | ||
| 87 | Added line. } | ||
| 88 | Added line. | ||
| 89 | Added line. extern "C" void cpp_diamond_delete (Diamond *object) | ||
| 90 | Added line. { | ||
| 91 | Added line. delete object; | ||
| 92 | Added line. } | ||
| 93 | Added line. | ||
| 94 | Added line. extern "C" int cpp_diamond_root_value (const Diamond *object) | ||
| 95 | Added line. { | ||
| 96 | Added line. return object->root_value; | ||
| 97 | Added line. } | ||
| 98 | Added line. | ||
| 99 | Added line. extern "C" int cpp_diamond_left_value (const Diamond *object) | ||
| 100 | Added line. { | ||
| 101 | Added line. return object->left_value; | ||
| 102 | Added line. } | ||
| 103 | Added line. | ||
| 104 | Added line. extern "C" int cpp_diamond_right_value (const Diamond *object) | ||
| 105 | Added line. { | ||
| 106 | Added line. return object->right_value; | ||
| 107 | Added line. } | ||
| 108 | Added line. | ||
| 109 | Added line. extern "C" int cpp_diamond_value (const Diamond *object) | ||
| 110 | Added line. { | ||
| 111 | Added line. return object->diamond_value; | ||
| 112 | Added line. } | ||
| 113 | Added line. | ||
| 114 | Added line. /* { dg-final { cleanup-ada-spec } } */ | ||
| 115 | | ||