1e4b17023SJohn Marino /* Subroutines shared by all languages that are variants of C.
2e4b17023SJohn Marino Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
3e4b17023SJohn Marino 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012
4e4b17023SJohn Marino Free Software Foundation, Inc.
5e4b17023SJohn Marino
6e4b17023SJohn Marino This file is part of GCC.
7e4b17023SJohn Marino
8e4b17023SJohn Marino GCC is free software; you can redistribute it and/or modify it under
9e4b17023SJohn Marino the terms of the GNU General Public License as published by the Free
10e4b17023SJohn Marino Software Foundation; either version 3, or (at your option) any later
11e4b17023SJohn Marino version.
12e4b17023SJohn Marino
13e4b17023SJohn Marino GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14e4b17023SJohn Marino WARRANTY; without even the implied warranty of MERCHANTABILITY or
15e4b17023SJohn Marino FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16e4b17023SJohn Marino for more details.
17e4b17023SJohn Marino
18e4b17023SJohn Marino You should have received a copy of the GNU General Public License
19e4b17023SJohn Marino along with GCC; see the file COPYING3. If not see
20e4b17023SJohn Marino <http://www.gnu.org/licenses/>. */
21e4b17023SJohn Marino
22e4b17023SJohn Marino #include "config.h"
23e4b17023SJohn Marino #include "system.h"
24e4b17023SJohn Marino #include "coretypes.h"
25e4b17023SJohn Marino #include "tm.h"
26e4b17023SJohn Marino #include "intl.h"
27e4b17023SJohn Marino #include "tree.h"
28e4b17023SJohn Marino #include "flags.h"
29e4b17023SJohn Marino #include "output.h"
30e4b17023SJohn Marino #include "c-pragma.h"
31e4b17023SJohn Marino #include "ggc.h"
32e4b17023SJohn Marino #include "c-common.h"
33e4b17023SJohn Marino #include "c-objc.h"
34e4b17023SJohn Marino #include "tm_p.h"
35e4b17023SJohn Marino #include "obstack.h"
36e4b17023SJohn Marino #include "cpplib.h"
37e4b17023SJohn Marino #include "target.h"
38e4b17023SJohn Marino #include "common/common-target.h"
39e4b17023SJohn Marino #include "langhooks.h"
40e4b17023SJohn Marino #include "tree-inline.h"
41e4b17023SJohn Marino #include "toplev.h"
42e4b17023SJohn Marino #include "diagnostic.h"
43e4b17023SJohn Marino #include "tree-iterator.h"
44e4b17023SJohn Marino #include "hashtab.h"
45e4b17023SJohn Marino #include "tree-mudflap.h"
46e4b17023SJohn Marino #include "opts.h"
47e4b17023SJohn Marino #include "cgraph.h"
48e4b17023SJohn Marino #include "target-def.h"
49e4b17023SJohn Marino #include "libfuncs.h"
50e4b17023SJohn Marino
51e4b17023SJohn Marino cpp_reader *parse_in; /* Declared in c-pragma.h. */
52e4b17023SJohn Marino
53e4b17023SJohn Marino /* The following symbols are subsumed in the c_global_trees array, and
54e4b17023SJohn Marino listed here individually for documentation purposes.
55e4b17023SJohn Marino
56e4b17023SJohn Marino INTEGER_TYPE and REAL_TYPE nodes for the standard data types.
57e4b17023SJohn Marino
58e4b17023SJohn Marino tree short_integer_type_node;
59e4b17023SJohn Marino tree long_integer_type_node;
60e4b17023SJohn Marino tree long_long_integer_type_node;
61e4b17023SJohn Marino tree int128_integer_type_node;
62e4b17023SJohn Marino
63e4b17023SJohn Marino tree short_unsigned_type_node;
64e4b17023SJohn Marino tree long_unsigned_type_node;
65e4b17023SJohn Marino tree long_long_unsigned_type_node;
66e4b17023SJohn Marino tree int128_unsigned_type_node;
67e4b17023SJohn Marino
68e4b17023SJohn Marino tree truthvalue_type_node;
69e4b17023SJohn Marino tree truthvalue_false_node;
70e4b17023SJohn Marino tree truthvalue_true_node;
71e4b17023SJohn Marino
72e4b17023SJohn Marino tree ptrdiff_type_node;
73e4b17023SJohn Marino
74e4b17023SJohn Marino tree unsigned_char_type_node;
75e4b17023SJohn Marino tree signed_char_type_node;
76e4b17023SJohn Marino tree wchar_type_node;
77e4b17023SJohn Marino
78e4b17023SJohn Marino tree char16_type_node;
79e4b17023SJohn Marino tree char32_type_node;
80e4b17023SJohn Marino
81e4b17023SJohn Marino tree float_type_node;
82e4b17023SJohn Marino tree double_type_node;
83e4b17023SJohn Marino tree long_double_type_node;
84e4b17023SJohn Marino
85e4b17023SJohn Marino tree complex_integer_type_node;
86e4b17023SJohn Marino tree complex_float_type_node;
87e4b17023SJohn Marino tree complex_double_type_node;
88e4b17023SJohn Marino tree complex_long_double_type_node;
89e4b17023SJohn Marino
90e4b17023SJohn Marino tree dfloat32_type_node;
91e4b17023SJohn Marino tree dfloat64_type_node;
92e4b17023SJohn Marino tree_dfloat128_type_node;
93e4b17023SJohn Marino
94e4b17023SJohn Marino tree intQI_type_node;
95e4b17023SJohn Marino tree intHI_type_node;
96e4b17023SJohn Marino tree intSI_type_node;
97e4b17023SJohn Marino tree intDI_type_node;
98e4b17023SJohn Marino tree intTI_type_node;
99e4b17023SJohn Marino
100e4b17023SJohn Marino tree unsigned_intQI_type_node;
101e4b17023SJohn Marino tree unsigned_intHI_type_node;
102e4b17023SJohn Marino tree unsigned_intSI_type_node;
103e4b17023SJohn Marino tree unsigned_intDI_type_node;
104e4b17023SJohn Marino tree unsigned_intTI_type_node;
105e4b17023SJohn Marino
106e4b17023SJohn Marino tree widest_integer_literal_type_node;
107e4b17023SJohn Marino tree widest_unsigned_literal_type_node;
108e4b17023SJohn Marino
109e4b17023SJohn Marino Nodes for types `void *' and `const void *'.
110e4b17023SJohn Marino
111e4b17023SJohn Marino tree ptr_type_node, const_ptr_type_node;
112e4b17023SJohn Marino
113e4b17023SJohn Marino Nodes for types `char *' and `const char *'.
114e4b17023SJohn Marino
115e4b17023SJohn Marino tree string_type_node, const_string_type_node;
116e4b17023SJohn Marino
117e4b17023SJohn Marino Type `char[SOMENUMBER]'.
118e4b17023SJohn Marino Used when an array of char is needed and the size is irrelevant.
119e4b17023SJohn Marino
120e4b17023SJohn Marino tree char_array_type_node;
121e4b17023SJohn Marino
122e4b17023SJohn Marino Type `int[SOMENUMBER]' or something like it.
123e4b17023SJohn Marino Used when an array of int needed and the size is irrelevant.
124e4b17023SJohn Marino
125e4b17023SJohn Marino tree int_array_type_node;
126e4b17023SJohn Marino
127e4b17023SJohn Marino Type `wchar_t[SOMENUMBER]' or something like it.
128e4b17023SJohn Marino Used when a wide string literal is created.
129e4b17023SJohn Marino
130e4b17023SJohn Marino tree wchar_array_type_node;
131e4b17023SJohn Marino
132e4b17023SJohn Marino Type `char16_t[SOMENUMBER]' or something like it.
133e4b17023SJohn Marino Used when a UTF-16 string literal is created.
134e4b17023SJohn Marino
135e4b17023SJohn Marino tree char16_array_type_node;
136e4b17023SJohn Marino
137e4b17023SJohn Marino Type `char32_t[SOMENUMBER]' or something like it.
138e4b17023SJohn Marino Used when a UTF-32 string literal is created.
139e4b17023SJohn Marino
140e4b17023SJohn Marino tree char32_array_type_node;
141e4b17023SJohn Marino
142e4b17023SJohn Marino Type `int ()' -- used for implicit declaration of functions.
143e4b17023SJohn Marino
144e4b17023SJohn Marino tree default_function_type;
145e4b17023SJohn Marino
146e4b17023SJohn Marino A VOID_TYPE node, packaged in a TREE_LIST.
147e4b17023SJohn Marino
148e4b17023SJohn Marino tree void_list_node;
149e4b17023SJohn Marino
150e4b17023SJohn Marino The lazily created VAR_DECLs for __FUNCTION__, __PRETTY_FUNCTION__,
151e4b17023SJohn Marino and __func__. (C doesn't generate __FUNCTION__ and__PRETTY_FUNCTION__
152e4b17023SJohn Marino VAR_DECLS, but C++ does.)
153e4b17023SJohn Marino
154e4b17023SJohn Marino tree function_name_decl_node;
155e4b17023SJohn Marino tree pretty_function_name_decl_node;
156e4b17023SJohn Marino tree c99_function_name_decl_node;
157e4b17023SJohn Marino
158e4b17023SJohn Marino Stack of nested function name VAR_DECLs.
159e4b17023SJohn Marino
160e4b17023SJohn Marino tree saved_function_name_decls;
161e4b17023SJohn Marino
162e4b17023SJohn Marino */
163e4b17023SJohn Marino
164e4b17023SJohn Marino tree c_global_trees[CTI_MAX];
165e4b17023SJohn Marino
166e4b17023SJohn Marino /* Switches common to the C front ends. */
167e4b17023SJohn Marino
168e4b17023SJohn Marino /* Nonzero means don't output line number information. */
169e4b17023SJohn Marino
170e4b17023SJohn Marino char flag_no_line_commands;
171e4b17023SJohn Marino
172e4b17023SJohn Marino /* Nonzero causes -E output not to be done, but directives such as
173e4b17023SJohn Marino #define that have side effects are still obeyed. */
174e4b17023SJohn Marino
175e4b17023SJohn Marino char flag_no_output;
176e4b17023SJohn Marino
177e4b17023SJohn Marino /* Nonzero means dump macros in some fashion. */
178e4b17023SJohn Marino
179e4b17023SJohn Marino char flag_dump_macros;
180e4b17023SJohn Marino
181e4b17023SJohn Marino /* Nonzero means pass #include lines through to the output. */
182e4b17023SJohn Marino
183e4b17023SJohn Marino char flag_dump_includes;
184e4b17023SJohn Marino
185e4b17023SJohn Marino /* Nonzero means process PCH files while preprocessing. */
186e4b17023SJohn Marino
187e4b17023SJohn Marino bool flag_pch_preprocess;
188e4b17023SJohn Marino
189e4b17023SJohn Marino /* The file name to which we should write a precompiled header, or
190e4b17023SJohn Marino NULL if no header will be written in this compile. */
191e4b17023SJohn Marino
192e4b17023SJohn Marino const char *pch_file;
193e4b17023SJohn Marino
194e4b17023SJohn Marino /* Nonzero if an ISO standard was selected. It rejects macros in the
195e4b17023SJohn Marino user's namespace. */
196e4b17023SJohn Marino int flag_iso;
197e4b17023SJohn Marino
198e4b17023SJohn Marino /* Warn about #pragma directives that are not recognized. */
199e4b17023SJohn Marino
200e4b17023SJohn Marino int warn_unknown_pragmas; /* Tri state variable. */
201e4b17023SJohn Marino
202e4b17023SJohn Marino /* Warn about format/argument anomalies in calls to formatted I/O functions
203e4b17023SJohn Marino (*printf, *scanf, strftime, strfmon, etc.). */
204e4b17023SJohn Marino
205e4b17023SJohn Marino int warn_format;
206e4b17023SJohn Marino
207e4b17023SJohn Marino /* C/ObjC language option variables. */
208e4b17023SJohn Marino
209e4b17023SJohn Marino
210e4b17023SJohn Marino /* Nonzero means allow type mismatches in conditional expressions;
211e4b17023SJohn Marino just make their values `void'. */
212e4b17023SJohn Marino
213e4b17023SJohn Marino int flag_cond_mismatch;
214e4b17023SJohn Marino
215e4b17023SJohn Marino /* Nonzero means enable C89 Amendment 1 features. */
216e4b17023SJohn Marino
217e4b17023SJohn Marino int flag_isoc94;
218e4b17023SJohn Marino
219e4b17023SJohn Marino /* Nonzero means use the ISO C99 (or C11) dialect of C. */
220e4b17023SJohn Marino
221e4b17023SJohn Marino int flag_isoc99;
222e4b17023SJohn Marino
223e4b17023SJohn Marino /* Nonzero means use the ISO C11 dialect of C. */
224e4b17023SJohn Marino
225e4b17023SJohn Marino int flag_isoc11;
226e4b17023SJohn Marino
227e4b17023SJohn Marino /* Nonzero means that we have builtin functions, and main is an int. */
228e4b17023SJohn Marino
229e4b17023SJohn Marino int flag_hosted = 1;
230e4b17023SJohn Marino
231e4b17023SJohn Marino
232e4b17023SJohn Marino /* ObjC language option variables. */
233e4b17023SJohn Marino
234e4b17023SJohn Marino
235e4b17023SJohn Marino /* Tells the compiler that this is a special run. Do not perform any
236e4b17023SJohn Marino compiling, instead we are to test some platform dependent features
237e4b17023SJohn Marino and output a C header file with appropriate definitions. */
238e4b17023SJohn Marino
239e4b17023SJohn Marino int print_struct_values;
240e4b17023SJohn Marino
241e4b17023SJohn Marino /* Tells the compiler what is the constant string class for ObjC. */
242e4b17023SJohn Marino
243e4b17023SJohn Marino const char *constant_string_class_name;
244e4b17023SJohn Marino
245e4b17023SJohn Marino
246e4b17023SJohn Marino /* C++ language option variables. */
247e4b17023SJohn Marino
248e4b17023SJohn Marino
249e4b17023SJohn Marino /* Nonzero means generate separate instantiation control files and
250e4b17023SJohn Marino juggle them at link time. */
251e4b17023SJohn Marino
252e4b17023SJohn Marino int flag_use_repository;
253e4b17023SJohn Marino
254e4b17023SJohn Marino /* The C++ dialect being used. C++98 is the default. */
255e4b17023SJohn Marino
256e4b17023SJohn Marino enum cxx_dialect cxx_dialect = cxx98;
257e4b17023SJohn Marino
258e4b17023SJohn Marino /* Maximum template instantiation depth. This limit exists to limit the
259e4b17023SJohn Marino time it takes to notice excessively recursive template instantiations.
260e4b17023SJohn Marino
261e4b17023SJohn Marino The default is lower than the 1024 recommended by the C++0x standard
262e4b17023SJohn Marino because G++ runs out of stack before 1024 with highly recursive template
263e4b17023SJohn Marino argument deduction substitution (g++.dg/cpp0x/enum11.C). */
264e4b17023SJohn Marino
265e4b17023SJohn Marino int max_tinst_depth = 900;
266e4b17023SJohn Marino
267e4b17023SJohn Marino /* The elements of `ridpointers' are identifier nodes for the reserved
268e4b17023SJohn Marino type names and storage classes. It is indexed by a RID_... value. */
269e4b17023SJohn Marino tree *ridpointers;
270e4b17023SJohn Marino
271e4b17023SJohn Marino tree (*make_fname_decl) (location_t, tree, int);
272e4b17023SJohn Marino
273e4b17023SJohn Marino /* Nonzero means don't warn about problems that occur when the code is
274e4b17023SJohn Marino executed. */
275e4b17023SJohn Marino int c_inhibit_evaluation_warnings;
276e4b17023SJohn Marino
277e4b17023SJohn Marino /* Whether we are building a boolean conversion inside
278e4b17023SJohn Marino convert_for_assignment, or some other late binary operation. If
279e4b17023SJohn Marino build_binary_op is called for C (from code shared by C and C++) in
280e4b17023SJohn Marino this case, then the operands have already been folded and the
281e4b17023SJohn Marino result will not be folded again, so C_MAYBE_CONST_EXPR should not
282e4b17023SJohn Marino be generated. */
283e4b17023SJohn Marino bool in_late_binary_op;
284e4b17023SJohn Marino
285e4b17023SJohn Marino /* Whether lexing has been completed, so subsequent preprocessor
286e4b17023SJohn Marino errors should use the compiler's input_location. */
287e4b17023SJohn Marino bool done_lexing = false;
288e4b17023SJohn Marino
289e4b17023SJohn Marino /* Information about how a function name is generated. */
290e4b17023SJohn Marino struct fname_var_t
291e4b17023SJohn Marino {
292e4b17023SJohn Marino tree *const decl; /* pointer to the VAR_DECL. */
293e4b17023SJohn Marino const unsigned rid; /* RID number for the identifier. */
294e4b17023SJohn Marino const int pretty; /* How pretty is it? */
295e4b17023SJohn Marino };
296e4b17023SJohn Marino
297e4b17023SJohn Marino /* The three ways of getting then name of the current function. */
298e4b17023SJohn Marino
299e4b17023SJohn Marino const struct fname_var_t fname_vars[] =
300e4b17023SJohn Marino {
301e4b17023SJohn Marino /* C99 compliant __func__, must be first. */
302e4b17023SJohn Marino {&c99_function_name_decl_node, RID_C99_FUNCTION_NAME, 0},
303e4b17023SJohn Marino /* GCC __FUNCTION__ compliant. */
304e4b17023SJohn Marino {&function_name_decl_node, RID_FUNCTION_NAME, 0},
305e4b17023SJohn Marino /* GCC __PRETTY_FUNCTION__ compliant. */
306e4b17023SJohn Marino {&pretty_function_name_decl_node, RID_PRETTY_FUNCTION_NAME, 1},
307e4b17023SJohn Marino {NULL, 0, 0},
308e4b17023SJohn Marino };
309e4b17023SJohn Marino
310e4b17023SJohn Marino /* Global visibility options. */
311e4b17023SJohn Marino struct visibility_flags visibility_options;
312e4b17023SJohn Marino
313e4b17023SJohn Marino static tree c_fully_fold_internal (tree expr, bool, bool *, bool *);
314e4b17023SJohn Marino static tree check_case_value (tree);
315e4b17023SJohn Marino static bool check_case_bounds (tree, tree, tree *, tree *);
316e4b17023SJohn Marino
317e4b17023SJohn Marino static tree handle_packed_attribute (tree *, tree, tree, int, bool *);
318e4b17023SJohn Marino static tree handle_nocommon_attribute (tree *, tree, tree, int, bool *);
319e4b17023SJohn Marino static tree handle_common_attribute (tree *, tree, tree, int, bool *);
320e4b17023SJohn Marino static tree handle_noreturn_attribute (tree *, tree, tree, int, bool *);
321e4b17023SJohn Marino static tree handle_hot_attribute (tree *, tree, tree, int, bool *);
322e4b17023SJohn Marino static tree handle_cold_attribute (tree *, tree, tree, int, bool *);
323e4b17023SJohn Marino static tree handle_noinline_attribute (tree *, tree, tree, int, bool *);
324e4b17023SJohn Marino static tree handle_noclone_attribute (tree *, tree, tree, int, bool *);
325e4b17023SJohn Marino static tree handle_leaf_attribute (tree *, tree, tree, int, bool *);
326e4b17023SJohn Marino static tree handle_always_inline_attribute (tree *, tree, tree, int,
327e4b17023SJohn Marino bool *);
328e4b17023SJohn Marino static tree handle_gnu_inline_attribute (tree *, tree, tree, int, bool *);
329e4b17023SJohn Marino static tree handle_artificial_attribute (tree *, tree, tree, int, bool *);
330e4b17023SJohn Marino static tree handle_flatten_attribute (tree *, tree, tree, int, bool *);
331e4b17023SJohn Marino static tree handle_error_attribute (tree *, tree, tree, int, bool *);
332e4b17023SJohn Marino static tree handle_used_attribute (tree *, tree, tree, int, bool *);
333e4b17023SJohn Marino static tree handle_unused_attribute (tree *, tree, tree, int, bool *);
334e4b17023SJohn Marino static tree handle_externally_visible_attribute (tree *, tree, tree, int,
335e4b17023SJohn Marino bool *);
336e4b17023SJohn Marino static tree handle_const_attribute (tree *, tree, tree, int, bool *);
337e4b17023SJohn Marino static tree handle_transparent_union_attribute (tree *, tree, tree,
338e4b17023SJohn Marino int, bool *);
339e4b17023SJohn Marino static tree handle_constructor_attribute (tree *, tree, tree, int, bool *);
340e4b17023SJohn Marino static tree handle_destructor_attribute (tree *, tree, tree, int, bool *);
341e4b17023SJohn Marino static tree handle_mode_attribute (tree *, tree, tree, int, bool *);
342e4b17023SJohn Marino static tree handle_section_attribute (tree *, tree, tree, int, bool *);
343e4b17023SJohn Marino static tree handle_aligned_attribute (tree *, tree, tree, int, bool *);
344e4b17023SJohn Marino static tree handle_weak_attribute (tree *, tree, tree, int, bool *) ;
345e4b17023SJohn Marino static tree handle_alias_ifunc_attribute (bool, tree *, tree, tree, bool *);
346e4b17023SJohn Marino static tree handle_ifunc_attribute (tree *, tree, tree, int, bool *);
347e4b17023SJohn Marino static tree handle_alias_attribute (tree *, tree, tree, int, bool *);
348e4b17023SJohn Marino static tree handle_weakref_attribute (tree *, tree, tree, int, bool *) ;
349e4b17023SJohn Marino static tree handle_visibility_attribute (tree *, tree, tree, int,
350e4b17023SJohn Marino bool *);
351e4b17023SJohn Marino static tree handle_tls_model_attribute (tree *, tree, tree, int,
352e4b17023SJohn Marino bool *);
353e4b17023SJohn Marino static tree handle_no_instrument_function_attribute (tree *, tree,
354e4b17023SJohn Marino tree, int, bool *);
355e4b17023SJohn Marino static tree handle_malloc_attribute (tree *, tree, tree, int, bool *);
356e4b17023SJohn Marino static tree handle_returns_twice_attribute (tree *, tree, tree, int, bool *);
357e4b17023SJohn Marino static tree handle_no_limit_stack_attribute (tree *, tree, tree, int,
358e4b17023SJohn Marino bool *);
359e4b17023SJohn Marino static tree handle_pure_attribute (tree *, tree, tree, int, bool *);
360e4b17023SJohn Marino static tree handle_tm_attribute (tree *, tree, tree, int, bool *);
361e4b17023SJohn Marino static tree handle_tm_wrap_attribute (tree *, tree, tree, int, bool *);
362e4b17023SJohn Marino static tree handle_novops_attribute (tree *, tree, tree, int, bool *);
363e4b17023SJohn Marino static tree handle_deprecated_attribute (tree *, tree, tree, int,
364e4b17023SJohn Marino bool *);
365e4b17023SJohn Marino static tree handle_vector_size_attribute (tree *, tree, tree, int,
366e4b17023SJohn Marino bool *);
367e4b17023SJohn Marino static tree handle_nonnull_attribute (tree *, tree, tree, int, bool *);
368e4b17023SJohn Marino static tree handle_nothrow_attribute (tree *, tree, tree, int, bool *);
369e4b17023SJohn Marino static tree handle_cleanup_attribute (tree *, tree, tree, int, bool *);
370e4b17023SJohn Marino static tree handle_warn_unused_result_attribute (tree *, tree, tree, int,
371e4b17023SJohn Marino bool *);
372e4b17023SJohn Marino static tree handle_sentinel_attribute (tree *, tree, tree, int, bool *);
373e4b17023SJohn Marino static tree handle_type_generic_attribute (tree *, tree, tree, int, bool *);
374e4b17023SJohn Marino static tree handle_alloc_size_attribute (tree *, tree, tree, int, bool *);
375e4b17023SJohn Marino static tree handle_target_attribute (tree *, tree, tree, int, bool *);
376e4b17023SJohn Marino static tree handle_optimize_attribute (tree *, tree, tree, int, bool *);
377e4b17023SJohn Marino static tree ignore_attribute (tree *, tree, tree, int, bool *);
378e4b17023SJohn Marino static tree handle_no_split_stack_attribute (tree *, tree, tree, int, bool *);
379e4b17023SJohn Marino static tree handle_fnspec_attribute (tree *, tree, tree, int, bool *);
380e4b17023SJohn Marino
381e4b17023SJohn Marino static void check_function_nonnull (tree, int, tree *);
382e4b17023SJohn Marino static void check_nonnull_arg (void *, tree, unsigned HOST_WIDE_INT);
383e4b17023SJohn Marino static bool nonnull_check_p (tree, unsigned HOST_WIDE_INT);
384e4b17023SJohn Marino static bool get_nonnull_operand (tree, unsigned HOST_WIDE_INT *);
385e4b17023SJohn Marino static int resort_field_decl_cmp (const void *, const void *);
386e4b17023SJohn Marino
387e4b17023SJohn Marino /* Reserved words. The third field is a mask: keywords are disabled
388e4b17023SJohn Marino if they match the mask.
389e4b17023SJohn Marino
390e4b17023SJohn Marino Masks for languages:
391e4b17023SJohn Marino C --std=c89: D_C99 | D_CXXONLY | D_OBJC | D_CXX_OBJC
392e4b17023SJohn Marino C --std=c99: D_CXXONLY | D_OBJC
393e4b17023SJohn Marino ObjC is like C except that D_OBJC and D_CXX_OBJC are not set
394e4b17023SJohn Marino C++ --std=c98: D_CONLY | D_CXXOX | D_OBJC
395e4b17023SJohn Marino C++ --std=c0x: D_CONLY | D_OBJC
396e4b17023SJohn Marino ObjC++ is like C++ except that D_OBJC is not set
397e4b17023SJohn Marino
398e4b17023SJohn Marino If -fno-asm is used, D_ASM is added to the mask. If
399e4b17023SJohn Marino -fno-gnu-keywords is used, D_EXT is added. If -fno-asm and C in
400e4b17023SJohn Marino C89 mode, D_EXT89 is added for both -fno-asm and -fno-gnu-keywords.
401e4b17023SJohn Marino In C with -Wc++-compat, we warn if D_CXXWARN is set.
402e4b17023SJohn Marino
403e4b17023SJohn Marino Note the complication of the D_CXX_OBJC keywords. These are
404e4b17023SJohn Marino reserved words such as 'class'. In C++, 'class' is a reserved
405e4b17023SJohn Marino word. In Objective-C++ it is too. In Objective-C, it is a
406e4b17023SJohn Marino reserved word too, but only if it follows an '@' sign.
407e4b17023SJohn Marino */
408e4b17023SJohn Marino const struct c_common_resword c_common_reswords[] =
409e4b17023SJohn Marino {
410e4b17023SJohn Marino { "_Alignas", RID_ALIGNAS, D_CONLY },
411e4b17023SJohn Marino { "_Alignof", RID_ALIGNOF, D_CONLY },
412e4b17023SJohn Marino { "_Bool", RID_BOOL, D_CONLY },
413e4b17023SJohn Marino { "_Complex", RID_COMPLEX, 0 },
414e4b17023SJohn Marino { "_Imaginary", RID_IMAGINARY, D_CONLY },
415e4b17023SJohn Marino { "_Decimal32", RID_DFLOAT32, D_CONLY | D_EXT },
416e4b17023SJohn Marino { "_Decimal64", RID_DFLOAT64, D_CONLY | D_EXT },
417e4b17023SJohn Marino { "_Decimal128", RID_DFLOAT128, D_CONLY | D_EXT },
418e4b17023SJohn Marino { "_Fract", RID_FRACT, D_CONLY | D_EXT },
419e4b17023SJohn Marino { "_Accum", RID_ACCUM, D_CONLY | D_EXT },
420e4b17023SJohn Marino { "_Sat", RID_SAT, D_CONLY | D_EXT },
421e4b17023SJohn Marino { "_Static_assert", RID_STATIC_ASSERT, D_CONLY },
422e4b17023SJohn Marino { "_Noreturn", RID_NORETURN, D_CONLY },
423e4b17023SJohn Marino { "__FUNCTION__", RID_FUNCTION_NAME, 0 },
424e4b17023SJohn Marino { "__PRETTY_FUNCTION__", RID_PRETTY_FUNCTION_NAME, 0 },
425e4b17023SJohn Marino { "__alignof", RID_ALIGNOF, 0 },
426e4b17023SJohn Marino { "__alignof__", RID_ALIGNOF, 0 },
427e4b17023SJohn Marino { "__asm", RID_ASM, 0 },
428e4b17023SJohn Marino { "__asm__", RID_ASM, 0 },
429e4b17023SJohn Marino { "__attribute", RID_ATTRIBUTE, 0 },
430e4b17023SJohn Marino { "__attribute__", RID_ATTRIBUTE, 0 },
431e4b17023SJohn Marino { "__bases", RID_BASES, D_CXXONLY },
432e4b17023SJohn Marino { "__builtin_choose_expr", RID_CHOOSE_EXPR, D_CONLY },
433e4b17023SJohn Marino { "__builtin_complex", RID_BUILTIN_COMPLEX, D_CONLY },
434e4b17023SJohn Marino { "__builtin_shuffle", RID_BUILTIN_SHUFFLE, D_CONLY },
435e4b17023SJohn Marino { "__builtin_offsetof", RID_OFFSETOF, 0 },
436e4b17023SJohn Marino { "__builtin_types_compatible_p", RID_TYPES_COMPATIBLE_P, D_CONLY },
437e4b17023SJohn Marino { "__builtin_va_arg", RID_VA_ARG, 0 },
438e4b17023SJohn Marino { "__complex", RID_COMPLEX, 0 },
439e4b17023SJohn Marino { "__complex__", RID_COMPLEX, 0 },
440e4b17023SJohn Marino { "__const", RID_CONST, 0 },
441e4b17023SJohn Marino { "__const__", RID_CONST, 0 },
442e4b17023SJohn Marino { "__decltype", RID_DECLTYPE, D_CXXONLY },
443e4b17023SJohn Marino { "__direct_bases", RID_DIRECT_BASES, D_CXXONLY },
444e4b17023SJohn Marino { "__extension__", RID_EXTENSION, 0 },
445e4b17023SJohn Marino { "__func__", RID_C99_FUNCTION_NAME, 0 },
446e4b17023SJohn Marino { "__has_nothrow_assign", RID_HAS_NOTHROW_ASSIGN, D_CXXONLY },
447e4b17023SJohn Marino { "__has_nothrow_constructor", RID_HAS_NOTHROW_CONSTRUCTOR, D_CXXONLY },
448e4b17023SJohn Marino { "__has_nothrow_copy", RID_HAS_NOTHROW_COPY, D_CXXONLY },
449e4b17023SJohn Marino { "__has_trivial_assign", RID_HAS_TRIVIAL_ASSIGN, D_CXXONLY },
450e4b17023SJohn Marino { "__has_trivial_constructor", RID_HAS_TRIVIAL_CONSTRUCTOR, D_CXXONLY },
451e4b17023SJohn Marino { "__has_trivial_copy", RID_HAS_TRIVIAL_COPY, D_CXXONLY },
452e4b17023SJohn Marino { "__has_trivial_destructor", RID_HAS_TRIVIAL_DESTRUCTOR, D_CXXONLY },
453e4b17023SJohn Marino { "__has_virtual_destructor", RID_HAS_VIRTUAL_DESTRUCTOR, D_CXXONLY },
454e4b17023SJohn Marino { "__imag", RID_IMAGPART, 0 },
455e4b17023SJohn Marino { "__imag__", RID_IMAGPART, 0 },
456e4b17023SJohn Marino { "__inline", RID_INLINE, 0 },
457e4b17023SJohn Marino { "__inline__", RID_INLINE, 0 },
458e4b17023SJohn Marino { "__int128", RID_INT128, 0 },
459e4b17023SJohn Marino { "__is_abstract", RID_IS_ABSTRACT, D_CXXONLY },
460e4b17023SJohn Marino { "__is_base_of", RID_IS_BASE_OF, D_CXXONLY },
461e4b17023SJohn Marino { "__is_class", RID_IS_CLASS, D_CXXONLY },
462e4b17023SJohn Marino { "__is_convertible_to", RID_IS_CONVERTIBLE_TO, D_CXXONLY },
463e4b17023SJohn Marino { "__is_empty", RID_IS_EMPTY, D_CXXONLY },
464e4b17023SJohn Marino { "__is_enum", RID_IS_ENUM, D_CXXONLY },
465e4b17023SJohn Marino { "__is_final", RID_IS_FINAL, D_CXXONLY },
466e4b17023SJohn Marino { "__is_literal_type", RID_IS_LITERAL_TYPE, D_CXXONLY },
467e4b17023SJohn Marino { "__is_pod", RID_IS_POD, D_CXXONLY },
468e4b17023SJohn Marino { "__is_polymorphic", RID_IS_POLYMORPHIC, D_CXXONLY },
469e4b17023SJohn Marino { "__is_standard_layout", RID_IS_STD_LAYOUT, D_CXXONLY },
470e4b17023SJohn Marino { "__is_trivial", RID_IS_TRIVIAL, D_CXXONLY },
471e4b17023SJohn Marino { "__is_union", RID_IS_UNION, D_CXXONLY },
472e4b17023SJohn Marino { "__label__", RID_LABEL, 0 },
473e4b17023SJohn Marino { "__null", RID_NULL, 0 },
474e4b17023SJohn Marino { "__real", RID_REALPART, 0 },
475e4b17023SJohn Marino { "__real__", RID_REALPART, 0 },
476e4b17023SJohn Marino { "__restrict", RID_RESTRICT, 0 },
477e4b17023SJohn Marino { "__restrict__", RID_RESTRICT, 0 },
478e4b17023SJohn Marino { "__signed", RID_SIGNED, 0 },
479e4b17023SJohn Marino { "__signed__", RID_SIGNED, 0 },
480e4b17023SJohn Marino { "__thread", RID_THREAD, 0 },
481e4b17023SJohn Marino { "__transaction_atomic", RID_TRANSACTION_ATOMIC, 0 },
482e4b17023SJohn Marino { "__transaction_relaxed", RID_TRANSACTION_RELAXED, 0 },
483e4b17023SJohn Marino { "__transaction_cancel", RID_TRANSACTION_CANCEL, 0 },
484e4b17023SJohn Marino { "__typeof", RID_TYPEOF, 0 },
485e4b17023SJohn Marino { "__typeof__", RID_TYPEOF, 0 },
486e4b17023SJohn Marino { "__underlying_type", RID_UNDERLYING_TYPE, D_CXXONLY },
487e4b17023SJohn Marino { "__volatile", RID_VOLATILE, 0 },
488e4b17023SJohn Marino { "__volatile__", RID_VOLATILE, 0 },
489e4b17023SJohn Marino { "alignof", RID_ALIGNOF, D_CXXONLY | D_CXX0X | D_CXXWARN },
490e4b17023SJohn Marino { "asm", RID_ASM, D_ASM },
491e4b17023SJohn Marino { "auto", RID_AUTO, 0 },
492e4b17023SJohn Marino { "bool", RID_BOOL, D_CXXONLY | D_CXXWARN },
493e4b17023SJohn Marino { "break", RID_BREAK, 0 },
494e4b17023SJohn Marino { "case", RID_CASE, 0 },
495e4b17023SJohn Marino { "catch", RID_CATCH, D_CXX_OBJC | D_CXXWARN },
496e4b17023SJohn Marino { "char", RID_CHAR, 0 },
497e4b17023SJohn Marino { "char16_t", RID_CHAR16, D_CXXONLY | D_CXX0X | D_CXXWARN },
498e4b17023SJohn Marino { "char32_t", RID_CHAR32, D_CXXONLY | D_CXX0X | D_CXXWARN },
499e4b17023SJohn Marino { "class", RID_CLASS, D_CXX_OBJC | D_CXXWARN },
500e4b17023SJohn Marino { "const", RID_CONST, 0 },
501e4b17023SJohn Marino { "constexpr", RID_CONSTEXPR, D_CXXONLY | D_CXX0X | D_CXXWARN },
502e4b17023SJohn Marino { "const_cast", RID_CONSTCAST, D_CXXONLY | D_CXXWARN },
503e4b17023SJohn Marino { "continue", RID_CONTINUE, 0 },
504e4b17023SJohn Marino { "decltype", RID_DECLTYPE, D_CXXONLY | D_CXX0X | D_CXXWARN },
505e4b17023SJohn Marino { "default", RID_DEFAULT, 0 },
506e4b17023SJohn Marino { "delete", RID_DELETE, D_CXXONLY | D_CXXWARN },
507e4b17023SJohn Marino { "do", RID_DO, 0 },
508e4b17023SJohn Marino { "double", RID_DOUBLE, 0 },
509e4b17023SJohn Marino { "dynamic_cast", RID_DYNCAST, D_CXXONLY | D_CXXWARN },
510e4b17023SJohn Marino { "else", RID_ELSE, 0 },
511e4b17023SJohn Marino { "enum", RID_ENUM, 0 },
512e4b17023SJohn Marino { "explicit", RID_EXPLICIT, D_CXXONLY | D_CXXWARN },
513e4b17023SJohn Marino { "export", RID_EXPORT, D_CXXONLY | D_CXXWARN },
514e4b17023SJohn Marino { "extern", RID_EXTERN, 0 },
515e4b17023SJohn Marino { "false", RID_FALSE, D_CXXONLY | D_CXXWARN },
516e4b17023SJohn Marino { "float", RID_FLOAT, 0 },
517e4b17023SJohn Marino { "for", RID_FOR, 0 },
518e4b17023SJohn Marino { "friend", RID_FRIEND, D_CXXONLY | D_CXXWARN },
519e4b17023SJohn Marino { "goto", RID_GOTO, 0 },
520e4b17023SJohn Marino { "if", RID_IF, 0 },
521e4b17023SJohn Marino { "inline", RID_INLINE, D_EXT89 },
522e4b17023SJohn Marino { "int", RID_INT, 0 },
523e4b17023SJohn Marino { "long", RID_LONG, 0 },
524e4b17023SJohn Marino { "mutable", RID_MUTABLE, D_CXXONLY | D_CXXWARN },
525e4b17023SJohn Marino { "namespace", RID_NAMESPACE, D_CXXONLY | D_CXXWARN },
526e4b17023SJohn Marino { "new", RID_NEW, D_CXXONLY | D_CXXWARN },
527e4b17023SJohn Marino { "noexcept", RID_NOEXCEPT, D_CXXONLY | D_CXX0X | D_CXXWARN },
528e4b17023SJohn Marino { "nullptr", RID_NULLPTR, D_CXXONLY | D_CXX0X | D_CXXWARN },
529e4b17023SJohn Marino { "operator", RID_OPERATOR, D_CXXONLY | D_CXXWARN },
530e4b17023SJohn Marino { "private", RID_PRIVATE, D_CXX_OBJC | D_CXXWARN },
531e4b17023SJohn Marino { "protected", RID_PROTECTED, D_CXX_OBJC | D_CXXWARN },
532e4b17023SJohn Marino { "public", RID_PUBLIC, D_CXX_OBJC | D_CXXWARN },
533e4b17023SJohn Marino { "register", RID_REGISTER, 0 },
534e4b17023SJohn Marino { "reinterpret_cast", RID_REINTCAST, D_CXXONLY | D_CXXWARN },
535e4b17023SJohn Marino { "restrict", RID_RESTRICT, D_CONLY | D_C99 },
536e4b17023SJohn Marino { "return", RID_RETURN, 0 },
537e4b17023SJohn Marino { "short", RID_SHORT, 0 },
538e4b17023SJohn Marino { "signed", RID_SIGNED, 0 },
539e4b17023SJohn Marino { "sizeof", RID_SIZEOF, 0 },
540e4b17023SJohn Marino { "static", RID_STATIC, 0 },
541e4b17023SJohn Marino { "static_assert", RID_STATIC_ASSERT, D_CXXONLY | D_CXX0X | D_CXXWARN },
542e4b17023SJohn Marino { "static_cast", RID_STATCAST, D_CXXONLY | D_CXXWARN },
543e4b17023SJohn Marino { "struct", RID_STRUCT, 0 },
544e4b17023SJohn Marino { "switch", RID_SWITCH, 0 },
545e4b17023SJohn Marino { "template", RID_TEMPLATE, D_CXXONLY | D_CXXWARN },
546e4b17023SJohn Marino { "this", RID_THIS, D_CXXONLY | D_CXXWARN },
547e4b17023SJohn Marino { "throw", RID_THROW, D_CXX_OBJC | D_CXXWARN },
548e4b17023SJohn Marino { "true", RID_TRUE, D_CXXONLY | D_CXXWARN },
549e4b17023SJohn Marino { "try", RID_TRY, D_CXX_OBJC | D_CXXWARN },
550e4b17023SJohn Marino { "typedef", RID_TYPEDEF, 0 },
551e4b17023SJohn Marino { "typename", RID_TYPENAME, D_CXXONLY | D_CXXWARN },
552e4b17023SJohn Marino { "typeid", RID_TYPEID, D_CXXONLY | D_CXXWARN },
553e4b17023SJohn Marino { "typeof", RID_TYPEOF, D_ASM | D_EXT },
554e4b17023SJohn Marino { "union", RID_UNION, 0 },
555e4b17023SJohn Marino { "unsigned", RID_UNSIGNED, 0 },
556e4b17023SJohn Marino { "using", RID_USING, D_CXXONLY | D_CXXWARN },
557e4b17023SJohn Marino { "virtual", RID_VIRTUAL, D_CXXONLY | D_CXXWARN },
558e4b17023SJohn Marino { "void", RID_VOID, 0 },
559e4b17023SJohn Marino { "volatile", RID_VOLATILE, 0 },
560e4b17023SJohn Marino { "wchar_t", RID_WCHAR, D_CXXONLY },
561e4b17023SJohn Marino { "while", RID_WHILE, 0 },
562e4b17023SJohn Marino /* These Objective-C keywords are recognized only immediately after
563e4b17023SJohn Marino an '@'. */
564e4b17023SJohn Marino { "compatibility_alias", RID_AT_ALIAS, D_OBJC },
565e4b17023SJohn Marino { "defs", RID_AT_DEFS, D_OBJC },
566e4b17023SJohn Marino { "encode", RID_AT_ENCODE, D_OBJC },
567e4b17023SJohn Marino { "end", RID_AT_END, D_OBJC },
568e4b17023SJohn Marino { "implementation", RID_AT_IMPLEMENTATION, D_OBJC },
569e4b17023SJohn Marino { "interface", RID_AT_INTERFACE, D_OBJC },
570e4b17023SJohn Marino { "protocol", RID_AT_PROTOCOL, D_OBJC },
571e4b17023SJohn Marino { "selector", RID_AT_SELECTOR, D_OBJC },
572e4b17023SJohn Marino { "finally", RID_AT_FINALLY, D_OBJC },
573e4b17023SJohn Marino { "synchronized", RID_AT_SYNCHRONIZED, D_OBJC },
574e4b17023SJohn Marino { "optional", RID_AT_OPTIONAL, D_OBJC },
575e4b17023SJohn Marino { "required", RID_AT_REQUIRED, D_OBJC },
576e4b17023SJohn Marino { "property", RID_AT_PROPERTY, D_OBJC },
577e4b17023SJohn Marino { "package", RID_AT_PACKAGE, D_OBJC },
578e4b17023SJohn Marino { "synthesize", RID_AT_SYNTHESIZE, D_OBJC },
579e4b17023SJohn Marino { "dynamic", RID_AT_DYNAMIC, D_OBJC },
580e4b17023SJohn Marino /* These are recognized only in protocol-qualifier context
581e4b17023SJohn Marino (see above) */
582e4b17023SJohn Marino { "bycopy", RID_BYCOPY, D_OBJC },
583e4b17023SJohn Marino { "byref", RID_BYREF, D_OBJC },
584e4b17023SJohn Marino { "in", RID_IN, D_OBJC },
585e4b17023SJohn Marino { "inout", RID_INOUT, D_OBJC },
586e4b17023SJohn Marino { "oneway", RID_ONEWAY, D_OBJC },
587e4b17023SJohn Marino { "out", RID_OUT, D_OBJC },
588e4b17023SJohn Marino /* These are recognized inside a property attribute list */
589e4b17023SJohn Marino { "assign", RID_ASSIGN, D_OBJC },
590e4b17023SJohn Marino { "copy", RID_COPY, D_OBJC },
591e4b17023SJohn Marino { "getter", RID_GETTER, D_OBJC },
592e4b17023SJohn Marino { "nonatomic", RID_NONATOMIC, D_OBJC },
593e4b17023SJohn Marino { "readonly", RID_READONLY, D_OBJC },
594e4b17023SJohn Marino { "readwrite", RID_READWRITE, D_OBJC },
595e4b17023SJohn Marino { "retain", RID_RETAIN, D_OBJC },
596e4b17023SJohn Marino { "setter", RID_SETTER, D_OBJC },
597e4b17023SJohn Marino };
598e4b17023SJohn Marino
599e4b17023SJohn Marino const unsigned int num_c_common_reswords =
600e4b17023SJohn Marino sizeof c_common_reswords / sizeof (struct c_common_resword);
601e4b17023SJohn Marino
602e4b17023SJohn Marino /* Table of machine-independent attributes common to all C-like languages. */
603e4b17023SJohn Marino const struct attribute_spec c_common_attribute_table[] =
604e4b17023SJohn Marino {
605e4b17023SJohn Marino /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
606e4b17023SJohn Marino affects_type_identity } */
607e4b17023SJohn Marino { "packed", 0, 0, false, false, false,
608e4b17023SJohn Marino handle_packed_attribute , false},
609e4b17023SJohn Marino { "nocommon", 0, 0, true, false, false,
610e4b17023SJohn Marino handle_nocommon_attribute, false},
611e4b17023SJohn Marino { "common", 0, 0, true, false, false,
612e4b17023SJohn Marino handle_common_attribute, false },
613e4b17023SJohn Marino /* FIXME: logically, noreturn attributes should be listed as
614e4b17023SJohn Marino "false, true, true" and apply to function types. But implementing this
615e4b17023SJohn Marino would require all the places in the compiler that use TREE_THIS_VOLATILE
616e4b17023SJohn Marino on a decl to identify non-returning functions to be located and fixed
617e4b17023SJohn Marino to check the function type instead. */
618e4b17023SJohn Marino { "noreturn", 0, 0, true, false, false,
619e4b17023SJohn Marino handle_noreturn_attribute, false },
620e4b17023SJohn Marino { "volatile", 0, 0, true, false, false,
621e4b17023SJohn Marino handle_noreturn_attribute, false },
622e4b17023SJohn Marino { "noinline", 0, 0, true, false, false,
623e4b17023SJohn Marino handle_noinline_attribute, false },
624e4b17023SJohn Marino { "noclone", 0, 0, true, false, false,
625e4b17023SJohn Marino handle_noclone_attribute, false },
626e4b17023SJohn Marino { "leaf", 0, 0, true, false, false,
627e4b17023SJohn Marino handle_leaf_attribute, false },
628e4b17023SJohn Marino { "always_inline", 0, 0, true, false, false,
629e4b17023SJohn Marino handle_always_inline_attribute, false },
630e4b17023SJohn Marino { "gnu_inline", 0, 0, true, false, false,
631e4b17023SJohn Marino handle_gnu_inline_attribute, false },
632e4b17023SJohn Marino { "artificial", 0, 0, true, false, false,
633e4b17023SJohn Marino handle_artificial_attribute, false },
634e4b17023SJohn Marino { "flatten", 0, 0, true, false, false,
635e4b17023SJohn Marino handle_flatten_attribute, false },
636e4b17023SJohn Marino { "used", 0, 0, true, false, false,
637e4b17023SJohn Marino handle_used_attribute, false },
638e4b17023SJohn Marino { "unused", 0, 0, false, false, false,
639e4b17023SJohn Marino handle_unused_attribute, false },
640e4b17023SJohn Marino { "externally_visible", 0, 0, true, false, false,
641e4b17023SJohn Marino handle_externally_visible_attribute, false },
642e4b17023SJohn Marino /* The same comments as for noreturn attributes apply to const ones. */
643e4b17023SJohn Marino { "const", 0, 0, true, false, false,
644e4b17023SJohn Marino handle_const_attribute, false },
645e4b17023SJohn Marino { "transparent_union", 0, 0, false, false, false,
646e4b17023SJohn Marino handle_transparent_union_attribute, false },
647e4b17023SJohn Marino { "constructor", 0, 1, true, false, false,
648e4b17023SJohn Marino handle_constructor_attribute, false },
649e4b17023SJohn Marino { "destructor", 0, 1, true, false, false,
650e4b17023SJohn Marino handle_destructor_attribute, false },
651e4b17023SJohn Marino { "mode", 1, 1, false, true, false,
652e4b17023SJohn Marino handle_mode_attribute, false },
653e4b17023SJohn Marino { "section", 1, 1, true, false, false,
654e4b17023SJohn Marino handle_section_attribute, false },
655e4b17023SJohn Marino { "aligned", 0, 1, false, false, false,
656e4b17023SJohn Marino handle_aligned_attribute, false },
657e4b17023SJohn Marino { "weak", 0, 0, true, false, false,
658e4b17023SJohn Marino handle_weak_attribute, false },
659e4b17023SJohn Marino { "ifunc", 1, 1, true, false, false,
660e4b17023SJohn Marino handle_ifunc_attribute, false },
661e4b17023SJohn Marino { "alias", 1, 1, true, false, false,
662e4b17023SJohn Marino handle_alias_attribute, false },
663e4b17023SJohn Marino { "weakref", 0, 1, true, false, false,
664e4b17023SJohn Marino handle_weakref_attribute, false },
665e4b17023SJohn Marino { "no_instrument_function", 0, 0, true, false, false,
666e4b17023SJohn Marino handle_no_instrument_function_attribute,
667e4b17023SJohn Marino false },
668e4b17023SJohn Marino { "malloc", 0, 0, true, false, false,
669e4b17023SJohn Marino handle_malloc_attribute, false },
670e4b17023SJohn Marino { "returns_twice", 0, 0, true, false, false,
671e4b17023SJohn Marino handle_returns_twice_attribute, false },
672e4b17023SJohn Marino { "no_stack_limit", 0, 0, true, false, false,
673e4b17023SJohn Marino handle_no_limit_stack_attribute, false },
674e4b17023SJohn Marino { "pure", 0, 0, true, false, false,
675e4b17023SJohn Marino handle_pure_attribute, false },
676e4b17023SJohn Marino { "transaction_callable", 0, 0, false, true, false,
677e4b17023SJohn Marino handle_tm_attribute, false },
678e4b17023SJohn Marino { "transaction_unsafe", 0, 0, false, true, false,
679e4b17023SJohn Marino handle_tm_attribute, false },
680e4b17023SJohn Marino { "transaction_safe", 0, 0, false, true, false,
681e4b17023SJohn Marino handle_tm_attribute, false },
682e4b17023SJohn Marino { "transaction_may_cancel_outer", 0, 0, false, true, false,
683e4b17023SJohn Marino handle_tm_attribute, false },
684e4b17023SJohn Marino /* ??? These two attributes didn't make the transition from the
685e4b17023SJohn Marino Intel language document to the multi-vendor language document. */
686e4b17023SJohn Marino { "transaction_pure", 0, 0, false, true, false,
687e4b17023SJohn Marino handle_tm_attribute, false },
688e4b17023SJohn Marino { "transaction_wrap", 1, 1, true, false, false,
689e4b17023SJohn Marino handle_tm_wrap_attribute, false },
690e4b17023SJohn Marino /* For internal use (marking of builtins) only. The name contains space
691e4b17023SJohn Marino to prevent its usage in source code. */
692e4b17023SJohn Marino { "no vops", 0, 0, true, false, false,
693e4b17023SJohn Marino handle_novops_attribute, false },
694e4b17023SJohn Marino { "deprecated", 0, 1, false, false, false,
695e4b17023SJohn Marino handle_deprecated_attribute, false },
696e4b17023SJohn Marino { "vector_size", 1, 1, false, true, false,
697e4b17023SJohn Marino handle_vector_size_attribute, false },
698e4b17023SJohn Marino { "visibility", 1, 1, false, false, false,
699e4b17023SJohn Marino handle_visibility_attribute, false },
700e4b17023SJohn Marino { "tls_model", 1, 1, true, false, false,
701e4b17023SJohn Marino handle_tls_model_attribute, false },
702e4b17023SJohn Marino { "nonnull", 0, -1, false, true, true,
703e4b17023SJohn Marino handle_nonnull_attribute, false },
704e4b17023SJohn Marino { "nothrow", 0, 0, true, false, false,
705e4b17023SJohn Marino handle_nothrow_attribute, false },
706e4b17023SJohn Marino { "may_alias", 0, 0, false, true, false, NULL, false },
707e4b17023SJohn Marino { "cleanup", 1, 1, true, false, false,
708e4b17023SJohn Marino handle_cleanup_attribute, false },
709e4b17023SJohn Marino { "warn_unused_result", 0, 0, false, true, true,
710e4b17023SJohn Marino handle_warn_unused_result_attribute, false },
711e4b17023SJohn Marino { "sentinel", 0, 1, false, true, true,
712e4b17023SJohn Marino handle_sentinel_attribute, false },
713e4b17023SJohn Marino /* For internal use (marking of builtins) only. The name contains space
714e4b17023SJohn Marino to prevent its usage in source code. */
715e4b17023SJohn Marino { "type generic", 0, 0, false, true, true,
716e4b17023SJohn Marino handle_type_generic_attribute, false },
717e4b17023SJohn Marino { "alloc_size", 1, 2, false, true, true,
718e4b17023SJohn Marino handle_alloc_size_attribute, false },
719e4b17023SJohn Marino { "cold", 0, 0, true, false, false,
720e4b17023SJohn Marino handle_cold_attribute, false },
721e4b17023SJohn Marino { "hot", 0, 0, true, false, false,
722e4b17023SJohn Marino handle_hot_attribute, false },
723e4b17023SJohn Marino { "warning", 1, 1, true, false, false,
724e4b17023SJohn Marino handle_error_attribute, false },
725e4b17023SJohn Marino { "error", 1, 1, true, false, false,
726e4b17023SJohn Marino handle_error_attribute, false },
727e4b17023SJohn Marino { "target", 1, -1, true, false, false,
728e4b17023SJohn Marino handle_target_attribute, false },
729e4b17023SJohn Marino { "optimize", 1, -1, true, false, false,
730e4b17023SJohn Marino handle_optimize_attribute, false },
731e4b17023SJohn Marino /* For internal use only. The leading '*' both prevents its usage in
732e4b17023SJohn Marino source code and signals that it may be overridden by machine tables. */
733e4b17023SJohn Marino { "*tm regparm", 0, 0, false, true, true,
734e4b17023SJohn Marino ignore_attribute, false },
735e4b17023SJohn Marino { "no_split_stack", 0, 0, true, false, false,
736e4b17023SJohn Marino handle_no_split_stack_attribute, false },
737e4b17023SJohn Marino /* For internal use (marking of builtins and runtime functions) only.
738e4b17023SJohn Marino The name contains space to prevent its usage in source code. */
739e4b17023SJohn Marino { "fn spec", 1, 1, false, true, true,
740e4b17023SJohn Marino handle_fnspec_attribute, false },
741e4b17023SJohn Marino { NULL, 0, 0, false, false, false, NULL, false }
742e4b17023SJohn Marino };
743e4b17023SJohn Marino
744e4b17023SJohn Marino /* Give the specifications for the format attributes, used by C and all
745e4b17023SJohn Marino descendants. */
746e4b17023SJohn Marino
747e4b17023SJohn Marino const struct attribute_spec c_common_format_attribute_table[] =
748e4b17023SJohn Marino {
749e4b17023SJohn Marino /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
750e4b17023SJohn Marino affects_type_identity } */
751e4b17023SJohn Marino { "format", 3, 3, false, true, true,
752e4b17023SJohn Marino handle_format_attribute, false },
753e4b17023SJohn Marino { "format_arg", 1, 1, false, true, true,
754e4b17023SJohn Marino handle_format_arg_attribute, false },
755e4b17023SJohn Marino { NULL, 0, 0, false, false, false, NULL, false }
756e4b17023SJohn Marino };
757e4b17023SJohn Marino
758e4b17023SJohn Marino /* Return identifier for address space AS. */
759e4b17023SJohn Marino
760e4b17023SJohn Marino const char *
c_addr_space_name(addr_space_t as)761e4b17023SJohn Marino c_addr_space_name (addr_space_t as)
762e4b17023SJohn Marino {
763e4b17023SJohn Marino int rid = RID_FIRST_ADDR_SPACE + as;
764e4b17023SJohn Marino gcc_assert (ridpointers [rid]);
765e4b17023SJohn Marino return IDENTIFIER_POINTER (ridpointers [rid]);
766e4b17023SJohn Marino }
767e4b17023SJohn Marino
768e4b17023SJohn Marino /* Push current bindings for the function name VAR_DECLS. */
769e4b17023SJohn Marino
770e4b17023SJohn Marino void
start_fname_decls(void)771e4b17023SJohn Marino start_fname_decls (void)
772e4b17023SJohn Marino {
773e4b17023SJohn Marino unsigned ix;
774e4b17023SJohn Marino tree saved = NULL_TREE;
775e4b17023SJohn Marino
776e4b17023SJohn Marino for (ix = 0; fname_vars[ix].decl; ix++)
777e4b17023SJohn Marino {
778e4b17023SJohn Marino tree decl = *fname_vars[ix].decl;
779e4b17023SJohn Marino
780e4b17023SJohn Marino if (decl)
781e4b17023SJohn Marino {
782e4b17023SJohn Marino saved = tree_cons (decl, build_int_cst (integer_type_node, ix),
783e4b17023SJohn Marino saved);
784e4b17023SJohn Marino *fname_vars[ix].decl = NULL_TREE;
785e4b17023SJohn Marino }
786e4b17023SJohn Marino }
787e4b17023SJohn Marino if (saved || saved_function_name_decls)
788e4b17023SJohn Marino /* Normally they'll have been NULL, so only push if we've got a
789e4b17023SJohn Marino stack, or they are non-NULL. */
790e4b17023SJohn Marino saved_function_name_decls = tree_cons (saved, NULL_TREE,
791e4b17023SJohn Marino saved_function_name_decls);
792e4b17023SJohn Marino }
793e4b17023SJohn Marino
794e4b17023SJohn Marino /* Finish up the current bindings, adding them into the current function's
795e4b17023SJohn Marino statement tree. This must be done _before_ finish_stmt_tree is called.
796e4b17023SJohn Marino If there is no current function, we must be at file scope and no statements
797e4b17023SJohn Marino are involved. Pop the previous bindings. */
798e4b17023SJohn Marino
799e4b17023SJohn Marino void
finish_fname_decls(void)800e4b17023SJohn Marino finish_fname_decls (void)
801e4b17023SJohn Marino {
802e4b17023SJohn Marino unsigned ix;
803e4b17023SJohn Marino tree stmts = NULL_TREE;
804e4b17023SJohn Marino tree stack = saved_function_name_decls;
805e4b17023SJohn Marino
806e4b17023SJohn Marino for (; stack && TREE_VALUE (stack); stack = TREE_CHAIN (stack))
807e4b17023SJohn Marino append_to_statement_list (TREE_VALUE (stack), &stmts);
808e4b17023SJohn Marino
809e4b17023SJohn Marino if (stmts)
810e4b17023SJohn Marino {
811e4b17023SJohn Marino tree *bodyp = &DECL_SAVED_TREE (current_function_decl);
812e4b17023SJohn Marino
813e4b17023SJohn Marino if (TREE_CODE (*bodyp) == BIND_EXPR)
814e4b17023SJohn Marino bodyp = &BIND_EXPR_BODY (*bodyp);
815e4b17023SJohn Marino
816e4b17023SJohn Marino append_to_statement_list_force (*bodyp, &stmts);
817e4b17023SJohn Marino *bodyp = stmts;
818e4b17023SJohn Marino }
819e4b17023SJohn Marino
820e4b17023SJohn Marino for (ix = 0; fname_vars[ix].decl; ix++)
821e4b17023SJohn Marino *fname_vars[ix].decl = NULL_TREE;
822e4b17023SJohn Marino
823e4b17023SJohn Marino if (stack)
824e4b17023SJohn Marino {
825e4b17023SJohn Marino /* We had saved values, restore them. */
826e4b17023SJohn Marino tree saved;
827e4b17023SJohn Marino
828e4b17023SJohn Marino for (saved = TREE_PURPOSE (stack); saved; saved = TREE_CHAIN (saved))
829e4b17023SJohn Marino {
830e4b17023SJohn Marino tree decl = TREE_PURPOSE (saved);
831e4b17023SJohn Marino unsigned ix = TREE_INT_CST_LOW (TREE_VALUE (saved));
832e4b17023SJohn Marino
833e4b17023SJohn Marino *fname_vars[ix].decl = decl;
834e4b17023SJohn Marino }
835e4b17023SJohn Marino stack = TREE_CHAIN (stack);
836e4b17023SJohn Marino }
837e4b17023SJohn Marino saved_function_name_decls = stack;
838e4b17023SJohn Marino }
839e4b17023SJohn Marino
840e4b17023SJohn Marino /* Return the text name of the current function, suitably prettified
841e4b17023SJohn Marino by PRETTY_P. Return string must be freed by caller. */
842e4b17023SJohn Marino
843e4b17023SJohn Marino const char *
fname_as_string(int pretty_p)844e4b17023SJohn Marino fname_as_string (int pretty_p)
845e4b17023SJohn Marino {
846e4b17023SJohn Marino const char *name = "top level";
847e4b17023SJohn Marino char *namep;
848e4b17023SJohn Marino int vrb = 2, len;
849e4b17023SJohn Marino cpp_string cstr = { 0, 0 }, strname;
850e4b17023SJohn Marino
851e4b17023SJohn Marino if (!pretty_p)
852e4b17023SJohn Marino {
853e4b17023SJohn Marino name = "";
854e4b17023SJohn Marino vrb = 0;
855e4b17023SJohn Marino }
856e4b17023SJohn Marino
857e4b17023SJohn Marino if (current_function_decl)
858e4b17023SJohn Marino name = lang_hooks.decl_printable_name (current_function_decl, vrb);
859e4b17023SJohn Marino
860e4b17023SJohn Marino len = strlen (name) + 3; /* Two for '"'s. One for NULL. */
861e4b17023SJohn Marino
862e4b17023SJohn Marino namep = XNEWVEC (char, len);
863e4b17023SJohn Marino snprintf (namep, len, "\"%s\"", name);
864e4b17023SJohn Marino strname.text = (unsigned char *) namep;
865e4b17023SJohn Marino strname.len = len - 1;
866e4b17023SJohn Marino
867e4b17023SJohn Marino if (cpp_interpret_string (parse_in, &strname, 1, &cstr, CPP_STRING))
868e4b17023SJohn Marino {
869e4b17023SJohn Marino XDELETEVEC (namep);
870e4b17023SJohn Marino return (const char *) cstr.text;
871e4b17023SJohn Marino }
872e4b17023SJohn Marino
873e4b17023SJohn Marino return namep;
874e4b17023SJohn Marino }
875e4b17023SJohn Marino
876e4b17023SJohn Marino /* Return the VAR_DECL for a const char array naming the current
877e4b17023SJohn Marino function. If the VAR_DECL has not yet been created, create it
878e4b17023SJohn Marino now. RID indicates how it should be formatted and IDENTIFIER_NODE
879e4b17023SJohn Marino ID is its name (unfortunately C and C++ hold the RID values of
880e4b17023SJohn Marino keywords in different places, so we can't derive RID from ID in
881e4b17023SJohn Marino this language independent code. LOC is the location of the
882e4b17023SJohn Marino function. */
883e4b17023SJohn Marino
884e4b17023SJohn Marino tree
fname_decl(location_t loc,unsigned int rid,tree id)885e4b17023SJohn Marino fname_decl (location_t loc, unsigned int rid, tree id)
886e4b17023SJohn Marino {
887e4b17023SJohn Marino unsigned ix;
888e4b17023SJohn Marino tree decl = NULL_TREE;
889e4b17023SJohn Marino
890e4b17023SJohn Marino for (ix = 0; fname_vars[ix].decl; ix++)
891e4b17023SJohn Marino if (fname_vars[ix].rid == rid)
892e4b17023SJohn Marino break;
893e4b17023SJohn Marino
894e4b17023SJohn Marino decl = *fname_vars[ix].decl;
895e4b17023SJohn Marino if (!decl)
896e4b17023SJohn Marino {
897e4b17023SJohn Marino /* If a tree is built here, it would normally have the lineno of
898e4b17023SJohn Marino the current statement. Later this tree will be moved to the
899e4b17023SJohn Marino beginning of the function and this line number will be wrong.
900e4b17023SJohn Marino To avoid this problem set the lineno to 0 here; that prevents
901e4b17023SJohn Marino it from appearing in the RTL. */
902e4b17023SJohn Marino tree stmts;
903e4b17023SJohn Marino location_t saved_location = input_location;
904e4b17023SJohn Marino input_location = UNKNOWN_LOCATION;
905e4b17023SJohn Marino
906e4b17023SJohn Marino stmts = push_stmt_list ();
907e4b17023SJohn Marino decl = (*make_fname_decl) (loc, id, fname_vars[ix].pretty);
908e4b17023SJohn Marino stmts = pop_stmt_list (stmts);
909e4b17023SJohn Marino if (!IS_EMPTY_STMT (stmts))
910e4b17023SJohn Marino saved_function_name_decls
911e4b17023SJohn Marino = tree_cons (decl, stmts, saved_function_name_decls);
912e4b17023SJohn Marino *fname_vars[ix].decl = decl;
913e4b17023SJohn Marino input_location = saved_location;
914e4b17023SJohn Marino }
915e4b17023SJohn Marino if (!ix && !current_function_decl)
916e4b17023SJohn Marino pedwarn (loc, 0, "%qD is not defined outside of function scope", decl);
917e4b17023SJohn Marino
918e4b17023SJohn Marino return decl;
919e4b17023SJohn Marino }
920e4b17023SJohn Marino
921e4b17023SJohn Marino /* Given a STRING_CST, give it a suitable array-of-chars data type. */
922e4b17023SJohn Marino
923e4b17023SJohn Marino tree
fix_string_type(tree value)924e4b17023SJohn Marino fix_string_type (tree value)
925e4b17023SJohn Marino {
926e4b17023SJohn Marino int length = TREE_STRING_LENGTH (value);
927e4b17023SJohn Marino int nchars;
928e4b17023SJohn Marino tree e_type, i_type, a_type;
929e4b17023SJohn Marino
930e4b17023SJohn Marino /* Compute the number of elements, for the array type. */
931e4b17023SJohn Marino if (TREE_TYPE (value) == char_array_type_node || !TREE_TYPE (value))
932e4b17023SJohn Marino {
933e4b17023SJohn Marino nchars = length;
934e4b17023SJohn Marino e_type = char_type_node;
935e4b17023SJohn Marino }
936e4b17023SJohn Marino else if (TREE_TYPE (value) == char16_array_type_node)
937e4b17023SJohn Marino {
938e4b17023SJohn Marino nchars = length / (TYPE_PRECISION (char16_type_node) / BITS_PER_UNIT);
939e4b17023SJohn Marino e_type = char16_type_node;
940e4b17023SJohn Marino }
941e4b17023SJohn Marino else if (TREE_TYPE (value) == char32_array_type_node)
942e4b17023SJohn Marino {
943e4b17023SJohn Marino nchars = length / (TYPE_PRECISION (char32_type_node) / BITS_PER_UNIT);
944e4b17023SJohn Marino e_type = char32_type_node;
945e4b17023SJohn Marino }
946e4b17023SJohn Marino else
947e4b17023SJohn Marino {
948e4b17023SJohn Marino nchars = length / (TYPE_PRECISION (wchar_type_node) / BITS_PER_UNIT);
949e4b17023SJohn Marino e_type = wchar_type_node;
950e4b17023SJohn Marino }
951e4b17023SJohn Marino
952e4b17023SJohn Marino /* C89 2.2.4.1, C99 5.2.4.1 (Translation limits). The analogous
953e4b17023SJohn Marino limit in C++98 Annex B is very large (65536) and is not normative,
954e4b17023SJohn Marino so we do not diagnose it (warn_overlength_strings is forced off
955e4b17023SJohn Marino in c_common_post_options). */
956e4b17023SJohn Marino if (warn_overlength_strings)
957e4b17023SJohn Marino {
958e4b17023SJohn Marino const int nchars_max = flag_isoc99 ? 4095 : 509;
959e4b17023SJohn Marino const int relevant_std = flag_isoc99 ? 99 : 90;
960e4b17023SJohn Marino if (nchars - 1 > nchars_max)
961e4b17023SJohn Marino /* Translators: The %d after 'ISO C' will be 90 or 99. Do not
962e4b17023SJohn Marino separate the %d from the 'C'. 'ISO' should not be
963e4b17023SJohn Marino translated, but it may be moved after 'C%d' in languages
964e4b17023SJohn Marino where modifiers follow nouns. */
965e4b17023SJohn Marino pedwarn (input_location, OPT_Woverlength_strings,
966e4b17023SJohn Marino "string length %qd is greater than the length %qd "
967e4b17023SJohn Marino "ISO C%d compilers are required to support",
968e4b17023SJohn Marino nchars - 1, nchars_max, relevant_std);
969e4b17023SJohn Marino }
970e4b17023SJohn Marino
971e4b17023SJohn Marino /* Create the array type for the string constant. The ISO C++
972e4b17023SJohn Marino standard says that a string literal has type `const char[N]' or
973e4b17023SJohn Marino `const wchar_t[N]'. We use the same logic when invoked as a C
974e4b17023SJohn Marino front-end with -Wwrite-strings.
975e4b17023SJohn Marino ??? We should change the type of an expression depending on the
976e4b17023SJohn Marino state of a warning flag. We should just be warning -- see how
977e4b17023SJohn Marino this is handled in the C++ front-end for the deprecated implicit
978e4b17023SJohn Marino conversion from string literals to `char*' or `wchar_t*'.
979e4b17023SJohn Marino
980e4b17023SJohn Marino The C++ front end relies on TYPE_MAIN_VARIANT of a cv-qualified
981e4b17023SJohn Marino array type being the unqualified version of that type.
982e4b17023SJohn Marino Therefore, if we are constructing an array of const char, we must
983e4b17023SJohn Marino construct the matching unqualified array type first. The C front
984e4b17023SJohn Marino end does not require this, but it does no harm, so we do it
985e4b17023SJohn Marino unconditionally. */
986e4b17023SJohn Marino i_type = build_index_type (size_int (nchars - 1));
987e4b17023SJohn Marino a_type = build_array_type (e_type, i_type);
988e4b17023SJohn Marino if (c_dialect_cxx() || warn_write_strings)
989e4b17023SJohn Marino a_type = c_build_qualified_type (a_type, TYPE_QUAL_CONST);
990e4b17023SJohn Marino
991e4b17023SJohn Marino TREE_TYPE (value) = a_type;
992e4b17023SJohn Marino TREE_CONSTANT (value) = 1;
993e4b17023SJohn Marino TREE_READONLY (value) = 1;
994e4b17023SJohn Marino TREE_STATIC (value) = 1;
995e4b17023SJohn Marino return value;
996e4b17023SJohn Marino }
997e4b17023SJohn Marino
998e4b17023SJohn Marino /* If DISABLE is true, stop issuing warnings. This is used when
999e4b17023SJohn Marino parsing code that we know will not be executed. This function may
1000e4b17023SJohn Marino be called multiple times, and works as a stack. */
1001e4b17023SJohn Marino
1002e4b17023SJohn Marino static void
c_disable_warnings(bool disable)1003e4b17023SJohn Marino c_disable_warnings (bool disable)
1004e4b17023SJohn Marino {
1005e4b17023SJohn Marino if (disable)
1006e4b17023SJohn Marino {
1007e4b17023SJohn Marino ++c_inhibit_evaluation_warnings;
1008e4b17023SJohn Marino fold_defer_overflow_warnings ();
1009e4b17023SJohn Marino }
1010e4b17023SJohn Marino }
1011e4b17023SJohn Marino
1012e4b17023SJohn Marino /* If ENABLE is true, reenable issuing warnings. */
1013e4b17023SJohn Marino
1014e4b17023SJohn Marino static void
c_enable_warnings(bool enable)1015e4b17023SJohn Marino c_enable_warnings (bool enable)
1016e4b17023SJohn Marino {
1017e4b17023SJohn Marino if (enable)
1018e4b17023SJohn Marino {
1019e4b17023SJohn Marino --c_inhibit_evaluation_warnings;
1020e4b17023SJohn Marino fold_undefer_and_ignore_overflow_warnings ();
1021e4b17023SJohn Marino }
1022e4b17023SJohn Marino }
1023e4b17023SJohn Marino
1024e4b17023SJohn Marino /* Fully fold EXPR, an expression that was not folded (beyond integer
1025e4b17023SJohn Marino constant expressions and null pointer constants) when being built
1026e4b17023SJohn Marino up. If IN_INIT, this is in a static initializer and certain
1027e4b17023SJohn Marino changes are made to the folding done. Clear *MAYBE_CONST if
1028e4b17023SJohn Marino MAYBE_CONST is not NULL and EXPR is definitely not a constant
1029e4b17023SJohn Marino expression because it contains an evaluated operator (in C99) or an
1030e4b17023SJohn Marino operator outside of sizeof returning an integer constant (in C90)
1031e4b17023SJohn Marino not permitted in constant expressions, or because it contains an
1032e4b17023SJohn Marino evaluated arithmetic overflow. (*MAYBE_CONST should typically be
1033e4b17023SJohn Marino set to true by callers before calling this function.) Return the
1034e4b17023SJohn Marino folded expression. Function arguments have already been folded
1035e4b17023SJohn Marino before calling this function, as have the contents of SAVE_EXPR,
1036e4b17023SJohn Marino TARGET_EXPR, BIND_EXPR, VA_ARG_EXPR, OBJ_TYPE_REF and
1037e4b17023SJohn Marino C_MAYBE_CONST_EXPR. */
1038e4b17023SJohn Marino
1039e4b17023SJohn Marino tree
c_fully_fold(tree expr,bool in_init,bool * maybe_const)1040e4b17023SJohn Marino c_fully_fold (tree expr, bool in_init, bool *maybe_const)
1041e4b17023SJohn Marino {
1042e4b17023SJohn Marino tree ret;
1043e4b17023SJohn Marino tree eptype = NULL_TREE;
1044e4b17023SJohn Marino bool dummy = true;
1045e4b17023SJohn Marino bool maybe_const_itself = true;
1046e4b17023SJohn Marino location_t loc = EXPR_LOCATION (expr);
1047e4b17023SJohn Marino
1048e4b17023SJohn Marino /* This function is not relevant to C++ because C++ folds while
1049e4b17023SJohn Marino parsing, and may need changes to be correct for C++ when C++
1050e4b17023SJohn Marino stops folding while parsing. */
1051e4b17023SJohn Marino if (c_dialect_cxx ())
1052e4b17023SJohn Marino gcc_unreachable ();
1053e4b17023SJohn Marino
1054e4b17023SJohn Marino if (!maybe_const)
1055e4b17023SJohn Marino maybe_const = &dummy;
1056e4b17023SJohn Marino if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR)
1057e4b17023SJohn Marino {
1058e4b17023SJohn Marino eptype = TREE_TYPE (expr);
1059e4b17023SJohn Marino expr = TREE_OPERAND (expr, 0);
1060e4b17023SJohn Marino }
1061e4b17023SJohn Marino ret = c_fully_fold_internal (expr, in_init, maybe_const,
1062e4b17023SJohn Marino &maybe_const_itself);
1063e4b17023SJohn Marino if (eptype)
1064e4b17023SJohn Marino ret = fold_convert_loc (loc, eptype, ret);
1065e4b17023SJohn Marino *maybe_const &= maybe_const_itself;
1066e4b17023SJohn Marino return ret;
1067e4b17023SJohn Marino }
1068e4b17023SJohn Marino
1069e4b17023SJohn Marino /* Internal helper for c_fully_fold. EXPR and IN_INIT are as for
1070e4b17023SJohn Marino c_fully_fold. *MAYBE_CONST_OPERANDS is cleared because of operands
1071e4b17023SJohn Marino not permitted, while *MAYBE_CONST_ITSELF is cleared because of
1072e4b17023SJohn Marino arithmetic overflow (for C90, *MAYBE_CONST_OPERANDS is carried from
1073e4b17023SJohn Marino both evaluated and unevaluated subexpressions while
1074e4b17023SJohn Marino *MAYBE_CONST_ITSELF is carried from only evaluated
1075e4b17023SJohn Marino subexpressions). */
1076e4b17023SJohn Marino
1077e4b17023SJohn Marino static tree
c_fully_fold_internal(tree expr,bool in_init,bool * maybe_const_operands,bool * maybe_const_itself)1078e4b17023SJohn Marino c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands,
1079e4b17023SJohn Marino bool *maybe_const_itself)
1080e4b17023SJohn Marino {
1081e4b17023SJohn Marino tree ret = expr;
1082e4b17023SJohn Marino enum tree_code code = TREE_CODE (expr);
1083e4b17023SJohn Marino enum tree_code_class kind = TREE_CODE_CLASS (code);
1084e4b17023SJohn Marino location_t loc = EXPR_LOCATION (expr);
1085e4b17023SJohn Marino tree op0, op1, op2, op3;
1086e4b17023SJohn Marino tree orig_op0, orig_op1, orig_op2;
1087e4b17023SJohn Marino bool op0_const = true, op1_const = true, op2_const = true;
1088e4b17023SJohn Marino bool op0_const_self = true, op1_const_self = true, op2_const_self = true;
1089e4b17023SJohn Marino bool nowarning = TREE_NO_WARNING (expr);
1090e4b17023SJohn Marino bool unused_p;
1091e4b17023SJohn Marino
1092e4b17023SJohn Marino /* This function is not relevant to C++ because C++ folds while
1093e4b17023SJohn Marino parsing, and may need changes to be correct for C++ when C++
1094e4b17023SJohn Marino stops folding while parsing. */
1095e4b17023SJohn Marino if (c_dialect_cxx ())
1096e4b17023SJohn Marino gcc_unreachable ();
1097e4b17023SJohn Marino
1098e4b17023SJohn Marino /* Constants, declarations, statements, errors, SAVE_EXPRs and
1099e4b17023SJohn Marino anything else not counted as an expression cannot usefully be
1100e4b17023SJohn Marino folded further at this point. */
1101e4b17023SJohn Marino if (!IS_EXPR_CODE_CLASS (kind)
1102e4b17023SJohn Marino || kind == tcc_statement
1103e4b17023SJohn Marino || code == SAVE_EXPR)
1104e4b17023SJohn Marino return expr;
1105e4b17023SJohn Marino
1106e4b17023SJohn Marino /* Operands of variable-length expressions (function calls) have
1107e4b17023SJohn Marino already been folded, as have __builtin_* function calls, and such
1108e4b17023SJohn Marino expressions cannot occur in constant expressions. */
1109e4b17023SJohn Marino if (kind == tcc_vl_exp)
1110e4b17023SJohn Marino {
1111e4b17023SJohn Marino *maybe_const_operands = false;
1112e4b17023SJohn Marino ret = fold (expr);
1113e4b17023SJohn Marino goto out;
1114e4b17023SJohn Marino }
1115e4b17023SJohn Marino
1116e4b17023SJohn Marino if (code == C_MAYBE_CONST_EXPR)
1117e4b17023SJohn Marino {
1118e4b17023SJohn Marino tree pre = C_MAYBE_CONST_EXPR_PRE (expr);
1119e4b17023SJohn Marino tree inner = C_MAYBE_CONST_EXPR_EXPR (expr);
1120e4b17023SJohn Marino if (C_MAYBE_CONST_EXPR_NON_CONST (expr))
1121e4b17023SJohn Marino *maybe_const_operands = false;
1122e4b17023SJohn Marino if (C_MAYBE_CONST_EXPR_INT_OPERANDS (expr))
1123e4b17023SJohn Marino *maybe_const_itself = false;
1124e4b17023SJohn Marino if (pre && !in_init)
1125e4b17023SJohn Marino ret = build2 (COMPOUND_EXPR, TREE_TYPE (expr), pre, inner);
1126e4b17023SJohn Marino else
1127e4b17023SJohn Marino ret = inner;
1128e4b17023SJohn Marino goto out;
1129e4b17023SJohn Marino }
1130e4b17023SJohn Marino
1131e4b17023SJohn Marino /* Assignment, increment, decrement, function call and comma
1132e4b17023SJohn Marino operators, and statement expressions, cannot occur in constant
1133e4b17023SJohn Marino expressions if evaluated / outside of sizeof. (Function calls
1134e4b17023SJohn Marino were handled above, though VA_ARG_EXPR is treated like a function
1135e4b17023SJohn Marino call here, and statement expressions are handled through
1136e4b17023SJohn Marino C_MAYBE_CONST_EXPR to avoid folding inside them.) */
1137e4b17023SJohn Marino switch (code)
1138e4b17023SJohn Marino {
1139e4b17023SJohn Marino case MODIFY_EXPR:
1140e4b17023SJohn Marino case PREDECREMENT_EXPR:
1141e4b17023SJohn Marino case PREINCREMENT_EXPR:
1142e4b17023SJohn Marino case POSTDECREMENT_EXPR:
1143e4b17023SJohn Marino case POSTINCREMENT_EXPR:
1144e4b17023SJohn Marino case COMPOUND_EXPR:
1145e4b17023SJohn Marino *maybe_const_operands = false;
1146e4b17023SJohn Marino break;
1147e4b17023SJohn Marino
1148e4b17023SJohn Marino case VA_ARG_EXPR:
1149e4b17023SJohn Marino case TARGET_EXPR:
1150e4b17023SJohn Marino case BIND_EXPR:
1151e4b17023SJohn Marino case OBJ_TYPE_REF:
1152e4b17023SJohn Marino *maybe_const_operands = false;
1153e4b17023SJohn Marino ret = fold (expr);
1154e4b17023SJohn Marino goto out;
1155e4b17023SJohn Marino
1156e4b17023SJohn Marino default:
1157e4b17023SJohn Marino break;
1158e4b17023SJohn Marino }
1159e4b17023SJohn Marino
1160e4b17023SJohn Marino /* Fold individual tree codes as appropriate. */
1161e4b17023SJohn Marino switch (code)
1162e4b17023SJohn Marino {
1163e4b17023SJohn Marino case COMPOUND_LITERAL_EXPR:
1164e4b17023SJohn Marino /* Any non-constancy will have been marked in a containing
1165e4b17023SJohn Marino C_MAYBE_CONST_EXPR; there is no more folding to do here. */
1166e4b17023SJohn Marino goto out;
1167e4b17023SJohn Marino
1168e4b17023SJohn Marino case COMPONENT_REF:
1169e4b17023SJohn Marino orig_op0 = op0 = TREE_OPERAND (expr, 0);
1170e4b17023SJohn Marino op1 = TREE_OPERAND (expr, 1);
1171e4b17023SJohn Marino op2 = TREE_OPERAND (expr, 2);
1172e4b17023SJohn Marino op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
1173e4b17023SJohn Marino maybe_const_itself);
1174e4b17023SJohn Marino STRIP_TYPE_NOPS (op0);
1175e4b17023SJohn Marino if (op0 != orig_op0)
1176e4b17023SJohn Marino ret = build3 (COMPONENT_REF, TREE_TYPE (expr), op0, op1, op2);
1177e4b17023SJohn Marino if (ret != expr)
1178e4b17023SJohn Marino {
1179e4b17023SJohn Marino TREE_READONLY (ret) = TREE_READONLY (expr);
1180e4b17023SJohn Marino TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
1181e4b17023SJohn Marino }
1182e4b17023SJohn Marino goto out;
1183e4b17023SJohn Marino
1184e4b17023SJohn Marino case ARRAY_REF:
1185e4b17023SJohn Marino orig_op0 = op0 = TREE_OPERAND (expr, 0);
1186e4b17023SJohn Marino orig_op1 = op1 = TREE_OPERAND (expr, 1);
1187e4b17023SJohn Marino op2 = TREE_OPERAND (expr, 2);
1188e4b17023SJohn Marino op3 = TREE_OPERAND (expr, 3);
1189e4b17023SJohn Marino op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
1190e4b17023SJohn Marino maybe_const_itself);
1191e4b17023SJohn Marino STRIP_TYPE_NOPS (op0);
1192e4b17023SJohn Marino op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
1193e4b17023SJohn Marino maybe_const_itself);
1194e4b17023SJohn Marino STRIP_TYPE_NOPS (op1);
1195e4b17023SJohn Marino op1 = decl_constant_value_for_optimization (op1);
1196e4b17023SJohn Marino if (op0 != orig_op0 || op1 != orig_op1)
1197e4b17023SJohn Marino ret = build4 (ARRAY_REF, TREE_TYPE (expr), op0, op1, op2, op3);
1198e4b17023SJohn Marino if (ret != expr)
1199e4b17023SJohn Marino {
1200e4b17023SJohn Marino TREE_READONLY (ret) = TREE_READONLY (expr);
1201e4b17023SJohn Marino TREE_SIDE_EFFECTS (ret) = TREE_SIDE_EFFECTS (expr);
1202e4b17023SJohn Marino TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
1203e4b17023SJohn Marino }
1204e4b17023SJohn Marino ret = fold (ret);
1205e4b17023SJohn Marino goto out;
1206e4b17023SJohn Marino
1207e4b17023SJohn Marino case COMPOUND_EXPR:
1208e4b17023SJohn Marino case MODIFY_EXPR:
1209e4b17023SJohn Marino case PREDECREMENT_EXPR:
1210e4b17023SJohn Marino case PREINCREMENT_EXPR:
1211e4b17023SJohn Marino case POSTDECREMENT_EXPR:
1212e4b17023SJohn Marino case POSTINCREMENT_EXPR:
1213e4b17023SJohn Marino case PLUS_EXPR:
1214e4b17023SJohn Marino case MINUS_EXPR:
1215e4b17023SJohn Marino case MULT_EXPR:
1216e4b17023SJohn Marino case POINTER_PLUS_EXPR:
1217e4b17023SJohn Marino case TRUNC_DIV_EXPR:
1218e4b17023SJohn Marino case CEIL_DIV_EXPR:
1219e4b17023SJohn Marino case FLOOR_DIV_EXPR:
1220e4b17023SJohn Marino case TRUNC_MOD_EXPR:
1221e4b17023SJohn Marino case RDIV_EXPR:
1222e4b17023SJohn Marino case EXACT_DIV_EXPR:
1223e4b17023SJohn Marino case LSHIFT_EXPR:
1224e4b17023SJohn Marino case RSHIFT_EXPR:
1225e4b17023SJohn Marino case BIT_IOR_EXPR:
1226e4b17023SJohn Marino case BIT_XOR_EXPR:
1227e4b17023SJohn Marino case BIT_AND_EXPR:
1228e4b17023SJohn Marino case LT_EXPR:
1229e4b17023SJohn Marino case LE_EXPR:
1230e4b17023SJohn Marino case GT_EXPR:
1231e4b17023SJohn Marino case GE_EXPR:
1232e4b17023SJohn Marino case EQ_EXPR:
1233e4b17023SJohn Marino case NE_EXPR:
1234e4b17023SJohn Marino case COMPLEX_EXPR:
1235e4b17023SJohn Marino case TRUTH_AND_EXPR:
1236e4b17023SJohn Marino case TRUTH_OR_EXPR:
1237e4b17023SJohn Marino case TRUTH_XOR_EXPR:
1238e4b17023SJohn Marino case UNORDERED_EXPR:
1239e4b17023SJohn Marino case ORDERED_EXPR:
1240e4b17023SJohn Marino case UNLT_EXPR:
1241e4b17023SJohn Marino case UNLE_EXPR:
1242e4b17023SJohn Marino case UNGT_EXPR:
1243e4b17023SJohn Marino case UNGE_EXPR:
1244e4b17023SJohn Marino case UNEQ_EXPR:
1245e4b17023SJohn Marino /* Binary operations evaluating both arguments (increment and
1246e4b17023SJohn Marino decrement are binary internally in GCC). */
1247e4b17023SJohn Marino orig_op0 = op0 = TREE_OPERAND (expr, 0);
1248e4b17023SJohn Marino orig_op1 = op1 = TREE_OPERAND (expr, 1);
1249e4b17023SJohn Marino op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
1250e4b17023SJohn Marino maybe_const_itself);
1251e4b17023SJohn Marino STRIP_TYPE_NOPS (op0);
1252e4b17023SJohn Marino if (code != MODIFY_EXPR
1253e4b17023SJohn Marino && code != PREDECREMENT_EXPR
1254e4b17023SJohn Marino && code != PREINCREMENT_EXPR
1255e4b17023SJohn Marino && code != POSTDECREMENT_EXPR
1256e4b17023SJohn Marino && code != POSTINCREMENT_EXPR)
1257e4b17023SJohn Marino op0 = decl_constant_value_for_optimization (op0);
1258e4b17023SJohn Marino /* The RHS of a MODIFY_EXPR was fully folded when building that
1259e4b17023SJohn Marino expression for the sake of conversion warnings. */
1260e4b17023SJohn Marino if (code != MODIFY_EXPR)
1261e4b17023SJohn Marino op1 = c_fully_fold_internal (op1, in_init, maybe_const_operands,
1262e4b17023SJohn Marino maybe_const_itself);
1263e4b17023SJohn Marino STRIP_TYPE_NOPS (op1);
1264e4b17023SJohn Marino op1 = decl_constant_value_for_optimization (op1);
1265e4b17023SJohn Marino if (op0 != orig_op0 || op1 != orig_op1 || in_init)
1266e4b17023SJohn Marino ret = in_init
1267e4b17023SJohn Marino ? fold_build2_initializer_loc (loc, code, TREE_TYPE (expr), op0, op1)
1268e4b17023SJohn Marino : fold_build2_loc (loc, code, TREE_TYPE (expr), op0, op1);
1269e4b17023SJohn Marino else
1270e4b17023SJohn Marino ret = fold (expr);
1271e4b17023SJohn Marino if (TREE_OVERFLOW_P (ret)
1272e4b17023SJohn Marino && !TREE_OVERFLOW_P (op0)
1273e4b17023SJohn Marino && !TREE_OVERFLOW_P (op1))
1274e4b17023SJohn Marino overflow_warning (EXPR_LOCATION (expr), ret);
1275e4b17023SJohn Marino goto out;
1276e4b17023SJohn Marino
1277e4b17023SJohn Marino case INDIRECT_REF:
1278e4b17023SJohn Marino case FIX_TRUNC_EXPR:
1279e4b17023SJohn Marino case FLOAT_EXPR:
1280e4b17023SJohn Marino CASE_CONVERT:
1281e4b17023SJohn Marino case VIEW_CONVERT_EXPR:
1282e4b17023SJohn Marino case NON_LVALUE_EXPR:
1283e4b17023SJohn Marino case NEGATE_EXPR:
1284e4b17023SJohn Marino case BIT_NOT_EXPR:
1285e4b17023SJohn Marino case TRUTH_NOT_EXPR:
1286e4b17023SJohn Marino case ADDR_EXPR:
1287e4b17023SJohn Marino case CONJ_EXPR:
1288e4b17023SJohn Marino case REALPART_EXPR:
1289e4b17023SJohn Marino case IMAGPART_EXPR:
1290e4b17023SJohn Marino /* Unary operations. */
1291e4b17023SJohn Marino orig_op0 = op0 = TREE_OPERAND (expr, 0);
1292e4b17023SJohn Marino op0 = c_fully_fold_internal (op0, in_init, maybe_const_operands,
1293e4b17023SJohn Marino maybe_const_itself);
1294e4b17023SJohn Marino STRIP_TYPE_NOPS (op0);
1295e4b17023SJohn Marino if (code != ADDR_EXPR && code != REALPART_EXPR && code != IMAGPART_EXPR)
1296e4b17023SJohn Marino op0 = decl_constant_value_for_optimization (op0);
1297e4b17023SJohn Marino /* ??? Cope with user tricks that amount to offsetof. The middle-end is
1298e4b17023SJohn Marino not prepared to deal with them if they occur in initializers. */
1299e4b17023SJohn Marino if (op0 != orig_op0
1300e4b17023SJohn Marino && code == ADDR_EXPR
1301e4b17023SJohn Marino && (op1 = get_base_address (op0)) != NULL_TREE
1302e4b17023SJohn Marino && TREE_CODE (op1) == INDIRECT_REF
1303e4b17023SJohn Marino && TREE_CONSTANT (TREE_OPERAND (op1, 0)))
1304e4b17023SJohn Marino ret = fold_convert_loc (loc, TREE_TYPE (expr), fold_offsetof_1 (op0));
1305e4b17023SJohn Marino else if (op0 != orig_op0 || in_init)
1306e4b17023SJohn Marino ret = in_init
1307e4b17023SJohn Marino ? fold_build1_initializer_loc (loc, code, TREE_TYPE (expr), op0)
1308e4b17023SJohn Marino : fold_build1_loc (loc, code, TREE_TYPE (expr), op0);
1309e4b17023SJohn Marino else
1310e4b17023SJohn Marino ret = fold (expr);
1311e4b17023SJohn Marino if (code == INDIRECT_REF
1312e4b17023SJohn Marino && ret != expr
1313e4b17023SJohn Marino && TREE_CODE (ret) == INDIRECT_REF)
1314e4b17023SJohn Marino {
1315e4b17023SJohn Marino TREE_READONLY (ret) = TREE_READONLY (expr);
1316e4b17023SJohn Marino TREE_SIDE_EFFECTS (ret) = TREE_SIDE_EFFECTS (expr);
1317e4b17023SJohn Marino TREE_THIS_VOLATILE (ret) = TREE_THIS_VOLATILE (expr);
1318e4b17023SJohn Marino }
1319e4b17023SJohn Marino switch (code)
1320e4b17023SJohn Marino {
1321e4b17023SJohn Marino case FIX_TRUNC_EXPR:
1322e4b17023SJohn Marino case FLOAT_EXPR:
1323e4b17023SJohn Marino CASE_CONVERT:
1324e4b17023SJohn Marino /* Don't warn about explicit conversions. We will already
1325e4b17023SJohn Marino have warned about suspect implicit conversions. */
1326e4b17023SJohn Marino break;
1327e4b17023SJohn Marino
1328e4b17023SJohn Marino default:
1329e4b17023SJohn Marino if (TREE_OVERFLOW_P (ret) && !TREE_OVERFLOW_P (op0))
1330e4b17023SJohn Marino overflow_warning (EXPR_LOCATION (expr), ret);
1331e4b17023SJohn Marino break;
1332e4b17023SJohn Marino }
1333e4b17023SJohn Marino goto out;
1334e4b17023SJohn Marino
1335e4b17023SJohn Marino case TRUTH_ANDIF_EXPR:
1336e4b17023SJohn Marino case TRUTH_ORIF_EXPR:
1337e4b17023SJohn Marino /* Binary operations not necessarily evaluating both
1338e4b17023SJohn Marino arguments. */
1339e4b17023SJohn Marino orig_op0 = op0 = TREE_OPERAND (expr, 0);
1340e4b17023SJohn Marino orig_op1 = op1 = TREE_OPERAND (expr, 1);
1341e4b17023SJohn Marino op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self);
1342e4b17023SJohn Marino STRIP_TYPE_NOPS (op0);
1343e4b17023SJohn Marino
1344e4b17023SJohn Marino unused_p = (op0 == (code == TRUTH_ANDIF_EXPR
1345e4b17023SJohn Marino ? truthvalue_false_node
1346e4b17023SJohn Marino : truthvalue_true_node));
1347e4b17023SJohn Marino c_disable_warnings (unused_p);
1348e4b17023SJohn Marino op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
1349e4b17023SJohn Marino STRIP_TYPE_NOPS (op1);
1350e4b17023SJohn Marino c_enable_warnings (unused_p);
1351e4b17023SJohn Marino
1352e4b17023SJohn Marino if (op0 != orig_op0 || op1 != orig_op1 || in_init)
1353e4b17023SJohn Marino ret = in_init
1354e4b17023SJohn Marino ? fold_build2_initializer_loc (loc, code, TREE_TYPE (expr), op0, op1)
1355e4b17023SJohn Marino : fold_build2_loc (loc, code, TREE_TYPE (expr), op0, op1);
1356e4b17023SJohn Marino else
1357e4b17023SJohn Marino ret = fold (expr);
1358e4b17023SJohn Marino *maybe_const_operands &= op0_const;
1359e4b17023SJohn Marino *maybe_const_itself &= op0_const_self;
1360e4b17023SJohn Marino if (!(flag_isoc99
1361e4b17023SJohn Marino && op0_const
1362e4b17023SJohn Marino && op0_const_self
1363e4b17023SJohn Marino && (code == TRUTH_ANDIF_EXPR
1364e4b17023SJohn Marino ? op0 == truthvalue_false_node
1365e4b17023SJohn Marino : op0 == truthvalue_true_node)))
1366e4b17023SJohn Marino *maybe_const_operands &= op1_const;
1367e4b17023SJohn Marino if (!(op0_const
1368e4b17023SJohn Marino && op0_const_self
1369e4b17023SJohn Marino && (code == TRUTH_ANDIF_EXPR
1370e4b17023SJohn Marino ? op0 == truthvalue_false_node
1371e4b17023SJohn Marino : op0 == truthvalue_true_node)))
1372e4b17023SJohn Marino *maybe_const_itself &= op1_const_self;
1373e4b17023SJohn Marino goto out;
1374e4b17023SJohn Marino
1375e4b17023SJohn Marino case COND_EXPR:
1376e4b17023SJohn Marino orig_op0 = op0 = TREE_OPERAND (expr, 0);
1377e4b17023SJohn Marino orig_op1 = op1 = TREE_OPERAND (expr, 1);
1378e4b17023SJohn Marino orig_op2 = op2 = TREE_OPERAND (expr, 2);
1379e4b17023SJohn Marino op0 = c_fully_fold_internal (op0, in_init, &op0_const, &op0_const_self);
1380e4b17023SJohn Marino
1381e4b17023SJohn Marino STRIP_TYPE_NOPS (op0);
1382e4b17023SJohn Marino c_disable_warnings (op0 == truthvalue_false_node);
1383e4b17023SJohn Marino op1 = c_fully_fold_internal (op1, in_init, &op1_const, &op1_const_self);
1384e4b17023SJohn Marino STRIP_TYPE_NOPS (op1);
1385e4b17023SJohn Marino c_enable_warnings (op0 == truthvalue_false_node);
1386e4b17023SJohn Marino
1387e4b17023SJohn Marino c_disable_warnings (op0 == truthvalue_true_node);
1388e4b17023SJohn Marino op2 = c_fully_fold_internal (op2, in_init, &op2_const, &op2_const_self);
1389e4b17023SJohn Marino STRIP_TYPE_NOPS (op2);
1390e4b17023SJohn Marino c_enable_warnings (op0 == truthvalue_true_node);
1391e4b17023SJohn Marino
1392e4b17023SJohn Marino if (op0 != orig_op0 || op1 != orig_op1 || op2 != orig_op2)
1393e4b17023SJohn Marino ret = fold_build3_loc (loc, code, TREE_TYPE (expr), op0, op1, op2);
1394e4b17023SJohn Marino else
1395e4b17023SJohn Marino ret = fold (expr);
1396e4b17023SJohn Marino *maybe_const_operands &= op0_const;
1397e4b17023SJohn Marino *maybe_const_itself &= op0_const_self;
1398e4b17023SJohn Marino if (!(flag_isoc99
1399e4b17023SJohn Marino && op0_const
1400e4b17023SJohn Marino && op0_const_self
1401e4b17023SJohn Marino && op0 == truthvalue_false_node))
1402e4b17023SJohn Marino *maybe_const_operands &= op1_const;
1403e4b17023SJohn Marino if (!(op0_const
1404e4b17023SJohn Marino && op0_const_self
1405e4b17023SJohn Marino && op0 == truthvalue_false_node))
1406e4b17023SJohn Marino *maybe_const_itself &= op1_const_self;
1407e4b17023SJohn Marino if (!(flag_isoc99
1408e4b17023SJohn Marino && op0_const
1409e4b17023SJohn Marino && op0_const_self
1410e4b17023SJohn Marino && op0 == truthvalue_true_node))
1411e4b17023SJohn Marino *maybe_const_operands &= op2_const;
1412e4b17023SJohn Marino if (!(op0_const
1413e4b17023SJohn Marino && op0_const_self
1414e4b17023SJohn Marino && op0 == truthvalue_true_node))
1415e4b17023SJohn Marino *maybe_const_itself &= op2_const_self;
1416e4b17023SJohn Marino goto out;
1417e4b17023SJohn Marino
1418e4b17023SJohn Marino case EXCESS_PRECISION_EXPR:
1419e4b17023SJohn Marino /* Each case where an operand with excess precision may be
1420e4b17023SJohn Marino encountered must remove the EXCESS_PRECISION_EXPR around
1421e4b17023SJohn Marino inner operands and possibly put one around the whole
1422e4b17023SJohn Marino expression or possibly convert to the semantic type (which
1423e4b17023SJohn Marino c_fully_fold does); we cannot tell at this stage which is
1424e4b17023SJohn Marino appropriate in any particular case. */
1425e4b17023SJohn Marino gcc_unreachable ();
1426e4b17023SJohn Marino
1427e4b17023SJohn Marino default:
1428e4b17023SJohn Marino /* Various codes may appear through folding built-in functions
1429e4b17023SJohn Marino and their arguments. */
1430e4b17023SJohn Marino goto out;
1431e4b17023SJohn Marino }
1432e4b17023SJohn Marino
1433e4b17023SJohn Marino out:
1434e4b17023SJohn Marino /* Some folding may introduce NON_LVALUE_EXPRs; all lvalue checks
1435e4b17023SJohn Marino have been done by this point, so remove them again. */
1436e4b17023SJohn Marino nowarning |= TREE_NO_WARNING (ret);
1437e4b17023SJohn Marino STRIP_TYPE_NOPS (ret);
1438e4b17023SJohn Marino if (nowarning && !TREE_NO_WARNING (ret))
1439e4b17023SJohn Marino {
1440e4b17023SJohn Marino if (!CAN_HAVE_LOCATION_P (ret))
1441e4b17023SJohn Marino ret = build1 (NOP_EXPR, TREE_TYPE (ret), ret);
1442e4b17023SJohn Marino TREE_NO_WARNING (ret) = 1;
1443e4b17023SJohn Marino }
1444e4b17023SJohn Marino if (ret != expr)
1445e4b17023SJohn Marino protected_set_expr_location (ret, loc);
1446e4b17023SJohn Marino return ret;
1447e4b17023SJohn Marino }
1448e4b17023SJohn Marino
1449e4b17023SJohn Marino /* If not optimizing, EXP is not a VAR_DECL, or EXP has array type,
1450e4b17023SJohn Marino return EXP. Otherwise, return either EXP or its known constant
1451e4b17023SJohn Marino value (if it has one), but return EXP if EXP has mode BLKmode. ???
1452e4b17023SJohn Marino Is the BLKmode test appropriate? */
1453e4b17023SJohn Marino
1454e4b17023SJohn Marino tree
decl_constant_value_for_optimization(tree exp)1455e4b17023SJohn Marino decl_constant_value_for_optimization (tree exp)
1456e4b17023SJohn Marino {
1457e4b17023SJohn Marino tree ret;
1458e4b17023SJohn Marino
1459e4b17023SJohn Marino /* This function is only used by C, for c_fully_fold and other
1460e4b17023SJohn Marino optimization, and may not be correct for C++. */
1461e4b17023SJohn Marino if (c_dialect_cxx ())
1462e4b17023SJohn Marino gcc_unreachable ();
1463e4b17023SJohn Marino
1464e4b17023SJohn Marino if (!optimize
1465e4b17023SJohn Marino || TREE_CODE (exp) != VAR_DECL
1466e4b17023SJohn Marino || TREE_CODE (TREE_TYPE (exp)) == ARRAY_TYPE
1467e4b17023SJohn Marino || DECL_MODE (exp) == BLKmode)
1468e4b17023SJohn Marino return exp;
1469e4b17023SJohn Marino
1470e4b17023SJohn Marino ret = decl_constant_value (exp);
1471e4b17023SJohn Marino /* Avoid unwanted tree sharing between the initializer and current
1472e4b17023SJohn Marino function's body where the tree can be modified e.g. by the
1473e4b17023SJohn Marino gimplifier. */
1474e4b17023SJohn Marino if (ret != exp && TREE_STATIC (exp))
1475e4b17023SJohn Marino ret = unshare_expr (ret);
1476e4b17023SJohn Marino return ret;
1477e4b17023SJohn Marino }
1478e4b17023SJohn Marino
1479e4b17023SJohn Marino /* Print a warning if a constant expression had overflow in folding.
1480e4b17023SJohn Marino Invoke this function on every expression that the language
1481e4b17023SJohn Marino requires to be a constant expression.
1482e4b17023SJohn Marino Note the ANSI C standard says it is erroneous for a
1483e4b17023SJohn Marino constant expression to overflow. */
1484e4b17023SJohn Marino
1485e4b17023SJohn Marino void
constant_expression_warning(tree value)1486e4b17023SJohn Marino constant_expression_warning (tree value)
1487e4b17023SJohn Marino {
1488e4b17023SJohn Marino if (warn_overflow && pedantic
1489e4b17023SJohn Marino && (TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST
1490e4b17023SJohn Marino || TREE_CODE (value) == FIXED_CST
1491e4b17023SJohn Marino || TREE_CODE (value) == VECTOR_CST
1492e4b17023SJohn Marino || TREE_CODE (value) == COMPLEX_CST)
1493e4b17023SJohn Marino && TREE_OVERFLOW (value))
1494e4b17023SJohn Marino pedwarn (input_location, OPT_Woverflow, "overflow in constant expression");
1495e4b17023SJohn Marino }
1496e4b17023SJohn Marino
1497e4b17023SJohn Marino /* The same as above but print an unconditional error. */
1498e4b17023SJohn Marino void
constant_expression_error(tree value)1499e4b17023SJohn Marino constant_expression_error (tree value)
1500e4b17023SJohn Marino {
1501e4b17023SJohn Marino if ((TREE_CODE (value) == INTEGER_CST || TREE_CODE (value) == REAL_CST
1502e4b17023SJohn Marino || TREE_CODE (value) == FIXED_CST
1503e4b17023SJohn Marino || TREE_CODE (value) == VECTOR_CST
1504e4b17023SJohn Marino || TREE_CODE (value) == COMPLEX_CST)
1505e4b17023SJohn Marino && TREE_OVERFLOW (value))
1506e4b17023SJohn Marino error ("overflow in constant expression");
1507e4b17023SJohn Marino }
1508e4b17023SJohn Marino
1509e4b17023SJohn Marino /* Print a warning if an expression had overflow in folding and its
1510e4b17023SJohn Marino operands hadn't.
1511e4b17023SJohn Marino
1512e4b17023SJohn Marino Invoke this function on every expression that
1513e4b17023SJohn Marino (1) appears in the source code, and
1514e4b17023SJohn Marino (2) is a constant expression that overflowed, and
1515e4b17023SJohn Marino (3) is not already checked by convert_and_check;
1516e4b17023SJohn Marino however, do not invoke this function on operands of explicit casts
1517e4b17023SJohn Marino or when the expression is the result of an operator and any operand
1518e4b17023SJohn Marino already overflowed. */
1519e4b17023SJohn Marino
1520e4b17023SJohn Marino void
overflow_warning(location_t loc,tree value)1521e4b17023SJohn Marino overflow_warning (location_t loc, tree value)
1522e4b17023SJohn Marino {
1523e4b17023SJohn Marino if (c_inhibit_evaluation_warnings != 0)
1524e4b17023SJohn Marino return;
1525e4b17023SJohn Marino
1526e4b17023SJohn Marino switch (TREE_CODE (value))
1527e4b17023SJohn Marino {
1528e4b17023SJohn Marino case INTEGER_CST:
1529e4b17023SJohn Marino warning_at (loc, OPT_Woverflow, "integer overflow in expression");
1530e4b17023SJohn Marino break;
1531e4b17023SJohn Marino
1532e4b17023SJohn Marino case REAL_CST:
1533e4b17023SJohn Marino warning_at (loc, OPT_Woverflow,
1534e4b17023SJohn Marino "floating point overflow in expression");
1535e4b17023SJohn Marino break;
1536e4b17023SJohn Marino
1537e4b17023SJohn Marino case FIXED_CST:
1538e4b17023SJohn Marino warning_at (loc, OPT_Woverflow, "fixed-point overflow in expression");
1539e4b17023SJohn Marino break;
1540e4b17023SJohn Marino
1541e4b17023SJohn Marino case VECTOR_CST:
1542e4b17023SJohn Marino warning_at (loc, OPT_Woverflow, "vector overflow in expression");
1543e4b17023SJohn Marino break;
1544e4b17023SJohn Marino
1545e4b17023SJohn Marino case COMPLEX_CST:
1546e4b17023SJohn Marino if (TREE_CODE (TREE_REALPART (value)) == INTEGER_CST)
1547e4b17023SJohn Marino warning_at (loc, OPT_Woverflow,
1548e4b17023SJohn Marino "complex integer overflow in expression");
1549e4b17023SJohn Marino else if (TREE_CODE (TREE_REALPART (value)) == REAL_CST)
1550e4b17023SJohn Marino warning_at (loc, OPT_Woverflow,
1551e4b17023SJohn Marino "complex floating point overflow in expression");
1552e4b17023SJohn Marino break;
1553e4b17023SJohn Marino
1554e4b17023SJohn Marino default:
1555e4b17023SJohn Marino break;
1556e4b17023SJohn Marino }
1557e4b17023SJohn Marino }
1558e4b17023SJohn Marino
1559e4b17023SJohn Marino /* Warn about uses of logical || / && operator in a context where it
1560e4b17023SJohn Marino is likely that the bitwise equivalent was intended by the
1561e4b17023SJohn Marino programmer. We have seen an expression in which CODE is a binary
1562e4b17023SJohn Marino operator used to combine expressions OP_LEFT and OP_RIGHT, which before folding
1563e4b17023SJohn Marino had CODE_LEFT and CODE_RIGHT, into an expression of type TYPE. */
1564e4b17023SJohn Marino void
warn_logical_operator(location_t location,enum tree_code code,tree type,enum tree_code code_left,tree op_left,enum tree_code ARG_UNUSED (code_right),tree op_right)1565e4b17023SJohn Marino warn_logical_operator (location_t location, enum tree_code code, tree type,
1566e4b17023SJohn Marino enum tree_code code_left, tree op_left,
1567e4b17023SJohn Marino enum tree_code ARG_UNUSED (code_right), tree op_right)
1568e4b17023SJohn Marino {
1569e4b17023SJohn Marino int or_op = (code == TRUTH_ORIF_EXPR || code == TRUTH_OR_EXPR);
1570e4b17023SJohn Marino int in0_p, in1_p, in_p;
1571e4b17023SJohn Marino tree low0, low1, low, high0, high1, high, lhs, rhs, tem;
1572e4b17023SJohn Marino bool strict_overflow_p = false;
1573e4b17023SJohn Marino
1574e4b17023SJohn Marino if (code != TRUTH_ANDIF_EXPR
1575e4b17023SJohn Marino && code != TRUTH_AND_EXPR
1576e4b17023SJohn Marino && code != TRUTH_ORIF_EXPR
1577e4b17023SJohn Marino && code != TRUTH_OR_EXPR)
1578e4b17023SJohn Marino return;
1579e4b17023SJohn Marino
1580e4b17023SJohn Marino /* Warn if &&/|| are being used in a context where it is
1581e4b17023SJohn Marino likely that the bitwise equivalent was intended by the
1582e4b17023SJohn Marino programmer. That is, an expression such as op && MASK
1583e4b17023SJohn Marino where op should not be any boolean expression, nor a
1584e4b17023SJohn Marino constant, and mask seems to be a non-boolean integer constant. */
1585e4b17023SJohn Marino if (!truth_value_p (code_left)
1586e4b17023SJohn Marino && INTEGRAL_TYPE_P (TREE_TYPE (op_left))
1587e4b17023SJohn Marino && !CONSTANT_CLASS_P (op_left)
1588e4b17023SJohn Marino && !TREE_NO_WARNING (op_left)
1589e4b17023SJohn Marino && TREE_CODE (op_right) == INTEGER_CST
1590e4b17023SJohn Marino && !integer_zerop (op_right)
1591e4b17023SJohn Marino && !integer_onep (op_right))
1592e4b17023SJohn Marino {
1593e4b17023SJohn Marino if (or_op)
1594e4b17023SJohn Marino warning_at (location, OPT_Wlogical_op, "logical %<or%>"
1595e4b17023SJohn Marino " applied to non-boolean constant");
1596e4b17023SJohn Marino else
1597e4b17023SJohn Marino warning_at (location, OPT_Wlogical_op, "logical %<and%>"
1598e4b17023SJohn Marino " applied to non-boolean constant");
1599e4b17023SJohn Marino TREE_NO_WARNING (op_left) = true;
1600e4b17023SJohn Marino return;
1601e4b17023SJohn Marino }
1602e4b17023SJohn Marino
1603e4b17023SJohn Marino /* We do not warn for constants because they are typical of macro
1604e4b17023SJohn Marino expansions that test for features. */
1605e4b17023SJohn Marino if (CONSTANT_CLASS_P (op_left) || CONSTANT_CLASS_P (op_right))
1606e4b17023SJohn Marino return;
1607e4b17023SJohn Marino
1608e4b17023SJohn Marino /* This warning only makes sense with logical operands. */
1609e4b17023SJohn Marino if (!(truth_value_p (TREE_CODE (op_left))
1610e4b17023SJohn Marino || INTEGRAL_TYPE_P (TREE_TYPE (op_left)))
1611e4b17023SJohn Marino || !(truth_value_p (TREE_CODE (op_right))
1612e4b17023SJohn Marino || INTEGRAL_TYPE_P (TREE_TYPE (op_right))))
1613e4b17023SJohn Marino return;
1614e4b17023SJohn Marino
1615e4b17023SJohn Marino lhs = make_range (op_left, &in0_p, &low0, &high0, &strict_overflow_p);
1616e4b17023SJohn Marino rhs = make_range (op_right, &in1_p, &low1, &high1, &strict_overflow_p);
1617e4b17023SJohn Marino
1618e4b17023SJohn Marino if (lhs && TREE_CODE (lhs) == C_MAYBE_CONST_EXPR)
1619e4b17023SJohn Marino lhs = C_MAYBE_CONST_EXPR_EXPR (lhs);
1620e4b17023SJohn Marino
1621e4b17023SJohn Marino if (rhs && TREE_CODE (rhs) == C_MAYBE_CONST_EXPR)
1622e4b17023SJohn Marino rhs = C_MAYBE_CONST_EXPR_EXPR (rhs);
1623e4b17023SJohn Marino
1624e4b17023SJohn Marino /* If this is an OR operation, invert both sides; we will invert
1625e4b17023SJohn Marino again at the end. */
1626e4b17023SJohn Marino if (or_op)
1627e4b17023SJohn Marino in0_p = !in0_p, in1_p = !in1_p;
1628e4b17023SJohn Marino
1629e4b17023SJohn Marino /* If both expressions are the same, if we can merge the ranges, and we
1630e4b17023SJohn Marino can build the range test, return it or it inverted. */
1631e4b17023SJohn Marino if (lhs && rhs && operand_equal_p (lhs, rhs, 0)
1632e4b17023SJohn Marino && merge_ranges (&in_p, &low, &high, in0_p, low0, high0,
1633e4b17023SJohn Marino in1_p, low1, high1)
1634e4b17023SJohn Marino && 0 != (tem = build_range_check (UNKNOWN_LOCATION,
1635e4b17023SJohn Marino type, lhs, in_p, low, high)))
1636e4b17023SJohn Marino {
1637e4b17023SJohn Marino if (TREE_CODE (tem) != INTEGER_CST)
1638e4b17023SJohn Marino return;
1639e4b17023SJohn Marino
1640e4b17023SJohn Marino if (or_op)
1641e4b17023SJohn Marino warning_at (location, OPT_Wlogical_op,
1642e4b17023SJohn Marino "logical %<or%> "
1643e4b17023SJohn Marino "of collectively exhaustive tests is always true");
1644e4b17023SJohn Marino else
1645e4b17023SJohn Marino warning_at (location, OPT_Wlogical_op,
1646e4b17023SJohn Marino "logical %<and%> "
1647e4b17023SJohn Marino "of mutually exclusive tests is always false");
1648e4b17023SJohn Marino }
1649e4b17023SJohn Marino }
1650e4b17023SJohn Marino
1651e4b17023SJohn Marino
1652e4b17023SJohn Marino /* Print a warning about casts that might indicate violation
1653e4b17023SJohn Marino of strict aliasing rules if -Wstrict-aliasing is used and
1654e4b17023SJohn Marino strict aliasing mode is in effect. OTYPE is the original
1655e4b17023SJohn Marino TREE_TYPE of EXPR, and TYPE the type we're casting to. */
1656e4b17023SJohn Marino
1657e4b17023SJohn Marino bool
strict_aliasing_warning(tree otype,tree type,tree expr)1658e4b17023SJohn Marino strict_aliasing_warning (tree otype, tree type, tree expr)
1659e4b17023SJohn Marino {
1660e4b17023SJohn Marino /* Strip pointer conversion chains and get to the correct original type. */
1661e4b17023SJohn Marino STRIP_NOPS (expr);
1662e4b17023SJohn Marino otype = TREE_TYPE (expr);
1663e4b17023SJohn Marino
1664e4b17023SJohn Marino if (!(flag_strict_aliasing
1665e4b17023SJohn Marino && POINTER_TYPE_P (type)
1666e4b17023SJohn Marino && POINTER_TYPE_P (otype)
1667e4b17023SJohn Marino && !VOID_TYPE_P (TREE_TYPE (type)))
1668e4b17023SJohn Marino /* If the type we are casting to is a ref-all pointer
1669e4b17023SJohn Marino dereferencing it is always valid. */
1670e4b17023SJohn Marino || TYPE_REF_CAN_ALIAS_ALL (type))
1671e4b17023SJohn Marino return false;
1672e4b17023SJohn Marino
1673e4b17023SJohn Marino if ((warn_strict_aliasing > 1) && TREE_CODE (expr) == ADDR_EXPR
1674e4b17023SJohn Marino && (DECL_P (TREE_OPERAND (expr, 0))
1675e4b17023SJohn Marino || handled_component_p (TREE_OPERAND (expr, 0))))
1676e4b17023SJohn Marino {
1677e4b17023SJohn Marino /* Casting the address of an object to non void pointer. Warn
1678e4b17023SJohn Marino if the cast breaks type based aliasing. */
1679e4b17023SJohn Marino if (!COMPLETE_TYPE_P (TREE_TYPE (type)) && warn_strict_aliasing == 2)
1680e4b17023SJohn Marino {
1681e4b17023SJohn Marino warning (OPT_Wstrict_aliasing, "type-punning to incomplete type "
1682e4b17023SJohn Marino "might break strict-aliasing rules");
1683e4b17023SJohn Marino return true;
1684e4b17023SJohn Marino }
1685e4b17023SJohn Marino else
1686e4b17023SJohn Marino {
1687e4b17023SJohn Marino /* warn_strict_aliasing >= 3. This includes the default (3).
1688e4b17023SJohn Marino Only warn if the cast is dereferenced immediately. */
1689e4b17023SJohn Marino alias_set_type set1 =
1690e4b17023SJohn Marino get_alias_set (TREE_TYPE (TREE_OPERAND (expr, 0)));
1691e4b17023SJohn Marino alias_set_type set2 = get_alias_set (TREE_TYPE (type));
1692e4b17023SJohn Marino
1693e4b17023SJohn Marino if (set1 != set2 && set2 != 0
1694e4b17023SJohn Marino && (set1 == 0 || !alias_sets_conflict_p (set1, set2)))
1695e4b17023SJohn Marino {
1696e4b17023SJohn Marino warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
1697e4b17023SJohn Marino "pointer will break strict-aliasing rules");
1698e4b17023SJohn Marino return true;
1699e4b17023SJohn Marino }
1700e4b17023SJohn Marino else if (warn_strict_aliasing == 2
1701e4b17023SJohn Marino && !alias_sets_must_conflict_p (set1, set2))
1702e4b17023SJohn Marino {
1703e4b17023SJohn Marino warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
1704e4b17023SJohn Marino "pointer might break strict-aliasing rules");
1705e4b17023SJohn Marino return true;
1706e4b17023SJohn Marino }
1707e4b17023SJohn Marino }
1708e4b17023SJohn Marino }
1709e4b17023SJohn Marino else
1710e4b17023SJohn Marino if ((warn_strict_aliasing == 1) && !VOID_TYPE_P (TREE_TYPE (otype)))
1711e4b17023SJohn Marino {
1712e4b17023SJohn Marino /* At this level, warn for any conversions, even if an address is
1713e4b17023SJohn Marino not taken in the same statement. This will likely produce many
1714e4b17023SJohn Marino false positives, but could be useful to pinpoint problems that
1715e4b17023SJohn Marino are not revealed at higher levels. */
1716e4b17023SJohn Marino alias_set_type set1 = get_alias_set (TREE_TYPE (otype));
1717e4b17023SJohn Marino alias_set_type set2 = get_alias_set (TREE_TYPE (type));
1718e4b17023SJohn Marino if (!COMPLETE_TYPE_P (type)
1719e4b17023SJohn Marino || !alias_sets_must_conflict_p (set1, set2))
1720e4b17023SJohn Marino {
1721e4b17023SJohn Marino warning (OPT_Wstrict_aliasing, "dereferencing type-punned "
1722e4b17023SJohn Marino "pointer might break strict-aliasing rules");
1723e4b17023SJohn Marino return true;
1724e4b17023SJohn Marino }
1725e4b17023SJohn Marino }
1726e4b17023SJohn Marino
1727e4b17023SJohn Marino return false;
1728e4b17023SJohn Marino }
1729e4b17023SJohn Marino
1730e4b17023SJohn Marino /* Warn for unlikely, improbable, or stupid DECL declarations
1731e4b17023SJohn Marino of `main'. */
1732e4b17023SJohn Marino
1733e4b17023SJohn Marino void
check_main_parameter_types(tree decl)1734e4b17023SJohn Marino check_main_parameter_types (tree decl)
1735e4b17023SJohn Marino {
1736e4b17023SJohn Marino function_args_iterator iter;
1737e4b17023SJohn Marino tree type;
1738e4b17023SJohn Marino int argct = 0;
1739e4b17023SJohn Marino
1740e4b17023SJohn Marino FOREACH_FUNCTION_ARGS (TREE_TYPE (decl), type, iter)
1741e4b17023SJohn Marino {
1742e4b17023SJohn Marino /* XXX void_type_node belies the abstraction. */
1743e4b17023SJohn Marino if (type == void_type_node || type == error_mark_node )
1744e4b17023SJohn Marino break;
1745e4b17023SJohn Marino
1746e4b17023SJohn Marino ++argct;
1747e4b17023SJohn Marino switch (argct)
1748e4b17023SJohn Marino {
1749e4b17023SJohn Marino case 1:
1750e4b17023SJohn Marino if (TYPE_MAIN_VARIANT (type) != integer_type_node)
1751e4b17023SJohn Marino pedwarn (input_location, OPT_Wmain,
1752e4b17023SJohn Marino "first argument of %q+D should be %<int%>", decl);
1753e4b17023SJohn Marino break;
1754e4b17023SJohn Marino
1755e4b17023SJohn Marino case 2:
1756e4b17023SJohn Marino if (TREE_CODE (type) != POINTER_TYPE
1757e4b17023SJohn Marino || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
1758e4b17023SJohn Marino || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
1759e4b17023SJohn Marino != char_type_node))
1760e4b17023SJohn Marino pedwarn (input_location, OPT_Wmain,
1761e4b17023SJohn Marino "second argument of %q+D should be %<char **%>", decl);
1762e4b17023SJohn Marino break;
1763e4b17023SJohn Marino
1764e4b17023SJohn Marino case 3:
1765e4b17023SJohn Marino if (TREE_CODE (type) != POINTER_TYPE
1766e4b17023SJohn Marino || TREE_CODE (TREE_TYPE (type)) != POINTER_TYPE
1767e4b17023SJohn Marino || (TYPE_MAIN_VARIANT (TREE_TYPE (TREE_TYPE (type)))
1768e4b17023SJohn Marino != char_type_node))
1769e4b17023SJohn Marino pedwarn (input_location, OPT_Wmain,
1770e4b17023SJohn Marino "third argument of %q+D should probably be "
1771e4b17023SJohn Marino "%<char **%>", decl);
1772e4b17023SJohn Marino break;
1773e4b17023SJohn Marino }
1774e4b17023SJohn Marino }
1775e4b17023SJohn Marino
1776e4b17023SJohn Marino /* It is intentional that this message does not mention the third
1777e4b17023SJohn Marino argument because it's only mentioned in an appendix of the
1778e4b17023SJohn Marino standard. */
1779e4b17023SJohn Marino if (argct > 0 && (argct < 2 || argct > 3))
1780e4b17023SJohn Marino pedwarn (input_location, OPT_Wmain,
1781e4b17023SJohn Marino "%q+D takes only zero or two arguments", decl);
1782e4b17023SJohn Marino }
1783e4b17023SJohn Marino
1784e4b17023SJohn Marino /* True if pointers to distinct types T1 and T2 can be converted to
1785e4b17023SJohn Marino each other without an explicit cast. Only returns true for opaque
1786e4b17023SJohn Marino vector types. */
1787e4b17023SJohn Marino bool
vector_targets_convertible_p(const_tree t1,const_tree t2)1788e4b17023SJohn Marino vector_targets_convertible_p (const_tree t1, const_tree t2)
1789e4b17023SJohn Marino {
1790e4b17023SJohn Marino if (TREE_CODE (t1) == VECTOR_TYPE && TREE_CODE (t2) == VECTOR_TYPE
1791e4b17023SJohn Marino && (TYPE_VECTOR_OPAQUE (t1) || TYPE_VECTOR_OPAQUE (t2))
1792e4b17023SJohn Marino && tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2)))
1793e4b17023SJohn Marino return true;
1794e4b17023SJohn Marino
1795e4b17023SJohn Marino return false;
1796e4b17023SJohn Marino }
1797e4b17023SJohn Marino
1798e4b17023SJohn Marino /* True if vector types T1 and T2 can be converted to each other
1799e4b17023SJohn Marino without an explicit cast. If EMIT_LAX_NOTE is true, and T1 and T2
1800e4b17023SJohn Marino can only be converted with -flax-vector-conversions yet that is not
1801e4b17023SJohn Marino in effect, emit a note telling the user about that option if such
1802e4b17023SJohn Marino a note has not previously been emitted. */
1803e4b17023SJohn Marino bool
vector_types_convertible_p(const_tree t1,const_tree t2,bool emit_lax_note)1804e4b17023SJohn Marino vector_types_convertible_p (const_tree t1, const_tree t2, bool emit_lax_note)
1805e4b17023SJohn Marino {
1806e4b17023SJohn Marino static bool emitted_lax_note = false;
1807e4b17023SJohn Marino bool convertible_lax;
1808e4b17023SJohn Marino
1809e4b17023SJohn Marino if ((TYPE_VECTOR_OPAQUE (t1) || TYPE_VECTOR_OPAQUE (t2))
1810e4b17023SJohn Marino && tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2)))
1811e4b17023SJohn Marino return true;
1812e4b17023SJohn Marino
1813e4b17023SJohn Marino convertible_lax =
1814e4b17023SJohn Marino (tree_int_cst_equal (TYPE_SIZE (t1), TYPE_SIZE (t2))
1815e4b17023SJohn Marino && (TREE_CODE (TREE_TYPE (t1)) != REAL_TYPE ||
1816e4b17023SJohn Marino TYPE_PRECISION (t1) == TYPE_PRECISION (t2))
1817e4b17023SJohn Marino && (INTEGRAL_TYPE_P (TREE_TYPE (t1))
1818e4b17023SJohn Marino == INTEGRAL_TYPE_P (TREE_TYPE (t2))));
1819e4b17023SJohn Marino
1820e4b17023SJohn Marino if (!convertible_lax || flag_lax_vector_conversions)
1821e4b17023SJohn Marino return convertible_lax;
1822e4b17023SJohn Marino
1823e4b17023SJohn Marino if (TYPE_VECTOR_SUBPARTS (t1) == TYPE_VECTOR_SUBPARTS (t2)
1824e4b17023SJohn Marino && lang_hooks.types_compatible_p (TREE_TYPE (t1), TREE_TYPE (t2)))
1825e4b17023SJohn Marino return true;
1826e4b17023SJohn Marino
1827e4b17023SJohn Marino if (emit_lax_note && !emitted_lax_note)
1828e4b17023SJohn Marino {
1829e4b17023SJohn Marino emitted_lax_note = true;
1830e4b17023SJohn Marino inform (input_location, "use -flax-vector-conversions to permit "
1831e4b17023SJohn Marino "conversions between vectors with differing "
1832e4b17023SJohn Marino "element types or numbers of subparts");
1833e4b17023SJohn Marino }
1834e4b17023SJohn Marino
1835e4b17023SJohn Marino return false;
1836e4b17023SJohn Marino }
1837e4b17023SJohn Marino
1838e4b17023SJohn Marino /* Like tree.c:get_narrower, but retain conversion from C++0x scoped enum
1839e4b17023SJohn Marino to integral type. */
1840e4b17023SJohn Marino
1841e4b17023SJohn Marino static tree
c_common_get_narrower(tree op,int * unsignedp_ptr)1842e4b17023SJohn Marino c_common_get_narrower (tree op, int *unsignedp_ptr)
1843e4b17023SJohn Marino {
1844e4b17023SJohn Marino op = get_narrower (op, unsignedp_ptr);
1845e4b17023SJohn Marino
1846e4b17023SJohn Marino if (TREE_CODE (TREE_TYPE (op)) == ENUMERAL_TYPE
1847e4b17023SJohn Marino && ENUM_IS_SCOPED (TREE_TYPE (op)))
1848e4b17023SJohn Marino {
1849e4b17023SJohn Marino /* C++0x scoped enumerations don't implicitly convert to integral
1850e4b17023SJohn Marino type; if we stripped an explicit conversion to a larger type we
1851e4b17023SJohn Marino need to replace it so common_type will still work. */
1852e4b17023SJohn Marino tree type = (lang_hooks.types.type_for_size
1853e4b17023SJohn Marino (TYPE_PRECISION (TREE_TYPE (op)),
1854e4b17023SJohn Marino TYPE_UNSIGNED (TREE_TYPE (op))));
1855e4b17023SJohn Marino op = fold_convert (type, op);
1856e4b17023SJohn Marino }
1857e4b17023SJohn Marino return op;
1858e4b17023SJohn Marino }
1859e4b17023SJohn Marino
1860e4b17023SJohn Marino /* This is a helper function of build_binary_op.
1861e4b17023SJohn Marino
1862e4b17023SJohn Marino For certain operations if both args were extended from the same
1863e4b17023SJohn Marino smaller type, do the arithmetic in that type and then extend.
1864e4b17023SJohn Marino
1865e4b17023SJohn Marino BITWISE indicates a bitwise operation.
1866e4b17023SJohn Marino For them, this optimization is safe only if
1867e4b17023SJohn Marino both args are zero-extended or both are sign-extended.
1868e4b17023SJohn Marino Otherwise, we might change the result.
1869e4b17023SJohn Marino Eg, (short)-1 | (unsigned short)-1 is (int)-1
1870e4b17023SJohn Marino but calculated in (unsigned short) it would be (unsigned short)-1.
1871e4b17023SJohn Marino */
1872e4b17023SJohn Marino tree
shorten_binary_op(tree result_type,tree op0,tree op1,bool bitwise)1873e4b17023SJohn Marino shorten_binary_op (tree result_type, tree op0, tree op1, bool bitwise)
1874e4b17023SJohn Marino {
1875e4b17023SJohn Marino int unsigned0, unsigned1;
1876e4b17023SJohn Marino tree arg0, arg1;
1877e4b17023SJohn Marino int uns;
1878e4b17023SJohn Marino tree type;
1879e4b17023SJohn Marino
1880e4b17023SJohn Marino /* Cast OP0 and OP1 to RESULT_TYPE. Doing so prevents
1881e4b17023SJohn Marino excessive narrowing when we call get_narrower below. For
1882e4b17023SJohn Marino example, suppose that OP0 is of unsigned int extended
1883e4b17023SJohn Marino from signed char and that RESULT_TYPE is long long int.
1884e4b17023SJohn Marino If we explicitly cast OP0 to RESULT_TYPE, OP0 would look
1885e4b17023SJohn Marino like
1886e4b17023SJohn Marino
1887e4b17023SJohn Marino (long long int) (unsigned int) signed_char
1888e4b17023SJohn Marino
1889e4b17023SJohn Marino which get_narrower would narrow down to
1890e4b17023SJohn Marino
1891e4b17023SJohn Marino (unsigned int) signed char
1892e4b17023SJohn Marino
1893e4b17023SJohn Marino If we do not cast OP0 first, get_narrower would return
1894e4b17023SJohn Marino signed_char, which is inconsistent with the case of the
1895e4b17023SJohn Marino explicit cast. */
1896e4b17023SJohn Marino op0 = convert (result_type, op0);
1897e4b17023SJohn Marino op1 = convert (result_type, op1);
1898e4b17023SJohn Marino
1899e4b17023SJohn Marino arg0 = c_common_get_narrower (op0, &unsigned0);
1900e4b17023SJohn Marino arg1 = c_common_get_narrower (op1, &unsigned1);
1901e4b17023SJohn Marino
1902e4b17023SJohn Marino /* UNS is 1 if the operation to be done is an unsigned one. */
1903e4b17023SJohn Marino uns = TYPE_UNSIGNED (result_type);
1904e4b17023SJohn Marino
1905e4b17023SJohn Marino /* Handle the case that OP0 (or OP1) does not *contain* a conversion
1906e4b17023SJohn Marino but it *requires* conversion to FINAL_TYPE. */
1907e4b17023SJohn Marino
1908e4b17023SJohn Marino if ((TYPE_PRECISION (TREE_TYPE (op0))
1909e4b17023SJohn Marino == TYPE_PRECISION (TREE_TYPE (arg0)))
1910e4b17023SJohn Marino && TREE_TYPE (op0) != result_type)
1911e4b17023SJohn Marino unsigned0 = TYPE_UNSIGNED (TREE_TYPE (op0));
1912e4b17023SJohn Marino if ((TYPE_PRECISION (TREE_TYPE (op1))
1913e4b17023SJohn Marino == TYPE_PRECISION (TREE_TYPE (arg1)))
1914e4b17023SJohn Marino && TREE_TYPE (op1) != result_type)
1915e4b17023SJohn Marino unsigned1 = TYPE_UNSIGNED (TREE_TYPE (op1));
1916e4b17023SJohn Marino
1917e4b17023SJohn Marino /* Now UNSIGNED0 is 1 if ARG0 zero-extends to FINAL_TYPE. */
1918e4b17023SJohn Marino
1919e4b17023SJohn Marino /* For bitwise operations, signedness of nominal type
1920e4b17023SJohn Marino does not matter. Consider only how operands were extended. */
1921e4b17023SJohn Marino if (bitwise)
1922e4b17023SJohn Marino uns = unsigned0;
1923e4b17023SJohn Marino
1924e4b17023SJohn Marino /* Note that in all three cases below we refrain from optimizing
1925e4b17023SJohn Marino an unsigned operation on sign-extended args.
1926e4b17023SJohn Marino That would not be valid. */
1927e4b17023SJohn Marino
1928e4b17023SJohn Marino /* Both args variable: if both extended in same way
1929e4b17023SJohn Marino from same width, do it in that width.
1930e4b17023SJohn Marino Do it unsigned if args were zero-extended. */
1931e4b17023SJohn Marino if ((TYPE_PRECISION (TREE_TYPE (arg0))
1932e4b17023SJohn Marino < TYPE_PRECISION (result_type))
1933e4b17023SJohn Marino && (TYPE_PRECISION (TREE_TYPE (arg1))
1934e4b17023SJohn Marino == TYPE_PRECISION (TREE_TYPE (arg0)))
1935e4b17023SJohn Marino && unsigned0 == unsigned1
1936e4b17023SJohn Marino && (unsigned0 || !uns))
1937e4b17023SJohn Marino return c_common_signed_or_unsigned_type
1938e4b17023SJohn Marino (unsigned0, common_type (TREE_TYPE (arg0), TREE_TYPE (arg1)));
1939e4b17023SJohn Marino
1940e4b17023SJohn Marino else if (TREE_CODE (arg0) == INTEGER_CST
1941e4b17023SJohn Marino && (unsigned1 || !uns)
1942e4b17023SJohn Marino && (TYPE_PRECISION (TREE_TYPE (arg1))
1943e4b17023SJohn Marino < TYPE_PRECISION (result_type))
1944e4b17023SJohn Marino && (type
1945e4b17023SJohn Marino = c_common_signed_or_unsigned_type (unsigned1,
1946e4b17023SJohn Marino TREE_TYPE (arg1)))
1947e4b17023SJohn Marino && !POINTER_TYPE_P (type)
1948e4b17023SJohn Marino && int_fits_type_p (arg0, type))
1949e4b17023SJohn Marino return type;
1950e4b17023SJohn Marino
1951e4b17023SJohn Marino else if (TREE_CODE (arg1) == INTEGER_CST
1952e4b17023SJohn Marino && (unsigned0 || !uns)
1953e4b17023SJohn Marino && (TYPE_PRECISION (TREE_TYPE (arg0))
1954e4b17023SJohn Marino < TYPE_PRECISION (result_type))
1955e4b17023SJohn Marino && (type
1956e4b17023SJohn Marino = c_common_signed_or_unsigned_type (unsigned0,
1957e4b17023SJohn Marino TREE_TYPE (arg0)))
1958e4b17023SJohn Marino && !POINTER_TYPE_P (type)
1959e4b17023SJohn Marino && int_fits_type_p (arg1, type))
1960e4b17023SJohn Marino return type;
1961e4b17023SJohn Marino
1962e4b17023SJohn Marino return result_type;
1963e4b17023SJohn Marino }
1964e4b17023SJohn Marino
1965e4b17023SJohn Marino /* Checks if expression EXPR of real/integer type cannot be converted
1966e4b17023SJohn Marino to the real/integer type TYPE. Function returns true when:
1967e4b17023SJohn Marino * EXPR is a constant which cannot be exactly converted to TYPE
1968e4b17023SJohn Marino * EXPR is not a constant and size of EXPR's type > than size of TYPE,
1969e4b17023SJohn Marino for EXPR type and TYPE being both integers or both real.
1970e4b17023SJohn Marino * EXPR is not a constant of real type and TYPE is an integer.
1971e4b17023SJohn Marino * EXPR is not a constant of integer type which cannot be
1972e4b17023SJohn Marino exactly converted to real type.
1973e4b17023SJohn Marino Function allows conversions between types of different signedness and
1974e4b17023SJohn Marino does not return true in that case. Function can produce signedness
1975e4b17023SJohn Marino warnings if PRODUCE_WARNS is true. */
1976e4b17023SJohn Marino bool
unsafe_conversion_p(tree type,tree expr,bool produce_warns)1977e4b17023SJohn Marino unsafe_conversion_p (tree type, tree expr, bool produce_warns)
1978e4b17023SJohn Marino {
1979e4b17023SJohn Marino bool give_warning = false;
1980e4b17023SJohn Marino tree expr_type = TREE_TYPE (expr);
1981e4b17023SJohn Marino location_t loc = EXPR_LOC_OR_HERE (expr);
1982e4b17023SJohn Marino
1983e4b17023SJohn Marino if (TREE_CODE (expr) == REAL_CST || TREE_CODE (expr) == INTEGER_CST)
1984e4b17023SJohn Marino {
1985e4b17023SJohn Marino /* Warn for real constant that is not an exact integer converted
1986e4b17023SJohn Marino to integer type. */
1987e4b17023SJohn Marino if (TREE_CODE (expr_type) == REAL_TYPE
1988e4b17023SJohn Marino && TREE_CODE (type) == INTEGER_TYPE)
1989e4b17023SJohn Marino {
1990e4b17023SJohn Marino if (!real_isinteger (TREE_REAL_CST_PTR (expr), TYPE_MODE (expr_type)))
1991e4b17023SJohn Marino give_warning = true;
1992e4b17023SJohn Marino }
1993e4b17023SJohn Marino /* Warn for an integer constant that does not fit into integer type. */
1994e4b17023SJohn Marino else if (TREE_CODE (expr_type) == INTEGER_TYPE
1995e4b17023SJohn Marino && TREE_CODE (type) == INTEGER_TYPE
1996e4b17023SJohn Marino && !int_fits_type_p (expr, type))
1997e4b17023SJohn Marino {
1998e4b17023SJohn Marino if (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type)
1999e4b17023SJohn Marino && tree_int_cst_sgn (expr) < 0)
2000e4b17023SJohn Marino {
2001e4b17023SJohn Marino if (produce_warns)
2002e4b17023SJohn Marino warning_at (loc, OPT_Wsign_conversion, "negative integer"
2003e4b17023SJohn Marino " implicitly converted to unsigned type");
2004e4b17023SJohn Marino }
2005e4b17023SJohn Marino else if (!TYPE_UNSIGNED (type) && TYPE_UNSIGNED (expr_type))
2006e4b17023SJohn Marino {
2007e4b17023SJohn Marino if (produce_warns)
2008e4b17023SJohn Marino warning_at (loc, OPT_Wsign_conversion, "conversion of unsigned"
2009e4b17023SJohn Marino " constant value to negative integer");
2010e4b17023SJohn Marino }
2011e4b17023SJohn Marino else
2012e4b17023SJohn Marino give_warning = true;
2013e4b17023SJohn Marino }
2014e4b17023SJohn Marino else if (TREE_CODE (type) == REAL_TYPE)
2015e4b17023SJohn Marino {
2016e4b17023SJohn Marino /* Warn for an integer constant that does not fit into real type. */
2017e4b17023SJohn Marino if (TREE_CODE (expr_type) == INTEGER_TYPE)
2018e4b17023SJohn Marino {
2019e4b17023SJohn Marino REAL_VALUE_TYPE a = real_value_from_int_cst (0, expr);
2020e4b17023SJohn Marino if (!exact_real_truncate (TYPE_MODE (type), &a))
2021e4b17023SJohn Marino give_warning = true;
2022e4b17023SJohn Marino }
2023e4b17023SJohn Marino /* Warn for a real constant that does not fit into a smaller
2024e4b17023SJohn Marino real type. */
2025e4b17023SJohn Marino else if (TREE_CODE (expr_type) == REAL_TYPE
2026e4b17023SJohn Marino && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
2027e4b17023SJohn Marino {
2028e4b17023SJohn Marino REAL_VALUE_TYPE a = TREE_REAL_CST (expr);
2029e4b17023SJohn Marino if (!exact_real_truncate (TYPE_MODE (type), &a))
2030e4b17023SJohn Marino give_warning = true;
2031e4b17023SJohn Marino }
2032e4b17023SJohn Marino }
2033e4b17023SJohn Marino }
2034e4b17023SJohn Marino else
2035e4b17023SJohn Marino {
2036e4b17023SJohn Marino /* Warn for real types converted to integer types. */
2037e4b17023SJohn Marino if (TREE_CODE (expr_type) == REAL_TYPE
2038e4b17023SJohn Marino && TREE_CODE (type) == INTEGER_TYPE)
2039e4b17023SJohn Marino give_warning = true;
2040e4b17023SJohn Marino
2041e4b17023SJohn Marino else if (TREE_CODE (expr_type) == INTEGER_TYPE
2042e4b17023SJohn Marino && TREE_CODE (type) == INTEGER_TYPE)
2043e4b17023SJohn Marino {
2044e4b17023SJohn Marino /* Don't warn about unsigned char y = 0xff, x = (int) y; */
2045e4b17023SJohn Marino expr = get_unwidened (expr, 0);
2046e4b17023SJohn Marino expr_type = TREE_TYPE (expr);
2047e4b17023SJohn Marino
2048e4b17023SJohn Marino /* Don't warn for short y; short x = ((int)y & 0xff); */
2049e4b17023SJohn Marino if (TREE_CODE (expr) == BIT_AND_EXPR
2050e4b17023SJohn Marino || TREE_CODE (expr) == BIT_IOR_EXPR
2051e4b17023SJohn Marino || TREE_CODE (expr) == BIT_XOR_EXPR)
2052e4b17023SJohn Marino {
2053e4b17023SJohn Marino /* If both args were extended from a shortest type,
2054e4b17023SJohn Marino use that type if that is safe. */
2055e4b17023SJohn Marino expr_type = shorten_binary_op (expr_type,
2056e4b17023SJohn Marino TREE_OPERAND (expr, 0),
2057e4b17023SJohn Marino TREE_OPERAND (expr, 1),
2058e4b17023SJohn Marino /* bitwise */1);
2059e4b17023SJohn Marino
2060e4b17023SJohn Marino if (TREE_CODE (expr) == BIT_AND_EXPR)
2061e4b17023SJohn Marino {
2062e4b17023SJohn Marino tree op0 = TREE_OPERAND (expr, 0);
2063e4b17023SJohn Marino tree op1 = TREE_OPERAND (expr, 1);
2064e4b17023SJohn Marino bool unsigned0 = TYPE_UNSIGNED (TREE_TYPE (op0));
2065e4b17023SJohn Marino bool unsigned1 = TYPE_UNSIGNED (TREE_TYPE (op1));
2066e4b17023SJohn Marino
2067e4b17023SJohn Marino /* If one of the operands is a non-negative constant
2068e4b17023SJohn Marino that fits in the target type, then the type of the
2069e4b17023SJohn Marino other operand does not matter. */
2070e4b17023SJohn Marino if ((TREE_CODE (op0) == INTEGER_CST
2071e4b17023SJohn Marino && int_fits_type_p (op0, c_common_signed_type (type))
2072e4b17023SJohn Marino && int_fits_type_p (op0, c_common_unsigned_type (type)))
2073e4b17023SJohn Marino || (TREE_CODE (op1) == INTEGER_CST
2074e4b17023SJohn Marino && int_fits_type_p (op1, c_common_signed_type (type))
2075e4b17023SJohn Marino && int_fits_type_p (op1,
2076e4b17023SJohn Marino c_common_unsigned_type (type))))
2077e4b17023SJohn Marino return false;
2078e4b17023SJohn Marino /* If constant is unsigned and fits in the target
2079e4b17023SJohn Marino type, then the result will also fit. */
2080e4b17023SJohn Marino else if ((TREE_CODE (op0) == INTEGER_CST
2081e4b17023SJohn Marino && unsigned0
2082e4b17023SJohn Marino && int_fits_type_p (op0, type))
2083e4b17023SJohn Marino || (TREE_CODE (op1) == INTEGER_CST
2084e4b17023SJohn Marino && unsigned1
2085e4b17023SJohn Marino && int_fits_type_p (op1, type)))
2086e4b17023SJohn Marino return false;
2087e4b17023SJohn Marino }
2088e4b17023SJohn Marino }
2089e4b17023SJohn Marino /* Warn for integer types converted to smaller integer types. */
2090e4b17023SJohn Marino if (TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
2091e4b17023SJohn Marino give_warning = true;
2092e4b17023SJohn Marino
2093e4b17023SJohn Marino /* When they are the same width but different signedness,
2094e4b17023SJohn Marino then the value may change. */
2095e4b17023SJohn Marino else if (((TYPE_PRECISION (type) == TYPE_PRECISION (expr_type)
2096e4b17023SJohn Marino && TYPE_UNSIGNED (expr_type) != TYPE_UNSIGNED (type))
2097e4b17023SJohn Marino /* Even when converted to a bigger type, if the type is
2098e4b17023SJohn Marino unsigned but expr is signed, then negative values
2099e4b17023SJohn Marino will be changed. */
2100e4b17023SJohn Marino || (TYPE_UNSIGNED (type) && !TYPE_UNSIGNED (expr_type)))
2101e4b17023SJohn Marino && produce_warns)
2102e4b17023SJohn Marino warning_at (loc, OPT_Wsign_conversion, "conversion to %qT from %qT "
2103e4b17023SJohn Marino "may change the sign of the result",
2104e4b17023SJohn Marino type, expr_type);
2105e4b17023SJohn Marino }
2106e4b17023SJohn Marino
2107e4b17023SJohn Marino /* Warn for integer types converted to real types if and only if
2108e4b17023SJohn Marino all the range of values of the integer type cannot be
2109e4b17023SJohn Marino represented by the real type. */
2110e4b17023SJohn Marino else if (TREE_CODE (expr_type) == INTEGER_TYPE
2111e4b17023SJohn Marino && TREE_CODE (type) == REAL_TYPE)
2112e4b17023SJohn Marino {
2113e4b17023SJohn Marino tree type_low_bound, type_high_bound;
2114e4b17023SJohn Marino REAL_VALUE_TYPE real_low_bound, real_high_bound;
2115e4b17023SJohn Marino
2116e4b17023SJohn Marino /* Don't warn about char y = 0xff; float x = (int) y; */
2117e4b17023SJohn Marino expr = get_unwidened (expr, 0);
2118e4b17023SJohn Marino expr_type = TREE_TYPE (expr);
2119e4b17023SJohn Marino
2120e4b17023SJohn Marino type_low_bound = TYPE_MIN_VALUE (expr_type);
2121e4b17023SJohn Marino type_high_bound = TYPE_MAX_VALUE (expr_type);
2122e4b17023SJohn Marino real_low_bound = real_value_from_int_cst (0, type_low_bound);
2123e4b17023SJohn Marino real_high_bound = real_value_from_int_cst (0, type_high_bound);
2124e4b17023SJohn Marino
2125e4b17023SJohn Marino if (!exact_real_truncate (TYPE_MODE (type), &real_low_bound)
2126e4b17023SJohn Marino || !exact_real_truncate (TYPE_MODE (type), &real_high_bound))
2127e4b17023SJohn Marino give_warning = true;
2128e4b17023SJohn Marino }
2129e4b17023SJohn Marino
2130e4b17023SJohn Marino /* Warn for real types converted to smaller real types. */
2131e4b17023SJohn Marino else if (TREE_CODE (expr_type) == REAL_TYPE
2132e4b17023SJohn Marino && TREE_CODE (type) == REAL_TYPE
2133e4b17023SJohn Marino && TYPE_PRECISION (type) < TYPE_PRECISION (expr_type))
2134e4b17023SJohn Marino give_warning = true;
2135e4b17023SJohn Marino }
2136e4b17023SJohn Marino
2137e4b17023SJohn Marino return give_warning;
2138e4b17023SJohn Marino }
2139e4b17023SJohn Marino
2140e4b17023SJohn Marino /* Warns if the conversion of EXPR to TYPE may alter a value.
2141e4b17023SJohn Marino This is a helper function for warnings_for_convert_and_check. */
2142e4b17023SJohn Marino
2143e4b17023SJohn Marino static void
conversion_warning(tree type,tree expr)2144e4b17023SJohn Marino conversion_warning (tree type, tree expr)
2145e4b17023SJohn Marino {
2146e4b17023SJohn Marino tree expr_type = TREE_TYPE (expr);
2147e4b17023SJohn Marino location_t loc = EXPR_LOC_OR_HERE (expr);
2148e4b17023SJohn Marino
2149e4b17023SJohn Marino if (!warn_conversion && !warn_sign_conversion)
2150e4b17023SJohn Marino return;
2151e4b17023SJohn Marino
2152e4b17023SJohn Marino switch (TREE_CODE (expr))
2153e4b17023SJohn Marino {
2154e4b17023SJohn Marino case EQ_EXPR:
2155e4b17023SJohn Marino case NE_EXPR:
2156e4b17023SJohn Marino case LE_EXPR:
2157e4b17023SJohn Marino case GE_EXPR:
2158e4b17023SJohn Marino case LT_EXPR:
2159e4b17023SJohn Marino case GT_EXPR:
2160e4b17023SJohn Marino case TRUTH_ANDIF_EXPR:
2161e4b17023SJohn Marino case TRUTH_ORIF_EXPR:
2162e4b17023SJohn Marino case TRUTH_AND_EXPR:
2163e4b17023SJohn Marino case TRUTH_OR_EXPR:
2164e4b17023SJohn Marino case TRUTH_XOR_EXPR:
2165e4b17023SJohn Marino case TRUTH_NOT_EXPR:
2166e4b17023SJohn Marino /* Conversion from boolean to a signed:1 bit-field (which only
2167e4b17023SJohn Marino can hold the values 0 and -1) doesn't lose information - but
2168e4b17023SJohn Marino it does change the value. */
2169e4b17023SJohn Marino if (TYPE_PRECISION (type) == 1 && !TYPE_UNSIGNED (type))
2170e4b17023SJohn Marino warning_at (loc, OPT_Wconversion,
2171e4b17023SJohn Marino "conversion to %qT from boolean expression", type);
2172e4b17023SJohn Marino return;
2173e4b17023SJohn Marino
2174e4b17023SJohn Marino case REAL_CST:
2175e4b17023SJohn Marino case INTEGER_CST:
2176e4b17023SJohn Marino if (unsafe_conversion_p (type, expr, true))
2177e4b17023SJohn Marino warning_at (loc, OPT_Wconversion,
2178e4b17023SJohn Marino "conversion to %qT alters %qT constant value",
2179e4b17023SJohn Marino type, expr_type);
2180e4b17023SJohn Marino return;
2181e4b17023SJohn Marino
2182e4b17023SJohn Marino case COND_EXPR:
2183e4b17023SJohn Marino {
2184e4b17023SJohn Marino /* In case of COND_EXPR, if both operands are constants or
2185e4b17023SJohn Marino COND_EXPR, then we do not care about the type of COND_EXPR,
2186e4b17023SJohn Marino only about the conversion of each operand. */
2187e4b17023SJohn Marino tree op1 = TREE_OPERAND (expr, 1);
2188e4b17023SJohn Marino tree op2 = TREE_OPERAND (expr, 2);
2189e4b17023SJohn Marino
2190e4b17023SJohn Marino if ((TREE_CODE (op1) == REAL_CST || TREE_CODE (op1) == INTEGER_CST
2191e4b17023SJohn Marino || TREE_CODE (op1) == COND_EXPR)
2192e4b17023SJohn Marino && (TREE_CODE (op2) == REAL_CST || TREE_CODE (op2) == INTEGER_CST
2193e4b17023SJohn Marino || TREE_CODE (op2) == COND_EXPR))
2194e4b17023SJohn Marino {
2195e4b17023SJohn Marino conversion_warning (type, op1);
2196e4b17023SJohn Marino conversion_warning (type, op2);
2197e4b17023SJohn Marino return;
2198e4b17023SJohn Marino }
2199e4b17023SJohn Marino /* Fall through. */
2200e4b17023SJohn Marino }
2201e4b17023SJohn Marino
2202e4b17023SJohn Marino default: /* 'expr' is not a constant. */
2203e4b17023SJohn Marino if (unsafe_conversion_p (type, expr, true))
2204e4b17023SJohn Marino warning_at (loc, OPT_Wconversion,
2205e4b17023SJohn Marino "conversion to %qT from %qT may alter its value",
2206e4b17023SJohn Marino type, expr_type);
2207e4b17023SJohn Marino }
2208e4b17023SJohn Marino }
2209e4b17023SJohn Marino
2210e4b17023SJohn Marino /* Produce warnings after a conversion. RESULT is the result of
2211e4b17023SJohn Marino converting EXPR to TYPE. This is a helper function for
2212e4b17023SJohn Marino convert_and_check and cp_convert_and_check. */
2213e4b17023SJohn Marino
2214e4b17023SJohn Marino void
warnings_for_convert_and_check(tree type,tree expr,tree result)2215e4b17023SJohn Marino warnings_for_convert_and_check (tree type, tree expr, tree result)
2216e4b17023SJohn Marino {
2217e4b17023SJohn Marino if (TREE_CODE (expr) == INTEGER_CST
2218e4b17023SJohn Marino && (TREE_CODE (type) == INTEGER_TYPE
2219e4b17023SJohn Marino || TREE_CODE (type) == ENUMERAL_TYPE)
2220e4b17023SJohn Marino && !int_fits_type_p (expr, type))
2221e4b17023SJohn Marino {
2222e4b17023SJohn Marino /* Do not diagnose overflow in a constant expression merely
2223e4b17023SJohn Marino because a conversion overflowed. */
2224e4b17023SJohn Marino if (TREE_OVERFLOW (result))
2225e4b17023SJohn Marino TREE_OVERFLOW (result) = TREE_OVERFLOW (expr);
2226e4b17023SJohn Marino
2227e4b17023SJohn Marino if (TYPE_UNSIGNED (type))
2228e4b17023SJohn Marino {
2229e4b17023SJohn Marino /* This detects cases like converting -129 or 256 to
2230e4b17023SJohn Marino unsigned char. */
2231e4b17023SJohn Marino if (!int_fits_type_p (expr, c_common_signed_type (type)))
2232e4b17023SJohn Marino warning (OPT_Woverflow,
2233e4b17023SJohn Marino "large integer implicitly truncated to unsigned type");
2234e4b17023SJohn Marino else
2235e4b17023SJohn Marino conversion_warning (type, expr);
2236e4b17023SJohn Marino }
2237e4b17023SJohn Marino else if (!int_fits_type_p (expr, c_common_unsigned_type (type)))
2238e4b17023SJohn Marino warning (OPT_Woverflow,
2239e4b17023SJohn Marino "overflow in implicit constant conversion");
2240e4b17023SJohn Marino /* No warning for converting 0x80000000 to int. */
2241e4b17023SJohn Marino else if (pedantic
2242e4b17023SJohn Marino && (TREE_CODE (TREE_TYPE (expr)) != INTEGER_TYPE
2243e4b17023SJohn Marino || TYPE_PRECISION (TREE_TYPE (expr))
2244e4b17023SJohn Marino != TYPE_PRECISION (type)))
2245e4b17023SJohn Marino warning (OPT_Woverflow,
2246e4b17023SJohn Marino "overflow in implicit constant conversion");
2247e4b17023SJohn Marino
2248e4b17023SJohn Marino else
2249e4b17023SJohn Marino conversion_warning (type, expr);
2250e4b17023SJohn Marino }
2251e4b17023SJohn Marino else if ((TREE_CODE (result) == INTEGER_CST
2252e4b17023SJohn Marino || TREE_CODE (result) == FIXED_CST) && TREE_OVERFLOW (result))
2253e4b17023SJohn Marino warning (OPT_Woverflow,
2254e4b17023SJohn Marino "overflow in implicit constant conversion");
2255e4b17023SJohn Marino else
2256e4b17023SJohn Marino conversion_warning (type, expr);
2257e4b17023SJohn Marino }
2258e4b17023SJohn Marino
2259e4b17023SJohn Marino
2260e4b17023SJohn Marino /* Convert EXPR to TYPE, warning about conversion problems with constants.
2261e4b17023SJohn Marino Invoke this function on every expression that is converted implicitly,
2262e4b17023SJohn Marino i.e. because of language rules and not because of an explicit cast. */
2263e4b17023SJohn Marino
2264e4b17023SJohn Marino tree
convert_and_check(tree type,tree expr)2265e4b17023SJohn Marino convert_and_check (tree type, tree expr)
2266e4b17023SJohn Marino {
2267e4b17023SJohn Marino tree result;
2268e4b17023SJohn Marino tree expr_for_warning;
2269e4b17023SJohn Marino
2270e4b17023SJohn Marino /* Convert from a value with possible excess precision rather than
2271e4b17023SJohn Marino via the semantic type, but do not warn about values not fitting
2272e4b17023SJohn Marino exactly in the semantic type. */
2273e4b17023SJohn Marino if (TREE_CODE (expr) == EXCESS_PRECISION_EXPR)
2274e4b17023SJohn Marino {
2275e4b17023SJohn Marino tree orig_type = TREE_TYPE (expr);
2276e4b17023SJohn Marino expr = TREE_OPERAND (expr, 0);
2277e4b17023SJohn Marino expr_for_warning = convert (orig_type, expr);
2278e4b17023SJohn Marino if (orig_type == type)
2279e4b17023SJohn Marino return expr_for_warning;
2280e4b17023SJohn Marino }
2281e4b17023SJohn Marino else
2282e4b17023SJohn Marino expr_for_warning = expr;
2283e4b17023SJohn Marino
2284e4b17023SJohn Marino if (TREE_TYPE (expr) == type)
2285e4b17023SJohn Marino return expr;
2286e4b17023SJohn Marino
2287e4b17023SJohn Marino result = convert (type, expr);
2288e4b17023SJohn Marino
2289e4b17023SJohn Marino if (c_inhibit_evaluation_warnings == 0
2290e4b17023SJohn Marino && !TREE_OVERFLOW_P (expr)
2291e4b17023SJohn Marino && result != error_mark_node)
2292e4b17023SJohn Marino warnings_for_convert_and_check (type, expr_for_warning, result);
2293e4b17023SJohn Marino
2294e4b17023SJohn Marino return result;
2295e4b17023SJohn Marino }
2296e4b17023SJohn Marino
2297e4b17023SJohn Marino /* A node in a list that describes references to variables (EXPR), which are
2298e4b17023SJohn Marino either read accesses if WRITER is zero, or write accesses, in which case
2299e4b17023SJohn Marino WRITER is the parent of EXPR. */
2300e4b17023SJohn Marino struct tlist
2301e4b17023SJohn Marino {
2302e4b17023SJohn Marino struct tlist *next;
2303e4b17023SJohn Marino tree expr, writer;
2304e4b17023SJohn Marino };
2305e4b17023SJohn Marino
2306e4b17023SJohn Marino /* Used to implement a cache the results of a call to verify_tree. We only
2307e4b17023SJohn Marino use this for SAVE_EXPRs. */
2308e4b17023SJohn Marino struct tlist_cache
2309e4b17023SJohn Marino {
2310e4b17023SJohn Marino struct tlist_cache *next;
2311e4b17023SJohn Marino struct tlist *cache_before_sp;
2312e4b17023SJohn Marino struct tlist *cache_after_sp;
2313e4b17023SJohn Marino tree expr;
2314e4b17023SJohn Marino };
2315e4b17023SJohn Marino
2316e4b17023SJohn Marino /* Obstack to use when allocating tlist structures, and corresponding
2317e4b17023SJohn Marino firstobj. */
2318e4b17023SJohn Marino static struct obstack tlist_obstack;
2319e4b17023SJohn Marino static char *tlist_firstobj = 0;
2320e4b17023SJohn Marino
2321e4b17023SJohn Marino /* Keep track of the identifiers we've warned about, so we can avoid duplicate
2322e4b17023SJohn Marino warnings. */
2323e4b17023SJohn Marino static struct tlist *warned_ids;
2324e4b17023SJohn Marino /* SAVE_EXPRs need special treatment. We process them only once and then
2325e4b17023SJohn Marino cache the results. */
2326e4b17023SJohn Marino static struct tlist_cache *save_expr_cache;
2327e4b17023SJohn Marino
2328e4b17023SJohn Marino static void add_tlist (struct tlist **, struct tlist *, tree, int);
2329e4b17023SJohn Marino static void merge_tlist (struct tlist **, struct tlist *, int);
2330e4b17023SJohn Marino static void verify_tree (tree, struct tlist **, struct tlist **, tree);
2331e4b17023SJohn Marino static int warning_candidate_p (tree);
2332e4b17023SJohn Marino static bool candidate_equal_p (const_tree, const_tree);
2333e4b17023SJohn Marino static void warn_for_collisions (struct tlist *);
2334e4b17023SJohn Marino static void warn_for_collisions_1 (tree, tree, struct tlist *, int);
2335e4b17023SJohn Marino static struct tlist *new_tlist (struct tlist *, tree, tree);
2336e4b17023SJohn Marino
2337e4b17023SJohn Marino /* Create a new struct tlist and fill in its fields. */
2338e4b17023SJohn Marino static struct tlist *
new_tlist(struct tlist * next,tree t,tree writer)2339e4b17023SJohn Marino new_tlist (struct tlist *next, tree t, tree writer)
2340e4b17023SJohn Marino {
2341e4b17023SJohn Marino struct tlist *l;
2342e4b17023SJohn Marino l = XOBNEW (&tlist_obstack, struct tlist);
2343e4b17023SJohn Marino l->next = next;
2344e4b17023SJohn Marino l->expr = t;
2345e4b17023SJohn Marino l->writer = writer;
2346e4b17023SJohn Marino return l;
2347e4b17023SJohn Marino }
2348e4b17023SJohn Marino
2349e4b17023SJohn Marino /* Add duplicates of the nodes found in ADD to the list *TO. If EXCLUDE_WRITER
2350e4b17023SJohn Marino is nonnull, we ignore any node we find which has a writer equal to it. */
2351e4b17023SJohn Marino
2352e4b17023SJohn Marino static void
add_tlist(struct tlist ** to,struct tlist * add,tree exclude_writer,int copy)2353e4b17023SJohn Marino add_tlist (struct tlist **to, struct tlist *add, tree exclude_writer, int copy)
2354e4b17023SJohn Marino {
2355e4b17023SJohn Marino while (add)
2356e4b17023SJohn Marino {
2357e4b17023SJohn Marino struct tlist *next = add->next;
2358e4b17023SJohn Marino if (!copy)
2359e4b17023SJohn Marino add->next = *to;
2360e4b17023SJohn Marino if (!exclude_writer || !candidate_equal_p (add->writer, exclude_writer))
2361e4b17023SJohn Marino *to = copy ? new_tlist (*to, add->expr, add->writer) : add;
2362e4b17023SJohn Marino add = next;
2363e4b17023SJohn Marino }
2364e4b17023SJohn Marino }
2365e4b17023SJohn Marino
2366e4b17023SJohn Marino /* Merge the nodes of ADD into TO. This merging process is done so that for
2367e4b17023SJohn Marino each variable that already exists in TO, no new node is added; however if
2368e4b17023SJohn Marino there is a write access recorded in ADD, and an occurrence on TO is only
2369e4b17023SJohn Marino a read access, then the occurrence in TO will be modified to record the
2370e4b17023SJohn Marino write. */
2371e4b17023SJohn Marino
2372e4b17023SJohn Marino static void
merge_tlist(struct tlist ** to,struct tlist * add,int copy)2373e4b17023SJohn Marino merge_tlist (struct tlist **to, struct tlist *add, int copy)
2374e4b17023SJohn Marino {
2375e4b17023SJohn Marino struct tlist **end = to;
2376e4b17023SJohn Marino
2377e4b17023SJohn Marino while (*end)
2378e4b17023SJohn Marino end = &(*end)->next;
2379e4b17023SJohn Marino
2380e4b17023SJohn Marino while (add)
2381e4b17023SJohn Marino {
2382e4b17023SJohn Marino int found = 0;
2383e4b17023SJohn Marino struct tlist *tmp2;
2384e4b17023SJohn Marino struct tlist *next = add->next;
2385e4b17023SJohn Marino
2386e4b17023SJohn Marino for (tmp2 = *to; tmp2; tmp2 = tmp2->next)
2387e4b17023SJohn Marino if (candidate_equal_p (tmp2->expr, add->expr))
2388e4b17023SJohn Marino {
2389e4b17023SJohn Marino found = 1;
2390e4b17023SJohn Marino if (!tmp2->writer)
2391e4b17023SJohn Marino tmp2->writer = add->writer;
2392e4b17023SJohn Marino }
2393e4b17023SJohn Marino if (!found)
2394e4b17023SJohn Marino {
2395e4b17023SJohn Marino *end = copy ? add : new_tlist (NULL, add->expr, add->writer);
2396e4b17023SJohn Marino end = &(*end)->next;
2397e4b17023SJohn Marino *end = 0;
2398e4b17023SJohn Marino }
2399e4b17023SJohn Marino add = next;
2400e4b17023SJohn Marino }
2401e4b17023SJohn Marino }
2402e4b17023SJohn Marino
2403e4b17023SJohn Marino /* WRITTEN is a variable, WRITER is its parent. Warn if any of the variable
2404e4b17023SJohn Marino references in list LIST conflict with it, excluding reads if ONLY writers
2405e4b17023SJohn Marino is nonzero. */
2406e4b17023SJohn Marino
2407e4b17023SJohn Marino static void
warn_for_collisions_1(tree written,tree writer,struct tlist * list,int only_writes)2408e4b17023SJohn Marino warn_for_collisions_1 (tree written, tree writer, struct tlist *list,
2409e4b17023SJohn Marino int only_writes)
2410e4b17023SJohn Marino {
2411e4b17023SJohn Marino struct tlist *tmp;
2412e4b17023SJohn Marino
2413e4b17023SJohn Marino /* Avoid duplicate warnings. */
2414e4b17023SJohn Marino for (tmp = warned_ids; tmp; tmp = tmp->next)
2415e4b17023SJohn Marino if (candidate_equal_p (tmp->expr, written))
2416e4b17023SJohn Marino return;
2417e4b17023SJohn Marino
2418e4b17023SJohn Marino while (list)
2419e4b17023SJohn Marino {
2420e4b17023SJohn Marino if (candidate_equal_p (list->expr, written)
2421e4b17023SJohn Marino && !candidate_equal_p (list->writer, writer)
2422e4b17023SJohn Marino && (!only_writes || list->writer))
2423e4b17023SJohn Marino {
2424e4b17023SJohn Marino warned_ids = new_tlist (warned_ids, written, NULL_TREE);
2425e4b17023SJohn Marino warning_at (EXPR_LOC_OR_HERE (writer),
2426e4b17023SJohn Marino OPT_Wsequence_point, "operation on %qE may be undefined",
2427e4b17023SJohn Marino list->expr);
2428e4b17023SJohn Marino }
2429e4b17023SJohn Marino list = list->next;
2430e4b17023SJohn Marino }
2431e4b17023SJohn Marino }
2432e4b17023SJohn Marino
2433e4b17023SJohn Marino /* Given a list LIST of references to variables, find whether any of these
2434e4b17023SJohn Marino can cause conflicts due to missing sequence points. */
2435e4b17023SJohn Marino
2436e4b17023SJohn Marino static void
warn_for_collisions(struct tlist * list)2437e4b17023SJohn Marino warn_for_collisions (struct tlist *list)
2438e4b17023SJohn Marino {
2439e4b17023SJohn Marino struct tlist *tmp;
2440e4b17023SJohn Marino
2441e4b17023SJohn Marino for (tmp = list; tmp; tmp = tmp->next)
2442e4b17023SJohn Marino {
2443e4b17023SJohn Marino if (tmp->writer)
2444e4b17023SJohn Marino warn_for_collisions_1 (tmp->expr, tmp->writer, list, 0);
2445e4b17023SJohn Marino }
2446e4b17023SJohn Marino }
2447e4b17023SJohn Marino
2448e4b17023SJohn Marino /* Return nonzero if X is a tree that can be verified by the sequence point
2449e4b17023SJohn Marino warnings. */
2450e4b17023SJohn Marino static int
warning_candidate_p(tree x)2451e4b17023SJohn Marino warning_candidate_p (tree x)
2452e4b17023SJohn Marino {
2453e4b17023SJohn Marino if (DECL_P (x) && DECL_ARTIFICIAL (x))
2454e4b17023SJohn Marino return 0;
2455e4b17023SJohn Marino
2456e4b17023SJohn Marino if (TREE_CODE (x) == BLOCK)
2457e4b17023SJohn Marino return 0;
2458e4b17023SJohn Marino
2459e4b17023SJohn Marino /* VOID_TYPE_P (TREE_TYPE (x)) is workaround for cp/tree.c
2460e4b17023SJohn Marino (lvalue_p) crash on TRY/CATCH. */
2461e4b17023SJohn Marino if (TREE_TYPE (x) == NULL_TREE || VOID_TYPE_P (TREE_TYPE (x)))
2462e4b17023SJohn Marino return 0;
2463e4b17023SJohn Marino
2464e4b17023SJohn Marino if (!lvalue_p (x))
2465e4b17023SJohn Marino return 0;
2466e4b17023SJohn Marino
2467e4b17023SJohn Marino /* No point to track non-const calls, they will never satisfy
2468e4b17023SJohn Marino operand_equal_p. */
2469e4b17023SJohn Marino if (TREE_CODE (x) == CALL_EXPR && (call_expr_flags (x) & ECF_CONST) == 0)
2470e4b17023SJohn Marino return 0;
2471e4b17023SJohn Marino
2472e4b17023SJohn Marino if (TREE_CODE (x) == STRING_CST)
2473e4b17023SJohn Marino return 0;
2474e4b17023SJohn Marino
2475e4b17023SJohn Marino return 1;
2476e4b17023SJohn Marino }
2477e4b17023SJohn Marino
2478e4b17023SJohn Marino /* Return nonzero if X and Y appear to be the same candidate (or NULL) */
2479e4b17023SJohn Marino static bool
candidate_equal_p(const_tree x,const_tree y)2480e4b17023SJohn Marino candidate_equal_p (const_tree x, const_tree y)
2481e4b17023SJohn Marino {
2482e4b17023SJohn Marino return (x == y) || (x && y && operand_equal_p (x, y, 0));
2483e4b17023SJohn Marino }
2484e4b17023SJohn Marino
2485e4b17023SJohn Marino /* Walk the tree X, and record accesses to variables. If X is written by the
2486e4b17023SJohn Marino parent tree, WRITER is the parent.
2487e4b17023SJohn Marino We store accesses in one of the two lists: PBEFORE_SP, and PNO_SP. If this
2488e4b17023SJohn Marino expression or its only operand forces a sequence point, then everything up
2489e4b17023SJohn Marino to the sequence point is stored in PBEFORE_SP. Everything else gets stored
2490e4b17023SJohn Marino in PNO_SP.
2491e4b17023SJohn Marino Once we return, we will have emitted warnings if any subexpression before
2492e4b17023SJohn Marino such a sequence point could be undefined. On a higher level, however, the
2493e4b17023SJohn Marino sequence point may not be relevant, and we'll merge the two lists.
2494e4b17023SJohn Marino
2495e4b17023SJohn Marino Example: (b++, a) + b;
2496e4b17023SJohn Marino The call that processes the COMPOUND_EXPR will store the increment of B
2497e4b17023SJohn Marino in PBEFORE_SP, and the use of A in PNO_SP. The higher-level call that
2498e4b17023SJohn Marino processes the PLUS_EXPR will need to merge the two lists so that
2499e4b17023SJohn Marino eventually, all accesses end up on the same list (and we'll warn about the
2500e4b17023SJohn Marino unordered subexpressions b++ and b.
2501e4b17023SJohn Marino
2502e4b17023SJohn Marino A note on merging. If we modify the former example so that our expression
2503e4b17023SJohn Marino becomes
2504e4b17023SJohn Marino (b++, b) + a
2505e4b17023SJohn Marino care must be taken not simply to add all three expressions into the final
2506e4b17023SJohn Marino PNO_SP list. The function merge_tlist takes care of that by merging the
2507e4b17023SJohn Marino before-SP list of the COMPOUND_EXPR into its after-SP list in a special
2508e4b17023SJohn Marino way, so that no more than one access to B is recorded. */
2509e4b17023SJohn Marino
2510e4b17023SJohn Marino static void
verify_tree(tree x,struct tlist ** pbefore_sp,struct tlist ** pno_sp,tree writer)2511e4b17023SJohn Marino verify_tree (tree x, struct tlist **pbefore_sp, struct tlist **pno_sp,
2512e4b17023SJohn Marino tree writer)
2513e4b17023SJohn Marino {
2514e4b17023SJohn Marino struct tlist *tmp_before, *tmp_nosp, *tmp_list2, *tmp_list3;
2515e4b17023SJohn Marino enum tree_code code;
2516e4b17023SJohn Marino enum tree_code_class cl;
2517e4b17023SJohn Marino
2518e4b17023SJohn Marino /* X may be NULL if it is the operand of an empty statement expression
2519e4b17023SJohn Marino ({ }). */
2520e4b17023SJohn Marino if (x == NULL)
2521e4b17023SJohn Marino return;
2522e4b17023SJohn Marino
2523e4b17023SJohn Marino restart:
2524e4b17023SJohn Marino code = TREE_CODE (x);
2525e4b17023SJohn Marino cl = TREE_CODE_CLASS (code);
2526e4b17023SJohn Marino
2527e4b17023SJohn Marino if (warning_candidate_p (x))
2528e4b17023SJohn Marino *pno_sp = new_tlist (*pno_sp, x, writer);
2529e4b17023SJohn Marino
2530e4b17023SJohn Marino switch (code)
2531e4b17023SJohn Marino {
2532e4b17023SJohn Marino case CONSTRUCTOR:
2533e4b17023SJohn Marino return;
2534e4b17023SJohn Marino
2535e4b17023SJohn Marino case COMPOUND_EXPR:
2536e4b17023SJohn Marino case TRUTH_ANDIF_EXPR:
2537e4b17023SJohn Marino case TRUTH_ORIF_EXPR:
2538e4b17023SJohn Marino tmp_before = tmp_nosp = tmp_list3 = 0;
2539e4b17023SJohn Marino verify_tree (TREE_OPERAND (x, 0), &tmp_before, &tmp_nosp, NULL_TREE);
2540e4b17023SJohn Marino warn_for_collisions (tmp_nosp);
2541e4b17023SJohn Marino merge_tlist (pbefore_sp, tmp_before, 0);
2542e4b17023SJohn Marino merge_tlist (pbefore_sp, tmp_nosp, 0);
2543e4b17023SJohn Marino verify_tree (TREE_OPERAND (x, 1), &tmp_list3, pno_sp, NULL_TREE);
2544e4b17023SJohn Marino merge_tlist (pbefore_sp, tmp_list3, 0);
2545e4b17023SJohn Marino return;
2546e4b17023SJohn Marino
2547e4b17023SJohn Marino case COND_EXPR:
2548e4b17023SJohn Marino tmp_before = tmp_list2 = 0;
2549e4b17023SJohn Marino verify_tree (TREE_OPERAND (x, 0), &tmp_before, &tmp_list2, NULL_TREE);
2550e4b17023SJohn Marino warn_for_collisions (tmp_list2);
2551e4b17023SJohn Marino merge_tlist (pbefore_sp, tmp_before, 0);
2552e4b17023SJohn Marino merge_tlist (pbefore_sp, tmp_list2, 1);
2553e4b17023SJohn Marino
2554e4b17023SJohn Marino tmp_list3 = tmp_nosp = 0;
2555e4b17023SJohn Marino verify_tree (TREE_OPERAND (x, 1), &tmp_list3, &tmp_nosp, NULL_TREE);
2556e4b17023SJohn Marino warn_for_collisions (tmp_nosp);
2557e4b17023SJohn Marino merge_tlist (pbefore_sp, tmp_list3, 0);
2558e4b17023SJohn Marino
2559e4b17023SJohn Marino tmp_list3 = tmp_list2 = 0;
2560e4b17023SJohn Marino verify_tree (TREE_OPERAND (x, 2), &tmp_list3, &tmp_list2, NULL_TREE);
2561e4b17023SJohn Marino warn_for_collisions (tmp_list2);
2562e4b17023SJohn Marino merge_tlist (pbefore_sp, tmp_list3, 0);
2563e4b17023SJohn Marino /* Rather than add both tmp_nosp and tmp_list2, we have to merge the
2564e4b17023SJohn Marino two first, to avoid warning for (a ? b++ : b++). */
2565e4b17023SJohn Marino merge_tlist (&tmp_nosp, tmp_list2, 0);
2566e4b17023SJohn Marino add_tlist (pno_sp, tmp_nosp, NULL_TREE, 0);
2567e4b17023SJohn Marino return;
2568e4b17023SJohn Marino
2569e4b17023SJohn Marino case PREDECREMENT_EXPR:
2570e4b17023SJohn Marino case PREINCREMENT_EXPR:
2571e4b17023SJohn Marino case POSTDECREMENT_EXPR:
2572e4b17023SJohn Marino case POSTINCREMENT_EXPR:
2573e4b17023SJohn Marino verify_tree (TREE_OPERAND (x, 0), pno_sp, pno_sp, x);
2574e4b17023SJohn Marino return;
2575e4b17023SJohn Marino
2576e4b17023SJohn Marino case MODIFY_EXPR:
2577e4b17023SJohn Marino tmp_before = tmp_nosp = tmp_list3 = 0;
2578e4b17023SJohn Marino verify_tree (TREE_OPERAND (x, 1), &tmp_before, &tmp_nosp, NULL_TREE);
2579e4b17023SJohn Marino verify_tree (TREE_OPERAND (x, 0), &tmp_list3, &tmp_list3, x);
2580e4b17023SJohn Marino /* Expressions inside the LHS are not ordered wrt. the sequence points
2581e4b17023SJohn Marino in the RHS. Example:
2582e4b17023SJohn Marino *a = (a++, 2)
2583e4b17023SJohn Marino Despite the fact that the modification of "a" is in the before_sp
2584e4b17023SJohn Marino list (tmp_before), it conflicts with the use of "a" in the LHS.
2585e4b17023SJohn Marino We can handle this by adding the contents of tmp_list3
2586e4b17023SJohn Marino to those of tmp_before, and redoing the collision warnings for that
2587e4b17023SJohn Marino list. */
2588e4b17023SJohn Marino add_tlist (&tmp_before, tmp_list3, x, 1);
2589e4b17023SJohn Marino warn_for_collisions (tmp_before);
2590e4b17023SJohn Marino /* Exclude the LHS itself here; we first have to merge it into the
2591e4b17023SJohn Marino tmp_nosp list. This is done to avoid warning for "a = a"; if we
2592e4b17023SJohn Marino didn't exclude the LHS, we'd get it twice, once as a read and once
2593e4b17023SJohn Marino as a write. */
2594e4b17023SJohn Marino add_tlist (pno_sp, tmp_list3, x, 0);
2595e4b17023SJohn Marino warn_for_collisions_1 (TREE_OPERAND (x, 0), x, tmp_nosp, 1);
2596e4b17023SJohn Marino
2597e4b17023SJohn Marino merge_tlist (pbefore_sp, tmp_before, 0);
2598e4b17023SJohn Marino if (warning_candidate_p (TREE_OPERAND (x, 0)))
2599e4b17023SJohn Marino merge_tlist (&tmp_nosp, new_tlist (NULL, TREE_OPERAND (x, 0), x), 0);
2600e4b17023SJohn Marino add_tlist (pno_sp, tmp_nosp, NULL_TREE, 1);
2601e4b17023SJohn Marino return;
2602e4b17023SJohn Marino
2603e4b17023SJohn Marino case CALL_EXPR:
2604e4b17023SJohn Marino /* We need to warn about conflicts among arguments and conflicts between
2605e4b17023SJohn Marino args and the function address. Side effects of the function address,
2606e4b17023SJohn Marino however, are not ordered by the sequence point of the call. */
2607e4b17023SJohn Marino {
2608e4b17023SJohn Marino call_expr_arg_iterator iter;
2609e4b17023SJohn Marino tree arg;
2610e4b17023SJohn Marino tmp_before = tmp_nosp = 0;
2611e4b17023SJohn Marino verify_tree (CALL_EXPR_FN (x), &tmp_before, &tmp_nosp, NULL_TREE);
2612e4b17023SJohn Marino FOR_EACH_CALL_EXPR_ARG (arg, iter, x)
2613e4b17023SJohn Marino {
2614e4b17023SJohn Marino tmp_list2 = tmp_list3 = 0;
2615e4b17023SJohn Marino verify_tree (arg, &tmp_list2, &tmp_list3, NULL_TREE);
2616e4b17023SJohn Marino merge_tlist (&tmp_list3, tmp_list2, 0);
2617e4b17023SJohn Marino add_tlist (&tmp_before, tmp_list3, NULL_TREE, 0);
2618e4b17023SJohn Marino }
2619e4b17023SJohn Marino add_tlist (&tmp_before, tmp_nosp, NULL_TREE, 0);
2620e4b17023SJohn Marino warn_for_collisions (tmp_before);
2621e4b17023SJohn Marino add_tlist (pbefore_sp, tmp_before, NULL_TREE, 0);
2622e4b17023SJohn Marino return;
2623e4b17023SJohn Marino }
2624e4b17023SJohn Marino
2625e4b17023SJohn Marino case TREE_LIST:
2626e4b17023SJohn Marino /* Scan all the list, e.g. indices of multi dimensional array. */
2627e4b17023SJohn Marino while (x)
2628e4b17023SJohn Marino {
2629e4b17023SJohn Marino tmp_before = tmp_nosp = 0;
2630e4b17023SJohn Marino verify_tree (TREE_VALUE (x), &tmp_before, &tmp_nosp, NULL_TREE);
2631e4b17023SJohn Marino merge_tlist (&tmp_nosp, tmp_before, 0);
2632e4b17023SJohn Marino add_tlist (pno_sp, tmp_nosp, NULL_TREE, 0);
2633e4b17023SJohn Marino x = TREE_CHAIN (x);
2634e4b17023SJohn Marino }
2635e4b17023SJohn Marino return;
2636e4b17023SJohn Marino
2637e4b17023SJohn Marino case SAVE_EXPR:
2638e4b17023SJohn Marino {
2639e4b17023SJohn Marino struct tlist_cache *t;
2640e4b17023SJohn Marino for (t = save_expr_cache; t; t = t->next)
2641e4b17023SJohn Marino if (candidate_equal_p (t->expr, x))
2642e4b17023SJohn Marino break;
2643e4b17023SJohn Marino
2644e4b17023SJohn Marino if (!t)
2645e4b17023SJohn Marino {
2646e4b17023SJohn Marino t = XOBNEW (&tlist_obstack, struct tlist_cache);
2647e4b17023SJohn Marino t->next = save_expr_cache;
2648e4b17023SJohn Marino t->expr = x;
2649e4b17023SJohn Marino save_expr_cache = t;
2650e4b17023SJohn Marino
2651e4b17023SJohn Marino tmp_before = tmp_nosp = 0;
2652e4b17023SJohn Marino verify_tree (TREE_OPERAND (x, 0), &tmp_before, &tmp_nosp, NULL_TREE);
2653e4b17023SJohn Marino warn_for_collisions (tmp_nosp);
2654e4b17023SJohn Marino
2655e4b17023SJohn Marino tmp_list3 = 0;
2656e4b17023SJohn Marino while (tmp_nosp)
2657e4b17023SJohn Marino {
2658e4b17023SJohn Marino struct tlist *t = tmp_nosp;
2659e4b17023SJohn Marino tmp_nosp = t->next;
2660e4b17023SJohn Marino merge_tlist (&tmp_list3, t, 0);
2661e4b17023SJohn Marino }
2662e4b17023SJohn Marino t->cache_before_sp = tmp_before;
2663e4b17023SJohn Marino t->cache_after_sp = tmp_list3;
2664e4b17023SJohn Marino }
2665e4b17023SJohn Marino merge_tlist (pbefore_sp, t->cache_before_sp, 1);
2666e4b17023SJohn Marino add_tlist (pno_sp, t->cache_after_sp, NULL_TREE, 1);
2667e4b17023SJohn Marino return;
2668e4b17023SJohn Marino }
2669e4b17023SJohn Marino
2670e4b17023SJohn Marino case ADDR_EXPR:
2671e4b17023SJohn Marino x = TREE_OPERAND (x, 0);
2672e4b17023SJohn Marino if (DECL_P (x))
2673e4b17023SJohn Marino return;
2674e4b17023SJohn Marino writer = 0;
2675e4b17023SJohn Marino goto restart;
2676e4b17023SJohn Marino
2677e4b17023SJohn Marino default:
2678e4b17023SJohn Marino /* For other expressions, simply recurse on their operands.
2679e4b17023SJohn Marino Manual tail recursion for unary expressions.
2680e4b17023SJohn Marino Other non-expressions need not be processed. */
2681e4b17023SJohn Marino if (cl == tcc_unary)
2682e4b17023SJohn Marino {
2683e4b17023SJohn Marino x = TREE_OPERAND (x, 0);
2684e4b17023SJohn Marino writer = 0;
2685e4b17023SJohn Marino goto restart;
2686e4b17023SJohn Marino }
2687e4b17023SJohn Marino else if (IS_EXPR_CODE_CLASS (cl))
2688e4b17023SJohn Marino {
2689e4b17023SJohn Marino int lp;
2690e4b17023SJohn Marino int max = TREE_OPERAND_LENGTH (x);
2691e4b17023SJohn Marino for (lp = 0; lp < max; lp++)
2692e4b17023SJohn Marino {
2693e4b17023SJohn Marino tmp_before = tmp_nosp = 0;
2694e4b17023SJohn Marino verify_tree (TREE_OPERAND (x, lp), &tmp_before, &tmp_nosp, 0);
2695e4b17023SJohn Marino merge_tlist (&tmp_nosp, tmp_before, 0);
2696e4b17023SJohn Marino add_tlist (pno_sp, tmp_nosp, NULL_TREE, 0);
2697e4b17023SJohn Marino }
2698e4b17023SJohn Marino }
2699e4b17023SJohn Marino return;
2700e4b17023SJohn Marino }
2701e4b17023SJohn Marino }
2702e4b17023SJohn Marino
2703e4b17023SJohn Marino /* Try to warn for undefined behavior in EXPR due to missing sequence
2704e4b17023SJohn Marino points. */
2705e4b17023SJohn Marino
2706e4b17023SJohn Marino DEBUG_FUNCTION void
verify_sequence_points(tree expr)2707e4b17023SJohn Marino verify_sequence_points (tree expr)
2708e4b17023SJohn Marino {
2709e4b17023SJohn Marino struct tlist *before_sp = 0, *after_sp = 0;
2710e4b17023SJohn Marino
2711e4b17023SJohn Marino warned_ids = 0;
2712e4b17023SJohn Marino save_expr_cache = 0;
2713e4b17023SJohn Marino if (tlist_firstobj == 0)
2714e4b17023SJohn Marino {
2715e4b17023SJohn Marino gcc_obstack_init (&tlist_obstack);
2716e4b17023SJohn Marino tlist_firstobj = (char *) obstack_alloc (&tlist_obstack, 0);
2717e4b17023SJohn Marino }
2718e4b17023SJohn Marino
2719e4b17023SJohn Marino verify_tree (expr, &before_sp, &after_sp, 0);
2720e4b17023SJohn Marino warn_for_collisions (after_sp);
2721e4b17023SJohn Marino obstack_free (&tlist_obstack, tlist_firstobj);
2722e4b17023SJohn Marino }
2723e4b17023SJohn Marino
2724e4b17023SJohn Marino /* Validate the expression after `case' and apply default promotions. */
2725e4b17023SJohn Marino
2726e4b17023SJohn Marino static tree
check_case_value(tree value)2727e4b17023SJohn Marino check_case_value (tree value)
2728e4b17023SJohn Marino {
2729e4b17023SJohn Marino if (value == NULL_TREE)
2730e4b17023SJohn Marino return value;
2731e4b17023SJohn Marino
2732e4b17023SJohn Marino if (TREE_CODE (value) == INTEGER_CST)
2733e4b17023SJohn Marino /* Promote char or short to int. */
2734e4b17023SJohn Marino value = perform_integral_promotions (value);
2735e4b17023SJohn Marino else if (value != error_mark_node)
2736e4b17023SJohn Marino {
2737e4b17023SJohn Marino error ("case label does not reduce to an integer constant");
2738e4b17023SJohn Marino value = error_mark_node;
2739e4b17023SJohn Marino }
2740e4b17023SJohn Marino
2741e4b17023SJohn Marino constant_expression_warning (value);
2742e4b17023SJohn Marino
2743e4b17023SJohn Marino return value;
2744e4b17023SJohn Marino }
2745e4b17023SJohn Marino
2746e4b17023SJohn Marino /* See if the case values LOW and HIGH are in the range of the original
2747e4b17023SJohn Marino type (i.e. before the default conversion to int) of the switch testing
2748e4b17023SJohn Marino expression.
2749e4b17023SJohn Marino TYPE is the promoted type of the testing expression, and ORIG_TYPE is
2750e4b17023SJohn Marino the type before promoting it. CASE_LOW_P is a pointer to the lower
2751e4b17023SJohn Marino bound of the case label, and CASE_HIGH_P is the upper bound or NULL
2752e4b17023SJohn Marino if the case is not a case range.
2753e4b17023SJohn Marino The caller has to make sure that we are not called with NULL for
2754e4b17023SJohn Marino CASE_LOW_P (i.e. the default case).
2755e4b17023SJohn Marino Returns true if the case label is in range of ORIG_TYPE (saturated or
2756e4b17023SJohn Marino untouched) or false if the label is out of range. */
2757e4b17023SJohn Marino
2758e4b17023SJohn Marino static bool
check_case_bounds(tree type,tree orig_type,tree * case_low_p,tree * case_high_p)2759e4b17023SJohn Marino check_case_bounds (tree type, tree orig_type,
2760e4b17023SJohn Marino tree *case_low_p, tree *case_high_p)
2761e4b17023SJohn Marino {
2762e4b17023SJohn Marino tree min_value, max_value;
2763e4b17023SJohn Marino tree case_low = *case_low_p;
2764e4b17023SJohn Marino tree case_high = case_high_p ? *case_high_p : case_low;
2765e4b17023SJohn Marino
2766e4b17023SJohn Marino /* If there was a problem with the original type, do nothing. */
2767e4b17023SJohn Marino if (orig_type == error_mark_node)
2768e4b17023SJohn Marino return true;
2769e4b17023SJohn Marino
2770e4b17023SJohn Marino min_value = TYPE_MIN_VALUE (orig_type);
2771e4b17023SJohn Marino max_value = TYPE_MAX_VALUE (orig_type);
2772e4b17023SJohn Marino
2773e4b17023SJohn Marino /* Case label is less than minimum for type. */
2774e4b17023SJohn Marino if (tree_int_cst_compare (case_low, min_value) < 0
2775e4b17023SJohn Marino && tree_int_cst_compare (case_high, min_value) < 0)
2776e4b17023SJohn Marino {
2777e4b17023SJohn Marino warning (0, "case label value is less than minimum value for type");
2778e4b17023SJohn Marino return false;
2779e4b17023SJohn Marino }
2780e4b17023SJohn Marino
2781e4b17023SJohn Marino /* Case value is greater than maximum for type. */
2782e4b17023SJohn Marino if (tree_int_cst_compare (case_low, max_value) > 0
2783e4b17023SJohn Marino && tree_int_cst_compare (case_high, max_value) > 0)
2784e4b17023SJohn Marino {
2785e4b17023SJohn Marino warning (0, "case label value exceeds maximum value for type");
2786e4b17023SJohn Marino return false;
2787e4b17023SJohn Marino }
2788e4b17023SJohn Marino
2789e4b17023SJohn Marino /* Saturate lower case label value to minimum. */
2790e4b17023SJohn Marino if (tree_int_cst_compare (case_high, min_value) >= 0
2791e4b17023SJohn Marino && tree_int_cst_compare (case_low, min_value) < 0)
2792e4b17023SJohn Marino {
2793e4b17023SJohn Marino warning (0, "lower value in case label range"
2794e4b17023SJohn Marino " less than minimum value for type");
2795e4b17023SJohn Marino case_low = min_value;
2796e4b17023SJohn Marino }
2797e4b17023SJohn Marino
2798e4b17023SJohn Marino /* Saturate upper case label value to maximum. */
2799e4b17023SJohn Marino if (tree_int_cst_compare (case_low, max_value) <= 0
2800e4b17023SJohn Marino && tree_int_cst_compare (case_high, max_value) > 0)
2801e4b17023SJohn Marino {
2802e4b17023SJohn Marino warning (0, "upper value in case label range"
2803e4b17023SJohn Marino " exceeds maximum value for type");
2804e4b17023SJohn Marino case_high = max_value;
2805e4b17023SJohn Marino }
2806e4b17023SJohn Marino
2807e4b17023SJohn Marino if (*case_low_p != case_low)
2808e4b17023SJohn Marino *case_low_p = convert (type, case_low);
2809e4b17023SJohn Marino if (case_high_p && *case_high_p != case_high)
2810e4b17023SJohn Marino *case_high_p = convert (type, case_high);
2811e4b17023SJohn Marino
2812e4b17023SJohn Marino return true;
2813e4b17023SJohn Marino }
2814e4b17023SJohn Marino
2815e4b17023SJohn Marino /* Return an integer type with BITS bits of precision,
2816e4b17023SJohn Marino that is unsigned if UNSIGNEDP is nonzero, otherwise signed. */
2817e4b17023SJohn Marino
2818e4b17023SJohn Marino tree
c_common_type_for_size(unsigned int bits,int unsignedp)2819e4b17023SJohn Marino c_common_type_for_size (unsigned int bits, int unsignedp)
2820e4b17023SJohn Marino {
2821e4b17023SJohn Marino if (bits == TYPE_PRECISION (integer_type_node))
2822e4b17023SJohn Marino return unsignedp ? unsigned_type_node : integer_type_node;
2823e4b17023SJohn Marino
2824e4b17023SJohn Marino if (bits == TYPE_PRECISION (signed_char_type_node))
2825e4b17023SJohn Marino return unsignedp ? unsigned_char_type_node : signed_char_type_node;
2826e4b17023SJohn Marino
2827e4b17023SJohn Marino if (bits == TYPE_PRECISION (short_integer_type_node))
2828e4b17023SJohn Marino return unsignedp ? short_unsigned_type_node : short_integer_type_node;
2829e4b17023SJohn Marino
2830e4b17023SJohn Marino if (bits == TYPE_PRECISION (long_integer_type_node))
2831e4b17023SJohn Marino return unsignedp ? long_unsigned_type_node : long_integer_type_node;
2832e4b17023SJohn Marino
2833e4b17023SJohn Marino if (bits == TYPE_PRECISION (long_long_integer_type_node))
2834e4b17023SJohn Marino return (unsignedp ? long_long_unsigned_type_node
2835e4b17023SJohn Marino : long_long_integer_type_node);
2836e4b17023SJohn Marino
2837e4b17023SJohn Marino if (int128_integer_type_node
2838e4b17023SJohn Marino && bits == TYPE_PRECISION (int128_integer_type_node))
2839e4b17023SJohn Marino return (unsignedp ? int128_unsigned_type_node
2840e4b17023SJohn Marino : int128_integer_type_node);
2841e4b17023SJohn Marino
2842e4b17023SJohn Marino if (bits == TYPE_PRECISION (widest_integer_literal_type_node))
2843e4b17023SJohn Marino return (unsignedp ? widest_unsigned_literal_type_node
2844e4b17023SJohn Marino : widest_integer_literal_type_node);
2845e4b17023SJohn Marino
2846e4b17023SJohn Marino if (bits <= TYPE_PRECISION (intQI_type_node))
2847e4b17023SJohn Marino return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
2848e4b17023SJohn Marino
2849e4b17023SJohn Marino if (bits <= TYPE_PRECISION (intHI_type_node))
2850e4b17023SJohn Marino return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
2851e4b17023SJohn Marino
2852e4b17023SJohn Marino if (bits <= TYPE_PRECISION (intSI_type_node))
2853e4b17023SJohn Marino return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
2854e4b17023SJohn Marino
2855e4b17023SJohn Marino if (bits <= TYPE_PRECISION (intDI_type_node))
2856e4b17023SJohn Marino return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
2857e4b17023SJohn Marino
2858e4b17023SJohn Marino return 0;
2859e4b17023SJohn Marino }
2860e4b17023SJohn Marino
2861e4b17023SJohn Marino /* Return a fixed-point type that has at least IBIT ibits and FBIT fbits
2862e4b17023SJohn Marino that is unsigned if UNSIGNEDP is nonzero, otherwise signed;
2863e4b17023SJohn Marino and saturating if SATP is nonzero, otherwise not saturating. */
2864e4b17023SJohn Marino
2865e4b17023SJohn Marino tree
c_common_fixed_point_type_for_size(unsigned int ibit,unsigned int fbit,int unsignedp,int satp)2866e4b17023SJohn Marino c_common_fixed_point_type_for_size (unsigned int ibit, unsigned int fbit,
2867e4b17023SJohn Marino int unsignedp, int satp)
2868e4b17023SJohn Marino {
2869e4b17023SJohn Marino enum machine_mode mode;
2870e4b17023SJohn Marino if (ibit == 0)
2871e4b17023SJohn Marino mode = unsignedp ? UQQmode : QQmode;
2872e4b17023SJohn Marino else
2873e4b17023SJohn Marino mode = unsignedp ? UHAmode : HAmode;
2874e4b17023SJohn Marino
2875e4b17023SJohn Marino for (; mode != VOIDmode; mode = GET_MODE_WIDER_MODE (mode))
2876e4b17023SJohn Marino if (GET_MODE_IBIT (mode) >= ibit && GET_MODE_FBIT (mode) >= fbit)
2877e4b17023SJohn Marino break;
2878e4b17023SJohn Marino
2879e4b17023SJohn Marino if (mode == VOIDmode || !targetm.scalar_mode_supported_p (mode))
2880e4b17023SJohn Marino {
2881e4b17023SJohn Marino sorry ("GCC cannot support operators with integer types and "
2882e4b17023SJohn Marino "fixed-point types that have too many integral and "
2883e4b17023SJohn Marino "fractional bits together");
2884e4b17023SJohn Marino return 0;
2885e4b17023SJohn Marino }
2886e4b17023SJohn Marino
2887e4b17023SJohn Marino return c_common_type_for_mode (mode, satp);
2888e4b17023SJohn Marino }
2889e4b17023SJohn Marino
2890e4b17023SJohn Marino /* Used for communication between c_common_type_for_mode and
2891e4b17023SJohn Marino c_register_builtin_type. */
2892e4b17023SJohn Marino static GTY(()) tree registered_builtin_types;
2893e4b17023SJohn Marino
2894e4b17023SJohn Marino /* Return a data type that has machine mode MODE.
2895e4b17023SJohn Marino If the mode is an integer,
2896e4b17023SJohn Marino then UNSIGNEDP selects between signed and unsigned types.
2897e4b17023SJohn Marino If the mode is a fixed-point mode,
2898e4b17023SJohn Marino then UNSIGNEDP selects between saturating and nonsaturating types. */
2899e4b17023SJohn Marino
2900e4b17023SJohn Marino tree
c_common_type_for_mode(enum machine_mode mode,int unsignedp)2901e4b17023SJohn Marino c_common_type_for_mode (enum machine_mode mode, int unsignedp)
2902e4b17023SJohn Marino {
2903e4b17023SJohn Marino tree t;
2904e4b17023SJohn Marino
2905e4b17023SJohn Marino if (mode == TYPE_MODE (integer_type_node))
2906e4b17023SJohn Marino return unsignedp ? unsigned_type_node : integer_type_node;
2907e4b17023SJohn Marino
2908e4b17023SJohn Marino if (mode == TYPE_MODE (signed_char_type_node))
2909e4b17023SJohn Marino return unsignedp ? unsigned_char_type_node : signed_char_type_node;
2910e4b17023SJohn Marino
2911e4b17023SJohn Marino if (mode == TYPE_MODE (short_integer_type_node))
2912e4b17023SJohn Marino return unsignedp ? short_unsigned_type_node : short_integer_type_node;
2913e4b17023SJohn Marino
2914e4b17023SJohn Marino if (mode == TYPE_MODE (long_integer_type_node))
2915e4b17023SJohn Marino return unsignedp ? long_unsigned_type_node : long_integer_type_node;
2916e4b17023SJohn Marino
2917e4b17023SJohn Marino if (mode == TYPE_MODE (long_long_integer_type_node))
2918e4b17023SJohn Marino return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
2919e4b17023SJohn Marino
2920e4b17023SJohn Marino if (int128_integer_type_node
2921e4b17023SJohn Marino && mode == TYPE_MODE (int128_integer_type_node))
2922e4b17023SJohn Marino return unsignedp ? int128_unsigned_type_node : int128_integer_type_node;
2923e4b17023SJohn Marino
2924e4b17023SJohn Marino if (mode == TYPE_MODE (widest_integer_literal_type_node))
2925e4b17023SJohn Marino return unsignedp ? widest_unsigned_literal_type_node
2926e4b17023SJohn Marino : widest_integer_literal_type_node;
2927e4b17023SJohn Marino
2928e4b17023SJohn Marino if (mode == QImode)
2929e4b17023SJohn Marino return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
2930e4b17023SJohn Marino
2931e4b17023SJohn Marino if (mode == HImode)
2932e4b17023SJohn Marino return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
2933e4b17023SJohn Marino
2934e4b17023SJohn Marino if (mode == SImode)
2935e4b17023SJohn Marino return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
2936e4b17023SJohn Marino
2937e4b17023SJohn Marino if (mode == DImode)
2938e4b17023SJohn Marino return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
2939e4b17023SJohn Marino
2940e4b17023SJohn Marino #if HOST_BITS_PER_WIDE_INT >= 64
2941e4b17023SJohn Marino if (mode == TYPE_MODE (intTI_type_node))
2942e4b17023SJohn Marino return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
2943e4b17023SJohn Marino #endif
2944e4b17023SJohn Marino
2945e4b17023SJohn Marino if (mode == TYPE_MODE (float_type_node))
2946e4b17023SJohn Marino return float_type_node;
2947e4b17023SJohn Marino
2948e4b17023SJohn Marino if (mode == TYPE_MODE (double_type_node))
2949e4b17023SJohn Marino return double_type_node;
2950e4b17023SJohn Marino
2951e4b17023SJohn Marino if (mode == TYPE_MODE (long_double_type_node))
2952e4b17023SJohn Marino return long_double_type_node;
2953e4b17023SJohn Marino
2954e4b17023SJohn Marino if (mode == TYPE_MODE (void_type_node))
2955e4b17023SJohn Marino return void_type_node;
2956e4b17023SJohn Marino
2957e4b17023SJohn Marino if (mode == TYPE_MODE (build_pointer_type (char_type_node)))
2958e4b17023SJohn Marino return (unsignedp
2959e4b17023SJohn Marino ? make_unsigned_type (GET_MODE_PRECISION (mode))
2960e4b17023SJohn Marino : make_signed_type (GET_MODE_PRECISION (mode)));
2961e4b17023SJohn Marino
2962e4b17023SJohn Marino if (mode == TYPE_MODE (build_pointer_type (integer_type_node)))
2963e4b17023SJohn Marino return (unsignedp
2964e4b17023SJohn Marino ? make_unsigned_type (GET_MODE_PRECISION (mode))
2965e4b17023SJohn Marino : make_signed_type (GET_MODE_PRECISION (mode)));
2966e4b17023SJohn Marino
2967e4b17023SJohn Marino if (COMPLEX_MODE_P (mode))
2968e4b17023SJohn Marino {
2969e4b17023SJohn Marino enum machine_mode inner_mode;
2970e4b17023SJohn Marino tree inner_type;
2971e4b17023SJohn Marino
2972e4b17023SJohn Marino if (mode == TYPE_MODE (complex_float_type_node))
2973e4b17023SJohn Marino return complex_float_type_node;
2974e4b17023SJohn Marino if (mode == TYPE_MODE (complex_double_type_node))
2975e4b17023SJohn Marino return complex_double_type_node;
2976e4b17023SJohn Marino if (mode == TYPE_MODE (complex_long_double_type_node))
2977e4b17023SJohn Marino return complex_long_double_type_node;
2978e4b17023SJohn Marino
2979e4b17023SJohn Marino if (mode == TYPE_MODE (complex_integer_type_node) && !unsignedp)
2980e4b17023SJohn Marino return complex_integer_type_node;
2981e4b17023SJohn Marino
2982e4b17023SJohn Marino inner_mode = GET_MODE_INNER (mode);
2983e4b17023SJohn Marino inner_type = c_common_type_for_mode (inner_mode, unsignedp);
2984e4b17023SJohn Marino if (inner_type != NULL_TREE)
2985e4b17023SJohn Marino return build_complex_type (inner_type);
2986e4b17023SJohn Marino }
2987e4b17023SJohn Marino else if (VECTOR_MODE_P (mode))
2988e4b17023SJohn Marino {
2989e4b17023SJohn Marino enum machine_mode inner_mode = GET_MODE_INNER (mode);
2990e4b17023SJohn Marino tree inner_type = c_common_type_for_mode (inner_mode, unsignedp);
2991e4b17023SJohn Marino if (inner_type != NULL_TREE)
2992e4b17023SJohn Marino return build_vector_type_for_mode (inner_type, mode);
2993e4b17023SJohn Marino }
2994e4b17023SJohn Marino
2995e4b17023SJohn Marino if (mode == TYPE_MODE (dfloat32_type_node))
2996e4b17023SJohn Marino return dfloat32_type_node;
2997e4b17023SJohn Marino if (mode == TYPE_MODE (dfloat64_type_node))
2998e4b17023SJohn Marino return dfloat64_type_node;
2999e4b17023SJohn Marino if (mode == TYPE_MODE (dfloat128_type_node))
3000e4b17023SJohn Marino return dfloat128_type_node;
3001e4b17023SJohn Marino
3002e4b17023SJohn Marino if (ALL_SCALAR_FIXED_POINT_MODE_P (mode))
3003e4b17023SJohn Marino {
3004e4b17023SJohn Marino if (mode == TYPE_MODE (short_fract_type_node))
3005e4b17023SJohn Marino return unsignedp ? sat_short_fract_type_node : short_fract_type_node;
3006e4b17023SJohn Marino if (mode == TYPE_MODE (fract_type_node))
3007e4b17023SJohn Marino return unsignedp ? sat_fract_type_node : fract_type_node;
3008e4b17023SJohn Marino if (mode == TYPE_MODE (long_fract_type_node))
3009e4b17023SJohn Marino return unsignedp ? sat_long_fract_type_node : long_fract_type_node;
3010e4b17023SJohn Marino if (mode == TYPE_MODE (long_long_fract_type_node))
3011e4b17023SJohn Marino return unsignedp ? sat_long_long_fract_type_node
3012e4b17023SJohn Marino : long_long_fract_type_node;
3013e4b17023SJohn Marino
3014e4b17023SJohn Marino if (mode == TYPE_MODE (unsigned_short_fract_type_node))
3015e4b17023SJohn Marino return unsignedp ? sat_unsigned_short_fract_type_node
3016e4b17023SJohn Marino : unsigned_short_fract_type_node;
3017e4b17023SJohn Marino if (mode == TYPE_MODE (unsigned_fract_type_node))
3018e4b17023SJohn Marino return unsignedp ? sat_unsigned_fract_type_node
3019e4b17023SJohn Marino : unsigned_fract_type_node;
3020e4b17023SJohn Marino if (mode == TYPE_MODE (unsigned_long_fract_type_node))
3021e4b17023SJohn Marino return unsignedp ? sat_unsigned_long_fract_type_node
3022e4b17023SJohn Marino : unsigned_long_fract_type_node;
3023e4b17023SJohn Marino if (mode == TYPE_MODE (unsigned_long_long_fract_type_node))
3024e4b17023SJohn Marino return unsignedp ? sat_unsigned_long_long_fract_type_node
3025e4b17023SJohn Marino : unsigned_long_long_fract_type_node;
3026e4b17023SJohn Marino
3027e4b17023SJohn Marino if (mode == TYPE_MODE (short_accum_type_node))
3028e4b17023SJohn Marino return unsignedp ? sat_short_accum_type_node : short_accum_type_node;
3029e4b17023SJohn Marino if (mode == TYPE_MODE (accum_type_node))
3030e4b17023SJohn Marino return unsignedp ? sat_accum_type_node : accum_type_node;
3031e4b17023SJohn Marino if (mode == TYPE_MODE (long_accum_type_node))
3032e4b17023SJohn Marino return unsignedp ? sat_long_accum_type_node : long_accum_type_node;
3033e4b17023SJohn Marino if (mode == TYPE_MODE (long_long_accum_type_node))
3034e4b17023SJohn Marino return unsignedp ? sat_long_long_accum_type_node
3035e4b17023SJohn Marino : long_long_accum_type_node;
3036e4b17023SJohn Marino
3037e4b17023SJohn Marino if (mode == TYPE_MODE (unsigned_short_accum_type_node))
3038e4b17023SJohn Marino return unsignedp ? sat_unsigned_short_accum_type_node
3039e4b17023SJohn Marino : unsigned_short_accum_type_node;
3040e4b17023SJohn Marino if (mode == TYPE_MODE (unsigned_accum_type_node))
3041e4b17023SJohn Marino return unsignedp ? sat_unsigned_accum_type_node
3042e4b17023SJohn Marino : unsigned_accum_type_node;
3043e4b17023SJohn Marino if (mode == TYPE_MODE (unsigned_long_accum_type_node))
3044e4b17023SJohn Marino return unsignedp ? sat_unsigned_long_accum_type_node
3045e4b17023SJohn Marino : unsigned_long_accum_type_node;
3046e4b17023SJohn Marino if (mode == TYPE_MODE (unsigned_long_long_accum_type_node))
3047e4b17023SJohn Marino return unsignedp ? sat_unsigned_long_long_accum_type_node
3048e4b17023SJohn Marino : unsigned_long_long_accum_type_node;
3049e4b17023SJohn Marino
3050e4b17023SJohn Marino if (mode == QQmode)
3051e4b17023SJohn Marino return unsignedp ? sat_qq_type_node : qq_type_node;
3052e4b17023SJohn Marino if (mode == HQmode)
3053e4b17023SJohn Marino return unsignedp ? sat_hq_type_node : hq_type_node;
3054e4b17023SJohn Marino if (mode == SQmode)
3055e4b17023SJohn Marino return unsignedp ? sat_sq_type_node : sq_type_node;
3056e4b17023SJohn Marino if (mode == DQmode)
3057e4b17023SJohn Marino return unsignedp ? sat_dq_type_node : dq_type_node;
3058e4b17023SJohn Marino if (mode == TQmode)
3059e4b17023SJohn Marino return unsignedp ? sat_tq_type_node : tq_type_node;
3060e4b17023SJohn Marino
3061e4b17023SJohn Marino if (mode == UQQmode)
3062e4b17023SJohn Marino return unsignedp ? sat_uqq_type_node : uqq_type_node;
3063e4b17023SJohn Marino if (mode == UHQmode)
3064e4b17023SJohn Marino return unsignedp ? sat_uhq_type_node : uhq_type_node;
3065e4b17023SJohn Marino if (mode == USQmode)
3066e4b17023SJohn Marino return unsignedp ? sat_usq_type_node : usq_type_node;
3067e4b17023SJohn Marino if (mode == UDQmode)
3068e4b17023SJohn Marino return unsignedp ? sat_udq_type_node : udq_type_node;
3069e4b17023SJohn Marino if (mode == UTQmode)
3070e4b17023SJohn Marino return unsignedp ? sat_utq_type_node : utq_type_node;
3071e4b17023SJohn Marino
3072e4b17023SJohn Marino if (mode == HAmode)
3073e4b17023SJohn Marino return unsignedp ? sat_ha_type_node : ha_type_node;
3074e4b17023SJohn Marino if (mode == SAmode)
3075e4b17023SJohn Marino return unsignedp ? sat_sa_type_node : sa_type_node;
3076e4b17023SJohn Marino if (mode == DAmode)
3077e4b17023SJohn Marino return unsignedp ? sat_da_type_node : da_type_node;
3078e4b17023SJohn Marino if (mode == TAmode)
3079e4b17023SJohn Marino return unsignedp ? sat_ta_type_node : ta_type_node;
3080e4b17023SJohn Marino
3081e4b17023SJohn Marino if (mode == UHAmode)
3082e4b17023SJohn Marino return unsignedp ? sat_uha_type_node : uha_type_node;
3083e4b17023SJohn Marino if (mode == USAmode)
3084e4b17023SJohn Marino return unsignedp ? sat_usa_type_node : usa_type_node;
3085e4b17023SJohn Marino if (mode == UDAmode)
3086e4b17023SJohn Marino return unsignedp ? sat_uda_type_node : uda_type_node;
3087e4b17023SJohn Marino if (mode == UTAmode)
3088e4b17023SJohn Marino return unsignedp ? sat_uta_type_node : uta_type_node;
3089e4b17023SJohn Marino }
3090e4b17023SJohn Marino
3091e4b17023SJohn Marino for (t = registered_builtin_types; t; t = TREE_CHAIN (t))
3092e4b17023SJohn Marino if (TYPE_MODE (TREE_VALUE (t)) == mode
3093e4b17023SJohn Marino && !!unsignedp == !!TYPE_UNSIGNED (TREE_VALUE (t)))
3094e4b17023SJohn Marino return TREE_VALUE (t);
3095e4b17023SJohn Marino
3096e4b17023SJohn Marino return 0;
3097e4b17023SJohn Marino }
3098e4b17023SJohn Marino
3099e4b17023SJohn Marino tree
c_common_unsigned_type(tree type)3100e4b17023SJohn Marino c_common_unsigned_type (tree type)
3101e4b17023SJohn Marino {
3102e4b17023SJohn Marino return c_common_signed_or_unsigned_type (1, type);
3103e4b17023SJohn Marino }
3104e4b17023SJohn Marino
3105e4b17023SJohn Marino /* Return a signed type the same as TYPE in other respects. */
3106e4b17023SJohn Marino
3107e4b17023SJohn Marino tree
c_common_signed_type(tree type)3108e4b17023SJohn Marino c_common_signed_type (tree type)
3109e4b17023SJohn Marino {
3110e4b17023SJohn Marino return c_common_signed_or_unsigned_type (0, type);
3111e4b17023SJohn Marino }
3112e4b17023SJohn Marino
3113e4b17023SJohn Marino /* Return a type the same as TYPE except unsigned or
3114e4b17023SJohn Marino signed according to UNSIGNEDP. */
3115e4b17023SJohn Marino
3116e4b17023SJohn Marino tree
c_common_signed_or_unsigned_type(int unsignedp,tree type)3117e4b17023SJohn Marino c_common_signed_or_unsigned_type (int unsignedp, tree type)
3118e4b17023SJohn Marino {
3119e4b17023SJohn Marino tree type1;
3120e4b17023SJohn Marino
3121e4b17023SJohn Marino /* This block of code emulates the behavior of the old
3122e4b17023SJohn Marino c_common_unsigned_type. In particular, it returns
3123e4b17023SJohn Marino long_unsigned_type_node if passed a long, even when a int would
3124e4b17023SJohn Marino have the same size. This is necessary for warnings to work
3125e4b17023SJohn Marino correctly in archs where sizeof(int) == sizeof(long) */
3126e4b17023SJohn Marino
3127e4b17023SJohn Marino type1 = TYPE_MAIN_VARIANT (type);
3128e4b17023SJohn Marino if (type1 == signed_char_type_node || type1 == char_type_node || type1 == unsigned_char_type_node)
3129e4b17023SJohn Marino return unsignedp ? unsigned_char_type_node : signed_char_type_node;
3130e4b17023SJohn Marino if (type1 == integer_type_node || type1 == unsigned_type_node)
3131e4b17023SJohn Marino return unsignedp ? unsigned_type_node : integer_type_node;
3132e4b17023SJohn Marino if (type1 == short_integer_type_node || type1 == short_unsigned_type_node)
3133e4b17023SJohn Marino return unsignedp ? short_unsigned_type_node : short_integer_type_node;
3134e4b17023SJohn Marino if (type1 == long_integer_type_node || type1 == long_unsigned_type_node)
3135e4b17023SJohn Marino return unsignedp ? long_unsigned_type_node : long_integer_type_node;
3136e4b17023SJohn Marino if (type1 == long_long_integer_type_node || type1 == long_long_unsigned_type_node)
3137e4b17023SJohn Marino return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node;
3138e4b17023SJohn Marino if (int128_integer_type_node
3139e4b17023SJohn Marino && (type1 == int128_integer_type_node
3140e4b17023SJohn Marino || type1 == int128_unsigned_type_node))
3141e4b17023SJohn Marino return unsignedp ? int128_unsigned_type_node : int128_integer_type_node;
3142e4b17023SJohn Marino if (type1 == widest_integer_literal_type_node || type1 == widest_unsigned_literal_type_node)
3143e4b17023SJohn Marino return unsignedp ? widest_unsigned_literal_type_node : widest_integer_literal_type_node;
3144e4b17023SJohn Marino #if HOST_BITS_PER_WIDE_INT >= 64
3145e4b17023SJohn Marino if (type1 == intTI_type_node || type1 == unsigned_intTI_type_node)
3146e4b17023SJohn Marino return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
3147e4b17023SJohn Marino #endif
3148e4b17023SJohn Marino if (type1 == intDI_type_node || type1 == unsigned_intDI_type_node)
3149e4b17023SJohn Marino return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
3150e4b17023SJohn Marino if (type1 == intSI_type_node || type1 == unsigned_intSI_type_node)
3151e4b17023SJohn Marino return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
3152e4b17023SJohn Marino if (type1 == intHI_type_node || type1 == unsigned_intHI_type_node)
3153e4b17023SJohn Marino return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
3154e4b17023SJohn Marino if (type1 == intQI_type_node || type1 == unsigned_intQI_type_node)
3155e4b17023SJohn Marino return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
3156e4b17023SJohn Marino
3157e4b17023SJohn Marino #define C_COMMON_FIXED_TYPES(NAME) \
3158e4b17023SJohn Marino if (type1 == short_ ## NAME ## _type_node \
3159e4b17023SJohn Marino || type1 == unsigned_short_ ## NAME ## _type_node) \
3160e4b17023SJohn Marino return unsignedp ? unsigned_short_ ## NAME ## _type_node \
3161e4b17023SJohn Marino : short_ ## NAME ## _type_node; \
3162e4b17023SJohn Marino if (type1 == NAME ## _type_node \
3163e4b17023SJohn Marino || type1 == unsigned_ ## NAME ## _type_node) \
3164e4b17023SJohn Marino return unsignedp ? unsigned_ ## NAME ## _type_node \
3165e4b17023SJohn Marino : NAME ## _type_node; \
3166e4b17023SJohn Marino if (type1 == long_ ## NAME ## _type_node \
3167e4b17023SJohn Marino || type1 == unsigned_long_ ## NAME ## _type_node) \
3168e4b17023SJohn Marino return unsignedp ? unsigned_long_ ## NAME ## _type_node \
3169e4b17023SJohn Marino : long_ ## NAME ## _type_node; \
3170e4b17023SJohn Marino if (type1 == long_long_ ## NAME ## _type_node \
3171e4b17023SJohn Marino || type1 == unsigned_long_long_ ## NAME ## _type_node) \
3172e4b17023SJohn Marino return unsignedp ? unsigned_long_long_ ## NAME ## _type_node \
3173e4b17023SJohn Marino : long_long_ ## NAME ## _type_node;
3174e4b17023SJohn Marino
3175e4b17023SJohn Marino #define C_COMMON_FIXED_MODE_TYPES(NAME) \
3176e4b17023SJohn Marino if (type1 == NAME ## _type_node \
3177e4b17023SJohn Marino || type1 == u ## NAME ## _type_node) \
3178e4b17023SJohn Marino return unsignedp ? u ## NAME ## _type_node \
3179e4b17023SJohn Marino : NAME ## _type_node;
3180e4b17023SJohn Marino
3181e4b17023SJohn Marino #define C_COMMON_FIXED_TYPES_SAT(NAME) \
3182e4b17023SJohn Marino if (type1 == sat_ ## short_ ## NAME ## _type_node \
3183e4b17023SJohn Marino || type1 == sat_ ## unsigned_short_ ## NAME ## _type_node) \
3184e4b17023SJohn Marino return unsignedp ? sat_ ## unsigned_short_ ## NAME ## _type_node \
3185e4b17023SJohn Marino : sat_ ## short_ ## NAME ## _type_node; \
3186e4b17023SJohn Marino if (type1 == sat_ ## NAME ## _type_node \
3187e4b17023SJohn Marino || type1 == sat_ ## unsigned_ ## NAME ## _type_node) \
3188e4b17023SJohn Marino return unsignedp ? sat_ ## unsigned_ ## NAME ## _type_node \
3189e4b17023SJohn Marino : sat_ ## NAME ## _type_node; \
3190e4b17023SJohn Marino if (type1 == sat_ ## long_ ## NAME ## _type_node \
3191e4b17023SJohn Marino || type1 == sat_ ## unsigned_long_ ## NAME ## _type_node) \
3192e4b17023SJohn Marino return unsignedp ? sat_ ## unsigned_long_ ## NAME ## _type_node \
3193e4b17023SJohn Marino : sat_ ## long_ ## NAME ## _type_node; \
3194e4b17023SJohn Marino if (type1 == sat_ ## long_long_ ## NAME ## _type_node \
3195e4b17023SJohn Marino || type1 == sat_ ## unsigned_long_long_ ## NAME ## _type_node) \
3196e4b17023SJohn Marino return unsignedp ? sat_ ## unsigned_long_long_ ## NAME ## _type_node \
3197e4b17023SJohn Marino : sat_ ## long_long_ ## NAME ## _type_node;
3198e4b17023SJohn Marino
3199e4b17023SJohn Marino #define C_COMMON_FIXED_MODE_TYPES_SAT(NAME) \
3200e4b17023SJohn Marino if (type1 == sat_ ## NAME ## _type_node \
3201e4b17023SJohn Marino || type1 == sat_ ## u ## NAME ## _type_node) \
3202e4b17023SJohn Marino return unsignedp ? sat_ ## u ## NAME ## _type_node \
3203e4b17023SJohn Marino : sat_ ## NAME ## _type_node;
3204e4b17023SJohn Marino
3205e4b17023SJohn Marino C_COMMON_FIXED_TYPES (fract);
3206e4b17023SJohn Marino C_COMMON_FIXED_TYPES_SAT (fract);
3207e4b17023SJohn Marino C_COMMON_FIXED_TYPES (accum);
3208e4b17023SJohn Marino C_COMMON_FIXED_TYPES_SAT (accum);
3209e4b17023SJohn Marino
3210e4b17023SJohn Marino C_COMMON_FIXED_MODE_TYPES (qq);
3211e4b17023SJohn Marino C_COMMON_FIXED_MODE_TYPES (hq);
3212e4b17023SJohn Marino C_COMMON_FIXED_MODE_TYPES (sq);
3213e4b17023SJohn Marino C_COMMON_FIXED_MODE_TYPES (dq);
3214e4b17023SJohn Marino C_COMMON_FIXED_MODE_TYPES (tq);
3215e4b17023SJohn Marino C_COMMON_FIXED_MODE_TYPES_SAT (qq);
3216e4b17023SJohn Marino C_COMMON_FIXED_MODE_TYPES_SAT (hq);
3217e4b17023SJohn Marino C_COMMON_FIXED_MODE_TYPES_SAT (sq);
3218e4b17023SJohn Marino C_COMMON_FIXED_MODE_TYPES_SAT (dq);
3219e4b17023SJohn Marino C_COMMON_FIXED_MODE_TYPES_SAT (tq);
3220e4b17023SJohn Marino C_COMMON_FIXED_MODE_TYPES (ha);
3221e4b17023SJohn Marino C_COMMON_FIXED_MODE_TYPES (sa);
3222e4b17023SJohn Marino C_COMMON_FIXED_MODE_TYPES (da);
3223e4b17023SJohn Marino C_COMMON_FIXED_MODE_TYPES (ta);
3224e4b17023SJohn Marino C_COMMON_FIXED_MODE_TYPES_SAT (ha);
3225e4b17023SJohn Marino C_COMMON_FIXED_MODE_TYPES_SAT (sa);
3226e4b17023SJohn Marino C_COMMON_FIXED_MODE_TYPES_SAT (da);
3227e4b17023SJohn Marino C_COMMON_FIXED_MODE_TYPES_SAT (ta);
3228e4b17023SJohn Marino
3229e4b17023SJohn Marino /* For ENUMERAL_TYPEs in C++, must check the mode of the types, not
3230e4b17023SJohn Marino the precision; they have precision set to match their range, but
3231e4b17023SJohn Marino may use a wider mode to match an ABI. If we change modes, we may
3232e4b17023SJohn Marino wind up with bad conversions. For INTEGER_TYPEs in C, must check
3233e4b17023SJohn Marino the precision as well, so as to yield correct results for
3234e4b17023SJohn Marino bit-field types. C++ does not have these separate bit-field
3235e4b17023SJohn Marino types, and producing a signed or unsigned variant of an
3236e4b17023SJohn Marino ENUMERAL_TYPE may cause other problems as well. */
3237e4b17023SJohn Marino
3238e4b17023SJohn Marino if (!INTEGRAL_TYPE_P (type)
3239e4b17023SJohn Marino || TYPE_UNSIGNED (type) == unsignedp)
3240e4b17023SJohn Marino return type;
3241e4b17023SJohn Marino
3242e4b17023SJohn Marino #define TYPE_OK(node) \
3243e4b17023SJohn Marino (TYPE_MODE (type) == TYPE_MODE (node) \
3244e4b17023SJohn Marino && TYPE_PRECISION (type) == TYPE_PRECISION (node))
3245e4b17023SJohn Marino if (TYPE_OK (signed_char_type_node))
3246e4b17023SJohn Marino return unsignedp ? unsigned_char_type_node : signed_char_type_node;
3247e4b17023SJohn Marino if (TYPE_OK (integer_type_node))
3248e4b17023SJohn Marino return unsignedp ? unsigned_type_node : integer_type_node;
3249e4b17023SJohn Marino if (TYPE_OK (short_integer_type_node))
3250e4b17023SJohn Marino return unsignedp ? short_unsigned_type_node : short_integer_type_node;
3251e4b17023SJohn Marino if (TYPE_OK (long_integer_type_node))
3252e4b17023SJohn Marino return unsignedp ? long_unsigned_type_node : long_integer_type_node;
3253e4b17023SJohn Marino if (TYPE_OK (long_long_integer_type_node))
3254e4b17023SJohn Marino return (unsignedp ? long_long_unsigned_type_node
3255e4b17023SJohn Marino : long_long_integer_type_node);
3256e4b17023SJohn Marino if (int128_integer_type_node && TYPE_OK (int128_integer_type_node))
3257e4b17023SJohn Marino return (unsignedp ? int128_unsigned_type_node
3258e4b17023SJohn Marino : int128_integer_type_node);
3259e4b17023SJohn Marino if (TYPE_OK (widest_integer_literal_type_node))
3260e4b17023SJohn Marino return (unsignedp ? widest_unsigned_literal_type_node
3261e4b17023SJohn Marino : widest_integer_literal_type_node);
3262e4b17023SJohn Marino
3263e4b17023SJohn Marino #if HOST_BITS_PER_WIDE_INT >= 64
3264e4b17023SJohn Marino if (TYPE_OK (intTI_type_node))
3265e4b17023SJohn Marino return unsignedp ? unsigned_intTI_type_node : intTI_type_node;
3266e4b17023SJohn Marino #endif
3267e4b17023SJohn Marino if (TYPE_OK (intDI_type_node))
3268e4b17023SJohn Marino return unsignedp ? unsigned_intDI_type_node : intDI_type_node;
3269e4b17023SJohn Marino if (TYPE_OK (intSI_type_node))
3270e4b17023SJohn Marino return unsignedp ? unsigned_intSI_type_node : intSI_type_node;
3271e4b17023SJohn Marino if (TYPE_OK (intHI_type_node))
3272e4b17023SJohn Marino return unsignedp ? unsigned_intHI_type_node : intHI_type_node;
3273e4b17023SJohn Marino if (TYPE_OK (intQI_type_node))
3274e4b17023SJohn Marino return unsignedp ? unsigned_intQI_type_node : intQI_type_node;
3275e4b17023SJohn Marino #undef TYPE_OK
3276e4b17023SJohn Marino
3277e4b17023SJohn Marino return build_nonstandard_integer_type (TYPE_PRECISION (type), unsignedp);
3278e4b17023SJohn Marino }
3279e4b17023SJohn Marino
3280e4b17023SJohn Marino /* Build a bit-field integer type for the given WIDTH and UNSIGNEDP. */
3281e4b17023SJohn Marino
3282e4b17023SJohn Marino tree
c_build_bitfield_integer_type(unsigned HOST_WIDE_INT width,int unsignedp)3283e4b17023SJohn Marino c_build_bitfield_integer_type (unsigned HOST_WIDE_INT width, int unsignedp)
3284e4b17023SJohn Marino {
3285e4b17023SJohn Marino /* Extended integer types of the same width as a standard type have
3286e4b17023SJohn Marino lesser rank, so those of the same width as int promote to int or
3287e4b17023SJohn Marino unsigned int and are valid for printf formats expecting int or
3288e4b17023SJohn Marino unsigned int. To avoid such special cases, avoid creating
3289e4b17023SJohn Marino extended integer types for bit-fields if a standard integer type
3290e4b17023SJohn Marino is available. */
3291e4b17023SJohn Marino if (width == TYPE_PRECISION (integer_type_node))
3292e4b17023SJohn Marino return unsignedp ? unsigned_type_node : integer_type_node;
3293e4b17023SJohn Marino if (width == TYPE_PRECISION (signed_char_type_node))
3294e4b17023SJohn Marino return unsignedp ? unsigned_char_type_node : signed_char_type_node;
3295e4b17023SJohn Marino if (width == TYPE_PRECISION (short_integer_type_node))
3296e4b17023SJohn Marino return unsignedp ? short_unsigned_type_node : short_integer_type_node;
3297e4b17023SJohn Marino if (width == TYPE_PRECISION (long_integer_type_node))
3298e4b17023SJohn Marino return unsignedp ? long_unsigned_type_node : long_integer_type_node;
3299e4b17023SJohn Marino if (width == TYPE_PRECISION (long_long_integer_type_node))
3300e4b17023SJohn Marino return (unsignedp ? long_long_unsigned_type_node
3301e4b17023SJohn Marino : long_long_integer_type_node);
3302e4b17023SJohn Marino if (int128_integer_type_node
3303e4b17023SJohn Marino && width == TYPE_PRECISION (int128_integer_type_node))
3304e4b17023SJohn Marino return (unsignedp ? int128_unsigned_type_node
3305e4b17023SJohn Marino : int128_integer_type_node);
3306e4b17023SJohn Marino return build_nonstandard_integer_type (width, unsignedp);
3307e4b17023SJohn Marino }
3308e4b17023SJohn Marino
3309e4b17023SJohn Marino /* The C version of the register_builtin_type langhook. */
3310e4b17023SJohn Marino
3311e4b17023SJohn Marino void
c_register_builtin_type(tree type,const char * name)3312e4b17023SJohn Marino c_register_builtin_type (tree type, const char* name)
3313e4b17023SJohn Marino {
3314e4b17023SJohn Marino tree decl;
3315e4b17023SJohn Marino
3316e4b17023SJohn Marino decl = build_decl (UNKNOWN_LOCATION,
3317e4b17023SJohn Marino TYPE_DECL, get_identifier (name), type);
3318e4b17023SJohn Marino DECL_ARTIFICIAL (decl) = 1;
3319e4b17023SJohn Marino if (!TYPE_NAME (type))
3320e4b17023SJohn Marino TYPE_NAME (type) = decl;
3321e4b17023SJohn Marino pushdecl (decl);
3322e4b17023SJohn Marino
3323e4b17023SJohn Marino registered_builtin_types = tree_cons (0, type, registered_builtin_types);
3324e4b17023SJohn Marino }
3325e4b17023SJohn Marino
3326e4b17023SJohn Marino /* Print an error message for invalid operands to arith operation
3327e4b17023SJohn Marino CODE with TYPE0 for operand 0, and TYPE1 for operand 1.
3328e4b17023SJohn Marino LOCATION is the location of the message. */
3329e4b17023SJohn Marino
3330e4b17023SJohn Marino void
binary_op_error(location_t location,enum tree_code code,tree type0,tree type1)3331e4b17023SJohn Marino binary_op_error (location_t location, enum tree_code code,
3332e4b17023SJohn Marino tree type0, tree type1)
3333e4b17023SJohn Marino {
3334e4b17023SJohn Marino const char *opname;
3335e4b17023SJohn Marino
3336e4b17023SJohn Marino switch (code)
3337e4b17023SJohn Marino {
3338e4b17023SJohn Marino case PLUS_EXPR:
3339e4b17023SJohn Marino opname = "+"; break;
3340e4b17023SJohn Marino case MINUS_EXPR:
3341e4b17023SJohn Marino opname = "-"; break;
3342e4b17023SJohn Marino case MULT_EXPR:
3343e4b17023SJohn Marino opname = "*"; break;
3344e4b17023SJohn Marino case MAX_EXPR:
3345e4b17023SJohn Marino opname = "max"; break;
3346e4b17023SJohn Marino case MIN_EXPR:
3347e4b17023SJohn Marino opname = "min"; break;
3348e4b17023SJohn Marino case EQ_EXPR:
3349e4b17023SJohn Marino opname = "=="; break;
3350e4b17023SJohn Marino case NE_EXPR:
3351e4b17023SJohn Marino opname = "!="; break;
3352e4b17023SJohn Marino case LE_EXPR:
3353e4b17023SJohn Marino opname = "<="; break;
3354e4b17023SJohn Marino case GE_EXPR:
3355e4b17023SJohn Marino opname = ">="; break;
3356e4b17023SJohn Marino case LT_EXPR:
3357e4b17023SJohn Marino opname = "<"; break;
3358e4b17023SJohn Marino case GT_EXPR:
3359e4b17023SJohn Marino opname = ">"; break;
3360e4b17023SJohn Marino case LSHIFT_EXPR:
3361e4b17023SJohn Marino opname = "<<"; break;
3362e4b17023SJohn Marino case RSHIFT_EXPR:
3363e4b17023SJohn Marino opname = ">>"; break;
3364e4b17023SJohn Marino case TRUNC_MOD_EXPR:
3365e4b17023SJohn Marino case FLOOR_MOD_EXPR:
3366e4b17023SJohn Marino opname = "%"; break;
3367e4b17023SJohn Marino case TRUNC_DIV_EXPR:
3368e4b17023SJohn Marino case FLOOR_DIV_EXPR:
3369e4b17023SJohn Marino opname = "/"; break;
3370e4b17023SJohn Marino case BIT_AND_EXPR:
3371e4b17023SJohn Marino opname = "&"; break;
3372e4b17023SJohn Marino case BIT_IOR_EXPR:
3373e4b17023SJohn Marino opname = "|"; break;
3374e4b17023SJohn Marino case TRUTH_ANDIF_EXPR:
3375e4b17023SJohn Marino opname = "&&"; break;
3376e4b17023SJohn Marino case TRUTH_ORIF_EXPR:
3377e4b17023SJohn Marino opname = "||"; break;
3378e4b17023SJohn Marino case BIT_XOR_EXPR:
3379e4b17023SJohn Marino opname = "^"; break;
3380e4b17023SJohn Marino default:
3381e4b17023SJohn Marino gcc_unreachable ();
3382e4b17023SJohn Marino }
3383e4b17023SJohn Marino error_at (location,
3384e4b17023SJohn Marino "invalid operands to binary %s (have %qT and %qT)", opname,
3385e4b17023SJohn Marino type0, type1);
3386e4b17023SJohn Marino }
3387e4b17023SJohn Marino
3388e4b17023SJohn Marino /* Subroutine of build_binary_op, used for comparison operations.
3389e4b17023SJohn Marino See if the operands have both been converted from subword integer types
3390e4b17023SJohn Marino and, if so, perhaps change them both back to their original type.
3391e4b17023SJohn Marino This function is also responsible for converting the two operands
3392e4b17023SJohn Marino to the proper common type for comparison.
3393e4b17023SJohn Marino
3394e4b17023SJohn Marino The arguments of this function are all pointers to local variables
3395e4b17023SJohn Marino of build_binary_op: OP0_PTR is &OP0, OP1_PTR is &OP1,
3396e4b17023SJohn Marino RESTYPE_PTR is &RESULT_TYPE and RESCODE_PTR is &RESULTCODE.
3397e4b17023SJohn Marino
3398e4b17023SJohn Marino If this function returns nonzero, it means that the comparison has
3399e4b17023SJohn Marino a constant value. What this function returns is an expression for
3400e4b17023SJohn Marino that value. */
3401e4b17023SJohn Marino
3402e4b17023SJohn Marino tree
shorten_compare(tree * op0_ptr,tree * op1_ptr,tree * restype_ptr,enum tree_code * rescode_ptr)3403e4b17023SJohn Marino shorten_compare (tree *op0_ptr, tree *op1_ptr, tree *restype_ptr,
3404e4b17023SJohn Marino enum tree_code *rescode_ptr)
3405e4b17023SJohn Marino {
3406e4b17023SJohn Marino tree type;
3407e4b17023SJohn Marino tree op0 = *op0_ptr;
3408e4b17023SJohn Marino tree op1 = *op1_ptr;
3409e4b17023SJohn Marino int unsignedp0, unsignedp1;
3410e4b17023SJohn Marino int real1, real2;
3411e4b17023SJohn Marino tree primop0, primop1;
3412e4b17023SJohn Marino enum tree_code code = *rescode_ptr;
3413e4b17023SJohn Marino
3414e4b17023SJohn Marino /* Throw away any conversions to wider types
3415e4b17023SJohn Marino already present in the operands. */
3416e4b17023SJohn Marino
3417e4b17023SJohn Marino primop0 = c_common_get_narrower (op0, &unsignedp0);
3418e4b17023SJohn Marino primop1 = c_common_get_narrower (op1, &unsignedp1);
3419e4b17023SJohn Marino
3420e4b17023SJohn Marino /* If primopN is first sign-extended from primopN's precision to opN's
3421e4b17023SJohn Marino precision, then zero-extended from opN's precision to
3422e4b17023SJohn Marino *restype_ptr precision, shortenings might be invalid. */
3423e4b17023SJohn Marino if (TYPE_PRECISION (TREE_TYPE (primop0)) < TYPE_PRECISION (TREE_TYPE (op0))
3424e4b17023SJohn Marino && TYPE_PRECISION (TREE_TYPE (op0)) < TYPE_PRECISION (*restype_ptr)
3425e4b17023SJohn Marino && !unsignedp0
3426e4b17023SJohn Marino && TYPE_UNSIGNED (TREE_TYPE (op0)))
3427e4b17023SJohn Marino primop0 = op0;
3428e4b17023SJohn Marino if (TYPE_PRECISION (TREE_TYPE (primop1)) < TYPE_PRECISION (TREE_TYPE (op1))
3429e4b17023SJohn Marino && TYPE_PRECISION (TREE_TYPE (op1)) < TYPE_PRECISION (*restype_ptr)
3430e4b17023SJohn Marino && !unsignedp1
3431e4b17023SJohn Marino && TYPE_UNSIGNED (TREE_TYPE (op1)))
3432e4b17023SJohn Marino primop1 = op1;
3433e4b17023SJohn Marino
3434e4b17023SJohn Marino /* Handle the case that OP0 does not *contain* a conversion
3435e4b17023SJohn Marino but it *requires* conversion to FINAL_TYPE. */
3436e4b17023SJohn Marino
3437e4b17023SJohn Marino if (op0 == primop0 && TREE_TYPE (op0) != *restype_ptr)
3438e4b17023SJohn Marino unsignedp0 = TYPE_UNSIGNED (TREE_TYPE (op0));
3439e4b17023SJohn Marino if (op1 == primop1 && TREE_TYPE (op1) != *restype_ptr)
3440e4b17023SJohn Marino unsignedp1 = TYPE_UNSIGNED (TREE_TYPE (op1));
3441e4b17023SJohn Marino
3442e4b17023SJohn Marino /* If one of the operands must be floated, we cannot optimize. */
3443e4b17023SJohn Marino real1 = TREE_CODE (TREE_TYPE (primop0)) == REAL_TYPE;
3444e4b17023SJohn Marino real2 = TREE_CODE (TREE_TYPE (primop1)) == REAL_TYPE;
3445e4b17023SJohn Marino
3446e4b17023SJohn Marino /* If first arg is constant, swap the args (changing operation
3447e4b17023SJohn Marino so value is preserved), for canonicalization. Don't do this if
3448e4b17023SJohn Marino the second arg is 0. */
3449e4b17023SJohn Marino
3450e4b17023SJohn Marino if (TREE_CONSTANT (primop0)
3451e4b17023SJohn Marino && !integer_zerop (primop1) && !real_zerop (primop1)
3452e4b17023SJohn Marino && !fixed_zerop (primop1))
3453e4b17023SJohn Marino {
3454e4b17023SJohn Marino tree tem = primop0;
3455e4b17023SJohn Marino int temi = unsignedp0;
3456e4b17023SJohn Marino primop0 = primop1;
3457e4b17023SJohn Marino primop1 = tem;
3458e4b17023SJohn Marino tem = op0;
3459e4b17023SJohn Marino op0 = op1;
3460e4b17023SJohn Marino op1 = tem;
3461e4b17023SJohn Marino *op0_ptr = op0;
3462e4b17023SJohn Marino *op1_ptr = op1;
3463e4b17023SJohn Marino unsignedp0 = unsignedp1;
3464e4b17023SJohn Marino unsignedp1 = temi;
3465e4b17023SJohn Marino temi = real1;
3466e4b17023SJohn Marino real1 = real2;
3467e4b17023SJohn Marino real2 = temi;
3468e4b17023SJohn Marino
3469e4b17023SJohn Marino switch (code)
3470e4b17023SJohn Marino {
3471e4b17023SJohn Marino case LT_EXPR:
3472e4b17023SJohn Marino code = GT_EXPR;
3473e4b17023SJohn Marino break;
3474e4b17023SJohn Marino case GT_EXPR:
3475e4b17023SJohn Marino code = LT_EXPR;
3476e4b17023SJohn Marino break;
3477e4b17023SJohn Marino case LE_EXPR:
3478e4b17023SJohn Marino code = GE_EXPR;
3479e4b17023SJohn Marino break;
3480e4b17023SJohn Marino case GE_EXPR:
3481e4b17023SJohn Marino code = LE_EXPR;
3482e4b17023SJohn Marino break;
3483e4b17023SJohn Marino default:
3484e4b17023SJohn Marino break;
3485e4b17023SJohn Marino }
3486e4b17023SJohn Marino *rescode_ptr = code;
3487e4b17023SJohn Marino }
3488e4b17023SJohn Marino
3489e4b17023SJohn Marino /* If comparing an integer against a constant more bits wide,
3490e4b17023SJohn Marino maybe we can deduce a value of 1 or 0 independent of the data.
3491e4b17023SJohn Marino Or else truncate the constant now
3492e4b17023SJohn Marino rather than extend the variable at run time.
3493e4b17023SJohn Marino
3494e4b17023SJohn Marino This is only interesting if the constant is the wider arg.
3495e4b17023SJohn Marino Also, it is not safe if the constant is unsigned and the
3496e4b17023SJohn Marino variable arg is signed, since in this case the variable
3497e4b17023SJohn Marino would be sign-extended and then regarded as unsigned.
3498e4b17023SJohn Marino Our technique fails in this case because the lowest/highest
3499e4b17023SJohn Marino possible unsigned results don't follow naturally from the
3500e4b17023SJohn Marino lowest/highest possible values of the variable operand.
3501e4b17023SJohn Marino For just EQ_EXPR and NE_EXPR there is another technique that
3502e4b17023SJohn Marino could be used: see if the constant can be faithfully represented
3503e4b17023SJohn Marino in the other operand's type, by truncating it and reextending it
3504e4b17023SJohn Marino and see if that preserves the constant's value. */
3505e4b17023SJohn Marino
3506e4b17023SJohn Marino if (!real1 && !real2
3507e4b17023SJohn Marino && TREE_CODE (TREE_TYPE (primop0)) != FIXED_POINT_TYPE
3508e4b17023SJohn Marino && TREE_CODE (primop1) == INTEGER_CST
3509e4b17023SJohn Marino && TYPE_PRECISION (TREE_TYPE (primop0)) < TYPE_PRECISION (*restype_ptr))
3510e4b17023SJohn Marino {
3511e4b17023SJohn Marino int min_gt, max_gt, min_lt, max_lt;
3512e4b17023SJohn Marino tree maxval, minval;
3513e4b17023SJohn Marino /* 1 if comparison is nominally unsigned. */
3514e4b17023SJohn Marino int unsignedp = TYPE_UNSIGNED (*restype_ptr);
3515e4b17023SJohn Marino tree val;
3516e4b17023SJohn Marino
3517e4b17023SJohn Marino type = c_common_signed_or_unsigned_type (unsignedp0,
3518e4b17023SJohn Marino TREE_TYPE (primop0));
3519e4b17023SJohn Marino
3520e4b17023SJohn Marino maxval = TYPE_MAX_VALUE (type);
3521e4b17023SJohn Marino minval = TYPE_MIN_VALUE (type);
3522e4b17023SJohn Marino
3523e4b17023SJohn Marino if (unsignedp && !unsignedp0)
3524e4b17023SJohn Marino *restype_ptr = c_common_signed_type (*restype_ptr);
3525e4b17023SJohn Marino
3526e4b17023SJohn Marino if (TREE_TYPE (primop1) != *restype_ptr)
3527e4b17023SJohn Marino {
3528e4b17023SJohn Marino /* Convert primop1 to target type, but do not introduce
3529e4b17023SJohn Marino additional overflow. We know primop1 is an int_cst. */
3530e4b17023SJohn Marino primop1 = force_fit_type_double (*restype_ptr,
3531e4b17023SJohn Marino tree_to_double_int (primop1),
3532e4b17023SJohn Marino 0, TREE_OVERFLOW (primop1));
3533e4b17023SJohn Marino }
3534e4b17023SJohn Marino if (type != *restype_ptr)
3535e4b17023SJohn Marino {
3536e4b17023SJohn Marino minval = convert (*restype_ptr, minval);
3537e4b17023SJohn Marino maxval = convert (*restype_ptr, maxval);
3538e4b17023SJohn Marino }
3539e4b17023SJohn Marino
3540e4b17023SJohn Marino if (unsignedp && unsignedp0)
3541e4b17023SJohn Marino {
3542e4b17023SJohn Marino min_gt = INT_CST_LT_UNSIGNED (primop1, minval);
3543e4b17023SJohn Marino max_gt = INT_CST_LT_UNSIGNED (primop1, maxval);
3544e4b17023SJohn Marino min_lt = INT_CST_LT_UNSIGNED (minval, primop1);
3545e4b17023SJohn Marino max_lt = INT_CST_LT_UNSIGNED (maxval, primop1);
3546e4b17023SJohn Marino }
3547e4b17023SJohn Marino else
3548e4b17023SJohn Marino {
3549e4b17023SJohn Marino min_gt = INT_CST_LT (primop1, minval);
3550e4b17023SJohn Marino max_gt = INT_CST_LT (primop1, maxval);
3551e4b17023SJohn Marino min_lt = INT_CST_LT (minval, primop1);
3552e4b17023SJohn Marino max_lt = INT_CST_LT (maxval, primop1);
3553e4b17023SJohn Marino }
3554e4b17023SJohn Marino
3555e4b17023SJohn Marino val = 0;
3556e4b17023SJohn Marino /* This used to be a switch, but Genix compiler can't handle that. */
3557e4b17023SJohn Marino if (code == NE_EXPR)
3558e4b17023SJohn Marino {
3559e4b17023SJohn Marino if (max_lt || min_gt)
3560e4b17023SJohn Marino val = truthvalue_true_node;
3561e4b17023SJohn Marino }
3562e4b17023SJohn Marino else if (code == EQ_EXPR)
3563e4b17023SJohn Marino {
3564e4b17023SJohn Marino if (max_lt || min_gt)
3565e4b17023SJohn Marino val = truthvalue_false_node;
3566e4b17023SJohn Marino }
3567e4b17023SJohn Marino else if (code == LT_EXPR)
3568e4b17023SJohn Marino {
3569e4b17023SJohn Marino if (max_lt)
3570e4b17023SJohn Marino val = truthvalue_true_node;
3571e4b17023SJohn Marino if (!min_lt)
3572e4b17023SJohn Marino val = truthvalue_false_node;
3573e4b17023SJohn Marino }
3574e4b17023SJohn Marino else if (code == GT_EXPR)
3575e4b17023SJohn Marino {
3576e4b17023SJohn Marino if (min_gt)
3577e4b17023SJohn Marino val = truthvalue_true_node;
3578e4b17023SJohn Marino if (!max_gt)
3579e4b17023SJohn Marino val = truthvalue_false_node;
3580e4b17023SJohn Marino }
3581e4b17023SJohn Marino else if (code == LE_EXPR)
3582e4b17023SJohn Marino {
3583e4b17023SJohn Marino if (!max_gt)
3584e4b17023SJohn Marino val = truthvalue_true_node;
3585e4b17023SJohn Marino if (min_gt)
3586e4b17023SJohn Marino val = truthvalue_false_node;
3587e4b17023SJohn Marino }
3588e4b17023SJohn Marino else if (code == GE_EXPR)
3589e4b17023SJohn Marino {
3590e4b17023SJohn Marino if (!min_lt)
3591e4b17023SJohn Marino val = truthvalue_true_node;
3592e4b17023SJohn Marino if (max_lt)
3593e4b17023SJohn Marino val = truthvalue_false_node;
3594e4b17023SJohn Marino }
3595e4b17023SJohn Marino
3596e4b17023SJohn Marino /* If primop0 was sign-extended and unsigned comparison specd,
3597e4b17023SJohn Marino we did a signed comparison above using the signed type bounds.
3598e4b17023SJohn Marino But the comparison we output must be unsigned.
3599e4b17023SJohn Marino
3600e4b17023SJohn Marino Also, for inequalities, VAL is no good; but if the signed
3601e4b17023SJohn Marino comparison had *any* fixed result, it follows that the
3602e4b17023SJohn Marino unsigned comparison just tests the sign in reverse
3603e4b17023SJohn Marino (positive values are LE, negative ones GE).
3604e4b17023SJohn Marino So we can generate an unsigned comparison
3605e4b17023SJohn Marino against an extreme value of the signed type. */
3606e4b17023SJohn Marino
3607e4b17023SJohn Marino if (unsignedp && !unsignedp0)
3608e4b17023SJohn Marino {
3609e4b17023SJohn Marino if (val != 0)
3610e4b17023SJohn Marino switch (code)
3611e4b17023SJohn Marino {
3612e4b17023SJohn Marino case LT_EXPR:
3613e4b17023SJohn Marino case GE_EXPR:
3614e4b17023SJohn Marino primop1 = TYPE_MIN_VALUE (type);
3615e4b17023SJohn Marino val = 0;
3616e4b17023SJohn Marino break;
3617e4b17023SJohn Marino
3618e4b17023SJohn Marino case LE_EXPR:
3619e4b17023SJohn Marino case GT_EXPR:
3620e4b17023SJohn Marino primop1 = TYPE_MAX_VALUE (type);
3621e4b17023SJohn Marino val = 0;
3622e4b17023SJohn Marino break;
3623e4b17023SJohn Marino
3624e4b17023SJohn Marino default:
3625e4b17023SJohn Marino break;
3626e4b17023SJohn Marino }
3627e4b17023SJohn Marino type = c_common_unsigned_type (type);
3628e4b17023SJohn Marino }
3629e4b17023SJohn Marino
3630e4b17023SJohn Marino if (TREE_CODE (primop0) != INTEGER_CST)
3631e4b17023SJohn Marino {
3632e4b17023SJohn Marino if (val == truthvalue_false_node)
3633e4b17023SJohn Marino warning (OPT_Wtype_limits, "comparison is always false due to limited range of data type");
3634e4b17023SJohn Marino if (val == truthvalue_true_node)
3635e4b17023SJohn Marino warning (OPT_Wtype_limits, "comparison is always true due to limited range of data type");
3636e4b17023SJohn Marino }
3637e4b17023SJohn Marino
3638e4b17023SJohn Marino if (val != 0)
3639e4b17023SJohn Marino {
3640e4b17023SJohn Marino /* Don't forget to evaluate PRIMOP0 if it has side effects. */
3641e4b17023SJohn Marino if (TREE_SIDE_EFFECTS (primop0))
3642e4b17023SJohn Marino return build2 (COMPOUND_EXPR, TREE_TYPE (val), primop0, val);
3643e4b17023SJohn Marino return val;
3644e4b17023SJohn Marino }
3645e4b17023SJohn Marino
3646e4b17023SJohn Marino /* Value is not predetermined, but do the comparison
3647e4b17023SJohn Marino in the type of the operand that is not constant.
3648e4b17023SJohn Marino TYPE is already properly set. */
3649e4b17023SJohn Marino }
3650e4b17023SJohn Marino
3651e4b17023SJohn Marino /* If either arg is decimal float and the other is float, find the
3652e4b17023SJohn Marino proper common type to use for comparison. */
3653e4b17023SJohn Marino else if (real1 && real2
3654e4b17023SJohn Marino && (DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop0)))
3655e4b17023SJohn Marino || DECIMAL_FLOAT_MODE_P (TYPE_MODE (TREE_TYPE (primop1)))))
3656e4b17023SJohn Marino type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1));
3657e4b17023SJohn Marino
3658e4b17023SJohn Marino else if (real1 && real2
3659e4b17023SJohn Marino && (TYPE_PRECISION (TREE_TYPE (primop0))
3660e4b17023SJohn Marino == TYPE_PRECISION (TREE_TYPE (primop1))))
3661e4b17023SJohn Marino type = TREE_TYPE (primop0);
3662e4b17023SJohn Marino
3663e4b17023SJohn Marino /* If args' natural types are both narrower than nominal type
3664e4b17023SJohn Marino and both extend in the same manner, compare them
3665e4b17023SJohn Marino in the type of the wider arg.
3666e4b17023SJohn Marino Otherwise must actually extend both to the nominal
3667e4b17023SJohn Marino common type lest different ways of extending
3668e4b17023SJohn Marino alter the result.
3669e4b17023SJohn Marino (eg, (short)-1 == (unsigned short)-1 should be 0.) */
3670e4b17023SJohn Marino
3671e4b17023SJohn Marino else if (unsignedp0 == unsignedp1 && real1 == real2
3672e4b17023SJohn Marino && TYPE_PRECISION (TREE_TYPE (primop0)) < TYPE_PRECISION (*restype_ptr)
3673e4b17023SJohn Marino && TYPE_PRECISION (TREE_TYPE (primop1)) < TYPE_PRECISION (*restype_ptr))
3674e4b17023SJohn Marino {
3675e4b17023SJohn Marino type = common_type (TREE_TYPE (primop0), TREE_TYPE (primop1));
3676e4b17023SJohn Marino type = c_common_signed_or_unsigned_type (unsignedp0
3677e4b17023SJohn Marino || TYPE_UNSIGNED (*restype_ptr),
3678e4b17023SJohn Marino type);
3679e4b17023SJohn Marino /* Make sure shorter operand is extended the right way
3680e4b17023SJohn Marino to match the longer operand. */
3681e4b17023SJohn Marino primop0
3682e4b17023SJohn Marino = convert (c_common_signed_or_unsigned_type (unsignedp0,
3683e4b17023SJohn Marino TREE_TYPE (primop0)),
3684e4b17023SJohn Marino primop0);
3685e4b17023SJohn Marino primop1
3686e4b17023SJohn Marino = convert (c_common_signed_or_unsigned_type (unsignedp1,
3687e4b17023SJohn Marino TREE_TYPE (primop1)),
3688e4b17023SJohn Marino primop1);
3689e4b17023SJohn Marino }
3690e4b17023SJohn Marino else
3691e4b17023SJohn Marino {
3692e4b17023SJohn Marino /* Here we must do the comparison on the nominal type
3693e4b17023SJohn Marino using the args exactly as we received them. */
3694e4b17023SJohn Marino type = *restype_ptr;
3695e4b17023SJohn Marino primop0 = op0;
3696e4b17023SJohn Marino primop1 = op1;
3697e4b17023SJohn Marino
3698e4b17023SJohn Marino if (!real1 && !real2 && integer_zerop (primop1)
3699e4b17023SJohn Marino && TYPE_UNSIGNED (*restype_ptr))
3700e4b17023SJohn Marino {
3701e4b17023SJohn Marino tree value = 0;
3702e4b17023SJohn Marino switch (code)
3703e4b17023SJohn Marino {
3704e4b17023SJohn Marino case GE_EXPR:
3705e4b17023SJohn Marino /* All unsigned values are >= 0, so we warn. However,
3706e4b17023SJohn Marino if OP0 is a constant that is >= 0, the signedness of
3707e4b17023SJohn Marino the comparison isn't an issue, so suppress the
3708e4b17023SJohn Marino warning. */
3709e4b17023SJohn Marino if (warn_type_limits && !in_system_header
3710e4b17023SJohn Marino && !(TREE_CODE (primop0) == INTEGER_CST
3711e4b17023SJohn Marino && !TREE_OVERFLOW (convert (c_common_signed_type (type),
3712e4b17023SJohn Marino primop0))))
3713e4b17023SJohn Marino warning (OPT_Wtype_limits,
3714e4b17023SJohn Marino "comparison of unsigned expression >= 0 is always true");
3715e4b17023SJohn Marino value = truthvalue_true_node;
3716e4b17023SJohn Marino break;
3717e4b17023SJohn Marino
3718e4b17023SJohn Marino case LT_EXPR:
3719e4b17023SJohn Marino if (warn_type_limits && !in_system_header
3720e4b17023SJohn Marino && !(TREE_CODE (primop0) == INTEGER_CST
3721e4b17023SJohn Marino && !TREE_OVERFLOW (convert (c_common_signed_type (type),
3722e4b17023SJohn Marino primop0))))
3723e4b17023SJohn Marino warning (OPT_Wtype_limits,
3724e4b17023SJohn Marino "comparison of unsigned expression < 0 is always false");
3725e4b17023SJohn Marino value = truthvalue_false_node;
3726e4b17023SJohn Marino break;
3727e4b17023SJohn Marino
3728e4b17023SJohn Marino default:
3729e4b17023SJohn Marino break;
3730e4b17023SJohn Marino }
3731e4b17023SJohn Marino
3732e4b17023SJohn Marino if (value != 0)
3733e4b17023SJohn Marino {
3734e4b17023SJohn Marino /* Don't forget to evaluate PRIMOP0 if it has side effects. */
3735e4b17023SJohn Marino if (TREE_SIDE_EFFECTS (primop0))
3736e4b17023SJohn Marino return build2 (COMPOUND_EXPR, TREE_TYPE (value),
3737e4b17023SJohn Marino primop0, value);
3738e4b17023SJohn Marino return value;
3739e4b17023SJohn Marino }
3740e4b17023SJohn Marino }
3741e4b17023SJohn Marino }
3742e4b17023SJohn Marino
3743e4b17023SJohn Marino *op0_ptr = convert (type, primop0);
3744e4b17023SJohn Marino *op1_ptr = convert (type, primop1);
3745e4b17023SJohn Marino
3746e4b17023SJohn Marino *restype_ptr = truthvalue_type_node;
3747e4b17023SJohn Marino
3748e4b17023SJohn Marino return 0;
3749e4b17023SJohn Marino }
3750e4b17023SJohn Marino
3751e4b17023SJohn Marino /* Return a tree for the sum or difference (RESULTCODE says which)
3752e4b17023SJohn Marino of pointer PTROP and integer INTOP. */
3753e4b17023SJohn Marino
3754e4b17023SJohn Marino tree
pointer_int_sum(location_t loc,enum tree_code resultcode,tree ptrop,tree intop)3755e4b17023SJohn Marino pointer_int_sum (location_t loc, enum tree_code resultcode,
3756e4b17023SJohn Marino tree ptrop, tree intop)
3757e4b17023SJohn Marino {
3758e4b17023SJohn Marino tree size_exp, ret;
3759e4b17023SJohn Marino
3760e4b17023SJohn Marino /* The result is a pointer of the same type that is being added. */
3761e4b17023SJohn Marino tree result_type = TREE_TYPE (ptrop);
3762e4b17023SJohn Marino
3763e4b17023SJohn Marino if (TREE_CODE (TREE_TYPE (result_type)) == VOID_TYPE)
3764e4b17023SJohn Marino {
3765e4b17023SJohn Marino pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
3766e4b17023SJohn Marino "pointer of type %<void *%> used in arithmetic");
3767e4b17023SJohn Marino size_exp = integer_one_node;
3768e4b17023SJohn Marino }
3769e4b17023SJohn Marino else if (TREE_CODE (TREE_TYPE (result_type)) == FUNCTION_TYPE)
3770e4b17023SJohn Marino {
3771e4b17023SJohn Marino pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
3772e4b17023SJohn Marino "pointer to a function used in arithmetic");
3773e4b17023SJohn Marino size_exp = integer_one_node;
3774e4b17023SJohn Marino }
3775e4b17023SJohn Marino else if (TREE_CODE (TREE_TYPE (result_type)) == METHOD_TYPE)
3776e4b17023SJohn Marino {
3777e4b17023SJohn Marino pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
3778e4b17023SJohn Marino "pointer to member function used in arithmetic");
3779e4b17023SJohn Marino size_exp = integer_one_node;
3780e4b17023SJohn Marino }
3781e4b17023SJohn Marino else
3782e4b17023SJohn Marino size_exp = size_in_bytes (TREE_TYPE (result_type));
3783e4b17023SJohn Marino
3784e4b17023SJohn Marino /* We are manipulating pointer values, so we don't need to warn
3785e4b17023SJohn Marino about relying on undefined signed overflow. We disable the
3786e4b17023SJohn Marino warning here because we use integer types so fold won't know that
3787e4b17023SJohn Marino they are really pointers. */
3788e4b17023SJohn Marino fold_defer_overflow_warnings ();
3789e4b17023SJohn Marino
3790e4b17023SJohn Marino /* If what we are about to multiply by the size of the elements
3791e4b17023SJohn Marino contains a constant term, apply distributive law
3792e4b17023SJohn Marino and multiply that constant term separately.
3793e4b17023SJohn Marino This helps produce common subexpressions. */
3794e4b17023SJohn Marino if ((TREE_CODE (intop) == PLUS_EXPR || TREE_CODE (intop) == MINUS_EXPR)
3795e4b17023SJohn Marino && !TREE_CONSTANT (intop)
3796e4b17023SJohn Marino && TREE_CONSTANT (TREE_OPERAND (intop, 1))
3797e4b17023SJohn Marino && TREE_CONSTANT (size_exp)
3798e4b17023SJohn Marino /* If the constant comes from pointer subtraction,
3799e4b17023SJohn Marino skip this optimization--it would cause an error. */
3800e4b17023SJohn Marino && TREE_CODE (TREE_TYPE (TREE_OPERAND (intop, 0))) == INTEGER_TYPE
3801e4b17023SJohn Marino /* If the constant is unsigned, and smaller than the pointer size,
3802e4b17023SJohn Marino then we must skip this optimization. This is because it could cause
3803e4b17023SJohn Marino an overflow error if the constant is negative but INTOP is not. */
3804e4b17023SJohn Marino && (!TYPE_UNSIGNED (TREE_TYPE (intop))
3805e4b17023SJohn Marino || (TYPE_PRECISION (TREE_TYPE (intop))
3806e4b17023SJohn Marino == TYPE_PRECISION (TREE_TYPE (ptrop)))))
3807e4b17023SJohn Marino {
3808e4b17023SJohn Marino enum tree_code subcode = resultcode;
3809e4b17023SJohn Marino tree int_type = TREE_TYPE (intop);
3810e4b17023SJohn Marino if (TREE_CODE (intop) == MINUS_EXPR)
3811e4b17023SJohn Marino subcode = (subcode == PLUS_EXPR ? MINUS_EXPR : PLUS_EXPR);
3812e4b17023SJohn Marino /* Convert both subexpression types to the type of intop,
3813e4b17023SJohn Marino because weird cases involving pointer arithmetic
3814e4b17023SJohn Marino can result in a sum or difference with different type args. */
3815e4b17023SJohn Marino ptrop = build_binary_op (EXPR_LOCATION (TREE_OPERAND (intop, 1)),
3816e4b17023SJohn Marino subcode, ptrop,
3817e4b17023SJohn Marino convert (int_type, TREE_OPERAND (intop, 1)), 1);
3818e4b17023SJohn Marino intop = convert (int_type, TREE_OPERAND (intop, 0));
3819e4b17023SJohn Marino }
3820e4b17023SJohn Marino
3821e4b17023SJohn Marino /* Convert the integer argument to a type the same size as sizetype
3822e4b17023SJohn Marino so the multiply won't overflow spuriously. */
3823e4b17023SJohn Marino if (TYPE_PRECISION (TREE_TYPE (intop)) != TYPE_PRECISION (sizetype)
3824e4b17023SJohn Marino || TYPE_UNSIGNED (TREE_TYPE (intop)) != TYPE_UNSIGNED (sizetype))
3825e4b17023SJohn Marino intop = convert (c_common_type_for_size (TYPE_PRECISION (sizetype),
3826e4b17023SJohn Marino TYPE_UNSIGNED (sizetype)), intop);
3827e4b17023SJohn Marino
3828e4b17023SJohn Marino /* Replace the integer argument with a suitable product by the object size.
3829e4b17023SJohn Marino Do this multiplication as signed, then convert to the appropriate type
3830e4b17023SJohn Marino for the pointer operation and disregard an overflow that occured only
3831e4b17023SJohn Marino because of the sign-extension change in the latter conversion. */
3832e4b17023SJohn Marino {
3833e4b17023SJohn Marino tree t = build_binary_op (loc,
3834e4b17023SJohn Marino MULT_EXPR, intop,
3835e4b17023SJohn Marino convert (TREE_TYPE (intop), size_exp), 1);
3836e4b17023SJohn Marino intop = convert (sizetype, t);
3837e4b17023SJohn Marino if (TREE_OVERFLOW_P (intop) && !TREE_OVERFLOW (t))
3838e4b17023SJohn Marino intop = build_int_cst_wide (TREE_TYPE (intop), TREE_INT_CST_LOW (intop),
3839e4b17023SJohn Marino TREE_INT_CST_HIGH (intop));
3840e4b17023SJohn Marino }
3841e4b17023SJohn Marino
3842e4b17023SJohn Marino /* Create the sum or difference. */
3843e4b17023SJohn Marino if (resultcode == MINUS_EXPR)
3844e4b17023SJohn Marino intop = fold_build1_loc (loc, NEGATE_EXPR, sizetype, intop);
3845e4b17023SJohn Marino
3846e4b17023SJohn Marino ret = fold_build_pointer_plus_loc (loc, ptrop, intop);
3847e4b17023SJohn Marino
3848e4b17023SJohn Marino fold_undefer_and_ignore_overflow_warnings ();
3849e4b17023SJohn Marino
3850e4b17023SJohn Marino return ret;
3851e4b17023SJohn Marino }
3852e4b17023SJohn Marino
3853e4b17023SJohn Marino /* Wrap a C_MAYBE_CONST_EXPR around an expression that is fully folded
3854e4b17023SJohn Marino and if NON_CONST is known not to be permitted in an evaluated part
3855e4b17023SJohn Marino of a constant expression. */
3856e4b17023SJohn Marino
3857e4b17023SJohn Marino tree
c_wrap_maybe_const(tree expr,bool non_const)3858e4b17023SJohn Marino c_wrap_maybe_const (tree expr, bool non_const)
3859e4b17023SJohn Marino {
3860e4b17023SJohn Marino bool nowarning = TREE_NO_WARNING (expr);
3861e4b17023SJohn Marino location_t loc = EXPR_LOCATION (expr);
3862e4b17023SJohn Marino
3863e4b17023SJohn Marino /* This should never be called for C++. */
3864e4b17023SJohn Marino if (c_dialect_cxx ())
3865e4b17023SJohn Marino gcc_unreachable ();
3866e4b17023SJohn Marino
3867e4b17023SJohn Marino /* The result of folding may have a NOP_EXPR to set TREE_NO_WARNING. */
3868e4b17023SJohn Marino STRIP_TYPE_NOPS (expr);
3869e4b17023SJohn Marino expr = build2 (C_MAYBE_CONST_EXPR, TREE_TYPE (expr), NULL, expr);
3870e4b17023SJohn Marino C_MAYBE_CONST_EXPR_NON_CONST (expr) = non_const;
3871e4b17023SJohn Marino if (nowarning)
3872e4b17023SJohn Marino TREE_NO_WARNING (expr) = 1;
3873e4b17023SJohn Marino protected_set_expr_location (expr, loc);
3874e4b17023SJohn Marino
3875e4b17023SJohn Marino return expr;
3876e4b17023SJohn Marino }
3877e4b17023SJohn Marino
3878e4b17023SJohn Marino /* Wrap a SAVE_EXPR around EXPR, if appropriate. Like save_expr, but
3879e4b17023SJohn Marino for C folds the inside expression and wraps a C_MAYBE_CONST_EXPR
3880e4b17023SJohn Marino around the SAVE_EXPR if needed so that c_fully_fold does not need
3881e4b17023SJohn Marino to look inside SAVE_EXPRs. */
3882e4b17023SJohn Marino
3883e4b17023SJohn Marino tree
c_save_expr(tree expr)3884e4b17023SJohn Marino c_save_expr (tree expr)
3885e4b17023SJohn Marino {
3886e4b17023SJohn Marino bool maybe_const = true;
3887e4b17023SJohn Marino if (c_dialect_cxx ())
3888e4b17023SJohn Marino return save_expr (expr);
3889e4b17023SJohn Marino expr = c_fully_fold (expr, false, &maybe_const);
3890e4b17023SJohn Marino expr = save_expr (expr);
3891e4b17023SJohn Marino if (!maybe_const)
3892e4b17023SJohn Marino expr = c_wrap_maybe_const (expr, true);
3893e4b17023SJohn Marino return expr;
3894e4b17023SJohn Marino }
3895e4b17023SJohn Marino
3896e4b17023SJohn Marino /* Return whether EXPR is a declaration whose address can never be
3897e4b17023SJohn Marino NULL. */
3898e4b17023SJohn Marino
3899e4b17023SJohn Marino bool
decl_with_nonnull_addr_p(const_tree expr)3900e4b17023SJohn Marino decl_with_nonnull_addr_p (const_tree expr)
3901e4b17023SJohn Marino {
3902e4b17023SJohn Marino return (DECL_P (expr)
3903e4b17023SJohn Marino && (TREE_CODE (expr) == PARM_DECL
3904e4b17023SJohn Marino || TREE_CODE (expr) == LABEL_DECL
3905e4b17023SJohn Marino || !DECL_WEAK (expr)));
3906e4b17023SJohn Marino }
3907e4b17023SJohn Marino
3908e4b17023SJohn Marino /* Prepare expr to be an argument of a TRUTH_NOT_EXPR,
3909e4b17023SJohn Marino or for an `if' or `while' statement or ?..: exp. It should already
3910e4b17023SJohn Marino have been validated to be of suitable type; otherwise, a bad
3911e4b17023SJohn Marino diagnostic may result.
3912e4b17023SJohn Marino
3913e4b17023SJohn Marino The EXPR is located at LOCATION.
3914e4b17023SJohn Marino
3915e4b17023SJohn Marino This preparation consists of taking the ordinary
3916e4b17023SJohn Marino representation of an expression expr and producing a valid tree
3917e4b17023SJohn Marino boolean expression describing whether expr is nonzero. We could
3918e4b17023SJohn Marino simply always do build_binary_op (NE_EXPR, expr, truthvalue_false_node, 1),
3919e4b17023SJohn Marino but we optimize comparisons, &&, ||, and !.
3920e4b17023SJohn Marino
3921e4b17023SJohn Marino The resulting type should always be `truthvalue_type_node'. */
3922e4b17023SJohn Marino
3923e4b17023SJohn Marino tree
c_common_truthvalue_conversion(location_t location,tree expr)3924e4b17023SJohn Marino c_common_truthvalue_conversion (location_t location, tree expr)
3925e4b17023SJohn Marino {
3926e4b17023SJohn Marino switch (TREE_CODE (expr))
3927e4b17023SJohn Marino {
3928e4b17023SJohn Marino case EQ_EXPR: case NE_EXPR: case UNEQ_EXPR: case LTGT_EXPR:
3929e4b17023SJohn Marino case LE_EXPR: case GE_EXPR: case LT_EXPR: case GT_EXPR:
3930e4b17023SJohn Marino case UNLE_EXPR: case UNGE_EXPR: case UNLT_EXPR: case UNGT_EXPR:
3931e4b17023SJohn Marino case ORDERED_EXPR: case UNORDERED_EXPR:
3932e4b17023SJohn Marino if (TREE_TYPE (expr) == truthvalue_type_node)
3933e4b17023SJohn Marino return expr;
3934e4b17023SJohn Marino expr = build2 (TREE_CODE (expr), truthvalue_type_node,
3935e4b17023SJohn Marino TREE_OPERAND (expr, 0), TREE_OPERAND (expr, 1));
3936e4b17023SJohn Marino goto ret;
3937e4b17023SJohn Marino
3938e4b17023SJohn Marino case TRUTH_ANDIF_EXPR:
3939e4b17023SJohn Marino case TRUTH_ORIF_EXPR:
3940e4b17023SJohn Marino case TRUTH_AND_EXPR:
3941e4b17023SJohn Marino case TRUTH_OR_EXPR:
3942e4b17023SJohn Marino case TRUTH_XOR_EXPR:
3943e4b17023SJohn Marino if (TREE_TYPE (expr) == truthvalue_type_node)
3944e4b17023SJohn Marino return expr;
3945e4b17023SJohn Marino expr = build2 (TREE_CODE (expr), truthvalue_type_node,
3946e4b17023SJohn Marino c_common_truthvalue_conversion (location,
3947e4b17023SJohn Marino TREE_OPERAND (expr, 0)),
3948e4b17023SJohn Marino c_common_truthvalue_conversion (location,
3949e4b17023SJohn Marino TREE_OPERAND (expr, 1)));
3950e4b17023SJohn Marino goto ret;
3951e4b17023SJohn Marino
3952e4b17023SJohn Marino case TRUTH_NOT_EXPR:
3953e4b17023SJohn Marino if (TREE_TYPE (expr) == truthvalue_type_node)
3954e4b17023SJohn Marino return expr;
3955e4b17023SJohn Marino expr = build1 (TREE_CODE (expr), truthvalue_type_node,
3956e4b17023SJohn Marino c_common_truthvalue_conversion (location,
3957e4b17023SJohn Marino TREE_OPERAND (expr, 0)));
3958e4b17023SJohn Marino goto ret;
3959e4b17023SJohn Marino
3960e4b17023SJohn Marino case ERROR_MARK:
3961e4b17023SJohn Marino return expr;
3962e4b17023SJohn Marino
3963e4b17023SJohn Marino case INTEGER_CST:
3964e4b17023SJohn Marino return integer_zerop (expr) ? truthvalue_false_node
3965e4b17023SJohn Marino : truthvalue_true_node;
3966e4b17023SJohn Marino
3967e4b17023SJohn Marino case REAL_CST:
3968e4b17023SJohn Marino return real_compare (NE_EXPR, &TREE_REAL_CST (expr), &dconst0)
3969e4b17023SJohn Marino ? truthvalue_true_node
3970e4b17023SJohn Marino : truthvalue_false_node;
3971e4b17023SJohn Marino
3972e4b17023SJohn Marino case FIXED_CST:
3973e4b17023SJohn Marino return fixed_compare (NE_EXPR, &TREE_FIXED_CST (expr),
3974e4b17023SJohn Marino &FCONST0 (TYPE_MODE (TREE_TYPE (expr))))
3975e4b17023SJohn Marino ? truthvalue_true_node
3976e4b17023SJohn Marino : truthvalue_false_node;
3977e4b17023SJohn Marino
3978e4b17023SJohn Marino case FUNCTION_DECL:
3979e4b17023SJohn Marino expr = build_unary_op (location, ADDR_EXPR, expr, 0);
3980e4b17023SJohn Marino /* Fall through. */
3981e4b17023SJohn Marino
3982e4b17023SJohn Marino case ADDR_EXPR:
3983e4b17023SJohn Marino {
3984e4b17023SJohn Marino tree inner = TREE_OPERAND (expr, 0);
3985e4b17023SJohn Marino if (decl_with_nonnull_addr_p (inner))
3986e4b17023SJohn Marino {
3987e4b17023SJohn Marino /* Common Ada/Pascal programmer's mistake. */
3988e4b17023SJohn Marino warning_at (location,
3989e4b17023SJohn Marino OPT_Waddress,
3990e4b17023SJohn Marino "the address of %qD will always evaluate as %<true%>",
3991e4b17023SJohn Marino inner);
3992e4b17023SJohn Marino return truthvalue_true_node;
3993e4b17023SJohn Marino }
3994e4b17023SJohn Marino break;
3995e4b17023SJohn Marino }
3996e4b17023SJohn Marino
3997e4b17023SJohn Marino case COMPLEX_EXPR:
3998e4b17023SJohn Marino expr = build_binary_op (EXPR_LOCATION (expr),
3999e4b17023SJohn Marino (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1))
4000e4b17023SJohn Marino ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
4001e4b17023SJohn Marino c_common_truthvalue_conversion (location,
4002e4b17023SJohn Marino TREE_OPERAND (expr, 0)),
4003e4b17023SJohn Marino c_common_truthvalue_conversion (location,
4004e4b17023SJohn Marino TREE_OPERAND (expr, 1)),
4005e4b17023SJohn Marino 0);
4006e4b17023SJohn Marino goto ret;
4007e4b17023SJohn Marino
4008e4b17023SJohn Marino case NEGATE_EXPR:
4009e4b17023SJohn Marino case ABS_EXPR:
4010e4b17023SJohn Marino case FLOAT_EXPR:
4011e4b17023SJohn Marino case EXCESS_PRECISION_EXPR:
4012e4b17023SJohn Marino /* These don't change whether an object is nonzero or zero. */
4013e4b17023SJohn Marino return c_common_truthvalue_conversion (location, TREE_OPERAND (expr, 0));
4014e4b17023SJohn Marino
4015e4b17023SJohn Marino case LROTATE_EXPR:
4016e4b17023SJohn Marino case RROTATE_EXPR:
4017e4b17023SJohn Marino /* These don't change whether an object is zero or nonzero, but
4018e4b17023SJohn Marino we can't ignore them if their second arg has side-effects. */
4019e4b17023SJohn Marino if (TREE_SIDE_EFFECTS (TREE_OPERAND (expr, 1)))
4020e4b17023SJohn Marino {
4021e4b17023SJohn Marino expr = build2 (COMPOUND_EXPR, truthvalue_type_node,
4022e4b17023SJohn Marino TREE_OPERAND (expr, 1),
4023e4b17023SJohn Marino c_common_truthvalue_conversion
4024e4b17023SJohn Marino (location, TREE_OPERAND (expr, 0)));
4025e4b17023SJohn Marino goto ret;
4026e4b17023SJohn Marino }
4027e4b17023SJohn Marino else
4028e4b17023SJohn Marino return c_common_truthvalue_conversion (location,
4029e4b17023SJohn Marino TREE_OPERAND (expr, 0));
4030e4b17023SJohn Marino
4031e4b17023SJohn Marino case COND_EXPR:
4032e4b17023SJohn Marino /* Distribute the conversion into the arms of a COND_EXPR. */
4033e4b17023SJohn Marino if (c_dialect_cxx ())
4034e4b17023SJohn Marino {
4035e4b17023SJohn Marino tree op1 = TREE_OPERAND (expr, 1);
4036e4b17023SJohn Marino tree op2 = TREE_OPERAND (expr, 2);
4037e4b17023SJohn Marino /* In C++ one of the arms might have void type if it is throw. */
4038e4b17023SJohn Marino if (!VOID_TYPE_P (TREE_TYPE (op1)))
4039e4b17023SJohn Marino op1 = c_common_truthvalue_conversion (location, op1);
4040e4b17023SJohn Marino if (!VOID_TYPE_P (TREE_TYPE (op2)))
4041e4b17023SJohn Marino op2 = c_common_truthvalue_conversion (location, op2);
4042e4b17023SJohn Marino expr = fold_build3_loc (location, COND_EXPR, truthvalue_type_node,
4043e4b17023SJohn Marino TREE_OPERAND (expr, 0), op1, op2);
4044e4b17023SJohn Marino goto ret;
4045e4b17023SJohn Marino }
4046e4b17023SJohn Marino else
4047e4b17023SJohn Marino {
4048e4b17023SJohn Marino /* Folding will happen later for C. */
4049e4b17023SJohn Marino expr = build3 (COND_EXPR, truthvalue_type_node,
4050e4b17023SJohn Marino TREE_OPERAND (expr, 0),
4051e4b17023SJohn Marino c_common_truthvalue_conversion (location,
4052e4b17023SJohn Marino TREE_OPERAND (expr, 1)),
4053e4b17023SJohn Marino c_common_truthvalue_conversion (location,
4054e4b17023SJohn Marino TREE_OPERAND (expr, 2)));
4055e4b17023SJohn Marino goto ret;
4056e4b17023SJohn Marino }
4057e4b17023SJohn Marino
4058e4b17023SJohn Marino CASE_CONVERT:
4059e4b17023SJohn Marino {
4060e4b17023SJohn Marino tree totype = TREE_TYPE (expr);
4061e4b17023SJohn Marino tree fromtype = TREE_TYPE (TREE_OPERAND (expr, 0));
4062e4b17023SJohn Marino
4063e4b17023SJohn Marino /* Don't cancel the effect of a CONVERT_EXPR from a REFERENCE_TYPE,
4064e4b17023SJohn Marino since that affects how `default_conversion' will behave. */
4065e4b17023SJohn Marino if (TREE_CODE (totype) == REFERENCE_TYPE
4066e4b17023SJohn Marino || TREE_CODE (fromtype) == REFERENCE_TYPE)
4067e4b17023SJohn Marino break;
4068e4b17023SJohn Marino /* Don't strip a conversion from C++0x scoped enum, since they
4069e4b17023SJohn Marino don't implicitly convert to other types. */
4070e4b17023SJohn Marino if (TREE_CODE (fromtype) == ENUMERAL_TYPE
4071e4b17023SJohn Marino && ENUM_IS_SCOPED (fromtype))
4072e4b17023SJohn Marino break;
4073e4b17023SJohn Marino /* If this isn't narrowing the argument, we can ignore it. */
4074e4b17023SJohn Marino if (TYPE_PRECISION (totype) >= TYPE_PRECISION (fromtype))
4075e4b17023SJohn Marino return c_common_truthvalue_conversion (location,
4076e4b17023SJohn Marino TREE_OPERAND (expr, 0));
4077e4b17023SJohn Marino }
4078e4b17023SJohn Marino break;
4079e4b17023SJohn Marino
4080e4b17023SJohn Marino case MODIFY_EXPR:
4081e4b17023SJohn Marino if (!TREE_NO_WARNING (expr)
4082e4b17023SJohn Marino && warn_parentheses)
4083e4b17023SJohn Marino {
4084e4b17023SJohn Marino warning (OPT_Wparentheses,
4085e4b17023SJohn Marino "suggest parentheses around assignment used as truth value");
4086e4b17023SJohn Marino TREE_NO_WARNING (expr) = 1;
4087e4b17023SJohn Marino }
4088e4b17023SJohn Marino break;
4089e4b17023SJohn Marino
4090e4b17023SJohn Marino default:
4091e4b17023SJohn Marino break;
4092e4b17023SJohn Marino }
4093e4b17023SJohn Marino
4094e4b17023SJohn Marino if (TREE_CODE (TREE_TYPE (expr)) == COMPLEX_TYPE)
4095e4b17023SJohn Marino {
4096e4b17023SJohn Marino tree t = (in_late_binary_op ? save_expr (expr) : c_save_expr (expr));
4097e4b17023SJohn Marino expr = (build_binary_op
4098e4b17023SJohn Marino (EXPR_LOCATION (expr),
4099e4b17023SJohn Marino (TREE_SIDE_EFFECTS (expr)
4100e4b17023SJohn Marino ? TRUTH_OR_EXPR : TRUTH_ORIF_EXPR),
4101e4b17023SJohn Marino c_common_truthvalue_conversion
4102e4b17023SJohn Marino (location,
4103e4b17023SJohn Marino build_unary_op (location, REALPART_EXPR, t, 0)),
4104e4b17023SJohn Marino c_common_truthvalue_conversion
4105e4b17023SJohn Marino (location,
4106e4b17023SJohn Marino build_unary_op (location, IMAGPART_EXPR, t, 0)),
4107e4b17023SJohn Marino 0));
4108e4b17023SJohn Marino goto ret;
4109e4b17023SJohn Marino }
4110e4b17023SJohn Marino
4111e4b17023SJohn Marino if (TREE_CODE (TREE_TYPE (expr)) == FIXED_POINT_TYPE)
4112e4b17023SJohn Marino {
4113e4b17023SJohn Marino tree fixed_zero_node = build_fixed (TREE_TYPE (expr),
4114e4b17023SJohn Marino FCONST0 (TYPE_MODE
4115e4b17023SJohn Marino (TREE_TYPE (expr))));
4116e4b17023SJohn Marino return build_binary_op (location, NE_EXPR, expr, fixed_zero_node, 1);
4117e4b17023SJohn Marino }
4118e4b17023SJohn Marino else
4119e4b17023SJohn Marino return build_binary_op (location, NE_EXPR, expr, integer_zero_node, 1);
4120e4b17023SJohn Marino
4121e4b17023SJohn Marino ret:
4122e4b17023SJohn Marino protected_set_expr_location (expr, location);
4123e4b17023SJohn Marino return expr;
4124e4b17023SJohn Marino }
4125e4b17023SJohn Marino
4126e4b17023SJohn Marino static void def_builtin_1 (enum built_in_function fncode,
4127e4b17023SJohn Marino const char *name,
4128e4b17023SJohn Marino enum built_in_class fnclass,
4129e4b17023SJohn Marino tree fntype, tree libtype,
4130e4b17023SJohn Marino bool both_p, bool fallback_p, bool nonansi_p,
4131e4b17023SJohn Marino tree fnattrs, bool implicit_p);
4132e4b17023SJohn Marino
4133e4b17023SJohn Marino
4134e4b17023SJohn Marino /* Apply the TYPE_QUALS to the new DECL. */
4135e4b17023SJohn Marino
4136e4b17023SJohn Marino void
c_apply_type_quals_to_decl(int type_quals,tree decl)4137e4b17023SJohn Marino c_apply_type_quals_to_decl (int type_quals, tree decl)
4138e4b17023SJohn Marino {
4139e4b17023SJohn Marino tree type = TREE_TYPE (decl);
4140e4b17023SJohn Marino
4141e4b17023SJohn Marino if (type == error_mark_node)
4142e4b17023SJohn Marino return;
4143e4b17023SJohn Marino
4144e4b17023SJohn Marino if ((type_quals & TYPE_QUAL_CONST)
4145e4b17023SJohn Marino || (type && TREE_CODE (type) == REFERENCE_TYPE))
4146e4b17023SJohn Marino /* We used to check TYPE_NEEDS_CONSTRUCTING here, but now a constexpr
4147e4b17023SJohn Marino constructor can produce constant init, so rely on cp_finish_decl to
4148e4b17023SJohn Marino clear TREE_READONLY if the variable has non-constant init. */
4149e4b17023SJohn Marino TREE_READONLY (decl) = 1;
4150e4b17023SJohn Marino if (type_quals & TYPE_QUAL_VOLATILE)
4151e4b17023SJohn Marino {
4152e4b17023SJohn Marino TREE_SIDE_EFFECTS (decl) = 1;
4153e4b17023SJohn Marino TREE_THIS_VOLATILE (decl) = 1;
4154e4b17023SJohn Marino }
4155e4b17023SJohn Marino if (type_quals & TYPE_QUAL_RESTRICT)
4156e4b17023SJohn Marino {
4157e4b17023SJohn Marino while (type && TREE_CODE (type) == ARRAY_TYPE)
4158e4b17023SJohn Marino /* Allow 'restrict' on arrays of pointers.
4159e4b17023SJohn Marino FIXME currently we just ignore it. */
4160e4b17023SJohn Marino type = TREE_TYPE (type);
4161e4b17023SJohn Marino if (!type
4162e4b17023SJohn Marino || !POINTER_TYPE_P (type)
4163e4b17023SJohn Marino || !C_TYPE_OBJECT_OR_INCOMPLETE_P (TREE_TYPE (type)))
4164e4b17023SJohn Marino error ("invalid use of %<restrict%>");
4165e4b17023SJohn Marino }
4166e4b17023SJohn Marino }
4167e4b17023SJohn Marino
4168e4b17023SJohn Marino /* Hash function for the problem of multiple type definitions in
4169e4b17023SJohn Marino different files. This must hash all types that will compare
4170e4b17023SJohn Marino equal via comptypes to the same value. In practice it hashes
4171e4b17023SJohn Marino on some of the simple stuff and leaves the details to comptypes. */
4172e4b17023SJohn Marino
4173e4b17023SJohn Marino static hashval_t
c_type_hash(const void * p)4174e4b17023SJohn Marino c_type_hash (const void *p)
4175e4b17023SJohn Marino {
4176e4b17023SJohn Marino int n_elements;
4177e4b17023SJohn Marino int shift, size;
4178e4b17023SJohn Marino const_tree const t = (const_tree) p;
4179e4b17023SJohn Marino tree t2;
4180e4b17023SJohn Marino switch (TREE_CODE (t))
4181e4b17023SJohn Marino {
4182e4b17023SJohn Marino /* For pointers, hash on pointee type plus some swizzling. */
4183e4b17023SJohn Marino case POINTER_TYPE:
4184e4b17023SJohn Marino return c_type_hash (TREE_TYPE (t)) ^ 0x3003003;
4185e4b17023SJohn Marino /* Hash on number of elements and total size. */
4186e4b17023SJohn Marino case ENUMERAL_TYPE:
4187e4b17023SJohn Marino shift = 3;
4188e4b17023SJohn Marino t2 = TYPE_VALUES (t);
4189e4b17023SJohn Marino break;
4190e4b17023SJohn Marino case RECORD_TYPE:
4191e4b17023SJohn Marino shift = 0;
4192e4b17023SJohn Marino t2 = TYPE_FIELDS (t);
4193e4b17023SJohn Marino break;
4194e4b17023SJohn Marino case QUAL_UNION_TYPE:
4195e4b17023SJohn Marino shift = 1;
4196e4b17023SJohn Marino t2 = TYPE_FIELDS (t);
4197e4b17023SJohn Marino break;
4198e4b17023SJohn Marino case UNION_TYPE:
4199e4b17023SJohn Marino shift = 2;
4200e4b17023SJohn Marino t2 = TYPE_FIELDS (t);
4201e4b17023SJohn Marino break;
4202e4b17023SJohn Marino default:
4203e4b17023SJohn Marino gcc_unreachable ();
4204e4b17023SJohn Marino }
4205e4b17023SJohn Marino /* FIXME: We want to use a DECL_CHAIN iteration method here, but
4206e4b17023SJohn Marino TYPE_VALUES of ENUMERAL_TYPEs is stored as a TREE_LIST. */
4207e4b17023SJohn Marino n_elements = list_length (t2);
4208e4b17023SJohn Marino /* We might have a VLA here. */
4209e4b17023SJohn Marino if (TREE_CODE (TYPE_SIZE (t)) != INTEGER_CST)
4210e4b17023SJohn Marino size = 0;
4211e4b17023SJohn Marino else
4212e4b17023SJohn Marino size = TREE_INT_CST_LOW (TYPE_SIZE (t));
4213e4b17023SJohn Marino return ((size << 24) | (n_elements << shift));
4214e4b17023SJohn Marino }
4215e4b17023SJohn Marino
4216e4b17023SJohn Marino static GTY((param_is (union tree_node))) htab_t type_hash_table;
4217e4b17023SJohn Marino
4218e4b17023SJohn Marino /* Return the typed-based alias set for T, which may be an expression
4219e4b17023SJohn Marino or a type. Return -1 if we don't do anything special. */
4220e4b17023SJohn Marino
4221e4b17023SJohn Marino alias_set_type
c_common_get_alias_set(tree t)4222e4b17023SJohn Marino c_common_get_alias_set (tree t)
4223e4b17023SJohn Marino {
4224e4b17023SJohn Marino tree u;
4225e4b17023SJohn Marino PTR *slot;
4226e4b17023SJohn Marino
4227e4b17023SJohn Marino /* For VLAs, use the alias set of the element type rather than the
4228e4b17023SJohn Marino default of alias set 0 for types compared structurally. */
4229e4b17023SJohn Marino if (TYPE_P (t) && TYPE_STRUCTURAL_EQUALITY_P (t))
4230e4b17023SJohn Marino {
4231e4b17023SJohn Marino if (TREE_CODE (t) == ARRAY_TYPE)
4232e4b17023SJohn Marino return get_alias_set (TREE_TYPE (t));
4233e4b17023SJohn Marino return -1;
4234e4b17023SJohn Marino }
4235e4b17023SJohn Marino
4236e4b17023SJohn Marino /* Permit type-punning when accessing a union, provided the access
4237e4b17023SJohn Marino is directly through the union. For example, this code does not
4238e4b17023SJohn Marino permit taking the address of a union member and then storing
4239e4b17023SJohn Marino through it. Even the type-punning allowed here is a GCC
4240e4b17023SJohn Marino extension, albeit a common and useful one; the C standard says
4241e4b17023SJohn Marino that such accesses have implementation-defined behavior. */
4242e4b17023SJohn Marino for (u = t;
4243e4b17023SJohn Marino TREE_CODE (u) == COMPONENT_REF || TREE_CODE (u) == ARRAY_REF;
4244e4b17023SJohn Marino u = TREE_OPERAND (u, 0))
4245e4b17023SJohn Marino if (TREE_CODE (u) == COMPONENT_REF
4246e4b17023SJohn Marino && TREE_CODE (TREE_TYPE (TREE_OPERAND (u, 0))) == UNION_TYPE)
4247e4b17023SJohn Marino return 0;
4248e4b17023SJohn Marino
4249e4b17023SJohn Marino /* That's all the expressions we handle specially. */
4250e4b17023SJohn Marino if (!TYPE_P (t))
4251e4b17023SJohn Marino return -1;
4252e4b17023SJohn Marino
4253e4b17023SJohn Marino /* The C standard guarantees that any object may be accessed via an
4254e4b17023SJohn Marino lvalue that has character type. */
4255e4b17023SJohn Marino if (t == char_type_node
4256e4b17023SJohn Marino || t == signed_char_type_node
4257e4b17023SJohn Marino || t == unsigned_char_type_node)
4258e4b17023SJohn Marino return 0;
4259e4b17023SJohn Marino
4260e4b17023SJohn Marino /* The C standard specifically allows aliasing between signed and
4261e4b17023SJohn Marino unsigned variants of the same type. We treat the signed
4262e4b17023SJohn Marino variant as canonical. */
4263e4b17023SJohn Marino if (TREE_CODE (t) == INTEGER_TYPE && TYPE_UNSIGNED (t))
4264e4b17023SJohn Marino {
4265e4b17023SJohn Marino tree t1 = c_common_signed_type (t);
4266e4b17023SJohn Marino
4267e4b17023SJohn Marino /* t1 == t can happen for boolean nodes which are always unsigned. */
4268e4b17023SJohn Marino if (t1 != t)
4269e4b17023SJohn Marino return get_alias_set (t1);
4270e4b17023SJohn Marino }
4271e4b17023SJohn Marino
4272e4b17023SJohn Marino /* Handle the case of multiple type nodes referring to "the same" type,
4273e4b17023SJohn Marino which occurs with IMA. These share an alias set. FIXME: Currently only
4274e4b17023SJohn Marino C90 is handled. (In C99 type compatibility is not transitive, which
4275e4b17023SJohn Marino complicates things mightily. The alias set splay trees can theoretically
4276e4b17023SJohn Marino represent this, but insertion is tricky when you consider all the
4277e4b17023SJohn Marino different orders things might arrive in.) */
4278e4b17023SJohn Marino
4279e4b17023SJohn Marino if (c_language != clk_c || flag_isoc99)
4280e4b17023SJohn Marino return -1;
4281e4b17023SJohn Marino
4282e4b17023SJohn Marino /* Save time if there's only one input file. */
4283e4b17023SJohn Marino if (num_in_fnames == 1)
4284e4b17023SJohn Marino return -1;
4285e4b17023SJohn Marino
4286e4b17023SJohn Marino /* Pointers need special handling if they point to any type that
4287e4b17023SJohn Marino needs special handling (below). */
4288e4b17023SJohn Marino if (TREE_CODE (t) == POINTER_TYPE)
4289e4b17023SJohn Marino {
4290e4b17023SJohn Marino tree t2;
4291e4b17023SJohn Marino /* Find bottom type under any nested POINTERs. */
4292e4b17023SJohn Marino for (t2 = TREE_TYPE (t);
4293e4b17023SJohn Marino TREE_CODE (t2) == POINTER_TYPE;
4294e4b17023SJohn Marino t2 = TREE_TYPE (t2))
4295e4b17023SJohn Marino ;
4296e4b17023SJohn Marino if (TREE_CODE (t2) != RECORD_TYPE
4297e4b17023SJohn Marino && TREE_CODE (t2) != ENUMERAL_TYPE
4298e4b17023SJohn Marino && TREE_CODE (t2) != QUAL_UNION_TYPE
4299e4b17023SJohn Marino && TREE_CODE (t2) != UNION_TYPE)
4300e4b17023SJohn Marino return -1;
4301e4b17023SJohn Marino if (TYPE_SIZE (t2) == 0)
4302e4b17023SJohn Marino return -1;
4303e4b17023SJohn Marino }
4304e4b17023SJohn Marino /* These are the only cases that need special handling. */
4305e4b17023SJohn Marino if (TREE_CODE (t) != RECORD_TYPE
4306e4b17023SJohn Marino && TREE_CODE (t) != ENUMERAL_TYPE
4307e4b17023SJohn Marino && TREE_CODE (t) != QUAL_UNION_TYPE
4308e4b17023SJohn Marino && TREE_CODE (t) != UNION_TYPE
4309e4b17023SJohn Marino && TREE_CODE (t) != POINTER_TYPE)
4310e4b17023SJohn Marino return -1;
4311e4b17023SJohn Marino /* Undefined? */
4312e4b17023SJohn Marino if (TYPE_SIZE (t) == 0)
4313e4b17023SJohn Marino return -1;
4314e4b17023SJohn Marino
4315e4b17023SJohn Marino /* Look up t in hash table. Only one of the compatible types within each
4316e4b17023SJohn Marino alias set is recorded in the table. */
4317e4b17023SJohn Marino if (!type_hash_table)
4318e4b17023SJohn Marino type_hash_table = htab_create_ggc (1021, c_type_hash,
4319e4b17023SJohn Marino (htab_eq) lang_hooks.types_compatible_p,
4320e4b17023SJohn Marino NULL);
4321e4b17023SJohn Marino slot = htab_find_slot (type_hash_table, t, INSERT);
4322e4b17023SJohn Marino if (*slot != NULL)
4323e4b17023SJohn Marino {
4324e4b17023SJohn Marino TYPE_ALIAS_SET (t) = TYPE_ALIAS_SET ((tree)*slot);
4325e4b17023SJohn Marino return TYPE_ALIAS_SET ((tree)*slot);
4326e4b17023SJohn Marino }
4327e4b17023SJohn Marino else
4328e4b17023SJohn Marino /* Our caller will assign and record (in t) a new alias set; all we need
4329e4b17023SJohn Marino to do is remember t in the hash table. */
4330e4b17023SJohn Marino *slot = t;
4331e4b17023SJohn Marino
4332e4b17023SJohn Marino return -1;
4333e4b17023SJohn Marino }
4334e4b17023SJohn Marino
4335e4b17023SJohn Marino /* Compute the value of 'sizeof (TYPE)' or '__alignof__ (TYPE)', where
4336e4b17023SJohn Marino the second parameter indicates which OPERATOR is being applied.
4337e4b17023SJohn Marino The COMPLAIN flag controls whether we should diagnose possibly
4338e4b17023SJohn Marino ill-formed constructs or not. LOC is the location of the SIZEOF or
4339e4b17023SJohn Marino TYPEOF operator. */
4340e4b17023SJohn Marino
4341e4b17023SJohn Marino tree
c_sizeof_or_alignof_type(location_t loc,tree type,bool is_sizeof,int complain)4342e4b17023SJohn Marino c_sizeof_or_alignof_type (location_t loc,
4343e4b17023SJohn Marino tree type, bool is_sizeof, int complain)
4344e4b17023SJohn Marino {
4345e4b17023SJohn Marino const char *op_name;
4346e4b17023SJohn Marino tree value = NULL;
4347e4b17023SJohn Marino enum tree_code type_code = TREE_CODE (type);
4348e4b17023SJohn Marino
4349e4b17023SJohn Marino op_name = is_sizeof ? "sizeof" : "__alignof__";
4350e4b17023SJohn Marino
4351e4b17023SJohn Marino if (type_code == FUNCTION_TYPE)
4352e4b17023SJohn Marino {
4353e4b17023SJohn Marino if (is_sizeof)
4354e4b17023SJohn Marino {
4355e4b17023SJohn Marino if (complain && (pedantic || warn_pointer_arith))
4356e4b17023SJohn Marino pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
4357e4b17023SJohn Marino "invalid application of %<sizeof%> to a function type");
4358e4b17023SJohn Marino else if (!complain)
4359e4b17023SJohn Marino return error_mark_node;
4360e4b17023SJohn Marino value = size_one_node;
4361e4b17023SJohn Marino }
4362e4b17023SJohn Marino else
4363e4b17023SJohn Marino {
4364e4b17023SJohn Marino if (complain)
4365e4b17023SJohn Marino {
4366e4b17023SJohn Marino if (c_dialect_cxx ())
4367e4b17023SJohn Marino pedwarn (loc, OPT_pedantic, "ISO C++ does not permit "
4368e4b17023SJohn Marino "%<alignof%> applied to a function type");
4369e4b17023SJohn Marino else
4370e4b17023SJohn Marino pedwarn (loc, OPT_pedantic, "ISO C does not permit "
4371e4b17023SJohn Marino "%<_Alignof%> applied to a function type");
4372e4b17023SJohn Marino }
4373e4b17023SJohn Marino value = size_int (FUNCTION_BOUNDARY / BITS_PER_UNIT);
4374e4b17023SJohn Marino }
4375e4b17023SJohn Marino }
4376e4b17023SJohn Marino else if (type_code == VOID_TYPE || type_code == ERROR_MARK)
4377e4b17023SJohn Marino {
4378e4b17023SJohn Marino if (type_code == VOID_TYPE
4379e4b17023SJohn Marino && complain && (pedantic || warn_pointer_arith))
4380e4b17023SJohn Marino pedwarn (loc, pedantic ? OPT_pedantic : OPT_Wpointer_arith,
4381e4b17023SJohn Marino "invalid application of %qs to a void type", op_name);
4382e4b17023SJohn Marino else if (!complain)
4383e4b17023SJohn Marino return error_mark_node;
4384e4b17023SJohn Marino value = size_one_node;
4385e4b17023SJohn Marino }
4386e4b17023SJohn Marino else if (!COMPLETE_TYPE_P (type)
4387e4b17023SJohn Marino && (!c_dialect_cxx () || is_sizeof || type_code != ARRAY_TYPE))
4388e4b17023SJohn Marino {
4389e4b17023SJohn Marino if (complain)
4390e4b17023SJohn Marino error_at (loc, "invalid application of %qs to incomplete type %qT",
4391e4b17023SJohn Marino op_name, type);
4392e4b17023SJohn Marino return error_mark_node;
4393e4b17023SJohn Marino }
4394e4b17023SJohn Marino else if (c_dialect_cxx () && type_code == ARRAY_TYPE
4395e4b17023SJohn Marino && !COMPLETE_TYPE_P (TREE_TYPE (type)))
4396e4b17023SJohn Marino {
4397e4b17023SJohn Marino if (complain)
4398e4b17023SJohn Marino error_at (loc, "invalid application of %qs to array type %qT of "
4399e4b17023SJohn Marino "incomplete element type", op_name, type);
4400e4b17023SJohn Marino return error_mark_node;
4401e4b17023SJohn Marino }
4402e4b17023SJohn Marino else
4403e4b17023SJohn Marino {
4404e4b17023SJohn Marino if (is_sizeof)
4405e4b17023SJohn Marino /* Convert in case a char is more than one unit. */
4406e4b17023SJohn Marino value = size_binop_loc (loc, CEIL_DIV_EXPR, TYPE_SIZE_UNIT (type),
4407e4b17023SJohn Marino size_int (TYPE_PRECISION (char_type_node)
4408e4b17023SJohn Marino / BITS_PER_UNIT));
4409e4b17023SJohn Marino else
4410e4b17023SJohn Marino value = size_int (TYPE_ALIGN_UNIT (type));
4411e4b17023SJohn Marino }
4412e4b17023SJohn Marino
4413e4b17023SJohn Marino /* VALUE will have an integer type with TYPE_IS_SIZETYPE set.
4414e4b17023SJohn Marino TYPE_IS_SIZETYPE means that certain things (like overflow) will
4415e4b17023SJohn Marino never happen. However, this node should really have type
4416e4b17023SJohn Marino `size_t', which is just a typedef for an ordinary integer type. */
4417e4b17023SJohn Marino value = fold_convert_loc (loc, size_type_node, value);
4418e4b17023SJohn Marino gcc_assert (!TYPE_IS_SIZETYPE (TREE_TYPE (value)));
4419e4b17023SJohn Marino
4420e4b17023SJohn Marino return value;
4421e4b17023SJohn Marino }
4422e4b17023SJohn Marino
4423e4b17023SJohn Marino /* Implement the __alignof keyword: Return the minimum required
4424e4b17023SJohn Marino alignment of EXPR, measured in bytes. For VAR_DECLs,
4425e4b17023SJohn Marino FUNCTION_DECLs and FIELD_DECLs return DECL_ALIGN (which can be set
4426e4b17023SJohn Marino from an "aligned" __attribute__ specification). LOC is the
4427e4b17023SJohn Marino location of the ALIGNOF operator. */
4428e4b17023SJohn Marino
4429e4b17023SJohn Marino tree
c_alignof_expr(location_t loc,tree expr)4430e4b17023SJohn Marino c_alignof_expr (location_t loc, tree expr)
4431e4b17023SJohn Marino {
4432e4b17023SJohn Marino tree t;
4433e4b17023SJohn Marino
4434e4b17023SJohn Marino if (VAR_OR_FUNCTION_DECL_P (expr))
4435e4b17023SJohn Marino t = size_int (DECL_ALIGN_UNIT (expr));
4436e4b17023SJohn Marino
4437e4b17023SJohn Marino else if (TREE_CODE (expr) == COMPONENT_REF
4438e4b17023SJohn Marino && DECL_C_BIT_FIELD (TREE_OPERAND (expr, 1)))
4439e4b17023SJohn Marino {
4440e4b17023SJohn Marino error_at (loc, "%<__alignof%> applied to a bit-field");
4441e4b17023SJohn Marino t = size_one_node;
4442e4b17023SJohn Marino }
4443e4b17023SJohn Marino else if (TREE_CODE (expr) == COMPONENT_REF
4444e4b17023SJohn Marino && TREE_CODE (TREE_OPERAND (expr, 1)) == FIELD_DECL)
4445e4b17023SJohn Marino t = size_int (DECL_ALIGN_UNIT (TREE_OPERAND (expr, 1)));
4446e4b17023SJohn Marino
4447e4b17023SJohn Marino else if (TREE_CODE (expr) == INDIRECT_REF)
4448e4b17023SJohn Marino {
4449e4b17023SJohn Marino tree t = TREE_OPERAND (expr, 0);
4450e4b17023SJohn Marino tree best = t;
4451e4b17023SJohn Marino int bestalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));
4452e4b17023SJohn Marino
4453e4b17023SJohn Marino while (CONVERT_EXPR_P (t)
4454e4b17023SJohn Marino && TREE_CODE (TREE_TYPE (TREE_OPERAND (t, 0))) == POINTER_TYPE)
4455e4b17023SJohn Marino {
4456e4b17023SJohn Marino int thisalign;
4457e4b17023SJohn Marino
4458e4b17023SJohn Marino t = TREE_OPERAND (t, 0);
4459e4b17023SJohn Marino thisalign = TYPE_ALIGN (TREE_TYPE (TREE_TYPE (t)));
4460e4b17023SJohn Marino if (thisalign > bestalign)
4461e4b17023SJohn Marino best = t, bestalign = thisalign;
4462e4b17023SJohn Marino }
4463e4b17023SJohn Marino return c_alignof (loc, TREE_TYPE (TREE_TYPE (best)));
4464e4b17023SJohn Marino }
4465e4b17023SJohn Marino else
4466e4b17023SJohn Marino return c_alignof (loc, TREE_TYPE (expr));
4467e4b17023SJohn Marino
4468e4b17023SJohn Marino return fold_convert_loc (loc, size_type_node, t);
4469e4b17023SJohn Marino }
4470e4b17023SJohn Marino
4471e4b17023SJohn Marino /* Handle C and C++ default attributes. */
4472e4b17023SJohn Marino
4473e4b17023SJohn Marino enum built_in_attribute
4474e4b17023SJohn Marino {
4475e4b17023SJohn Marino #define DEF_ATTR_NULL_TREE(ENUM) ENUM,
4476e4b17023SJohn Marino #define DEF_ATTR_INT(ENUM, VALUE) ENUM,
4477e4b17023SJohn Marino #define DEF_ATTR_IDENT(ENUM, STRING) ENUM,
4478e4b17023SJohn Marino #define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) ENUM,
4479e4b17023SJohn Marino #include "builtin-attrs.def"
4480e4b17023SJohn Marino #undef DEF_ATTR_NULL_TREE
4481e4b17023SJohn Marino #undef DEF_ATTR_INT
4482e4b17023SJohn Marino #undef DEF_ATTR_IDENT
4483e4b17023SJohn Marino #undef DEF_ATTR_TREE_LIST
4484e4b17023SJohn Marino ATTR_LAST
4485e4b17023SJohn Marino };
4486e4b17023SJohn Marino
4487e4b17023SJohn Marino static GTY(()) tree built_in_attributes[(int) ATTR_LAST];
4488e4b17023SJohn Marino
4489e4b17023SJohn Marino static void c_init_attributes (void);
4490e4b17023SJohn Marino
4491e4b17023SJohn Marino enum c_builtin_type
4492e4b17023SJohn Marino {
4493e4b17023SJohn Marino #define DEF_PRIMITIVE_TYPE(NAME, VALUE) NAME,
4494e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_0(NAME, RETURN) NAME,
4495e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_1(NAME, RETURN, ARG1) NAME,
4496e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_2(NAME, RETURN, ARG1, ARG2) NAME,
4497e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
4498e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
4499e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) NAME,
4500e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_6(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6) NAME,
4501e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_7(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7) NAME,
4502e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_VAR_0(NAME, RETURN) NAME,
4503e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_VAR_1(NAME, RETURN, ARG1) NAME,
4504e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_VAR_2(NAME, RETURN, ARG1, ARG2) NAME,
4505e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_VAR_3(NAME, RETURN, ARG1, ARG2, ARG3) NAME,
4506e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_VAR_4(NAME, RETURN, ARG1, ARG2, ARG3, ARG4) NAME,
4507e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_VAR_5(NAME, RETURN, ARG1, ARG2, ARG3, ARG4, ARG6) \
4508e4b17023SJohn Marino NAME,
4509e4b17023SJohn Marino #define DEF_POINTER_TYPE(NAME, TYPE) NAME,
4510e4b17023SJohn Marino #include "builtin-types.def"
4511e4b17023SJohn Marino #undef DEF_PRIMITIVE_TYPE
4512e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_0
4513e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_1
4514e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_2
4515e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_3
4516e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_4
4517e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_5
4518e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_6
4519e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_7
4520e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_VAR_0
4521e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_VAR_1
4522e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_VAR_2
4523e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_VAR_3
4524e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_VAR_4
4525e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_VAR_5
4526e4b17023SJohn Marino #undef DEF_POINTER_TYPE
4527e4b17023SJohn Marino BT_LAST
4528e4b17023SJohn Marino };
4529e4b17023SJohn Marino
4530e4b17023SJohn Marino typedef enum c_builtin_type builtin_type;
4531e4b17023SJohn Marino
4532e4b17023SJohn Marino /* A temporary array for c_common_nodes_and_builtins. Used in
4533e4b17023SJohn Marino communication with def_fn_type. */
4534e4b17023SJohn Marino static tree builtin_types[(int) BT_LAST + 1];
4535e4b17023SJohn Marino
4536e4b17023SJohn Marino /* A helper function for c_common_nodes_and_builtins. Build function type
4537e4b17023SJohn Marino for DEF with return type RET and N arguments. If VAR is true, then the
4538e4b17023SJohn Marino function should be variadic after those N arguments.
4539e4b17023SJohn Marino
4540e4b17023SJohn Marino Takes special care not to ICE if any of the types involved are
4541e4b17023SJohn Marino error_mark_node, which indicates that said type is not in fact available
4542e4b17023SJohn Marino (see builtin_type_for_size). In which case the function type as a whole
4543e4b17023SJohn Marino should be error_mark_node. */
4544e4b17023SJohn Marino
4545e4b17023SJohn Marino static void
def_fn_type(builtin_type def,builtin_type ret,bool var,int n,...)4546e4b17023SJohn Marino def_fn_type (builtin_type def, builtin_type ret, bool var, int n, ...)
4547e4b17023SJohn Marino {
4548e4b17023SJohn Marino tree t;
4549e4b17023SJohn Marino tree *args = XALLOCAVEC (tree, n);
4550e4b17023SJohn Marino va_list list;
4551e4b17023SJohn Marino int i;
4552e4b17023SJohn Marino
4553e4b17023SJohn Marino va_start (list, n);
4554e4b17023SJohn Marino for (i = 0; i < n; ++i)
4555e4b17023SJohn Marino {
4556e4b17023SJohn Marino builtin_type a = (builtin_type) va_arg (list, int);
4557e4b17023SJohn Marino t = builtin_types[a];
4558e4b17023SJohn Marino if (t == error_mark_node)
4559e4b17023SJohn Marino goto egress;
4560e4b17023SJohn Marino args[i] = t;
4561e4b17023SJohn Marino }
4562e4b17023SJohn Marino
4563e4b17023SJohn Marino t = builtin_types[ret];
4564e4b17023SJohn Marino if (t == error_mark_node)
4565e4b17023SJohn Marino goto egress;
4566e4b17023SJohn Marino if (var)
4567e4b17023SJohn Marino t = build_varargs_function_type_array (t, n, args);
4568e4b17023SJohn Marino else
4569e4b17023SJohn Marino t = build_function_type_array (t, n, args);
4570e4b17023SJohn Marino
4571e4b17023SJohn Marino egress:
4572e4b17023SJohn Marino builtin_types[def] = t;
4573e4b17023SJohn Marino va_end (list);
4574e4b17023SJohn Marino }
4575e4b17023SJohn Marino
4576e4b17023SJohn Marino /* Build builtin functions common to both C and C++ language
4577e4b17023SJohn Marino frontends. */
4578e4b17023SJohn Marino
4579e4b17023SJohn Marino static void
c_define_builtins(tree va_list_ref_type_node,tree va_list_arg_type_node)4580e4b17023SJohn Marino c_define_builtins (tree va_list_ref_type_node, tree va_list_arg_type_node)
4581e4b17023SJohn Marino {
4582e4b17023SJohn Marino #define DEF_PRIMITIVE_TYPE(ENUM, VALUE) \
4583e4b17023SJohn Marino builtin_types[ENUM] = VALUE;
4584e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_0(ENUM, RETURN) \
4585e4b17023SJohn Marino def_fn_type (ENUM, RETURN, 0, 0);
4586e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_1(ENUM, RETURN, ARG1) \
4587e4b17023SJohn Marino def_fn_type (ENUM, RETURN, 0, 1, ARG1);
4588e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_2(ENUM, RETURN, ARG1, ARG2) \
4589e4b17023SJohn Marino def_fn_type (ENUM, RETURN, 0, 2, ARG1, ARG2);
4590e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
4591e4b17023SJohn Marino def_fn_type (ENUM, RETURN, 0, 3, ARG1, ARG2, ARG3);
4592e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
4593e4b17023SJohn Marino def_fn_type (ENUM, RETURN, 0, 4, ARG1, ARG2, ARG3, ARG4);
4594e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
4595e4b17023SJohn Marino def_fn_type (ENUM, RETURN, 0, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
4596e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_6(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
4597e4b17023SJohn Marino ARG6) \
4598e4b17023SJohn Marino def_fn_type (ENUM, RETURN, 0, 6, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6);
4599e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_7(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5, \
4600e4b17023SJohn Marino ARG6, ARG7) \
4601e4b17023SJohn Marino def_fn_type (ENUM, RETURN, 0, 7, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6, ARG7);
4602e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_VAR_0(ENUM, RETURN) \
4603e4b17023SJohn Marino def_fn_type (ENUM, RETURN, 1, 0);
4604e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_VAR_1(ENUM, RETURN, ARG1) \
4605e4b17023SJohn Marino def_fn_type (ENUM, RETURN, 1, 1, ARG1);
4606e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_VAR_2(ENUM, RETURN, ARG1, ARG2) \
4607e4b17023SJohn Marino def_fn_type (ENUM, RETURN, 1, 2, ARG1, ARG2);
4608e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_VAR_3(ENUM, RETURN, ARG1, ARG2, ARG3) \
4609e4b17023SJohn Marino def_fn_type (ENUM, RETURN, 1, 3, ARG1, ARG2, ARG3);
4610e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_VAR_4(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4) \
4611e4b17023SJohn Marino def_fn_type (ENUM, RETURN, 1, 4, ARG1, ARG2, ARG3, ARG4);
4612e4b17023SJohn Marino #define DEF_FUNCTION_TYPE_VAR_5(ENUM, RETURN, ARG1, ARG2, ARG3, ARG4, ARG5) \
4613e4b17023SJohn Marino def_fn_type (ENUM, RETURN, 1, 5, ARG1, ARG2, ARG3, ARG4, ARG5);
4614e4b17023SJohn Marino #define DEF_POINTER_TYPE(ENUM, TYPE) \
4615e4b17023SJohn Marino builtin_types[(int) ENUM] = build_pointer_type (builtin_types[(int) TYPE]);
4616e4b17023SJohn Marino
4617e4b17023SJohn Marino #include "builtin-types.def"
4618e4b17023SJohn Marino
4619e4b17023SJohn Marino #undef DEF_PRIMITIVE_TYPE
4620e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_1
4621e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_2
4622e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_3
4623e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_4
4624e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_5
4625e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_6
4626e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_VAR_0
4627e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_VAR_1
4628e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_VAR_2
4629e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_VAR_3
4630e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_VAR_4
4631e4b17023SJohn Marino #undef DEF_FUNCTION_TYPE_VAR_5
4632e4b17023SJohn Marino #undef DEF_POINTER_TYPE
4633e4b17023SJohn Marino builtin_types[(int) BT_LAST] = NULL_TREE;
4634e4b17023SJohn Marino
4635e4b17023SJohn Marino c_init_attributes ();
4636e4b17023SJohn Marino
4637e4b17023SJohn Marino #define DEF_BUILTIN(ENUM, NAME, CLASS, TYPE, LIBTYPE, BOTH_P, FALLBACK_P, \
4638e4b17023SJohn Marino NONANSI_P, ATTRS, IMPLICIT, COND) \
4639e4b17023SJohn Marino if (NAME && COND) \
4640e4b17023SJohn Marino def_builtin_1 (ENUM, NAME, CLASS, \
4641e4b17023SJohn Marino builtin_types[(int) TYPE], \
4642e4b17023SJohn Marino builtin_types[(int) LIBTYPE], \
4643e4b17023SJohn Marino BOTH_P, FALLBACK_P, NONANSI_P, \
4644e4b17023SJohn Marino built_in_attributes[(int) ATTRS], IMPLICIT);
4645e4b17023SJohn Marino #include "builtins.def"
4646e4b17023SJohn Marino #undef DEF_BUILTIN
4647e4b17023SJohn Marino
4648e4b17023SJohn Marino targetm.init_builtins ();
4649e4b17023SJohn Marino
4650e4b17023SJohn Marino build_common_builtin_nodes ();
4651e4b17023SJohn Marino
4652e4b17023SJohn Marino if (flag_mudflap)
4653e4b17023SJohn Marino mudflap_init ();
4654e4b17023SJohn Marino }
4655e4b17023SJohn Marino
4656e4b17023SJohn Marino /* Like get_identifier, but avoid warnings about null arguments when
4657e4b17023SJohn Marino the argument may be NULL for targets where GCC lacks stdint.h type
4658e4b17023SJohn Marino information. */
4659e4b17023SJohn Marino
4660e4b17023SJohn Marino static inline tree
c_get_ident(const char * id)4661e4b17023SJohn Marino c_get_ident (const char *id)
4662e4b17023SJohn Marino {
4663e4b17023SJohn Marino return get_identifier (id);
4664e4b17023SJohn Marino }
4665e4b17023SJohn Marino
4666e4b17023SJohn Marino /* Build tree nodes and builtin functions common to both C and C++ language
4667e4b17023SJohn Marino frontends. */
4668e4b17023SJohn Marino
4669e4b17023SJohn Marino void
c_common_nodes_and_builtins(void)4670e4b17023SJohn Marino c_common_nodes_and_builtins (void)
4671e4b17023SJohn Marino {
4672e4b17023SJohn Marino int char16_type_size;
4673e4b17023SJohn Marino int char32_type_size;
4674e4b17023SJohn Marino int wchar_type_size;
4675e4b17023SJohn Marino tree array_domain_type;
4676e4b17023SJohn Marino tree va_list_ref_type_node;
4677e4b17023SJohn Marino tree va_list_arg_type_node;
4678e4b17023SJohn Marino
4679e4b17023SJohn Marino build_common_tree_nodes (flag_signed_char, flag_short_double);
4680e4b17023SJohn Marino
4681e4b17023SJohn Marino /* Define `int' and `char' first so that dbx will output them first. */
4682e4b17023SJohn Marino record_builtin_type (RID_INT, NULL, integer_type_node);
4683e4b17023SJohn Marino record_builtin_type (RID_CHAR, "char", char_type_node);
4684e4b17023SJohn Marino
4685e4b17023SJohn Marino /* `signed' is the same as `int'. FIXME: the declarations of "signed",
4686e4b17023SJohn Marino "unsigned long", "long long unsigned" and "unsigned short" were in C++
4687e4b17023SJohn Marino but not C. Are the conditionals here needed? */
4688e4b17023SJohn Marino if (c_dialect_cxx ())
4689e4b17023SJohn Marino record_builtin_type (RID_SIGNED, NULL, integer_type_node);
4690e4b17023SJohn Marino record_builtin_type (RID_LONG, "long int", long_integer_type_node);
4691e4b17023SJohn Marino record_builtin_type (RID_UNSIGNED, "unsigned int", unsigned_type_node);
4692e4b17023SJohn Marino record_builtin_type (RID_MAX, "long unsigned int",
4693e4b17023SJohn Marino long_unsigned_type_node);
4694e4b17023SJohn Marino if (int128_integer_type_node != NULL_TREE)
4695e4b17023SJohn Marino {
4696e4b17023SJohn Marino record_builtin_type (RID_INT128, "__int128",
4697e4b17023SJohn Marino int128_integer_type_node);
4698e4b17023SJohn Marino record_builtin_type (RID_MAX, "__int128 unsigned",
4699e4b17023SJohn Marino int128_unsigned_type_node);
4700e4b17023SJohn Marino }
4701e4b17023SJohn Marino if (c_dialect_cxx ())
4702e4b17023SJohn Marino record_builtin_type (RID_MAX, "unsigned long", long_unsigned_type_node);
4703e4b17023SJohn Marino record_builtin_type (RID_MAX, "long long int",
4704e4b17023SJohn Marino long_long_integer_type_node);
4705e4b17023SJohn Marino record_builtin_type (RID_MAX, "long long unsigned int",
4706e4b17023SJohn Marino long_long_unsigned_type_node);
4707e4b17023SJohn Marino if (c_dialect_cxx ())
4708e4b17023SJohn Marino record_builtin_type (RID_MAX, "long long unsigned",
4709e4b17023SJohn Marino long_long_unsigned_type_node);
4710e4b17023SJohn Marino record_builtin_type (RID_SHORT, "short int", short_integer_type_node);
4711e4b17023SJohn Marino record_builtin_type (RID_MAX, "short unsigned int",
4712e4b17023SJohn Marino short_unsigned_type_node);
4713e4b17023SJohn Marino if (c_dialect_cxx ())
4714e4b17023SJohn Marino record_builtin_type (RID_MAX, "unsigned short",
4715e4b17023SJohn Marino short_unsigned_type_node);
4716e4b17023SJohn Marino
4717e4b17023SJohn Marino /* Define both `signed char' and `unsigned char'. */
4718e4b17023SJohn Marino record_builtin_type (RID_MAX, "signed char", signed_char_type_node);
4719e4b17023SJohn Marino record_builtin_type (RID_MAX, "unsigned char", unsigned_char_type_node);
4720e4b17023SJohn Marino
4721e4b17023SJohn Marino /* These are types that c_common_type_for_size and
4722e4b17023SJohn Marino c_common_type_for_mode use. */
4723e4b17023SJohn Marino lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
4724e4b17023SJohn Marino TYPE_DECL, NULL_TREE,
4725e4b17023SJohn Marino intQI_type_node));
4726e4b17023SJohn Marino lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
4727e4b17023SJohn Marino TYPE_DECL, NULL_TREE,
4728e4b17023SJohn Marino intHI_type_node));
4729e4b17023SJohn Marino lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
4730e4b17023SJohn Marino TYPE_DECL, NULL_TREE,
4731e4b17023SJohn Marino intSI_type_node));
4732e4b17023SJohn Marino lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
4733e4b17023SJohn Marino TYPE_DECL, NULL_TREE,
4734e4b17023SJohn Marino intDI_type_node));
4735e4b17023SJohn Marino #if HOST_BITS_PER_WIDE_INT >= 64
4736e4b17023SJohn Marino if (targetm.scalar_mode_supported_p (TImode))
4737e4b17023SJohn Marino lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
4738e4b17023SJohn Marino TYPE_DECL,
4739e4b17023SJohn Marino get_identifier ("__int128_t"),
4740e4b17023SJohn Marino intTI_type_node));
4741e4b17023SJohn Marino #endif
4742e4b17023SJohn Marino lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
4743e4b17023SJohn Marino TYPE_DECL, NULL_TREE,
4744e4b17023SJohn Marino unsigned_intQI_type_node));
4745e4b17023SJohn Marino lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
4746e4b17023SJohn Marino TYPE_DECL, NULL_TREE,
4747e4b17023SJohn Marino unsigned_intHI_type_node));
4748e4b17023SJohn Marino lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
4749e4b17023SJohn Marino TYPE_DECL, NULL_TREE,
4750e4b17023SJohn Marino unsigned_intSI_type_node));
4751e4b17023SJohn Marino lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
4752e4b17023SJohn Marino TYPE_DECL, NULL_TREE,
4753e4b17023SJohn Marino unsigned_intDI_type_node));
4754e4b17023SJohn Marino #if HOST_BITS_PER_WIDE_INT >= 64
4755e4b17023SJohn Marino if (targetm.scalar_mode_supported_p (TImode))
4756e4b17023SJohn Marino lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
4757e4b17023SJohn Marino TYPE_DECL,
4758e4b17023SJohn Marino get_identifier ("__uint128_t"),
4759e4b17023SJohn Marino unsigned_intTI_type_node));
4760e4b17023SJohn Marino #endif
4761e4b17023SJohn Marino
4762e4b17023SJohn Marino /* Create the widest literal types. */
4763e4b17023SJohn Marino widest_integer_literal_type_node
4764e4b17023SJohn Marino = make_signed_type (HOST_BITS_PER_WIDE_INT * 2);
4765e4b17023SJohn Marino lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
4766e4b17023SJohn Marino TYPE_DECL, NULL_TREE,
4767e4b17023SJohn Marino widest_integer_literal_type_node));
4768e4b17023SJohn Marino
4769e4b17023SJohn Marino widest_unsigned_literal_type_node
4770e4b17023SJohn Marino = make_unsigned_type (HOST_BITS_PER_WIDE_INT * 2);
4771e4b17023SJohn Marino lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
4772e4b17023SJohn Marino TYPE_DECL, NULL_TREE,
4773e4b17023SJohn Marino widest_unsigned_literal_type_node));
4774e4b17023SJohn Marino
4775e4b17023SJohn Marino signed_size_type_node = c_common_signed_type (size_type_node);
4776e4b17023SJohn Marino
4777e4b17023SJohn Marino pid_type_node =
4778e4b17023SJohn Marino TREE_TYPE (identifier_global_value (get_identifier (PID_TYPE)));
4779e4b17023SJohn Marino
4780e4b17023SJohn Marino record_builtin_type (RID_FLOAT, NULL, float_type_node);
4781e4b17023SJohn Marino record_builtin_type (RID_DOUBLE, NULL, double_type_node);
4782e4b17023SJohn Marino record_builtin_type (RID_MAX, "long double", long_double_type_node);
4783e4b17023SJohn Marino
4784e4b17023SJohn Marino /* Only supported decimal floating point extension if the target
4785e4b17023SJohn Marino actually supports underlying modes. */
4786e4b17023SJohn Marino if (targetm.scalar_mode_supported_p (SDmode)
4787e4b17023SJohn Marino && targetm.scalar_mode_supported_p (DDmode)
4788e4b17023SJohn Marino && targetm.scalar_mode_supported_p (TDmode))
4789e4b17023SJohn Marino {
4790e4b17023SJohn Marino record_builtin_type (RID_DFLOAT32, NULL, dfloat32_type_node);
4791e4b17023SJohn Marino record_builtin_type (RID_DFLOAT64, NULL, dfloat64_type_node);
4792e4b17023SJohn Marino record_builtin_type (RID_DFLOAT128, NULL, dfloat128_type_node);
4793e4b17023SJohn Marino }
4794e4b17023SJohn Marino
4795e4b17023SJohn Marino if (targetm.fixed_point_supported_p ())
4796e4b17023SJohn Marino {
4797e4b17023SJohn Marino record_builtin_type (RID_MAX, "short _Fract", short_fract_type_node);
4798e4b17023SJohn Marino record_builtin_type (RID_FRACT, NULL, fract_type_node);
4799e4b17023SJohn Marino record_builtin_type (RID_MAX, "long _Fract", long_fract_type_node);
4800e4b17023SJohn Marino record_builtin_type (RID_MAX, "long long _Fract",
4801e4b17023SJohn Marino long_long_fract_type_node);
4802e4b17023SJohn Marino record_builtin_type (RID_MAX, "unsigned short _Fract",
4803e4b17023SJohn Marino unsigned_short_fract_type_node);
4804e4b17023SJohn Marino record_builtin_type (RID_MAX, "unsigned _Fract",
4805e4b17023SJohn Marino unsigned_fract_type_node);
4806e4b17023SJohn Marino record_builtin_type (RID_MAX, "unsigned long _Fract",
4807e4b17023SJohn Marino unsigned_long_fract_type_node);
4808e4b17023SJohn Marino record_builtin_type (RID_MAX, "unsigned long long _Fract",
4809e4b17023SJohn Marino unsigned_long_long_fract_type_node);
4810e4b17023SJohn Marino record_builtin_type (RID_MAX, "_Sat short _Fract",
4811e4b17023SJohn Marino sat_short_fract_type_node);
4812e4b17023SJohn Marino record_builtin_type (RID_MAX, "_Sat _Fract", sat_fract_type_node);
4813e4b17023SJohn Marino record_builtin_type (RID_MAX, "_Sat long _Fract",
4814e4b17023SJohn Marino sat_long_fract_type_node);
4815e4b17023SJohn Marino record_builtin_type (RID_MAX, "_Sat long long _Fract",
4816e4b17023SJohn Marino sat_long_long_fract_type_node);
4817e4b17023SJohn Marino record_builtin_type (RID_MAX, "_Sat unsigned short _Fract",
4818e4b17023SJohn Marino sat_unsigned_short_fract_type_node);
4819e4b17023SJohn Marino record_builtin_type (RID_MAX, "_Sat unsigned _Fract",
4820e4b17023SJohn Marino sat_unsigned_fract_type_node);
4821e4b17023SJohn Marino record_builtin_type (RID_MAX, "_Sat unsigned long _Fract",
4822e4b17023SJohn Marino sat_unsigned_long_fract_type_node);
4823e4b17023SJohn Marino record_builtin_type (RID_MAX, "_Sat unsigned long long _Fract",
4824e4b17023SJohn Marino sat_unsigned_long_long_fract_type_node);
4825e4b17023SJohn Marino record_builtin_type (RID_MAX, "short _Accum", short_accum_type_node);
4826e4b17023SJohn Marino record_builtin_type (RID_ACCUM, NULL, accum_type_node);
4827e4b17023SJohn Marino record_builtin_type (RID_MAX, "long _Accum", long_accum_type_node);
4828e4b17023SJohn Marino record_builtin_type (RID_MAX, "long long _Accum",
4829e4b17023SJohn Marino long_long_accum_type_node);
4830e4b17023SJohn Marino record_builtin_type (RID_MAX, "unsigned short _Accum",
4831e4b17023SJohn Marino unsigned_short_accum_type_node);
4832e4b17023SJohn Marino record_builtin_type (RID_MAX, "unsigned _Accum",
4833e4b17023SJohn Marino unsigned_accum_type_node);
4834e4b17023SJohn Marino record_builtin_type (RID_MAX, "unsigned long _Accum",
4835e4b17023SJohn Marino unsigned_long_accum_type_node);
4836e4b17023SJohn Marino record_builtin_type (RID_MAX, "unsigned long long _Accum",
4837e4b17023SJohn Marino unsigned_long_long_accum_type_node);
4838e4b17023SJohn Marino record_builtin_type (RID_MAX, "_Sat short _Accum",
4839e4b17023SJohn Marino sat_short_accum_type_node);
4840e4b17023SJohn Marino record_builtin_type (RID_MAX, "_Sat _Accum", sat_accum_type_node);
4841e4b17023SJohn Marino record_builtin_type (RID_MAX, "_Sat long _Accum",
4842e4b17023SJohn Marino sat_long_accum_type_node);
4843e4b17023SJohn Marino record_builtin_type (RID_MAX, "_Sat long long _Accum",
4844e4b17023SJohn Marino sat_long_long_accum_type_node);
4845e4b17023SJohn Marino record_builtin_type (RID_MAX, "_Sat unsigned short _Accum",
4846e4b17023SJohn Marino sat_unsigned_short_accum_type_node);
4847e4b17023SJohn Marino record_builtin_type (RID_MAX, "_Sat unsigned _Accum",
4848e4b17023SJohn Marino sat_unsigned_accum_type_node);
4849e4b17023SJohn Marino record_builtin_type (RID_MAX, "_Sat unsigned long _Accum",
4850e4b17023SJohn Marino sat_unsigned_long_accum_type_node);
4851e4b17023SJohn Marino record_builtin_type (RID_MAX, "_Sat unsigned long long _Accum",
4852e4b17023SJohn Marino sat_unsigned_long_long_accum_type_node);
4853e4b17023SJohn Marino
4854e4b17023SJohn Marino }
4855e4b17023SJohn Marino
4856e4b17023SJohn Marino lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
4857e4b17023SJohn Marino TYPE_DECL,
4858e4b17023SJohn Marino get_identifier ("complex int"),
4859e4b17023SJohn Marino complex_integer_type_node));
4860e4b17023SJohn Marino lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
4861e4b17023SJohn Marino TYPE_DECL,
4862e4b17023SJohn Marino get_identifier ("complex float"),
4863e4b17023SJohn Marino complex_float_type_node));
4864e4b17023SJohn Marino lang_hooks.decls.pushdecl (build_decl (UNKNOWN_LOCATION,
4865e4b17023SJohn Marino TYPE_DECL,
4866e4b17023SJohn Marino get_identifier ("complex double"),
4867e4b17023SJohn Marino complex_double_type_node));
4868e4b17023SJohn Marino lang_hooks.decls.pushdecl
4869e4b17023SJohn Marino (build_decl (UNKNOWN_LOCATION,
4870e4b17023SJohn Marino TYPE_DECL, get_identifier ("complex long double"),
4871e4b17023SJohn Marino complex_long_double_type_node));
4872e4b17023SJohn Marino
4873e4b17023SJohn Marino if (c_dialect_cxx ())
4874e4b17023SJohn Marino /* For C++, make fileptr_type_node a distinct void * type until
4875e4b17023SJohn Marino FILE type is defined. */
4876e4b17023SJohn Marino fileptr_type_node = build_variant_type_copy (ptr_type_node);
4877e4b17023SJohn Marino
4878e4b17023SJohn Marino record_builtin_type (RID_VOID, NULL, void_type_node);
4879e4b17023SJohn Marino
4880e4b17023SJohn Marino /* Set the TYPE_NAME for any variants that were built before
4881e4b17023SJohn Marino record_builtin_type gave names to the built-in types. */
4882e4b17023SJohn Marino {
4883e4b17023SJohn Marino tree void_name = TYPE_NAME (void_type_node);
4884e4b17023SJohn Marino TYPE_NAME (void_type_node) = NULL_TREE;
4885e4b17023SJohn Marino TYPE_NAME (build_qualified_type (void_type_node, TYPE_QUAL_CONST))
4886e4b17023SJohn Marino = void_name;
4887e4b17023SJohn Marino TYPE_NAME (void_type_node) = void_name;
4888e4b17023SJohn Marino }
4889e4b17023SJohn Marino
4890e4b17023SJohn Marino /* This node must not be shared. */
4891e4b17023SJohn Marino void_zero_node = make_node (INTEGER_CST);
4892e4b17023SJohn Marino TREE_TYPE (void_zero_node) = void_type_node;
4893e4b17023SJohn Marino
4894e4b17023SJohn Marino void_list_node = build_void_list_node ();
4895e4b17023SJohn Marino
4896e4b17023SJohn Marino /* Make a type to be the domain of a few array types
4897e4b17023SJohn Marino whose domains don't really matter.
4898e4b17023SJohn Marino 200 is small enough that it always fits in size_t
4899e4b17023SJohn Marino and large enough that it can hold most function names for the
4900e4b17023SJohn Marino initializations of __FUNCTION__ and __PRETTY_FUNCTION__. */
4901e4b17023SJohn Marino array_domain_type = build_index_type (size_int (200));
4902e4b17023SJohn Marino
4903e4b17023SJohn Marino /* Make a type for arrays of characters.
4904e4b17023SJohn Marino With luck nothing will ever really depend on the length of this
4905e4b17023SJohn Marino array type. */
4906e4b17023SJohn Marino char_array_type_node
4907e4b17023SJohn Marino = build_array_type (char_type_node, array_domain_type);
4908e4b17023SJohn Marino
4909e4b17023SJohn Marino /* Likewise for arrays of ints. */
4910e4b17023SJohn Marino int_array_type_node
4911e4b17023SJohn Marino = build_array_type (integer_type_node, array_domain_type);
4912e4b17023SJohn Marino
4913e4b17023SJohn Marino string_type_node = build_pointer_type (char_type_node);
4914e4b17023SJohn Marino const_string_type_node
4915e4b17023SJohn Marino = build_pointer_type (build_qualified_type
4916e4b17023SJohn Marino (char_type_node, TYPE_QUAL_CONST));
4917e4b17023SJohn Marino
4918e4b17023SJohn Marino /* This is special for C++ so functions can be overloaded. */
4919e4b17023SJohn Marino wchar_type_node = get_identifier (MODIFIED_WCHAR_TYPE);
4920e4b17023SJohn Marino wchar_type_node = TREE_TYPE (identifier_global_value (wchar_type_node));
4921e4b17023SJohn Marino wchar_type_size = TYPE_PRECISION (wchar_type_node);
4922e4b17023SJohn Marino underlying_wchar_type_node = wchar_type_node;
4923e4b17023SJohn Marino if (c_dialect_cxx ())
4924e4b17023SJohn Marino {
4925e4b17023SJohn Marino if (TYPE_UNSIGNED (wchar_type_node))
4926e4b17023SJohn Marino wchar_type_node = make_unsigned_type (wchar_type_size);
4927e4b17023SJohn Marino else
4928e4b17023SJohn Marino wchar_type_node = make_signed_type (wchar_type_size);
4929e4b17023SJohn Marino record_builtin_type (RID_WCHAR, "wchar_t", wchar_type_node);
4930e4b17023SJohn Marino }
4931e4b17023SJohn Marino
4932e4b17023SJohn Marino /* This is for wide string constants. */
4933e4b17023SJohn Marino wchar_array_type_node
4934e4b17023SJohn Marino = build_array_type (wchar_type_node, array_domain_type);
4935e4b17023SJohn Marino
4936e4b17023SJohn Marino /* Define 'char16_t'. */
4937e4b17023SJohn Marino char16_type_node = get_identifier (CHAR16_TYPE);
4938e4b17023SJohn Marino char16_type_node = TREE_TYPE (identifier_global_value (char16_type_node));
4939e4b17023SJohn Marino char16_type_size = TYPE_PRECISION (char16_type_node);
4940e4b17023SJohn Marino if (c_dialect_cxx ())
4941e4b17023SJohn Marino {
4942e4b17023SJohn Marino char16_type_node = make_unsigned_type (char16_type_size);
4943e4b17023SJohn Marino
4944e4b17023SJohn Marino if (cxx_dialect == cxx0x)
4945e4b17023SJohn Marino record_builtin_type (RID_CHAR16, "char16_t", char16_type_node);
4946e4b17023SJohn Marino }
4947e4b17023SJohn Marino
4948e4b17023SJohn Marino /* This is for UTF-16 string constants. */
4949e4b17023SJohn Marino char16_array_type_node
4950e4b17023SJohn Marino = build_array_type (char16_type_node, array_domain_type);
4951e4b17023SJohn Marino
4952e4b17023SJohn Marino /* Define 'char32_t'. */
4953e4b17023SJohn Marino char32_type_node = get_identifier (CHAR32_TYPE);
4954e4b17023SJohn Marino char32_type_node = TREE_TYPE (identifier_global_value (char32_type_node));
4955e4b17023SJohn Marino char32_type_size = TYPE_PRECISION (char32_type_node);
4956e4b17023SJohn Marino if (c_dialect_cxx ())
4957e4b17023SJohn Marino {
4958e4b17023SJohn Marino char32_type_node = make_unsigned_type (char32_type_size);
4959e4b17023SJohn Marino
4960e4b17023SJohn Marino if (cxx_dialect == cxx0x)
4961e4b17023SJohn Marino record_builtin_type (RID_CHAR32, "char32_t", char32_type_node);
4962e4b17023SJohn Marino }
4963e4b17023SJohn Marino
4964e4b17023SJohn Marino /* This is for UTF-32 string constants. */
4965e4b17023SJohn Marino char32_array_type_node
4966e4b17023SJohn Marino = build_array_type (char32_type_node, array_domain_type);
4967e4b17023SJohn Marino
4968e4b17023SJohn Marino wint_type_node =
4969e4b17023SJohn Marino TREE_TYPE (identifier_global_value (get_identifier (WINT_TYPE)));
4970e4b17023SJohn Marino
4971e4b17023SJohn Marino intmax_type_node =
4972e4b17023SJohn Marino TREE_TYPE (identifier_global_value (get_identifier (INTMAX_TYPE)));
4973e4b17023SJohn Marino uintmax_type_node =
4974e4b17023SJohn Marino TREE_TYPE (identifier_global_value (get_identifier (UINTMAX_TYPE)));
4975e4b17023SJohn Marino
4976e4b17023SJohn Marino if (SIG_ATOMIC_TYPE)
4977e4b17023SJohn Marino sig_atomic_type_node =
4978e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (SIG_ATOMIC_TYPE)));
4979e4b17023SJohn Marino if (INT8_TYPE)
4980e4b17023SJohn Marino int8_type_node =
4981e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (INT8_TYPE)));
4982e4b17023SJohn Marino if (INT16_TYPE)
4983e4b17023SJohn Marino int16_type_node =
4984e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (INT16_TYPE)));
4985e4b17023SJohn Marino if (INT32_TYPE)
4986e4b17023SJohn Marino int32_type_node =
4987e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (INT32_TYPE)));
4988e4b17023SJohn Marino if (INT64_TYPE)
4989e4b17023SJohn Marino int64_type_node =
4990e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (INT64_TYPE)));
4991e4b17023SJohn Marino if (UINT8_TYPE)
4992e4b17023SJohn Marino uint8_type_node =
4993e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (UINT8_TYPE)));
4994e4b17023SJohn Marino if (UINT16_TYPE)
4995e4b17023SJohn Marino uint16_type_node =
4996e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (UINT16_TYPE)));
4997e4b17023SJohn Marino if (UINT32_TYPE)
4998e4b17023SJohn Marino c_uint32_type_node =
4999e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (UINT32_TYPE)));
5000e4b17023SJohn Marino if (UINT64_TYPE)
5001e4b17023SJohn Marino c_uint64_type_node =
5002e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (UINT64_TYPE)));
5003e4b17023SJohn Marino if (INT_LEAST8_TYPE)
5004e4b17023SJohn Marino int_least8_type_node =
5005e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (INT_LEAST8_TYPE)));
5006e4b17023SJohn Marino if (INT_LEAST16_TYPE)
5007e4b17023SJohn Marino int_least16_type_node =
5008e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (INT_LEAST16_TYPE)));
5009e4b17023SJohn Marino if (INT_LEAST32_TYPE)
5010e4b17023SJohn Marino int_least32_type_node =
5011e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (INT_LEAST32_TYPE)));
5012e4b17023SJohn Marino if (INT_LEAST64_TYPE)
5013e4b17023SJohn Marino int_least64_type_node =
5014e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (INT_LEAST64_TYPE)));
5015e4b17023SJohn Marino if (UINT_LEAST8_TYPE)
5016e4b17023SJohn Marino uint_least8_type_node =
5017e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (UINT_LEAST8_TYPE)));
5018e4b17023SJohn Marino if (UINT_LEAST16_TYPE)
5019e4b17023SJohn Marino uint_least16_type_node =
5020e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (UINT_LEAST16_TYPE)));
5021e4b17023SJohn Marino if (UINT_LEAST32_TYPE)
5022e4b17023SJohn Marino uint_least32_type_node =
5023e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (UINT_LEAST32_TYPE)));
5024e4b17023SJohn Marino if (UINT_LEAST64_TYPE)
5025e4b17023SJohn Marino uint_least64_type_node =
5026e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (UINT_LEAST64_TYPE)));
5027e4b17023SJohn Marino if (INT_FAST8_TYPE)
5028e4b17023SJohn Marino int_fast8_type_node =
5029e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (INT_FAST8_TYPE)));
5030e4b17023SJohn Marino if (INT_FAST16_TYPE)
5031e4b17023SJohn Marino int_fast16_type_node =
5032e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (INT_FAST16_TYPE)));
5033e4b17023SJohn Marino if (INT_FAST32_TYPE)
5034e4b17023SJohn Marino int_fast32_type_node =
5035e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (INT_FAST32_TYPE)));
5036e4b17023SJohn Marino if (INT_FAST64_TYPE)
5037e4b17023SJohn Marino int_fast64_type_node =
5038e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (INT_FAST64_TYPE)));
5039e4b17023SJohn Marino if (UINT_FAST8_TYPE)
5040e4b17023SJohn Marino uint_fast8_type_node =
5041e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (UINT_FAST8_TYPE)));
5042e4b17023SJohn Marino if (UINT_FAST16_TYPE)
5043e4b17023SJohn Marino uint_fast16_type_node =
5044e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (UINT_FAST16_TYPE)));
5045e4b17023SJohn Marino if (UINT_FAST32_TYPE)
5046e4b17023SJohn Marino uint_fast32_type_node =
5047e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (UINT_FAST32_TYPE)));
5048e4b17023SJohn Marino if (UINT_FAST64_TYPE)
5049e4b17023SJohn Marino uint_fast64_type_node =
5050e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (UINT_FAST64_TYPE)));
5051e4b17023SJohn Marino if (INTPTR_TYPE)
5052e4b17023SJohn Marino intptr_type_node =
5053e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (INTPTR_TYPE)));
5054e4b17023SJohn Marino if (UINTPTR_TYPE)
5055e4b17023SJohn Marino uintptr_type_node =
5056e4b17023SJohn Marino TREE_TYPE (identifier_global_value (c_get_ident (UINTPTR_TYPE)));
5057e4b17023SJohn Marino
5058e4b17023SJohn Marino default_function_type
5059e4b17023SJohn Marino = build_varargs_function_type_list (integer_type_node, NULL_TREE);
5060e4b17023SJohn Marino ptrdiff_type_node
5061e4b17023SJohn Marino = TREE_TYPE (identifier_global_value (get_identifier (PTRDIFF_TYPE)));
5062e4b17023SJohn Marino unsigned_ptrdiff_type_node = c_common_unsigned_type (ptrdiff_type_node);
5063e4b17023SJohn Marino
5064e4b17023SJohn Marino lang_hooks.decls.pushdecl
5065e4b17023SJohn Marino (build_decl (UNKNOWN_LOCATION,
5066e4b17023SJohn Marino TYPE_DECL, get_identifier ("__builtin_va_list"),
5067e4b17023SJohn Marino va_list_type_node));
5068e4b17023SJohn Marino if (targetm.enum_va_list_p)
5069e4b17023SJohn Marino {
5070e4b17023SJohn Marino int l;
5071e4b17023SJohn Marino const char *pname;
5072e4b17023SJohn Marino tree ptype;
5073e4b17023SJohn Marino
5074e4b17023SJohn Marino for (l = 0; targetm.enum_va_list_p (l, &pname, &ptype); ++l)
5075e4b17023SJohn Marino {
5076e4b17023SJohn Marino lang_hooks.decls.pushdecl
5077e4b17023SJohn Marino (build_decl (UNKNOWN_LOCATION,
5078e4b17023SJohn Marino TYPE_DECL, get_identifier (pname),
5079e4b17023SJohn Marino ptype));
5080e4b17023SJohn Marino
5081e4b17023SJohn Marino }
5082e4b17023SJohn Marino }
5083e4b17023SJohn Marino
5084e4b17023SJohn Marino if (TREE_CODE (va_list_type_node) == ARRAY_TYPE)
5085e4b17023SJohn Marino {
5086e4b17023SJohn Marino va_list_arg_type_node = va_list_ref_type_node =
5087e4b17023SJohn Marino build_pointer_type (TREE_TYPE (va_list_type_node));
5088e4b17023SJohn Marino }
5089e4b17023SJohn Marino else
5090e4b17023SJohn Marino {
5091e4b17023SJohn Marino va_list_arg_type_node = va_list_type_node;
5092e4b17023SJohn Marino va_list_ref_type_node = build_reference_type (va_list_type_node);
5093e4b17023SJohn Marino }
5094e4b17023SJohn Marino
5095e4b17023SJohn Marino if (!flag_preprocess_only)
5096e4b17023SJohn Marino c_define_builtins (va_list_ref_type_node, va_list_arg_type_node);
5097e4b17023SJohn Marino
5098e4b17023SJohn Marino main_identifier_node = get_identifier ("main");
5099e4b17023SJohn Marino
5100e4b17023SJohn Marino /* Create the built-in __null node. It is important that this is
5101e4b17023SJohn Marino not shared. */
5102e4b17023SJohn Marino null_node = make_node (INTEGER_CST);
5103e4b17023SJohn Marino TREE_TYPE (null_node) = c_common_type_for_size (POINTER_SIZE, 0);
5104e4b17023SJohn Marino
5105e4b17023SJohn Marino /* Since builtin_types isn't gc'ed, don't export these nodes. */
5106e4b17023SJohn Marino memset (builtin_types, 0, sizeof (builtin_types));
5107e4b17023SJohn Marino }
5108e4b17023SJohn Marino
5109e4b17023SJohn Marino /* The number of named compound-literals generated thus far. */
5110e4b17023SJohn Marino static GTY(()) int compound_literal_number;
5111e4b17023SJohn Marino
5112e4b17023SJohn Marino /* Set DECL_NAME for DECL, a VAR_DECL for a compound-literal. */
5113e4b17023SJohn Marino
5114e4b17023SJohn Marino void
set_compound_literal_name(tree decl)5115e4b17023SJohn Marino set_compound_literal_name (tree decl)
5116e4b17023SJohn Marino {
5117e4b17023SJohn Marino char *name;
5118e4b17023SJohn Marino ASM_FORMAT_PRIVATE_NAME (name, "__compound_literal",
5119e4b17023SJohn Marino compound_literal_number);
5120e4b17023SJohn Marino compound_literal_number++;
5121e4b17023SJohn Marino DECL_NAME (decl) = get_identifier (name);
5122e4b17023SJohn Marino }
5123e4b17023SJohn Marino
5124e4b17023SJohn Marino tree
build_va_arg(location_t loc,tree expr,tree type)5125e4b17023SJohn Marino build_va_arg (location_t loc, tree expr, tree type)
5126e4b17023SJohn Marino {
5127e4b17023SJohn Marino expr = build1 (VA_ARG_EXPR, type, expr);
5128e4b17023SJohn Marino SET_EXPR_LOCATION (expr, loc);
5129e4b17023SJohn Marino return expr;
5130e4b17023SJohn Marino }
5131e4b17023SJohn Marino
5132e4b17023SJohn Marino
5133e4b17023SJohn Marino /* Linked list of disabled built-in functions. */
5134e4b17023SJohn Marino
5135e4b17023SJohn Marino typedef struct disabled_builtin
5136e4b17023SJohn Marino {
5137e4b17023SJohn Marino const char *name;
5138e4b17023SJohn Marino struct disabled_builtin *next;
5139e4b17023SJohn Marino } disabled_builtin;
5140e4b17023SJohn Marino static disabled_builtin *disabled_builtins = NULL;
5141e4b17023SJohn Marino
5142e4b17023SJohn Marino static bool builtin_function_disabled_p (const char *);
5143e4b17023SJohn Marino
5144e4b17023SJohn Marino /* Disable a built-in function specified by -fno-builtin-NAME. If NAME
5145e4b17023SJohn Marino begins with "__builtin_", give an error. */
5146e4b17023SJohn Marino
5147e4b17023SJohn Marino void
disable_builtin_function(const char * name)5148e4b17023SJohn Marino disable_builtin_function (const char *name)
5149e4b17023SJohn Marino {
5150e4b17023SJohn Marino if (strncmp (name, "__builtin_", strlen ("__builtin_")) == 0)
5151e4b17023SJohn Marino error ("cannot disable built-in function %qs", name);
5152e4b17023SJohn Marino else
5153e4b17023SJohn Marino {
5154e4b17023SJohn Marino disabled_builtin *new_disabled_builtin = XNEW (disabled_builtin);
5155e4b17023SJohn Marino new_disabled_builtin->name = name;
5156e4b17023SJohn Marino new_disabled_builtin->next = disabled_builtins;
5157e4b17023SJohn Marino disabled_builtins = new_disabled_builtin;
5158e4b17023SJohn Marino }
5159e4b17023SJohn Marino }
5160e4b17023SJohn Marino
5161e4b17023SJohn Marino
5162e4b17023SJohn Marino /* Return true if the built-in function NAME has been disabled, false
5163e4b17023SJohn Marino otherwise. */
5164e4b17023SJohn Marino
5165e4b17023SJohn Marino static bool
builtin_function_disabled_p(const char * name)5166e4b17023SJohn Marino builtin_function_disabled_p (const char *name)
5167e4b17023SJohn Marino {
5168e4b17023SJohn Marino disabled_builtin *p;
5169e4b17023SJohn Marino for (p = disabled_builtins; p != NULL; p = p->next)
5170e4b17023SJohn Marino {
5171e4b17023SJohn Marino if (strcmp (name, p->name) == 0)
5172e4b17023SJohn Marino return true;
5173e4b17023SJohn Marino }
5174e4b17023SJohn Marino return false;
5175e4b17023SJohn Marino }
5176e4b17023SJohn Marino
5177e4b17023SJohn Marino
5178e4b17023SJohn Marino /* Worker for DEF_BUILTIN.
5179e4b17023SJohn Marino Possibly define a builtin function with one or two names.
5180e4b17023SJohn Marino Does not declare a non-__builtin_ function if flag_no_builtin, or if
5181e4b17023SJohn Marino nonansi_p and flag_no_nonansi_builtin. */
5182e4b17023SJohn Marino
5183e4b17023SJohn Marino static void
def_builtin_1(enum built_in_function fncode,const char * name,enum built_in_class fnclass,tree fntype,tree libtype,bool both_p,bool fallback_p,bool nonansi_p,tree fnattrs,bool implicit_p)5184e4b17023SJohn Marino def_builtin_1 (enum built_in_function fncode,
5185e4b17023SJohn Marino const char *name,
5186e4b17023SJohn Marino enum built_in_class fnclass,
5187e4b17023SJohn Marino tree fntype, tree libtype,
5188e4b17023SJohn Marino bool both_p, bool fallback_p, bool nonansi_p,
5189e4b17023SJohn Marino tree fnattrs, bool implicit_p)
5190e4b17023SJohn Marino {
5191e4b17023SJohn Marino tree decl;
5192e4b17023SJohn Marino const char *libname;
5193e4b17023SJohn Marino
5194e4b17023SJohn Marino if (fntype == error_mark_node)
5195e4b17023SJohn Marino return;
5196e4b17023SJohn Marino
5197e4b17023SJohn Marino gcc_assert ((!both_p && !fallback_p)
5198e4b17023SJohn Marino || !strncmp (name, "__builtin_",
5199e4b17023SJohn Marino strlen ("__builtin_")));
5200e4b17023SJohn Marino
5201e4b17023SJohn Marino libname = name + strlen ("__builtin_");
5202e4b17023SJohn Marino decl = add_builtin_function (name, fntype, fncode, fnclass,
5203e4b17023SJohn Marino (fallback_p ? libname : NULL),
5204e4b17023SJohn Marino fnattrs);
5205e4b17023SJohn Marino
5206e4b17023SJohn Marino set_builtin_decl (fncode, decl, implicit_p);
5207e4b17023SJohn Marino
5208e4b17023SJohn Marino if (both_p
5209e4b17023SJohn Marino && !flag_no_builtin && !builtin_function_disabled_p (libname)
5210e4b17023SJohn Marino && !(nonansi_p && flag_no_nonansi_builtin))
5211e4b17023SJohn Marino add_builtin_function (libname, libtype, fncode, fnclass,
5212e4b17023SJohn Marino NULL, fnattrs);
5213e4b17023SJohn Marino }
5214e4b17023SJohn Marino
5215e4b17023SJohn Marino /* Nonzero if the type T promotes to int. This is (nearly) the
5216e4b17023SJohn Marino integral promotions defined in ISO C99 6.3.1.1/2. */
5217e4b17023SJohn Marino
5218e4b17023SJohn Marino bool
c_promoting_integer_type_p(const_tree t)5219e4b17023SJohn Marino c_promoting_integer_type_p (const_tree t)
5220e4b17023SJohn Marino {
5221e4b17023SJohn Marino switch (TREE_CODE (t))
5222e4b17023SJohn Marino {
5223e4b17023SJohn Marino case INTEGER_TYPE:
5224e4b17023SJohn Marino return (TYPE_MAIN_VARIANT (t) == char_type_node
5225e4b17023SJohn Marino || TYPE_MAIN_VARIANT (t) == signed_char_type_node
5226e4b17023SJohn Marino || TYPE_MAIN_VARIANT (t) == unsigned_char_type_node
5227e4b17023SJohn Marino || TYPE_MAIN_VARIANT (t) == short_integer_type_node
5228e4b17023SJohn Marino || TYPE_MAIN_VARIANT (t) == short_unsigned_type_node
5229e4b17023SJohn Marino || TYPE_PRECISION (t) < TYPE_PRECISION (integer_type_node));
5230e4b17023SJohn Marino
5231e4b17023SJohn Marino case ENUMERAL_TYPE:
5232e4b17023SJohn Marino /* ??? Technically all enumerations not larger than an int
5233e4b17023SJohn Marino promote to an int. But this is used along code paths
5234e4b17023SJohn Marino that only want to notice a size change. */
5235e4b17023SJohn Marino return TYPE_PRECISION (t) < TYPE_PRECISION (integer_type_node);
5236e4b17023SJohn Marino
5237e4b17023SJohn Marino case BOOLEAN_TYPE:
5238e4b17023SJohn Marino return 1;
5239e4b17023SJohn Marino
5240e4b17023SJohn Marino default:
5241e4b17023SJohn Marino return 0;
5242e4b17023SJohn Marino }
5243e4b17023SJohn Marino }
5244e4b17023SJohn Marino
5245e4b17023SJohn Marino /* Return 1 if PARMS specifies a fixed number of parameters
5246e4b17023SJohn Marino and none of their types is affected by default promotions. */
5247e4b17023SJohn Marino
5248e4b17023SJohn Marino int
self_promoting_args_p(const_tree parms)5249e4b17023SJohn Marino self_promoting_args_p (const_tree parms)
5250e4b17023SJohn Marino {
5251e4b17023SJohn Marino const_tree t;
5252e4b17023SJohn Marino for (t = parms; t; t = TREE_CHAIN (t))
5253e4b17023SJohn Marino {
5254e4b17023SJohn Marino tree type = TREE_VALUE (t);
5255e4b17023SJohn Marino
5256e4b17023SJohn Marino if (type == error_mark_node)
5257e4b17023SJohn Marino continue;
5258e4b17023SJohn Marino
5259e4b17023SJohn Marino if (TREE_CHAIN (t) == 0 && type != void_type_node)
5260e4b17023SJohn Marino return 0;
5261e4b17023SJohn Marino
5262e4b17023SJohn Marino if (type == 0)
5263e4b17023SJohn Marino return 0;
5264e4b17023SJohn Marino
5265e4b17023SJohn Marino if (TYPE_MAIN_VARIANT (type) == float_type_node)
5266e4b17023SJohn Marino return 0;
5267e4b17023SJohn Marino
5268e4b17023SJohn Marino if (c_promoting_integer_type_p (type))
5269e4b17023SJohn Marino return 0;
5270e4b17023SJohn Marino }
5271e4b17023SJohn Marino return 1;
5272e4b17023SJohn Marino }
5273e4b17023SJohn Marino
5274e4b17023SJohn Marino /* Recursively remove any '*' or '&' operator from TYPE. */
5275e4b17023SJohn Marino tree
strip_pointer_operator(tree t)5276e4b17023SJohn Marino strip_pointer_operator (tree t)
5277e4b17023SJohn Marino {
5278e4b17023SJohn Marino while (POINTER_TYPE_P (t))
5279e4b17023SJohn Marino t = TREE_TYPE (t);
5280e4b17023SJohn Marino return t;
5281e4b17023SJohn Marino }
5282e4b17023SJohn Marino
5283e4b17023SJohn Marino /* Recursively remove pointer or array type from TYPE. */
5284e4b17023SJohn Marino tree
strip_pointer_or_array_types(tree t)5285e4b17023SJohn Marino strip_pointer_or_array_types (tree t)
5286e4b17023SJohn Marino {
5287e4b17023SJohn Marino while (TREE_CODE (t) == ARRAY_TYPE || POINTER_TYPE_P (t))
5288e4b17023SJohn Marino t = TREE_TYPE (t);
5289e4b17023SJohn Marino return t;
5290e4b17023SJohn Marino }
5291e4b17023SJohn Marino
5292e4b17023SJohn Marino /* Used to compare case labels. K1 and K2 are actually tree nodes
5293e4b17023SJohn Marino representing case labels, or NULL_TREE for a `default' label.
5294e4b17023SJohn Marino Returns -1 if K1 is ordered before K2, -1 if K1 is ordered after
5295e4b17023SJohn Marino K2, and 0 if K1 and K2 are equal. */
5296e4b17023SJohn Marino
5297e4b17023SJohn Marino int
case_compare(splay_tree_key k1,splay_tree_key k2)5298e4b17023SJohn Marino case_compare (splay_tree_key k1, splay_tree_key k2)
5299e4b17023SJohn Marino {
5300e4b17023SJohn Marino /* Consider a NULL key (such as arises with a `default' label) to be
5301e4b17023SJohn Marino smaller than anything else. */
5302e4b17023SJohn Marino if (!k1)
5303e4b17023SJohn Marino return k2 ? -1 : 0;
5304e4b17023SJohn Marino else if (!k2)
5305e4b17023SJohn Marino return k1 ? 1 : 0;
5306e4b17023SJohn Marino
5307e4b17023SJohn Marino return tree_int_cst_compare ((tree) k1, (tree) k2);
5308e4b17023SJohn Marino }
5309e4b17023SJohn Marino
5310e4b17023SJohn Marino /* Process a case label, located at LOC, for the range LOW_VALUE
5311e4b17023SJohn Marino ... HIGH_VALUE. If LOW_VALUE and HIGH_VALUE are both NULL_TREE
5312e4b17023SJohn Marino then this case label is actually a `default' label. If only
5313e4b17023SJohn Marino HIGH_VALUE is NULL_TREE, then case label was declared using the
5314e4b17023SJohn Marino usual C/C++ syntax, rather than the GNU case range extension.
5315e4b17023SJohn Marino CASES is a tree containing all the case ranges processed so far;
5316e4b17023SJohn Marino COND is the condition for the switch-statement itself. Returns the
5317e4b17023SJohn Marino CASE_LABEL_EXPR created, or ERROR_MARK_NODE if no CASE_LABEL_EXPR
5318e4b17023SJohn Marino is created. */
5319e4b17023SJohn Marino
5320e4b17023SJohn Marino tree
c_add_case_label(location_t loc,splay_tree cases,tree cond,tree orig_type,tree low_value,tree high_value)5321e4b17023SJohn Marino c_add_case_label (location_t loc, splay_tree cases, tree cond, tree orig_type,
5322e4b17023SJohn Marino tree low_value, tree high_value)
5323e4b17023SJohn Marino {
5324e4b17023SJohn Marino tree type;
5325e4b17023SJohn Marino tree label;
5326e4b17023SJohn Marino tree case_label;
5327e4b17023SJohn Marino splay_tree_node node;
5328e4b17023SJohn Marino
5329e4b17023SJohn Marino /* Create the LABEL_DECL itself. */
5330e4b17023SJohn Marino label = create_artificial_label (loc);
5331e4b17023SJohn Marino
5332e4b17023SJohn Marino /* If there was an error processing the switch condition, bail now
5333e4b17023SJohn Marino before we get more confused. */
5334e4b17023SJohn Marino if (!cond || cond == error_mark_node)
5335e4b17023SJohn Marino goto error_out;
5336e4b17023SJohn Marino
5337e4b17023SJohn Marino if ((low_value && TREE_TYPE (low_value)
5338e4b17023SJohn Marino && POINTER_TYPE_P (TREE_TYPE (low_value)))
5339e4b17023SJohn Marino || (high_value && TREE_TYPE (high_value)
5340e4b17023SJohn Marino && POINTER_TYPE_P (TREE_TYPE (high_value))))
5341e4b17023SJohn Marino {
5342e4b17023SJohn Marino error_at (loc, "pointers are not permitted as case values");
5343e4b17023SJohn Marino goto error_out;
5344e4b17023SJohn Marino }
5345e4b17023SJohn Marino
5346e4b17023SJohn Marino /* Case ranges are a GNU extension. */
5347e4b17023SJohn Marino if (high_value)
5348e4b17023SJohn Marino pedwarn (loc, OPT_pedantic,
5349e4b17023SJohn Marino "range expressions in switch statements are non-standard");
5350e4b17023SJohn Marino
5351e4b17023SJohn Marino type = TREE_TYPE (cond);
5352e4b17023SJohn Marino if (low_value)
5353e4b17023SJohn Marino {
5354e4b17023SJohn Marino low_value = check_case_value (low_value);
5355e4b17023SJohn Marino low_value = convert_and_check (type, low_value);
5356e4b17023SJohn Marino if (low_value == error_mark_node)
5357e4b17023SJohn Marino goto error_out;
5358e4b17023SJohn Marino }
5359e4b17023SJohn Marino if (high_value)
5360e4b17023SJohn Marino {
5361e4b17023SJohn Marino high_value = check_case_value (high_value);
5362e4b17023SJohn Marino high_value = convert_and_check (type, high_value);
5363e4b17023SJohn Marino if (high_value == error_mark_node)
5364e4b17023SJohn Marino goto error_out;
5365e4b17023SJohn Marino }
5366e4b17023SJohn Marino
5367e4b17023SJohn Marino if (low_value && high_value)
5368e4b17023SJohn Marino {
5369e4b17023SJohn Marino /* If the LOW_VALUE and HIGH_VALUE are the same, then this isn't
5370e4b17023SJohn Marino really a case range, even though it was written that way.
5371e4b17023SJohn Marino Remove the HIGH_VALUE to simplify later processing. */
5372e4b17023SJohn Marino if (tree_int_cst_equal (low_value, high_value))
5373e4b17023SJohn Marino high_value = NULL_TREE;
5374e4b17023SJohn Marino else if (!tree_int_cst_lt (low_value, high_value))
5375e4b17023SJohn Marino warning_at (loc, 0, "empty range specified");
5376e4b17023SJohn Marino }
5377e4b17023SJohn Marino
5378e4b17023SJohn Marino /* See if the case is in range of the type of the original testing
5379e4b17023SJohn Marino expression. If both low_value and high_value are out of range,
5380e4b17023SJohn Marino don't insert the case label and return NULL_TREE. */
5381e4b17023SJohn Marino if (low_value
5382e4b17023SJohn Marino && !check_case_bounds (type, orig_type,
5383e4b17023SJohn Marino &low_value, high_value ? &high_value : NULL))
5384e4b17023SJohn Marino return NULL_TREE;
5385e4b17023SJohn Marino
5386e4b17023SJohn Marino /* Look up the LOW_VALUE in the table of case labels we already
5387e4b17023SJohn Marino have. */
5388e4b17023SJohn Marino node = splay_tree_lookup (cases, (splay_tree_key) low_value);
5389e4b17023SJohn Marino /* If there was not an exact match, check for overlapping ranges.
5390e4b17023SJohn Marino There's no need to do this if there's no LOW_VALUE or HIGH_VALUE;
5391e4b17023SJohn Marino that's a `default' label and the only overlap is an exact match. */
5392e4b17023SJohn Marino if (!node && (low_value || high_value))
5393e4b17023SJohn Marino {
5394e4b17023SJohn Marino splay_tree_node low_bound;
5395e4b17023SJohn Marino splay_tree_node high_bound;
5396e4b17023SJohn Marino
5397e4b17023SJohn Marino /* Even though there wasn't an exact match, there might be an
5398e4b17023SJohn Marino overlap between this case range and another case range.
5399e4b17023SJohn Marino Since we've (inductively) not allowed any overlapping case
5400e4b17023SJohn Marino ranges, we simply need to find the greatest low case label
5401e4b17023SJohn Marino that is smaller that LOW_VALUE, and the smallest low case
5402e4b17023SJohn Marino label that is greater than LOW_VALUE. If there is an overlap
5403e4b17023SJohn Marino it will occur in one of these two ranges. */
5404e4b17023SJohn Marino low_bound = splay_tree_predecessor (cases,
5405e4b17023SJohn Marino (splay_tree_key) low_value);
5406e4b17023SJohn Marino high_bound = splay_tree_successor (cases,
5407e4b17023SJohn Marino (splay_tree_key) low_value);
5408e4b17023SJohn Marino
5409e4b17023SJohn Marino /* Check to see if the LOW_BOUND overlaps. It is smaller than
5410e4b17023SJohn Marino the LOW_VALUE, so there is no need to check unless the
5411e4b17023SJohn Marino LOW_BOUND is in fact itself a case range. */
5412e4b17023SJohn Marino if (low_bound
5413e4b17023SJohn Marino && CASE_HIGH ((tree) low_bound->value)
5414e4b17023SJohn Marino && tree_int_cst_compare (CASE_HIGH ((tree) low_bound->value),
5415e4b17023SJohn Marino low_value) >= 0)
5416e4b17023SJohn Marino node = low_bound;
5417e4b17023SJohn Marino /* Check to see if the HIGH_BOUND overlaps. The low end of that
5418e4b17023SJohn Marino range is bigger than the low end of the current range, so we
5419e4b17023SJohn Marino are only interested if the current range is a real range, and
5420e4b17023SJohn Marino not an ordinary case label. */
5421e4b17023SJohn Marino else if (high_bound
5422e4b17023SJohn Marino && high_value
5423e4b17023SJohn Marino && (tree_int_cst_compare ((tree) high_bound->key,
5424e4b17023SJohn Marino high_value)
5425e4b17023SJohn Marino <= 0))
5426e4b17023SJohn Marino node = high_bound;
5427e4b17023SJohn Marino }
5428e4b17023SJohn Marino /* If there was an overlap, issue an error. */
5429e4b17023SJohn Marino if (node)
5430e4b17023SJohn Marino {
5431e4b17023SJohn Marino tree duplicate = CASE_LABEL ((tree) node->value);
5432e4b17023SJohn Marino
5433e4b17023SJohn Marino if (high_value)
5434e4b17023SJohn Marino {
5435e4b17023SJohn Marino error_at (loc, "duplicate (or overlapping) case value");
5436e4b17023SJohn Marino error_at (DECL_SOURCE_LOCATION (duplicate),
5437e4b17023SJohn Marino "this is the first entry overlapping that value");
5438e4b17023SJohn Marino }
5439e4b17023SJohn Marino else if (low_value)
5440e4b17023SJohn Marino {
5441e4b17023SJohn Marino error_at (loc, "duplicate case value") ;
5442e4b17023SJohn Marino error_at (DECL_SOURCE_LOCATION (duplicate), "previously used here");
5443e4b17023SJohn Marino }
5444e4b17023SJohn Marino else
5445e4b17023SJohn Marino {
5446e4b17023SJohn Marino error_at (loc, "multiple default labels in one switch");
5447e4b17023SJohn Marino error_at (DECL_SOURCE_LOCATION (duplicate),
5448e4b17023SJohn Marino "this is the first default label");
5449e4b17023SJohn Marino }
5450e4b17023SJohn Marino goto error_out;
5451e4b17023SJohn Marino }
5452e4b17023SJohn Marino
5453e4b17023SJohn Marino /* Add a CASE_LABEL to the statement-tree. */
5454e4b17023SJohn Marino case_label = add_stmt (build_case_label (low_value, high_value, label));
5455e4b17023SJohn Marino /* Register this case label in the splay tree. */
5456e4b17023SJohn Marino splay_tree_insert (cases,
5457e4b17023SJohn Marino (splay_tree_key) low_value,
5458e4b17023SJohn Marino (splay_tree_value) case_label);
5459e4b17023SJohn Marino
5460e4b17023SJohn Marino return case_label;
5461e4b17023SJohn Marino
5462e4b17023SJohn Marino error_out:
5463e4b17023SJohn Marino /* Add a label so that the back-end doesn't think that the beginning of
5464e4b17023SJohn Marino the switch is unreachable. Note that we do not add a case label, as
5465e4b17023SJohn Marino that just leads to duplicates and thence to failure later on. */
5466e4b17023SJohn Marino if (!cases->root)
5467e4b17023SJohn Marino {
5468e4b17023SJohn Marino tree t = create_artificial_label (loc);
5469e4b17023SJohn Marino add_stmt (build_stmt (loc, LABEL_EXPR, t));
5470e4b17023SJohn Marino }
5471e4b17023SJohn Marino return error_mark_node;
5472e4b17023SJohn Marino }
5473e4b17023SJohn Marino
5474e4b17023SJohn Marino /* Subroutines of c_do_switch_warnings, called via splay_tree_foreach.
5475e4b17023SJohn Marino Used to verify that case values match up with enumerator values. */
5476e4b17023SJohn Marino
5477e4b17023SJohn Marino static void
match_case_to_enum_1(tree key,tree type,tree label)5478e4b17023SJohn Marino match_case_to_enum_1 (tree key, tree type, tree label)
5479e4b17023SJohn Marino {
5480e4b17023SJohn Marino char buf[2 + 2*HOST_BITS_PER_WIDE_INT/4 + 1];
5481e4b17023SJohn Marino
5482e4b17023SJohn Marino /* ??? Not working too hard to print the double-word value.
5483e4b17023SJohn Marino Should perhaps be done with %lwd in the diagnostic routines? */
5484e4b17023SJohn Marino if (TREE_INT_CST_HIGH (key) == 0)
5485e4b17023SJohn Marino snprintf (buf, sizeof (buf), HOST_WIDE_INT_PRINT_UNSIGNED,
5486e4b17023SJohn Marino TREE_INT_CST_LOW (key));
5487e4b17023SJohn Marino else if (!TYPE_UNSIGNED (type)
5488e4b17023SJohn Marino && TREE_INT_CST_HIGH (key) == -1
5489e4b17023SJohn Marino && TREE_INT_CST_LOW (key) != 0)
5490e4b17023SJohn Marino snprintf (buf, sizeof (buf), "-" HOST_WIDE_INT_PRINT_UNSIGNED,
5491e4b17023SJohn Marino -TREE_INT_CST_LOW (key));
5492e4b17023SJohn Marino else
5493e4b17023SJohn Marino snprintf (buf, sizeof (buf), HOST_WIDE_INT_PRINT_DOUBLE_HEX,
5494e4b17023SJohn Marino (unsigned HOST_WIDE_INT) TREE_INT_CST_HIGH (key),
5495e4b17023SJohn Marino (unsigned HOST_WIDE_INT) TREE_INT_CST_LOW (key));
5496e4b17023SJohn Marino
5497e4b17023SJohn Marino if (TYPE_NAME (type) == 0)
5498e4b17023SJohn Marino warning_at (DECL_SOURCE_LOCATION (CASE_LABEL (label)),
5499e4b17023SJohn Marino warn_switch ? OPT_Wswitch : OPT_Wswitch_enum,
5500e4b17023SJohn Marino "case value %qs not in enumerated type",
5501e4b17023SJohn Marino buf);
5502e4b17023SJohn Marino else
5503e4b17023SJohn Marino warning_at (DECL_SOURCE_LOCATION (CASE_LABEL (label)),
5504e4b17023SJohn Marino warn_switch ? OPT_Wswitch : OPT_Wswitch_enum,
5505e4b17023SJohn Marino "case value %qs not in enumerated type %qT",
5506e4b17023SJohn Marino buf, type);
5507e4b17023SJohn Marino }
5508e4b17023SJohn Marino
5509e4b17023SJohn Marino /* Subroutine of c_do_switch_warnings, called via splay_tree_foreach.
5510e4b17023SJohn Marino Used to verify that case values match up with enumerator values. */
5511e4b17023SJohn Marino
5512e4b17023SJohn Marino static int
match_case_to_enum(splay_tree_node node,void * data)5513e4b17023SJohn Marino match_case_to_enum (splay_tree_node node, void *data)
5514e4b17023SJohn Marino {
5515e4b17023SJohn Marino tree label = (tree) node->value;
5516e4b17023SJohn Marino tree type = (tree) data;
5517e4b17023SJohn Marino
5518e4b17023SJohn Marino /* Skip default case. */
5519e4b17023SJohn Marino if (!CASE_LOW (label))
5520e4b17023SJohn Marino return 0;
5521e4b17023SJohn Marino
5522e4b17023SJohn Marino /* If CASE_LOW_SEEN is not set, that means CASE_LOW did not appear
5523e4b17023SJohn Marino when we did our enum->case scan. Reset our scratch bit after. */
5524e4b17023SJohn Marino if (!CASE_LOW_SEEN (label))
5525e4b17023SJohn Marino match_case_to_enum_1 (CASE_LOW (label), type, label);
5526e4b17023SJohn Marino else
5527e4b17023SJohn Marino CASE_LOW_SEEN (label) = 0;
5528e4b17023SJohn Marino
5529e4b17023SJohn Marino /* If CASE_HIGH is non-null, we have a range. If CASE_HIGH_SEEN is
5530e4b17023SJohn Marino not set, that means that CASE_HIGH did not appear when we did our
5531e4b17023SJohn Marino enum->case scan. Reset our scratch bit after. */
5532e4b17023SJohn Marino if (CASE_HIGH (label))
5533e4b17023SJohn Marino {
5534e4b17023SJohn Marino if (!CASE_HIGH_SEEN (label))
5535e4b17023SJohn Marino match_case_to_enum_1 (CASE_HIGH (label), type, label);
5536e4b17023SJohn Marino else
5537e4b17023SJohn Marino CASE_HIGH_SEEN (label) = 0;
5538e4b17023SJohn Marino }
5539e4b17023SJohn Marino
5540e4b17023SJohn Marino return 0;
5541e4b17023SJohn Marino }
5542e4b17023SJohn Marino
5543e4b17023SJohn Marino /* Handle -Wswitch*. Called from the front end after parsing the
5544e4b17023SJohn Marino switch construct. */
5545e4b17023SJohn Marino /* ??? Should probably be somewhere generic, since other languages
5546e4b17023SJohn Marino besides C and C++ would want this. At the moment, however, C/C++
5547e4b17023SJohn Marino are the only tree-ssa languages that support enumerations at all,
5548e4b17023SJohn Marino so the point is moot. */
5549e4b17023SJohn Marino
5550e4b17023SJohn Marino void
c_do_switch_warnings(splay_tree cases,location_t switch_location,tree type,tree cond)5551e4b17023SJohn Marino c_do_switch_warnings (splay_tree cases, location_t switch_location,
5552e4b17023SJohn Marino tree type, tree cond)
5553e4b17023SJohn Marino {
5554e4b17023SJohn Marino splay_tree_node default_node;
5555e4b17023SJohn Marino splay_tree_node node;
5556e4b17023SJohn Marino tree chain;
5557e4b17023SJohn Marino
5558e4b17023SJohn Marino if (!warn_switch && !warn_switch_enum && !warn_switch_default)
5559e4b17023SJohn Marino return;
5560e4b17023SJohn Marino
5561e4b17023SJohn Marino default_node = splay_tree_lookup (cases, (splay_tree_key) NULL);
5562e4b17023SJohn Marino if (!default_node)
5563e4b17023SJohn Marino warning_at (switch_location, OPT_Wswitch_default,
5564e4b17023SJohn Marino "switch missing default case");
5565e4b17023SJohn Marino
5566e4b17023SJohn Marino /* From here on, we only care about about enumerated types. */
5567e4b17023SJohn Marino if (!type || TREE_CODE (type) != ENUMERAL_TYPE)
5568e4b17023SJohn Marino return;
5569e4b17023SJohn Marino
5570e4b17023SJohn Marino /* From here on, we only care about -Wswitch and -Wswitch-enum. */
5571e4b17023SJohn Marino if (!warn_switch_enum && !warn_switch)
5572e4b17023SJohn Marino return;
5573e4b17023SJohn Marino
5574e4b17023SJohn Marino /* Check the cases. Warn about case values which are not members of
5575e4b17023SJohn Marino the enumerated type. For -Wswitch-enum, or for -Wswitch when
5576e4b17023SJohn Marino there is no default case, check that exactly all enumeration
5577e4b17023SJohn Marino literals are covered by the cases. */
5578e4b17023SJohn Marino
5579e4b17023SJohn Marino /* Clearing COND if it is not an integer constant simplifies
5580e4b17023SJohn Marino the tests inside the loop below. */
5581e4b17023SJohn Marino if (TREE_CODE (cond) != INTEGER_CST)
5582e4b17023SJohn Marino cond = NULL_TREE;
5583e4b17023SJohn Marino
5584e4b17023SJohn Marino /* The time complexity here is O(N*lg(N)) worst case, but for the
5585e4b17023SJohn Marino common case of monotonically increasing enumerators, it is
5586e4b17023SJohn Marino O(N), since the nature of the splay tree will keep the next
5587e4b17023SJohn Marino element adjacent to the root at all times. */
5588e4b17023SJohn Marino
5589e4b17023SJohn Marino for (chain = TYPE_VALUES (type); chain; chain = TREE_CHAIN (chain))
5590e4b17023SJohn Marino {
5591e4b17023SJohn Marino tree value = TREE_VALUE (chain);
5592e4b17023SJohn Marino if (TREE_CODE (value) == CONST_DECL)
5593e4b17023SJohn Marino value = DECL_INITIAL (value);
5594e4b17023SJohn Marino node = splay_tree_lookup (cases, (splay_tree_key) value);
5595e4b17023SJohn Marino if (node)
5596e4b17023SJohn Marino {
5597e4b17023SJohn Marino /* Mark the CASE_LOW part of the case entry as seen. */
5598e4b17023SJohn Marino tree label = (tree) node->value;
5599e4b17023SJohn Marino CASE_LOW_SEEN (label) = 1;
5600e4b17023SJohn Marino continue;
5601e4b17023SJohn Marino }
5602e4b17023SJohn Marino
5603e4b17023SJohn Marino /* Even though there wasn't an exact match, there might be a
5604e4b17023SJohn Marino case range which includes the enumerator's value. */
5605e4b17023SJohn Marino node = splay_tree_predecessor (cases, (splay_tree_key) value);
5606e4b17023SJohn Marino if (node && CASE_HIGH ((tree) node->value))
5607e4b17023SJohn Marino {
5608e4b17023SJohn Marino tree label = (tree) node->value;
5609e4b17023SJohn Marino int cmp = tree_int_cst_compare (CASE_HIGH (label), value);
5610e4b17023SJohn Marino if (cmp >= 0)
5611e4b17023SJohn Marino {
5612e4b17023SJohn Marino /* If we match the upper bound exactly, mark the CASE_HIGH
5613e4b17023SJohn Marino part of the case entry as seen. */
5614e4b17023SJohn Marino if (cmp == 0)
5615e4b17023SJohn Marino CASE_HIGH_SEEN (label) = 1;
5616e4b17023SJohn Marino continue;
5617e4b17023SJohn Marino }
5618e4b17023SJohn Marino }
5619e4b17023SJohn Marino
5620e4b17023SJohn Marino /* We've now determined that this enumerated literal isn't
5621e4b17023SJohn Marino handled by the case labels of the switch statement. */
5622e4b17023SJohn Marino
5623e4b17023SJohn Marino /* If the switch expression is a constant, we only really care
5624e4b17023SJohn Marino about whether that constant is handled by the switch. */
5625e4b17023SJohn Marino if (cond && tree_int_cst_compare (cond, value))
5626e4b17023SJohn Marino continue;
5627e4b17023SJohn Marino
5628e4b17023SJohn Marino /* If there is a default_node, the only relevant option is
5629e4b17023SJohn Marino Wswitch-enum. Otherwise, if both are enabled then we prefer
5630e4b17023SJohn Marino to warn using -Wswitch because -Wswitch is enabled by -Wall
5631e4b17023SJohn Marino while -Wswitch-enum is explicit. */
5632e4b17023SJohn Marino warning_at (switch_location,
5633e4b17023SJohn Marino (default_node || !warn_switch
5634e4b17023SJohn Marino ? OPT_Wswitch_enum
5635e4b17023SJohn Marino : OPT_Wswitch),
5636e4b17023SJohn Marino "enumeration value %qE not handled in switch",
5637e4b17023SJohn Marino TREE_PURPOSE (chain));
5638e4b17023SJohn Marino }
5639e4b17023SJohn Marino
5640e4b17023SJohn Marino /* Warn if there are case expressions that don't correspond to
5641e4b17023SJohn Marino enumerators. This can occur since C and C++ don't enforce
5642e4b17023SJohn Marino type-checking of assignments to enumeration variables.
5643e4b17023SJohn Marino
5644e4b17023SJohn Marino The time complexity here is now always O(N) worst case, since
5645e4b17023SJohn Marino we should have marked both the lower bound and upper bound of
5646e4b17023SJohn Marino every disjoint case label, with CASE_LOW_SEEN and CASE_HIGH_SEEN
5647e4b17023SJohn Marino above. This scan also resets those fields. */
5648e4b17023SJohn Marino
5649e4b17023SJohn Marino splay_tree_foreach (cases, match_case_to_enum, type);
5650e4b17023SJohn Marino }
5651e4b17023SJohn Marino
5652e4b17023SJohn Marino /* Finish an expression taking the address of LABEL (an
5653e4b17023SJohn Marino IDENTIFIER_NODE). Returns an expression for the address.
5654e4b17023SJohn Marino
5655e4b17023SJohn Marino LOC is the location for the expression returned. */
5656e4b17023SJohn Marino
5657e4b17023SJohn Marino tree
finish_label_address_expr(tree label,location_t loc)5658e4b17023SJohn Marino finish_label_address_expr (tree label, location_t loc)
5659e4b17023SJohn Marino {
5660e4b17023SJohn Marino tree result;
5661e4b17023SJohn Marino
5662e4b17023SJohn Marino pedwarn (input_location, OPT_pedantic, "taking the address of a label is non-standard");
5663e4b17023SJohn Marino
5664e4b17023SJohn Marino if (label == error_mark_node)
5665e4b17023SJohn Marino return error_mark_node;
5666e4b17023SJohn Marino
5667e4b17023SJohn Marino label = lookup_label (label);
5668e4b17023SJohn Marino if (label == NULL_TREE)
5669e4b17023SJohn Marino result = null_pointer_node;
5670e4b17023SJohn Marino else
5671e4b17023SJohn Marino {
5672e4b17023SJohn Marino TREE_USED (label) = 1;
5673e4b17023SJohn Marino result = build1 (ADDR_EXPR, ptr_type_node, label);
5674e4b17023SJohn Marino /* The current function is not necessarily uninlinable.
5675e4b17023SJohn Marino Computed gotos are incompatible with inlining, but the value
5676e4b17023SJohn Marino here could be used only in a diagnostic, for example. */
5677e4b17023SJohn Marino protected_set_expr_location (result, loc);
5678e4b17023SJohn Marino }
5679e4b17023SJohn Marino
5680e4b17023SJohn Marino return result;
5681e4b17023SJohn Marino }
5682e4b17023SJohn Marino
5683e4b17023SJohn Marino
5684e4b17023SJohn Marino /* Given a boolean expression ARG, return a tree representing an increment
5685e4b17023SJohn Marino or decrement (as indicated by CODE) of ARG. The front end must check for
5686e4b17023SJohn Marino invalid cases (e.g., decrement in C++). */
5687e4b17023SJohn Marino tree
boolean_increment(enum tree_code code,tree arg)5688e4b17023SJohn Marino boolean_increment (enum tree_code code, tree arg)
5689e4b17023SJohn Marino {
5690e4b17023SJohn Marino tree val;
5691e4b17023SJohn Marino tree true_res = build_int_cst (TREE_TYPE (arg), 1);
5692e4b17023SJohn Marino
5693e4b17023SJohn Marino arg = stabilize_reference (arg);
5694e4b17023SJohn Marino switch (code)
5695e4b17023SJohn Marino {
5696e4b17023SJohn Marino case PREINCREMENT_EXPR:
5697e4b17023SJohn Marino val = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg, true_res);
5698e4b17023SJohn Marino break;
5699e4b17023SJohn Marino case POSTINCREMENT_EXPR:
5700e4b17023SJohn Marino val = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg, true_res);
5701e4b17023SJohn Marino arg = save_expr (arg);
5702e4b17023SJohn Marino val = build2 (COMPOUND_EXPR, TREE_TYPE (arg), val, arg);
5703e4b17023SJohn Marino val = build2 (COMPOUND_EXPR, TREE_TYPE (arg), arg, val);
5704e4b17023SJohn Marino break;
5705e4b17023SJohn Marino case PREDECREMENT_EXPR:
5706e4b17023SJohn Marino val = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg,
5707e4b17023SJohn Marino invert_truthvalue_loc (input_location, arg));
5708e4b17023SJohn Marino break;
5709e4b17023SJohn Marino case POSTDECREMENT_EXPR:
5710e4b17023SJohn Marino val = build2 (MODIFY_EXPR, TREE_TYPE (arg), arg,
5711e4b17023SJohn Marino invert_truthvalue_loc (input_location, arg));
5712e4b17023SJohn Marino arg = save_expr (arg);
5713e4b17023SJohn Marino val = build2 (COMPOUND_EXPR, TREE_TYPE (arg), val, arg);
5714e4b17023SJohn Marino val = build2 (COMPOUND_EXPR, TREE_TYPE (arg), arg, val);
5715e4b17023SJohn Marino break;
5716e4b17023SJohn Marino default:
5717e4b17023SJohn Marino gcc_unreachable ();
5718e4b17023SJohn Marino }
5719e4b17023SJohn Marino TREE_SIDE_EFFECTS (val) = 1;
5720e4b17023SJohn Marino return val;
5721e4b17023SJohn Marino }
5722e4b17023SJohn Marino
5723e4b17023SJohn Marino /* Built-in macros for stddef.h and stdint.h, that require macros
5724e4b17023SJohn Marino defined in this file. */
5725e4b17023SJohn Marino void
c_stddef_cpp_builtins(void)5726e4b17023SJohn Marino c_stddef_cpp_builtins(void)
5727e4b17023SJohn Marino {
5728e4b17023SJohn Marino builtin_define_with_value ("__SIZE_TYPE__", SIZE_TYPE, 0);
5729e4b17023SJohn Marino builtin_define_with_value ("__PTRDIFF_TYPE__", PTRDIFF_TYPE, 0);
5730e4b17023SJohn Marino builtin_define_with_value ("__WCHAR_TYPE__", MODIFIED_WCHAR_TYPE, 0);
5731e4b17023SJohn Marino builtin_define_with_value ("__WINT_TYPE__", WINT_TYPE, 0);
5732e4b17023SJohn Marino builtin_define_with_value ("__INTMAX_TYPE__", INTMAX_TYPE, 0);
5733e4b17023SJohn Marino builtin_define_with_value ("__UINTMAX_TYPE__", UINTMAX_TYPE, 0);
5734e4b17023SJohn Marino builtin_define_with_value ("__CHAR16_TYPE__", CHAR16_TYPE, 0);
5735e4b17023SJohn Marino builtin_define_with_value ("__CHAR32_TYPE__", CHAR32_TYPE, 0);
5736e4b17023SJohn Marino if (SIG_ATOMIC_TYPE)
5737e4b17023SJohn Marino builtin_define_with_value ("__SIG_ATOMIC_TYPE__", SIG_ATOMIC_TYPE, 0);
5738e4b17023SJohn Marino if (INT8_TYPE)
5739e4b17023SJohn Marino builtin_define_with_value ("__INT8_TYPE__", INT8_TYPE, 0);
5740e4b17023SJohn Marino if (INT16_TYPE)
5741e4b17023SJohn Marino builtin_define_with_value ("__INT16_TYPE__", INT16_TYPE, 0);
5742e4b17023SJohn Marino if (INT32_TYPE)
5743e4b17023SJohn Marino builtin_define_with_value ("__INT32_TYPE__", INT32_TYPE, 0);
5744e4b17023SJohn Marino if (INT64_TYPE)
5745e4b17023SJohn Marino builtin_define_with_value ("__INT64_TYPE__", INT64_TYPE, 0);
5746e4b17023SJohn Marino if (UINT8_TYPE)
5747e4b17023SJohn Marino builtin_define_with_value ("__UINT8_TYPE__", UINT8_TYPE, 0);
5748e4b17023SJohn Marino if (UINT16_TYPE)
5749e4b17023SJohn Marino builtin_define_with_value ("__UINT16_TYPE__", UINT16_TYPE, 0);
5750e4b17023SJohn Marino if (UINT32_TYPE)
5751e4b17023SJohn Marino builtin_define_with_value ("__UINT32_TYPE__", UINT32_TYPE, 0);
5752e4b17023SJohn Marino if (UINT64_TYPE)
5753e4b17023SJohn Marino builtin_define_with_value ("__UINT64_TYPE__", UINT64_TYPE, 0);
5754e4b17023SJohn Marino if (INT_LEAST8_TYPE)
5755e4b17023SJohn Marino builtin_define_with_value ("__INT_LEAST8_TYPE__", INT_LEAST8_TYPE, 0);
5756e4b17023SJohn Marino if (INT_LEAST16_TYPE)
5757e4b17023SJohn Marino builtin_define_with_value ("__INT_LEAST16_TYPE__", INT_LEAST16_TYPE, 0);
5758e4b17023SJohn Marino if (INT_LEAST32_TYPE)
5759e4b17023SJohn Marino builtin_define_with_value ("__INT_LEAST32_TYPE__", INT_LEAST32_TYPE, 0);
5760e4b17023SJohn Marino if (INT_LEAST64_TYPE)
5761e4b17023SJohn Marino builtin_define_with_value ("__INT_LEAST64_TYPE__", INT_LEAST64_TYPE, 0);
5762e4b17023SJohn Marino if (UINT_LEAST8_TYPE)
5763e4b17023SJohn Marino builtin_define_with_value ("__UINT_LEAST8_TYPE__", UINT_LEAST8_TYPE, 0);
5764e4b17023SJohn Marino if (UINT_LEAST16_TYPE)
5765e4b17023SJohn Marino builtin_define_with_value ("__UINT_LEAST16_TYPE__", UINT_LEAST16_TYPE, 0);
5766e4b17023SJohn Marino if (UINT_LEAST32_TYPE)
5767e4b17023SJohn Marino builtin_define_with_value ("__UINT_LEAST32_TYPE__", UINT_LEAST32_TYPE, 0);
5768e4b17023SJohn Marino if (UINT_LEAST64_TYPE)
5769e4b17023SJohn Marino builtin_define_with_value ("__UINT_LEAST64_TYPE__", UINT_LEAST64_TYPE, 0);
5770e4b17023SJohn Marino if (INT_FAST8_TYPE)
5771e4b17023SJohn Marino builtin_define_with_value ("__INT_FAST8_TYPE__", INT_FAST8_TYPE, 0);
5772e4b17023SJohn Marino if (INT_FAST16_TYPE)
5773e4b17023SJohn Marino builtin_define_with_value ("__INT_FAST16_TYPE__", INT_FAST16_TYPE, 0);
5774e4b17023SJohn Marino if (INT_FAST32_TYPE)
5775e4b17023SJohn Marino builtin_define_with_value ("__INT_FAST32_TYPE__", INT_FAST32_TYPE, 0);
5776e4b17023SJohn Marino if (INT_FAST64_TYPE)
5777e4b17023SJohn Marino builtin_define_with_value ("__INT_FAST64_TYPE__", INT_FAST64_TYPE, 0);
5778e4b17023SJohn Marino if (UINT_FAST8_TYPE)
5779e4b17023SJohn Marino builtin_define_with_value ("__UINT_FAST8_TYPE__", UINT_FAST8_TYPE, 0);
5780e4b17023SJohn Marino if (UINT_FAST16_TYPE)
5781e4b17023SJohn Marino builtin_define_with_value ("__UINT_FAST16_TYPE__", UINT_FAST16_TYPE, 0);
5782e4b17023SJohn Marino if (UINT_FAST32_TYPE)
5783e4b17023SJohn Marino builtin_define_with_value ("__UINT_FAST32_TYPE__", UINT_FAST32_TYPE, 0);
5784e4b17023SJohn Marino if (UINT_FAST64_TYPE)
5785e4b17023SJohn Marino builtin_define_with_value ("__UINT_FAST64_TYPE__", UINT_FAST64_TYPE, 0);
5786e4b17023SJohn Marino if (INTPTR_TYPE)
5787e4b17023SJohn Marino builtin_define_with_value ("__INTPTR_TYPE__", INTPTR_TYPE, 0);
5788e4b17023SJohn Marino if (UINTPTR_TYPE)
5789e4b17023SJohn Marino builtin_define_with_value ("__UINTPTR_TYPE__", UINTPTR_TYPE, 0);
5790e4b17023SJohn Marino }
5791e4b17023SJohn Marino
5792e4b17023SJohn Marino static void
c_init_attributes(void)5793e4b17023SJohn Marino c_init_attributes (void)
5794e4b17023SJohn Marino {
5795e4b17023SJohn Marino /* Fill in the built_in_attributes array. */
5796e4b17023SJohn Marino #define DEF_ATTR_NULL_TREE(ENUM) \
5797e4b17023SJohn Marino built_in_attributes[(int) ENUM] = NULL_TREE;
5798e4b17023SJohn Marino #define DEF_ATTR_INT(ENUM, VALUE) \
5799e4b17023SJohn Marino built_in_attributes[(int) ENUM] = build_int_cst (integer_type_node, VALUE);
5800e4b17023SJohn Marino #define DEF_ATTR_IDENT(ENUM, STRING) \
5801e4b17023SJohn Marino built_in_attributes[(int) ENUM] = get_identifier (STRING);
5802e4b17023SJohn Marino #define DEF_ATTR_TREE_LIST(ENUM, PURPOSE, VALUE, CHAIN) \
5803e4b17023SJohn Marino built_in_attributes[(int) ENUM] \
5804e4b17023SJohn Marino = tree_cons (built_in_attributes[(int) PURPOSE], \
5805e4b17023SJohn Marino built_in_attributes[(int) VALUE], \
5806e4b17023SJohn Marino built_in_attributes[(int) CHAIN]);
5807e4b17023SJohn Marino #include "builtin-attrs.def"
5808e4b17023SJohn Marino #undef DEF_ATTR_NULL_TREE
5809e4b17023SJohn Marino #undef DEF_ATTR_INT
5810e4b17023SJohn Marino #undef DEF_ATTR_IDENT
5811e4b17023SJohn Marino #undef DEF_ATTR_TREE_LIST
5812e4b17023SJohn Marino }
5813e4b17023SJohn Marino
5814e4b17023SJohn Marino /* Returns TRUE iff the attribute indicated by ATTR_ID takes a plain
5815e4b17023SJohn Marino identifier as an argument, so the front end shouldn't look it up. */
5816e4b17023SJohn Marino
5817e4b17023SJohn Marino bool
attribute_takes_identifier_p(const_tree attr_id)5818e4b17023SJohn Marino attribute_takes_identifier_p (const_tree attr_id)
5819e4b17023SJohn Marino {
5820e4b17023SJohn Marino const struct attribute_spec *spec = lookup_attribute_spec (attr_id);
5821e4b17023SJohn Marino if (spec == NULL)
5822e4b17023SJohn Marino /* Unknown attribute that we'll end up ignoring, return true so we
5823e4b17023SJohn Marino don't complain about an identifier argument. */
5824e4b17023SJohn Marino return true;
5825e4b17023SJohn Marino else if (!strcmp ("mode", spec->name)
5826e4b17023SJohn Marino || !strcmp ("format", spec->name)
5827e4b17023SJohn Marino || !strcmp ("cleanup", spec->name))
5828e4b17023SJohn Marino return true;
5829e4b17023SJohn Marino else
5830e4b17023SJohn Marino return targetm.attribute_takes_identifier_p (attr_id);
5831e4b17023SJohn Marino }
5832e4b17023SJohn Marino
5833e4b17023SJohn Marino /* Attribute handlers common to C front ends. */
5834e4b17023SJohn Marino
5835e4b17023SJohn Marino /* Handle a "packed" attribute; arguments as in
5836e4b17023SJohn Marino struct attribute_spec.handler. */
5837e4b17023SJohn Marino
5838e4b17023SJohn Marino static tree
handle_packed_attribute(tree * node,tree name,tree ARG_UNUSED (args),int flags,bool * no_add_attrs)5839e4b17023SJohn Marino handle_packed_attribute (tree *node, tree name, tree ARG_UNUSED (args),
5840e4b17023SJohn Marino int flags, bool *no_add_attrs)
5841e4b17023SJohn Marino {
5842e4b17023SJohn Marino if (TYPE_P (*node))
5843e4b17023SJohn Marino {
5844e4b17023SJohn Marino if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
5845e4b17023SJohn Marino *node = build_variant_type_copy (*node);
5846e4b17023SJohn Marino TYPE_PACKED (*node) = 1;
5847e4b17023SJohn Marino }
5848e4b17023SJohn Marino else if (TREE_CODE (*node) == FIELD_DECL)
5849e4b17023SJohn Marino {
5850e4b17023SJohn Marino if (TYPE_ALIGN (TREE_TYPE (*node)) <= BITS_PER_UNIT
5851e4b17023SJohn Marino /* Still pack bitfields. */
5852e4b17023SJohn Marino && ! DECL_INITIAL (*node))
5853e4b17023SJohn Marino warning (OPT_Wattributes,
5854e4b17023SJohn Marino "%qE attribute ignored for field of type %qT",
5855e4b17023SJohn Marino name, TREE_TYPE (*node));
5856e4b17023SJohn Marino else
5857e4b17023SJohn Marino DECL_PACKED (*node) = 1;
5858e4b17023SJohn Marino }
5859e4b17023SJohn Marino /* We can't set DECL_PACKED for a VAR_DECL, because the bit is
5860e4b17023SJohn Marino used for DECL_REGISTER. It wouldn't mean anything anyway.
5861e4b17023SJohn Marino We can't set DECL_PACKED on the type of a TYPE_DECL, because
5862e4b17023SJohn Marino that changes what the typedef is typing. */
5863e4b17023SJohn Marino else
5864e4b17023SJohn Marino {
5865e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
5866e4b17023SJohn Marino *no_add_attrs = true;
5867e4b17023SJohn Marino }
5868e4b17023SJohn Marino
5869e4b17023SJohn Marino return NULL_TREE;
5870e4b17023SJohn Marino }
5871e4b17023SJohn Marino
5872e4b17023SJohn Marino /* Handle a "nocommon" attribute; arguments as in
5873e4b17023SJohn Marino struct attribute_spec.handler. */
5874e4b17023SJohn Marino
5875e4b17023SJohn Marino static tree
handle_nocommon_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)5876e4b17023SJohn Marino handle_nocommon_attribute (tree *node, tree name,
5877e4b17023SJohn Marino tree ARG_UNUSED (args),
5878e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
5879e4b17023SJohn Marino {
5880e4b17023SJohn Marino if (TREE_CODE (*node) == VAR_DECL)
5881e4b17023SJohn Marino DECL_COMMON (*node) = 0;
5882e4b17023SJohn Marino else
5883e4b17023SJohn Marino {
5884e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
5885e4b17023SJohn Marino *no_add_attrs = true;
5886e4b17023SJohn Marino }
5887e4b17023SJohn Marino
5888e4b17023SJohn Marino return NULL_TREE;
5889e4b17023SJohn Marino }
5890e4b17023SJohn Marino
5891e4b17023SJohn Marino /* Handle a "common" attribute; arguments as in
5892e4b17023SJohn Marino struct attribute_spec.handler. */
5893e4b17023SJohn Marino
5894e4b17023SJohn Marino static tree
handle_common_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)5895e4b17023SJohn Marino handle_common_attribute (tree *node, tree name, tree ARG_UNUSED (args),
5896e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
5897e4b17023SJohn Marino {
5898e4b17023SJohn Marino if (TREE_CODE (*node) == VAR_DECL)
5899e4b17023SJohn Marino DECL_COMMON (*node) = 1;
5900e4b17023SJohn Marino else
5901e4b17023SJohn Marino {
5902e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
5903e4b17023SJohn Marino *no_add_attrs = true;
5904e4b17023SJohn Marino }
5905e4b17023SJohn Marino
5906e4b17023SJohn Marino return NULL_TREE;
5907e4b17023SJohn Marino }
5908e4b17023SJohn Marino
5909e4b17023SJohn Marino /* Handle a "noreturn" attribute; arguments as in
5910e4b17023SJohn Marino struct attribute_spec.handler. */
5911e4b17023SJohn Marino
5912e4b17023SJohn Marino static tree
handle_noreturn_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)5913e4b17023SJohn Marino handle_noreturn_attribute (tree *node, tree name, tree ARG_UNUSED (args),
5914e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
5915e4b17023SJohn Marino {
5916e4b17023SJohn Marino tree type = TREE_TYPE (*node);
5917e4b17023SJohn Marino
5918e4b17023SJohn Marino /* See FIXME comment in c_common_attribute_table. */
5919e4b17023SJohn Marino if (TREE_CODE (*node) == FUNCTION_DECL
5920e4b17023SJohn Marino || objc_method_decl (TREE_CODE (*node)))
5921e4b17023SJohn Marino TREE_THIS_VOLATILE (*node) = 1;
5922e4b17023SJohn Marino else if (TREE_CODE (type) == POINTER_TYPE
5923e4b17023SJohn Marino && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
5924e4b17023SJohn Marino TREE_TYPE (*node)
5925e4b17023SJohn Marino = build_pointer_type
5926e4b17023SJohn Marino (build_type_variant (TREE_TYPE (type),
5927e4b17023SJohn Marino TYPE_READONLY (TREE_TYPE (type)), 1));
5928e4b17023SJohn Marino else
5929e4b17023SJohn Marino {
5930e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
5931e4b17023SJohn Marino *no_add_attrs = true;
5932e4b17023SJohn Marino }
5933e4b17023SJohn Marino
5934e4b17023SJohn Marino return NULL_TREE;
5935e4b17023SJohn Marino }
5936e4b17023SJohn Marino
5937e4b17023SJohn Marino /* Handle a "hot" and attribute; arguments as in
5938e4b17023SJohn Marino struct attribute_spec.handler. */
5939e4b17023SJohn Marino
5940e4b17023SJohn Marino static tree
handle_hot_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)5941e4b17023SJohn Marino handle_hot_attribute (tree *node, tree name, tree ARG_UNUSED (args),
5942e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
5943e4b17023SJohn Marino {
5944e4b17023SJohn Marino if (TREE_CODE (*node) == FUNCTION_DECL)
5945e4b17023SJohn Marino {
5946e4b17023SJohn Marino if (lookup_attribute ("cold", DECL_ATTRIBUTES (*node)) != NULL)
5947e4b17023SJohn Marino {
5948e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute conflicts with attribute %s",
5949e4b17023SJohn Marino name, "cold");
5950e4b17023SJohn Marino *no_add_attrs = true;
5951e4b17023SJohn Marino }
5952e4b17023SJohn Marino /* Most of the rest of the hot processing is done later with
5953e4b17023SJohn Marino lookup_attribute. */
5954e4b17023SJohn Marino }
5955e4b17023SJohn Marino else
5956e4b17023SJohn Marino {
5957e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
5958e4b17023SJohn Marino *no_add_attrs = true;
5959e4b17023SJohn Marino }
5960e4b17023SJohn Marino
5961e4b17023SJohn Marino return NULL_TREE;
5962e4b17023SJohn Marino }
5963e4b17023SJohn Marino /* Handle a "cold" and attribute; arguments as in
5964e4b17023SJohn Marino struct attribute_spec.handler. */
5965e4b17023SJohn Marino
5966e4b17023SJohn Marino static tree
handle_cold_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)5967e4b17023SJohn Marino handle_cold_attribute (tree *node, tree name, tree ARG_UNUSED (args),
5968e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
5969e4b17023SJohn Marino {
5970e4b17023SJohn Marino if (TREE_CODE (*node) == FUNCTION_DECL)
5971e4b17023SJohn Marino {
5972e4b17023SJohn Marino if (lookup_attribute ("hot", DECL_ATTRIBUTES (*node)) != NULL)
5973e4b17023SJohn Marino {
5974e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute conflicts with attribute %s",
5975e4b17023SJohn Marino name, "hot");
5976e4b17023SJohn Marino *no_add_attrs = true;
5977e4b17023SJohn Marino }
5978e4b17023SJohn Marino /* Most of the rest of the cold processing is done later with
5979e4b17023SJohn Marino lookup_attribute. */
5980e4b17023SJohn Marino }
5981e4b17023SJohn Marino else
5982e4b17023SJohn Marino {
5983e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
5984e4b17023SJohn Marino *no_add_attrs = true;
5985e4b17023SJohn Marino }
5986e4b17023SJohn Marino
5987e4b17023SJohn Marino return NULL_TREE;
5988e4b17023SJohn Marino }
5989e4b17023SJohn Marino
5990e4b17023SJohn Marino /* Handle a "noinline" attribute; arguments as in
5991e4b17023SJohn Marino struct attribute_spec.handler. */
5992e4b17023SJohn Marino
5993e4b17023SJohn Marino static tree
handle_noinline_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)5994e4b17023SJohn Marino handle_noinline_attribute (tree *node, tree name,
5995e4b17023SJohn Marino tree ARG_UNUSED (args),
5996e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
5997e4b17023SJohn Marino {
5998e4b17023SJohn Marino if (TREE_CODE (*node) == FUNCTION_DECL)
5999e4b17023SJohn Marino DECL_UNINLINABLE (*node) = 1;
6000e4b17023SJohn Marino else
6001e4b17023SJohn Marino {
6002e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6003e4b17023SJohn Marino *no_add_attrs = true;
6004e4b17023SJohn Marino }
6005e4b17023SJohn Marino
6006e4b17023SJohn Marino return NULL_TREE;
6007e4b17023SJohn Marino }
6008e4b17023SJohn Marino
6009e4b17023SJohn Marino /* Handle a "noclone" attribute; arguments as in
6010e4b17023SJohn Marino struct attribute_spec.handler. */
6011e4b17023SJohn Marino
6012e4b17023SJohn Marino static tree
handle_noclone_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)6013e4b17023SJohn Marino handle_noclone_attribute (tree *node, tree name,
6014e4b17023SJohn Marino tree ARG_UNUSED (args),
6015e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
6016e4b17023SJohn Marino {
6017e4b17023SJohn Marino if (TREE_CODE (*node) != FUNCTION_DECL)
6018e4b17023SJohn Marino {
6019e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6020e4b17023SJohn Marino *no_add_attrs = true;
6021e4b17023SJohn Marino }
6022e4b17023SJohn Marino
6023e4b17023SJohn Marino return NULL_TREE;
6024e4b17023SJohn Marino }
6025e4b17023SJohn Marino
6026e4b17023SJohn Marino /* Handle a "always_inline" attribute; arguments as in
6027e4b17023SJohn Marino struct attribute_spec.handler. */
6028e4b17023SJohn Marino
6029e4b17023SJohn Marino static tree
handle_always_inline_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)6030e4b17023SJohn Marino handle_always_inline_attribute (tree *node, tree name,
6031e4b17023SJohn Marino tree ARG_UNUSED (args),
6032e4b17023SJohn Marino int ARG_UNUSED (flags),
6033e4b17023SJohn Marino bool *no_add_attrs)
6034e4b17023SJohn Marino {
6035e4b17023SJohn Marino if (TREE_CODE (*node) == FUNCTION_DECL)
6036e4b17023SJohn Marino {
6037e4b17023SJohn Marino /* Set the attribute and mark it for disregarding inline
6038e4b17023SJohn Marino limits. */
6039e4b17023SJohn Marino DECL_DISREGARD_INLINE_LIMITS (*node) = 1;
6040e4b17023SJohn Marino }
6041e4b17023SJohn Marino else
6042e4b17023SJohn Marino {
6043e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6044e4b17023SJohn Marino *no_add_attrs = true;
6045e4b17023SJohn Marino }
6046e4b17023SJohn Marino
6047e4b17023SJohn Marino return NULL_TREE;
6048e4b17023SJohn Marino }
6049e4b17023SJohn Marino
6050e4b17023SJohn Marino /* Handle a "gnu_inline" attribute; arguments as in
6051e4b17023SJohn Marino struct attribute_spec.handler. */
6052e4b17023SJohn Marino
6053e4b17023SJohn Marino static tree
handle_gnu_inline_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)6054e4b17023SJohn Marino handle_gnu_inline_attribute (tree *node, tree name,
6055e4b17023SJohn Marino tree ARG_UNUSED (args),
6056e4b17023SJohn Marino int ARG_UNUSED (flags),
6057e4b17023SJohn Marino bool *no_add_attrs)
6058e4b17023SJohn Marino {
6059e4b17023SJohn Marino if (TREE_CODE (*node) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (*node))
6060e4b17023SJohn Marino {
6061e4b17023SJohn Marino /* Do nothing else, just set the attribute. We'll get at
6062e4b17023SJohn Marino it later with lookup_attribute. */
6063e4b17023SJohn Marino }
6064e4b17023SJohn Marino else
6065e4b17023SJohn Marino {
6066e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6067e4b17023SJohn Marino *no_add_attrs = true;
6068e4b17023SJohn Marino }
6069e4b17023SJohn Marino
6070e4b17023SJohn Marino return NULL_TREE;
6071e4b17023SJohn Marino }
6072e4b17023SJohn Marino
6073e4b17023SJohn Marino /* Handle a "leaf" attribute; arguments as in
6074e4b17023SJohn Marino struct attribute_spec.handler. */
6075e4b17023SJohn Marino
6076e4b17023SJohn Marino static tree
handle_leaf_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)6077e4b17023SJohn Marino handle_leaf_attribute (tree *node, tree name,
6078e4b17023SJohn Marino tree ARG_UNUSED (args),
6079e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
6080e4b17023SJohn Marino {
6081e4b17023SJohn Marino if (TREE_CODE (*node) != FUNCTION_DECL)
6082e4b17023SJohn Marino {
6083e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6084e4b17023SJohn Marino *no_add_attrs = true;
6085e4b17023SJohn Marino }
6086e4b17023SJohn Marino if (!TREE_PUBLIC (*node))
6087e4b17023SJohn Marino {
6088e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute has no effect on unit local functions", name);
6089e4b17023SJohn Marino *no_add_attrs = true;
6090e4b17023SJohn Marino }
6091e4b17023SJohn Marino
6092e4b17023SJohn Marino return NULL_TREE;
6093e4b17023SJohn Marino }
6094e4b17023SJohn Marino
6095e4b17023SJohn Marino /* Handle an "artificial" attribute; arguments as in
6096e4b17023SJohn Marino struct attribute_spec.handler. */
6097e4b17023SJohn Marino
6098e4b17023SJohn Marino static tree
handle_artificial_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)6099e4b17023SJohn Marino handle_artificial_attribute (tree *node, tree name,
6100e4b17023SJohn Marino tree ARG_UNUSED (args),
6101e4b17023SJohn Marino int ARG_UNUSED (flags),
6102e4b17023SJohn Marino bool *no_add_attrs)
6103e4b17023SJohn Marino {
6104e4b17023SJohn Marino if (TREE_CODE (*node) == FUNCTION_DECL && DECL_DECLARED_INLINE_P (*node))
6105e4b17023SJohn Marino {
6106e4b17023SJohn Marino /* Do nothing else, just set the attribute. We'll get at
6107e4b17023SJohn Marino it later with lookup_attribute. */
6108e4b17023SJohn Marino }
6109e4b17023SJohn Marino else
6110e4b17023SJohn Marino {
6111e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6112e4b17023SJohn Marino *no_add_attrs = true;
6113e4b17023SJohn Marino }
6114e4b17023SJohn Marino
6115e4b17023SJohn Marino return NULL_TREE;
6116e4b17023SJohn Marino }
6117e4b17023SJohn Marino
6118e4b17023SJohn Marino /* Handle a "flatten" attribute; arguments as in
6119e4b17023SJohn Marino struct attribute_spec.handler. */
6120e4b17023SJohn Marino
6121e4b17023SJohn Marino static tree
handle_flatten_attribute(tree * node,tree name,tree args ATTRIBUTE_UNUSED,int flags ATTRIBUTE_UNUSED,bool * no_add_attrs)6122e4b17023SJohn Marino handle_flatten_attribute (tree *node, tree name,
6123e4b17023SJohn Marino tree args ATTRIBUTE_UNUSED,
6124e4b17023SJohn Marino int flags ATTRIBUTE_UNUSED, bool *no_add_attrs)
6125e4b17023SJohn Marino {
6126e4b17023SJohn Marino if (TREE_CODE (*node) == FUNCTION_DECL)
6127e4b17023SJohn Marino /* Do nothing else, just set the attribute. We'll get at
6128e4b17023SJohn Marino it later with lookup_attribute. */
6129e4b17023SJohn Marino ;
6130e4b17023SJohn Marino else
6131e4b17023SJohn Marino {
6132e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6133e4b17023SJohn Marino *no_add_attrs = true;
6134e4b17023SJohn Marino }
6135e4b17023SJohn Marino
6136e4b17023SJohn Marino return NULL_TREE;
6137e4b17023SJohn Marino }
6138e4b17023SJohn Marino
6139e4b17023SJohn Marino /* Handle a "warning" or "error" attribute; arguments as in
6140e4b17023SJohn Marino struct attribute_spec.handler. */
6141e4b17023SJohn Marino
6142e4b17023SJohn Marino static tree
handle_error_attribute(tree * node,tree name,tree args,int ARG_UNUSED (flags),bool * no_add_attrs)6143e4b17023SJohn Marino handle_error_attribute (tree *node, tree name, tree args,
6144e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
6145e4b17023SJohn Marino {
6146e4b17023SJohn Marino if (TREE_CODE (*node) == FUNCTION_DECL
6147e4b17023SJohn Marino || TREE_CODE (TREE_VALUE (args)) == STRING_CST)
6148e4b17023SJohn Marino /* Do nothing else, just set the attribute. We'll get at
6149e4b17023SJohn Marino it later with lookup_attribute. */
6150e4b17023SJohn Marino ;
6151e4b17023SJohn Marino else
6152e4b17023SJohn Marino {
6153e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6154e4b17023SJohn Marino *no_add_attrs = true;
6155e4b17023SJohn Marino }
6156e4b17023SJohn Marino
6157e4b17023SJohn Marino return NULL_TREE;
6158e4b17023SJohn Marino }
6159e4b17023SJohn Marino
6160e4b17023SJohn Marino /* Handle a "used" attribute; arguments as in
6161e4b17023SJohn Marino struct attribute_spec.handler. */
6162e4b17023SJohn Marino
6163e4b17023SJohn Marino static tree
handle_used_attribute(tree * pnode,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)6164e4b17023SJohn Marino handle_used_attribute (tree *pnode, tree name, tree ARG_UNUSED (args),
6165e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
6166e4b17023SJohn Marino {
6167e4b17023SJohn Marino tree node = *pnode;
6168e4b17023SJohn Marino
6169e4b17023SJohn Marino if (TREE_CODE (node) == FUNCTION_DECL
6170e4b17023SJohn Marino || (TREE_CODE (node) == VAR_DECL && TREE_STATIC (node))
6171e4b17023SJohn Marino || (TREE_CODE (node) == TYPE_DECL))
6172e4b17023SJohn Marino {
6173e4b17023SJohn Marino TREE_USED (node) = 1;
6174e4b17023SJohn Marino DECL_PRESERVE_P (node) = 1;
6175e4b17023SJohn Marino if (TREE_CODE (node) == VAR_DECL)
6176e4b17023SJohn Marino DECL_READ_P (node) = 1;
6177e4b17023SJohn Marino }
6178e4b17023SJohn Marino else
6179e4b17023SJohn Marino {
6180e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6181e4b17023SJohn Marino *no_add_attrs = true;
6182e4b17023SJohn Marino }
6183e4b17023SJohn Marino
6184e4b17023SJohn Marino return NULL_TREE;
6185e4b17023SJohn Marino }
6186e4b17023SJohn Marino
6187e4b17023SJohn Marino /* Handle a "unused" attribute; arguments as in
6188e4b17023SJohn Marino struct attribute_spec.handler. */
6189e4b17023SJohn Marino
6190e4b17023SJohn Marino static tree
handle_unused_attribute(tree * node,tree name,tree ARG_UNUSED (args),int flags,bool * no_add_attrs)6191e4b17023SJohn Marino handle_unused_attribute (tree *node, tree name, tree ARG_UNUSED (args),
6192e4b17023SJohn Marino int flags, bool *no_add_attrs)
6193e4b17023SJohn Marino {
6194e4b17023SJohn Marino if (DECL_P (*node))
6195e4b17023SJohn Marino {
6196e4b17023SJohn Marino tree decl = *node;
6197e4b17023SJohn Marino
6198e4b17023SJohn Marino if (TREE_CODE (decl) == PARM_DECL
6199e4b17023SJohn Marino || TREE_CODE (decl) == VAR_DECL
6200e4b17023SJohn Marino || TREE_CODE (decl) == FUNCTION_DECL
6201e4b17023SJohn Marino || TREE_CODE (decl) == LABEL_DECL
6202e4b17023SJohn Marino || TREE_CODE (decl) == TYPE_DECL)
6203e4b17023SJohn Marino {
6204e4b17023SJohn Marino TREE_USED (decl) = 1;
6205e4b17023SJohn Marino if (TREE_CODE (decl) == VAR_DECL
6206e4b17023SJohn Marino || TREE_CODE (decl) == PARM_DECL)
6207e4b17023SJohn Marino DECL_READ_P (decl) = 1;
6208e4b17023SJohn Marino }
6209e4b17023SJohn Marino else
6210e4b17023SJohn Marino {
6211e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6212e4b17023SJohn Marino *no_add_attrs = true;
6213e4b17023SJohn Marino }
6214e4b17023SJohn Marino }
6215e4b17023SJohn Marino else
6216e4b17023SJohn Marino {
6217e4b17023SJohn Marino if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
6218e4b17023SJohn Marino *node = build_variant_type_copy (*node);
6219e4b17023SJohn Marino TREE_USED (*node) = 1;
6220e4b17023SJohn Marino }
6221e4b17023SJohn Marino
6222e4b17023SJohn Marino return NULL_TREE;
6223e4b17023SJohn Marino }
6224e4b17023SJohn Marino
6225e4b17023SJohn Marino /* Handle a "externally_visible" attribute; arguments as in
6226e4b17023SJohn Marino struct attribute_spec.handler. */
6227e4b17023SJohn Marino
6228e4b17023SJohn Marino static tree
handle_externally_visible_attribute(tree * pnode,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)6229e4b17023SJohn Marino handle_externally_visible_attribute (tree *pnode, tree name,
6230e4b17023SJohn Marino tree ARG_UNUSED (args),
6231e4b17023SJohn Marino int ARG_UNUSED (flags),
6232e4b17023SJohn Marino bool *no_add_attrs)
6233e4b17023SJohn Marino {
6234e4b17023SJohn Marino tree node = *pnode;
6235e4b17023SJohn Marino
6236e4b17023SJohn Marino if (TREE_CODE (node) == FUNCTION_DECL || TREE_CODE (node) == VAR_DECL)
6237e4b17023SJohn Marino {
6238e4b17023SJohn Marino if ((!TREE_STATIC (node) && TREE_CODE (node) != FUNCTION_DECL
6239e4b17023SJohn Marino && !DECL_EXTERNAL (node)) || !TREE_PUBLIC (node))
6240e4b17023SJohn Marino {
6241e4b17023SJohn Marino warning (OPT_Wattributes,
6242e4b17023SJohn Marino "%qE attribute have effect only on public objects", name);
6243e4b17023SJohn Marino *no_add_attrs = true;
6244e4b17023SJohn Marino }
6245e4b17023SJohn Marino }
6246e4b17023SJohn Marino else
6247e4b17023SJohn Marino {
6248e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6249e4b17023SJohn Marino *no_add_attrs = true;
6250e4b17023SJohn Marino }
6251e4b17023SJohn Marino
6252e4b17023SJohn Marino return NULL_TREE;
6253e4b17023SJohn Marino }
6254e4b17023SJohn Marino
6255e4b17023SJohn Marino /* Handle a "const" attribute; arguments as in
6256e4b17023SJohn Marino struct attribute_spec.handler. */
6257e4b17023SJohn Marino
6258e4b17023SJohn Marino static tree
handle_const_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)6259e4b17023SJohn Marino handle_const_attribute (tree *node, tree name, tree ARG_UNUSED (args),
6260e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
6261e4b17023SJohn Marino {
6262e4b17023SJohn Marino tree type = TREE_TYPE (*node);
6263e4b17023SJohn Marino
6264e4b17023SJohn Marino /* See FIXME comment on noreturn in c_common_attribute_table. */
6265e4b17023SJohn Marino if (TREE_CODE (*node) == FUNCTION_DECL)
6266e4b17023SJohn Marino TREE_READONLY (*node) = 1;
6267e4b17023SJohn Marino else if (TREE_CODE (type) == POINTER_TYPE
6268e4b17023SJohn Marino && TREE_CODE (TREE_TYPE (type)) == FUNCTION_TYPE)
6269e4b17023SJohn Marino TREE_TYPE (*node)
6270e4b17023SJohn Marino = build_pointer_type
6271e4b17023SJohn Marino (build_type_variant (TREE_TYPE (type), 1,
6272e4b17023SJohn Marino TREE_THIS_VOLATILE (TREE_TYPE (type))));
6273e4b17023SJohn Marino else
6274e4b17023SJohn Marino {
6275e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6276e4b17023SJohn Marino *no_add_attrs = true;
6277e4b17023SJohn Marino }
6278e4b17023SJohn Marino
6279e4b17023SJohn Marino return NULL_TREE;
6280e4b17023SJohn Marino }
6281e4b17023SJohn Marino
6282e4b17023SJohn Marino /* Handle a "transparent_union" attribute; arguments as in
6283e4b17023SJohn Marino struct attribute_spec.handler. */
6284e4b17023SJohn Marino
6285e4b17023SJohn Marino static tree
handle_transparent_union_attribute(tree * node,tree name,tree ARG_UNUSED (args),int flags,bool * no_add_attrs)6286e4b17023SJohn Marino handle_transparent_union_attribute (tree *node, tree name,
6287e4b17023SJohn Marino tree ARG_UNUSED (args), int flags,
6288e4b17023SJohn Marino bool *no_add_attrs)
6289e4b17023SJohn Marino {
6290e4b17023SJohn Marino tree type;
6291e4b17023SJohn Marino
6292e4b17023SJohn Marino *no_add_attrs = true;
6293e4b17023SJohn Marino
6294e4b17023SJohn Marino if (TREE_CODE (*node) == TYPE_DECL)
6295e4b17023SJohn Marino node = &TREE_TYPE (*node);
6296e4b17023SJohn Marino type = *node;
6297e4b17023SJohn Marino
6298e4b17023SJohn Marino if (TREE_CODE (type) == UNION_TYPE)
6299e4b17023SJohn Marino {
6300e4b17023SJohn Marino /* Make sure that the first field will work for a transparent union.
6301e4b17023SJohn Marino If the type isn't complete yet, leave the check to the code in
6302e4b17023SJohn Marino finish_struct. */
6303e4b17023SJohn Marino if (TYPE_SIZE (type))
6304e4b17023SJohn Marino {
6305e4b17023SJohn Marino tree first = first_field (type);
6306e4b17023SJohn Marino if (first == NULL_TREE
6307e4b17023SJohn Marino || DECL_ARTIFICIAL (first)
6308e4b17023SJohn Marino || TYPE_MODE (type) != DECL_MODE (first))
6309e4b17023SJohn Marino goto ignored;
6310e4b17023SJohn Marino }
6311e4b17023SJohn Marino
6312e4b17023SJohn Marino if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
6313e4b17023SJohn Marino {
6314e4b17023SJohn Marino /* If the type isn't complete yet, setting the flag
6315e4b17023SJohn Marino on a variant wouldn't ever be checked. */
6316e4b17023SJohn Marino if (!TYPE_SIZE (type))
6317e4b17023SJohn Marino goto ignored;
6318e4b17023SJohn Marino
6319e4b17023SJohn Marino /* build_duplicate_type doesn't work for C++. */
6320e4b17023SJohn Marino if (c_dialect_cxx ())
6321e4b17023SJohn Marino goto ignored;
6322e4b17023SJohn Marino
6323e4b17023SJohn Marino /* A type variant isn't good enough, since we don't a cast
6324e4b17023SJohn Marino to such a type removed as a no-op. */
6325e4b17023SJohn Marino *node = type = build_duplicate_type (type);
6326e4b17023SJohn Marino }
6327e4b17023SJohn Marino
6328e4b17023SJohn Marino TYPE_TRANSPARENT_AGGR (type) = 1;
6329e4b17023SJohn Marino return NULL_TREE;
6330e4b17023SJohn Marino }
6331e4b17023SJohn Marino
6332e4b17023SJohn Marino ignored:
6333e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6334e4b17023SJohn Marino return NULL_TREE;
6335e4b17023SJohn Marino }
6336e4b17023SJohn Marino
6337e4b17023SJohn Marino /* Subroutine of handle_{con,de}structor_attribute. Evaluate ARGS to
6338e4b17023SJohn Marino get the requested priority for a constructor or destructor,
6339e4b17023SJohn Marino possibly issuing diagnostics for invalid or reserved
6340e4b17023SJohn Marino priorities. */
6341e4b17023SJohn Marino
6342e4b17023SJohn Marino static priority_type
get_priority(tree args,bool is_destructor)6343e4b17023SJohn Marino get_priority (tree args, bool is_destructor)
6344e4b17023SJohn Marino {
6345e4b17023SJohn Marino HOST_WIDE_INT pri;
6346e4b17023SJohn Marino tree arg;
6347e4b17023SJohn Marino
6348e4b17023SJohn Marino if (!args)
6349e4b17023SJohn Marino return DEFAULT_INIT_PRIORITY;
6350e4b17023SJohn Marino
6351e4b17023SJohn Marino if (!SUPPORTS_INIT_PRIORITY)
6352e4b17023SJohn Marino {
6353e4b17023SJohn Marino if (is_destructor)
6354e4b17023SJohn Marino error ("destructor priorities are not supported");
6355e4b17023SJohn Marino else
6356e4b17023SJohn Marino error ("constructor priorities are not supported");
6357e4b17023SJohn Marino return DEFAULT_INIT_PRIORITY;
6358e4b17023SJohn Marino }
6359e4b17023SJohn Marino
6360e4b17023SJohn Marino arg = TREE_VALUE (args);
6361e4b17023SJohn Marino if (!host_integerp (arg, /*pos=*/0)
6362e4b17023SJohn Marino || !INTEGRAL_TYPE_P (TREE_TYPE (arg)))
6363e4b17023SJohn Marino goto invalid;
6364e4b17023SJohn Marino
6365e4b17023SJohn Marino pri = tree_low_cst (TREE_VALUE (args), /*pos=*/0);
6366e4b17023SJohn Marino if (pri < 0 || pri > MAX_INIT_PRIORITY)
6367e4b17023SJohn Marino goto invalid;
6368e4b17023SJohn Marino
6369e4b17023SJohn Marino if (pri <= MAX_RESERVED_INIT_PRIORITY)
6370e4b17023SJohn Marino {
6371e4b17023SJohn Marino if (is_destructor)
6372e4b17023SJohn Marino warning (0,
6373e4b17023SJohn Marino "destructor priorities from 0 to %d are reserved "
6374e4b17023SJohn Marino "for the implementation",
6375e4b17023SJohn Marino MAX_RESERVED_INIT_PRIORITY);
6376e4b17023SJohn Marino else
6377e4b17023SJohn Marino warning (0,
6378e4b17023SJohn Marino "constructor priorities from 0 to %d are reserved "
6379e4b17023SJohn Marino "for the implementation",
6380e4b17023SJohn Marino MAX_RESERVED_INIT_PRIORITY);
6381e4b17023SJohn Marino }
6382e4b17023SJohn Marino return pri;
6383e4b17023SJohn Marino
6384e4b17023SJohn Marino invalid:
6385e4b17023SJohn Marino if (is_destructor)
6386e4b17023SJohn Marino error ("destructor priorities must be integers from 0 to %d inclusive",
6387e4b17023SJohn Marino MAX_INIT_PRIORITY);
6388e4b17023SJohn Marino else
6389e4b17023SJohn Marino error ("constructor priorities must be integers from 0 to %d inclusive",
6390e4b17023SJohn Marino MAX_INIT_PRIORITY);
6391e4b17023SJohn Marino return DEFAULT_INIT_PRIORITY;
6392e4b17023SJohn Marino }
6393e4b17023SJohn Marino
6394e4b17023SJohn Marino /* Handle a "constructor" attribute; arguments as in
6395e4b17023SJohn Marino struct attribute_spec.handler. */
6396e4b17023SJohn Marino
6397e4b17023SJohn Marino static tree
handle_constructor_attribute(tree * node,tree name,tree args,int ARG_UNUSED (flags),bool * no_add_attrs)6398e4b17023SJohn Marino handle_constructor_attribute (tree *node, tree name, tree args,
6399e4b17023SJohn Marino int ARG_UNUSED (flags),
6400e4b17023SJohn Marino bool *no_add_attrs)
6401e4b17023SJohn Marino {
6402e4b17023SJohn Marino tree decl = *node;
6403e4b17023SJohn Marino tree type = TREE_TYPE (decl);
6404e4b17023SJohn Marino
6405e4b17023SJohn Marino if (TREE_CODE (decl) == FUNCTION_DECL
6406e4b17023SJohn Marino && TREE_CODE (type) == FUNCTION_TYPE
6407e4b17023SJohn Marino && decl_function_context (decl) == 0)
6408e4b17023SJohn Marino {
6409e4b17023SJohn Marino priority_type priority;
6410e4b17023SJohn Marino DECL_STATIC_CONSTRUCTOR (decl) = 1;
6411e4b17023SJohn Marino priority = get_priority (args, /*is_destructor=*/false);
6412e4b17023SJohn Marino SET_DECL_INIT_PRIORITY (decl, priority);
6413e4b17023SJohn Marino TREE_USED (decl) = 1;
6414e4b17023SJohn Marino }
6415e4b17023SJohn Marino else
6416e4b17023SJohn Marino {
6417e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6418e4b17023SJohn Marino *no_add_attrs = true;
6419e4b17023SJohn Marino }
6420e4b17023SJohn Marino
6421e4b17023SJohn Marino return NULL_TREE;
6422e4b17023SJohn Marino }
6423e4b17023SJohn Marino
6424e4b17023SJohn Marino /* Handle a "destructor" attribute; arguments as in
6425e4b17023SJohn Marino struct attribute_spec.handler. */
6426e4b17023SJohn Marino
6427e4b17023SJohn Marino static tree
handle_destructor_attribute(tree * node,tree name,tree args,int ARG_UNUSED (flags),bool * no_add_attrs)6428e4b17023SJohn Marino handle_destructor_attribute (tree *node, tree name, tree args,
6429e4b17023SJohn Marino int ARG_UNUSED (flags),
6430e4b17023SJohn Marino bool *no_add_attrs)
6431e4b17023SJohn Marino {
6432e4b17023SJohn Marino tree decl = *node;
6433e4b17023SJohn Marino tree type = TREE_TYPE (decl);
6434e4b17023SJohn Marino
6435e4b17023SJohn Marino if (TREE_CODE (decl) == FUNCTION_DECL
6436e4b17023SJohn Marino && TREE_CODE (type) == FUNCTION_TYPE
6437e4b17023SJohn Marino && decl_function_context (decl) == 0)
6438e4b17023SJohn Marino {
6439e4b17023SJohn Marino priority_type priority;
6440e4b17023SJohn Marino DECL_STATIC_DESTRUCTOR (decl) = 1;
6441e4b17023SJohn Marino priority = get_priority (args, /*is_destructor=*/true);
6442e4b17023SJohn Marino SET_DECL_FINI_PRIORITY (decl, priority);
6443e4b17023SJohn Marino TREE_USED (decl) = 1;
6444e4b17023SJohn Marino }
6445e4b17023SJohn Marino else
6446e4b17023SJohn Marino {
6447e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6448e4b17023SJohn Marino *no_add_attrs = true;
6449e4b17023SJohn Marino }
6450e4b17023SJohn Marino
6451e4b17023SJohn Marino return NULL_TREE;
6452e4b17023SJohn Marino }
6453e4b17023SJohn Marino
6454e4b17023SJohn Marino /* Nonzero if the mode is a valid vector mode for this architecture.
6455e4b17023SJohn Marino This returns nonzero even if there is no hardware support for the
6456e4b17023SJohn Marino vector mode, but we can emulate with narrower modes. */
6457e4b17023SJohn Marino
6458e4b17023SJohn Marino static int
vector_mode_valid_p(enum machine_mode mode)6459e4b17023SJohn Marino vector_mode_valid_p (enum machine_mode mode)
6460e4b17023SJohn Marino {
6461e4b17023SJohn Marino enum mode_class mclass = GET_MODE_CLASS (mode);
6462e4b17023SJohn Marino enum machine_mode innermode;
6463e4b17023SJohn Marino
6464e4b17023SJohn Marino /* Doh! What's going on? */
6465e4b17023SJohn Marino if (mclass != MODE_VECTOR_INT
6466e4b17023SJohn Marino && mclass != MODE_VECTOR_FLOAT
6467e4b17023SJohn Marino && mclass != MODE_VECTOR_FRACT
6468e4b17023SJohn Marino && mclass != MODE_VECTOR_UFRACT
6469e4b17023SJohn Marino && mclass != MODE_VECTOR_ACCUM
6470e4b17023SJohn Marino && mclass != MODE_VECTOR_UACCUM)
6471e4b17023SJohn Marino return 0;
6472e4b17023SJohn Marino
6473e4b17023SJohn Marino /* Hardware support. Woo hoo! */
6474e4b17023SJohn Marino if (targetm.vector_mode_supported_p (mode))
6475e4b17023SJohn Marino return 1;
6476e4b17023SJohn Marino
6477e4b17023SJohn Marino innermode = GET_MODE_INNER (mode);
6478e4b17023SJohn Marino
6479e4b17023SJohn Marino /* We should probably return 1 if requesting V4DI and we have no DI,
6480e4b17023SJohn Marino but we have V2DI, but this is probably very unlikely. */
6481e4b17023SJohn Marino
6482e4b17023SJohn Marino /* If we have support for the inner mode, we can safely emulate it.
6483e4b17023SJohn Marino We may not have V2DI, but me can emulate with a pair of DIs. */
6484e4b17023SJohn Marino return targetm.scalar_mode_supported_p (innermode);
6485e4b17023SJohn Marino }
6486e4b17023SJohn Marino
6487e4b17023SJohn Marino
6488e4b17023SJohn Marino /* Handle a "mode" attribute; arguments as in
6489e4b17023SJohn Marino struct attribute_spec.handler. */
6490e4b17023SJohn Marino
6491e4b17023SJohn Marino static tree
handle_mode_attribute(tree * node,tree name,tree args,int ARG_UNUSED (flags),bool * no_add_attrs)6492e4b17023SJohn Marino handle_mode_attribute (tree *node, tree name, tree args,
6493e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
6494e4b17023SJohn Marino {
6495e4b17023SJohn Marino tree type = *node;
6496e4b17023SJohn Marino tree ident = TREE_VALUE (args);
6497e4b17023SJohn Marino
6498e4b17023SJohn Marino *no_add_attrs = true;
6499e4b17023SJohn Marino
6500e4b17023SJohn Marino if (TREE_CODE (ident) != IDENTIFIER_NODE)
6501e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6502e4b17023SJohn Marino else
6503e4b17023SJohn Marino {
6504e4b17023SJohn Marino int j;
6505e4b17023SJohn Marino const char *p = IDENTIFIER_POINTER (ident);
6506e4b17023SJohn Marino int len = strlen (p);
6507e4b17023SJohn Marino enum machine_mode mode = VOIDmode;
6508e4b17023SJohn Marino tree typefm;
6509e4b17023SJohn Marino bool valid_mode;
6510e4b17023SJohn Marino
6511e4b17023SJohn Marino if (len > 4 && p[0] == '_' && p[1] == '_'
6512e4b17023SJohn Marino && p[len - 1] == '_' && p[len - 2] == '_')
6513e4b17023SJohn Marino {
6514e4b17023SJohn Marino char *newp = (char *) alloca (len - 1);
6515e4b17023SJohn Marino
6516e4b17023SJohn Marino strcpy (newp, &p[2]);
6517e4b17023SJohn Marino newp[len - 4] = '\0';
6518e4b17023SJohn Marino p = newp;
6519e4b17023SJohn Marino }
6520e4b17023SJohn Marino
6521e4b17023SJohn Marino /* Change this type to have a type with the specified mode.
6522e4b17023SJohn Marino First check for the special modes. */
6523e4b17023SJohn Marino if (!strcmp (p, "byte"))
6524e4b17023SJohn Marino mode = byte_mode;
6525e4b17023SJohn Marino else if (!strcmp (p, "word"))
6526e4b17023SJohn Marino mode = word_mode;
6527e4b17023SJohn Marino else if (!strcmp (p, "pointer"))
6528e4b17023SJohn Marino mode = ptr_mode;
6529e4b17023SJohn Marino else if (!strcmp (p, "libgcc_cmp_return"))
6530e4b17023SJohn Marino mode = targetm.libgcc_cmp_return_mode ();
6531e4b17023SJohn Marino else if (!strcmp (p, "libgcc_shift_count"))
6532e4b17023SJohn Marino mode = targetm.libgcc_shift_count_mode ();
6533e4b17023SJohn Marino else if (!strcmp (p, "unwind_word"))
6534e4b17023SJohn Marino mode = targetm.unwind_word_mode ();
6535e4b17023SJohn Marino else
6536e4b17023SJohn Marino for (j = 0; j < NUM_MACHINE_MODES; j++)
6537e4b17023SJohn Marino if (!strcmp (p, GET_MODE_NAME (j)))
6538e4b17023SJohn Marino {
6539e4b17023SJohn Marino mode = (enum machine_mode) j;
6540e4b17023SJohn Marino break;
6541e4b17023SJohn Marino }
6542e4b17023SJohn Marino
6543e4b17023SJohn Marino if (mode == VOIDmode)
6544e4b17023SJohn Marino {
6545e4b17023SJohn Marino error ("unknown machine mode %qE", ident);
6546e4b17023SJohn Marino return NULL_TREE;
6547e4b17023SJohn Marino }
6548e4b17023SJohn Marino
6549e4b17023SJohn Marino valid_mode = false;
6550e4b17023SJohn Marino switch (GET_MODE_CLASS (mode))
6551e4b17023SJohn Marino {
6552e4b17023SJohn Marino case MODE_INT:
6553e4b17023SJohn Marino case MODE_PARTIAL_INT:
6554e4b17023SJohn Marino case MODE_FLOAT:
6555e4b17023SJohn Marino case MODE_DECIMAL_FLOAT:
6556e4b17023SJohn Marino case MODE_FRACT:
6557e4b17023SJohn Marino case MODE_UFRACT:
6558e4b17023SJohn Marino case MODE_ACCUM:
6559e4b17023SJohn Marino case MODE_UACCUM:
6560e4b17023SJohn Marino valid_mode = targetm.scalar_mode_supported_p (mode);
6561e4b17023SJohn Marino break;
6562e4b17023SJohn Marino
6563e4b17023SJohn Marino case MODE_COMPLEX_INT:
6564e4b17023SJohn Marino case MODE_COMPLEX_FLOAT:
6565e4b17023SJohn Marino valid_mode = targetm.scalar_mode_supported_p (GET_MODE_INNER (mode));
6566e4b17023SJohn Marino break;
6567e4b17023SJohn Marino
6568e4b17023SJohn Marino case MODE_VECTOR_INT:
6569e4b17023SJohn Marino case MODE_VECTOR_FLOAT:
6570e4b17023SJohn Marino case MODE_VECTOR_FRACT:
6571e4b17023SJohn Marino case MODE_VECTOR_UFRACT:
6572e4b17023SJohn Marino case MODE_VECTOR_ACCUM:
6573e4b17023SJohn Marino case MODE_VECTOR_UACCUM:
6574e4b17023SJohn Marino warning (OPT_Wattributes, "specifying vector types with "
6575e4b17023SJohn Marino "__attribute__ ((mode)) is deprecated");
6576e4b17023SJohn Marino warning (OPT_Wattributes,
6577e4b17023SJohn Marino "use __attribute__ ((vector_size)) instead");
6578e4b17023SJohn Marino valid_mode = vector_mode_valid_p (mode);
6579e4b17023SJohn Marino break;
6580e4b17023SJohn Marino
6581e4b17023SJohn Marino default:
6582e4b17023SJohn Marino break;
6583e4b17023SJohn Marino }
6584e4b17023SJohn Marino if (!valid_mode)
6585e4b17023SJohn Marino {
6586e4b17023SJohn Marino error ("unable to emulate %qs", p);
6587e4b17023SJohn Marino return NULL_TREE;
6588e4b17023SJohn Marino }
6589e4b17023SJohn Marino
6590e4b17023SJohn Marino if (POINTER_TYPE_P (type))
6591e4b17023SJohn Marino {
6592e4b17023SJohn Marino addr_space_t as = TYPE_ADDR_SPACE (TREE_TYPE (type));
6593e4b17023SJohn Marino tree (*fn)(tree, enum machine_mode, bool);
6594e4b17023SJohn Marino
6595e4b17023SJohn Marino if (!targetm.addr_space.valid_pointer_mode (mode, as))
6596e4b17023SJohn Marino {
6597e4b17023SJohn Marino error ("invalid pointer mode %qs", p);
6598e4b17023SJohn Marino return NULL_TREE;
6599e4b17023SJohn Marino }
6600e4b17023SJohn Marino
6601e4b17023SJohn Marino if (TREE_CODE (type) == POINTER_TYPE)
6602e4b17023SJohn Marino fn = build_pointer_type_for_mode;
6603e4b17023SJohn Marino else
6604e4b17023SJohn Marino fn = build_reference_type_for_mode;
6605e4b17023SJohn Marino typefm = fn (TREE_TYPE (type), mode, false);
6606e4b17023SJohn Marino }
6607e4b17023SJohn Marino else
6608e4b17023SJohn Marino {
6609e4b17023SJohn Marino /* For fixed-point modes, we need to test if the signness of type
6610e4b17023SJohn Marino and the machine mode are consistent. */
6611e4b17023SJohn Marino if (ALL_FIXED_POINT_MODE_P (mode)
6612e4b17023SJohn Marino && TYPE_UNSIGNED (type) != UNSIGNED_FIXED_POINT_MODE_P (mode))
6613e4b17023SJohn Marino {
6614e4b17023SJohn Marino error ("signedness of type and machine mode %qs don%'t match", p);
6615e4b17023SJohn Marino return NULL_TREE;
6616e4b17023SJohn Marino }
6617e4b17023SJohn Marino /* For fixed-point modes, we need to pass saturating info. */
6618e4b17023SJohn Marino typefm = lang_hooks.types.type_for_mode (mode,
6619e4b17023SJohn Marino ALL_FIXED_POINT_MODE_P (mode) ? TYPE_SATURATING (type)
6620e4b17023SJohn Marino : TYPE_UNSIGNED (type));
6621e4b17023SJohn Marino }
6622e4b17023SJohn Marino
6623e4b17023SJohn Marino if (typefm == NULL_TREE)
6624e4b17023SJohn Marino {
6625e4b17023SJohn Marino error ("no data type for mode %qs", p);
6626e4b17023SJohn Marino return NULL_TREE;
6627e4b17023SJohn Marino }
6628e4b17023SJohn Marino else if (TREE_CODE (type) == ENUMERAL_TYPE)
6629e4b17023SJohn Marino {
6630e4b17023SJohn Marino /* For enumeral types, copy the precision from the integer
6631e4b17023SJohn Marino type returned above. If not an INTEGER_TYPE, we can't use
6632e4b17023SJohn Marino this mode for this type. */
6633e4b17023SJohn Marino if (TREE_CODE (typefm) != INTEGER_TYPE)
6634e4b17023SJohn Marino {
6635e4b17023SJohn Marino error ("cannot use mode %qs for enumeral types", p);
6636e4b17023SJohn Marino return NULL_TREE;
6637e4b17023SJohn Marino }
6638e4b17023SJohn Marino
6639e4b17023SJohn Marino if (flags & ATTR_FLAG_TYPE_IN_PLACE)
6640e4b17023SJohn Marino {
6641e4b17023SJohn Marino TYPE_PRECISION (type) = TYPE_PRECISION (typefm);
6642e4b17023SJohn Marino typefm = type;
6643e4b17023SJohn Marino }
6644e4b17023SJohn Marino else
6645e4b17023SJohn Marino {
6646e4b17023SJohn Marino /* We cannot build a type variant, as there's code that assumes
6647e4b17023SJohn Marino that TYPE_MAIN_VARIANT has the same mode. This includes the
6648e4b17023SJohn Marino debug generators. Instead, create a subrange type. This
6649e4b17023SJohn Marino results in all of the enumeral values being emitted only once
6650e4b17023SJohn Marino in the original, and the subtype gets them by reference. */
6651e4b17023SJohn Marino if (TYPE_UNSIGNED (type))
6652e4b17023SJohn Marino typefm = make_unsigned_type (TYPE_PRECISION (typefm));
6653e4b17023SJohn Marino else
6654e4b17023SJohn Marino typefm = make_signed_type (TYPE_PRECISION (typefm));
6655e4b17023SJohn Marino TREE_TYPE (typefm) = type;
6656e4b17023SJohn Marino }
6657e4b17023SJohn Marino }
6658e4b17023SJohn Marino else if (VECTOR_MODE_P (mode)
6659e4b17023SJohn Marino ? TREE_CODE (type) != TREE_CODE (TREE_TYPE (typefm))
6660e4b17023SJohn Marino : TREE_CODE (type) != TREE_CODE (typefm))
6661e4b17023SJohn Marino {
6662e4b17023SJohn Marino error ("mode %qs applied to inappropriate type", p);
6663e4b17023SJohn Marino return NULL_TREE;
6664e4b17023SJohn Marino }
6665e4b17023SJohn Marino
6666e4b17023SJohn Marino *node = typefm;
6667e4b17023SJohn Marino }
6668e4b17023SJohn Marino
6669e4b17023SJohn Marino return NULL_TREE;
6670e4b17023SJohn Marino }
6671e4b17023SJohn Marino
6672e4b17023SJohn Marino /* Handle a "section" attribute; arguments as in
6673e4b17023SJohn Marino struct attribute_spec.handler. */
6674e4b17023SJohn Marino
6675e4b17023SJohn Marino static tree
handle_section_attribute(tree * node,tree ARG_UNUSED (name),tree args,int ARG_UNUSED (flags),bool * no_add_attrs)6676e4b17023SJohn Marino handle_section_attribute (tree *node, tree ARG_UNUSED (name), tree args,
6677e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
6678e4b17023SJohn Marino {
6679e4b17023SJohn Marino tree decl = *node;
6680e4b17023SJohn Marino
6681e4b17023SJohn Marino if (targetm_common.have_named_sections)
6682e4b17023SJohn Marino {
6683e4b17023SJohn Marino user_defined_section_attribute = true;
6684e4b17023SJohn Marino
6685e4b17023SJohn Marino if ((TREE_CODE (decl) == FUNCTION_DECL
6686e4b17023SJohn Marino || TREE_CODE (decl) == VAR_DECL)
6687e4b17023SJohn Marino && TREE_CODE (TREE_VALUE (args)) == STRING_CST)
6688e4b17023SJohn Marino {
6689e4b17023SJohn Marino if (TREE_CODE (decl) == VAR_DECL
6690e4b17023SJohn Marino && current_function_decl != NULL_TREE
6691e4b17023SJohn Marino && !TREE_STATIC (decl))
6692e4b17023SJohn Marino {
6693e4b17023SJohn Marino error_at (DECL_SOURCE_LOCATION (decl),
6694e4b17023SJohn Marino "section attribute cannot be specified for "
6695e4b17023SJohn Marino "local variables");
6696e4b17023SJohn Marino *no_add_attrs = true;
6697e4b17023SJohn Marino }
6698e4b17023SJohn Marino
6699e4b17023SJohn Marino /* The decl may have already been given a section attribute
6700e4b17023SJohn Marino from a previous declaration. Ensure they match. */
6701e4b17023SJohn Marino else if (DECL_SECTION_NAME (decl) != NULL_TREE
6702e4b17023SJohn Marino && strcmp (TREE_STRING_POINTER (DECL_SECTION_NAME (decl)),
6703e4b17023SJohn Marino TREE_STRING_POINTER (TREE_VALUE (args))) != 0)
6704e4b17023SJohn Marino {
6705e4b17023SJohn Marino error ("section of %q+D conflicts with previous declaration",
6706e4b17023SJohn Marino *node);
6707e4b17023SJohn Marino *no_add_attrs = true;
6708e4b17023SJohn Marino }
6709e4b17023SJohn Marino else if (TREE_CODE (decl) == VAR_DECL
6710e4b17023SJohn Marino && !targetm.have_tls && targetm.emutls.tmpl_section
6711e4b17023SJohn Marino && DECL_THREAD_LOCAL_P (decl))
6712e4b17023SJohn Marino {
6713e4b17023SJohn Marino error ("section of %q+D cannot be overridden", *node);
6714e4b17023SJohn Marino *no_add_attrs = true;
6715e4b17023SJohn Marino }
6716e4b17023SJohn Marino else
6717e4b17023SJohn Marino DECL_SECTION_NAME (decl) = TREE_VALUE (args);
6718e4b17023SJohn Marino }
6719e4b17023SJohn Marino else
6720e4b17023SJohn Marino {
6721e4b17023SJohn Marino error ("section attribute not allowed for %q+D", *node);
6722e4b17023SJohn Marino *no_add_attrs = true;
6723e4b17023SJohn Marino }
6724e4b17023SJohn Marino }
6725e4b17023SJohn Marino else
6726e4b17023SJohn Marino {
6727e4b17023SJohn Marino error_at (DECL_SOURCE_LOCATION (*node),
6728e4b17023SJohn Marino "section attributes are not supported for this target");
6729e4b17023SJohn Marino *no_add_attrs = true;
6730e4b17023SJohn Marino }
6731e4b17023SJohn Marino
6732e4b17023SJohn Marino return NULL_TREE;
6733e4b17023SJohn Marino }
6734e4b17023SJohn Marino
6735e4b17023SJohn Marino /* Check whether ALIGN is a valid user-specified alignment. If so,
6736e4b17023SJohn Marino return its base-2 log; if not, output an error and return -1. If
6737e4b17023SJohn Marino ALLOW_ZERO then 0 is valid and should result in a return of -1 with
6738e4b17023SJohn Marino no error. */
6739e4b17023SJohn Marino int
check_user_alignment(const_tree align,bool allow_zero)6740e4b17023SJohn Marino check_user_alignment (const_tree align, bool allow_zero)
6741e4b17023SJohn Marino {
6742e4b17023SJohn Marino int i;
6743e4b17023SJohn Marino
6744*5ce9237cSJohn Marino if (TREE_CODE (align) != INTEGER_CST
6745*5ce9237cSJohn Marino || !INTEGRAL_TYPE_P (TREE_TYPE (align)))
6746e4b17023SJohn Marino {
6747e4b17023SJohn Marino error ("requested alignment is not an integer constant");
6748e4b17023SJohn Marino return -1;
6749e4b17023SJohn Marino }
6750e4b17023SJohn Marino else if (allow_zero && integer_zerop (align))
6751e4b17023SJohn Marino return -1;
6752e4b17023SJohn Marino else if ((i = tree_log2 (align)) == -1)
6753e4b17023SJohn Marino {
6754e4b17023SJohn Marino error ("requested alignment is not a power of 2");
6755e4b17023SJohn Marino return -1;
6756e4b17023SJohn Marino }
6757e4b17023SJohn Marino else if (i >= HOST_BITS_PER_INT - BITS_PER_UNIT_LOG)
6758e4b17023SJohn Marino {
6759e4b17023SJohn Marino error ("requested alignment is too large");
6760e4b17023SJohn Marino return -1;
6761e4b17023SJohn Marino }
6762e4b17023SJohn Marino return i;
6763e4b17023SJohn Marino }
6764e4b17023SJohn Marino
6765e4b17023SJohn Marino /* Handle a "aligned" attribute; arguments as in
6766e4b17023SJohn Marino struct attribute_spec.handler. */
6767e4b17023SJohn Marino
6768e4b17023SJohn Marino static tree
handle_aligned_attribute(tree * node,tree ARG_UNUSED (name),tree args,int flags,bool * no_add_attrs)6769e4b17023SJohn Marino handle_aligned_attribute (tree *node, tree ARG_UNUSED (name), tree args,
6770e4b17023SJohn Marino int flags, bool *no_add_attrs)
6771e4b17023SJohn Marino {
6772e4b17023SJohn Marino tree decl = NULL_TREE;
6773e4b17023SJohn Marino tree *type = NULL;
6774e4b17023SJohn Marino int is_type = 0;
6775e4b17023SJohn Marino tree align_expr = (args ? TREE_VALUE (args)
6776e4b17023SJohn Marino : size_int (ATTRIBUTE_ALIGNED_VALUE / BITS_PER_UNIT));
6777e4b17023SJohn Marino int i;
6778e4b17023SJohn Marino
6779e4b17023SJohn Marino if (DECL_P (*node))
6780e4b17023SJohn Marino {
6781e4b17023SJohn Marino decl = *node;
6782e4b17023SJohn Marino type = &TREE_TYPE (decl);
6783e4b17023SJohn Marino is_type = TREE_CODE (*node) == TYPE_DECL;
6784e4b17023SJohn Marino }
6785e4b17023SJohn Marino else if (TYPE_P (*node))
6786e4b17023SJohn Marino type = node, is_type = 1;
6787e4b17023SJohn Marino
6788e4b17023SJohn Marino if ((i = check_user_alignment (align_expr, false)) == -1)
6789e4b17023SJohn Marino *no_add_attrs = true;
6790e4b17023SJohn Marino else if (is_type)
6791e4b17023SJohn Marino {
6792e4b17023SJohn Marino if ((flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
6793e4b17023SJohn Marino /* OK, modify the type in place. */;
6794e4b17023SJohn Marino /* If we have a TYPE_DECL, then copy the type, so that we
6795e4b17023SJohn Marino don't accidentally modify a builtin type. See pushdecl. */
6796e4b17023SJohn Marino else if (decl && TREE_TYPE (decl) != error_mark_node
6797e4b17023SJohn Marino && DECL_ORIGINAL_TYPE (decl) == NULL_TREE)
6798e4b17023SJohn Marino {
6799e4b17023SJohn Marino tree tt = TREE_TYPE (decl);
6800e4b17023SJohn Marino *type = build_variant_type_copy (*type);
6801e4b17023SJohn Marino DECL_ORIGINAL_TYPE (decl) = tt;
6802e4b17023SJohn Marino TYPE_NAME (*type) = decl;
6803e4b17023SJohn Marino TREE_USED (*type) = TREE_USED (decl);
6804e4b17023SJohn Marino TREE_TYPE (decl) = *type;
6805e4b17023SJohn Marino }
6806e4b17023SJohn Marino else
6807e4b17023SJohn Marino *type = build_variant_type_copy (*type);
6808e4b17023SJohn Marino
6809e4b17023SJohn Marino TYPE_ALIGN (*type) = (1U << i) * BITS_PER_UNIT;
6810e4b17023SJohn Marino TYPE_USER_ALIGN (*type) = 1;
6811e4b17023SJohn Marino }
6812e4b17023SJohn Marino else if (! VAR_OR_FUNCTION_DECL_P (decl)
6813e4b17023SJohn Marino && TREE_CODE (decl) != FIELD_DECL)
6814e4b17023SJohn Marino {
6815e4b17023SJohn Marino error ("alignment may not be specified for %q+D", decl);
6816e4b17023SJohn Marino *no_add_attrs = true;
6817e4b17023SJohn Marino }
6818e4b17023SJohn Marino else if (TREE_CODE (decl) == FUNCTION_DECL
6819e4b17023SJohn Marino && DECL_ALIGN (decl) > (1U << i) * BITS_PER_UNIT)
6820e4b17023SJohn Marino {
6821e4b17023SJohn Marino if (DECL_USER_ALIGN (decl))
6822e4b17023SJohn Marino error ("alignment for %q+D was previously specified as %d "
6823e4b17023SJohn Marino "and may not be decreased", decl,
6824e4b17023SJohn Marino DECL_ALIGN (decl) / BITS_PER_UNIT);
6825e4b17023SJohn Marino else
6826e4b17023SJohn Marino error ("alignment for %q+D must be at least %d", decl,
6827e4b17023SJohn Marino DECL_ALIGN (decl) / BITS_PER_UNIT);
6828e4b17023SJohn Marino *no_add_attrs = true;
6829e4b17023SJohn Marino }
6830e4b17023SJohn Marino else
6831e4b17023SJohn Marino {
6832e4b17023SJohn Marino DECL_ALIGN (decl) = (1U << i) * BITS_PER_UNIT;
6833e4b17023SJohn Marino DECL_USER_ALIGN (decl) = 1;
6834e4b17023SJohn Marino }
6835e4b17023SJohn Marino
6836e4b17023SJohn Marino return NULL_TREE;
6837e4b17023SJohn Marino }
6838e4b17023SJohn Marino
6839e4b17023SJohn Marino /* Handle a "weak" attribute; arguments as in
6840e4b17023SJohn Marino struct attribute_spec.handler. */
6841e4b17023SJohn Marino
6842e4b17023SJohn Marino static tree
handle_weak_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * ARG_UNUSED (no_add_attrs))6843e4b17023SJohn Marino handle_weak_attribute (tree *node, tree name,
6844e4b17023SJohn Marino tree ARG_UNUSED (args),
6845e4b17023SJohn Marino int ARG_UNUSED (flags),
6846e4b17023SJohn Marino bool * ARG_UNUSED (no_add_attrs))
6847e4b17023SJohn Marino {
6848e4b17023SJohn Marino if (TREE_CODE (*node) == FUNCTION_DECL
6849e4b17023SJohn Marino && DECL_DECLARED_INLINE_P (*node))
6850e4b17023SJohn Marino {
6851e4b17023SJohn Marino warning (OPT_Wattributes, "inline function %q+D declared weak", *node);
6852e4b17023SJohn Marino *no_add_attrs = true;
6853e4b17023SJohn Marino }
6854e4b17023SJohn Marino else if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (*node)))
6855e4b17023SJohn Marino {
6856e4b17023SJohn Marino error ("indirect function %q+D cannot be declared weak", *node);
6857e4b17023SJohn Marino *no_add_attrs = true;
6858e4b17023SJohn Marino return NULL_TREE;
6859e4b17023SJohn Marino }
6860e4b17023SJohn Marino else if (TREE_CODE (*node) == FUNCTION_DECL
6861e4b17023SJohn Marino || TREE_CODE (*node) == VAR_DECL)
6862e4b17023SJohn Marino declare_weak (*node);
6863e4b17023SJohn Marino else
6864e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6865e4b17023SJohn Marino
6866e4b17023SJohn Marino return NULL_TREE;
6867e4b17023SJohn Marino }
6868e4b17023SJohn Marino
6869e4b17023SJohn Marino /* Handle an "alias" or "ifunc" attribute; arguments as in
6870e4b17023SJohn Marino struct attribute_spec.handler, except that IS_ALIAS tells us
6871e4b17023SJohn Marino whether this is an alias as opposed to ifunc attribute. */
6872e4b17023SJohn Marino
6873e4b17023SJohn Marino static tree
handle_alias_ifunc_attribute(bool is_alias,tree * node,tree name,tree args,bool * no_add_attrs)6874e4b17023SJohn Marino handle_alias_ifunc_attribute (bool is_alias, tree *node, tree name, tree args,
6875e4b17023SJohn Marino bool *no_add_attrs)
6876e4b17023SJohn Marino {
6877e4b17023SJohn Marino tree decl = *node;
6878e4b17023SJohn Marino
6879e4b17023SJohn Marino if (TREE_CODE (decl) != FUNCTION_DECL
6880e4b17023SJohn Marino && (!is_alias || TREE_CODE (decl) != VAR_DECL))
6881e4b17023SJohn Marino {
6882e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6883e4b17023SJohn Marino *no_add_attrs = true;
6884e4b17023SJohn Marino }
6885e4b17023SJohn Marino else if ((TREE_CODE (decl) == FUNCTION_DECL && DECL_INITIAL (decl))
6886e4b17023SJohn Marino || (TREE_CODE (decl) != FUNCTION_DECL
6887e4b17023SJohn Marino && TREE_PUBLIC (decl) && !DECL_EXTERNAL (decl))
6888e4b17023SJohn Marino /* A static variable declaration is always a tentative definition,
6889e4b17023SJohn Marino but the alias is a non-tentative definition which overrides. */
6890e4b17023SJohn Marino || (TREE_CODE (decl) != FUNCTION_DECL
6891e4b17023SJohn Marino && ! TREE_PUBLIC (decl) && DECL_INITIAL (decl)))
6892e4b17023SJohn Marino {
6893e4b17023SJohn Marino error ("%q+D defined both normally and as %qE attribute", decl, name);
6894e4b17023SJohn Marino *no_add_attrs = true;
6895e4b17023SJohn Marino return NULL_TREE;
6896e4b17023SJohn Marino }
6897e4b17023SJohn Marino else if (!is_alias
6898e4b17023SJohn Marino && (lookup_attribute ("weak", DECL_ATTRIBUTES (decl))
6899e4b17023SJohn Marino || lookup_attribute ("weakref", DECL_ATTRIBUTES (decl))))
6900e4b17023SJohn Marino {
6901e4b17023SJohn Marino error ("weak %q+D cannot be defined %qE", decl, name);
6902e4b17023SJohn Marino *no_add_attrs = true;
6903e4b17023SJohn Marino return NULL_TREE;
6904e4b17023SJohn Marino }
6905e4b17023SJohn Marino
6906e4b17023SJohn Marino /* Note that the very first time we process a nested declaration,
6907e4b17023SJohn Marino decl_function_context will not be set. Indeed, *would* never
6908e4b17023SJohn Marino be set except for the DECL_INITIAL/DECL_EXTERNAL frobbery that
6909e4b17023SJohn Marino we do below. After such frobbery, pushdecl would set the context.
6910e4b17023SJohn Marino In any case, this is never what we want. */
6911e4b17023SJohn Marino else if (decl_function_context (decl) == 0 && current_function_decl == NULL)
6912e4b17023SJohn Marino {
6913e4b17023SJohn Marino tree id;
6914e4b17023SJohn Marino
6915e4b17023SJohn Marino id = TREE_VALUE (args);
6916e4b17023SJohn Marino if (TREE_CODE (id) != STRING_CST)
6917e4b17023SJohn Marino {
6918e4b17023SJohn Marino error ("attribute %qE argument not a string", name);
6919e4b17023SJohn Marino *no_add_attrs = true;
6920e4b17023SJohn Marino return NULL_TREE;
6921e4b17023SJohn Marino }
6922e4b17023SJohn Marino id = get_identifier (TREE_STRING_POINTER (id));
6923e4b17023SJohn Marino /* This counts as a use of the object pointed to. */
6924e4b17023SJohn Marino TREE_USED (id) = 1;
6925e4b17023SJohn Marino
6926e4b17023SJohn Marino if (TREE_CODE (decl) == FUNCTION_DECL)
6927e4b17023SJohn Marino DECL_INITIAL (decl) = error_mark_node;
6928e4b17023SJohn Marino else
6929e4b17023SJohn Marino {
6930e4b17023SJohn Marino if (lookup_attribute ("weakref", DECL_ATTRIBUTES (decl)))
6931e4b17023SJohn Marino DECL_EXTERNAL (decl) = 1;
6932e4b17023SJohn Marino else
6933e4b17023SJohn Marino DECL_EXTERNAL (decl) = 0;
6934e4b17023SJohn Marino TREE_STATIC (decl) = 1;
6935e4b17023SJohn Marino }
6936e4b17023SJohn Marino
6937e4b17023SJohn Marino if (!is_alias)
6938e4b17023SJohn Marino /* ifuncs are also aliases, so set that attribute too. */
6939e4b17023SJohn Marino DECL_ATTRIBUTES (decl)
6940e4b17023SJohn Marino = tree_cons (get_identifier ("alias"), args, DECL_ATTRIBUTES (decl));
6941e4b17023SJohn Marino }
6942e4b17023SJohn Marino else
6943e4b17023SJohn Marino {
6944e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6945e4b17023SJohn Marino *no_add_attrs = true;
6946e4b17023SJohn Marino }
6947e4b17023SJohn Marino
6948e4b17023SJohn Marino return NULL_TREE;
6949e4b17023SJohn Marino }
6950e4b17023SJohn Marino
6951e4b17023SJohn Marino /* Handle an "alias" or "ifunc" attribute; arguments as in
6952e4b17023SJohn Marino struct attribute_spec.handler. */
6953e4b17023SJohn Marino
6954e4b17023SJohn Marino static tree
handle_ifunc_attribute(tree * node,tree name,tree args,int ARG_UNUSED (flags),bool * no_add_attrs)6955e4b17023SJohn Marino handle_ifunc_attribute (tree *node, tree name, tree args,
6956e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
6957e4b17023SJohn Marino {
6958e4b17023SJohn Marino return handle_alias_ifunc_attribute (false, node, name, args, no_add_attrs);
6959e4b17023SJohn Marino }
6960e4b17023SJohn Marino
6961e4b17023SJohn Marino /* Handle an "alias" or "ifunc" attribute; arguments as in
6962e4b17023SJohn Marino struct attribute_spec.handler. */
6963e4b17023SJohn Marino
6964e4b17023SJohn Marino static tree
handle_alias_attribute(tree * node,tree name,tree args,int ARG_UNUSED (flags),bool * no_add_attrs)6965e4b17023SJohn Marino handle_alias_attribute (tree *node, tree name, tree args,
6966e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
6967e4b17023SJohn Marino {
6968e4b17023SJohn Marino return handle_alias_ifunc_attribute (true, node, name, args, no_add_attrs);
6969e4b17023SJohn Marino }
6970e4b17023SJohn Marino
6971e4b17023SJohn Marino /* Handle a "weakref" attribute; arguments as in struct
6972e4b17023SJohn Marino attribute_spec.handler. */
6973e4b17023SJohn Marino
6974e4b17023SJohn Marino static tree
handle_weakref_attribute(tree * node,tree ARG_UNUSED (name),tree args,int flags,bool * no_add_attrs)6975e4b17023SJohn Marino handle_weakref_attribute (tree *node, tree ARG_UNUSED (name), tree args,
6976e4b17023SJohn Marino int flags, bool *no_add_attrs)
6977e4b17023SJohn Marino {
6978e4b17023SJohn Marino tree attr = NULL_TREE;
6979e4b17023SJohn Marino
6980e4b17023SJohn Marino /* We must ignore the attribute when it is associated with
6981e4b17023SJohn Marino local-scoped decls, since attribute alias is ignored and many
6982e4b17023SJohn Marino such symbols do not even have a DECL_WEAK field. */
6983e4b17023SJohn Marino if (decl_function_context (*node)
6984e4b17023SJohn Marino || current_function_decl
6985e4b17023SJohn Marino || (TREE_CODE (*node) != VAR_DECL && TREE_CODE (*node) != FUNCTION_DECL))
6986e4b17023SJohn Marino {
6987e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
6988e4b17023SJohn Marino *no_add_attrs = true;
6989e4b17023SJohn Marino return NULL_TREE;
6990e4b17023SJohn Marino }
6991e4b17023SJohn Marino
6992e4b17023SJohn Marino if (lookup_attribute ("ifunc", DECL_ATTRIBUTES (*node)))
6993e4b17023SJohn Marino {
6994e4b17023SJohn Marino error ("indirect function %q+D cannot be declared weakref", *node);
6995e4b17023SJohn Marino *no_add_attrs = true;
6996e4b17023SJohn Marino return NULL_TREE;
6997e4b17023SJohn Marino }
6998e4b17023SJohn Marino
6999e4b17023SJohn Marino /* The idea here is that `weakref("name")' mutates into `weakref,
7000e4b17023SJohn Marino alias("name")', and weakref without arguments, in turn,
7001e4b17023SJohn Marino implicitly adds weak. */
7002e4b17023SJohn Marino
7003e4b17023SJohn Marino if (args)
7004e4b17023SJohn Marino {
7005e4b17023SJohn Marino attr = tree_cons (get_identifier ("alias"), args, attr);
7006e4b17023SJohn Marino attr = tree_cons (get_identifier ("weakref"), NULL_TREE, attr);
7007e4b17023SJohn Marino
7008e4b17023SJohn Marino *no_add_attrs = true;
7009e4b17023SJohn Marino
7010e4b17023SJohn Marino decl_attributes (node, attr, flags);
7011e4b17023SJohn Marino }
7012e4b17023SJohn Marino else
7013e4b17023SJohn Marino {
7014e4b17023SJohn Marino if (lookup_attribute ("alias", DECL_ATTRIBUTES (*node)))
7015e4b17023SJohn Marino error_at (DECL_SOURCE_LOCATION (*node),
7016e4b17023SJohn Marino "weakref attribute must appear before alias attribute");
7017e4b17023SJohn Marino
7018e4b17023SJohn Marino /* Can't call declare_weak because it wants this to be TREE_PUBLIC,
7019e4b17023SJohn Marino and that isn't supported; and because it wants to add it to
7020e4b17023SJohn Marino the list of weak decls, which isn't helpful. */
7021e4b17023SJohn Marino DECL_WEAK (*node) = 1;
7022e4b17023SJohn Marino }
7023e4b17023SJohn Marino
7024e4b17023SJohn Marino return NULL_TREE;
7025e4b17023SJohn Marino }
7026e4b17023SJohn Marino
7027e4b17023SJohn Marino /* Handle an "visibility" attribute; arguments as in
7028e4b17023SJohn Marino struct attribute_spec.handler. */
7029e4b17023SJohn Marino
7030e4b17023SJohn Marino static tree
handle_visibility_attribute(tree * node,tree name,tree args,int ARG_UNUSED (flags),bool * ARG_UNUSED (no_add_attrs))7031e4b17023SJohn Marino handle_visibility_attribute (tree *node, tree name, tree args,
7032e4b17023SJohn Marino int ARG_UNUSED (flags),
7033e4b17023SJohn Marino bool *ARG_UNUSED (no_add_attrs))
7034e4b17023SJohn Marino {
7035e4b17023SJohn Marino tree decl = *node;
7036e4b17023SJohn Marino tree id = TREE_VALUE (args);
7037e4b17023SJohn Marino enum symbol_visibility vis;
7038e4b17023SJohn Marino
7039e4b17023SJohn Marino if (TYPE_P (*node))
7040e4b17023SJohn Marino {
7041e4b17023SJohn Marino if (TREE_CODE (*node) == ENUMERAL_TYPE)
7042e4b17023SJohn Marino /* OK */;
7043e4b17023SJohn Marino else if (TREE_CODE (*node) != RECORD_TYPE && TREE_CODE (*node) != UNION_TYPE)
7044e4b17023SJohn Marino {
7045e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored on non-class types",
7046e4b17023SJohn Marino name);
7047e4b17023SJohn Marino return NULL_TREE;
7048e4b17023SJohn Marino }
7049e4b17023SJohn Marino else if (TYPE_FIELDS (*node))
7050e4b17023SJohn Marino {
7051e4b17023SJohn Marino error ("%qE attribute ignored because %qT is already defined",
7052e4b17023SJohn Marino name, *node);
7053e4b17023SJohn Marino return NULL_TREE;
7054e4b17023SJohn Marino }
7055e4b17023SJohn Marino }
7056e4b17023SJohn Marino else if (decl_function_context (decl) != 0 || !TREE_PUBLIC (decl))
7057e4b17023SJohn Marino {
7058e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
7059e4b17023SJohn Marino return NULL_TREE;
7060e4b17023SJohn Marino }
7061e4b17023SJohn Marino
7062e4b17023SJohn Marino if (TREE_CODE (id) != STRING_CST)
7063e4b17023SJohn Marino {
7064e4b17023SJohn Marino error ("visibility argument not a string");
7065e4b17023SJohn Marino return NULL_TREE;
7066e4b17023SJohn Marino }
7067e4b17023SJohn Marino
7068e4b17023SJohn Marino /* If this is a type, set the visibility on the type decl. */
7069e4b17023SJohn Marino if (TYPE_P (decl))
7070e4b17023SJohn Marino {
7071e4b17023SJohn Marino decl = TYPE_NAME (decl);
7072e4b17023SJohn Marino if (!decl)
7073e4b17023SJohn Marino return NULL_TREE;
7074e4b17023SJohn Marino if (TREE_CODE (decl) == IDENTIFIER_NODE)
7075e4b17023SJohn Marino {
7076e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored on types",
7077e4b17023SJohn Marino name);
7078e4b17023SJohn Marino return NULL_TREE;
7079e4b17023SJohn Marino }
7080e4b17023SJohn Marino }
7081e4b17023SJohn Marino
7082e4b17023SJohn Marino if (strcmp (TREE_STRING_POINTER (id), "default") == 0)
7083e4b17023SJohn Marino vis = VISIBILITY_DEFAULT;
7084e4b17023SJohn Marino else if (strcmp (TREE_STRING_POINTER (id), "internal") == 0)
7085e4b17023SJohn Marino vis = VISIBILITY_INTERNAL;
7086e4b17023SJohn Marino else if (strcmp (TREE_STRING_POINTER (id), "hidden") == 0)
7087e4b17023SJohn Marino vis = VISIBILITY_HIDDEN;
7088e4b17023SJohn Marino else if (strcmp (TREE_STRING_POINTER (id), "protected") == 0)
7089e4b17023SJohn Marino vis = VISIBILITY_PROTECTED;
7090e4b17023SJohn Marino else
7091e4b17023SJohn Marino {
7092e4b17023SJohn Marino error ("visibility argument must be one of \"default\", \"hidden\", \"protected\" or \"internal\"");
7093e4b17023SJohn Marino vis = VISIBILITY_DEFAULT;
7094e4b17023SJohn Marino }
7095e4b17023SJohn Marino
7096e4b17023SJohn Marino if (DECL_VISIBILITY_SPECIFIED (decl)
7097e4b17023SJohn Marino && vis != DECL_VISIBILITY (decl))
7098e4b17023SJohn Marino {
7099e4b17023SJohn Marino tree attributes = (TYPE_P (*node)
7100e4b17023SJohn Marino ? TYPE_ATTRIBUTES (*node)
7101e4b17023SJohn Marino : DECL_ATTRIBUTES (decl));
7102e4b17023SJohn Marino if (lookup_attribute ("visibility", attributes))
7103e4b17023SJohn Marino error ("%qD redeclared with different visibility", decl);
7104e4b17023SJohn Marino else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
7105e4b17023SJohn Marino && lookup_attribute ("dllimport", attributes))
7106e4b17023SJohn Marino error ("%qD was declared %qs which implies default visibility",
7107e4b17023SJohn Marino decl, "dllimport");
7108e4b17023SJohn Marino else if (TARGET_DLLIMPORT_DECL_ATTRIBUTES
7109e4b17023SJohn Marino && lookup_attribute ("dllexport", attributes))
7110e4b17023SJohn Marino error ("%qD was declared %qs which implies default visibility",
7111e4b17023SJohn Marino decl, "dllexport");
7112e4b17023SJohn Marino }
7113e4b17023SJohn Marino
7114e4b17023SJohn Marino DECL_VISIBILITY (decl) = vis;
7115e4b17023SJohn Marino DECL_VISIBILITY_SPECIFIED (decl) = 1;
7116e4b17023SJohn Marino
7117e4b17023SJohn Marino /* Go ahead and attach the attribute to the node as well. This is needed
7118e4b17023SJohn Marino so we can determine whether we have VISIBILITY_DEFAULT because the
7119e4b17023SJohn Marino visibility was not specified, or because it was explicitly overridden
7120e4b17023SJohn Marino from the containing scope. */
7121e4b17023SJohn Marino
7122e4b17023SJohn Marino return NULL_TREE;
7123e4b17023SJohn Marino }
7124e4b17023SJohn Marino
7125e4b17023SJohn Marino /* Determine the ELF symbol visibility for DECL, which is either a
7126e4b17023SJohn Marino variable or a function. It is an error to use this function if a
7127e4b17023SJohn Marino definition of DECL is not available in this translation unit.
7128e4b17023SJohn Marino Returns true if the final visibility has been determined by this
7129e4b17023SJohn Marino function; false if the caller is free to make additional
7130e4b17023SJohn Marino modifications. */
7131e4b17023SJohn Marino
7132e4b17023SJohn Marino bool
c_determine_visibility(tree decl)7133e4b17023SJohn Marino c_determine_visibility (tree decl)
7134e4b17023SJohn Marino {
7135e4b17023SJohn Marino gcc_assert (TREE_CODE (decl) == VAR_DECL
7136e4b17023SJohn Marino || TREE_CODE (decl) == FUNCTION_DECL);
7137e4b17023SJohn Marino
7138e4b17023SJohn Marino /* If the user explicitly specified the visibility with an
7139e4b17023SJohn Marino attribute, honor that. DECL_VISIBILITY will have been set during
7140e4b17023SJohn Marino the processing of the attribute. We check for an explicit
7141e4b17023SJohn Marino attribute, rather than just checking DECL_VISIBILITY_SPECIFIED,
7142e4b17023SJohn Marino to distinguish the use of an attribute from the use of a "#pragma
7143e4b17023SJohn Marino GCC visibility push(...)"; in the latter case we still want other
7144e4b17023SJohn Marino considerations to be able to overrule the #pragma. */
7145e4b17023SJohn Marino if (lookup_attribute ("visibility", DECL_ATTRIBUTES (decl))
7146e4b17023SJohn Marino || (TARGET_DLLIMPORT_DECL_ATTRIBUTES
7147e4b17023SJohn Marino && (lookup_attribute ("dllimport", DECL_ATTRIBUTES (decl))
7148e4b17023SJohn Marino || lookup_attribute ("dllexport", DECL_ATTRIBUTES (decl)))))
7149e4b17023SJohn Marino return true;
7150e4b17023SJohn Marino
7151e4b17023SJohn Marino /* Set default visibility to whatever the user supplied with
7152e4b17023SJohn Marino visibility_specified depending on #pragma GCC visibility. */
7153e4b17023SJohn Marino if (!DECL_VISIBILITY_SPECIFIED (decl))
7154e4b17023SJohn Marino {
7155e4b17023SJohn Marino if (visibility_options.inpragma
7156e4b17023SJohn Marino || DECL_VISIBILITY (decl) != default_visibility)
7157e4b17023SJohn Marino {
7158e4b17023SJohn Marino DECL_VISIBILITY (decl) = default_visibility;
7159e4b17023SJohn Marino DECL_VISIBILITY_SPECIFIED (decl) = visibility_options.inpragma;
7160e4b17023SJohn Marino /* If visibility changed and DECL already has DECL_RTL, ensure
7161e4b17023SJohn Marino symbol flags are updated. */
7162e4b17023SJohn Marino if (((TREE_CODE (decl) == VAR_DECL && TREE_STATIC (decl))
7163e4b17023SJohn Marino || TREE_CODE (decl) == FUNCTION_DECL)
7164e4b17023SJohn Marino && DECL_RTL_SET_P (decl))
7165e4b17023SJohn Marino make_decl_rtl (decl);
7166e4b17023SJohn Marino }
7167e4b17023SJohn Marino }
7168e4b17023SJohn Marino return false;
7169e4b17023SJohn Marino }
7170e4b17023SJohn Marino
7171e4b17023SJohn Marino /* Handle an "tls_model" attribute; arguments as in
7172e4b17023SJohn Marino struct attribute_spec.handler. */
7173e4b17023SJohn Marino
7174e4b17023SJohn Marino static tree
handle_tls_model_attribute(tree * node,tree name,tree args,int ARG_UNUSED (flags),bool * no_add_attrs)7175e4b17023SJohn Marino handle_tls_model_attribute (tree *node, tree name, tree args,
7176e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
7177e4b17023SJohn Marino {
7178e4b17023SJohn Marino tree id;
7179e4b17023SJohn Marino tree decl = *node;
7180e4b17023SJohn Marino enum tls_model kind;
7181e4b17023SJohn Marino
7182e4b17023SJohn Marino *no_add_attrs = true;
7183e4b17023SJohn Marino
7184e4b17023SJohn Marino if (TREE_CODE (decl) != VAR_DECL || !DECL_THREAD_LOCAL_P (decl))
7185e4b17023SJohn Marino {
7186e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
7187e4b17023SJohn Marino return NULL_TREE;
7188e4b17023SJohn Marino }
7189e4b17023SJohn Marino
7190e4b17023SJohn Marino kind = DECL_TLS_MODEL (decl);
7191e4b17023SJohn Marino id = TREE_VALUE (args);
7192e4b17023SJohn Marino if (TREE_CODE (id) != STRING_CST)
7193e4b17023SJohn Marino {
7194e4b17023SJohn Marino error ("tls_model argument not a string");
7195e4b17023SJohn Marino return NULL_TREE;
7196e4b17023SJohn Marino }
7197e4b17023SJohn Marino
7198e4b17023SJohn Marino if (!strcmp (TREE_STRING_POINTER (id), "local-exec"))
7199e4b17023SJohn Marino kind = TLS_MODEL_LOCAL_EXEC;
7200e4b17023SJohn Marino else if (!strcmp (TREE_STRING_POINTER (id), "initial-exec"))
7201e4b17023SJohn Marino kind = TLS_MODEL_INITIAL_EXEC;
7202e4b17023SJohn Marino else if (!strcmp (TREE_STRING_POINTER (id), "local-dynamic"))
7203e4b17023SJohn Marino kind = optimize ? TLS_MODEL_LOCAL_DYNAMIC : TLS_MODEL_GLOBAL_DYNAMIC;
7204e4b17023SJohn Marino else if (!strcmp (TREE_STRING_POINTER (id), "global-dynamic"))
7205e4b17023SJohn Marino kind = TLS_MODEL_GLOBAL_DYNAMIC;
7206e4b17023SJohn Marino else
7207e4b17023SJohn Marino error ("tls_model argument must be one of \"local-exec\", \"initial-exec\", \"local-dynamic\" or \"global-dynamic\"");
7208e4b17023SJohn Marino
7209e4b17023SJohn Marino DECL_TLS_MODEL (decl) = kind;
7210e4b17023SJohn Marino return NULL_TREE;
7211e4b17023SJohn Marino }
7212e4b17023SJohn Marino
7213e4b17023SJohn Marino /* Handle a "no_instrument_function" attribute; arguments as in
7214e4b17023SJohn Marino struct attribute_spec.handler. */
7215e4b17023SJohn Marino
7216e4b17023SJohn Marino static tree
handle_no_instrument_function_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)7217e4b17023SJohn Marino handle_no_instrument_function_attribute (tree *node, tree name,
7218e4b17023SJohn Marino tree ARG_UNUSED (args),
7219e4b17023SJohn Marino int ARG_UNUSED (flags),
7220e4b17023SJohn Marino bool *no_add_attrs)
7221e4b17023SJohn Marino {
7222e4b17023SJohn Marino tree decl = *node;
7223e4b17023SJohn Marino
7224e4b17023SJohn Marino if (TREE_CODE (decl) != FUNCTION_DECL)
7225e4b17023SJohn Marino {
7226e4b17023SJohn Marino error_at (DECL_SOURCE_LOCATION (decl),
7227e4b17023SJohn Marino "%qE attribute applies only to functions", name);
7228e4b17023SJohn Marino *no_add_attrs = true;
7229e4b17023SJohn Marino }
7230e4b17023SJohn Marino else if (DECL_INITIAL (decl))
7231e4b17023SJohn Marino {
7232e4b17023SJohn Marino error_at (DECL_SOURCE_LOCATION (decl),
7233e4b17023SJohn Marino "can%'t set %qE attribute after definition", name);
7234e4b17023SJohn Marino *no_add_attrs = true;
7235e4b17023SJohn Marino }
7236e4b17023SJohn Marino else
7237e4b17023SJohn Marino DECL_NO_INSTRUMENT_FUNCTION_ENTRY_EXIT (decl) = 1;
7238e4b17023SJohn Marino
7239e4b17023SJohn Marino return NULL_TREE;
7240e4b17023SJohn Marino }
7241e4b17023SJohn Marino
7242e4b17023SJohn Marino /* Handle a "malloc" attribute; arguments as in
7243e4b17023SJohn Marino struct attribute_spec.handler. */
7244e4b17023SJohn Marino
7245e4b17023SJohn Marino static tree
handle_malloc_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)7246e4b17023SJohn Marino handle_malloc_attribute (tree *node, tree name, tree ARG_UNUSED (args),
7247e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
7248e4b17023SJohn Marino {
7249e4b17023SJohn Marino if (TREE_CODE (*node) == FUNCTION_DECL
7250e4b17023SJohn Marino && POINTER_TYPE_P (TREE_TYPE (TREE_TYPE (*node))))
7251e4b17023SJohn Marino DECL_IS_MALLOC (*node) = 1;
7252e4b17023SJohn Marino else
7253e4b17023SJohn Marino {
7254e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
7255e4b17023SJohn Marino *no_add_attrs = true;
7256e4b17023SJohn Marino }
7257e4b17023SJohn Marino
7258e4b17023SJohn Marino return NULL_TREE;
7259e4b17023SJohn Marino }
7260e4b17023SJohn Marino
7261e4b17023SJohn Marino /* Handle a "alloc_size" attribute; arguments as in
7262e4b17023SJohn Marino struct attribute_spec.handler. */
7263e4b17023SJohn Marino
7264e4b17023SJohn Marino static tree
handle_alloc_size_attribute(tree * node,tree ARG_UNUSED (name),tree args,int ARG_UNUSED (flags),bool * no_add_attrs)7265e4b17023SJohn Marino handle_alloc_size_attribute (tree *node, tree ARG_UNUSED (name), tree args,
7266e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
7267e4b17023SJohn Marino {
7268e4b17023SJohn Marino unsigned arg_count = type_num_arguments (*node);
7269e4b17023SJohn Marino for (; args; args = TREE_CHAIN (args))
7270e4b17023SJohn Marino {
7271e4b17023SJohn Marino tree position = TREE_VALUE (args);
7272e4b17023SJohn Marino
7273e4b17023SJohn Marino if (TREE_CODE (position) != INTEGER_CST
7274e4b17023SJohn Marino || TREE_INT_CST_HIGH (position)
7275e4b17023SJohn Marino || TREE_INT_CST_LOW (position) < 1
7276e4b17023SJohn Marino || TREE_INT_CST_LOW (position) > arg_count )
7277e4b17023SJohn Marino {
7278e4b17023SJohn Marino warning (OPT_Wattributes,
7279e4b17023SJohn Marino "alloc_size parameter outside range");
7280e4b17023SJohn Marino *no_add_attrs = true;
7281e4b17023SJohn Marino return NULL_TREE;
7282e4b17023SJohn Marino }
7283e4b17023SJohn Marino }
7284e4b17023SJohn Marino return NULL_TREE;
7285e4b17023SJohn Marino }
7286e4b17023SJohn Marino
7287e4b17023SJohn Marino /* Handle a "fn spec" attribute; arguments as in
7288e4b17023SJohn Marino struct attribute_spec.handler. */
7289e4b17023SJohn Marino
7290e4b17023SJohn Marino static tree
handle_fnspec_attribute(tree * node ATTRIBUTE_UNUSED,tree ARG_UNUSED (name),tree args,int ARG_UNUSED (flags),bool * no_add_attrs ATTRIBUTE_UNUSED)7291e4b17023SJohn Marino handle_fnspec_attribute (tree *node ATTRIBUTE_UNUSED, tree ARG_UNUSED (name),
7292e4b17023SJohn Marino tree args, int ARG_UNUSED (flags),
7293e4b17023SJohn Marino bool *no_add_attrs ATTRIBUTE_UNUSED)
7294e4b17023SJohn Marino {
7295e4b17023SJohn Marino gcc_assert (args
7296e4b17023SJohn Marino && TREE_CODE (TREE_VALUE (args)) == STRING_CST
7297e4b17023SJohn Marino && !TREE_CHAIN (args));
7298e4b17023SJohn Marino return NULL_TREE;
7299e4b17023SJohn Marino }
7300e4b17023SJohn Marino
7301e4b17023SJohn Marino /* Handle a "returns_twice" attribute; arguments as in
7302e4b17023SJohn Marino struct attribute_spec.handler. */
7303e4b17023SJohn Marino
7304e4b17023SJohn Marino static tree
handle_returns_twice_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)7305e4b17023SJohn Marino handle_returns_twice_attribute (tree *node, tree name, tree ARG_UNUSED (args),
7306e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
7307e4b17023SJohn Marino {
7308e4b17023SJohn Marino if (TREE_CODE (*node) == FUNCTION_DECL)
7309e4b17023SJohn Marino DECL_IS_RETURNS_TWICE (*node) = 1;
7310e4b17023SJohn Marino else
7311e4b17023SJohn Marino {
7312e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
7313e4b17023SJohn Marino *no_add_attrs = true;
7314e4b17023SJohn Marino }
7315e4b17023SJohn Marino
7316e4b17023SJohn Marino return NULL_TREE;
7317e4b17023SJohn Marino }
7318e4b17023SJohn Marino
7319e4b17023SJohn Marino /* Handle a "no_limit_stack" attribute; arguments as in
7320e4b17023SJohn Marino struct attribute_spec.handler. */
7321e4b17023SJohn Marino
7322e4b17023SJohn Marino static tree
handle_no_limit_stack_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)7323e4b17023SJohn Marino handle_no_limit_stack_attribute (tree *node, tree name,
7324e4b17023SJohn Marino tree ARG_UNUSED (args),
7325e4b17023SJohn Marino int ARG_UNUSED (flags),
7326e4b17023SJohn Marino bool *no_add_attrs)
7327e4b17023SJohn Marino {
7328e4b17023SJohn Marino tree decl = *node;
7329e4b17023SJohn Marino
7330e4b17023SJohn Marino if (TREE_CODE (decl) != FUNCTION_DECL)
7331e4b17023SJohn Marino {
7332e4b17023SJohn Marino error_at (DECL_SOURCE_LOCATION (decl),
7333e4b17023SJohn Marino "%qE attribute applies only to functions", name);
7334e4b17023SJohn Marino *no_add_attrs = true;
7335e4b17023SJohn Marino }
7336e4b17023SJohn Marino else if (DECL_INITIAL (decl))
7337e4b17023SJohn Marino {
7338e4b17023SJohn Marino error_at (DECL_SOURCE_LOCATION (decl),
7339e4b17023SJohn Marino "can%'t set %qE attribute after definition", name);
7340e4b17023SJohn Marino *no_add_attrs = true;
7341e4b17023SJohn Marino }
7342e4b17023SJohn Marino else
7343e4b17023SJohn Marino DECL_NO_LIMIT_STACK (decl) = 1;
7344e4b17023SJohn Marino
7345e4b17023SJohn Marino return NULL_TREE;
7346e4b17023SJohn Marino }
7347e4b17023SJohn Marino
7348e4b17023SJohn Marino /* Handle a "pure" attribute; arguments as in
7349e4b17023SJohn Marino struct attribute_spec.handler. */
7350e4b17023SJohn Marino
7351e4b17023SJohn Marino static tree
handle_pure_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)7352e4b17023SJohn Marino handle_pure_attribute (tree *node, tree name, tree ARG_UNUSED (args),
7353e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
7354e4b17023SJohn Marino {
7355e4b17023SJohn Marino if (TREE_CODE (*node) == FUNCTION_DECL)
7356e4b17023SJohn Marino DECL_PURE_P (*node) = 1;
7357e4b17023SJohn Marino /* ??? TODO: Support types. */
7358e4b17023SJohn Marino else
7359e4b17023SJohn Marino {
7360e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
7361e4b17023SJohn Marino *no_add_attrs = true;
7362e4b17023SJohn Marino }
7363e4b17023SJohn Marino
7364e4b17023SJohn Marino return NULL_TREE;
7365e4b17023SJohn Marino }
7366e4b17023SJohn Marino
7367e4b17023SJohn Marino /* Digest an attribute list destined for a transactional memory statement.
7368e4b17023SJohn Marino ALLOWED is the set of attributes that are allowed for this statement;
7369e4b17023SJohn Marino return the attribute we parsed. Multiple attributes are never allowed. */
7370e4b17023SJohn Marino
7371e4b17023SJohn Marino int
parse_tm_stmt_attr(tree attrs,int allowed)7372e4b17023SJohn Marino parse_tm_stmt_attr (tree attrs, int allowed)
7373e4b17023SJohn Marino {
7374e4b17023SJohn Marino tree a_seen = NULL;
7375e4b17023SJohn Marino int m_seen = 0;
7376e4b17023SJohn Marino
7377e4b17023SJohn Marino for ( ; attrs ; attrs = TREE_CHAIN (attrs))
7378e4b17023SJohn Marino {
7379e4b17023SJohn Marino tree a = TREE_PURPOSE (attrs);
7380e4b17023SJohn Marino int m = 0;
7381e4b17023SJohn Marino
7382e4b17023SJohn Marino if (is_attribute_p ("outer", a))
7383e4b17023SJohn Marino m = TM_STMT_ATTR_OUTER;
7384e4b17023SJohn Marino
7385e4b17023SJohn Marino if ((m & allowed) == 0)
7386e4b17023SJohn Marino {
7387e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute directive ignored", a);
7388e4b17023SJohn Marino continue;
7389e4b17023SJohn Marino }
7390e4b17023SJohn Marino
7391e4b17023SJohn Marino if (m_seen == 0)
7392e4b17023SJohn Marino {
7393e4b17023SJohn Marino a_seen = a;
7394e4b17023SJohn Marino m_seen = m;
7395e4b17023SJohn Marino }
7396e4b17023SJohn Marino else if (m_seen == m)
7397e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute duplicated", a);
7398e4b17023SJohn Marino else
7399e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute follows %qE", a, a_seen);
7400e4b17023SJohn Marino }
7401e4b17023SJohn Marino
7402e4b17023SJohn Marino return m_seen;
7403e4b17023SJohn Marino }
7404e4b17023SJohn Marino
7405e4b17023SJohn Marino /* Transform a TM attribute name into a maskable integer and back.
7406e4b17023SJohn Marino Note that NULL (i.e. no attribute) is mapped to UNKNOWN, corresponding
7407e4b17023SJohn Marino to how the lack of an attribute is treated. */
7408e4b17023SJohn Marino
7409e4b17023SJohn Marino int
tm_attr_to_mask(tree attr)7410e4b17023SJohn Marino tm_attr_to_mask (tree attr)
7411e4b17023SJohn Marino {
7412e4b17023SJohn Marino if (attr == NULL)
7413e4b17023SJohn Marino return 0;
7414e4b17023SJohn Marino if (is_attribute_p ("transaction_safe", attr))
7415e4b17023SJohn Marino return TM_ATTR_SAFE;
7416e4b17023SJohn Marino if (is_attribute_p ("transaction_callable", attr))
7417e4b17023SJohn Marino return TM_ATTR_CALLABLE;
7418e4b17023SJohn Marino if (is_attribute_p ("transaction_pure", attr))
7419e4b17023SJohn Marino return TM_ATTR_PURE;
7420e4b17023SJohn Marino if (is_attribute_p ("transaction_unsafe", attr))
7421e4b17023SJohn Marino return TM_ATTR_IRREVOCABLE;
7422e4b17023SJohn Marino if (is_attribute_p ("transaction_may_cancel_outer", attr))
7423e4b17023SJohn Marino return TM_ATTR_MAY_CANCEL_OUTER;
7424e4b17023SJohn Marino return 0;
7425e4b17023SJohn Marino }
7426e4b17023SJohn Marino
7427e4b17023SJohn Marino tree
tm_mask_to_attr(int mask)7428e4b17023SJohn Marino tm_mask_to_attr (int mask)
7429e4b17023SJohn Marino {
7430e4b17023SJohn Marino const char *str;
7431e4b17023SJohn Marino switch (mask)
7432e4b17023SJohn Marino {
7433e4b17023SJohn Marino case TM_ATTR_SAFE:
7434e4b17023SJohn Marino str = "transaction_safe";
7435e4b17023SJohn Marino break;
7436e4b17023SJohn Marino case TM_ATTR_CALLABLE:
7437e4b17023SJohn Marino str = "transaction_callable";
7438e4b17023SJohn Marino break;
7439e4b17023SJohn Marino case TM_ATTR_PURE:
7440e4b17023SJohn Marino str = "transaction_pure";
7441e4b17023SJohn Marino break;
7442e4b17023SJohn Marino case TM_ATTR_IRREVOCABLE:
7443e4b17023SJohn Marino str = "transaction_unsafe";
7444e4b17023SJohn Marino break;
7445e4b17023SJohn Marino case TM_ATTR_MAY_CANCEL_OUTER:
7446e4b17023SJohn Marino str = "transaction_may_cancel_outer";
7447e4b17023SJohn Marino break;
7448e4b17023SJohn Marino default:
7449e4b17023SJohn Marino gcc_unreachable ();
7450e4b17023SJohn Marino }
7451e4b17023SJohn Marino return get_identifier (str);
7452e4b17023SJohn Marino }
7453e4b17023SJohn Marino
7454e4b17023SJohn Marino /* Return the first TM attribute seen in LIST. */
7455e4b17023SJohn Marino
7456e4b17023SJohn Marino tree
find_tm_attribute(tree list)7457e4b17023SJohn Marino find_tm_attribute (tree list)
7458e4b17023SJohn Marino {
7459e4b17023SJohn Marino for (; list ; list = TREE_CHAIN (list))
7460e4b17023SJohn Marino {
7461e4b17023SJohn Marino tree name = TREE_PURPOSE (list);
7462e4b17023SJohn Marino if (tm_attr_to_mask (name) != 0)
7463e4b17023SJohn Marino return name;
7464e4b17023SJohn Marino }
7465e4b17023SJohn Marino return NULL_TREE;
7466e4b17023SJohn Marino }
7467e4b17023SJohn Marino
7468e4b17023SJohn Marino /* Handle the TM attributes; arguments as in struct attribute_spec.handler.
7469e4b17023SJohn Marino Here we accept only function types, and verify that none of the other
7470e4b17023SJohn Marino function TM attributes are also applied. */
7471e4b17023SJohn Marino /* ??? We need to accept class types for C++, but not C. This greatly
7472e4b17023SJohn Marino complicates this function, since we can no longer rely on the extra
7473e4b17023SJohn Marino processing given by function_type_required. */
7474e4b17023SJohn Marino
7475e4b17023SJohn Marino static tree
handle_tm_attribute(tree * node,tree name,tree args,int flags,bool * no_add_attrs)7476e4b17023SJohn Marino handle_tm_attribute (tree *node, tree name, tree args,
7477e4b17023SJohn Marino int flags, bool *no_add_attrs)
7478e4b17023SJohn Marino {
7479e4b17023SJohn Marino /* Only one path adds the attribute; others don't. */
7480e4b17023SJohn Marino *no_add_attrs = true;
7481e4b17023SJohn Marino
7482e4b17023SJohn Marino switch (TREE_CODE (*node))
7483e4b17023SJohn Marino {
7484e4b17023SJohn Marino case RECORD_TYPE:
7485e4b17023SJohn Marino case UNION_TYPE:
7486e4b17023SJohn Marino /* Only tm_callable and tm_safe apply to classes. */
7487e4b17023SJohn Marino if (tm_attr_to_mask (name) & ~(TM_ATTR_SAFE | TM_ATTR_CALLABLE))
7488e4b17023SJohn Marino goto ignored;
7489e4b17023SJohn Marino /* FALLTHRU */
7490e4b17023SJohn Marino
7491e4b17023SJohn Marino case FUNCTION_TYPE:
7492e4b17023SJohn Marino case METHOD_TYPE:
7493e4b17023SJohn Marino {
7494e4b17023SJohn Marino tree old_name = find_tm_attribute (TYPE_ATTRIBUTES (*node));
7495e4b17023SJohn Marino if (old_name == name)
7496e4b17023SJohn Marino ;
7497e4b17023SJohn Marino else if (old_name != NULL_TREE)
7498e4b17023SJohn Marino error ("type was previously declared %qE", old_name);
7499e4b17023SJohn Marino else
7500e4b17023SJohn Marino *no_add_attrs = false;
7501e4b17023SJohn Marino }
7502e4b17023SJohn Marino break;
7503e4b17023SJohn Marino
7504e4b17023SJohn Marino case POINTER_TYPE:
7505e4b17023SJohn Marino {
7506e4b17023SJohn Marino enum tree_code subcode = TREE_CODE (TREE_TYPE (*node));
7507e4b17023SJohn Marino if (subcode == FUNCTION_TYPE || subcode == METHOD_TYPE)
7508e4b17023SJohn Marino {
7509e4b17023SJohn Marino tree fn_tmp = TREE_TYPE (*node);
7510e4b17023SJohn Marino decl_attributes (&fn_tmp, tree_cons (name, args, NULL), 0);
7511e4b17023SJohn Marino *node = build_pointer_type (fn_tmp);
7512e4b17023SJohn Marino break;
7513e4b17023SJohn Marino }
7514e4b17023SJohn Marino }
7515e4b17023SJohn Marino /* FALLTHRU */
7516e4b17023SJohn Marino
7517e4b17023SJohn Marino default:
7518e4b17023SJohn Marino /* If a function is next, pass it on to be tried next. */
7519e4b17023SJohn Marino if (flags & (int) ATTR_FLAG_FUNCTION_NEXT)
7520e4b17023SJohn Marino return tree_cons (name, args, NULL);
7521e4b17023SJohn Marino
7522e4b17023SJohn Marino ignored:
7523e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
7524e4b17023SJohn Marino break;
7525e4b17023SJohn Marino }
7526e4b17023SJohn Marino
7527e4b17023SJohn Marino return NULL_TREE;
7528e4b17023SJohn Marino }
7529e4b17023SJohn Marino
7530e4b17023SJohn Marino /* Handle the TM_WRAP attribute; arguments as in
7531e4b17023SJohn Marino struct attribute_spec.handler. */
7532e4b17023SJohn Marino
7533e4b17023SJohn Marino static tree
handle_tm_wrap_attribute(tree * node,tree name,tree args,int ARG_UNUSED (flags),bool * no_add_attrs)7534e4b17023SJohn Marino handle_tm_wrap_attribute (tree *node, tree name, tree args,
7535e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
7536e4b17023SJohn Marino {
7537e4b17023SJohn Marino tree decl = *node;
7538e4b17023SJohn Marino
7539e4b17023SJohn Marino /* We don't need the attribute even on success, since we
7540e4b17023SJohn Marino record the entry in an external table. */
7541e4b17023SJohn Marino *no_add_attrs = true;
7542e4b17023SJohn Marino
7543e4b17023SJohn Marino if (TREE_CODE (decl) != FUNCTION_DECL)
7544e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
7545e4b17023SJohn Marino else
7546e4b17023SJohn Marino {
7547e4b17023SJohn Marino tree wrap_decl = TREE_VALUE (args);
7548e4b17023SJohn Marino if (TREE_CODE (wrap_decl) != IDENTIFIER_NODE
7549e4b17023SJohn Marino && TREE_CODE (wrap_decl) != VAR_DECL
7550e4b17023SJohn Marino && TREE_CODE (wrap_decl) != FUNCTION_DECL)
7551e4b17023SJohn Marino error ("%qE argument not an identifier", name);
7552e4b17023SJohn Marino else
7553e4b17023SJohn Marino {
7554e4b17023SJohn Marino if (TREE_CODE (wrap_decl) == IDENTIFIER_NODE)
7555e4b17023SJohn Marino wrap_decl = lookup_name (wrap_decl);
7556e4b17023SJohn Marino if (wrap_decl && TREE_CODE (wrap_decl) == FUNCTION_DECL)
7557e4b17023SJohn Marino {
7558e4b17023SJohn Marino if (lang_hooks.types_compatible_p (TREE_TYPE (decl),
7559e4b17023SJohn Marino TREE_TYPE (wrap_decl)))
7560e4b17023SJohn Marino record_tm_replacement (wrap_decl, decl);
7561e4b17023SJohn Marino else
7562e4b17023SJohn Marino error ("%qD is not compatible with %qD", wrap_decl, decl);
7563e4b17023SJohn Marino }
7564e4b17023SJohn Marino else
7565e4b17023SJohn Marino error ("transaction_wrap argument is not a function");
7566e4b17023SJohn Marino }
7567e4b17023SJohn Marino }
7568e4b17023SJohn Marino
7569e4b17023SJohn Marino return NULL_TREE;
7570e4b17023SJohn Marino }
7571e4b17023SJohn Marino
7572e4b17023SJohn Marino /* Ignore the given attribute. Used when this attribute may be usefully
7573e4b17023SJohn Marino overridden by the target, but is not used generically. */
7574e4b17023SJohn Marino
7575e4b17023SJohn Marino static tree
ignore_attribute(tree * ARG_UNUSED (node),tree ARG_UNUSED (name),tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)7576e4b17023SJohn Marino ignore_attribute (tree * ARG_UNUSED (node), tree ARG_UNUSED (name),
7577e4b17023SJohn Marino tree ARG_UNUSED (args), int ARG_UNUSED (flags),
7578e4b17023SJohn Marino bool *no_add_attrs)
7579e4b17023SJohn Marino {
7580e4b17023SJohn Marino *no_add_attrs = true;
7581e4b17023SJohn Marino return NULL_TREE;
7582e4b17023SJohn Marino }
7583e4b17023SJohn Marino
7584e4b17023SJohn Marino /* Handle a "no vops" attribute; arguments as in
7585e4b17023SJohn Marino struct attribute_spec.handler. */
7586e4b17023SJohn Marino
7587e4b17023SJohn Marino static tree
handle_novops_attribute(tree * node,tree ARG_UNUSED (name),tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * ARG_UNUSED (no_add_attrs))7588e4b17023SJohn Marino handle_novops_attribute (tree *node, tree ARG_UNUSED (name),
7589e4b17023SJohn Marino tree ARG_UNUSED (args), int ARG_UNUSED (flags),
7590e4b17023SJohn Marino bool *ARG_UNUSED (no_add_attrs))
7591e4b17023SJohn Marino {
7592e4b17023SJohn Marino gcc_assert (TREE_CODE (*node) == FUNCTION_DECL);
7593e4b17023SJohn Marino DECL_IS_NOVOPS (*node) = 1;
7594e4b17023SJohn Marino return NULL_TREE;
7595e4b17023SJohn Marino }
7596e4b17023SJohn Marino
7597e4b17023SJohn Marino /* Handle a "deprecated" attribute; arguments as in
7598e4b17023SJohn Marino struct attribute_spec.handler. */
7599e4b17023SJohn Marino
7600e4b17023SJohn Marino static tree
handle_deprecated_attribute(tree * node,tree name,tree args,int flags,bool * no_add_attrs)7601e4b17023SJohn Marino handle_deprecated_attribute (tree *node, tree name,
7602e4b17023SJohn Marino tree args, int flags,
7603e4b17023SJohn Marino bool *no_add_attrs)
7604e4b17023SJohn Marino {
7605e4b17023SJohn Marino tree type = NULL_TREE;
7606e4b17023SJohn Marino int warn = 0;
7607e4b17023SJohn Marino tree what = NULL_TREE;
7608e4b17023SJohn Marino
7609e4b17023SJohn Marino if (!args)
7610e4b17023SJohn Marino *no_add_attrs = true;
7611e4b17023SJohn Marino else if (TREE_CODE (TREE_VALUE (args)) != STRING_CST)
7612e4b17023SJohn Marino {
7613e4b17023SJohn Marino error ("deprecated message is not a string");
7614e4b17023SJohn Marino *no_add_attrs = true;
7615e4b17023SJohn Marino }
7616e4b17023SJohn Marino
7617e4b17023SJohn Marino if (DECL_P (*node))
7618e4b17023SJohn Marino {
7619e4b17023SJohn Marino tree decl = *node;
7620e4b17023SJohn Marino type = TREE_TYPE (decl);
7621e4b17023SJohn Marino
7622e4b17023SJohn Marino if (TREE_CODE (decl) == TYPE_DECL
7623e4b17023SJohn Marino || TREE_CODE (decl) == PARM_DECL
7624e4b17023SJohn Marino || TREE_CODE (decl) == VAR_DECL
7625e4b17023SJohn Marino || TREE_CODE (decl) == FUNCTION_DECL
7626e4b17023SJohn Marino || TREE_CODE (decl) == FIELD_DECL
7627e4b17023SJohn Marino || objc_method_decl (TREE_CODE (decl)))
7628e4b17023SJohn Marino TREE_DEPRECATED (decl) = 1;
7629e4b17023SJohn Marino else
7630e4b17023SJohn Marino warn = 1;
7631e4b17023SJohn Marino }
7632e4b17023SJohn Marino else if (TYPE_P (*node))
7633e4b17023SJohn Marino {
7634e4b17023SJohn Marino if (!(flags & (int) ATTR_FLAG_TYPE_IN_PLACE))
7635e4b17023SJohn Marino *node = build_variant_type_copy (*node);
7636e4b17023SJohn Marino TREE_DEPRECATED (*node) = 1;
7637e4b17023SJohn Marino type = *node;
7638e4b17023SJohn Marino }
7639e4b17023SJohn Marino else
7640e4b17023SJohn Marino warn = 1;
7641e4b17023SJohn Marino
7642e4b17023SJohn Marino if (warn)
7643e4b17023SJohn Marino {
7644e4b17023SJohn Marino *no_add_attrs = true;
7645e4b17023SJohn Marino if (type && TYPE_NAME (type))
7646e4b17023SJohn Marino {
7647e4b17023SJohn Marino if (TREE_CODE (TYPE_NAME (type)) == IDENTIFIER_NODE)
7648e4b17023SJohn Marino what = TYPE_NAME (*node);
7649e4b17023SJohn Marino else if (TREE_CODE (TYPE_NAME (type)) == TYPE_DECL
7650e4b17023SJohn Marino && DECL_NAME (TYPE_NAME (type)))
7651e4b17023SJohn Marino what = DECL_NAME (TYPE_NAME (type));
7652e4b17023SJohn Marino }
7653e4b17023SJohn Marino if (what)
7654e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored for %qE", name, what);
7655e4b17023SJohn Marino else
7656e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
7657e4b17023SJohn Marino }
7658e4b17023SJohn Marino
7659e4b17023SJohn Marino return NULL_TREE;
7660e4b17023SJohn Marino }
7661e4b17023SJohn Marino
7662e4b17023SJohn Marino /* Handle a "vector_size" attribute; arguments as in
7663e4b17023SJohn Marino struct attribute_spec.handler. */
7664e4b17023SJohn Marino
7665e4b17023SJohn Marino static tree
handle_vector_size_attribute(tree * node,tree name,tree args,int ARG_UNUSED (flags),bool * no_add_attrs)7666e4b17023SJohn Marino handle_vector_size_attribute (tree *node, tree name, tree args,
7667e4b17023SJohn Marino int ARG_UNUSED (flags),
7668e4b17023SJohn Marino bool *no_add_attrs)
7669e4b17023SJohn Marino {
7670e4b17023SJohn Marino unsigned HOST_WIDE_INT vecsize, nunits;
7671e4b17023SJohn Marino enum machine_mode orig_mode;
7672e4b17023SJohn Marino tree type = *node, new_type, size;
7673e4b17023SJohn Marino
7674e4b17023SJohn Marino *no_add_attrs = true;
7675e4b17023SJohn Marino
7676e4b17023SJohn Marino size = TREE_VALUE (args);
7677e4b17023SJohn Marino
7678e4b17023SJohn Marino if (!host_integerp (size, 1))
7679e4b17023SJohn Marino {
7680e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
7681e4b17023SJohn Marino return NULL_TREE;
7682e4b17023SJohn Marino }
7683e4b17023SJohn Marino
7684e4b17023SJohn Marino /* Get the vector size (in bytes). */
7685e4b17023SJohn Marino vecsize = tree_low_cst (size, 1);
7686e4b17023SJohn Marino
7687e4b17023SJohn Marino /* We need to provide for vector pointers, vector arrays, and
7688e4b17023SJohn Marino functions returning vectors. For example:
7689e4b17023SJohn Marino
7690e4b17023SJohn Marino __attribute__((vector_size(16))) short *foo;
7691e4b17023SJohn Marino
7692e4b17023SJohn Marino In this case, the mode is SI, but the type being modified is
7693e4b17023SJohn Marino HI, so we need to look further. */
7694e4b17023SJohn Marino
7695e4b17023SJohn Marino while (POINTER_TYPE_P (type)
7696e4b17023SJohn Marino || TREE_CODE (type) == FUNCTION_TYPE
7697e4b17023SJohn Marino || TREE_CODE (type) == METHOD_TYPE
7698e4b17023SJohn Marino || TREE_CODE (type) == ARRAY_TYPE
7699e4b17023SJohn Marino || TREE_CODE (type) == OFFSET_TYPE)
7700e4b17023SJohn Marino type = TREE_TYPE (type);
7701e4b17023SJohn Marino
7702e4b17023SJohn Marino /* Get the mode of the type being modified. */
7703e4b17023SJohn Marino orig_mode = TYPE_MODE (type);
7704e4b17023SJohn Marino
7705e4b17023SJohn Marino if ((!INTEGRAL_TYPE_P (type)
7706e4b17023SJohn Marino && !SCALAR_FLOAT_TYPE_P (type)
7707e4b17023SJohn Marino && !FIXED_POINT_TYPE_P (type))
7708e4b17023SJohn Marino || (!SCALAR_FLOAT_MODE_P (orig_mode)
7709e4b17023SJohn Marino && GET_MODE_CLASS (orig_mode) != MODE_INT
7710e4b17023SJohn Marino && !ALL_SCALAR_FIXED_POINT_MODE_P (orig_mode))
7711e4b17023SJohn Marino || !host_integerp (TYPE_SIZE_UNIT (type), 1)
7712e4b17023SJohn Marino || TREE_CODE (type) == BOOLEAN_TYPE)
7713e4b17023SJohn Marino {
7714e4b17023SJohn Marino error ("invalid vector type for attribute %qE", name);
7715e4b17023SJohn Marino return NULL_TREE;
7716e4b17023SJohn Marino }
7717e4b17023SJohn Marino
7718e4b17023SJohn Marino if (vecsize % tree_low_cst (TYPE_SIZE_UNIT (type), 1))
7719e4b17023SJohn Marino {
7720e4b17023SJohn Marino error ("vector size not an integral multiple of component size");
7721e4b17023SJohn Marino return NULL;
7722e4b17023SJohn Marino }
7723e4b17023SJohn Marino
7724e4b17023SJohn Marino if (vecsize == 0)
7725e4b17023SJohn Marino {
7726e4b17023SJohn Marino error ("zero vector size");
7727e4b17023SJohn Marino return NULL;
7728e4b17023SJohn Marino }
7729e4b17023SJohn Marino
7730e4b17023SJohn Marino /* Calculate how many units fit in the vector. */
7731e4b17023SJohn Marino nunits = vecsize / tree_low_cst (TYPE_SIZE_UNIT (type), 1);
7732e4b17023SJohn Marino if (nunits & (nunits - 1))
7733e4b17023SJohn Marino {
7734e4b17023SJohn Marino error ("number of components of the vector not a power of two");
7735e4b17023SJohn Marino return NULL_TREE;
7736e4b17023SJohn Marino }
7737e4b17023SJohn Marino
7738e4b17023SJohn Marino new_type = build_vector_type (type, nunits);
7739e4b17023SJohn Marino
7740e4b17023SJohn Marino /* Build back pointers if needed. */
7741e4b17023SJohn Marino *node = lang_hooks.types.reconstruct_complex_type (*node, new_type);
7742e4b17023SJohn Marino
7743e4b17023SJohn Marino return NULL_TREE;
7744e4b17023SJohn Marino }
7745e4b17023SJohn Marino
7746e4b17023SJohn Marino /* Handle the "nonnull" attribute. */
7747e4b17023SJohn Marino static tree
handle_nonnull_attribute(tree * node,tree ARG_UNUSED (name),tree args,int ARG_UNUSED (flags),bool * no_add_attrs)7748e4b17023SJohn Marino handle_nonnull_attribute (tree *node, tree ARG_UNUSED (name),
7749e4b17023SJohn Marino tree args, int ARG_UNUSED (flags),
7750e4b17023SJohn Marino bool *no_add_attrs)
7751e4b17023SJohn Marino {
7752e4b17023SJohn Marino tree type = *node;
7753e4b17023SJohn Marino unsigned HOST_WIDE_INT attr_arg_num;
7754e4b17023SJohn Marino
7755e4b17023SJohn Marino /* If no arguments are specified, all pointer arguments should be
7756e4b17023SJohn Marino non-null. Verify a full prototype is given so that the arguments
7757e4b17023SJohn Marino will have the correct types when we actually check them later. */
7758e4b17023SJohn Marino if (!args)
7759e4b17023SJohn Marino {
7760e4b17023SJohn Marino if (!prototype_p (type))
7761e4b17023SJohn Marino {
7762e4b17023SJohn Marino error ("nonnull attribute without arguments on a non-prototype");
7763e4b17023SJohn Marino *no_add_attrs = true;
7764e4b17023SJohn Marino }
7765e4b17023SJohn Marino return NULL_TREE;
7766e4b17023SJohn Marino }
7767e4b17023SJohn Marino
7768e4b17023SJohn Marino /* Argument list specified. Verify that each argument number references
7769e4b17023SJohn Marino a pointer argument. */
7770e4b17023SJohn Marino for (attr_arg_num = 1; args; args = TREE_CHAIN (args))
7771e4b17023SJohn Marino {
7772e4b17023SJohn Marino unsigned HOST_WIDE_INT arg_num = 0, ck_num;
7773e4b17023SJohn Marino
7774e4b17023SJohn Marino if (!get_nonnull_operand (TREE_VALUE (args), &arg_num))
7775e4b17023SJohn Marino {
7776e4b17023SJohn Marino error ("nonnull argument has invalid operand number (argument %lu)",
7777e4b17023SJohn Marino (unsigned long) attr_arg_num);
7778e4b17023SJohn Marino *no_add_attrs = true;
7779e4b17023SJohn Marino return NULL_TREE;
7780e4b17023SJohn Marino }
7781e4b17023SJohn Marino
7782e4b17023SJohn Marino if (prototype_p (type))
7783e4b17023SJohn Marino {
7784e4b17023SJohn Marino function_args_iterator iter;
7785e4b17023SJohn Marino tree argument;
7786e4b17023SJohn Marino
7787e4b17023SJohn Marino function_args_iter_init (&iter, type);
7788e4b17023SJohn Marino for (ck_num = 1; ; ck_num++, function_args_iter_next (&iter))
7789e4b17023SJohn Marino {
7790e4b17023SJohn Marino argument = function_args_iter_cond (&iter);
7791e4b17023SJohn Marino if (argument == NULL_TREE || ck_num == arg_num)
7792e4b17023SJohn Marino break;
7793e4b17023SJohn Marino }
7794e4b17023SJohn Marino
7795e4b17023SJohn Marino if (!argument
7796e4b17023SJohn Marino || TREE_CODE (argument) == VOID_TYPE)
7797e4b17023SJohn Marino {
7798e4b17023SJohn Marino error ("nonnull argument with out-of-range operand number (argument %lu, operand %lu)",
7799e4b17023SJohn Marino (unsigned long) attr_arg_num, (unsigned long) arg_num);
7800e4b17023SJohn Marino *no_add_attrs = true;
7801e4b17023SJohn Marino return NULL_TREE;
7802e4b17023SJohn Marino }
7803e4b17023SJohn Marino
7804e4b17023SJohn Marino if (TREE_CODE (argument) != POINTER_TYPE)
7805e4b17023SJohn Marino {
7806e4b17023SJohn Marino error ("nonnull argument references non-pointer operand (argument %lu, operand %lu)",
7807e4b17023SJohn Marino (unsigned long) attr_arg_num, (unsigned long) arg_num);
7808e4b17023SJohn Marino *no_add_attrs = true;
7809e4b17023SJohn Marino return NULL_TREE;
7810e4b17023SJohn Marino }
7811e4b17023SJohn Marino }
7812e4b17023SJohn Marino }
7813e4b17023SJohn Marino
7814e4b17023SJohn Marino return NULL_TREE;
7815e4b17023SJohn Marino }
7816e4b17023SJohn Marino
7817e4b17023SJohn Marino /* Check the argument list of a function call for null in argument slots
7818e4b17023SJohn Marino that are marked as requiring a non-null pointer argument. The NARGS
7819e4b17023SJohn Marino arguments are passed in the array ARGARRAY.
7820e4b17023SJohn Marino */
7821e4b17023SJohn Marino
7822e4b17023SJohn Marino static void
check_function_nonnull(tree attrs,int nargs,tree * argarray)7823e4b17023SJohn Marino check_function_nonnull (tree attrs, int nargs, tree *argarray)
7824e4b17023SJohn Marino {
7825e4b17023SJohn Marino tree a, args;
7826e4b17023SJohn Marino int i;
7827e4b17023SJohn Marino
7828e4b17023SJohn Marino for (a = attrs; a; a = TREE_CHAIN (a))
7829e4b17023SJohn Marino {
7830e4b17023SJohn Marino if (is_attribute_p ("nonnull", TREE_PURPOSE (a)))
7831e4b17023SJohn Marino {
7832e4b17023SJohn Marino args = TREE_VALUE (a);
7833e4b17023SJohn Marino
7834e4b17023SJohn Marino /* Walk the argument list. If we encounter an argument number we
7835e4b17023SJohn Marino should check for non-null, do it. If the attribute has no args,
7836e4b17023SJohn Marino then every pointer argument is checked (in which case the check
7837e4b17023SJohn Marino for pointer type is done in check_nonnull_arg). */
7838e4b17023SJohn Marino for (i = 0; i < nargs; i++)
7839e4b17023SJohn Marino {
7840e4b17023SJohn Marino if (!args || nonnull_check_p (args, i + 1))
7841e4b17023SJohn Marino check_function_arguments_recurse (check_nonnull_arg, NULL,
7842e4b17023SJohn Marino argarray[i],
7843e4b17023SJohn Marino i + 1);
7844e4b17023SJohn Marino }
7845e4b17023SJohn Marino }
7846e4b17023SJohn Marino }
7847e4b17023SJohn Marino }
7848e4b17023SJohn Marino
7849e4b17023SJohn Marino /* Check that the Nth argument of a function call (counting backwards
7850e4b17023SJohn Marino from the end) is a (pointer)0. The NARGS arguments are passed in the
7851e4b17023SJohn Marino array ARGARRAY. */
7852e4b17023SJohn Marino
7853e4b17023SJohn Marino static void
check_function_sentinel(const_tree fntype,int nargs,tree * argarray)7854e4b17023SJohn Marino check_function_sentinel (const_tree fntype, int nargs, tree *argarray)
7855e4b17023SJohn Marino {
7856e4b17023SJohn Marino tree attr = lookup_attribute ("sentinel", TYPE_ATTRIBUTES (fntype));
7857e4b17023SJohn Marino
7858e4b17023SJohn Marino if (attr)
7859e4b17023SJohn Marino {
7860e4b17023SJohn Marino int len = 0;
7861e4b17023SJohn Marino int pos = 0;
7862e4b17023SJohn Marino tree sentinel;
7863e4b17023SJohn Marino function_args_iterator iter;
7864e4b17023SJohn Marino tree t;
7865e4b17023SJohn Marino
7866e4b17023SJohn Marino /* Skip over the named arguments. */
7867e4b17023SJohn Marino FOREACH_FUNCTION_ARGS (fntype, t, iter)
7868e4b17023SJohn Marino {
7869e4b17023SJohn Marino if (len == nargs)
7870e4b17023SJohn Marino break;
7871e4b17023SJohn Marino len++;
7872e4b17023SJohn Marino }
7873e4b17023SJohn Marino
7874e4b17023SJohn Marino if (TREE_VALUE (attr))
7875e4b17023SJohn Marino {
7876e4b17023SJohn Marino tree p = TREE_VALUE (TREE_VALUE (attr));
7877e4b17023SJohn Marino pos = TREE_INT_CST_LOW (p);
7878e4b17023SJohn Marino }
7879e4b17023SJohn Marino
7880e4b17023SJohn Marino /* The sentinel must be one of the varargs, i.e.
7881e4b17023SJohn Marino in position >= the number of fixed arguments. */
7882e4b17023SJohn Marino if ((nargs - 1 - pos) < len)
7883e4b17023SJohn Marino {
7884e4b17023SJohn Marino warning (OPT_Wformat,
7885e4b17023SJohn Marino "not enough variable arguments to fit a sentinel");
7886e4b17023SJohn Marino return;
7887e4b17023SJohn Marino }
7888e4b17023SJohn Marino
7889e4b17023SJohn Marino /* Validate the sentinel. */
7890e4b17023SJohn Marino sentinel = argarray[nargs - 1 - pos];
7891e4b17023SJohn Marino if ((!POINTER_TYPE_P (TREE_TYPE (sentinel))
7892e4b17023SJohn Marino || !integer_zerop (sentinel))
7893e4b17023SJohn Marino /* Although __null (in C++) is only an integer we allow it
7894e4b17023SJohn Marino nevertheless, as we are guaranteed that it's exactly
7895e4b17023SJohn Marino as wide as a pointer, and we don't want to force
7896e4b17023SJohn Marino users to cast the NULL they have written there.
7897e4b17023SJohn Marino We warn with -Wstrict-null-sentinel, though. */
7898e4b17023SJohn Marino && (warn_strict_null_sentinel || null_node != sentinel))
7899e4b17023SJohn Marino warning (OPT_Wformat, "missing sentinel in function call");
7900e4b17023SJohn Marino }
7901e4b17023SJohn Marino }
7902e4b17023SJohn Marino
7903e4b17023SJohn Marino /* Helper for check_function_nonnull; given a list of operands which
7904e4b17023SJohn Marino must be non-null in ARGS, determine if operand PARAM_NUM should be
7905e4b17023SJohn Marino checked. */
7906e4b17023SJohn Marino
7907e4b17023SJohn Marino static bool
nonnull_check_p(tree args,unsigned HOST_WIDE_INT param_num)7908e4b17023SJohn Marino nonnull_check_p (tree args, unsigned HOST_WIDE_INT param_num)
7909e4b17023SJohn Marino {
7910e4b17023SJohn Marino unsigned HOST_WIDE_INT arg_num = 0;
7911e4b17023SJohn Marino
7912e4b17023SJohn Marino for (; args; args = TREE_CHAIN (args))
7913e4b17023SJohn Marino {
7914e4b17023SJohn Marino bool found = get_nonnull_operand (TREE_VALUE (args), &arg_num);
7915e4b17023SJohn Marino
7916e4b17023SJohn Marino gcc_assert (found);
7917e4b17023SJohn Marino
7918e4b17023SJohn Marino if (arg_num == param_num)
7919e4b17023SJohn Marino return true;
7920e4b17023SJohn Marino }
7921e4b17023SJohn Marino return false;
7922e4b17023SJohn Marino }
7923e4b17023SJohn Marino
7924e4b17023SJohn Marino /* Check that the function argument PARAM (which is operand number
7925e4b17023SJohn Marino PARAM_NUM) is non-null. This is called by check_function_nonnull
7926e4b17023SJohn Marino via check_function_arguments_recurse. */
7927e4b17023SJohn Marino
7928e4b17023SJohn Marino static void
check_nonnull_arg(void * ARG_UNUSED (ctx),tree param,unsigned HOST_WIDE_INT param_num)7929e4b17023SJohn Marino check_nonnull_arg (void * ARG_UNUSED (ctx), tree param,
7930e4b17023SJohn Marino unsigned HOST_WIDE_INT param_num)
7931e4b17023SJohn Marino {
7932e4b17023SJohn Marino /* Just skip checking the argument if it's not a pointer. This can
7933e4b17023SJohn Marino happen if the "nonnull" attribute was given without an operand
7934e4b17023SJohn Marino list (which means to check every pointer argument). */
7935e4b17023SJohn Marino
7936e4b17023SJohn Marino if (TREE_CODE (TREE_TYPE (param)) != POINTER_TYPE)
7937e4b17023SJohn Marino return;
7938e4b17023SJohn Marino
7939e4b17023SJohn Marino if (integer_zerop (param))
7940e4b17023SJohn Marino warning (OPT_Wnonnull, "null argument where non-null required "
7941e4b17023SJohn Marino "(argument %lu)", (unsigned long) param_num);
7942e4b17023SJohn Marino }
7943e4b17023SJohn Marino
7944e4b17023SJohn Marino /* Helper for nonnull attribute handling; fetch the operand number
7945e4b17023SJohn Marino from the attribute argument list. */
7946e4b17023SJohn Marino
7947e4b17023SJohn Marino static bool
get_nonnull_operand(tree arg_num_expr,unsigned HOST_WIDE_INT * valp)7948e4b17023SJohn Marino get_nonnull_operand (tree arg_num_expr, unsigned HOST_WIDE_INT *valp)
7949e4b17023SJohn Marino {
7950e4b17023SJohn Marino /* Verify the arg number is a constant. */
7951e4b17023SJohn Marino if (TREE_CODE (arg_num_expr) != INTEGER_CST
7952e4b17023SJohn Marino || TREE_INT_CST_HIGH (arg_num_expr) != 0)
7953e4b17023SJohn Marino return false;
7954e4b17023SJohn Marino
7955e4b17023SJohn Marino *valp = TREE_INT_CST_LOW (arg_num_expr);
7956e4b17023SJohn Marino return true;
7957e4b17023SJohn Marino }
7958e4b17023SJohn Marino
7959e4b17023SJohn Marino /* Handle a "nothrow" attribute; arguments as in
7960e4b17023SJohn Marino struct attribute_spec.handler. */
7961e4b17023SJohn Marino
7962e4b17023SJohn Marino static tree
handle_nothrow_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)7963e4b17023SJohn Marino handle_nothrow_attribute (tree *node, tree name, tree ARG_UNUSED (args),
7964e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
7965e4b17023SJohn Marino {
7966e4b17023SJohn Marino if (TREE_CODE (*node) == FUNCTION_DECL)
7967e4b17023SJohn Marino TREE_NOTHROW (*node) = 1;
7968e4b17023SJohn Marino /* ??? TODO: Support types. */
7969e4b17023SJohn Marino else
7970e4b17023SJohn Marino {
7971e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
7972e4b17023SJohn Marino *no_add_attrs = true;
7973e4b17023SJohn Marino }
7974e4b17023SJohn Marino
7975e4b17023SJohn Marino return NULL_TREE;
7976e4b17023SJohn Marino }
7977e4b17023SJohn Marino
7978e4b17023SJohn Marino /* Handle a "cleanup" attribute; arguments as in
7979e4b17023SJohn Marino struct attribute_spec.handler. */
7980e4b17023SJohn Marino
7981e4b17023SJohn Marino static tree
handle_cleanup_attribute(tree * node,tree name,tree args,int ARG_UNUSED (flags),bool * no_add_attrs)7982e4b17023SJohn Marino handle_cleanup_attribute (tree *node, tree name, tree args,
7983e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
7984e4b17023SJohn Marino {
7985e4b17023SJohn Marino tree decl = *node;
7986e4b17023SJohn Marino tree cleanup_id, cleanup_decl;
7987e4b17023SJohn Marino
7988e4b17023SJohn Marino /* ??? Could perhaps support cleanups on TREE_STATIC, much like we do
7989e4b17023SJohn Marino for global destructors in C++. This requires infrastructure that
7990e4b17023SJohn Marino we don't have generically at the moment. It's also not a feature
7991e4b17023SJohn Marino we'd be missing too much, since we do have attribute constructor. */
7992e4b17023SJohn Marino if (TREE_CODE (decl) != VAR_DECL || TREE_STATIC (decl))
7993e4b17023SJohn Marino {
7994e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
7995e4b17023SJohn Marino *no_add_attrs = true;
7996e4b17023SJohn Marino return NULL_TREE;
7997e4b17023SJohn Marino }
7998e4b17023SJohn Marino
7999e4b17023SJohn Marino /* Verify that the argument is a function in scope. */
8000e4b17023SJohn Marino /* ??? We could support pointers to functions here as well, if
8001e4b17023SJohn Marino that was considered desirable. */
8002e4b17023SJohn Marino cleanup_id = TREE_VALUE (args);
8003e4b17023SJohn Marino if (TREE_CODE (cleanup_id) != IDENTIFIER_NODE)
8004e4b17023SJohn Marino {
8005e4b17023SJohn Marino error ("cleanup argument not an identifier");
8006e4b17023SJohn Marino *no_add_attrs = true;
8007e4b17023SJohn Marino return NULL_TREE;
8008e4b17023SJohn Marino }
8009e4b17023SJohn Marino cleanup_decl = lookup_name (cleanup_id);
8010e4b17023SJohn Marino if (!cleanup_decl || TREE_CODE (cleanup_decl) != FUNCTION_DECL)
8011e4b17023SJohn Marino {
8012e4b17023SJohn Marino error ("cleanup argument not a function");
8013e4b17023SJohn Marino *no_add_attrs = true;
8014e4b17023SJohn Marino return NULL_TREE;
8015e4b17023SJohn Marino }
8016e4b17023SJohn Marino
8017e4b17023SJohn Marino /* That the function has proper type is checked with the
8018e4b17023SJohn Marino eventual call to build_function_call. */
8019e4b17023SJohn Marino
8020e4b17023SJohn Marino return NULL_TREE;
8021e4b17023SJohn Marino }
8022e4b17023SJohn Marino
8023e4b17023SJohn Marino /* Handle a "warn_unused_result" attribute. No special handling. */
8024e4b17023SJohn Marino
8025e4b17023SJohn Marino static tree
handle_warn_unused_result_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)8026e4b17023SJohn Marino handle_warn_unused_result_attribute (tree *node, tree name,
8027e4b17023SJohn Marino tree ARG_UNUSED (args),
8028e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
8029e4b17023SJohn Marino {
8030e4b17023SJohn Marino /* Ignore the attribute for functions not returning any value. */
8031e4b17023SJohn Marino if (VOID_TYPE_P (TREE_TYPE (*node)))
8032e4b17023SJohn Marino {
8033e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
8034e4b17023SJohn Marino *no_add_attrs = true;
8035e4b17023SJohn Marino }
8036e4b17023SJohn Marino
8037e4b17023SJohn Marino return NULL_TREE;
8038e4b17023SJohn Marino }
8039e4b17023SJohn Marino
8040e4b17023SJohn Marino /* Handle a "sentinel" attribute. */
8041e4b17023SJohn Marino
8042e4b17023SJohn Marino static tree
handle_sentinel_attribute(tree * node,tree name,tree args,int ARG_UNUSED (flags),bool * no_add_attrs)8043e4b17023SJohn Marino handle_sentinel_attribute (tree *node, tree name, tree args,
8044e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
8045e4b17023SJohn Marino {
8046e4b17023SJohn Marino if (!prototype_p (*node))
8047e4b17023SJohn Marino {
8048e4b17023SJohn Marino warning (OPT_Wattributes,
8049e4b17023SJohn Marino "%qE attribute requires prototypes with named arguments", name);
8050e4b17023SJohn Marino *no_add_attrs = true;
8051e4b17023SJohn Marino }
8052e4b17023SJohn Marino else
8053e4b17023SJohn Marino {
8054e4b17023SJohn Marino if (!stdarg_p (*node))
8055e4b17023SJohn Marino {
8056e4b17023SJohn Marino warning (OPT_Wattributes,
8057e4b17023SJohn Marino "%qE attribute only applies to variadic functions", name);
8058e4b17023SJohn Marino *no_add_attrs = true;
8059e4b17023SJohn Marino }
8060e4b17023SJohn Marino }
8061e4b17023SJohn Marino
8062e4b17023SJohn Marino if (args)
8063e4b17023SJohn Marino {
8064e4b17023SJohn Marino tree position = TREE_VALUE (args);
8065e4b17023SJohn Marino
8066e4b17023SJohn Marino if (TREE_CODE (position) != INTEGER_CST)
8067e4b17023SJohn Marino {
8068e4b17023SJohn Marino warning (OPT_Wattributes,
8069e4b17023SJohn Marino "requested position is not an integer constant");
8070e4b17023SJohn Marino *no_add_attrs = true;
8071e4b17023SJohn Marino }
8072e4b17023SJohn Marino else
8073e4b17023SJohn Marino {
8074e4b17023SJohn Marino if (tree_int_cst_lt (position, integer_zero_node))
8075e4b17023SJohn Marino {
8076e4b17023SJohn Marino warning (OPT_Wattributes,
8077e4b17023SJohn Marino "requested position is less than zero");
8078e4b17023SJohn Marino *no_add_attrs = true;
8079e4b17023SJohn Marino }
8080e4b17023SJohn Marino }
8081e4b17023SJohn Marino }
8082e4b17023SJohn Marino
8083e4b17023SJohn Marino return NULL_TREE;
8084e4b17023SJohn Marino }
8085e4b17023SJohn Marino
8086e4b17023SJohn Marino /* Handle a "type_generic" attribute. */
8087e4b17023SJohn Marino
8088e4b17023SJohn Marino static tree
handle_type_generic_attribute(tree * node,tree ARG_UNUSED (name),tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * ARG_UNUSED (no_add_attrs))8089e4b17023SJohn Marino handle_type_generic_attribute (tree *node, tree ARG_UNUSED (name),
8090e4b17023SJohn Marino tree ARG_UNUSED (args), int ARG_UNUSED (flags),
8091e4b17023SJohn Marino bool * ARG_UNUSED (no_add_attrs))
8092e4b17023SJohn Marino {
8093e4b17023SJohn Marino /* Ensure we have a function type. */
8094e4b17023SJohn Marino gcc_assert (TREE_CODE (*node) == FUNCTION_TYPE);
8095e4b17023SJohn Marino
8096e4b17023SJohn Marino /* Ensure we have a variadic function. */
8097e4b17023SJohn Marino gcc_assert (!prototype_p (*node) || stdarg_p (*node));
8098e4b17023SJohn Marino
8099e4b17023SJohn Marino return NULL_TREE;
8100e4b17023SJohn Marino }
8101e4b17023SJohn Marino
8102e4b17023SJohn Marino /* Handle a "target" attribute. */
8103e4b17023SJohn Marino
8104e4b17023SJohn Marino static tree
handle_target_attribute(tree * node,tree name,tree args,int flags,bool * no_add_attrs)8105e4b17023SJohn Marino handle_target_attribute (tree *node, tree name, tree args, int flags,
8106e4b17023SJohn Marino bool *no_add_attrs)
8107e4b17023SJohn Marino {
8108e4b17023SJohn Marino /* Ensure we have a function type. */
8109e4b17023SJohn Marino if (TREE_CODE (*node) != FUNCTION_DECL)
8110e4b17023SJohn Marino {
8111e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
8112e4b17023SJohn Marino *no_add_attrs = true;
8113e4b17023SJohn Marino }
8114e4b17023SJohn Marino else if (! targetm.target_option.valid_attribute_p (*node, name, args,
8115e4b17023SJohn Marino flags))
8116e4b17023SJohn Marino *no_add_attrs = true;
8117e4b17023SJohn Marino
8118e4b17023SJohn Marino return NULL_TREE;
8119e4b17023SJohn Marino }
8120e4b17023SJohn Marino
8121e4b17023SJohn Marino /* Arguments being collected for optimization. */
8122e4b17023SJohn Marino typedef const char *const_char_p; /* For DEF_VEC_P. */
8123e4b17023SJohn Marino DEF_VEC_P(const_char_p);
8124e4b17023SJohn Marino DEF_VEC_ALLOC_P(const_char_p, gc);
8125e4b17023SJohn Marino static GTY(()) VEC(const_char_p, gc) *optimize_args;
8126e4b17023SJohn Marino
8127e4b17023SJohn Marino
8128e4b17023SJohn Marino /* Inner function to convert a TREE_LIST to argv string to parse the optimize
8129e4b17023SJohn Marino options in ARGS. ATTR_P is true if this is for attribute(optimize), and
8130e4b17023SJohn Marino false for #pragma GCC optimize. */
8131e4b17023SJohn Marino
8132e4b17023SJohn Marino bool
parse_optimize_options(tree args,bool attr_p)8133e4b17023SJohn Marino parse_optimize_options (tree args, bool attr_p)
8134e4b17023SJohn Marino {
8135e4b17023SJohn Marino bool ret = true;
8136e4b17023SJohn Marino unsigned opt_argc;
8137e4b17023SJohn Marino unsigned i;
8138e4b17023SJohn Marino int saved_flag_strict_aliasing;
8139e4b17023SJohn Marino const char **opt_argv;
8140e4b17023SJohn Marino struct cl_decoded_option *decoded_options;
8141e4b17023SJohn Marino unsigned int decoded_options_count;
8142e4b17023SJohn Marino tree ap;
8143e4b17023SJohn Marino
8144e4b17023SJohn Marino /* Build up argv vector. Just in case the string is stored away, use garbage
8145e4b17023SJohn Marino collected strings. */
8146e4b17023SJohn Marino VEC_truncate (const_char_p, optimize_args, 0);
8147e4b17023SJohn Marino VEC_safe_push (const_char_p, gc, optimize_args, NULL);
8148e4b17023SJohn Marino
8149e4b17023SJohn Marino for (ap = args; ap != NULL_TREE; ap = TREE_CHAIN (ap))
8150e4b17023SJohn Marino {
8151e4b17023SJohn Marino tree value = TREE_VALUE (ap);
8152e4b17023SJohn Marino
8153e4b17023SJohn Marino if (TREE_CODE (value) == INTEGER_CST)
8154e4b17023SJohn Marino {
8155e4b17023SJohn Marino char buffer[20];
8156e4b17023SJohn Marino sprintf (buffer, "-O%ld", (long) TREE_INT_CST_LOW (value));
8157e4b17023SJohn Marino VEC_safe_push (const_char_p, gc, optimize_args, ggc_strdup (buffer));
8158e4b17023SJohn Marino }
8159e4b17023SJohn Marino
8160e4b17023SJohn Marino else if (TREE_CODE (value) == STRING_CST)
8161e4b17023SJohn Marino {
8162e4b17023SJohn Marino /* Split string into multiple substrings. */
8163e4b17023SJohn Marino size_t len = TREE_STRING_LENGTH (value);
8164e4b17023SJohn Marino char *p = ASTRDUP (TREE_STRING_POINTER (value));
8165e4b17023SJohn Marino char *end = p + len;
8166e4b17023SJohn Marino char *comma;
8167e4b17023SJohn Marino char *next_p = p;
8168e4b17023SJohn Marino
8169e4b17023SJohn Marino while (next_p != NULL)
8170e4b17023SJohn Marino {
8171e4b17023SJohn Marino size_t len2;
8172e4b17023SJohn Marino char *q, *r;
8173e4b17023SJohn Marino
8174e4b17023SJohn Marino p = next_p;
8175e4b17023SJohn Marino comma = strchr (p, ',');
8176e4b17023SJohn Marino if (comma)
8177e4b17023SJohn Marino {
8178e4b17023SJohn Marino len2 = comma - p;
8179e4b17023SJohn Marino *comma = '\0';
8180e4b17023SJohn Marino next_p = comma+1;
8181e4b17023SJohn Marino }
8182e4b17023SJohn Marino else
8183e4b17023SJohn Marino {
8184e4b17023SJohn Marino len2 = end - p;
8185e4b17023SJohn Marino next_p = NULL;
8186e4b17023SJohn Marino }
8187e4b17023SJohn Marino
8188e4b17023SJohn Marino r = q = (char *) ggc_alloc_atomic (len2 + 3);
8189e4b17023SJohn Marino
8190e4b17023SJohn Marino /* If the user supplied -Oxxx or -fxxx, only allow -Oxxx or -fxxx
8191e4b17023SJohn Marino options. */
8192e4b17023SJohn Marino if (*p == '-' && p[1] != 'O' && p[1] != 'f')
8193e4b17023SJohn Marino {
8194e4b17023SJohn Marino ret = false;
8195e4b17023SJohn Marino if (attr_p)
8196e4b17023SJohn Marino warning (OPT_Wattributes,
8197e4b17023SJohn Marino "bad option %s to optimize attribute", p);
8198e4b17023SJohn Marino else
8199e4b17023SJohn Marino warning (OPT_Wpragmas,
8200e4b17023SJohn Marino "bad option %s to pragma attribute", p);
8201e4b17023SJohn Marino continue;
8202e4b17023SJohn Marino }
8203e4b17023SJohn Marino
8204e4b17023SJohn Marino if (*p != '-')
8205e4b17023SJohn Marino {
8206e4b17023SJohn Marino *r++ = '-';
8207e4b17023SJohn Marino
8208e4b17023SJohn Marino /* Assume that Ox is -Ox, a numeric value is -Ox, a s by
8209e4b17023SJohn Marino itself is -Os, and any other switch begins with a -f. */
8210e4b17023SJohn Marino if ((*p >= '0' && *p <= '9')
8211e4b17023SJohn Marino || (p[0] == 's' && p[1] == '\0'))
8212e4b17023SJohn Marino *r++ = 'O';
8213e4b17023SJohn Marino else if (*p != 'O')
8214e4b17023SJohn Marino *r++ = 'f';
8215e4b17023SJohn Marino }
8216e4b17023SJohn Marino
8217e4b17023SJohn Marino memcpy (r, p, len2);
8218e4b17023SJohn Marino r[len2] = '\0';
8219e4b17023SJohn Marino VEC_safe_push (const_char_p, gc, optimize_args, q);
8220e4b17023SJohn Marino }
8221e4b17023SJohn Marino
8222e4b17023SJohn Marino }
8223e4b17023SJohn Marino }
8224e4b17023SJohn Marino
8225e4b17023SJohn Marino opt_argc = VEC_length (const_char_p, optimize_args);
8226e4b17023SJohn Marino opt_argv = (const char **) alloca (sizeof (char *) * (opt_argc + 1));
8227e4b17023SJohn Marino
8228e4b17023SJohn Marino for (i = 1; i < opt_argc; i++)
8229e4b17023SJohn Marino opt_argv[i] = VEC_index (const_char_p, optimize_args, i);
8230e4b17023SJohn Marino
8231e4b17023SJohn Marino saved_flag_strict_aliasing = flag_strict_aliasing;
8232e4b17023SJohn Marino
8233e4b17023SJohn Marino /* Now parse the options. */
8234e4b17023SJohn Marino decode_cmdline_options_to_array_default_mask (opt_argc, opt_argv,
8235e4b17023SJohn Marino &decoded_options,
8236e4b17023SJohn Marino &decoded_options_count);
8237e4b17023SJohn Marino decode_options (&global_options, &global_options_set,
8238e4b17023SJohn Marino decoded_options, decoded_options_count,
8239e4b17023SJohn Marino input_location, global_dc);
8240e4b17023SJohn Marino
8241e4b17023SJohn Marino targetm.override_options_after_change();
8242e4b17023SJohn Marino
8243e4b17023SJohn Marino /* Don't allow changing -fstrict-aliasing. */
8244e4b17023SJohn Marino flag_strict_aliasing = saved_flag_strict_aliasing;
8245e4b17023SJohn Marino
8246e4b17023SJohn Marino VEC_truncate (const_char_p, optimize_args, 0);
8247e4b17023SJohn Marino return ret;
8248e4b17023SJohn Marino }
8249e4b17023SJohn Marino
8250e4b17023SJohn Marino /* For handling "optimize" attribute. arguments as in
8251e4b17023SJohn Marino struct attribute_spec.handler. */
8252e4b17023SJohn Marino
8253e4b17023SJohn Marino static tree
handle_optimize_attribute(tree * node,tree name,tree args,int ARG_UNUSED (flags),bool * no_add_attrs)8254e4b17023SJohn Marino handle_optimize_attribute (tree *node, tree name, tree args,
8255e4b17023SJohn Marino int ARG_UNUSED (flags), bool *no_add_attrs)
8256e4b17023SJohn Marino {
8257e4b17023SJohn Marino /* Ensure we have a function type. */
8258e4b17023SJohn Marino if (TREE_CODE (*node) != FUNCTION_DECL)
8259e4b17023SJohn Marino {
8260e4b17023SJohn Marino warning (OPT_Wattributes, "%qE attribute ignored", name);
8261e4b17023SJohn Marino *no_add_attrs = true;
8262e4b17023SJohn Marino }
8263e4b17023SJohn Marino else
8264e4b17023SJohn Marino {
8265e4b17023SJohn Marino struct cl_optimization cur_opts;
8266e4b17023SJohn Marino tree old_opts = DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node);
8267e4b17023SJohn Marino
8268e4b17023SJohn Marino /* Save current options. */
8269e4b17023SJohn Marino cl_optimization_save (&cur_opts, &global_options);
8270e4b17023SJohn Marino
8271e4b17023SJohn Marino /* If we previously had some optimization options, use them as the
8272e4b17023SJohn Marino default. */
8273e4b17023SJohn Marino if (old_opts)
8274e4b17023SJohn Marino cl_optimization_restore (&global_options,
8275e4b17023SJohn Marino TREE_OPTIMIZATION (old_opts));
8276e4b17023SJohn Marino
8277e4b17023SJohn Marino /* Parse options, and update the vector. */
8278e4b17023SJohn Marino parse_optimize_options (args, true);
8279e4b17023SJohn Marino DECL_FUNCTION_SPECIFIC_OPTIMIZATION (*node)
8280e4b17023SJohn Marino = build_optimization_node ();
8281e4b17023SJohn Marino
8282e4b17023SJohn Marino /* Restore current options. */
8283e4b17023SJohn Marino cl_optimization_restore (&global_options, &cur_opts);
8284e4b17023SJohn Marino }
8285e4b17023SJohn Marino
8286e4b17023SJohn Marino return NULL_TREE;
8287e4b17023SJohn Marino }
8288e4b17023SJohn Marino
8289e4b17023SJohn Marino /* Handle a "no_split_stack" attribute. */
8290e4b17023SJohn Marino
8291e4b17023SJohn Marino static tree
handle_no_split_stack_attribute(tree * node,tree name,tree ARG_UNUSED (args),int ARG_UNUSED (flags),bool * no_add_attrs)8292e4b17023SJohn Marino handle_no_split_stack_attribute (tree *node, tree name,
8293e4b17023SJohn Marino tree ARG_UNUSED (args),
8294e4b17023SJohn Marino int ARG_UNUSED (flags),
8295e4b17023SJohn Marino bool *no_add_attrs)
8296e4b17023SJohn Marino {
8297e4b17023SJohn Marino tree decl = *node;
8298e4b17023SJohn Marino
8299e4b17023SJohn Marino if (TREE_CODE (decl) != FUNCTION_DECL)
8300e4b17023SJohn Marino {
8301e4b17023SJohn Marino error_at (DECL_SOURCE_LOCATION (decl),
8302e4b17023SJohn Marino "%qE attribute applies only to functions", name);
8303e4b17023SJohn Marino *no_add_attrs = true;
8304e4b17023SJohn Marino }
8305e4b17023SJohn Marino else if (DECL_INITIAL (decl))
8306e4b17023SJohn Marino {
8307e4b17023SJohn Marino error_at (DECL_SOURCE_LOCATION (decl),
8308e4b17023SJohn Marino "can%'t set %qE attribute after definition", name);
8309e4b17023SJohn Marino *no_add_attrs = true;
8310e4b17023SJohn Marino }
8311e4b17023SJohn Marino
8312e4b17023SJohn Marino return NULL_TREE;
8313e4b17023SJohn Marino }
8314e4b17023SJohn Marino
8315e4b17023SJohn Marino /* Check for valid arguments being passed to a function with FNTYPE.
8316e4b17023SJohn Marino There are NARGS arguments in the array ARGARRAY. */
8317e4b17023SJohn Marino void
check_function_arguments(const_tree fntype,int nargs,tree * argarray)8318e4b17023SJohn Marino check_function_arguments (const_tree fntype, int nargs, tree *argarray)
8319e4b17023SJohn Marino {
8320e4b17023SJohn Marino /* Check for null being passed in a pointer argument that must be
8321e4b17023SJohn Marino non-null. We also need to do this if format checking is enabled. */
8322e4b17023SJohn Marino
8323e4b17023SJohn Marino if (warn_nonnull)
8324e4b17023SJohn Marino check_function_nonnull (TYPE_ATTRIBUTES (fntype), nargs, argarray);
8325e4b17023SJohn Marino
8326e4b17023SJohn Marino /* Check for errors in format strings. */
8327e4b17023SJohn Marino
8328e4b17023SJohn Marino if (warn_format || warn_missing_format_attribute)
8329e4b17023SJohn Marino check_function_format (TYPE_ATTRIBUTES (fntype), nargs, argarray);
8330e4b17023SJohn Marino
8331e4b17023SJohn Marino if (warn_format)
8332e4b17023SJohn Marino check_function_sentinel (fntype, nargs, argarray);
8333e4b17023SJohn Marino }
8334e4b17023SJohn Marino
8335e4b17023SJohn Marino /* Generic argument checking recursion routine. PARAM is the argument to
8336e4b17023SJohn Marino be checked. PARAM_NUM is the number of the argument. CALLBACK is invoked
8337e4b17023SJohn Marino once the argument is resolved. CTX is context for the callback. */
8338e4b17023SJohn Marino void
check_function_arguments_recurse(void (* callback)(void *,tree,unsigned HOST_WIDE_INT),void * ctx,tree param,unsigned HOST_WIDE_INT param_num)8339e4b17023SJohn Marino check_function_arguments_recurse (void (*callback)
8340e4b17023SJohn Marino (void *, tree, unsigned HOST_WIDE_INT),
8341e4b17023SJohn Marino void *ctx, tree param,
8342e4b17023SJohn Marino unsigned HOST_WIDE_INT param_num)
8343e4b17023SJohn Marino {
8344e4b17023SJohn Marino if (CONVERT_EXPR_P (param)
8345e4b17023SJohn Marino && (TYPE_PRECISION (TREE_TYPE (param))
8346e4b17023SJohn Marino == TYPE_PRECISION (TREE_TYPE (TREE_OPERAND (param, 0)))))
8347e4b17023SJohn Marino {
8348e4b17023SJohn Marino /* Strip coercion. */
8349e4b17023SJohn Marino check_function_arguments_recurse (callback, ctx,
8350e4b17023SJohn Marino TREE_OPERAND (param, 0), param_num);
8351e4b17023SJohn Marino return;
8352e4b17023SJohn Marino }
8353e4b17023SJohn Marino
8354e4b17023SJohn Marino if (TREE_CODE (param) == CALL_EXPR)
8355e4b17023SJohn Marino {
8356e4b17023SJohn Marino tree type = TREE_TYPE (TREE_TYPE (CALL_EXPR_FN (param)));
8357e4b17023SJohn Marino tree attrs;
8358e4b17023SJohn Marino bool found_format_arg = false;
8359e4b17023SJohn Marino
8360e4b17023SJohn Marino /* See if this is a call to a known internationalization function
8361e4b17023SJohn Marino that modifies a format arg. Such a function may have multiple
8362e4b17023SJohn Marino format_arg attributes (for example, ngettext). */
8363e4b17023SJohn Marino
8364e4b17023SJohn Marino for (attrs = TYPE_ATTRIBUTES (type);
8365e4b17023SJohn Marino attrs;
8366e4b17023SJohn Marino attrs = TREE_CHAIN (attrs))
8367e4b17023SJohn Marino if (is_attribute_p ("format_arg", TREE_PURPOSE (attrs)))
8368e4b17023SJohn Marino {
8369e4b17023SJohn Marino tree inner_arg;
8370e4b17023SJohn Marino tree format_num_expr;
8371e4b17023SJohn Marino int format_num;
8372e4b17023SJohn Marino int i;
8373e4b17023SJohn Marino call_expr_arg_iterator iter;
8374e4b17023SJohn Marino
8375e4b17023SJohn Marino /* Extract the argument number, which was previously checked
8376e4b17023SJohn Marino to be valid. */
8377e4b17023SJohn Marino format_num_expr = TREE_VALUE (TREE_VALUE (attrs));
8378e4b17023SJohn Marino
8379e4b17023SJohn Marino gcc_assert (TREE_CODE (format_num_expr) == INTEGER_CST
8380e4b17023SJohn Marino && !TREE_INT_CST_HIGH (format_num_expr));
8381e4b17023SJohn Marino
8382e4b17023SJohn Marino format_num = TREE_INT_CST_LOW (format_num_expr);
8383e4b17023SJohn Marino
8384e4b17023SJohn Marino for (inner_arg = first_call_expr_arg (param, &iter), i = 1;
8385e4b17023SJohn Marino inner_arg != 0;
8386e4b17023SJohn Marino inner_arg = next_call_expr_arg (&iter), i++)
8387e4b17023SJohn Marino if (i == format_num)
8388e4b17023SJohn Marino {
8389e4b17023SJohn Marino check_function_arguments_recurse (callback, ctx,
8390e4b17023SJohn Marino inner_arg, param_num);
8391e4b17023SJohn Marino found_format_arg = true;
8392e4b17023SJohn Marino break;
8393e4b17023SJohn Marino }
8394e4b17023SJohn Marino }
8395e4b17023SJohn Marino
8396e4b17023SJohn Marino /* If we found a format_arg attribute and did a recursive check,
8397e4b17023SJohn Marino we are done with checking this argument. Otherwise, we continue
8398e4b17023SJohn Marino and this will be considered a non-literal. */
8399e4b17023SJohn Marino if (found_format_arg)
8400e4b17023SJohn Marino return;
8401e4b17023SJohn Marino }
8402e4b17023SJohn Marino
8403e4b17023SJohn Marino if (TREE_CODE (param) == COND_EXPR)
8404e4b17023SJohn Marino {
8405e4b17023SJohn Marino /* Check both halves of the conditional expression. */
8406e4b17023SJohn Marino check_function_arguments_recurse (callback, ctx,
8407e4b17023SJohn Marino TREE_OPERAND (param, 1), param_num);
8408e4b17023SJohn Marino check_function_arguments_recurse (callback, ctx,
8409e4b17023SJohn Marino TREE_OPERAND (param, 2), param_num);
8410e4b17023SJohn Marino return;
8411e4b17023SJohn Marino }
8412e4b17023SJohn Marino
8413e4b17023SJohn Marino (*callback) (ctx, param, param_num);
8414e4b17023SJohn Marino }
8415e4b17023SJohn Marino
8416e4b17023SJohn Marino /* Checks for a builtin function FNDECL that the number of arguments
8417e4b17023SJohn Marino NARGS against the required number REQUIRED and issues an error if
8418e4b17023SJohn Marino there is a mismatch. Returns true if the number of arguments is
8419e4b17023SJohn Marino correct, otherwise false. */
8420e4b17023SJohn Marino
8421e4b17023SJohn Marino static bool
builtin_function_validate_nargs(tree fndecl,int nargs,int required)8422e4b17023SJohn Marino builtin_function_validate_nargs (tree fndecl, int nargs, int required)
8423e4b17023SJohn Marino {
8424e4b17023SJohn Marino if (nargs < required)
8425e4b17023SJohn Marino {
8426e4b17023SJohn Marino error_at (input_location,
8427e4b17023SJohn Marino "not enough arguments to function %qE", fndecl);
8428e4b17023SJohn Marino return false;
8429e4b17023SJohn Marino }
8430e4b17023SJohn Marino else if (nargs > required)
8431e4b17023SJohn Marino {
8432e4b17023SJohn Marino error_at (input_location,
8433e4b17023SJohn Marino "too many arguments to function %qE", fndecl);
8434e4b17023SJohn Marino return false;
8435e4b17023SJohn Marino }
8436e4b17023SJohn Marino return true;
8437e4b17023SJohn Marino }
8438e4b17023SJohn Marino
8439e4b17023SJohn Marino /* Verifies the NARGS arguments ARGS to the builtin function FNDECL.
8440e4b17023SJohn Marino Returns false if there was an error, otherwise true. */
8441e4b17023SJohn Marino
8442e4b17023SJohn Marino bool
check_builtin_function_arguments(tree fndecl,int nargs,tree * args)8443e4b17023SJohn Marino check_builtin_function_arguments (tree fndecl, int nargs, tree *args)
8444e4b17023SJohn Marino {
8445e4b17023SJohn Marino if (!DECL_BUILT_IN (fndecl)
8446e4b17023SJohn Marino || DECL_BUILT_IN_CLASS (fndecl) != BUILT_IN_NORMAL)
8447e4b17023SJohn Marino return true;
8448e4b17023SJohn Marino
8449e4b17023SJohn Marino switch (DECL_FUNCTION_CODE (fndecl))
8450e4b17023SJohn Marino {
8451e4b17023SJohn Marino case BUILT_IN_CONSTANT_P:
8452e4b17023SJohn Marino return builtin_function_validate_nargs (fndecl, nargs, 1);
8453e4b17023SJohn Marino
8454e4b17023SJohn Marino case BUILT_IN_ISFINITE:
8455e4b17023SJohn Marino case BUILT_IN_ISINF:
8456e4b17023SJohn Marino case BUILT_IN_ISINF_SIGN:
8457e4b17023SJohn Marino case BUILT_IN_ISNAN:
8458e4b17023SJohn Marino case BUILT_IN_ISNORMAL:
8459e4b17023SJohn Marino if (builtin_function_validate_nargs (fndecl, nargs, 1))
8460e4b17023SJohn Marino {
8461e4b17023SJohn Marino if (TREE_CODE (TREE_TYPE (args[0])) != REAL_TYPE)
8462e4b17023SJohn Marino {
8463e4b17023SJohn Marino error ("non-floating-point argument in call to "
8464e4b17023SJohn Marino "function %qE", fndecl);
8465e4b17023SJohn Marino return false;
8466e4b17023SJohn Marino }
8467e4b17023SJohn Marino return true;
8468e4b17023SJohn Marino }
8469e4b17023SJohn Marino return false;
8470e4b17023SJohn Marino
8471e4b17023SJohn Marino case BUILT_IN_ISGREATER:
8472e4b17023SJohn Marino case BUILT_IN_ISGREATEREQUAL:
8473e4b17023SJohn Marino case BUILT_IN_ISLESS:
8474e4b17023SJohn Marino case BUILT_IN_ISLESSEQUAL:
8475e4b17023SJohn Marino case BUILT_IN_ISLESSGREATER:
8476e4b17023SJohn Marino case BUILT_IN_ISUNORDERED:
8477e4b17023SJohn Marino if (builtin_function_validate_nargs (fndecl, nargs, 2))
8478e4b17023SJohn Marino {
8479e4b17023SJohn Marino enum tree_code code0, code1;
8480e4b17023SJohn Marino code0 = TREE_CODE (TREE_TYPE (args[0]));
8481e4b17023SJohn Marino code1 = TREE_CODE (TREE_TYPE (args[1]));
8482e4b17023SJohn Marino if (!((code0 == REAL_TYPE && code1 == REAL_TYPE)
8483e4b17023SJohn Marino || (code0 == REAL_TYPE && code1 == INTEGER_TYPE)
8484e4b17023SJohn Marino || (code0 == INTEGER_TYPE && code1 == REAL_TYPE)))
8485e4b17023SJohn Marino {
8486e4b17023SJohn Marino error ("non-floating-point arguments in call to "
8487e4b17023SJohn Marino "function %qE", fndecl);
8488e4b17023SJohn Marino return false;
8489e4b17023SJohn Marino }
8490e4b17023SJohn Marino return true;
8491e4b17023SJohn Marino }
8492e4b17023SJohn Marino return false;
8493e4b17023SJohn Marino
8494e4b17023SJohn Marino case BUILT_IN_FPCLASSIFY:
8495e4b17023SJohn Marino if (builtin_function_validate_nargs (fndecl, nargs, 6))
8496e4b17023SJohn Marino {
8497e4b17023SJohn Marino unsigned i;
8498e4b17023SJohn Marino
8499e4b17023SJohn Marino for (i=0; i<5; i++)
8500e4b17023SJohn Marino if (TREE_CODE (args[i]) != INTEGER_CST)
8501e4b17023SJohn Marino {
8502e4b17023SJohn Marino error ("non-const integer argument %u in call to function %qE",
8503e4b17023SJohn Marino i+1, fndecl);
8504e4b17023SJohn Marino return false;
8505e4b17023SJohn Marino }
8506e4b17023SJohn Marino
8507e4b17023SJohn Marino if (TREE_CODE (TREE_TYPE (args[5])) != REAL_TYPE)
8508e4b17023SJohn Marino {
8509e4b17023SJohn Marino error ("non-floating-point argument in call to function %qE",
8510e4b17023SJohn Marino fndecl);
8511e4b17023SJohn Marino return false;
8512e4b17023SJohn Marino }
8513e4b17023SJohn Marino return true;
8514e4b17023SJohn Marino }
8515e4b17023SJohn Marino return false;
8516e4b17023SJohn Marino
8517e4b17023SJohn Marino case BUILT_IN_ASSUME_ALIGNED:
8518e4b17023SJohn Marino if (builtin_function_validate_nargs (fndecl, nargs, 2 + (nargs > 2)))
8519e4b17023SJohn Marino {
8520e4b17023SJohn Marino if (nargs >= 3 && TREE_CODE (TREE_TYPE (args[2])) != INTEGER_TYPE)
8521e4b17023SJohn Marino {
8522e4b17023SJohn Marino error ("non-integer argument 3 in call to function %qE", fndecl);
8523e4b17023SJohn Marino return false;
8524e4b17023SJohn Marino }
8525e4b17023SJohn Marino return true;
8526e4b17023SJohn Marino }
8527e4b17023SJohn Marino return false;
8528e4b17023SJohn Marino
8529e4b17023SJohn Marino default:
8530e4b17023SJohn Marino return true;
8531e4b17023SJohn Marino }
8532e4b17023SJohn Marino }
8533e4b17023SJohn Marino
8534e4b17023SJohn Marino /* Function to help qsort sort FIELD_DECLs by name order. */
8535e4b17023SJohn Marino
8536e4b17023SJohn Marino int
field_decl_cmp(const void * x_p,const void * y_p)8537e4b17023SJohn Marino field_decl_cmp (const void *x_p, const void *y_p)
8538e4b17023SJohn Marino {
8539e4b17023SJohn Marino const tree *const x = (const tree *const) x_p;
8540e4b17023SJohn Marino const tree *const y = (const tree *const) y_p;
8541e4b17023SJohn Marino
8542e4b17023SJohn Marino if (DECL_NAME (*x) == DECL_NAME (*y))
8543e4b17023SJohn Marino /* A nontype is "greater" than a type. */
8544e4b17023SJohn Marino return (TREE_CODE (*y) == TYPE_DECL) - (TREE_CODE (*x) == TYPE_DECL);
8545e4b17023SJohn Marino if (DECL_NAME (*x) == NULL_TREE)
8546e4b17023SJohn Marino return -1;
8547e4b17023SJohn Marino if (DECL_NAME (*y) == NULL_TREE)
8548e4b17023SJohn Marino return 1;
8549e4b17023SJohn Marino if (DECL_NAME (*x) < DECL_NAME (*y))
8550e4b17023SJohn Marino return -1;
8551e4b17023SJohn Marino return 1;
8552e4b17023SJohn Marino }
8553e4b17023SJohn Marino
8554e4b17023SJohn Marino static struct {
8555e4b17023SJohn Marino gt_pointer_operator new_value;
8556e4b17023SJohn Marino void *cookie;
8557e4b17023SJohn Marino } resort_data;
8558e4b17023SJohn Marino
8559e4b17023SJohn Marino /* This routine compares two fields like field_decl_cmp but using the
8560e4b17023SJohn Marino pointer operator in resort_data. */
8561e4b17023SJohn Marino
8562e4b17023SJohn Marino static int
resort_field_decl_cmp(const void * x_p,const void * y_p)8563e4b17023SJohn Marino resort_field_decl_cmp (const void *x_p, const void *y_p)
8564e4b17023SJohn Marino {
8565e4b17023SJohn Marino const tree *const x = (const tree *const) x_p;
8566e4b17023SJohn Marino const tree *const y = (const tree *const) y_p;
8567e4b17023SJohn Marino
8568e4b17023SJohn Marino if (DECL_NAME (*x) == DECL_NAME (*y))
8569e4b17023SJohn Marino /* A nontype is "greater" than a type. */
8570e4b17023SJohn Marino return (TREE_CODE (*y) == TYPE_DECL) - (TREE_CODE (*x) == TYPE_DECL);
8571e4b17023SJohn Marino if (DECL_NAME (*x) == NULL_TREE)
8572e4b17023SJohn Marino return -1;
8573e4b17023SJohn Marino if (DECL_NAME (*y) == NULL_TREE)
8574e4b17023SJohn Marino return 1;
8575e4b17023SJohn Marino {
8576e4b17023SJohn Marino tree d1 = DECL_NAME (*x);
8577e4b17023SJohn Marino tree d2 = DECL_NAME (*y);
8578e4b17023SJohn Marino resort_data.new_value (&d1, resort_data.cookie);
8579e4b17023SJohn Marino resort_data.new_value (&d2, resort_data.cookie);
8580e4b17023SJohn Marino if (d1 < d2)
8581e4b17023SJohn Marino return -1;
8582e4b17023SJohn Marino }
8583e4b17023SJohn Marino return 1;
8584e4b17023SJohn Marino }
8585e4b17023SJohn Marino
8586e4b17023SJohn Marino /* Resort DECL_SORTED_FIELDS because pointers have been reordered. */
8587e4b17023SJohn Marino
8588e4b17023SJohn Marino void
resort_sorted_fields(void * obj,void * ARG_UNUSED (orig_obj),gt_pointer_operator new_value,void * cookie)8589e4b17023SJohn Marino resort_sorted_fields (void *obj,
8590e4b17023SJohn Marino void * ARG_UNUSED (orig_obj),
8591e4b17023SJohn Marino gt_pointer_operator new_value,
8592e4b17023SJohn Marino void *cookie)
8593e4b17023SJohn Marino {
8594e4b17023SJohn Marino struct sorted_fields_type *sf = (struct sorted_fields_type *) obj;
8595e4b17023SJohn Marino resort_data.new_value = new_value;
8596e4b17023SJohn Marino resort_data.cookie = cookie;
8597e4b17023SJohn Marino qsort (&sf->elts[0], sf->len, sizeof (tree),
8598e4b17023SJohn Marino resort_field_decl_cmp);
8599e4b17023SJohn Marino }
8600e4b17023SJohn Marino
8601e4b17023SJohn Marino /* Subroutine of c_parse_error.
8602e4b17023SJohn Marino Return the result of concatenating LHS and RHS. RHS is really
8603e4b17023SJohn Marino a string literal, its first character is indicated by RHS_START and
8604e4b17023SJohn Marino RHS_SIZE is its length (including the terminating NUL character).
8605e4b17023SJohn Marino
8606e4b17023SJohn Marino The caller is responsible for deleting the returned pointer. */
8607e4b17023SJohn Marino
8608e4b17023SJohn Marino static char *
catenate_strings(const char * lhs,const char * rhs_start,int rhs_size)8609e4b17023SJohn Marino catenate_strings (const char *lhs, const char *rhs_start, int rhs_size)
8610e4b17023SJohn Marino {
8611e4b17023SJohn Marino const int lhs_size = strlen (lhs);
8612e4b17023SJohn Marino char *result = XNEWVEC (char, lhs_size + rhs_size);
8613e4b17023SJohn Marino strncpy (result, lhs, lhs_size);
8614e4b17023SJohn Marino strncpy (result + lhs_size, rhs_start, rhs_size);
8615e4b17023SJohn Marino return result;
8616e4b17023SJohn Marino }
8617e4b17023SJohn Marino
8618e4b17023SJohn Marino /* Issue the error given by GMSGID, indicating that it occurred before
8619e4b17023SJohn Marino TOKEN, which had the associated VALUE. */
8620e4b17023SJohn Marino
8621e4b17023SJohn Marino void
c_parse_error(const char * gmsgid,enum cpp_ttype token_type,tree value,unsigned char token_flags)8622e4b17023SJohn Marino c_parse_error (const char *gmsgid, enum cpp_ttype token_type,
8623e4b17023SJohn Marino tree value, unsigned char token_flags)
8624e4b17023SJohn Marino {
8625e4b17023SJohn Marino #define catenate_messages(M1, M2) catenate_strings ((M1), (M2), sizeof (M2))
8626e4b17023SJohn Marino
8627e4b17023SJohn Marino char *message = NULL;
8628e4b17023SJohn Marino
8629e4b17023SJohn Marino if (token_type == CPP_EOF)
8630e4b17023SJohn Marino message = catenate_messages (gmsgid, " at end of input");
8631e4b17023SJohn Marino else if (token_type == CPP_CHAR
8632e4b17023SJohn Marino || token_type == CPP_WCHAR
8633e4b17023SJohn Marino || token_type == CPP_CHAR16
8634e4b17023SJohn Marino || token_type == CPP_CHAR32)
8635e4b17023SJohn Marino {
8636e4b17023SJohn Marino unsigned int val = TREE_INT_CST_LOW (value);
8637e4b17023SJohn Marino const char *prefix;
8638e4b17023SJohn Marino
8639e4b17023SJohn Marino switch (token_type)
8640e4b17023SJohn Marino {
8641e4b17023SJohn Marino default:
8642e4b17023SJohn Marino prefix = "";
8643e4b17023SJohn Marino break;
8644e4b17023SJohn Marino case CPP_WCHAR:
8645e4b17023SJohn Marino prefix = "L";
8646e4b17023SJohn Marino break;
8647e4b17023SJohn Marino case CPP_CHAR16:
8648e4b17023SJohn Marino prefix = "u";
8649e4b17023SJohn Marino break;
8650e4b17023SJohn Marino case CPP_CHAR32:
8651e4b17023SJohn Marino prefix = "U";
8652e4b17023SJohn Marino break;
8653e4b17023SJohn Marino }
8654e4b17023SJohn Marino
8655e4b17023SJohn Marino if (val <= UCHAR_MAX && ISGRAPH (val))
8656e4b17023SJohn Marino message = catenate_messages (gmsgid, " before %s'%c'");
8657e4b17023SJohn Marino else
8658e4b17023SJohn Marino message = catenate_messages (gmsgid, " before %s'\\x%x'");
8659e4b17023SJohn Marino
8660e4b17023SJohn Marino error (message, prefix, val);
8661e4b17023SJohn Marino free (message);
8662e4b17023SJohn Marino message = NULL;
8663e4b17023SJohn Marino }
8664e4b17023SJohn Marino else if (token_type == CPP_STRING
8665e4b17023SJohn Marino || token_type == CPP_WSTRING
8666e4b17023SJohn Marino || token_type == CPP_STRING16
8667e4b17023SJohn Marino || token_type == CPP_STRING32
8668e4b17023SJohn Marino || token_type == CPP_UTF8STRING)
8669e4b17023SJohn Marino message = catenate_messages (gmsgid, " before string constant");
8670e4b17023SJohn Marino else if (token_type == CPP_NUMBER)
8671e4b17023SJohn Marino message = catenate_messages (gmsgid, " before numeric constant");
8672e4b17023SJohn Marino else if (token_type == CPP_NAME)
8673e4b17023SJohn Marino {
8674e4b17023SJohn Marino message = catenate_messages (gmsgid, " before %qE");
8675e4b17023SJohn Marino error (message, value);
8676e4b17023SJohn Marino free (message);
8677e4b17023SJohn Marino message = NULL;
8678e4b17023SJohn Marino }
8679e4b17023SJohn Marino else if (token_type == CPP_PRAGMA)
8680e4b17023SJohn Marino message = catenate_messages (gmsgid, " before %<#pragma%>");
8681e4b17023SJohn Marino else if (token_type == CPP_PRAGMA_EOL)
8682e4b17023SJohn Marino message = catenate_messages (gmsgid, " before end of line");
8683e4b17023SJohn Marino else if (token_type == CPP_DECLTYPE)
8684e4b17023SJohn Marino message = catenate_messages (gmsgid, " before %<decltype%>");
8685e4b17023SJohn Marino else if (token_type < N_TTYPES)
8686e4b17023SJohn Marino {
8687e4b17023SJohn Marino message = catenate_messages (gmsgid, " before %qs token");
8688e4b17023SJohn Marino error (message, cpp_type2name (token_type, token_flags));
8689e4b17023SJohn Marino free (message);
8690e4b17023SJohn Marino message = NULL;
8691e4b17023SJohn Marino }
8692e4b17023SJohn Marino else
8693e4b17023SJohn Marino error (gmsgid);
8694e4b17023SJohn Marino
8695e4b17023SJohn Marino if (message)
8696e4b17023SJohn Marino {
8697e4b17023SJohn Marino error (message);
8698e4b17023SJohn Marino free (message);
8699e4b17023SJohn Marino }
8700e4b17023SJohn Marino #undef catenate_messages
8701e4b17023SJohn Marino }
8702e4b17023SJohn Marino
8703e4b17023SJohn Marino /* Mapping for cpp message reasons to the options that enable them. */
8704e4b17023SJohn Marino
8705e4b17023SJohn Marino struct reason_option_codes_t
8706e4b17023SJohn Marino {
8707e4b17023SJohn Marino const int reason; /* cpplib message reason. */
8708e4b17023SJohn Marino const int option_code; /* gcc option that controls this message. */
8709e4b17023SJohn Marino };
8710e4b17023SJohn Marino
8711e4b17023SJohn Marino static const struct reason_option_codes_t option_codes[] = {
8712e4b17023SJohn Marino {CPP_W_DEPRECATED, OPT_Wdeprecated},
8713e4b17023SJohn Marino {CPP_W_COMMENTS, OPT_Wcomment},
8714e4b17023SJohn Marino {CPP_W_TRIGRAPHS, OPT_Wtrigraphs},
8715e4b17023SJohn Marino {CPP_W_MULTICHAR, OPT_Wmultichar},
8716e4b17023SJohn Marino {CPP_W_TRADITIONAL, OPT_Wtraditional},
8717e4b17023SJohn Marino {CPP_W_LONG_LONG, OPT_Wlong_long},
8718e4b17023SJohn Marino {CPP_W_ENDIF_LABELS, OPT_Wendif_labels},
8719e4b17023SJohn Marino {CPP_W_VARIADIC_MACROS, OPT_Wvariadic_macros},
8720e4b17023SJohn Marino {CPP_W_BUILTIN_MACRO_REDEFINED, OPT_Wbuiltin_macro_redefined},
8721e4b17023SJohn Marino {CPP_W_UNDEF, OPT_Wundef},
8722e4b17023SJohn Marino {CPP_W_UNUSED_MACROS, OPT_Wunused_macros},
8723e4b17023SJohn Marino {CPP_W_CXX_OPERATOR_NAMES, OPT_Wc___compat},
8724e4b17023SJohn Marino {CPP_W_NORMALIZE, OPT_Wnormalized_},
8725e4b17023SJohn Marino {CPP_W_INVALID_PCH, OPT_Winvalid_pch},
8726e4b17023SJohn Marino {CPP_W_WARNING_DIRECTIVE, OPT_Wcpp},
8727e4b17023SJohn Marino {CPP_W_NONE, 0}
8728e4b17023SJohn Marino };
8729e4b17023SJohn Marino
8730e4b17023SJohn Marino /* Return the gcc option code associated with the reason for a cpp
8731e4b17023SJohn Marino message, or 0 if none. */
8732e4b17023SJohn Marino
8733e4b17023SJohn Marino static int
c_option_controlling_cpp_error(int reason)8734e4b17023SJohn Marino c_option_controlling_cpp_error (int reason)
8735e4b17023SJohn Marino {
8736e4b17023SJohn Marino const struct reason_option_codes_t *entry;
8737e4b17023SJohn Marino
8738e4b17023SJohn Marino for (entry = option_codes; entry->reason != CPP_W_NONE; entry++)
8739e4b17023SJohn Marino {
8740e4b17023SJohn Marino if (entry->reason == reason)
8741e4b17023SJohn Marino return entry->option_code;
8742e4b17023SJohn Marino }
8743e4b17023SJohn Marino return 0;
8744e4b17023SJohn Marino }
8745e4b17023SJohn Marino
8746e4b17023SJohn Marino /* Callback from cpp_error for PFILE to print diagnostics from the
8747e4b17023SJohn Marino preprocessor. The diagnostic is of type LEVEL, with REASON set
8748e4b17023SJohn Marino to the reason code if LEVEL is represents a warning, at location
8749e4b17023SJohn Marino LOCATION unless this is after lexing and the compiler's location
8750e4b17023SJohn Marino should be used instead, with column number possibly overridden by
8751e4b17023SJohn Marino COLUMN_OVERRIDE if not zero; MSG is the translated message and AP
8752e4b17023SJohn Marino the arguments. Returns true if a diagnostic was emitted, false
8753e4b17023SJohn Marino otherwise. */
8754e4b17023SJohn Marino
8755e4b17023SJohn Marino bool
c_cpp_error(cpp_reader * pfile ATTRIBUTE_UNUSED,int level,int reason,location_t location,unsigned int column_override,const char * msg,va_list * ap)8756e4b17023SJohn Marino c_cpp_error (cpp_reader *pfile ATTRIBUTE_UNUSED, int level, int reason,
8757e4b17023SJohn Marino location_t location, unsigned int column_override,
8758e4b17023SJohn Marino const char *msg, va_list *ap)
8759e4b17023SJohn Marino {
8760e4b17023SJohn Marino diagnostic_info diagnostic;
8761e4b17023SJohn Marino diagnostic_t dlevel;
8762e4b17023SJohn Marino bool save_warn_system_headers = global_dc->dc_warn_system_headers;
8763e4b17023SJohn Marino bool ret;
8764e4b17023SJohn Marino
8765e4b17023SJohn Marino switch (level)
8766e4b17023SJohn Marino {
8767e4b17023SJohn Marino case CPP_DL_WARNING_SYSHDR:
8768e4b17023SJohn Marino if (flag_no_output)
8769e4b17023SJohn Marino return false;
8770e4b17023SJohn Marino global_dc->dc_warn_system_headers = 1;
8771e4b17023SJohn Marino /* Fall through. */
8772e4b17023SJohn Marino case CPP_DL_WARNING:
8773e4b17023SJohn Marino if (flag_no_output)
8774e4b17023SJohn Marino return false;
8775e4b17023SJohn Marino dlevel = DK_WARNING;
8776e4b17023SJohn Marino break;
8777e4b17023SJohn Marino case CPP_DL_PEDWARN:
8778e4b17023SJohn Marino if (flag_no_output && !flag_pedantic_errors)
8779e4b17023SJohn Marino return false;
8780e4b17023SJohn Marino dlevel = DK_PEDWARN;
8781e4b17023SJohn Marino break;
8782e4b17023SJohn Marino case CPP_DL_ERROR:
8783e4b17023SJohn Marino dlevel = DK_ERROR;
8784e4b17023SJohn Marino break;
8785e4b17023SJohn Marino case CPP_DL_ICE:
8786e4b17023SJohn Marino dlevel = DK_ICE;
8787e4b17023SJohn Marino break;
8788e4b17023SJohn Marino case CPP_DL_NOTE:
8789e4b17023SJohn Marino dlevel = DK_NOTE;
8790e4b17023SJohn Marino break;
8791e4b17023SJohn Marino case CPP_DL_FATAL:
8792e4b17023SJohn Marino dlevel = DK_FATAL;
8793e4b17023SJohn Marino break;
8794e4b17023SJohn Marino default:
8795e4b17023SJohn Marino gcc_unreachable ();
8796e4b17023SJohn Marino }
8797e4b17023SJohn Marino if (done_lexing)
8798e4b17023SJohn Marino location = input_location;
8799e4b17023SJohn Marino diagnostic_set_info_translated (&diagnostic, msg, ap,
8800e4b17023SJohn Marino location, dlevel);
8801e4b17023SJohn Marino if (column_override)
8802e4b17023SJohn Marino diagnostic_override_column (&diagnostic, column_override);
8803e4b17023SJohn Marino diagnostic_override_option_index (&diagnostic,
8804e4b17023SJohn Marino c_option_controlling_cpp_error (reason));
8805e4b17023SJohn Marino ret = report_diagnostic (&diagnostic);
8806e4b17023SJohn Marino if (level == CPP_DL_WARNING_SYSHDR)
8807e4b17023SJohn Marino global_dc->dc_warn_system_headers = save_warn_system_headers;
8808e4b17023SJohn Marino return ret;
8809e4b17023SJohn Marino }
8810e4b17023SJohn Marino
8811e4b17023SJohn Marino /* Convert a character from the host to the target execution character
8812e4b17023SJohn Marino set. cpplib handles this, mostly. */
8813e4b17023SJohn Marino
8814e4b17023SJohn Marino HOST_WIDE_INT
c_common_to_target_charset(HOST_WIDE_INT c)8815e4b17023SJohn Marino c_common_to_target_charset (HOST_WIDE_INT c)
8816e4b17023SJohn Marino {
8817e4b17023SJohn Marino /* Character constants in GCC proper are sign-extended under -fsigned-char,
8818e4b17023SJohn Marino zero-extended under -fno-signed-char. cpplib insists that characters
8819e4b17023SJohn Marino and character constants are always unsigned. Hence we must convert
8820e4b17023SJohn Marino back and forth. */
8821e4b17023SJohn Marino cppchar_t uc = ((cppchar_t)c) & ((((cppchar_t)1) << CHAR_BIT)-1);
8822e4b17023SJohn Marino
8823e4b17023SJohn Marino uc = cpp_host_to_exec_charset (parse_in, uc);
8824e4b17023SJohn Marino
8825e4b17023SJohn Marino if (flag_signed_char)
8826e4b17023SJohn Marino return ((HOST_WIDE_INT)uc) << (HOST_BITS_PER_WIDE_INT - CHAR_TYPE_SIZE)
8827e4b17023SJohn Marino >> (HOST_BITS_PER_WIDE_INT - CHAR_TYPE_SIZE);
8828e4b17023SJohn Marino else
8829e4b17023SJohn Marino return uc;
8830e4b17023SJohn Marino }
8831e4b17023SJohn Marino
8832e4b17023SJohn Marino /* Fold an offsetof-like expression. EXPR is a nested sequence of component
8833e4b17023SJohn Marino references with an INDIRECT_REF of a constant at the bottom; much like the
8834e4b17023SJohn Marino traditional rendering of offsetof as a macro. Return the folded result. */
8835e4b17023SJohn Marino
8836e4b17023SJohn Marino tree
fold_offsetof_1(tree expr)8837e4b17023SJohn Marino fold_offsetof_1 (tree expr)
8838e4b17023SJohn Marino {
8839e4b17023SJohn Marino tree base, off, t;
8840e4b17023SJohn Marino
8841e4b17023SJohn Marino switch (TREE_CODE (expr))
8842e4b17023SJohn Marino {
8843e4b17023SJohn Marino case ERROR_MARK:
8844e4b17023SJohn Marino return expr;
8845e4b17023SJohn Marino
8846e4b17023SJohn Marino case VAR_DECL:
8847e4b17023SJohn Marino error ("cannot apply %<offsetof%> to static data member %qD", expr);
8848e4b17023SJohn Marino return error_mark_node;
8849e4b17023SJohn Marino
8850e4b17023SJohn Marino case CALL_EXPR:
8851e4b17023SJohn Marino case TARGET_EXPR:
8852e4b17023SJohn Marino error ("cannot apply %<offsetof%> when %<operator[]%> is overloaded");
8853e4b17023SJohn Marino return error_mark_node;
8854e4b17023SJohn Marino
8855e4b17023SJohn Marino case NOP_EXPR:
8856e4b17023SJohn Marino case INDIRECT_REF:
8857e4b17023SJohn Marino if (!TREE_CONSTANT (TREE_OPERAND (expr, 0)))
8858e4b17023SJohn Marino {
8859e4b17023SJohn Marino error ("cannot apply %<offsetof%> to a non constant address");
8860e4b17023SJohn Marino return error_mark_node;
8861e4b17023SJohn Marino }
8862e4b17023SJohn Marino return TREE_OPERAND (expr, 0);
8863e4b17023SJohn Marino
8864e4b17023SJohn Marino case COMPONENT_REF:
8865e4b17023SJohn Marino base = fold_offsetof_1 (TREE_OPERAND (expr, 0));
8866e4b17023SJohn Marino if (base == error_mark_node)
8867e4b17023SJohn Marino return base;
8868e4b17023SJohn Marino
8869e4b17023SJohn Marino t = TREE_OPERAND (expr, 1);
8870e4b17023SJohn Marino if (DECL_C_BIT_FIELD (t))
8871e4b17023SJohn Marino {
8872e4b17023SJohn Marino error ("attempt to take address of bit-field structure "
8873e4b17023SJohn Marino "member %qD", t);
8874e4b17023SJohn Marino return error_mark_node;
8875e4b17023SJohn Marino }
8876e4b17023SJohn Marino off = size_binop_loc (input_location, PLUS_EXPR, DECL_FIELD_OFFSET (t),
8877e4b17023SJohn Marino size_int (tree_low_cst (DECL_FIELD_BIT_OFFSET (t),
8878e4b17023SJohn Marino 1)
8879e4b17023SJohn Marino / BITS_PER_UNIT));
8880e4b17023SJohn Marino break;
8881e4b17023SJohn Marino
8882e4b17023SJohn Marino case ARRAY_REF:
8883e4b17023SJohn Marino base = fold_offsetof_1 (TREE_OPERAND (expr, 0));
8884e4b17023SJohn Marino if (base == error_mark_node)
8885e4b17023SJohn Marino return base;
8886e4b17023SJohn Marino
8887e4b17023SJohn Marino t = TREE_OPERAND (expr, 1);
8888e4b17023SJohn Marino
8889e4b17023SJohn Marino /* Check if the offset goes beyond the upper bound of the array. */
8890e4b17023SJohn Marino if (TREE_CODE (t) == INTEGER_CST && tree_int_cst_sgn (t) >= 0)
8891e4b17023SJohn Marino {
8892e4b17023SJohn Marino tree upbound = array_ref_up_bound (expr);
8893e4b17023SJohn Marino if (upbound != NULL_TREE
8894e4b17023SJohn Marino && TREE_CODE (upbound) == INTEGER_CST
8895e4b17023SJohn Marino && !tree_int_cst_equal (upbound,
8896e4b17023SJohn Marino TYPE_MAX_VALUE (TREE_TYPE (upbound))))
8897e4b17023SJohn Marino {
8898e4b17023SJohn Marino upbound = size_binop (PLUS_EXPR, upbound,
8899e4b17023SJohn Marino build_int_cst (TREE_TYPE (upbound), 1));
8900e4b17023SJohn Marino if (tree_int_cst_lt (upbound, t))
8901e4b17023SJohn Marino {
8902e4b17023SJohn Marino tree v;
8903e4b17023SJohn Marino
8904e4b17023SJohn Marino for (v = TREE_OPERAND (expr, 0);
8905e4b17023SJohn Marino TREE_CODE (v) == COMPONENT_REF;
8906e4b17023SJohn Marino v = TREE_OPERAND (v, 0))
8907e4b17023SJohn Marino if (TREE_CODE (TREE_TYPE (TREE_OPERAND (v, 0)))
8908e4b17023SJohn Marino == RECORD_TYPE)
8909e4b17023SJohn Marino {
8910e4b17023SJohn Marino tree fld_chain = DECL_CHAIN (TREE_OPERAND (v, 1));
8911e4b17023SJohn Marino for (; fld_chain; fld_chain = DECL_CHAIN (fld_chain))
8912e4b17023SJohn Marino if (TREE_CODE (fld_chain) == FIELD_DECL)
8913e4b17023SJohn Marino break;
8914e4b17023SJohn Marino
8915e4b17023SJohn Marino if (fld_chain)
8916e4b17023SJohn Marino break;
8917e4b17023SJohn Marino }
8918e4b17023SJohn Marino /* Don't warn if the array might be considered a poor
8919e4b17023SJohn Marino man's flexible array member with a very permissive
8920e4b17023SJohn Marino definition thereof. */
8921e4b17023SJohn Marino if (TREE_CODE (v) == ARRAY_REF
8922e4b17023SJohn Marino || TREE_CODE (v) == COMPONENT_REF)
8923e4b17023SJohn Marino warning (OPT_Warray_bounds,
8924e4b17023SJohn Marino "index %E denotes an offset "
8925e4b17023SJohn Marino "greater than size of %qT",
8926e4b17023SJohn Marino t, TREE_TYPE (TREE_OPERAND (expr, 0)));
8927e4b17023SJohn Marino }
8928e4b17023SJohn Marino }
8929e4b17023SJohn Marino }
8930e4b17023SJohn Marino
8931e4b17023SJohn Marino t = convert (sizetype, t);
8932e4b17023SJohn Marino off = size_binop (MULT_EXPR, TYPE_SIZE_UNIT (TREE_TYPE (expr)), t);
8933e4b17023SJohn Marino break;
8934e4b17023SJohn Marino
8935e4b17023SJohn Marino case COMPOUND_EXPR:
8936e4b17023SJohn Marino /* Handle static members of volatile structs. */
8937e4b17023SJohn Marino t = TREE_OPERAND (expr, 1);
8938e4b17023SJohn Marino gcc_assert (TREE_CODE (t) == VAR_DECL);
8939e4b17023SJohn Marino return fold_offsetof_1 (t);
8940e4b17023SJohn Marino
8941e4b17023SJohn Marino default:
8942e4b17023SJohn Marino gcc_unreachable ();
8943e4b17023SJohn Marino }
8944e4b17023SJohn Marino
8945e4b17023SJohn Marino return fold_build_pointer_plus (base, off);
8946e4b17023SJohn Marino }
8947e4b17023SJohn Marino
8948e4b17023SJohn Marino /* Likewise, but convert it to the return type of offsetof. */
8949e4b17023SJohn Marino
8950e4b17023SJohn Marino tree
fold_offsetof(tree expr)8951e4b17023SJohn Marino fold_offsetof (tree expr)
8952e4b17023SJohn Marino {
8953e4b17023SJohn Marino return convert (size_type_node, fold_offsetof_1 (expr));
8954e4b17023SJohn Marino }
8955e4b17023SJohn Marino
8956e4b17023SJohn Marino /* Warn for A ?: C expressions (with B omitted) where A is a boolean
8957e4b17023SJohn Marino expression, because B will always be true. */
8958e4b17023SJohn Marino
8959e4b17023SJohn Marino void
warn_for_omitted_condop(location_t location,tree cond)8960e4b17023SJohn Marino warn_for_omitted_condop (location_t location, tree cond)
8961e4b17023SJohn Marino {
8962e4b17023SJohn Marino if (truth_value_p (TREE_CODE (cond)))
8963e4b17023SJohn Marino warning_at (location, OPT_Wparentheses,
8964e4b17023SJohn Marino "the omitted middle operand in ?: will always be %<true%>, "
8965e4b17023SJohn Marino "suggest explicit middle operand");
8966e4b17023SJohn Marino }
8967e4b17023SJohn Marino
8968e4b17023SJohn Marino /* Give an error for storing into ARG, which is 'const'. USE indicates
8969e4b17023SJohn Marino how ARG was being used. */
8970e4b17023SJohn Marino
8971e4b17023SJohn Marino void
readonly_error(tree arg,enum lvalue_use use)8972e4b17023SJohn Marino readonly_error (tree arg, enum lvalue_use use)
8973e4b17023SJohn Marino {
8974e4b17023SJohn Marino gcc_assert (use == lv_assign || use == lv_increment || use == lv_decrement
8975e4b17023SJohn Marino || use == lv_asm);
8976e4b17023SJohn Marino /* Using this macro rather than (for example) arrays of messages
8977e4b17023SJohn Marino ensures that all the format strings are checked at compile
8978e4b17023SJohn Marino time. */
8979e4b17023SJohn Marino #define READONLY_MSG(A, I, D, AS) (use == lv_assign ? (A) \
8980e4b17023SJohn Marino : (use == lv_increment ? (I) \
8981e4b17023SJohn Marino : (use == lv_decrement ? (D) : (AS))))
8982e4b17023SJohn Marino if (TREE_CODE (arg) == COMPONENT_REF)
8983e4b17023SJohn Marino {
8984e4b17023SJohn Marino if (TYPE_READONLY (TREE_TYPE (TREE_OPERAND (arg, 0))))
8985e4b17023SJohn Marino error (READONLY_MSG (G_("assignment of member "
8986e4b17023SJohn Marino "%qD in read-only object"),
8987e4b17023SJohn Marino G_("increment of member "
8988e4b17023SJohn Marino "%qD in read-only object"),
8989e4b17023SJohn Marino G_("decrement of member "
8990e4b17023SJohn Marino "%qD in read-only object"),
8991e4b17023SJohn Marino G_("member %qD in read-only object "
8992e4b17023SJohn Marino "used as %<asm%> output")),
8993e4b17023SJohn Marino TREE_OPERAND (arg, 1));
8994e4b17023SJohn Marino else
8995e4b17023SJohn Marino error (READONLY_MSG (G_("assignment of read-only member %qD"),
8996e4b17023SJohn Marino G_("increment of read-only member %qD"),
8997e4b17023SJohn Marino G_("decrement of read-only member %qD"),
8998e4b17023SJohn Marino G_("read-only member %qD used as %<asm%> output")),
8999e4b17023SJohn Marino TREE_OPERAND (arg, 1));
9000e4b17023SJohn Marino }
9001e4b17023SJohn Marino else if (TREE_CODE (arg) == VAR_DECL)
9002e4b17023SJohn Marino error (READONLY_MSG (G_("assignment of read-only variable %qD"),
9003e4b17023SJohn Marino G_("increment of read-only variable %qD"),
9004e4b17023SJohn Marino G_("decrement of read-only variable %qD"),
9005e4b17023SJohn Marino G_("read-only variable %qD used as %<asm%> output")),
9006e4b17023SJohn Marino arg);
9007e4b17023SJohn Marino else if (TREE_CODE (arg) == PARM_DECL)
9008e4b17023SJohn Marino error (READONLY_MSG (G_("assignment of read-only parameter %qD"),
9009e4b17023SJohn Marino G_("increment of read-only parameter %qD"),
9010e4b17023SJohn Marino G_("decrement of read-only parameter %qD"),
9011e4b17023SJohn Marino G_("read-only parameter %qD use as %<asm%> output")),
9012e4b17023SJohn Marino arg);
9013e4b17023SJohn Marino else if (TREE_CODE (arg) == RESULT_DECL)
9014e4b17023SJohn Marino {
9015e4b17023SJohn Marino gcc_assert (c_dialect_cxx ());
9016e4b17023SJohn Marino error (READONLY_MSG (G_("assignment of "
9017e4b17023SJohn Marino "read-only named return value %qD"),
9018e4b17023SJohn Marino G_("increment of "
9019e4b17023SJohn Marino "read-only named return value %qD"),
9020e4b17023SJohn Marino G_("decrement of "
9021e4b17023SJohn Marino "read-only named return value %qD"),
9022e4b17023SJohn Marino G_("read-only named return value %qD "
9023e4b17023SJohn Marino "used as %<asm%>output")),
9024e4b17023SJohn Marino arg);
9025e4b17023SJohn Marino }
9026e4b17023SJohn Marino else if (TREE_CODE (arg) == FUNCTION_DECL)
9027e4b17023SJohn Marino error (READONLY_MSG (G_("assignment of function %qD"),
9028e4b17023SJohn Marino G_("increment of function %qD"),
9029e4b17023SJohn Marino G_("decrement of function %qD"),
9030e4b17023SJohn Marino G_("function %qD used as %<asm%> output")),
9031e4b17023SJohn Marino arg);
9032e4b17023SJohn Marino else
9033e4b17023SJohn Marino error (READONLY_MSG (G_("assignment of read-only location %qE"),
9034e4b17023SJohn Marino G_("increment of read-only location %qE"),
9035e4b17023SJohn Marino G_("decrement of read-only location %qE"),
9036e4b17023SJohn Marino G_("read-only location %qE used as %<asm%> output")),
9037e4b17023SJohn Marino arg);
9038e4b17023SJohn Marino }
9039e4b17023SJohn Marino
9040e4b17023SJohn Marino /* Print an error message for an invalid lvalue. USE says
9041e4b17023SJohn Marino how the lvalue is being used and so selects the error message. LOC
9042e4b17023SJohn Marino is the location for the error. */
9043e4b17023SJohn Marino
9044e4b17023SJohn Marino void
lvalue_error(location_t loc,enum lvalue_use use)9045e4b17023SJohn Marino lvalue_error (location_t loc, enum lvalue_use use)
9046e4b17023SJohn Marino {
9047e4b17023SJohn Marino switch (use)
9048e4b17023SJohn Marino {
9049e4b17023SJohn Marino case lv_assign:
9050e4b17023SJohn Marino error_at (loc, "lvalue required as left operand of assignment");
9051e4b17023SJohn Marino break;
9052e4b17023SJohn Marino case lv_increment:
9053e4b17023SJohn Marino error_at (loc, "lvalue required as increment operand");
9054e4b17023SJohn Marino break;
9055e4b17023SJohn Marino case lv_decrement:
9056e4b17023SJohn Marino error_at (loc, "lvalue required as decrement operand");
9057e4b17023SJohn Marino break;
9058e4b17023SJohn Marino case lv_addressof:
9059e4b17023SJohn Marino error_at (loc, "lvalue required as unary %<&%> operand");
9060e4b17023SJohn Marino break;
9061e4b17023SJohn Marino case lv_asm:
9062e4b17023SJohn Marino error_at (loc, "lvalue required in asm statement");
9063e4b17023SJohn Marino break;
9064e4b17023SJohn Marino default:
9065e4b17023SJohn Marino gcc_unreachable ();
9066e4b17023SJohn Marino }
9067e4b17023SJohn Marino }
9068e4b17023SJohn Marino
9069e4b17023SJohn Marino /* Print an error message for an invalid indirection of type TYPE.
9070e4b17023SJohn Marino ERRSTRING is the name of the operator for the indirection. */
9071e4b17023SJohn Marino
9072e4b17023SJohn Marino void
invalid_indirection_error(location_t loc,tree type,ref_operator errstring)9073e4b17023SJohn Marino invalid_indirection_error (location_t loc, tree type, ref_operator errstring)
9074e4b17023SJohn Marino {
9075e4b17023SJohn Marino switch (errstring)
9076e4b17023SJohn Marino {
9077e4b17023SJohn Marino case RO_NULL:
9078e4b17023SJohn Marino gcc_assert (c_dialect_cxx ());
9079e4b17023SJohn Marino error_at (loc, "invalid type argument (have %qT)", type);
9080e4b17023SJohn Marino break;
9081e4b17023SJohn Marino case RO_ARRAY_INDEXING:
9082e4b17023SJohn Marino error_at (loc,
9083e4b17023SJohn Marino "invalid type argument of array indexing (have %qT)",
9084e4b17023SJohn Marino type);
9085e4b17023SJohn Marino break;
9086e4b17023SJohn Marino case RO_UNARY_STAR:
9087e4b17023SJohn Marino error_at (loc,
9088e4b17023SJohn Marino "invalid type argument of unary %<*%> (have %qT)",
9089e4b17023SJohn Marino type);
9090e4b17023SJohn Marino break;
9091e4b17023SJohn Marino case RO_ARROW:
9092e4b17023SJohn Marino error_at (loc,
9093e4b17023SJohn Marino "invalid type argument of %<->%> (have %qT)",
9094e4b17023SJohn Marino type);
9095e4b17023SJohn Marino break;
9096e4b17023SJohn Marino case RO_IMPLICIT_CONVERSION:
9097e4b17023SJohn Marino error_at (loc,
9098e4b17023SJohn Marino "invalid type argument of implicit conversion (have %qT)",
9099e4b17023SJohn Marino type);
9100e4b17023SJohn Marino break;
9101e4b17023SJohn Marino default:
9102e4b17023SJohn Marino gcc_unreachable ();
9103e4b17023SJohn Marino }
9104e4b17023SJohn Marino }
9105e4b17023SJohn Marino
9106e4b17023SJohn Marino /* *PTYPE is an incomplete array. Complete it with a domain based on
9107e4b17023SJohn Marino INITIAL_VALUE. If INITIAL_VALUE is not present, use 1 if DO_DEFAULT
9108e4b17023SJohn Marino is true. Return 0 if successful, 1 if INITIAL_VALUE can't be deciphered,
9109e4b17023SJohn Marino 2 if INITIAL_VALUE was NULL, and 3 if INITIAL_VALUE was empty. */
9110e4b17023SJohn Marino
9111e4b17023SJohn Marino int
complete_array_type(tree * ptype,tree initial_value,bool do_default)9112e4b17023SJohn Marino complete_array_type (tree *ptype, tree initial_value, bool do_default)
9113e4b17023SJohn Marino {
9114e4b17023SJohn Marino tree maxindex, type, main_type, elt, unqual_elt;
9115e4b17023SJohn Marino int failure = 0, quals;
9116e4b17023SJohn Marino hashval_t hashcode = 0;
9117e4b17023SJohn Marino
9118e4b17023SJohn Marino maxindex = size_zero_node;
9119e4b17023SJohn Marino if (initial_value)
9120e4b17023SJohn Marino {
9121e4b17023SJohn Marino if (TREE_CODE (initial_value) == STRING_CST)
9122e4b17023SJohn Marino {
9123e4b17023SJohn Marino int eltsize
9124e4b17023SJohn Marino = int_size_in_bytes (TREE_TYPE (TREE_TYPE (initial_value)));
9125e4b17023SJohn Marino maxindex = size_int (TREE_STRING_LENGTH (initial_value)/eltsize - 1);
9126e4b17023SJohn Marino }
9127e4b17023SJohn Marino else if (TREE_CODE (initial_value) == CONSTRUCTOR)
9128e4b17023SJohn Marino {
9129e4b17023SJohn Marino VEC(constructor_elt,gc) *v = CONSTRUCTOR_ELTS (initial_value);
9130e4b17023SJohn Marino
9131e4b17023SJohn Marino if (VEC_empty (constructor_elt, v))
9132e4b17023SJohn Marino {
9133e4b17023SJohn Marino if (pedantic)
9134e4b17023SJohn Marino failure = 3;
9135e4b17023SJohn Marino maxindex = ssize_int (-1);
9136e4b17023SJohn Marino }
9137e4b17023SJohn Marino else
9138e4b17023SJohn Marino {
9139e4b17023SJohn Marino tree curindex;
9140e4b17023SJohn Marino unsigned HOST_WIDE_INT cnt;
9141e4b17023SJohn Marino constructor_elt *ce;
9142e4b17023SJohn Marino bool fold_p = false;
9143e4b17023SJohn Marino
9144e4b17023SJohn Marino if (VEC_index (constructor_elt, v, 0)->index)
9145e4b17023SJohn Marino maxindex = fold_convert_loc (input_location, sizetype,
9146e4b17023SJohn Marino VEC_index (constructor_elt,
9147e4b17023SJohn Marino v, 0)->index);
9148e4b17023SJohn Marino curindex = maxindex;
9149e4b17023SJohn Marino
9150e4b17023SJohn Marino for (cnt = 1;
9151e4b17023SJohn Marino VEC_iterate (constructor_elt, v, cnt, ce);
9152e4b17023SJohn Marino cnt++)
9153e4b17023SJohn Marino {
9154e4b17023SJohn Marino bool curfold_p = false;
9155e4b17023SJohn Marino if (ce->index)
9156e4b17023SJohn Marino curindex = ce->index, curfold_p = true;
9157e4b17023SJohn Marino else
9158e4b17023SJohn Marino {
9159e4b17023SJohn Marino if (fold_p)
9160e4b17023SJohn Marino curindex = fold_convert (sizetype, curindex);
9161e4b17023SJohn Marino curindex = size_binop (PLUS_EXPR, curindex,
9162e4b17023SJohn Marino size_one_node);
9163e4b17023SJohn Marino }
9164e4b17023SJohn Marino if (tree_int_cst_lt (maxindex, curindex))
9165e4b17023SJohn Marino maxindex = curindex, fold_p = curfold_p;
9166e4b17023SJohn Marino }
9167e4b17023SJohn Marino if (fold_p)
9168e4b17023SJohn Marino maxindex = fold_convert (sizetype, maxindex);
9169e4b17023SJohn Marino }
9170e4b17023SJohn Marino }
9171e4b17023SJohn Marino else
9172e4b17023SJohn Marino {
9173e4b17023SJohn Marino /* Make an error message unless that happened already. */
9174e4b17023SJohn Marino if (initial_value != error_mark_node)
9175e4b17023SJohn Marino failure = 1;
9176e4b17023SJohn Marino }
9177e4b17023SJohn Marino }
9178e4b17023SJohn Marino else
9179e4b17023SJohn Marino {
9180e4b17023SJohn Marino failure = 2;
9181e4b17023SJohn Marino if (!do_default)
9182e4b17023SJohn Marino return failure;
9183e4b17023SJohn Marino }
9184e4b17023SJohn Marino
9185e4b17023SJohn Marino type = *ptype;
9186e4b17023SJohn Marino elt = TREE_TYPE (type);
9187e4b17023SJohn Marino quals = TYPE_QUALS (strip_array_types (elt));
9188e4b17023SJohn Marino if (quals == 0)
9189e4b17023SJohn Marino unqual_elt = elt;
9190e4b17023SJohn Marino else
9191e4b17023SJohn Marino unqual_elt = c_build_qualified_type (elt, KEEP_QUAL_ADDR_SPACE (quals));
9192e4b17023SJohn Marino
9193e4b17023SJohn Marino /* Using build_distinct_type_copy and modifying things afterward instead
9194e4b17023SJohn Marino of using build_array_type to create a new type preserves all of the
9195e4b17023SJohn Marino TYPE_LANG_FLAG_? bits that the front end may have set. */
9196e4b17023SJohn Marino main_type = build_distinct_type_copy (TYPE_MAIN_VARIANT (type));
9197e4b17023SJohn Marino TREE_TYPE (main_type) = unqual_elt;
9198e4b17023SJohn Marino TYPE_DOMAIN (main_type)
9199e4b17023SJohn Marino = build_range_type (TREE_TYPE (maxindex),
9200e4b17023SJohn Marino build_int_cst (TREE_TYPE (maxindex), 0), maxindex);
9201e4b17023SJohn Marino layout_type (main_type);
9202e4b17023SJohn Marino
9203e4b17023SJohn Marino /* Make sure we have the canonical MAIN_TYPE. */
9204e4b17023SJohn Marino hashcode = iterative_hash_object (TYPE_HASH (unqual_elt), hashcode);
9205e4b17023SJohn Marino hashcode = iterative_hash_object (TYPE_HASH (TYPE_DOMAIN (main_type)),
9206e4b17023SJohn Marino hashcode);
9207e4b17023SJohn Marino main_type = type_hash_canon (hashcode, main_type);
9208e4b17023SJohn Marino
9209e4b17023SJohn Marino /* Fix the canonical type. */
9210e4b17023SJohn Marino if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (main_type))
9211e4b17023SJohn Marino || TYPE_STRUCTURAL_EQUALITY_P (TYPE_DOMAIN (main_type)))
9212e4b17023SJohn Marino SET_TYPE_STRUCTURAL_EQUALITY (main_type);
9213e4b17023SJohn Marino else if (TYPE_CANONICAL (TREE_TYPE (main_type)) != TREE_TYPE (main_type)
9214e4b17023SJohn Marino || (TYPE_CANONICAL (TYPE_DOMAIN (main_type))
9215e4b17023SJohn Marino != TYPE_DOMAIN (main_type)))
9216e4b17023SJohn Marino TYPE_CANONICAL (main_type)
9217e4b17023SJohn Marino = build_array_type (TYPE_CANONICAL (TREE_TYPE (main_type)),
9218e4b17023SJohn Marino TYPE_CANONICAL (TYPE_DOMAIN (main_type)));
9219e4b17023SJohn Marino else
9220e4b17023SJohn Marino TYPE_CANONICAL (main_type) = main_type;
9221e4b17023SJohn Marino
9222e4b17023SJohn Marino if (quals == 0)
9223e4b17023SJohn Marino type = main_type;
9224e4b17023SJohn Marino else
9225e4b17023SJohn Marino type = c_build_qualified_type (main_type, quals);
9226e4b17023SJohn Marino
9227e4b17023SJohn Marino if (COMPLETE_TYPE_P (type)
9228e4b17023SJohn Marino && TREE_CODE (TYPE_SIZE_UNIT (type)) == INTEGER_CST
9229e4b17023SJohn Marino && TREE_OVERFLOW (TYPE_SIZE_UNIT (type)))
9230e4b17023SJohn Marino {
9231e4b17023SJohn Marino error ("size of array is too large");
9232e4b17023SJohn Marino /* If we proceed with the array type as it is, we'll eventually
9233e4b17023SJohn Marino crash in tree_low_cst(). */
9234e4b17023SJohn Marino type = error_mark_node;
9235e4b17023SJohn Marino }
9236e4b17023SJohn Marino
9237e4b17023SJohn Marino *ptype = type;
9238e4b17023SJohn Marino return failure;
9239e4b17023SJohn Marino }
9240e4b17023SJohn Marino
9241e4b17023SJohn Marino /* Like c_mark_addressable but don't check register qualifier. */
9242e4b17023SJohn Marino void
c_common_mark_addressable_vec(tree t)9243e4b17023SJohn Marino c_common_mark_addressable_vec (tree t)
9244e4b17023SJohn Marino {
9245e4b17023SJohn Marino while (handled_component_p (t))
9246e4b17023SJohn Marino t = TREE_OPERAND (t, 0);
9247e4b17023SJohn Marino if (TREE_CODE (t) != VAR_DECL && TREE_CODE (t) != PARM_DECL)
9248e4b17023SJohn Marino return;
9249e4b17023SJohn Marino TREE_ADDRESSABLE (t) = 1;
9250e4b17023SJohn Marino }
9251e4b17023SJohn Marino
9252e4b17023SJohn Marino
9253e4b17023SJohn Marino
9254e4b17023SJohn Marino /* Used to help initialize the builtin-types.def table. When a type of
9255e4b17023SJohn Marino the correct size doesn't exist, use error_mark_node instead of NULL.
9256e4b17023SJohn Marino The later results in segfaults even when a decl using the type doesn't
9257e4b17023SJohn Marino get invoked. */
9258e4b17023SJohn Marino
9259e4b17023SJohn Marino tree
builtin_type_for_size(int size,bool unsignedp)9260e4b17023SJohn Marino builtin_type_for_size (int size, bool unsignedp)
9261e4b17023SJohn Marino {
9262e4b17023SJohn Marino tree type = lang_hooks.types.type_for_size (size, unsignedp);
9263e4b17023SJohn Marino return type ? type : error_mark_node;
9264e4b17023SJohn Marino }
9265e4b17023SJohn Marino
9266e4b17023SJohn Marino /* A helper function for resolve_overloaded_builtin in resolving the
9267e4b17023SJohn Marino overloaded __sync_ builtins. Returns a positive power of 2 if the
9268e4b17023SJohn Marino first operand of PARAMS is a pointer to a supported data type.
9269e4b17023SJohn Marino Returns 0 if an error is encountered. */
9270e4b17023SJohn Marino
9271e4b17023SJohn Marino static int
sync_resolve_size(tree function,VEC (tree,gc)* params)9272e4b17023SJohn Marino sync_resolve_size (tree function, VEC(tree,gc) *params)
9273e4b17023SJohn Marino {
9274e4b17023SJohn Marino tree type;
9275e4b17023SJohn Marino int size;
9276e4b17023SJohn Marino
9277e4b17023SJohn Marino if (VEC_empty (tree, params))
9278e4b17023SJohn Marino {
9279e4b17023SJohn Marino error ("too few arguments to function %qE", function);
9280e4b17023SJohn Marino return 0;
9281e4b17023SJohn Marino }
9282e4b17023SJohn Marino
9283e4b17023SJohn Marino type = TREE_TYPE (VEC_index (tree, params, 0));
9284e4b17023SJohn Marino if (TREE_CODE (type) != POINTER_TYPE)
9285e4b17023SJohn Marino goto incompatible;
9286e4b17023SJohn Marino
9287e4b17023SJohn Marino type = TREE_TYPE (type);
9288e4b17023SJohn Marino if (!INTEGRAL_TYPE_P (type) && !POINTER_TYPE_P (type))
9289e4b17023SJohn Marino goto incompatible;
9290e4b17023SJohn Marino
9291e4b17023SJohn Marino size = tree_low_cst (TYPE_SIZE_UNIT (type), 1);
9292e4b17023SJohn Marino if (size == 1 || size == 2 || size == 4 || size == 8 || size == 16)
9293e4b17023SJohn Marino return size;
9294e4b17023SJohn Marino
9295e4b17023SJohn Marino incompatible:
9296e4b17023SJohn Marino error ("incompatible type for argument %d of %qE", 1, function);
9297e4b17023SJohn Marino return 0;
9298e4b17023SJohn Marino }
9299e4b17023SJohn Marino
9300e4b17023SJohn Marino /* A helper function for resolve_overloaded_builtin. Adds casts to
9301e4b17023SJohn Marino PARAMS to make arguments match up with those of FUNCTION. Drops
9302e4b17023SJohn Marino the variadic arguments at the end. Returns false if some error
9303e4b17023SJohn Marino was encountered; true on success. */
9304e4b17023SJohn Marino
9305e4b17023SJohn Marino static bool
sync_resolve_params(location_t loc,tree orig_function,tree function,VEC (tree,gc)* params,bool orig_format)9306e4b17023SJohn Marino sync_resolve_params (location_t loc, tree orig_function, tree function,
9307e4b17023SJohn Marino VEC(tree, gc) *params, bool orig_format)
9308e4b17023SJohn Marino {
9309e4b17023SJohn Marino function_args_iterator iter;
9310e4b17023SJohn Marino tree ptype;
9311e4b17023SJohn Marino unsigned int parmnum;
9312e4b17023SJohn Marino
9313e4b17023SJohn Marino function_args_iter_init (&iter, TREE_TYPE (function));
9314e4b17023SJohn Marino /* We've declared the implementation functions to use "volatile void *"
9315e4b17023SJohn Marino as the pointer parameter, so we shouldn't get any complaints from the
9316e4b17023SJohn Marino call to check_function_arguments what ever type the user used. */
9317e4b17023SJohn Marino function_args_iter_next (&iter);
9318e4b17023SJohn Marino ptype = TREE_TYPE (TREE_TYPE (VEC_index (tree, params, 0)));
9319e4b17023SJohn Marino
9320e4b17023SJohn Marino /* For the rest of the values, we need to cast these to FTYPE, so that we
9321e4b17023SJohn Marino don't get warnings for passing pointer types, etc. */
9322e4b17023SJohn Marino parmnum = 0;
9323e4b17023SJohn Marino while (1)
9324e4b17023SJohn Marino {
9325e4b17023SJohn Marino tree val, arg_type;
9326e4b17023SJohn Marino
9327e4b17023SJohn Marino arg_type = function_args_iter_cond (&iter);
9328e4b17023SJohn Marino /* XXX void_type_node belies the abstraction. */
9329e4b17023SJohn Marino if (arg_type == void_type_node)
9330e4b17023SJohn Marino break;
9331e4b17023SJohn Marino
9332e4b17023SJohn Marino ++parmnum;
9333e4b17023SJohn Marino if (VEC_length (tree, params) <= parmnum)
9334e4b17023SJohn Marino {
9335e4b17023SJohn Marino error_at (loc, "too few arguments to function %qE", orig_function);
9336e4b17023SJohn Marino return false;
9337e4b17023SJohn Marino }
9338e4b17023SJohn Marino
9339e4b17023SJohn Marino /* Only convert parameters if arg_type is unsigned integer type with
9340e4b17023SJohn Marino new format sync routines, i.e. don't attempt to convert pointer
9341e4b17023SJohn Marino arguments (e.g. EXPECTED argument of __atomic_compare_exchange_n),
9342e4b17023SJohn Marino bool arguments (e.g. WEAK argument) or signed int arguments (memmodel
9343e4b17023SJohn Marino kinds). */
9344e4b17023SJohn Marino if (TREE_CODE (arg_type) == INTEGER_TYPE && TYPE_UNSIGNED (arg_type))
9345e4b17023SJohn Marino {
9346e4b17023SJohn Marino /* Ideally for the first conversion we'd use convert_for_assignment
9347e4b17023SJohn Marino so that we get warnings for anything that doesn't match the pointer
9348e4b17023SJohn Marino type. This isn't portable across the C and C++ front ends atm. */
9349e4b17023SJohn Marino val = VEC_index (tree, params, parmnum);
9350e4b17023SJohn Marino val = convert (ptype, val);
9351e4b17023SJohn Marino val = convert (arg_type, val);
9352e4b17023SJohn Marino VEC_replace (tree, params, parmnum, val);
9353e4b17023SJohn Marino }
9354e4b17023SJohn Marino
9355e4b17023SJohn Marino function_args_iter_next (&iter);
9356e4b17023SJohn Marino }
9357e4b17023SJohn Marino
9358e4b17023SJohn Marino /* __atomic routines are not variadic. */
9359e4b17023SJohn Marino if (!orig_format && VEC_length (tree, params) != parmnum + 1)
9360e4b17023SJohn Marino {
9361e4b17023SJohn Marino error_at (loc, "too many arguments to function %qE", orig_function);
9362e4b17023SJohn Marino return false;
9363e4b17023SJohn Marino }
9364e4b17023SJohn Marino
9365e4b17023SJohn Marino /* The definition of these primitives is variadic, with the remaining
9366e4b17023SJohn Marino being "an optional list of variables protected by the memory barrier".
9367e4b17023SJohn Marino No clue what that's supposed to mean, precisely, but we consider all
9368e4b17023SJohn Marino call-clobbered variables to be protected so we're safe. */
9369e4b17023SJohn Marino VEC_truncate (tree, params, parmnum + 1);
9370e4b17023SJohn Marino
9371e4b17023SJohn Marino return true;
9372e4b17023SJohn Marino }
9373e4b17023SJohn Marino
9374e4b17023SJohn Marino /* A helper function for resolve_overloaded_builtin. Adds a cast to
9375e4b17023SJohn Marino RESULT to make it match the type of the first pointer argument in
9376e4b17023SJohn Marino PARAMS. */
9377e4b17023SJohn Marino
9378e4b17023SJohn Marino static tree
sync_resolve_return(tree first_param,tree result,bool orig_format)9379e4b17023SJohn Marino sync_resolve_return (tree first_param, tree result, bool orig_format)
9380e4b17023SJohn Marino {
9381e4b17023SJohn Marino tree ptype = TREE_TYPE (TREE_TYPE (first_param));
9382e4b17023SJohn Marino tree rtype = TREE_TYPE (result);
9383e4b17023SJohn Marino ptype = TYPE_MAIN_VARIANT (ptype);
9384e4b17023SJohn Marino
9385e4b17023SJohn Marino /* New format doesn't require casting unless the types are the same size. */
9386e4b17023SJohn Marino if (orig_format || tree_int_cst_equal (TYPE_SIZE (ptype), TYPE_SIZE (rtype)))
9387e4b17023SJohn Marino return convert (ptype, result);
9388e4b17023SJohn Marino else
9389e4b17023SJohn Marino return result;
9390e4b17023SJohn Marino }
9391e4b17023SJohn Marino
9392e4b17023SJohn Marino /* This function verifies the PARAMS to generic atomic FUNCTION.
9393e4b17023SJohn Marino It returns the size if all the parameters are the same size, otherwise
9394e4b17023SJohn Marino 0 is returned if the parameters are invalid. */
9395e4b17023SJohn Marino
9396e4b17023SJohn Marino static int
get_atomic_generic_size(location_t loc,tree function,VEC (tree,gc)* params)9397e4b17023SJohn Marino get_atomic_generic_size (location_t loc, tree function, VEC(tree,gc) *params)
9398e4b17023SJohn Marino {
9399e4b17023SJohn Marino unsigned int n_param;
9400e4b17023SJohn Marino unsigned int n_model;
9401e4b17023SJohn Marino unsigned int x;
9402e4b17023SJohn Marino int size_0;
9403e4b17023SJohn Marino tree type_0;
9404e4b17023SJohn Marino
9405e4b17023SJohn Marino /* Determine the parameter makeup. */
9406e4b17023SJohn Marino switch (DECL_FUNCTION_CODE (function))
9407e4b17023SJohn Marino {
9408e4b17023SJohn Marino case BUILT_IN_ATOMIC_EXCHANGE:
9409e4b17023SJohn Marino n_param = 4;
9410e4b17023SJohn Marino n_model = 1;
9411e4b17023SJohn Marino break;
9412e4b17023SJohn Marino case BUILT_IN_ATOMIC_LOAD:
9413e4b17023SJohn Marino case BUILT_IN_ATOMIC_STORE:
9414e4b17023SJohn Marino n_param = 3;
9415e4b17023SJohn Marino n_model = 1;
9416e4b17023SJohn Marino break;
9417e4b17023SJohn Marino case BUILT_IN_ATOMIC_COMPARE_EXCHANGE:
9418e4b17023SJohn Marino n_param = 6;
9419e4b17023SJohn Marino n_model = 2;
9420e4b17023SJohn Marino break;
9421e4b17023SJohn Marino default:
9422e4b17023SJohn Marino gcc_unreachable ();
9423e4b17023SJohn Marino }
9424e4b17023SJohn Marino
9425e4b17023SJohn Marino if (VEC_length (tree, params) != n_param)
9426e4b17023SJohn Marino {
9427e4b17023SJohn Marino error_at (loc, "incorrect number of arguments to function %qE", function);
9428e4b17023SJohn Marino return 0;
9429e4b17023SJohn Marino }
9430e4b17023SJohn Marino
9431e4b17023SJohn Marino /* Get type of first parameter, and determine its size. */
9432e4b17023SJohn Marino type_0 = TREE_TYPE (VEC_index (tree, params, 0));
9433e4b17023SJohn Marino if (TREE_CODE (type_0) != POINTER_TYPE || VOID_TYPE_P (TREE_TYPE (type_0)))
9434e4b17023SJohn Marino {
9435e4b17023SJohn Marino error_at (loc, "argument 1 of %qE must be a non-void pointer type",
9436e4b17023SJohn Marino function);
9437e4b17023SJohn Marino return 0;
9438e4b17023SJohn Marino }
9439e4b17023SJohn Marino
9440e4b17023SJohn Marino /* Types must be compile time constant sizes. */
9441e4b17023SJohn Marino if (TREE_CODE ((TYPE_SIZE_UNIT (TREE_TYPE (type_0)))) != INTEGER_CST)
9442e4b17023SJohn Marino {
9443e4b17023SJohn Marino error_at (loc,
9444e4b17023SJohn Marino "argument 1 of %qE must be a pointer to a constant size type",
9445e4b17023SJohn Marino function);
9446e4b17023SJohn Marino return 0;
9447e4b17023SJohn Marino }
9448e4b17023SJohn Marino
9449e4b17023SJohn Marino size_0 = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (type_0)), 1);
9450e4b17023SJohn Marino
9451e4b17023SJohn Marino /* Zero size objects are not allowed. */
9452e4b17023SJohn Marino if (size_0 == 0)
9453e4b17023SJohn Marino {
9454e4b17023SJohn Marino error_at (loc,
9455e4b17023SJohn Marino "argument 1 of %qE must be a pointer to a nonzero size object",
9456e4b17023SJohn Marino function);
9457e4b17023SJohn Marino return 0;
9458e4b17023SJohn Marino }
9459e4b17023SJohn Marino
9460e4b17023SJohn Marino /* Check each other parameter is a pointer and the same size. */
9461e4b17023SJohn Marino for (x = 0; x < n_param - n_model; x++)
9462e4b17023SJohn Marino {
9463e4b17023SJohn Marino int size;
9464e4b17023SJohn Marino tree type = TREE_TYPE (VEC_index (tree, params, x));
9465e4b17023SJohn Marino /* __atomic_compare_exchange has a bool in the 4th postion, skip it. */
9466e4b17023SJohn Marino if (n_param == 6 && x == 3)
9467e4b17023SJohn Marino continue;
9468e4b17023SJohn Marino if (!POINTER_TYPE_P (type))
9469e4b17023SJohn Marino {
9470e4b17023SJohn Marino error_at (loc, "argument %d of %qE must be a pointer type", x + 1,
9471e4b17023SJohn Marino function);
9472e4b17023SJohn Marino return 0;
9473e4b17023SJohn Marino }
9474e4b17023SJohn Marino size = tree_low_cst (TYPE_SIZE_UNIT (TREE_TYPE (type)), 1);
9475e4b17023SJohn Marino if (size != size_0)
9476e4b17023SJohn Marino {
9477e4b17023SJohn Marino error_at (loc, "size mismatch in argument %d of %qE", x + 1,
9478e4b17023SJohn Marino function);
9479e4b17023SJohn Marino return 0;
9480e4b17023SJohn Marino }
9481e4b17023SJohn Marino }
9482e4b17023SJohn Marino
9483e4b17023SJohn Marino /* Check memory model parameters for validity. */
9484e4b17023SJohn Marino for (x = n_param - n_model ; x < n_param; x++)
9485e4b17023SJohn Marino {
9486e4b17023SJohn Marino tree p = VEC_index (tree, params, x);
9487e4b17023SJohn Marino if (TREE_CODE (p) == INTEGER_CST)
9488e4b17023SJohn Marino {
9489e4b17023SJohn Marino int i = tree_low_cst (p, 1);
9490e4b17023SJohn Marino if (i < 0 || i >= MEMMODEL_LAST)
9491e4b17023SJohn Marino {
9492e4b17023SJohn Marino warning_at (loc, OPT_Winvalid_memory_model,
9493e4b17023SJohn Marino "invalid memory model argument %d of %qE", x + 1,
9494e4b17023SJohn Marino function);
9495e4b17023SJohn Marino }
9496e4b17023SJohn Marino }
9497e4b17023SJohn Marino else
9498e4b17023SJohn Marino if (!INTEGRAL_TYPE_P (TREE_TYPE (p)))
9499e4b17023SJohn Marino {
9500e4b17023SJohn Marino error_at (loc, "non-integer memory model argument %d of %qE", x + 1,
9501e4b17023SJohn Marino function);
9502e4b17023SJohn Marino return 0;
9503e4b17023SJohn Marino }
9504e4b17023SJohn Marino }
9505e4b17023SJohn Marino
9506e4b17023SJohn Marino return size_0;
9507e4b17023SJohn Marino }
9508e4b17023SJohn Marino
9509e4b17023SJohn Marino
9510e4b17023SJohn Marino /* This will take an __atomic_ generic FUNCTION call, and add a size parameter N
9511e4b17023SJohn Marino at the beginning of the parameter list PARAMS representing the size of the
9512e4b17023SJohn Marino objects. This is to match the library ABI requirement. LOC is the location
9513e4b17023SJohn Marino of the function call.
9514e4b17023SJohn Marino The new function is returned if it needed rebuilding, otherwise NULL_TREE is
9515e4b17023SJohn Marino returned to allow the external call to be constructed. */
9516e4b17023SJohn Marino
9517e4b17023SJohn Marino static tree
add_atomic_size_parameter(unsigned n,location_t loc,tree function,VEC (tree,gc)* params)9518e4b17023SJohn Marino add_atomic_size_parameter (unsigned n, location_t loc, tree function,
9519e4b17023SJohn Marino VEC(tree,gc) *params)
9520e4b17023SJohn Marino {
9521e4b17023SJohn Marino tree size_node;
9522e4b17023SJohn Marino
9523e4b17023SJohn Marino /* Insert a SIZE_T parameter as the first param. If there isn't
9524e4b17023SJohn Marino enough space, allocate a new vector and recursively re-build with that. */
9525e4b17023SJohn Marino if (!VEC_space (tree, params, 1))
9526e4b17023SJohn Marino {
9527e4b17023SJohn Marino unsigned int z, len;
9528e4b17023SJohn Marino VEC(tree,gc) *vec;
9529e4b17023SJohn Marino tree f;
9530e4b17023SJohn Marino
9531e4b17023SJohn Marino len = VEC_length (tree, params);
9532e4b17023SJohn Marino vec = VEC_alloc (tree, gc, len + 1);
9533e4b17023SJohn Marino for (z = 0; z < len; z++)
9534e4b17023SJohn Marino VEC_quick_push (tree, vec, VEC_index (tree, params, z));
9535e4b17023SJohn Marino f = build_function_call_vec (loc, function, vec, NULL);
9536e4b17023SJohn Marino VEC_free (tree, gc, vec);
9537e4b17023SJohn Marino return f;
9538e4b17023SJohn Marino }
9539e4b17023SJohn Marino
9540e4b17023SJohn Marino /* Add the size parameter and leave as a function call for processing. */
9541e4b17023SJohn Marino size_node = build_int_cst (size_type_node, n);
9542e4b17023SJohn Marino VEC_quick_insert (tree, params, 0, size_node);
9543e4b17023SJohn Marino return NULL_TREE;
9544e4b17023SJohn Marino }
9545e4b17023SJohn Marino
9546e4b17023SJohn Marino
9547e4b17023SJohn Marino /* This will process an __atomic_exchange function call, determine whether it
9548e4b17023SJohn Marino needs to be mapped to the _N variation, or turned into a library call.
9549e4b17023SJohn Marino LOC is the location of the builtin call.
9550e4b17023SJohn Marino FUNCTION is the DECL that has been invoked;
9551e4b17023SJohn Marino PARAMS is the argument list for the call. The return value is non-null
9552e4b17023SJohn Marino TRUE is returned if it is translated into the proper format for a call to the
9553e4b17023SJohn Marino external library, and NEW_RETURN is set the tree for that function.
9554e4b17023SJohn Marino FALSE is returned if processing for the _N variation is required, and
9555e4b17023SJohn Marino NEW_RETURN is set to the the return value the result is copied into. */
9556e4b17023SJohn Marino static bool
resolve_overloaded_atomic_exchange(location_t loc,tree function,VEC (tree,gc)* params,tree * new_return)9557e4b17023SJohn Marino resolve_overloaded_atomic_exchange (location_t loc, tree function,
9558e4b17023SJohn Marino VEC(tree,gc) *params, tree *new_return)
9559e4b17023SJohn Marino {
9560e4b17023SJohn Marino tree p0, p1, p2, p3;
9561e4b17023SJohn Marino tree I_type, I_type_ptr;
9562e4b17023SJohn Marino int n = get_atomic_generic_size (loc, function, params);
9563e4b17023SJohn Marino
9564e4b17023SJohn Marino /* Size of 0 is an error condition. */
9565e4b17023SJohn Marino if (n == 0)
9566e4b17023SJohn Marino {
9567e4b17023SJohn Marino *new_return = error_mark_node;
9568e4b17023SJohn Marino return true;
9569e4b17023SJohn Marino }
9570e4b17023SJohn Marino
9571e4b17023SJohn Marino /* If not a lock-free size, change to the library generic format. */
9572e4b17023SJohn Marino if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
9573e4b17023SJohn Marino {
9574e4b17023SJohn Marino *new_return = add_atomic_size_parameter (n, loc, function, params);
9575e4b17023SJohn Marino return true;
9576e4b17023SJohn Marino }
9577e4b17023SJohn Marino
9578e4b17023SJohn Marino /* Otherwise there is a lockfree match, transform the call from:
9579e4b17023SJohn Marino void fn(T* mem, T* desired, T* return, model)
9580e4b17023SJohn Marino into
9581e4b17023SJohn Marino *return = (T) (fn (In* mem, (In) *desired, model)) */
9582e4b17023SJohn Marino
9583e4b17023SJohn Marino p0 = VEC_index (tree, params, 0);
9584e4b17023SJohn Marino p1 = VEC_index (tree, params, 1);
9585e4b17023SJohn Marino p2 = VEC_index (tree, params, 2);
9586e4b17023SJohn Marino p3 = VEC_index (tree, params, 3);
9587e4b17023SJohn Marino
9588e4b17023SJohn Marino /* Create pointer to appropriate size. */
9589e4b17023SJohn Marino I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
9590e4b17023SJohn Marino I_type_ptr = build_pointer_type (I_type);
9591e4b17023SJohn Marino
9592e4b17023SJohn Marino /* Convert object pointer to required type. */
9593e4b17023SJohn Marino p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
9594e4b17023SJohn Marino VEC_replace (tree, params, 0, p0);
9595e4b17023SJohn Marino /* Convert new value to required type, and dereference it. */
9596e4b17023SJohn Marino p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR);
9597e4b17023SJohn Marino p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1);
9598e4b17023SJohn Marino VEC_replace (tree, params, 1, p1);
9599e4b17023SJohn Marino
9600e4b17023SJohn Marino /* Move memory model to the 3rd position, and end param list. */
9601e4b17023SJohn Marino VEC_replace (tree, params, 2, p3);
9602e4b17023SJohn Marino VEC_truncate (tree, params, 3);
9603e4b17023SJohn Marino
9604e4b17023SJohn Marino /* Convert return pointer and dereference it for later assignment. */
9605e4b17023SJohn Marino *new_return = build_indirect_ref (loc, p2, RO_UNARY_STAR);
9606e4b17023SJohn Marino
9607e4b17023SJohn Marino return false;
9608e4b17023SJohn Marino }
9609e4b17023SJohn Marino
9610e4b17023SJohn Marino
9611e4b17023SJohn Marino /* This will process an __atomic_compare_exchange function call, determine
9612e4b17023SJohn Marino whether it needs to be mapped to the _N variation, or turned into a lib call.
9613e4b17023SJohn Marino LOC is the location of the builtin call.
9614e4b17023SJohn Marino FUNCTION is the DECL that has been invoked;
9615e4b17023SJohn Marino PARAMS is the argument list for the call. The return value is non-null
9616e4b17023SJohn Marino TRUE is returned if it is translated into the proper format for a call to the
9617e4b17023SJohn Marino external library, and NEW_RETURN is set the tree for that function.
9618e4b17023SJohn Marino FALSE is returned if processing for the _N variation is required. */
9619e4b17023SJohn Marino
9620e4b17023SJohn Marino static bool
resolve_overloaded_atomic_compare_exchange(location_t loc,tree function,VEC (tree,gc)* params,tree * new_return)9621e4b17023SJohn Marino resolve_overloaded_atomic_compare_exchange (location_t loc, tree function,
9622e4b17023SJohn Marino VEC(tree,gc) *params,
9623e4b17023SJohn Marino tree *new_return)
9624e4b17023SJohn Marino {
9625e4b17023SJohn Marino tree p0, p1, p2;
9626e4b17023SJohn Marino tree I_type, I_type_ptr;
9627e4b17023SJohn Marino int n = get_atomic_generic_size (loc, function, params);
9628e4b17023SJohn Marino
9629e4b17023SJohn Marino /* Size of 0 is an error condition. */
9630e4b17023SJohn Marino if (n == 0)
9631e4b17023SJohn Marino {
9632e4b17023SJohn Marino *new_return = error_mark_node;
9633e4b17023SJohn Marino return true;
9634e4b17023SJohn Marino }
9635e4b17023SJohn Marino
9636e4b17023SJohn Marino /* If not a lock-free size, change to the library generic format. */
9637e4b17023SJohn Marino if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
9638e4b17023SJohn Marino {
9639e4b17023SJohn Marino /* The library generic format does not have the weak parameter, so
9640e4b17023SJohn Marino remove it from the param list. Since a parameter has been removed,
9641e4b17023SJohn Marino we can be sure that there is room for the SIZE_T parameter, meaning
9642e4b17023SJohn Marino there will not be a recursive rebuilding of the parameter list, so
9643e4b17023SJohn Marino there is no danger this will be done twice. */
9644e4b17023SJohn Marino if (n > 0)
9645e4b17023SJohn Marino {
9646e4b17023SJohn Marino VEC_replace (tree, params, 3, VEC_index (tree, params, 4));
9647e4b17023SJohn Marino VEC_replace (tree, params, 4, VEC_index (tree, params, 5));
9648e4b17023SJohn Marino VEC_truncate (tree, params, 5);
9649e4b17023SJohn Marino }
9650e4b17023SJohn Marino *new_return = add_atomic_size_parameter (n, loc, function, params);
9651e4b17023SJohn Marino return true;
9652e4b17023SJohn Marino }
9653e4b17023SJohn Marino
9654e4b17023SJohn Marino /* Otherwise, there is a match, so the call needs to be transformed from:
9655e4b17023SJohn Marino bool fn(T* mem, T* desired, T* return, weak, success, failure)
9656e4b17023SJohn Marino into
9657e4b17023SJohn Marino bool fn ((In *)mem, (In *)expected, (In) *desired, weak, succ, fail) */
9658e4b17023SJohn Marino
9659e4b17023SJohn Marino p0 = VEC_index (tree, params, 0);
9660e4b17023SJohn Marino p1 = VEC_index (tree, params, 1);
9661e4b17023SJohn Marino p2 = VEC_index (tree, params, 2);
9662e4b17023SJohn Marino
9663e4b17023SJohn Marino /* Create pointer to appropriate size. */
9664e4b17023SJohn Marino I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
9665e4b17023SJohn Marino I_type_ptr = build_pointer_type (I_type);
9666e4b17023SJohn Marino
9667e4b17023SJohn Marino /* Convert object pointer to required type. */
9668e4b17023SJohn Marino p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
9669e4b17023SJohn Marino VEC_replace (tree, params, 0, p0);
9670e4b17023SJohn Marino
9671e4b17023SJohn Marino /* Convert expected pointer to required type. */
9672e4b17023SJohn Marino p1 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p1);
9673e4b17023SJohn Marino VEC_replace (tree, params, 1, p1);
9674e4b17023SJohn Marino
9675e4b17023SJohn Marino /* Convert desired value to required type, and dereference it. */
9676e4b17023SJohn Marino p2 = build_indirect_ref (loc, p2, RO_UNARY_STAR);
9677e4b17023SJohn Marino p2 = build1 (VIEW_CONVERT_EXPR, I_type, p2);
9678e4b17023SJohn Marino VEC_replace (tree, params, 2, p2);
9679e4b17023SJohn Marino
9680e4b17023SJohn Marino /* The rest of the parameters are fine. NULL means no special return value
9681e4b17023SJohn Marino processing.*/
9682e4b17023SJohn Marino *new_return = NULL;
9683e4b17023SJohn Marino return false;
9684e4b17023SJohn Marino }
9685e4b17023SJohn Marino
9686e4b17023SJohn Marino
9687e4b17023SJohn Marino /* This will process an __atomic_load function call, determine whether it
9688e4b17023SJohn Marino needs to be mapped to the _N variation, or turned into a library call.
9689e4b17023SJohn Marino LOC is the location of the builtin call.
9690e4b17023SJohn Marino FUNCTION is the DECL that has been invoked;
9691e4b17023SJohn Marino PARAMS is the argument list for the call. The return value is non-null
9692e4b17023SJohn Marino TRUE is returned if it is translated into the proper format for a call to the
9693e4b17023SJohn Marino external library, and NEW_RETURN is set the tree for that function.
9694e4b17023SJohn Marino FALSE is returned if processing for the _N variation is required, and
9695e4b17023SJohn Marino NEW_RETURN is set to the the return value the result is copied into. */
9696e4b17023SJohn Marino
9697e4b17023SJohn Marino static bool
resolve_overloaded_atomic_load(location_t loc,tree function,VEC (tree,gc)* params,tree * new_return)9698e4b17023SJohn Marino resolve_overloaded_atomic_load (location_t loc, tree function,
9699e4b17023SJohn Marino VEC(tree,gc) *params, tree *new_return)
9700e4b17023SJohn Marino {
9701e4b17023SJohn Marino tree p0, p1, p2;
9702e4b17023SJohn Marino tree I_type, I_type_ptr;
9703e4b17023SJohn Marino int n = get_atomic_generic_size (loc, function, params);
9704e4b17023SJohn Marino
9705e4b17023SJohn Marino /* Size of 0 is an error condition. */
9706e4b17023SJohn Marino if (n == 0)
9707e4b17023SJohn Marino {
9708e4b17023SJohn Marino *new_return = error_mark_node;
9709e4b17023SJohn Marino return true;
9710e4b17023SJohn Marino }
9711e4b17023SJohn Marino
9712e4b17023SJohn Marino /* If not a lock-free size, change to the library generic format. */
9713e4b17023SJohn Marino if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
9714e4b17023SJohn Marino {
9715e4b17023SJohn Marino *new_return = add_atomic_size_parameter (n, loc, function, params);
9716e4b17023SJohn Marino return true;
9717e4b17023SJohn Marino }
9718e4b17023SJohn Marino
9719e4b17023SJohn Marino /* Otherwise, there is a match, so the call needs to be transformed from:
9720e4b17023SJohn Marino void fn(T* mem, T* return, model)
9721e4b17023SJohn Marino into
9722e4b17023SJohn Marino *return = (T) (fn ((In *) mem, model)) */
9723e4b17023SJohn Marino
9724e4b17023SJohn Marino p0 = VEC_index (tree, params, 0);
9725e4b17023SJohn Marino p1 = VEC_index (tree, params, 1);
9726e4b17023SJohn Marino p2 = VEC_index (tree, params, 2);
9727e4b17023SJohn Marino
9728e4b17023SJohn Marino /* Create pointer to appropriate size. */
9729e4b17023SJohn Marino I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
9730e4b17023SJohn Marino I_type_ptr = build_pointer_type (I_type);
9731e4b17023SJohn Marino
9732e4b17023SJohn Marino /* Convert object pointer to required type. */
9733e4b17023SJohn Marino p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
9734e4b17023SJohn Marino VEC_replace (tree, params, 0, p0);
9735e4b17023SJohn Marino
9736e4b17023SJohn Marino /* Move memory model to the 2nd position, and end param list. */
9737e4b17023SJohn Marino VEC_replace (tree, params, 1, p2);
9738e4b17023SJohn Marino VEC_truncate (tree, params, 2);
9739e4b17023SJohn Marino
9740e4b17023SJohn Marino /* Convert return pointer and dereference it for later assignment. */
9741e4b17023SJohn Marino *new_return = build_indirect_ref (loc, p1, RO_UNARY_STAR);
9742e4b17023SJohn Marino
9743e4b17023SJohn Marino return false;
9744e4b17023SJohn Marino }
9745e4b17023SJohn Marino
9746e4b17023SJohn Marino
9747e4b17023SJohn Marino /* This will process an __atomic_store function call, determine whether it
9748e4b17023SJohn Marino needs to be mapped to the _N variation, or turned into a library call.
9749e4b17023SJohn Marino LOC is the location of the builtin call.
9750e4b17023SJohn Marino FUNCTION is the DECL that has been invoked;
9751e4b17023SJohn Marino PARAMS is the argument list for the call. The return value is non-null
9752e4b17023SJohn Marino TRUE is returned if it is translated into the proper format for a call to the
9753e4b17023SJohn Marino external library, and NEW_RETURN is set the tree for that function.
9754e4b17023SJohn Marino FALSE is returned if processing for the _N variation is required, and
9755e4b17023SJohn Marino NEW_RETURN is set to the the return value the result is copied into. */
9756e4b17023SJohn Marino
9757e4b17023SJohn Marino static bool
resolve_overloaded_atomic_store(location_t loc,tree function,VEC (tree,gc)* params,tree * new_return)9758e4b17023SJohn Marino resolve_overloaded_atomic_store (location_t loc, tree function,
9759e4b17023SJohn Marino VEC(tree,gc) *params, tree *new_return)
9760e4b17023SJohn Marino {
9761e4b17023SJohn Marino tree p0, p1;
9762e4b17023SJohn Marino tree I_type, I_type_ptr;
9763e4b17023SJohn Marino int n = get_atomic_generic_size (loc, function, params);
9764e4b17023SJohn Marino
9765e4b17023SJohn Marino /* Size of 0 is an error condition. */
9766e4b17023SJohn Marino if (n == 0)
9767e4b17023SJohn Marino {
9768e4b17023SJohn Marino *new_return = error_mark_node;
9769e4b17023SJohn Marino return true;
9770e4b17023SJohn Marino }
9771e4b17023SJohn Marino
9772e4b17023SJohn Marino /* If not a lock-free size, change to the library generic format. */
9773e4b17023SJohn Marino if (n != 1 && n != 2 && n != 4 && n != 8 && n != 16)
9774e4b17023SJohn Marino {
9775e4b17023SJohn Marino *new_return = add_atomic_size_parameter (n, loc, function, params);
9776e4b17023SJohn Marino return true;
9777e4b17023SJohn Marino }
9778e4b17023SJohn Marino
9779e4b17023SJohn Marino /* Otherwise, there is a match, so the call needs to be transformed from:
9780e4b17023SJohn Marino void fn(T* mem, T* value, model)
9781e4b17023SJohn Marino into
9782e4b17023SJohn Marino fn ((In *) mem, (In) *value, model) */
9783e4b17023SJohn Marino
9784e4b17023SJohn Marino p0 = VEC_index (tree, params, 0);
9785e4b17023SJohn Marino p1 = VEC_index (tree, params, 1);
9786e4b17023SJohn Marino
9787e4b17023SJohn Marino /* Create pointer to appropriate size. */
9788e4b17023SJohn Marino I_type = builtin_type_for_size (BITS_PER_UNIT * n, 1);
9789e4b17023SJohn Marino I_type_ptr = build_pointer_type (I_type);
9790e4b17023SJohn Marino
9791e4b17023SJohn Marino /* Convert object pointer to required type. */
9792e4b17023SJohn Marino p0 = build1 (VIEW_CONVERT_EXPR, I_type_ptr, p0);
9793e4b17023SJohn Marino VEC_replace (tree, params, 0, p0);
9794e4b17023SJohn Marino
9795e4b17023SJohn Marino /* Convert new value to required type, and dereference it. */
9796e4b17023SJohn Marino p1 = build_indirect_ref (loc, p1, RO_UNARY_STAR);
9797e4b17023SJohn Marino p1 = build1 (VIEW_CONVERT_EXPR, I_type, p1);
9798e4b17023SJohn Marino VEC_replace (tree, params, 1, p1);
9799e4b17023SJohn Marino
9800e4b17023SJohn Marino /* The memory model is in the right spot already. Return is void. */
9801e4b17023SJohn Marino *new_return = NULL_TREE;
9802e4b17023SJohn Marino
9803e4b17023SJohn Marino return false;
9804e4b17023SJohn Marino }
9805e4b17023SJohn Marino
9806e4b17023SJohn Marino
9807e4b17023SJohn Marino /* Some builtin functions are placeholders for other expressions. This
9808e4b17023SJohn Marino function should be called immediately after parsing the call expression
9809e4b17023SJohn Marino before surrounding code has committed to the type of the expression.
9810e4b17023SJohn Marino
9811e4b17023SJohn Marino LOC is the location of the builtin call.
9812e4b17023SJohn Marino
9813e4b17023SJohn Marino FUNCTION is the DECL that has been invoked; it is known to be a builtin.
9814e4b17023SJohn Marino PARAMS is the argument list for the call. The return value is non-null
9815e4b17023SJohn Marino when expansion is complete, and null if normal processing should
9816e4b17023SJohn Marino continue. */
9817e4b17023SJohn Marino
9818e4b17023SJohn Marino tree
resolve_overloaded_builtin(location_t loc,tree function,VEC (tree,gc)* params)9819e4b17023SJohn Marino resolve_overloaded_builtin (location_t loc, tree function, VEC(tree,gc) *params)
9820e4b17023SJohn Marino {
9821e4b17023SJohn Marino enum built_in_function orig_code = DECL_FUNCTION_CODE (function);
9822e4b17023SJohn Marino bool orig_format = true;
9823e4b17023SJohn Marino tree new_return = NULL_TREE;
9824e4b17023SJohn Marino
9825e4b17023SJohn Marino switch (DECL_BUILT_IN_CLASS (function))
9826e4b17023SJohn Marino {
9827e4b17023SJohn Marino case BUILT_IN_NORMAL:
9828e4b17023SJohn Marino break;
9829e4b17023SJohn Marino case BUILT_IN_MD:
9830e4b17023SJohn Marino if (targetm.resolve_overloaded_builtin)
9831e4b17023SJohn Marino return targetm.resolve_overloaded_builtin (loc, function, params);
9832e4b17023SJohn Marino else
9833e4b17023SJohn Marino return NULL_TREE;
9834e4b17023SJohn Marino default:
9835e4b17023SJohn Marino return NULL_TREE;
9836e4b17023SJohn Marino }
9837e4b17023SJohn Marino
9838e4b17023SJohn Marino /* Handle BUILT_IN_NORMAL here. */
9839e4b17023SJohn Marino switch (orig_code)
9840e4b17023SJohn Marino {
9841e4b17023SJohn Marino case BUILT_IN_ATOMIC_EXCHANGE:
9842e4b17023SJohn Marino case BUILT_IN_ATOMIC_COMPARE_EXCHANGE:
9843e4b17023SJohn Marino case BUILT_IN_ATOMIC_LOAD:
9844e4b17023SJohn Marino case BUILT_IN_ATOMIC_STORE:
9845e4b17023SJohn Marino {
9846e4b17023SJohn Marino /* Handle these 4 together so that they can fall through to the next
9847e4b17023SJohn Marino case if the call is transformed to an _N variant. */
9848e4b17023SJohn Marino switch (orig_code)
9849e4b17023SJohn Marino {
9850e4b17023SJohn Marino case BUILT_IN_ATOMIC_EXCHANGE:
9851e4b17023SJohn Marino {
9852e4b17023SJohn Marino if (resolve_overloaded_atomic_exchange (loc, function, params,
9853e4b17023SJohn Marino &new_return))
9854e4b17023SJohn Marino return new_return;
9855e4b17023SJohn Marino /* Change to the _N variant. */
9856e4b17023SJohn Marino orig_code = BUILT_IN_ATOMIC_EXCHANGE_N;
9857e4b17023SJohn Marino break;
9858e4b17023SJohn Marino }
9859e4b17023SJohn Marino
9860e4b17023SJohn Marino case BUILT_IN_ATOMIC_COMPARE_EXCHANGE:
9861e4b17023SJohn Marino {
9862e4b17023SJohn Marino if (resolve_overloaded_atomic_compare_exchange (loc, function,
9863e4b17023SJohn Marino params,
9864e4b17023SJohn Marino &new_return))
9865e4b17023SJohn Marino return new_return;
9866e4b17023SJohn Marino /* Change to the _N variant. */
9867e4b17023SJohn Marino orig_code = BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N;
9868e4b17023SJohn Marino break;
9869e4b17023SJohn Marino }
9870e4b17023SJohn Marino case BUILT_IN_ATOMIC_LOAD:
9871e4b17023SJohn Marino {
9872e4b17023SJohn Marino if (resolve_overloaded_atomic_load (loc, function, params,
9873e4b17023SJohn Marino &new_return))
9874e4b17023SJohn Marino return new_return;
9875e4b17023SJohn Marino /* Change to the _N variant. */
9876e4b17023SJohn Marino orig_code = BUILT_IN_ATOMIC_LOAD_N;
9877e4b17023SJohn Marino break;
9878e4b17023SJohn Marino }
9879e4b17023SJohn Marino case BUILT_IN_ATOMIC_STORE:
9880e4b17023SJohn Marino {
9881e4b17023SJohn Marino if (resolve_overloaded_atomic_store (loc, function, params,
9882e4b17023SJohn Marino &new_return))
9883e4b17023SJohn Marino return new_return;
9884e4b17023SJohn Marino /* Change to the _N variant. */
9885e4b17023SJohn Marino orig_code = BUILT_IN_ATOMIC_STORE_N;
9886e4b17023SJohn Marino break;
9887e4b17023SJohn Marino }
9888e4b17023SJohn Marino default:
9889e4b17023SJohn Marino gcc_unreachable ();
9890e4b17023SJohn Marino }
9891e4b17023SJohn Marino /* Fallthrough to the normal processing. */
9892e4b17023SJohn Marino }
9893e4b17023SJohn Marino case BUILT_IN_ATOMIC_EXCHANGE_N:
9894e4b17023SJohn Marino case BUILT_IN_ATOMIC_COMPARE_EXCHANGE_N:
9895e4b17023SJohn Marino case BUILT_IN_ATOMIC_LOAD_N:
9896e4b17023SJohn Marino case BUILT_IN_ATOMIC_STORE_N:
9897e4b17023SJohn Marino case BUILT_IN_ATOMIC_ADD_FETCH_N:
9898e4b17023SJohn Marino case BUILT_IN_ATOMIC_SUB_FETCH_N:
9899e4b17023SJohn Marino case BUILT_IN_ATOMIC_AND_FETCH_N:
9900e4b17023SJohn Marino case BUILT_IN_ATOMIC_NAND_FETCH_N:
9901e4b17023SJohn Marino case BUILT_IN_ATOMIC_XOR_FETCH_N:
9902e4b17023SJohn Marino case BUILT_IN_ATOMIC_OR_FETCH_N:
9903e4b17023SJohn Marino case BUILT_IN_ATOMIC_FETCH_ADD_N:
9904e4b17023SJohn Marino case BUILT_IN_ATOMIC_FETCH_SUB_N:
9905e4b17023SJohn Marino case BUILT_IN_ATOMIC_FETCH_AND_N:
9906e4b17023SJohn Marino case BUILT_IN_ATOMIC_FETCH_NAND_N:
9907e4b17023SJohn Marino case BUILT_IN_ATOMIC_FETCH_XOR_N:
9908e4b17023SJohn Marino case BUILT_IN_ATOMIC_FETCH_OR_N:
9909e4b17023SJohn Marino {
9910e4b17023SJohn Marino orig_format = false;
9911e4b17023SJohn Marino /* Fallthru for parameter processing. */
9912e4b17023SJohn Marino }
9913e4b17023SJohn Marino case BUILT_IN_SYNC_FETCH_AND_ADD_N:
9914e4b17023SJohn Marino case BUILT_IN_SYNC_FETCH_AND_SUB_N:
9915e4b17023SJohn Marino case BUILT_IN_SYNC_FETCH_AND_OR_N:
9916e4b17023SJohn Marino case BUILT_IN_SYNC_FETCH_AND_AND_N:
9917e4b17023SJohn Marino case BUILT_IN_SYNC_FETCH_AND_XOR_N:
9918e4b17023SJohn Marino case BUILT_IN_SYNC_FETCH_AND_NAND_N:
9919e4b17023SJohn Marino case BUILT_IN_SYNC_ADD_AND_FETCH_N:
9920e4b17023SJohn Marino case BUILT_IN_SYNC_SUB_AND_FETCH_N:
9921e4b17023SJohn Marino case BUILT_IN_SYNC_OR_AND_FETCH_N:
9922e4b17023SJohn Marino case BUILT_IN_SYNC_AND_AND_FETCH_N:
9923e4b17023SJohn Marino case BUILT_IN_SYNC_XOR_AND_FETCH_N:
9924e4b17023SJohn Marino case BUILT_IN_SYNC_NAND_AND_FETCH_N:
9925e4b17023SJohn Marino case BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_N:
9926e4b17023SJohn Marino case BUILT_IN_SYNC_VAL_COMPARE_AND_SWAP_N:
9927e4b17023SJohn Marino case BUILT_IN_SYNC_LOCK_TEST_AND_SET_N:
9928e4b17023SJohn Marino case BUILT_IN_SYNC_LOCK_RELEASE_N:
9929e4b17023SJohn Marino {
9930e4b17023SJohn Marino int n = sync_resolve_size (function, params);
9931e4b17023SJohn Marino tree new_function, first_param, result;
9932e4b17023SJohn Marino enum built_in_function fncode;
9933e4b17023SJohn Marino
9934e4b17023SJohn Marino if (n == 0)
9935e4b17023SJohn Marino return error_mark_node;
9936e4b17023SJohn Marino
9937e4b17023SJohn Marino fncode = (enum built_in_function)((int)orig_code + exact_log2 (n) + 1);
9938e4b17023SJohn Marino new_function = builtin_decl_explicit (fncode);
9939e4b17023SJohn Marino if (!sync_resolve_params (loc, function, new_function, params,
9940e4b17023SJohn Marino orig_format))
9941e4b17023SJohn Marino return error_mark_node;
9942e4b17023SJohn Marino
9943e4b17023SJohn Marino first_param = VEC_index (tree, params, 0);
9944e4b17023SJohn Marino result = build_function_call_vec (loc, new_function, params, NULL);
9945e4b17023SJohn Marino if (result == error_mark_node)
9946e4b17023SJohn Marino return result;
9947e4b17023SJohn Marino if (orig_code != BUILT_IN_SYNC_BOOL_COMPARE_AND_SWAP_N
9948e4b17023SJohn Marino && orig_code != BUILT_IN_SYNC_LOCK_RELEASE_N
9949e4b17023SJohn Marino && orig_code != BUILT_IN_ATOMIC_STORE_N)
9950e4b17023SJohn Marino result = sync_resolve_return (first_param, result, orig_format);
9951e4b17023SJohn Marino
9952e4b17023SJohn Marino /* If new_return is set, assign function to that expr and cast the
9953e4b17023SJohn Marino result to void since the generic interface returned void. */
9954e4b17023SJohn Marino if (new_return)
9955e4b17023SJohn Marino {
9956e4b17023SJohn Marino /* Cast function result from I{1,2,4,8,16} to the required type. */
9957e4b17023SJohn Marino result = build1 (VIEW_CONVERT_EXPR, TREE_TYPE (new_return), result);
9958e4b17023SJohn Marino result = build2 (MODIFY_EXPR, TREE_TYPE (new_return), new_return,
9959e4b17023SJohn Marino result);
9960e4b17023SJohn Marino TREE_SIDE_EFFECTS (result) = 1;
9961e4b17023SJohn Marino protected_set_expr_location (result, loc);
9962e4b17023SJohn Marino result = convert (void_type_node, result);
9963e4b17023SJohn Marino }
9964e4b17023SJohn Marino return result;
9965e4b17023SJohn Marino }
9966e4b17023SJohn Marino
9967e4b17023SJohn Marino default:
9968e4b17023SJohn Marino return NULL_TREE;
9969e4b17023SJohn Marino }
9970e4b17023SJohn Marino }
9971e4b17023SJohn Marino
9972e4b17023SJohn Marino /* Ignoring their sign, return true if two scalar types are the same. */
9973e4b17023SJohn Marino bool
same_scalar_type_ignoring_signedness(tree t1,tree t2)9974e4b17023SJohn Marino same_scalar_type_ignoring_signedness (tree t1, tree t2)
9975e4b17023SJohn Marino {
9976e4b17023SJohn Marino enum tree_code c1 = TREE_CODE (t1), c2 = TREE_CODE (t2);
9977e4b17023SJohn Marino
9978e4b17023SJohn Marino gcc_assert ((c1 == INTEGER_TYPE || c1 == REAL_TYPE || c1 == FIXED_POINT_TYPE)
9979e4b17023SJohn Marino && (c2 == INTEGER_TYPE || c2 == REAL_TYPE
9980e4b17023SJohn Marino || c2 == FIXED_POINT_TYPE));
9981e4b17023SJohn Marino
9982e4b17023SJohn Marino /* Equality works here because c_common_signed_type uses
9983e4b17023SJohn Marino TYPE_MAIN_VARIANT. */
9984e4b17023SJohn Marino return c_common_signed_type (t1)
9985e4b17023SJohn Marino == c_common_signed_type (t2);
9986e4b17023SJohn Marino }
9987e4b17023SJohn Marino
9988e4b17023SJohn Marino /* Check for missing format attributes on function pointers. LTYPE is
9989e4b17023SJohn Marino the new type or left-hand side type. RTYPE is the old type or
9990e4b17023SJohn Marino right-hand side type. Returns TRUE if LTYPE is missing the desired
9991e4b17023SJohn Marino attribute. */
9992e4b17023SJohn Marino
9993e4b17023SJohn Marino bool
check_missing_format_attribute(tree ltype,tree rtype)9994e4b17023SJohn Marino check_missing_format_attribute (tree ltype, tree rtype)
9995e4b17023SJohn Marino {
9996e4b17023SJohn Marino tree const ttr = TREE_TYPE (rtype), ttl = TREE_TYPE (ltype);
9997e4b17023SJohn Marino tree ra;
9998e4b17023SJohn Marino
9999e4b17023SJohn Marino for (ra = TYPE_ATTRIBUTES (ttr); ra; ra = TREE_CHAIN (ra))
10000e4b17023SJohn Marino if (is_attribute_p ("format", TREE_PURPOSE (ra)))
10001e4b17023SJohn Marino break;
10002e4b17023SJohn Marino if (ra)
10003e4b17023SJohn Marino {
10004e4b17023SJohn Marino tree la;
10005e4b17023SJohn Marino for (la = TYPE_ATTRIBUTES (ttl); la; la = TREE_CHAIN (la))
10006e4b17023SJohn Marino if (is_attribute_p ("format", TREE_PURPOSE (la)))
10007e4b17023SJohn Marino break;
10008e4b17023SJohn Marino return !la;
10009e4b17023SJohn Marino }
10010e4b17023SJohn Marino else
10011e4b17023SJohn Marino return false;
10012e4b17023SJohn Marino }
10013e4b17023SJohn Marino
10014e4b17023SJohn Marino /* Subscripting with type char is likely to lose on a machine where
10015e4b17023SJohn Marino chars are signed. So warn on any machine, but optionally. Don't
10016e4b17023SJohn Marino warn for unsigned char since that type is safe. Don't warn for
10017e4b17023SJohn Marino signed char because anyone who uses that must have done so
10018e4b17023SJohn Marino deliberately. Furthermore, we reduce the false positive load by
10019e4b17023SJohn Marino warning only for non-constant value of type char. */
10020e4b17023SJohn Marino
10021e4b17023SJohn Marino void
warn_array_subscript_with_type_char(tree index)10022e4b17023SJohn Marino warn_array_subscript_with_type_char (tree index)
10023e4b17023SJohn Marino {
10024e4b17023SJohn Marino if (TYPE_MAIN_VARIANT (TREE_TYPE (index)) == char_type_node
10025e4b17023SJohn Marino && TREE_CODE (index) != INTEGER_CST)
10026e4b17023SJohn Marino warning (OPT_Wchar_subscripts, "array subscript has type %<char%>");
10027e4b17023SJohn Marino }
10028e4b17023SJohn Marino
10029e4b17023SJohn Marino /* Implement -Wparentheses for the unexpected C precedence rules, to
10030e4b17023SJohn Marino cover cases like x + y << z which readers are likely to
10031e4b17023SJohn Marino misinterpret. We have seen an expression in which CODE is a binary
10032e4b17023SJohn Marino operator used to combine expressions ARG_LEFT and ARG_RIGHT, which
10033e4b17023SJohn Marino before folding had CODE_LEFT and CODE_RIGHT. CODE_LEFT and
10034e4b17023SJohn Marino CODE_RIGHT may be ERROR_MARK, which means that that side of the
10035e4b17023SJohn Marino expression was not formed using a binary or unary operator, or it
10036e4b17023SJohn Marino was enclosed in parentheses. */
10037e4b17023SJohn Marino
10038e4b17023SJohn Marino void
warn_about_parentheses(enum tree_code code,enum tree_code code_left,tree arg_left,enum tree_code code_right,tree arg_right)10039e4b17023SJohn Marino warn_about_parentheses (enum tree_code code,
10040e4b17023SJohn Marino enum tree_code code_left, tree arg_left,
10041e4b17023SJohn Marino enum tree_code code_right, tree arg_right)
10042e4b17023SJohn Marino {
10043e4b17023SJohn Marino if (!warn_parentheses)
10044e4b17023SJohn Marino return;
10045e4b17023SJohn Marino
10046e4b17023SJohn Marino /* This macro tests that the expression ARG with original tree code
10047e4b17023SJohn Marino CODE appears to be a boolean expression. or the result of folding a
10048e4b17023SJohn Marino boolean expression. */
10049e4b17023SJohn Marino #define APPEARS_TO_BE_BOOLEAN_EXPR_P(CODE, ARG) \
10050e4b17023SJohn Marino (truth_value_p (TREE_CODE (ARG)) \
10051e4b17023SJohn Marino || TREE_CODE (TREE_TYPE (ARG)) == BOOLEAN_TYPE \
10052e4b17023SJohn Marino /* Folding may create 0 or 1 integers from other expressions. */ \
10053e4b17023SJohn Marino || ((CODE) != INTEGER_CST \
10054e4b17023SJohn Marino && (integer_onep (ARG) || integer_zerop (ARG))))
10055e4b17023SJohn Marino
10056e4b17023SJohn Marino switch (code)
10057e4b17023SJohn Marino {
10058e4b17023SJohn Marino case LSHIFT_EXPR:
10059e4b17023SJohn Marino if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
10060e4b17023SJohn Marino warning (OPT_Wparentheses,
10061e4b17023SJohn Marino "suggest parentheses around %<+%> inside %<<<%>");
10062e4b17023SJohn Marino else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
10063e4b17023SJohn Marino warning (OPT_Wparentheses,
10064e4b17023SJohn Marino "suggest parentheses around %<-%> inside %<<<%>");
10065e4b17023SJohn Marino return;
10066e4b17023SJohn Marino
10067e4b17023SJohn Marino case RSHIFT_EXPR:
10068e4b17023SJohn Marino if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
10069e4b17023SJohn Marino warning (OPT_Wparentheses,
10070e4b17023SJohn Marino "suggest parentheses around %<+%> inside %<>>%>");
10071e4b17023SJohn Marino else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
10072e4b17023SJohn Marino warning (OPT_Wparentheses,
10073e4b17023SJohn Marino "suggest parentheses around %<-%> inside %<>>%>");
10074e4b17023SJohn Marino return;
10075e4b17023SJohn Marino
10076e4b17023SJohn Marino case TRUTH_ORIF_EXPR:
10077e4b17023SJohn Marino if (code_left == TRUTH_ANDIF_EXPR || code_right == TRUTH_ANDIF_EXPR)
10078e4b17023SJohn Marino warning (OPT_Wparentheses,
10079e4b17023SJohn Marino "suggest parentheses around %<&&%> within %<||%>");
10080e4b17023SJohn Marino return;
10081e4b17023SJohn Marino
10082e4b17023SJohn Marino case BIT_IOR_EXPR:
10083e4b17023SJohn Marino if (code_left == BIT_AND_EXPR || code_left == BIT_XOR_EXPR
10084e4b17023SJohn Marino || code_left == PLUS_EXPR || code_left == MINUS_EXPR
10085e4b17023SJohn Marino || code_right == BIT_AND_EXPR || code_right == BIT_XOR_EXPR
10086e4b17023SJohn Marino || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
10087e4b17023SJohn Marino warning (OPT_Wparentheses,
10088e4b17023SJohn Marino "suggest parentheses around arithmetic in operand of %<|%>");
10089e4b17023SJohn Marino /* Check cases like x|y==z */
10090e4b17023SJohn Marino else if (TREE_CODE_CLASS (code_left) == tcc_comparison
10091e4b17023SJohn Marino || TREE_CODE_CLASS (code_right) == tcc_comparison)
10092e4b17023SJohn Marino warning (OPT_Wparentheses,
10093e4b17023SJohn Marino "suggest parentheses around comparison in operand of %<|%>");
10094e4b17023SJohn Marino /* Check cases like !x | y */
10095e4b17023SJohn Marino else if (code_left == TRUTH_NOT_EXPR
10096e4b17023SJohn Marino && !APPEARS_TO_BE_BOOLEAN_EXPR_P (code_right, arg_right))
10097e4b17023SJohn Marino warning (OPT_Wparentheses, "suggest parentheses around operand of "
10098e4b17023SJohn Marino "%<!%> or change %<|%> to %<||%> or %<!%> to %<~%>");
10099e4b17023SJohn Marino return;
10100e4b17023SJohn Marino
10101e4b17023SJohn Marino case BIT_XOR_EXPR:
10102e4b17023SJohn Marino if (code_left == BIT_AND_EXPR
10103e4b17023SJohn Marino || code_left == PLUS_EXPR || code_left == MINUS_EXPR
10104e4b17023SJohn Marino || code_right == BIT_AND_EXPR
10105e4b17023SJohn Marino || code_right == PLUS_EXPR || code_right == MINUS_EXPR)
10106e4b17023SJohn Marino warning (OPT_Wparentheses,
10107e4b17023SJohn Marino "suggest parentheses around arithmetic in operand of %<^%>");
10108e4b17023SJohn Marino /* Check cases like x^y==z */
10109e4b17023SJohn Marino else if (TREE_CODE_CLASS (code_left) == tcc_comparison
10110e4b17023SJohn Marino || TREE_CODE_CLASS (code_right) == tcc_comparison)
10111e4b17023SJohn Marino warning (OPT_Wparentheses,
10112e4b17023SJohn Marino "suggest parentheses around comparison in operand of %<^%>");
10113e4b17023SJohn Marino return;
10114e4b17023SJohn Marino
10115e4b17023SJohn Marino case BIT_AND_EXPR:
10116e4b17023SJohn Marino if (code_left == PLUS_EXPR || code_right == PLUS_EXPR)
10117e4b17023SJohn Marino warning (OPT_Wparentheses,
10118e4b17023SJohn Marino "suggest parentheses around %<+%> in operand of %<&%>");
10119e4b17023SJohn Marino else if (code_left == MINUS_EXPR || code_right == MINUS_EXPR)
10120e4b17023SJohn Marino warning (OPT_Wparentheses,
10121e4b17023SJohn Marino "suggest parentheses around %<-%> in operand of %<&%>");
10122e4b17023SJohn Marino /* Check cases like x&y==z */
10123e4b17023SJohn Marino else if (TREE_CODE_CLASS (code_left) == tcc_comparison
10124e4b17023SJohn Marino || TREE_CODE_CLASS (code_right) == tcc_comparison)
10125e4b17023SJohn Marino warning (OPT_Wparentheses,
10126e4b17023SJohn Marino "suggest parentheses around comparison in operand of %<&%>");
10127e4b17023SJohn Marino /* Check cases like !x & y */
10128e4b17023SJohn Marino else if (code_left == TRUTH_NOT_EXPR
10129e4b17023SJohn Marino && !APPEARS_TO_BE_BOOLEAN_EXPR_P (code_right, arg_right))
10130e4b17023SJohn Marino warning (OPT_Wparentheses, "suggest parentheses around operand of "
10131e4b17023SJohn Marino "%<!%> or change %<&%> to %<&&%> or %<!%> to %<~%>");
10132e4b17023SJohn Marino return;
10133e4b17023SJohn Marino
10134e4b17023SJohn Marino case EQ_EXPR:
10135e4b17023SJohn Marino if (TREE_CODE_CLASS (code_left) == tcc_comparison
10136e4b17023SJohn Marino || TREE_CODE_CLASS (code_right) == tcc_comparison)
10137e4b17023SJohn Marino warning (OPT_Wparentheses,
10138e4b17023SJohn Marino "suggest parentheses around comparison in operand of %<==%>");
10139e4b17023SJohn Marino return;
10140e4b17023SJohn Marino case NE_EXPR:
10141e4b17023SJohn Marino if (TREE_CODE_CLASS (code_left) == tcc_comparison
10142e4b17023SJohn Marino || TREE_CODE_CLASS (code_right) == tcc_comparison)
10143e4b17023SJohn Marino warning (OPT_Wparentheses,
10144e4b17023SJohn Marino "suggest parentheses around comparison in operand of %<!=%>");
10145e4b17023SJohn Marino return;
10146e4b17023SJohn Marino
10147e4b17023SJohn Marino default:
10148e4b17023SJohn Marino if (TREE_CODE_CLASS (code) == tcc_comparison
10149e4b17023SJohn Marino && ((TREE_CODE_CLASS (code_left) == tcc_comparison
10150e4b17023SJohn Marino && code_left != NE_EXPR && code_left != EQ_EXPR
10151e4b17023SJohn Marino && INTEGRAL_TYPE_P (TREE_TYPE (arg_left)))
10152e4b17023SJohn Marino || (TREE_CODE_CLASS (code_right) == tcc_comparison
10153e4b17023SJohn Marino && code_right != NE_EXPR && code_right != EQ_EXPR
10154e4b17023SJohn Marino && INTEGRAL_TYPE_P (TREE_TYPE (arg_right)))))
10155e4b17023SJohn Marino warning (OPT_Wparentheses, "comparisons like %<X<=Y<=Z%> do not "
10156e4b17023SJohn Marino "have their mathematical meaning");
10157e4b17023SJohn Marino return;
10158e4b17023SJohn Marino }
10159e4b17023SJohn Marino #undef NOT_A_BOOLEAN_EXPR_P
10160e4b17023SJohn Marino }
10161e4b17023SJohn Marino
10162e4b17023SJohn Marino /* If LABEL (a LABEL_DECL) has not been used, issue a warning. */
10163e4b17023SJohn Marino
10164e4b17023SJohn Marino void
warn_for_unused_label(tree label)10165e4b17023SJohn Marino warn_for_unused_label (tree label)
10166e4b17023SJohn Marino {
10167e4b17023SJohn Marino if (!TREE_USED (label))
10168e4b17023SJohn Marino {
10169e4b17023SJohn Marino if (DECL_INITIAL (label))
10170e4b17023SJohn Marino warning (OPT_Wunused_label, "label %q+D defined but not used", label);
10171e4b17023SJohn Marino else
10172e4b17023SJohn Marino warning (OPT_Wunused_label, "label %q+D declared but not defined", label);
10173e4b17023SJohn Marino }
10174e4b17023SJohn Marino }
10175e4b17023SJohn Marino
10176e4b17023SJohn Marino /* Warn for division by zero according to the value of DIVISOR. LOC
10177e4b17023SJohn Marino is the location of the division operator. */
10178e4b17023SJohn Marino
10179e4b17023SJohn Marino void
warn_for_div_by_zero(location_t loc,tree divisor)10180e4b17023SJohn Marino warn_for_div_by_zero (location_t loc, tree divisor)
10181e4b17023SJohn Marino {
10182e4b17023SJohn Marino /* If DIVISOR is zero, and has integral or fixed-point type, issue a warning
10183e4b17023SJohn Marino about division by zero. Do not issue a warning if DIVISOR has a
10184e4b17023SJohn Marino floating-point type, since we consider 0.0/0.0 a valid way of
10185e4b17023SJohn Marino generating a NaN. */
10186e4b17023SJohn Marino if (c_inhibit_evaluation_warnings == 0
10187e4b17023SJohn Marino && (integer_zerop (divisor) || fixed_zerop (divisor)))
10188e4b17023SJohn Marino warning_at (loc, OPT_Wdiv_by_zero, "division by zero");
10189e4b17023SJohn Marino }
10190e4b17023SJohn Marino
10191e4b17023SJohn Marino /* Subroutine of build_binary_op. Give warnings for comparisons
10192e4b17023SJohn Marino between signed and unsigned quantities that may fail. Do the
10193e4b17023SJohn Marino checking based on the original operand trees ORIG_OP0 and ORIG_OP1,
10194e4b17023SJohn Marino so that casts will be considered, but default promotions won't
10195e4b17023SJohn Marino be.
10196e4b17023SJohn Marino
10197e4b17023SJohn Marino LOCATION is the location of the comparison operator.
10198e4b17023SJohn Marino
10199e4b17023SJohn Marino The arguments of this function map directly to local variables
10200e4b17023SJohn Marino of build_binary_op. */
10201e4b17023SJohn Marino
10202e4b17023SJohn Marino void
warn_for_sign_compare(location_t location,tree orig_op0,tree orig_op1,tree op0,tree op1,tree result_type,enum tree_code resultcode)10203e4b17023SJohn Marino warn_for_sign_compare (location_t location,
10204e4b17023SJohn Marino tree orig_op0, tree orig_op1,
10205e4b17023SJohn Marino tree op0, tree op1,
10206e4b17023SJohn Marino tree result_type, enum tree_code resultcode)
10207e4b17023SJohn Marino {
10208e4b17023SJohn Marino int op0_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op0));
10209e4b17023SJohn Marino int op1_signed = !TYPE_UNSIGNED (TREE_TYPE (orig_op1));
10210e4b17023SJohn Marino int unsignedp0, unsignedp1;
10211e4b17023SJohn Marino
10212e4b17023SJohn Marino /* In C++, check for comparison of different enum types. */
10213e4b17023SJohn Marino if (c_dialect_cxx()
10214e4b17023SJohn Marino && TREE_CODE (TREE_TYPE (orig_op0)) == ENUMERAL_TYPE
10215e4b17023SJohn Marino && TREE_CODE (TREE_TYPE (orig_op1)) == ENUMERAL_TYPE
10216e4b17023SJohn Marino && TYPE_MAIN_VARIANT (TREE_TYPE (orig_op0))
10217e4b17023SJohn Marino != TYPE_MAIN_VARIANT (TREE_TYPE (orig_op1)))
10218e4b17023SJohn Marino {
10219e4b17023SJohn Marino warning_at (location,
10220e4b17023SJohn Marino OPT_Wsign_compare, "comparison between types %qT and %qT",
10221e4b17023SJohn Marino TREE_TYPE (orig_op0), TREE_TYPE (orig_op1));
10222e4b17023SJohn Marino }
10223e4b17023SJohn Marino
10224e4b17023SJohn Marino /* Do not warn if the comparison is being done in a signed type,
10225e4b17023SJohn Marino since the signed type will only be chosen if it can represent
10226e4b17023SJohn Marino all the values of the unsigned type. */
10227e4b17023SJohn Marino if (!TYPE_UNSIGNED (result_type))
10228e4b17023SJohn Marino /* OK */;
10229e4b17023SJohn Marino /* Do not warn if both operands are unsigned. */
10230e4b17023SJohn Marino else if (op0_signed == op1_signed)
10231e4b17023SJohn Marino /* OK */;
10232e4b17023SJohn Marino else
10233e4b17023SJohn Marino {
10234e4b17023SJohn Marino tree sop, uop, base_type;
10235e4b17023SJohn Marino bool ovf;
10236e4b17023SJohn Marino
10237e4b17023SJohn Marino if (op0_signed)
10238e4b17023SJohn Marino sop = orig_op0, uop = orig_op1;
10239e4b17023SJohn Marino else
10240e4b17023SJohn Marino sop = orig_op1, uop = orig_op0;
10241e4b17023SJohn Marino
10242e4b17023SJohn Marino STRIP_TYPE_NOPS (sop);
10243e4b17023SJohn Marino STRIP_TYPE_NOPS (uop);
10244e4b17023SJohn Marino base_type = (TREE_CODE (result_type) == COMPLEX_TYPE
10245e4b17023SJohn Marino ? TREE_TYPE (result_type) : result_type);
10246e4b17023SJohn Marino
10247e4b17023SJohn Marino /* Do not warn if the signed quantity is an unsuffixed integer
10248e4b17023SJohn Marino literal (or some static constant expression involving such
10249e4b17023SJohn Marino literals or a conditional expression involving such literals)
10250e4b17023SJohn Marino and it is non-negative. */
10251e4b17023SJohn Marino if (tree_expr_nonnegative_warnv_p (sop, &ovf))
10252e4b17023SJohn Marino /* OK */;
10253e4b17023SJohn Marino /* Do not warn if the comparison is an equality operation, the
10254e4b17023SJohn Marino unsigned quantity is an integral constant, and it would fit
10255e4b17023SJohn Marino in the result if the result were signed. */
10256e4b17023SJohn Marino else if (TREE_CODE (uop) == INTEGER_CST
10257e4b17023SJohn Marino && (resultcode == EQ_EXPR || resultcode == NE_EXPR)
10258e4b17023SJohn Marino && int_fits_type_p (uop, c_common_signed_type (base_type)))
10259e4b17023SJohn Marino /* OK */;
10260e4b17023SJohn Marino /* In C, do not warn if the unsigned quantity is an enumeration
10261e4b17023SJohn Marino constant and its maximum value would fit in the result if the
10262e4b17023SJohn Marino result were signed. */
10263e4b17023SJohn Marino else if (!c_dialect_cxx() && TREE_CODE (uop) == INTEGER_CST
10264e4b17023SJohn Marino && TREE_CODE (TREE_TYPE (uop)) == ENUMERAL_TYPE
10265e4b17023SJohn Marino && int_fits_type_p (TYPE_MAX_VALUE (TREE_TYPE (uop)),
10266e4b17023SJohn Marino c_common_signed_type (base_type)))
10267e4b17023SJohn Marino /* OK */;
10268e4b17023SJohn Marino else
10269e4b17023SJohn Marino warning_at (location,
10270e4b17023SJohn Marino OPT_Wsign_compare,
10271e4b17023SJohn Marino "comparison between signed and unsigned integer expressions");
10272e4b17023SJohn Marino }
10273e4b17023SJohn Marino
10274e4b17023SJohn Marino /* Warn if two unsigned values are being compared in a size larger
10275e4b17023SJohn Marino than their original size, and one (and only one) is the result of
10276e4b17023SJohn Marino a `~' operator. This comparison will always fail.
10277e4b17023SJohn Marino
10278e4b17023SJohn Marino Also warn if one operand is a constant, and the constant does not
10279e4b17023SJohn Marino have all bits set that are set in the ~ operand when it is
10280e4b17023SJohn Marino extended. */
10281e4b17023SJohn Marino
10282e4b17023SJohn Marino op0 = c_common_get_narrower (op0, &unsignedp0);
10283e4b17023SJohn Marino op1 = c_common_get_narrower (op1, &unsignedp1);
10284e4b17023SJohn Marino
10285e4b17023SJohn Marino if ((TREE_CODE (op0) == BIT_NOT_EXPR)
10286e4b17023SJohn Marino ^ (TREE_CODE (op1) == BIT_NOT_EXPR))
10287e4b17023SJohn Marino {
10288e4b17023SJohn Marino if (TREE_CODE (op0) == BIT_NOT_EXPR)
10289e4b17023SJohn Marino op0 = c_common_get_narrower (TREE_OPERAND (op0, 0), &unsignedp0);
10290e4b17023SJohn Marino if (TREE_CODE (op1) == BIT_NOT_EXPR)
10291e4b17023SJohn Marino op1 = c_common_get_narrower (TREE_OPERAND (op1, 0), &unsignedp1);
10292e4b17023SJohn Marino
10293e4b17023SJohn Marino if (host_integerp (op0, 0) || host_integerp (op1, 0))
10294e4b17023SJohn Marino {
10295e4b17023SJohn Marino tree primop;
10296e4b17023SJohn Marino HOST_WIDE_INT constant, mask;
10297e4b17023SJohn Marino int unsignedp;
10298e4b17023SJohn Marino unsigned int bits;
10299e4b17023SJohn Marino
10300e4b17023SJohn Marino if (host_integerp (op0, 0))
10301e4b17023SJohn Marino {
10302e4b17023SJohn Marino primop = op1;
10303e4b17023SJohn Marino unsignedp = unsignedp1;
10304e4b17023SJohn Marino constant = tree_low_cst (op0, 0);
10305e4b17023SJohn Marino }
10306e4b17023SJohn Marino else
10307e4b17023SJohn Marino {
10308e4b17023SJohn Marino primop = op0;
10309e4b17023SJohn Marino unsignedp = unsignedp0;
10310e4b17023SJohn Marino constant = tree_low_cst (op1, 0);
10311e4b17023SJohn Marino }
10312e4b17023SJohn Marino
10313e4b17023SJohn Marino bits = TYPE_PRECISION (TREE_TYPE (primop));
10314e4b17023SJohn Marino if (bits < TYPE_PRECISION (result_type)
10315e4b17023SJohn Marino && bits < HOST_BITS_PER_LONG && unsignedp)
10316e4b17023SJohn Marino {
10317e4b17023SJohn Marino mask = (~ (HOST_WIDE_INT) 0) << bits;
10318e4b17023SJohn Marino if ((mask & constant) != mask)
10319e4b17023SJohn Marino {
10320e4b17023SJohn Marino if (constant == 0)
10321e4b17023SJohn Marino warning (OPT_Wsign_compare,
10322e4b17023SJohn Marino "promoted ~unsigned is always non-zero");
10323e4b17023SJohn Marino else
10324e4b17023SJohn Marino warning_at (location, OPT_Wsign_compare,
10325e4b17023SJohn Marino "comparison of promoted ~unsigned with constant");
10326e4b17023SJohn Marino }
10327e4b17023SJohn Marino }
10328e4b17023SJohn Marino }
10329e4b17023SJohn Marino else if (unsignedp0 && unsignedp1
10330e4b17023SJohn Marino && (TYPE_PRECISION (TREE_TYPE (op0))
10331e4b17023SJohn Marino < TYPE_PRECISION (result_type))
10332e4b17023SJohn Marino && (TYPE_PRECISION (TREE_TYPE (op1))
10333e4b17023SJohn Marino < TYPE_PRECISION (result_type)))
10334e4b17023SJohn Marino warning_at (location, OPT_Wsign_compare,
10335e4b17023SJohn Marino "comparison of promoted ~unsigned with unsigned");
10336e4b17023SJohn Marino }
10337e4b17023SJohn Marino }
10338e4b17023SJohn Marino
10339e4b17023SJohn Marino /* RESULT_TYPE is the result of converting TYPE1 and TYPE2 to a common
10340e4b17023SJohn Marino type via c_common_type. If -Wdouble-promotion is in use, and the
10341e4b17023SJohn Marino conditions for warning have been met, issue a warning. GMSGID is
10342e4b17023SJohn Marino the warning message. It must have two %T specifiers for the type
10343e4b17023SJohn Marino that was converted (generally "float") and the type to which it was
10344e4b17023SJohn Marino converted (generally "double), respectively. LOC is the location
10345e4b17023SJohn Marino to which the awrning should refer. */
10346e4b17023SJohn Marino
10347e4b17023SJohn Marino void
do_warn_double_promotion(tree result_type,tree type1,tree type2,const char * gmsgid,location_t loc)10348e4b17023SJohn Marino do_warn_double_promotion (tree result_type, tree type1, tree type2,
10349e4b17023SJohn Marino const char *gmsgid, location_t loc)
10350e4b17023SJohn Marino {
10351e4b17023SJohn Marino tree source_type;
10352e4b17023SJohn Marino
10353e4b17023SJohn Marino if (!warn_double_promotion)
10354e4b17023SJohn Marino return;
10355e4b17023SJohn Marino /* If the conversion will not occur at run-time, there is no need to
10356e4b17023SJohn Marino warn about it. */
10357e4b17023SJohn Marino if (c_inhibit_evaluation_warnings)
10358e4b17023SJohn Marino return;
10359e4b17023SJohn Marino if (TYPE_MAIN_VARIANT (result_type) != double_type_node
10360e4b17023SJohn Marino && TYPE_MAIN_VARIANT (result_type) != complex_double_type_node)
10361e4b17023SJohn Marino return;
10362e4b17023SJohn Marino if (TYPE_MAIN_VARIANT (type1) == float_type_node
10363e4b17023SJohn Marino || TYPE_MAIN_VARIANT (type1) == complex_float_type_node)
10364e4b17023SJohn Marino source_type = type1;
10365e4b17023SJohn Marino else if (TYPE_MAIN_VARIANT (type2) == float_type_node
10366e4b17023SJohn Marino || TYPE_MAIN_VARIANT (type2) == complex_float_type_node)
10367e4b17023SJohn Marino source_type = type2;
10368e4b17023SJohn Marino else
10369e4b17023SJohn Marino return;
10370e4b17023SJohn Marino warning_at (loc, OPT_Wdouble_promotion, gmsgid, source_type, result_type);
10371e4b17023SJohn Marino }
10372e4b17023SJohn Marino
10373e4b17023SJohn Marino /* Setup a TYPE_DECL node as a typedef representation.
10374e4b17023SJohn Marino
10375e4b17023SJohn Marino X is a TYPE_DECL for a typedef statement. Create a brand new
10376e4b17023SJohn Marino ..._TYPE node (which will be just a variant of the existing
10377e4b17023SJohn Marino ..._TYPE node with identical properties) and then install X
10378e4b17023SJohn Marino as the TYPE_NAME of this brand new (duplicate) ..._TYPE node.
10379e4b17023SJohn Marino
10380e4b17023SJohn Marino The whole point here is to end up with a situation where each
10381e4b17023SJohn Marino and every ..._TYPE node the compiler creates will be uniquely
10382e4b17023SJohn Marino associated with AT MOST one node representing a typedef name.
10383e4b17023SJohn Marino This way, even though the compiler substitutes corresponding
10384e4b17023SJohn Marino ..._TYPE nodes for TYPE_DECL (i.e. "typedef name") nodes very
10385e4b17023SJohn Marino early on, later parts of the compiler can always do the reverse
10386e4b17023SJohn Marino translation and get back the corresponding typedef name. For
10387e4b17023SJohn Marino example, given:
10388e4b17023SJohn Marino
10389e4b17023SJohn Marino typedef struct S MY_TYPE;
10390e4b17023SJohn Marino MY_TYPE object;
10391e4b17023SJohn Marino
10392e4b17023SJohn Marino Later parts of the compiler might only know that `object' was of
10393e4b17023SJohn Marino type `struct S' if it were not for code just below. With this
10394e4b17023SJohn Marino code however, later parts of the compiler see something like:
10395e4b17023SJohn Marino
10396e4b17023SJohn Marino struct S' == struct S
10397e4b17023SJohn Marino typedef struct S' MY_TYPE;
10398e4b17023SJohn Marino struct S' object;
10399e4b17023SJohn Marino
10400e4b17023SJohn Marino And they can then deduce (from the node for type struct S') that
10401e4b17023SJohn Marino the original object declaration was:
10402e4b17023SJohn Marino
10403e4b17023SJohn Marino MY_TYPE object;
10404e4b17023SJohn Marino
10405e4b17023SJohn Marino Being able to do this is important for proper support of protoize,
10406e4b17023SJohn Marino and also for generating precise symbolic debugging information
10407e4b17023SJohn Marino which takes full account of the programmer's (typedef) vocabulary.
10408e4b17023SJohn Marino
10409e4b17023SJohn Marino Obviously, we don't want to generate a duplicate ..._TYPE node if
10410e4b17023SJohn Marino the TYPE_DECL node that we are now processing really represents a
10411e4b17023SJohn Marino standard built-in type. */
10412e4b17023SJohn Marino
10413e4b17023SJohn Marino void
set_underlying_type(tree x)10414e4b17023SJohn Marino set_underlying_type (tree x)
10415e4b17023SJohn Marino {
10416e4b17023SJohn Marino if (x == error_mark_node)
10417e4b17023SJohn Marino return;
10418e4b17023SJohn Marino if (DECL_IS_BUILTIN (x))
10419e4b17023SJohn Marino {
10420e4b17023SJohn Marino if (TYPE_NAME (TREE_TYPE (x)) == 0)
10421e4b17023SJohn Marino TYPE_NAME (TREE_TYPE (x)) = x;
10422e4b17023SJohn Marino }
10423e4b17023SJohn Marino else if (TREE_TYPE (x) != error_mark_node
10424e4b17023SJohn Marino && DECL_ORIGINAL_TYPE (x) == NULL_TREE)
10425e4b17023SJohn Marino {
10426e4b17023SJohn Marino tree tt = TREE_TYPE (x);
10427e4b17023SJohn Marino DECL_ORIGINAL_TYPE (x) = tt;
10428e4b17023SJohn Marino tt = build_variant_type_copy (tt);
10429e4b17023SJohn Marino TYPE_STUB_DECL (tt) = TYPE_STUB_DECL (DECL_ORIGINAL_TYPE (x));
10430e4b17023SJohn Marino TYPE_NAME (tt) = x;
10431e4b17023SJohn Marino TREE_USED (tt) = TREE_USED (x);
10432e4b17023SJohn Marino TREE_TYPE (x) = tt;
10433e4b17023SJohn Marino }
10434e4b17023SJohn Marino }
10435e4b17023SJohn Marino
10436e4b17023SJohn Marino /* Record the types used by the current global variable declaration
10437e4b17023SJohn Marino being parsed, so that we can decide later to emit their debug info.
10438e4b17023SJohn Marino Those types are in types_used_by_cur_var_decl, and we are going to
10439e4b17023SJohn Marino store them in the types_used_by_vars_hash hash table.
10440e4b17023SJohn Marino DECL is the declaration of the global variable that has been parsed. */
10441e4b17023SJohn Marino
10442e4b17023SJohn Marino void
record_types_used_by_current_var_decl(tree decl)10443e4b17023SJohn Marino record_types_used_by_current_var_decl (tree decl)
10444e4b17023SJohn Marino {
10445e4b17023SJohn Marino gcc_assert (decl && DECL_P (decl) && TREE_STATIC (decl));
10446e4b17023SJohn Marino
10447e4b17023SJohn Marino while (!VEC_empty (tree, types_used_by_cur_var_decl))
10448e4b17023SJohn Marino {
10449e4b17023SJohn Marino tree type = VEC_pop (tree, types_used_by_cur_var_decl);
10450e4b17023SJohn Marino types_used_by_var_decl_insert (type, decl);
10451e4b17023SJohn Marino }
10452e4b17023SJohn Marino }
10453e4b17023SJohn Marino
10454e4b17023SJohn Marino /* If DECL is a typedef that is declared in the current function,
10455e4b17023SJohn Marino record it for the purpose of -Wunused-local-typedefs. */
10456e4b17023SJohn Marino
10457e4b17023SJohn Marino void
record_locally_defined_typedef(tree decl)10458e4b17023SJohn Marino record_locally_defined_typedef (tree decl)
10459e4b17023SJohn Marino {
10460e4b17023SJohn Marino struct c_language_function *l;
10461e4b17023SJohn Marino
10462e4b17023SJohn Marino if (!warn_unused_local_typedefs
10463e4b17023SJohn Marino || cfun == NULL
10464e4b17023SJohn Marino /* if this is not a locally defined typedef then we are not
10465e4b17023SJohn Marino interested. */
10466e4b17023SJohn Marino || !is_typedef_decl (decl)
10467e4b17023SJohn Marino || !decl_function_context (decl))
10468e4b17023SJohn Marino return;
10469e4b17023SJohn Marino
10470e4b17023SJohn Marino l = (struct c_language_function *) cfun->language;
10471e4b17023SJohn Marino VEC_safe_push (tree, gc, l->local_typedefs, decl);
10472e4b17023SJohn Marino }
10473e4b17023SJohn Marino
10474e4b17023SJohn Marino /* If T is a TYPE_DECL declared locally, mark it as used. */
10475e4b17023SJohn Marino
10476e4b17023SJohn Marino void
maybe_record_typedef_use(tree t)10477e4b17023SJohn Marino maybe_record_typedef_use (tree t)
10478e4b17023SJohn Marino {
10479e4b17023SJohn Marino if (!is_typedef_decl (t))
10480e4b17023SJohn Marino return;
10481e4b17023SJohn Marino
10482e4b17023SJohn Marino TREE_USED (t) = true;
10483e4b17023SJohn Marino }
10484e4b17023SJohn Marino
10485e4b17023SJohn Marino /* Warn if there are some unused locally defined typedefs in the
10486e4b17023SJohn Marino current function. */
10487e4b17023SJohn Marino
10488e4b17023SJohn Marino void
maybe_warn_unused_local_typedefs(void)10489e4b17023SJohn Marino maybe_warn_unused_local_typedefs (void)
10490e4b17023SJohn Marino {
10491e4b17023SJohn Marino int i;
10492e4b17023SJohn Marino tree decl;
10493e4b17023SJohn Marino /* The number of times we have emitted -Wunused-local-typedefs
10494e4b17023SJohn Marino warnings. If this is different from errorcount, that means some
10495e4b17023SJohn Marino unrelated errors have been issued. In which case, we'll avoid
10496e4b17023SJohn Marino emitting "unused-local-typedefs" warnings. */
10497e4b17023SJohn Marino static int unused_local_typedefs_warn_count;
10498e4b17023SJohn Marino struct c_language_function *l;
10499e4b17023SJohn Marino
10500e4b17023SJohn Marino if (cfun == NULL)
10501e4b17023SJohn Marino return;
10502e4b17023SJohn Marino
10503e4b17023SJohn Marino if ((l = (struct c_language_function *) cfun->language) == NULL)
10504e4b17023SJohn Marino return;
10505e4b17023SJohn Marino
10506e4b17023SJohn Marino if (warn_unused_local_typedefs
10507e4b17023SJohn Marino && errorcount == unused_local_typedefs_warn_count)
10508e4b17023SJohn Marino {
10509e4b17023SJohn Marino FOR_EACH_VEC_ELT (tree, l->local_typedefs, i, decl)
10510e4b17023SJohn Marino if (!TREE_USED (decl))
10511e4b17023SJohn Marino warning_at (DECL_SOURCE_LOCATION (decl),
10512e4b17023SJohn Marino OPT_Wunused_local_typedefs,
10513e4b17023SJohn Marino "typedef %qD locally defined but not used", decl);
10514e4b17023SJohn Marino unused_local_typedefs_warn_count = errorcount;
10515e4b17023SJohn Marino }
10516e4b17023SJohn Marino
10517e4b17023SJohn Marino if (l->local_typedefs)
10518e4b17023SJohn Marino {
10519e4b17023SJohn Marino VEC_free (tree, gc, l->local_typedefs);
10520e4b17023SJohn Marino l->local_typedefs = NULL;
10521e4b17023SJohn Marino }
10522e4b17023SJohn Marino }
10523e4b17023SJohn Marino
10524e4b17023SJohn Marino /* The C and C++ parsers both use vectors to hold function arguments.
10525e4b17023SJohn Marino For efficiency, we keep a cache of unused vectors. This is the
10526e4b17023SJohn Marino cache. */
10527e4b17023SJohn Marino
10528e4b17023SJohn Marino typedef VEC(tree,gc)* tree_gc_vec;
10529e4b17023SJohn Marino DEF_VEC_P(tree_gc_vec);
10530e4b17023SJohn Marino DEF_VEC_ALLOC_P(tree_gc_vec,gc);
10531e4b17023SJohn Marino static GTY((deletable)) VEC(tree_gc_vec,gc) *tree_vector_cache;
10532e4b17023SJohn Marino
10533e4b17023SJohn Marino /* Return a new vector from the cache. If the cache is empty,
10534e4b17023SJohn Marino allocate a new vector. These vectors are GC'ed, so it is OK if the
10535e4b17023SJohn Marino pointer is not released.. */
10536e4b17023SJohn Marino
VEC(tree,gc)10537e4b17023SJohn Marino VEC(tree,gc) *
10538e4b17023SJohn Marino make_tree_vector (void)
10539e4b17023SJohn Marino {
10540e4b17023SJohn Marino if (!VEC_empty (tree_gc_vec, tree_vector_cache))
10541e4b17023SJohn Marino return VEC_pop (tree_gc_vec, tree_vector_cache);
10542e4b17023SJohn Marino else
10543e4b17023SJohn Marino {
10544e4b17023SJohn Marino /* Passing 0 to VEC_alloc returns NULL, and our callers require
10545e4b17023SJohn Marino that we always return a non-NULL value. The vector code uses
10546e4b17023SJohn Marino 4 when growing a NULL vector, so we do too. */
10547e4b17023SJohn Marino return VEC_alloc (tree, gc, 4);
10548e4b17023SJohn Marino }
10549e4b17023SJohn Marino }
10550e4b17023SJohn Marino
10551e4b17023SJohn Marino /* Release a vector of trees back to the cache. */
10552e4b17023SJohn Marino
10553e4b17023SJohn Marino void
release_tree_vector(VEC (tree,gc)* vec)10554e4b17023SJohn Marino release_tree_vector (VEC(tree,gc) *vec)
10555e4b17023SJohn Marino {
10556e4b17023SJohn Marino if (vec != NULL)
10557e4b17023SJohn Marino {
10558e4b17023SJohn Marino VEC_truncate (tree, vec, 0);
10559e4b17023SJohn Marino VEC_safe_push (tree_gc_vec, gc, tree_vector_cache, vec);
10560e4b17023SJohn Marino }
10561e4b17023SJohn Marino }
10562e4b17023SJohn Marino
10563e4b17023SJohn Marino /* Get a new tree vector holding a single tree. */
10564e4b17023SJohn Marino
VEC(tree,gc)10565e4b17023SJohn Marino VEC(tree,gc) *
10566e4b17023SJohn Marino make_tree_vector_single (tree t)
10567e4b17023SJohn Marino {
10568e4b17023SJohn Marino VEC(tree,gc) *ret = make_tree_vector ();
10569e4b17023SJohn Marino VEC_quick_push (tree, ret, t);
10570e4b17023SJohn Marino return ret;
10571e4b17023SJohn Marino }
10572e4b17023SJohn Marino
10573e4b17023SJohn Marino /* Get a new tree vector of the TREE_VALUEs of a TREE_LIST chain. */
10574e4b17023SJohn Marino
VEC(tree,gc)10575e4b17023SJohn Marino VEC(tree,gc) *
10576e4b17023SJohn Marino make_tree_vector_from_list (tree list)
10577e4b17023SJohn Marino {
10578e4b17023SJohn Marino VEC(tree,gc) *ret = make_tree_vector ();
10579e4b17023SJohn Marino for (; list; list = TREE_CHAIN (list))
10580e4b17023SJohn Marino VEC_safe_push (tree, gc, ret, TREE_VALUE (list));
10581e4b17023SJohn Marino return ret;
10582e4b17023SJohn Marino }
10583e4b17023SJohn Marino
10584e4b17023SJohn Marino /* Get a new tree vector which is a copy of an existing one. */
10585e4b17023SJohn Marino
VEC(tree,gc)10586e4b17023SJohn Marino VEC(tree,gc) *
10587e4b17023SJohn Marino make_tree_vector_copy (const VEC(tree,gc) *orig)
10588e4b17023SJohn Marino {
10589e4b17023SJohn Marino VEC(tree,gc) *ret;
10590e4b17023SJohn Marino unsigned int ix;
10591e4b17023SJohn Marino tree t;
10592e4b17023SJohn Marino
10593e4b17023SJohn Marino ret = make_tree_vector ();
10594e4b17023SJohn Marino VEC_reserve (tree, gc, ret, VEC_length (tree, orig));
10595e4b17023SJohn Marino FOR_EACH_VEC_ELT (tree, orig, ix, t)
10596e4b17023SJohn Marino VEC_quick_push (tree, ret, t);
10597e4b17023SJohn Marino return ret;
10598e4b17023SJohn Marino }
10599e4b17023SJohn Marino
10600e4b17023SJohn Marino /* Return true if KEYWORD starts a type specifier. */
10601e4b17023SJohn Marino
10602e4b17023SJohn Marino bool
keyword_begins_type_specifier(enum rid keyword)10603e4b17023SJohn Marino keyword_begins_type_specifier (enum rid keyword)
10604e4b17023SJohn Marino {
10605e4b17023SJohn Marino switch (keyword)
10606e4b17023SJohn Marino {
10607e4b17023SJohn Marino case RID_INT:
10608e4b17023SJohn Marino case RID_CHAR:
10609e4b17023SJohn Marino case RID_FLOAT:
10610e4b17023SJohn Marino case RID_DOUBLE:
10611e4b17023SJohn Marino case RID_VOID:
10612e4b17023SJohn Marino case RID_INT128:
10613e4b17023SJohn Marino case RID_UNSIGNED:
10614e4b17023SJohn Marino case RID_LONG:
10615e4b17023SJohn Marino case RID_SHORT:
10616e4b17023SJohn Marino case RID_SIGNED:
10617e4b17023SJohn Marino case RID_DFLOAT32:
10618e4b17023SJohn Marino case RID_DFLOAT64:
10619e4b17023SJohn Marino case RID_DFLOAT128:
10620e4b17023SJohn Marino case RID_FRACT:
10621e4b17023SJohn Marino case RID_ACCUM:
10622e4b17023SJohn Marino case RID_BOOL:
10623e4b17023SJohn Marino case RID_WCHAR:
10624e4b17023SJohn Marino case RID_CHAR16:
10625e4b17023SJohn Marino case RID_CHAR32:
10626e4b17023SJohn Marino case RID_SAT:
10627e4b17023SJohn Marino case RID_COMPLEX:
10628e4b17023SJohn Marino case RID_TYPEOF:
10629e4b17023SJohn Marino case RID_STRUCT:
10630e4b17023SJohn Marino case RID_CLASS:
10631e4b17023SJohn Marino case RID_UNION:
10632e4b17023SJohn Marino case RID_ENUM:
10633e4b17023SJohn Marino return true;
10634e4b17023SJohn Marino default:
10635e4b17023SJohn Marino return false;
10636e4b17023SJohn Marino }
10637e4b17023SJohn Marino }
10638e4b17023SJohn Marino
10639e4b17023SJohn Marino /* Return true if KEYWORD names a type qualifier. */
10640e4b17023SJohn Marino
10641e4b17023SJohn Marino bool
keyword_is_type_qualifier(enum rid keyword)10642e4b17023SJohn Marino keyword_is_type_qualifier (enum rid keyword)
10643e4b17023SJohn Marino {
10644e4b17023SJohn Marino switch (keyword)
10645e4b17023SJohn Marino {
10646e4b17023SJohn Marino case RID_CONST:
10647e4b17023SJohn Marino case RID_VOLATILE:
10648e4b17023SJohn Marino case RID_RESTRICT:
10649e4b17023SJohn Marino return true;
10650e4b17023SJohn Marino default:
10651e4b17023SJohn Marino return false;
10652e4b17023SJohn Marino }
10653e4b17023SJohn Marino }
10654e4b17023SJohn Marino
10655e4b17023SJohn Marino /* Return true if KEYWORD names a storage class specifier.
10656e4b17023SJohn Marino
10657e4b17023SJohn Marino RID_TYPEDEF is not included in this list despite `typedef' being
10658e4b17023SJohn Marino listed in C99 6.7.1.1. 6.7.1.3 indicates that `typedef' is listed as
10659e4b17023SJohn Marino such for syntactic convenience only. */
10660e4b17023SJohn Marino
10661e4b17023SJohn Marino bool
keyword_is_storage_class_specifier(enum rid keyword)10662e4b17023SJohn Marino keyword_is_storage_class_specifier (enum rid keyword)
10663e4b17023SJohn Marino {
10664e4b17023SJohn Marino switch (keyword)
10665e4b17023SJohn Marino {
10666e4b17023SJohn Marino case RID_STATIC:
10667e4b17023SJohn Marino case RID_EXTERN:
10668e4b17023SJohn Marino case RID_REGISTER:
10669e4b17023SJohn Marino case RID_AUTO:
10670e4b17023SJohn Marino case RID_MUTABLE:
10671e4b17023SJohn Marino case RID_THREAD:
10672e4b17023SJohn Marino return true;
10673e4b17023SJohn Marino default:
10674e4b17023SJohn Marino return false;
10675e4b17023SJohn Marino }
10676e4b17023SJohn Marino }
10677e4b17023SJohn Marino
10678e4b17023SJohn Marino /* Return true if KEYWORD names a function-specifier [dcl.fct.spec]. */
10679e4b17023SJohn Marino
10680e4b17023SJohn Marino static bool
keyword_is_function_specifier(enum rid keyword)10681e4b17023SJohn Marino keyword_is_function_specifier (enum rid keyword)
10682e4b17023SJohn Marino {
10683e4b17023SJohn Marino switch (keyword)
10684e4b17023SJohn Marino {
10685e4b17023SJohn Marino case RID_INLINE:
10686e4b17023SJohn Marino case RID_NORETURN:
10687e4b17023SJohn Marino case RID_VIRTUAL:
10688e4b17023SJohn Marino case RID_EXPLICIT:
10689e4b17023SJohn Marino return true;
10690e4b17023SJohn Marino default:
10691e4b17023SJohn Marino return false;
10692e4b17023SJohn Marino }
10693e4b17023SJohn Marino }
10694e4b17023SJohn Marino
10695e4b17023SJohn Marino /* Return true if KEYWORD names a decl-specifier [dcl.spec] or a
10696e4b17023SJohn Marino declaration-specifier (C99 6.7). */
10697e4b17023SJohn Marino
10698e4b17023SJohn Marino bool
keyword_is_decl_specifier(enum rid keyword)10699e4b17023SJohn Marino keyword_is_decl_specifier (enum rid keyword)
10700e4b17023SJohn Marino {
10701e4b17023SJohn Marino if (keyword_is_storage_class_specifier (keyword)
10702e4b17023SJohn Marino || keyword_is_type_qualifier (keyword)
10703e4b17023SJohn Marino || keyword_is_function_specifier (keyword))
10704e4b17023SJohn Marino return true;
10705e4b17023SJohn Marino
10706e4b17023SJohn Marino switch (keyword)
10707e4b17023SJohn Marino {
10708e4b17023SJohn Marino case RID_TYPEDEF:
10709e4b17023SJohn Marino case RID_FRIEND:
10710e4b17023SJohn Marino case RID_CONSTEXPR:
10711e4b17023SJohn Marino return true;
10712e4b17023SJohn Marino default:
10713e4b17023SJohn Marino return false;
10714e4b17023SJohn Marino }
10715e4b17023SJohn Marino }
10716e4b17023SJohn Marino
10717e4b17023SJohn Marino /* Initialize language-specific-bits of tree_contains_struct. */
10718e4b17023SJohn Marino
10719e4b17023SJohn Marino void
c_common_init_ts(void)10720e4b17023SJohn Marino c_common_init_ts (void)
10721e4b17023SJohn Marino {
10722e4b17023SJohn Marino MARK_TS_TYPED (C_MAYBE_CONST_EXPR);
10723e4b17023SJohn Marino MARK_TS_TYPED (EXCESS_PRECISION_EXPR);
10724e4b17023SJohn Marino }
10725e4b17023SJohn Marino
10726e4b17023SJohn Marino /* Build a user-defined numeric literal out of an integer constant type VALUE
10727e4b17023SJohn Marino with identifier SUFFIX. */
10728e4b17023SJohn Marino
10729e4b17023SJohn Marino tree
build_userdef_literal(tree suffix_id,tree value,tree num_string)10730e4b17023SJohn Marino build_userdef_literal (tree suffix_id, tree value, tree num_string)
10731e4b17023SJohn Marino {
10732e4b17023SJohn Marino tree literal = make_node (USERDEF_LITERAL);
10733e4b17023SJohn Marino USERDEF_LITERAL_SUFFIX_ID (literal) = suffix_id;
10734e4b17023SJohn Marino USERDEF_LITERAL_VALUE (literal) = value;
10735e4b17023SJohn Marino USERDEF_LITERAL_NUM_STRING (literal) = num_string;
10736e4b17023SJohn Marino return literal;
10737e4b17023SJohn Marino }
10738e4b17023SJohn Marino
10739e4b17023SJohn Marino #include "gt-c-family-c-common.h"
10740