]>
Commit | Line | Data |
---|---|---|
e04a16fb | 1 | /* Java(TM) language-specific utility routines. |
5624e564 | 2 | Copyright (C) 1996-2015 Free Software Foundation, Inc. |
e04a16fb | 3 | |
f309ff0a | 4 | This file is part of GCC. |
e04a16fb | 5 | |
f309ff0a | 6 | GCC is free software; you can redistribute it and/or modify |
e04a16fb | 7 | it under the terms of the GNU General Public License as published by |
8328d52a | 8 | the Free Software Foundation; either version 3, or (at your option) |
e04a16fb AG |
9 | any later version. |
10 | ||
f309ff0a | 11 | GCC is distributed in the hope that it will be useful, |
e04a16fb AG |
12 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | GNU General Public License for more details. | |
15 | ||
16 | You should have received a copy of the GNU General Public License | |
8328d52a NC |
17 | along with GCC; see the file COPYING3. If not see |
18 | <http://www.gnu.org/licenses/>. | |
e04a16fb AG |
19 | |
20 | Java and all Java-based marks are trademarks or registered trademarks | |
21 | of Sun Microsystems, Inc. in the United States and other countries. | |
22 | The Free Software Foundation is independent of Sun Microsystems, Inc. */ | |
23 | ||
24 | /* Hacked by Per Bothner <bothner@cygnus.com> February 1996. */ | |
25 | ||
e04a16fb | 26 | #include "config.h" |
1f43f4b4 | 27 | #include "system.h" |
4977bab6 ZW |
28 | #include "coretypes.h" |
29 | #include "tm.h" | |
40e23961 MC |
30 | #include "hash-set.h" |
31 | #include "machmode.h" | |
32 | #include "vec.h" | |
33 | #include "double-int.h" | |
34 | #include "input.h" | |
35 | #include "alias.h" | |
36 | #include "symtab.h" | |
37 | #include "wide-int.h" | |
38 | #include "inchash.h" | |
e04a16fb AG |
39 | #include "tree.h" |
40 | #include "input.h" | |
41 | #include "java-tree.h" | |
42 | #include "jcf.h" | |
c83303d8 | 43 | #include "langhooks.h" |
d23c55c2 | 44 | #include "langhooks-def.h" |
fc45c7ef | 45 | #include "flags.h" |
19e223db | 46 | #include "ggc.h" |
46f018e1 | 47 | #include "diagnostic.h" |
7149627b | 48 | #include "tree-inline.h" |
3eb429b2 | 49 | #include "splay-tree.h" |
c1ddb5c8 | 50 | #include "tree-dump.h" |
c8b04b13 | 51 | #include "opts.h" |
d7b42618 | 52 | #include "options.h" |
f0a0390e | 53 | #include "target.h" |
47e0da37 | 54 | #include "context.h" |
b7436b72 | 55 | |
4bfec483 | 56 | static bool java_init (void); |
d2097937 | 57 | static void java_finish (void); |
7a9bf9a4 | 58 | static unsigned int java_option_lang_mask (void); |
a75bfaa6 | 59 | static void java_init_options_struct (struct gcc_options *); |
7a9bf9a4 | 60 | static void java_init_options (unsigned int, struct cl_decoded_option *); |
4bfec483 | 61 | static bool java_post_options (const char **); |
36d010ca | 62 | |
a4d8c676 | 63 | static bool java_handle_option (size_t, const char *, int, int, location_t, |
5f20c657 | 64 | const struct cl_option_handlers *); |
d2097937 | 65 | static void put_decl_string (const char *, int); |
df4aca79 | 66 | static void put_decl_node (tree, int); |
c94ed7a1 JJ |
67 | static void java_print_error_function (diagnostic_context *, const char *, |
68 | diagnostic_info *); | |
2bd3ecad | 69 | static bool java_dump_tree (void *, tree); |
d2097937 | 70 | static void dump_compound_expr (dump_info_p, tree); |
58f9752a | 71 | static bool java_decl_ok_for_sibcall (const_tree); |
0d811e1a | 72 | |
394d9fe7 AO |
73 | static enum classify_record java_classify_record (tree type); |
74 | ||
f9417da1 RG |
75 | static tree java_eh_personality (void); |
76 | ||
45936a85 DD |
77 | #ifndef TARGET_OBJECT_SUFFIX |
78 | # define TARGET_OBJECT_SUFFIX ".o" | |
8603f9c5 TT |
79 | #endif |
80 | ||
e6b7893e AH |
81 | /* Table of machine-independent attributes. */ |
82 | const struct attribute_spec java_attribute_table[] = | |
83 | { | |
84 | { "nonnull", 0, -1, false, true, true, | |
62d784f7 KT |
85 | NULL, false }, |
86 | { NULL, 0, 0, false, false, false, NULL, false } | |
e6b7893e AH |
87 | }; |
88 | ||
7cb32822 NB |
89 | /* Used to avoid printing error messages with bogus function |
90 | prototypes. Starts out false. */ | |
91 | static bool inhibit_error_function_printing; | |
92 | ||
95ca6d8b | 93 | const char *resource_name; |
7be5b0e5 | 94 | |
ee142fe7 | 95 | /* When nonzero, -Wall was turned on. */ |
c877974e APB |
96 | int flag_wall = 0; |
97 | ||
36739040 TT |
98 | /* When nonzero, report use of deprecated classes, methods, or fields. */ |
99 | int flag_deprecated = 1; | |
100 | ||
101 | /* When zero, don't optimize static class initialization. This flag shouldn't | |
102 | be tested alone, use STATIC_CLASS_INITIALIZATION_OPTIMIZATION_P instead. */ | |
103 | /* FIXME: Make this work with gimplify. */ | |
104 | /* int flag_optimize_sci = 0; */ | |
105 | ||
106 | /* Don't attempt to verify invocations. */ | |
107 | int flag_verify_invocations = 0; | |
108 | ||
ee142fe7 | 109 | /* When nonzero, print extra version information. */ |
d185d268 | 110 | static int v_flag = 0; |
4266d0b2 | 111 | |
e04a16fb AG |
112 | JCF *current_jcf; |
113 | ||
fc45c7ef | 114 | /* Variable controlling how dependency tracking is enabled in |
f5e99456 | 115 | java_init. */ |
fc45c7ef TT |
116 | static int dependency_tracking = 0; |
117 | ||
118 | /* Flag values for DEPENDENCY_TRACKING. */ | |
119 | #define DEPEND_SET_FILE 1 | |
120 | #define DEPEND_ENABLE 2 | |
316a06a1 TT |
121 | #define DEPEND_TARGET_SET 4 |
122 | #define DEPEND_FILE_ALREADY_SET 8 | |
fc45c7ef | 123 | |
d1b38208 | 124 | struct GTY(()) language_function { |
e2500fed GK |
125 | int unused; |
126 | }; | |
127 | ||
3ac88239 NB |
128 | #undef LANG_HOOKS_NAME |
129 | #define LANG_HOOKS_NAME "GNU Java" | |
c83303d8 APB |
130 | #undef LANG_HOOKS_INIT |
131 | #define LANG_HOOKS_INIT java_init | |
22703ccc NB |
132 | #undef LANG_HOOKS_FINISH |
133 | #define LANG_HOOKS_FINISH java_finish | |
7a9bf9a4 JM |
134 | #undef LANG_HOOKS_OPTION_LANG_MASK |
135 | #define LANG_HOOKS_OPTION_LANG_MASK java_option_lang_mask | |
a75bfaa6 JM |
136 | #undef LANG_HOOKS_INIT_OPTIONS_STRUCT |
137 | #define LANG_HOOKS_INIT_OPTIONS_STRUCT java_init_options_struct | |
c83303d8 APB |
138 | #undef LANG_HOOKS_INIT_OPTIONS |
139 | #define LANG_HOOKS_INIT_OPTIONS java_init_options | |
95ca6d8b NB |
140 | #undef LANG_HOOKS_HANDLE_OPTION |
141 | #define LANG_HOOKS_HANDLE_OPTION java_handle_option | |
36d010ca BM |
142 | #undef LANG_HOOKS_POST_OPTIONS |
143 | #define LANG_HOOKS_POST_OPTIONS java_post_options | |
52dabb6c NB |
144 | #undef LANG_HOOKS_PARSE_FILE |
145 | #define LANG_HOOKS_PARSE_FILE java_parse_file | |
63e1b1c4 NB |
146 | #undef LANG_HOOKS_DUP_LANG_SPECIFIC_DECL |
147 | #define LANG_HOOKS_DUP_LANG_SPECIFIC_DECL java_dup_lang_specific_decl | |
7afff7cf NB |
148 | #undef LANG_HOOKS_DECL_PRINTABLE_NAME |
149 | #define LANG_HOOKS_DECL_PRINTABLE_NAME lang_printable_name | |
7cb32822 NB |
150 | #undef LANG_HOOKS_PRINT_ERROR_FUNCTION |
151 | #define LANG_HOOKS_PRINT_ERROR_FUNCTION java_print_error_function | |
6bb0a66a JJ |
152 | #undef LANG_HOOKS_WRITE_GLOBALS |
153 | #define LANG_HOOKS_WRITE_GLOBALS java_write_globals | |
ceef8ce4 | 154 | |
b0c48229 NB |
155 | #undef LANG_HOOKS_TYPE_FOR_MODE |
156 | #define LANG_HOOKS_TYPE_FOR_MODE java_type_for_mode | |
157 | #undef LANG_HOOKS_TYPE_FOR_SIZE | |
158 | #define LANG_HOOKS_TYPE_FOR_SIZE java_type_for_size | |
394d9fe7 AO |
159 | #undef LANG_HOOKS_CLASSIFY_RECORD |
160 | #define LANG_HOOKS_CLASSIFY_RECORD java_classify_record | |
c83303d8 | 161 | |
c1ddb5c8 AH |
162 | #undef LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN |
163 | #define LANG_HOOKS_TREE_DUMP_DUMP_TREE_FN java_dump_tree | |
164 | ||
6de9cd9a DN |
165 | #undef LANG_HOOKS_GIMPLIFY_EXPR |
166 | #define LANG_HOOKS_GIMPLIFY_EXPR java_gimplify_expr | |
167 | ||
e076f71a AH |
168 | #undef LANG_HOOKS_DECL_OK_FOR_SIBCALL |
169 | #define LANG_HOOKS_DECL_OK_FOR_SIBCALL java_decl_ok_for_sibcall | |
170 | ||
6de33afa RH |
171 | #undef LANG_HOOKS_SET_DECL_ASSEMBLER_NAME |
172 | #define LANG_HOOKS_SET_DECL_ASSEMBLER_NAME java_mangle_decl | |
173 | ||
e6b7893e AH |
174 | #undef LANG_HOOKS_ATTRIBUTE_TABLE |
175 | #define LANG_HOOKS_ATTRIBUTE_TABLE java_attribute_table | |
176 | ||
f9417da1 RG |
177 | #undef LANG_HOOKS_EH_PERSONALITY |
178 | #define LANG_HOOKS_EH_PERSONALITY java_eh_personality | |
179 | ||
384c400a RH |
180 | #undef LANG_HOOKS_EH_USE_CXA_END_CLEANUP |
181 | #define LANG_HOOKS_EH_USE_CXA_END_CLEANUP true | |
182 | ||
cd2a3ba2 | 183 | /* Each front end provides its own. */ |
4537ec0c | 184 | struct lang_hooks lang_hooks = LANG_HOOKS_INITIALIZER; |
cd2a3ba2 | 185 | |
e04a16fb AG |
186 | /* |
187 | * process java-specific compiler command-line options | |
5f20c657 | 188 | * return false, but do not complain if the option is not recognized. |
e04a16fb | 189 | */ |
5f20c657 | 190 | static bool |
3734d960 | 191 | java_handle_option (size_t scode, const char *arg, int value, |
a4d8c676 | 192 | int kind ATTRIBUTE_UNUSED, location_t loc ATTRIBUTE_UNUSED, |
5f20c657 | 193 | const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED) |
e04a16fb | 194 | { |
95ca6d8b | 195 | enum opt_code code = (enum opt_code) scode; |
2a85660d | 196 | |
95ca6d8b | 197 | switch (code) |
e04a16fb | 198 | { |
95ca6d8b NB |
199 | case OPT_I: |
200 | jcf_path_include_arg (arg); | |
201 | break; | |
7f10c2e2 | 202 | |
95ca6d8b NB |
203 | case OPT_M: |
204 | jcf_dependency_init (1); | |
205 | dependency_tracking |= DEPEND_ENABLE; | |
206 | break; | |
5f1c312a | 207 | |
cef67dce | 208 | case OPT_MD_: |
fc45c7ef TT |
209 | jcf_dependency_init (1); |
210 | dependency_tracking |= DEPEND_SET_FILE | DEPEND_ENABLE; | |
95ca6d8b NB |
211 | break; |
212 | ||
213 | case OPT_MF: | |
214 | jcf_dependency_set_dep_file (arg); | |
4a09cbac | 215 | dependency_tracking |= DEPEND_FILE_ALREADY_SET; |
95ca6d8b NB |
216 | break; |
217 | ||
218 | case OPT_MM: | |
fc45c7ef | 219 | jcf_dependency_init (0); |
fc45c7ef | 220 | dependency_tracking |= DEPEND_ENABLE; |
95ca6d8b NB |
221 | break; |
222 | ||
cef67dce | 223 | case OPT_MMD_: |
fc45c7ef | 224 | jcf_dependency_init (0); |
95ca6d8b NB |
225 | dependency_tracking |= DEPEND_SET_FILE | DEPEND_ENABLE; |
226 | break; | |
227 | ||
228 | case OPT_MP: | |
316a06a1 | 229 | jcf_dependency_print_dummies (); |
95ca6d8b NB |
230 | break; |
231 | ||
232 | case OPT_MT: | |
233 | jcf_dependency_set_target (arg); | |
316a06a1 | 234 | dependency_tracking |= DEPEND_TARGET_SET; |
95ca6d8b | 235 | break; |
fc45c7ef | 236 | |
95ca6d8b NB |
237 | case OPT_Wall: |
238 | flag_wall = value; | |
95ca6d8b NB |
239 | /* When -Wall given, enable -Wunused. We do this because the C |
240 | compiler does it, and people expect it. */ | |
e73f7547 | 241 | warn_unused = value; |
95ca6d8b NB |
242 | break; |
243 | ||
24d82bce PB |
244 | case OPT_fenable_assertions_: |
245 | add_enable_assert (arg, value); | |
246 | break; | |
247 | ||
248 | case OPT_fenable_assertions: | |
249 | add_enable_assert ("", value); | |
250 | break; | |
251 | ||
252 | case OPT_fdisable_assertions_: | |
253 | add_enable_assert (arg, !value); | |
254 | break; | |
255 | ||
256 | case OPT_fdisable_assertions: | |
257 | add_enable_assert ("", !value); | |
258 | break; | |
259 | ||
95ca6d8b NB |
260 | case OPT_fassume_compiled_: |
261 | add_assume_compiled (arg, !value); | |
262 | break; | |
263 | ||
264 | case OPT_fassume_compiled: | |
265 | add_assume_compiled ("", !value); | |
266 | break; | |
267 | ||
268 | case OPT_fbootclasspath_: | |
269 | jcf_path_bootclasspath_arg (arg); | |
270 | break; | |
271 | ||
97b8365c | 272 | case OPT_faux_classpath: |
95ca6d8b | 273 | case OPT_fclasspath_: |
95ca6d8b NB |
274 | jcf_path_classpath_arg (arg); |
275 | break; | |
276 | ||
277 | case OPT_fcompile_resource_: | |
278 | resource_name = arg; | |
279 | break; | |
280 | ||
281 | case OPT_fdump_: | |
47e0da37 | 282 | if (!g->get_dumps ()->dump_switch_p (arg)) |
5f20c657 | 283 | return false; |
95ca6d8b NB |
284 | break; |
285 | ||
95ca6d8b | 286 | case OPT_fencoding_: |
97b8365c | 287 | /* Nothing. */ |
95ca6d8b NB |
288 | break; |
289 | ||
290 | case OPT_fextdirs_: | |
291 | jcf_path_extdirs_arg (arg); | |
292 | break; | |
293 | ||
95ca6d8b | 294 | case OPT_foutput_class_dir_: |
97b8365c | 295 | /* FIXME: remove; this is handled by ecj1 now. */ |
95ca6d8b NB |
296 | break; |
297 | ||
95ca6d8b | 298 | case OPT_version: |
d185d268 | 299 | v_flag = 1; |
95ca6d8b | 300 | break; |
9ddfe26e | 301 | |
97b8365c TT |
302 | case OPT_fsource_filename_: |
303 | java_read_sourcefilenames (arg); | |
304 | break; | |
305 | ||
9ddfe26e KC |
306 | default: |
307 | if (cl_options[code].flags & CL_Java) | |
308 | break; | |
ab184b2a | 309 | gcc_unreachable (); |
95ca6d8b NB |
310 | } |
311 | ||
5f20c657 | 312 | return true; |
e04a16fb AG |
313 | } |
314 | ||
d19cbcb5 | 315 | /* Global open file. */ |
e04a16fb | 316 | FILE *finput; |
d19cbcb5 | 317 | |
4bfec483 NB |
318 | static bool |
319 | java_init (void) | |
e04a16fb | 320 | { |
85194ee9 AH |
321 | /* FIXME: Indirect dispatch isn't yet compatible with static class |
322 | init optimization. */ | |
323 | if (flag_indirect_dispatch) | |
324 | always_initialize_class_p = true; | |
325 | ||
621ae65d AH |
326 | if (!flag_indirect_dispatch) |
327 | flag_indirect_classes = false; | |
328 | ||
d185d268 | 329 | jcf_path_seal (v_flag); |
f5e99456 | 330 | |
f5e99456 NB |
331 | java_init_decl_processing (); |
332 | ||
333 | using_eh_for_cleanups (); | |
334 | ||
4bfec483 | 335 | return true; |
e04a16fb AG |
336 | } |
337 | ||
22703ccc | 338 | static void |
0a2f0c54 | 339 | java_finish (void) |
e04a16fb | 340 | { |
fc45c7ef | 341 | jcf_dependency_write (); |
e04a16fb AG |
342 | } |
343 | ||
344 | /* Buffer used by lang_printable_name. */ | |
345 | static char *decl_buf = NULL; | |
346 | ||
347 | /* Allocated size of decl_buf. */ | |
348 | static int decl_buflen = 0; | |
349 | ||
350 | /* Length of used part of decl_buf; position for next character. */ | |
351 | static int decl_bufpos = 0; | |
352 | ||
353 | /* Append the string STR to decl_buf. | |
354 | It length is given by LEN; -1 means the string is nul-terminated. */ | |
355 | ||
356 | static void | |
0a2f0c54 | 357 | put_decl_string (const char *str, int len) |
e04a16fb AG |
358 | { |
359 | if (len < 0) | |
360 | len = strlen (str); | |
361 | if (decl_bufpos + len >= decl_buflen) | |
362 | { | |
363 | if (decl_buf == NULL) | |
364 | { | |
365 | decl_buflen = len + 100; | |
5ed6ace5 | 366 | decl_buf = XNEWVEC (char, decl_buflen); |
e04a16fb AG |
367 | } |
368 | else | |
369 | { | |
370 | decl_buflen *= 2; | |
e1e4cdc4 | 371 | decl_buf = XRESIZEVAR (char, decl_buf, decl_buflen); |
e04a16fb AG |
372 | } |
373 | } | |
374 | strcpy (decl_buf + decl_bufpos, str); | |
375 | decl_bufpos += len; | |
376 | } | |
377 | ||
df4aca79 DS |
378 | /* Append to decl_buf a printable name for NODE. |
379 | Depending on VERBOSITY, more information about NODE | |
380 | is printed. Read the comments of decl_printable_name in | |
381 | langhooks.h for more. */ | |
e04a16fb AG |
382 | |
383 | static void | |
df4aca79 | 384 | put_decl_node (tree node, int verbosity) |
e04a16fb AG |
385 | { |
386 | int was_pointer = 0; | |
387 | if (TREE_CODE (node) == POINTER_TYPE) | |
388 | { | |
389 | node = TREE_TYPE (node); | |
390 | was_pointer = 1; | |
391 | } | |
6615c446 | 392 | if (DECL_P (node) && DECL_NAME (node) != NULL_TREE) |
e04a16fb | 393 | { |
bc8a5e56 | 394 | if (TREE_CODE (node) == FUNCTION_DECL) |
2c36c7fd | 395 | { |
df4aca79 DS |
396 | if (verbosity == 0 && DECL_NAME (node)) |
397 | /* We have been instructed to just print the bare name | |
398 | of the function. */ | |
399 | { | |
400 | put_decl_node (DECL_NAME (node), 0); | |
401 | return; | |
402 | } | |
403 | ||
bc8a5e56 PB |
404 | /* We want to print the type the DECL belongs to. We don't do |
405 | that when we handle constructors. */ | |
406 | if (! DECL_CONSTRUCTOR_P (node) | |
df4aca79 DS |
407 | && ! DECL_ARTIFICIAL (node) && DECL_CONTEXT (node) |
408 | /* We want to print qualified DECL names only | |
409 | if verbosity is higher than 1. */ | |
410 | && verbosity >= 1) | |
e04a16fb | 411 | { |
9dd22dd8 DK |
412 | put_decl_node (TREE_CODE (DECL_CONTEXT (node)) == FUNCTION_DECL |
413 | ? DECL_CONTEXT (node) | |
414 | : TYPE_NAME (DECL_CONTEXT (node)), | |
df4aca79 | 415 | verbosity); |
bc8a5e56 PB |
416 | put_decl_string (".", 1); |
417 | } | |
418 | if (! DECL_CONSTRUCTOR_P (node)) | |
df4aca79 DS |
419 | put_decl_node (DECL_NAME (node), verbosity); |
420 | if (TREE_TYPE (node) != NULL_TREE | |
421 | /* We want to print function parameters only if verbosity | |
422 | is higher than 2. */ | |
423 | && verbosity >= 2) | |
bc8a5e56 PB |
424 | { |
425 | int i = 0; | |
426 | tree args = TYPE_ARG_TYPES (TREE_TYPE (node)); | |
427 | if (TREE_CODE (TREE_TYPE (node)) == METHOD_TYPE) | |
428 | args = TREE_CHAIN (args); | |
429 | put_decl_string ("(", 1); | |
226e58b7 KT |
430 | for ( ; args != NULL_TREE && args != end_params_node; |
431 | args = TREE_CHAIN (args), i++) | |
bc8a5e56 PB |
432 | { |
433 | if (i > 0) | |
434 | put_decl_string (",", 1); | |
df4aca79 | 435 | put_decl_node (TREE_VALUE (args), verbosity); |
bc8a5e56 PB |
436 | } |
437 | put_decl_string (")", 1); | |
e04a16fb | 438 | } |
e04a16fb | 439 | } |
bc8a5e56 | 440 | else |
df4aca79 | 441 | put_decl_node (DECL_NAME (node), verbosity); |
e04a16fb | 442 | } |
6615c446 | 443 | else if (TYPE_P (node) && TYPE_NAME (node) != NULL_TREE) |
e04a16fb | 444 | { |
df4aca79 DS |
445 | if (TREE_CODE (node) == RECORD_TYPE && TYPE_ARRAY_P (node) |
446 | /* Print detailed array information only if verbosity is higher | |
447 | than 2. */ | |
448 | && verbosity >= 2) | |
e04a16fb | 449 | { |
df4aca79 | 450 | put_decl_node (TYPE_ARRAY_ELEMENT (node), verbosity); |
e04a16fb AG |
451 | put_decl_string("[]", 2); |
452 | } | |
453 | else if (node == promoted_byte_type_node) | |
454 | put_decl_string ("byte", 4); | |
455 | else if (node == promoted_short_type_node) | |
456 | put_decl_string ("short", 5); | |
457 | else if (node == promoted_char_type_node) | |
458 | put_decl_string ("char", 4); | |
459 | else if (node == promoted_boolean_type_node) | |
460 | put_decl_string ("boolean", 7); | |
461 | else if (node == void_type_node && was_pointer) | |
462 | put_decl_string ("null", 4); | |
463 | else | |
df4aca79 | 464 | put_decl_node (TYPE_NAME (node), verbosity); |
e04a16fb AG |
465 | } |
466 | else if (TREE_CODE (node) == IDENTIFIER_NODE) | |
467 | put_decl_string (IDENTIFIER_POINTER (node), IDENTIFIER_LENGTH (node)); | |
468 | else | |
469 | put_decl_string ("<unknown>", -1); | |
470 | } | |
471 | ||
472 | /* Return a user-friendly name for DECL. | |
473 | The resulting string is only valid until the next call. | |
474 | The value of the hook decl_printable_name is this function, | |
7cb32822 | 475 | which is also called directly by java_print_error_function. */ |
e04a16fb | 476 | |
1b93a502 | 477 | const char * |
1b9deeb4 | 478 | lang_printable_name (tree decl, int v) |
e04a16fb AG |
479 | { |
480 | decl_bufpos = 0; | |
df4aca79 | 481 | put_decl_node (decl, v); |
761491c8 | 482 | put_decl_string ("", 1); |
761491c8 APB |
483 | return decl_buf; |
484 | } | |
485 | ||
e04a16fb | 486 | /* Print on stderr the current class and method context. This function |
7cb32822 | 487 | is the value of the hook print_error_function. */ |
e04a16fb | 488 | |
e2500fed GK |
489 | static GTY(()) tree last_error_function_context; |
490 | static GTY(()) tree last_error_function; | |
be245ac0 | 491 | static void |
0a2f0c54 | 492 | java_print_error_function (diagnostic_context *context ATTRIBUTE_UNUSED, |
c94ed7a1 JJ |
493 | const char *file, |
494 | diagnostic_info *diagnostic ATTRIBUTE_UNUSED) | |
e04a16fb | 495 | { |
7cb32822 NB |
496 | /* Don't print error messages with bogus function prototypes. */ |
497 | if (inhibit_error_function_printing) | |
498 | return; | |
499 | ||
e04a16fb | 500 | if (current_function_decl != NULL |
1cbd1174 | 501 | && DECL_CONTEXT (current_function_decl) != NULL |
e04a16fb AG |
502 | && DECL_CONTEXT (current_function_decl) != last_error_function_context) |
503 | { | |
504 | if (file) | |
505 | fprintf (stderr, "%s: ", file); | |
506 | ||
507 | last_error_function_context = DECL_CONTEXT (current_function_decl); | |
a1402da3 | 508 | fprintf (stderr, "In class '%s':\n", |
0a2138e2 | 509 | lang_printable_name (last_error_function_context, 0)); |
e04a16fb AG |
510 | } |
511 | if (last_error_function != current_function_decl) | |
512 | { | |
513 | if (file) | |
514 | fprintf (stderr, "%s: ", file); | |
515 | ||
516 | if (current_function_decl == NULL) | |
517 | fprintf (stderr, "At top level:\n"); | |
518 | else | |
519 | { | |
c8e7d2e6 | 520 | const char *name = lang_printable_name (current_function_decl, 2); |
a1402da3 | 521 | fprintf (stderr, "In %s '%s':\n", |
9f63daea | 522 | (DECL_CONSTRUCTOR_P (current_function_decl) ? "constructor" |
bc8a5e56 PB |
523 | : "method"), |
524 | name); | |
e04a16fb AG |
525 | } |
526 | ||
527 | last_error_function = current_function_decl; | |
528 | } | |
529 | ||
530 | } | |
531 | ||
e04a16fb AG |
532 | /* Called to install the PRINT_ERROR_FUNCTION hook differently |
533 | according to LEVEL. LEVEL is 1 during early parsing, when function | |
7cb32822 NB |
534 | prototypes aren't fully resolved. java_print_error_function is set |
535 | so it doesn't print incomplete function prototypes. When LEVEL is | |
536 | 2, function prototypes are fully resolved and can be printed when | |
e04a16fb AG |
537 | reporting errors. */ |
538 | ||
fe0b9fb5 RM |
539 | void |
540 | lang_init_source (int level) | |
e04a16fb | 541 | { |
7cb32822 | 542 | inhibit_error_function_printing = (level == 1); |
e04a16fb AG |
543 | } |
544 | ||
b86f6cd9 | 545 | static unsigned int |
7a9bf9a4 JM |
546 | java_option_lang_mask (void) |
547 | { | |
548 | return CL_Java; | |
549 | } | |
550 | ||
a75bfaa6 JM |
551 | /* Initialize options structure OPTS. */ |
552 | ||
7a9bf9a4 | 553 | static void |
a75bfaa6 | 554 | java_init_options_struct (struct gcc_options *opts) |
e04a16fb | 555 | { |
a75bfaa6 JM |
556 | opts->x_flag_bounds_check = 1; |
557 | opts->x_flag_exceptions = 1; | |
558 | opts->x_flag_non_call_exceptions = 1; | |
f5eb5fd0 JH |
559 | |
560 | /* In Java floating point operations never trap. */ | |
a75bfaa6 | 561 | opts->x_flag_trapping_math = 0; |
ff06e6b1 | 562 | opts->frontend_set_flag_trapping_math = true; |
4fa26a60 RS |
563 | |
564 | /* In Java arithmetic overflow always wraps around. */ | |
a75bfaa6 | 565 | opts->x_flag_wrapv = 1; |
2772ef3e | 566 | |
c67e6e14 | 567 | /* Java requires left-to-right evaluation of subexpressions. */ |
a75bfaa6 | 568 | opts->x_flag_evaluation_order = 1; |
810fb8f1 JL |
569 | |
570 | /* Java catches NULL pointer exceptions, thus we can not necessarily | |
571 | rely on a pointer having a non-NULL value after a dereference. */ | |
572 | opts->x_flag_delete_null_pointer_checks = 0; | |
a75bfaa6 | 573 | } |
c67e6e14 | 574 | |
a75bfaa6 JM |
575 | static void |
576 | java_init_options (unsigned int decoded_options_count ATTRIBUTE_UNUSED, | |
577 | struct cl_decoded_option *decoded_options ATTRIBUTE_UNUSED) | |
578 | { | |
95ca6d8b | 579 | jcf_path_init (); |
e04a16fb | 580 | } |
e2500fed | 581 | |
36d010ca | 582 | /* Post-switch processing. */ |
5351f1ca | 583 | static bool |
4bfec483 | 584 | java_post_options (const char **pfilename) |
36d010ca | 585 | { |
4bfec483 NB |
586 | const char *filename = *pfilename; |
587 | ||
8ce94e44 JM |
588 | /* Excess precision other than "fast" requires front-end |
589 | support. */ | |
590 | if (flag_excess_precision_cmdline == EXCESS_PRECISION_STANDARD | |
591 | && TARGET_FLT_EVAL_METHOD_NON_DEFAULT) | |
592 | sorry ("-fexcess-precision=standard for Java"); | |
593 | flag_excess_precision_cmdline = EXCESS_PRECISION_FAST; | |
594 | ||
36739040 TT |
595 | /* An absolute requirement: if we're not using indirect dispatch, we |
596 | must always verify everything. */ | |
597 | if (! flag_indirect_dispatch) | |
598 | flag_verify_invocations = true; | |
599 | ||
dba370a8 DD |
600 | if (flag_reduced_reflection) |
601 | { | |
602 | if (flag_indirect_dispatch) | |
603 | error ("-findirect-dispatch is incompatible " | |
604 | "with -freduced-reflection"); | |
605 | if (flag_jni) | |
606 | error ("-fjni is incompatible with -freduced-reflection"); | |
607 | } | |
608 | ||
4bfec483 NB |
609 | /* Open input file. */ |
610 | ||
611 | if (filename == 0 || !strcmp (filename, "-")) | |
612 | { | |
613 | finput = stdin; | |
614 | filename = "stdin"; | |
615 | ||
616 | if (dependency_tracking) | |
d8a07487 | 617 | error ("can%'t do dependency tracking with input from stdin"); |
4bfec483 NB |
618 | } |
619 | else | |
620 | { | |
621 | if (dependency_tracking) | |
622 | { | |
c24ea667 | 623 | const char *dot; |
4bfec483 NB |
624 | |
625 | /* If the target is set and the output filename is set, then | |
626 | there's no processing to do here. Otherwise we must | |
627 | compute one or the other. */ | |
628 | if (! ((dependency_tracking & DEPEND_TARGET_SET) | |
629 | && (dependency_tracking & DEPEND_FILE_ALREADY_SET))) | |
630 | { | |
631 | dot = strrchr (filename, '.'); | |
632 | if (dot == NULL) | |
d8a07487 | 633 | error ("couldn%'t determine target name for dependency tracking"); |
4bfec483 NB |
634 | else |
635 | { | |
5ed6ace5 | 636 | char *buf = XNEWVEC (char, dot - filename + |
4bfec483 NB |
637 | 3 + sizeof (TARGET_OBJECT_SUFFIX)); |
638 | strncpy (buf, filename, dot - filename); | |
639 | ||
640 | /* If emitting class files, we might have multiple | |
641 | targets. The class generation code takes care of | |
642 | registering them. Otherwise we compute the | |
643 | target name here. */ | |
644 | if ((dependency_tracking & DEPEND_TARGET_SET)) | |
645 | ; /* Nothing. */ | |
4bfec483 NB |
646 | else |
647 | { | |
648 | strcpy (buf + (dot - filename), TARGET_OBJECT_SUFFIX); | |
649 | jcf_dependency_set_target (buf); | |
650 | } | |
651 | ||
652 | if ((dependency_tracking & DEPEND_FILE_ALREADY_SET)) | |
653 | ; /* Nothing. */ | |
654 | else if ((dependency_tracking & DEPEND_SET_FILE)) | |
655 | { | |
656 | strcpy (buf + (dot - filename), ".d"); | |
657 | jcf_dependency_set_dep_file (buf); | |
658 | } | |
659 | else | |
660 | jcf_dependency_set_dep_file ("-"); | |
661 | ||
662 | free (buf); | |
663 | } | |
664 | } | |
665 | } | |
666 | } | |
5ffeb913 TT |
667 | linemap_add (line_table, LC_ENTER, false, filename, 0); |
668 | linemap_add (line_table, LC_RENAME, false, "<built-in>", 0); | |
4bfec483 | 669 | |
5351f1ca NB |
670 | /* Initialize the compiler back end. */ |
671 | return false; | |
36d010ca BM |
672 | } |
673 | ||
7149627b AH |
674 | /* Return either DECL or its known constant value (if it has one). */ |
675 | ||
676 | tree | |
0a2f0c54 | 677 | decl_constant_value (tree decl) |
7149627b AH |
678 | { |
679 | if (/* Don't change a variable array bound or initial value to a constant | |
680 | in a place where a variable is invalid. */ | |
681 | current_function_decl != 0 | |
682 | && ! TREE_THIS_VOLATILE (decl) | |
683 | && TREE_READONLY (decl) | |
684 | && DECL_INITIAL (decl) != 0 | |
685 | && TREE_CODE (DECL_INITIAL (decl)) != ERROR_MARK | |
686 | /* This is invalid if initial value is not constant. | |
687 | If it has either a function call, a memory reference, | |
688 | or a variable, then re-evaluating it could give different results. */ | |
689 | && TREE_CONSTANT (DECL_INITIAL (decl)) | |
690 | /* Check for cases where this is sub-optimal, even though valid. */ | |
691 | && TREE_CODE (DECL_INITIAL (decl)) != CONSTRUCTOR) | |
692 | return DECL_INITIAL (decl); | |
693 | return decl; | |
694 | } | |
695 | ||
3eb429b2 AH |
696 | /* Every call to a static constructor has an associated boolean |
697 | variable which is in the outermost scope of the calling method. | |
698 | This variable is used to avoid multiple calls to the static | |
9f63daea | 699 | constructor for each class. |
3eb429b2 | 700 | |
634661fe | 701 | It looks something like this: |
3eb429b2 AH |
702 | |
703 | foo () | |
704 | { | |
705 | boolean dummy = OtherClass.is_initialized; | |
9f63daea | 706 | |
3eb429b2 | 707 | ... |
9f63daea | 708 | |
3eb429b2 AH |
709 | if (! dummy) |
710 | OtherClass.initialize(); | |
711 | ||
712 | ... use OtherClass.data ... | |
713 | } | |
714 | ||
715 | Each of these boolean variables has an entry in the | |
716 | DECL_FUNCTION_INIT_TEST_TABLE of a method. When inlining a method | |
717 | we must merge the DECL_FUNCTION_INIT_TEST_TABLE from the function | |
634661fe | 718 | being inlined and create the boolean variables in the outermost |
3eb429b2 AH |
719 | scope of the method being inlined into. */ |
720 | ||
721 | /* Create a mapping from a boolean variable in a method being inlined | |
722 | to one in the scope of the method being inlined into. */ | |
723 | ||
2a22f99c TS |
724 | int |
725 | merge_init_test_initialization (treetreehash_entry **entry, void *x) | |
3eb429b2 | 726 | { |
2a22f99c | 727 | struct treetreehash_entry *ite = *entry; |
3eb429b2 AH |
728 | splay_tree decl_map = (splay_tree)x; |
729 | splay_tree_node n; | |
730 | tree *init_test_decl; | |
9f63daea | 731 | |
3eb429b2 AH |
732 | /* See if we have remapped this declaration. If we haven't there's |
733 | a bug in the inliner. */ | |
734 | n = splay_tree_lookup (decl_map, (splay_tree_key) ite->value); | |
ab184b2a | 735 | gcc_assert (n); |
3eb429b2 AH |
736 | |
737 | /* Create a new entry for the class and its remapped boolean | |
738 | variable. If we already have a mapping for this class we've | |
739 | already initialized it, so don't overwrite the value. */ | |
740 | init_test_decl = java_treetreehash_new | |
741 | (DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl), ite->key); | |
742 | if (!*init_test_decl) | |
743 | *init_test_decl = (tree)n->value; | |
744 | ||
9f63daea | 745 | /* This fixes a weird case. |
7304c6cf AH |
746 | |
747 | The front end assumes that once we have called a method that | |
748 | initializes some class, we can assume the class is initialized. It | |
749 | does this by setting the DECL_INITIAL of the init_test_decl for that | |
750 | class, and no initializations are emitted for that class. | |
9f63daea | 751 | |
df044388 | 752 | However, what if the method that is supposed to do the initialization |
7304c6cf | 753 | is itself inlined in the caller? When expanding the called method |
c048d56d | 754 | we'll assume that the class initialization has already been done, |
7304c6cf | 755 | because the DECL_INITIAL of the init_test_decl is set. |
9f63daea | 756 | |
7304c6cf AH |
757 | To fix this we remove the DECL_INITIAL (in the caller scope) of all |
758 | the init_test_decls corresponding to classes initialized by the | |
759 | inlined method. This makes the caller no longer assume that the | |
760 | method being inlined does any class initializations. */ | |
761 | DECL_INITIAL (*init_test_decl) = NULL; | |
762 | ||
3eb429b2 AH |
763 | return true; |
764 | } | |
765 | ||
766 | /* Merge the DECL_FUNCTION_INIT_TEST_TABLE from the function we're | |
767 | inlining. */ | |
768 | ||
769 | void | |
0a2f0c54 | 770 | java_inlining_merge_static_initializers (tree fn, void *decl_map) |
3eb429b2 | 771 | { |
2a22f99c TS |
772 | DECL_FUNCTION_INIT_TEST_TABLE (fn) |
773 | ->traverse<void *, merge_init_test_initialization> (decl_map); | |
3eb429b2 AH |
774 | } |
775 | ||
776 | /* Lookup a DECL_FUNCTION_INIT_TEST_TABLE entry in the method we're | |
777 | inlining into. If we already have a corresponding entry in that | |
778 | class we don't need to create another one, so we create a mapping | |
779 | from the variable in the inlined class to the corresponding | |
780 | pre-existing one. */ | |
781 | ||
2a22f99c TS |
782 | int |
783 | inline_init_test_initialization (treetreehash_entry **entry, void *x) | |
3eb429b2 | 784 | { |
2a22f99c | 785 | struct treetreehash_entry *ite = *entry; |
3eb429b2 | 786 | splay_tree decl_map = (splay_tree)x; |
9f63daea EC |
787 | |
788 | tree h = java_treetreehash_find | |
3eb429b2 AH |
789 | (DECL_FUNCTION_INIT_TEST_TABLE (current_function_decl), ite->key); |
790 | if (! h) | |
791 | return true; | |
3eb429b2 AH |
792 | splay_tree_insert (decl_map, |
793 | (splay_tree_key) ite->value, | |
794 | (splay_tree_value) h); | |
3eb429b2 AH |
795 | return true; |
796 | } | |
797 | ||
798 | /* Look up the boolean variables in the DECL_FUNCTION_INIT_TEST_TABLE | |
799 | of a method being inlined. For each hone, if we already have a | |
800 | variable associated with the same class in the method being inlined | |
801 | into, create a new mapping for it. */ | |
802 | ||
803 | void | |
0a2f0c54 | 804 | java_inlining_map_static_initializers (tree fn, void *decl_map) |
3eb429b2 | 805 | { |
2a22f99c TS |
806 | DECL_FUNCTION_INIT_TEST_TABLE (fn) |
807 | ->traverse<void *, inline_init_test_initialization> (decl_map); | |
3eb429b2 AH |
808 | } |
809 | ||
c1ddb5c8 AH |
810 | /* Avoid voluminous output for deep recursion of compound exprs. */ |
811 | ||
812 | static void | |
0a2f0c54 | 813 | dump_compound_expr (dump_info_p di, tree t) |
c1ddb5c8 AH |
814 | { |
815 | int i; | |
816 | ||
817 | for (i=0; i<2; i++) | |
818 | { | |
819 | switch (TREE_CODE (TREE_OPERAND (t, i))) | |
820 | { | |
821 | case COMPOUND_EXPR: | |
822 | dump_compound_expr (di, TREE_OPERAND (t, i)); | |
823 | break; | |
824 | ||
c1ddb5c8 AH |
825 | default: |
826 | dump_child ("expr", TREE_OPERAND (t, i)); | |
827 | } | |
828 | } | |
829 | } | |
9f63daea | 830 | |
2bd3ecad | 831 | static bool |
0a2f0c54 | 832 | java_dump_tree (void *dump_info, tree t) |
c1ddb5c8 AH |
833 | { |
834 | enum tree_code code; | |
835 | dump_info_p di = (dump_info_p) dump_info; | |
836 | ||
837 | /* Figure out what kind of node this is. */ | |
838 | code = TREE_CODE (t); | |
839 | ||
840 | switch (code) | |
841 | { | |
842 | case FUNCTION_DECL: | |
843 | dump_child ("args", DECL_ARGUMENTS (t)); | |
844 | if (DECL_EXTERNAL (t)) | |
845 | dump_string (di, "undefined"); | |
846 | if (TREE_PUBLIC (t)) | |
847 | dump_string (di, "extern"); | |
848 | else | |
849 | dump_string (di, "static"); | |
c1ddb5c8 AH |
850 | if (DECL_LANG_SPECIFIC (t) && !dump_flag (di, TDF_SLIM, t)) |
851 | dump_child ("inline body", DECL_SAVED_TREE (t)); | |
2bd3ecad | 852 | return true; |
c1ddb5c8 AH |
853 | |
854 | case RETURN_EXPR: | |
855 | dump_child ("expr", TREE_OPERAND (t, 0)); | |
2bd3ecad | 856 | return true; |
c1ddb5c8 AH |
857 | |
858 | case GOTO_EXPR: | |
859 | dump_child ("goto", TREE_OPERAND (t, 0)); | |
2bd3ecad | 860 | return true; |
c1ddb5c8 AH |
861 | |
862 | case LABEL_EXPR: | |
863 | dump_child ("label", TREE_OPERAND (t, 0)); | |
2bd3ecad | 864 | return true; |
c1ddb5c8 | 865 | |
c1ddb5c8 AH |
866 | case BLOCK: |
867 | if (BLOCK_EXPR_BODY (t)) | |
868 | { | |
869 | tree local = BLOCK_VARS (t); | |
870 | while (local) | |
871 | { | |
872 | tree next = TREE_CHAIN (local); | |
873 | dump_child ("var", local); | |
874 | local = next; | |
875 | } | |
9f63daea | 876 | |
c1ddb5c8 AH |
877 | { |
878 | tree block = BLOCK_EXPR_BODY (t); | |
879 | dump_child ("body", block); | |
880 | block = TREE_CHAIN (block); | |
881 | } | |
882 | } | |
2bd3ecad | 883 | return true; |
9f63daea | 884 | |
c1ddb5c8 AH |
885 | case COMPOUND_EXPR: |
886 | if (!dump_flag (di, TDF_SLIM, t)) | |
2bd3ecad | 887 | return false; |
c1ddb5c8 | 888 | dump_compound_expr (di, t); |
2bd3ecad | 889 | return true; |
c1ddb5c8 AH |
890 | |
891 | default: | |
892 | break; | |
893 | } | |
2bd3ecad | 894 | return false; |
c1ddb5c8 | 895 | } |
e076f71a AH |
896 | |
897 | /* Java calls can't, in general, be sibcalls because we need an | |
898 | accurate stack trace in order to guarantee correct operation of | |
899 | methods such as Class.forName(String) and | |
900 | SecurityManager.getClassContext(). */ | |
901 | ||
902 | static bool | |
58f9752a | 903 | java_decl_ok_for_sibcall (const_tree decl) |
e076f71a | 904 | { |
97b8365c | 905 | return (decl != NULL && DECL_CONTEXT (decl) == output_class |
0494626a | 906 | && !DECL_UNINLINABLE (decl)); |
e076f71a AH |
907 | } |
908 | ||
394d9fe7 AO |
909 | static enum classify_record |
910 | java_classify_record (tree type) | |
911 | { | |
912 | if (! CLASS_P (type)) | |
913 | return RECORD_IS_STRUCT; | |
914 | ||
1a17651b | 915 | if (CLASS_INTERFACE (TYPE_NAME (type))) |
394d9fe7 AO |
916 | return RECORD_IS_INTERFACE; |
917 | ||
918 | return RECORD_IS_CLASS; | |
919 | } | |
920 | ||
f9417da1 RG |
921 | static GTY(()) tree java_eh_personality_decl; |
922 | ||
923 | static tree | |
924 | java_eh_personality (void) | |
925 | { | |
926 | if (!java_eh_personality_decl) | |
bde8a146 | 927 | java_eh_personality_decl = build_personality_function ("gcj"); |
f9417da1 RG |
928 | return java_eh_personality_decl; |
929 | } | |
930 | ||
e2500fed | 931 | #include "gt-java-lang.h" |