Line data Source code
1 : /* Language-level data type conversion for GNU C.
2 : Copyright (C) 1987-2026 Free Software Foundation, Inc.
3 :
4 : This file is part of GCC.
5 :
6 : GCC is free software; you can redistribute it and/or modify it under
7 : the terms of the GNU General Public License as published by the Free
8 : Software Foundation; either version 3, or (at your option) any later
9 : version.
10 :
11 : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
12 : WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14 : for more details.
15 :
16 : You should have received a copy of the GNU General Public License
17 : along with GCC; see the file COPYING3. If not see
18 : <http://www.gnu.org/licenses/>. */
19 :
20 :
21 : /* This file contains the functions for converting C expressions
22 : to different data types. The only entry point is `convert'.
23 : Every language front end must have a `convert' function
24 : but what kind of conversions it does will depend on the language. */
25 :
26 : #include "config.h"
27 : #include "system.h"
28 : #include "coretypes.h"
29 : #include "target.h"
30 : #include "c-tree.h"
31 : #include "convert.h"
32 : #include "langhooks.h"
33 : #include "ubsan.h"
34 : #include "stringpool.h"
35 : #include "attribs.h"
36 : #include "asan.h"
37 :
38 : /* Change of width--truncation and extension of integers or reals--
39 : is represented with NOP_EXPR. Proper functioning of many things
40 : assumes that no other conversions can be NOP_EXPRs.
41 :
42 : Conversion between integer and pointer is represented with CONVERT_EXPR.
43 : Converting integer to real uses FLOAT_EXPR
44 : and real to integer uses FIX_TRUNC_EXPR.
45 :
46 : Here is a list of all the functions that assume that widening and
47 : narrowing is always done with a NOP_EXPR:
48 : In convert.cc, convert_to_integer.
49 : In c-typeck.cc, build_binary_op (boolean ops), and
50 : c_common_truthvalue_conversion.
51 : In expr.cc: expand_expr, for operands of a MULT_EXPR.
52 : In fold-const.cc: fold.
53 : In tree.cc: get_narrower and get_unwidened. */
54 :
55 : /* Subroutines of `convert'. */
56 :
57 :
58 :
59 : /* Create an expression whose value is that of EXPR,
60 : converted to type TYPE. The TREE_TYPE of the value
61 : is always TYPE. This function implements all reasonable
62 : conversions; callers should filter out those that are
63 : not permitted by the language being compiled.
64 : INIT_CONST is true if the conversion is for arithmetic types for a static
65 : initializer and folding must apply accordingly (discarding floating-point
66 : exceptions and assuming the default rounding mode is in effect). */
67 :
68 : static tree
69 602625698 : c_convert (tree type, tree expr, bool init_const)
70 : {
71 602625698 : tree e = expr;
72 602625698 : enum tree_code code = TREE_CODE (type);
73 602625698 : const char *invalid_conv_diag;
74 602625698 : tree ret;
75 602625698 : location_t loc = EXPR_LOCATION (expr);
76 :
77 602625698 : if (type == error_mark_node
78 602625698 : || error_operand_p (expr))
79 : return error_mark_node;
80 :
81 1205251184 : if ((invalid_conv_diag
82 602625592 : = targetm.invalid_conversion (TREE_TYPE (expr), type)))
83 : {
84 2 : error (invalid_conv_diag);
85 2 : return error_mark_node;
86 : }
87 :
88 602625590 : if (type == TREE_TYPE (expr))
89 : return expr;
90 196661993 : ret = targetm.convert_to_type (type, expr);
91 196661993 : if (ret)
92 : return ret;
93 :
94 196708561 : STRIP_TYPE_NOPS (e);
95 :
96 196661993 : if (TYPE_MAIN_VARIANT (type) == TYPE_MAIN_VARIANT (TREE_TYPE (expr))
97 196661993 : && (TREE_CODE (TREE_TYPE (expr)) != COMPLEX_TYPE
98 37723 : || TREE_CODE (e) == COMPLEX_EXPR))
99 62155034 : return fold_convert_loc (loc, type, expr);
100 134506959 : if (TREE_CODE (TREE_TYPE (expr)) == ERROR_MARK)
101 0 : return error_mark_node;
102 134506959 : if (VOID_TYPE_P (TREE_TYPE (expr)))
103 : {
104 0 : error ("void value not ignored as it ought to be");
105 0 : return error_mark_node;
106 : }
107 :
108 134506959 : {
109 134506959 : tree false_value, true_value;
110 134506959 : if (c_hardbool_type_attr (type, &false_value, &true_value))
111 : {
112 8736 : bool save = in_late_binary_op;
113 8736 : in_late_binary_op = true;
114 8736 : expr = c_objc_common_truthvalue_conversion (input_location, expr);
115 8736 : in_late_binary_op = save;
116 :
117 8736 : return fold_build3_loc (loc, COND_EXPR, type,
118 8736 : expr, true_value, false_value);
119 : }
120 : }
121 :
122 134498223 : switch (code)
123 : {
124 63899 : case VOID_TYPE:
125 63899 : return fold_convert_loc (loc, type, e);
126 :
127 124675 : case ENUMERAL_TYPE:
128 124675 : if (ENUM_UNDERLYING_TYPE (type) != NULL_TREE
129 124675 : && TREE_CODE (ENUM_UNDERLYING_TYPE (type)) == BOOLEAN_TYPE)
130 165 : goto convert_to_boolean;
131 25565369 : gcc_fallthrough ();
132 :
133 25565369 : case INTEGER_TYPE:
134 25565369 : case BITINT_TYPE:
135 25565369 : if (sanitize_flags_p (SANITIZE_FLOAT_CAST)
136 82163 : && current_function_decl != NULL_TREE
137 82163 : && SCALAR_FLOAT_TYPE_P (TREE_TYPE (expr))
138 25577093 : && COMPLETE_TYPE_P (type))
139 : {
140 11724 : expr = save_expr (expr);
141 11724 : expr = c_fully_fold (expr, init_const, NULL);
142 11724 : tree check = ubsan_instrument_float_cast (loc, type, expr);
143 11724 : expr = fold_build1 (FIX_TRUNC_EXPR, type, expr);
144 11724 : if (check == NULL_TREE)
145 : return expr;
146 7128 : return fold_build2 (COMPOUND_EXPR, TREE_TYPE (expr), check, expr);
147 : }
148 25553645 : ret = convert_to_integer (type, e);
149 25553645 : goto maybe_fold;
150 :
151 37821 : case BOOLEAN_TYPE:
152 37821 : convert_to_boolean:
153 37821 : return c_objc_common_truthvalue_conversion (input_location, expr, type);
154 :
155 6398067 : case POINTER_TYPE:
156 : /* The type nullptr_t may be converted to a pointer type. The result is
157 : a null pointer value. */
158 6398067 : if (NULLPTR_TYPE_P (TREE_TYPE (e)))
159 : {
160 : /* To make sure that (void *)nullptr is not a null pointer constant,
161 : build_c_cast will create an additional NOP_EXPR around the result
162 : of this conversion. */
163 103 : if (TREE_SIDE_EFFECTS (e))
164 11 : ret = build2 (COMPOUND_EXPR, type, e, build_int_cst (type, 0));
165 : else
166 92 : ret = build_int_cst (type, 0);
167 103 : goto maybe_fold;
168 : }
169 6397964 : gcc_fallthrough ();
170 6397964 : case REFERENCE_TYPE:
171 6397964 : ret = convert_to_pointer (type, e);
172 6397964 : goto maybe_fold;
173 :
174 10 : case NULLPTR_TYPE:
175 : /* A null pointer constant or value of type nullptr_t may be
176 : converted to nullptr_t. The latter case has already been
177 : handled. build_c_cast will create an additional NOP_EXPR to
178 : ensure the result of the conversion is not itself a null
179 : pointer constant. */
180 10 : if (null_pointer_constant_p (expr))
181 : {
182 7 : ret = build_int_cst (type, 0);
183 7 : goto maybe_fold;
184 : }
185 : break;
186 :
187 1003954 : case REAL_TYPE:
188 1003954 : ret = convert_to_real (type, e);
189 1003954 : goto maybe_fold;
190 :
191 0 : case FIXED_POINT_TYPE:
192 0 : ret = convert_to_fixed (type, e);
193 0 : goto maybe_fold;
194 :
195 133307 : case COMPLEX_TYPE:
196 133307 : ret = convert_to_complex (type, e);
197 133307 : goto maybe_fold;
198 :
199 101295765 : case VECTOR_TYPE:
200 101295765 : if (gnu_vector_type_p (type)
201 0 : || gnu_vector_type_p (TREE_TYPE (e))
202 : /* Allow conversions between compatible non-GNU vector types
203 : when -flax-vector-conversions is passed. The whole purpose
204 : of the option is to bend the normal type rules and accept
205 : nonconforming code. */
206 101295765 : || (flag_lax_vector_conversions
207 0 : && VECTOR_TYPE_P (TREE_TYPE (e))
208 0 : && vector_types_convertible_p (type, TREE_TYPE (e), false)))
209 : {
210 101295765 : ret = convert_to_vector (type, e);
211 101295765 : goto maybe_fold;
212 : }
213 : break;
214 :
215 31 : case RECORD_TYPE:
216 31 : case UNION_TYPE:
217 31 : if (lang_hooks.types_compatible_p (type, TREE_TYPE (expr)))
218 : return e;
219 : break;
220 :
221 : default:
222 : break;
223 :
224 134384745 : maybe_fold:
225 134384745 : if (TREE_CODE (ret) != C_MAYBE_CONST_EXPR)
226 134384731 : ret = init_const ? fold_init (ret) : fold (ret);
227 : return ret;
228 : }
229 :
230 : /* If we are converting to nullptr_t, don't say "non-scalar type" because
231 : the nullptr_t type is a scalar type. Only nullptr_t or a null pointer
232 : constant shall be converted to nullptr_t. */
233 11 : if (code == NULLPTR_TYPE)
234 : {
235 3 : error ("conversion from %qT to %qT", TREE_TYPE (e), type);
236 3 : inform (input_location,
237 : "only %qT or a null pointer constant can be converted to %qT",
238 : type, type);
239 : }
240 : else
241 8 : error ("conversion to non-scalar type requested");
242 11 : return error_mark_node;
243 : }
244 :
245 : /* Create an expression whose value is that of EXPR, converted to type TYPE.
246 : The TREE_TYPE of the value is always TYPE. This function implements all
247 : reasonable conversions; callers should filter out those that are not
248 : permitted by the language being compiled. */
249 :
250 : tree
251 602081954 : convert (tree type, tree expr)
252 : {
253 602081954 : return c_convert (type, expr, false);
254 : }
255 :
256 : /* Create an expression whose value is that of EXPR, converted to type TYPE, in
257 : a static initializer. The TREE_TYPE of the value is always TYPE. This
258 : function implements all reasonable conversions; callers should filter out
259 : those that are not permitted by the language being compiled. */
260 :
261 : tree
262 543744 : convert_init (tree type, tree expr)
263 : {
264 543744 : return c_convert (type, expr, true);
265 : }
|