Mercurial > hg > CbC > GCC_original
comparison gcc/plugin.c @ 16:04ced10e8804
gcc 7
author | kono |
---|---|
date | Fri, 27 Oct 2017 22:46:09 +0900 |
parents | f6334be47118 |
children | 84e7813d76e9 |
comparison
equal
deleted
inserted
replaced
15:561a7518be6b | 16:04ced10e8804 |
---|---|
1 /* Support for GCC plugin mechanism. | 1 /* Support for GCC plugin mechanism. |
2 Copyright (C) 2009, 2010 Free Software Foundation, Inc. | 2 Copyright (C) 2009-2017 Free Software Foundation, Inc. |
3 | 3 |
4 This file is part of GCC. | 4 This file is part of GCC. |
5 | 5 |
6 GCC is free software; you can redistribute it and/or modify | 6 GCC is free software; you can redistribute it and/or modify |
7 it under the terms of the GNU General Public License as published by | 7 it under the terms of the GNU General Public License as published by |
21 APIs described in doc/plugin.texi. */ | 21 APIs described in doc/plugin.texi. */ |
22 | 22 |
23 #include "config.h" | 23 #include "config.h" |
24 #include "system.h" | 24 #include "system.h" |
25 #include "coretypes.h" | 25 #include "coretypes.h" |
26 #include "options.h" | |
27 #include "tree-pass.h" | |
26 #include "diagnostic-core.h" | 28 #include "diagnostic-core.h" |
27 #include "tree.h" | 29 #include "flags.h" |
28 #include "tree-pass.h" | |
29 #include "intl.h" | 30 #include "intl.h" |
30 #include "plugin.h" | 31 #include "plugin.h" |
31 #include "timevar.h" | |
32 #include "ggc.h" | |
33 | 32 |
34 #ifdef ENABLE_PLUGIN | 33 #ifdef ENABLE_PLUGIN |
35 #include "plugin-version.h" | 34 #include "plugin-version.h" |
36 #endif | 35 #endif |
37 | 36 |
49 /* A printf format large enough for the largest event above. */ | 48 /* A printf format large enough for the largest event above. */ |
50 #define FMT_FOR_PLUGIN_EVENT "%-32s" | 49 #define FMT_FOR_PLUGIN_EVENT "%-32s" |
51 | 50 |
52 const char **plugin_event_name = plugin_event_name_init; | 51 const char **plugin_event_name = plugin_event_name_init; |
53 | 52 |
53 /* Event hashtable helpers. */ | |
54 | |
55 struct event_hasher : nofree_ptr_hash <const char *> | |
56 { | |
57 static inline hashval_t hash (const char **); | |
58 static inline bool equal (const char **, const char **); | |
59 }; | |
60 | |
61 /* Helper function for the event hash table that hashes the entry V. */ | |
62 | |
63 inline hashval_t | |
64 event_hasher::hash (const char **v) | |
65 { | |
66 return htab_hash_string (*v); | |
67 } | |
68 | |
69 /* Helper function for the event hash table that compares the name of an | |
70 existing entry (S1) with the given string (S2). */ | |
71 | |
72 inline bool | |
73 event_hasher::equal (const char **s1, const char **s2) | |
74 { | |
75 return !strcmp (*s1, *s2); | |
76 } | |
77 | |
54 /* A hash table to map event names to the position of the names in the | 78 /* A hash table to map event names to the position of the names in the |
55 plugin_event_name table. */ | 79 plugin_event_name table. */ |
56 static htab_t event_tab; | 80 static hash_table<event_hasher> *event_tab; |
57 | 81 |
58 /* Keep track of the limit of allocated events and space ready for | 82 /* Keep track of the limit of allocated events and space ready for |
59 allocating events. */ | 83 allocating events. */ |
60 static int event_last = PLUGIN_EVENT_FIRST_DYNAMIC; | 84 static int event_last = PLUGIN_EVENT_FIRST_DYNAMIC; |
61 static int event_horizon = PLUGIN_EVENT_FIRST_DYNAMIC; | 85 static int event_horizon = PLUGIN_EVENT_FIRST_DYNAMIC; |
87 | 111 |
88 /* Each plugin should define this symbol to assert that it is | 112 /* Each plugin should define this symbol to assert that it is |
89 distributed under a GPL-compatible license. */ | 113 distributed under a GPL-compatible license. */ |
90 static const char *str_license = "plugin_is_GPL_compatible"; | 114 static const char *str_license = "plugin_is_GPL_compatible"; |
91 #endif | 115 #endif |
116 | |
117 /* Helper function for hashing the base_name of the plugin_name_args | |
118 structure to be inserted into the hash table. */ | |
119 | |
120 static hashval_t | |
121 htab_hash_plugin (const PTR p) | |
122 { | |
123 const struct plugin_name_args *plugin = (const struct plugin_name_args *) p; | |
124 return htab_hash_string (plugin->base_name); | |
125 } | |
92 | 126 |
93 /* Helper function for the hash table that compares the base_name of the | 127 /* Helper function for the hash table that compares the base_name of the |
94 existing entry (S1) with the given string (S2). */ | 128 existing entry (S1) with the given string (S2). */ |
95 | 129 |
96 static int | 130 static int |
147 Windows or MacOS, this code has to be greatly improved. */ | 181 Windows or MacOS, this code has to be greatly improved. */ |
148 plugin_name = concat (default_plugin_dir_name (), "/", | 182 plugin_name = concat (default_plugin_dir_name (), "/", |
149 plugin_name, ".so", NULL); | 183 plugin_name, ".so", NULL); |
150 if (access (plugin_name, R_OK)) | 184 if (access (plugin_name, R_OK)) |
151 fatal_error | 185 fatal_error |
152 ("inacessible plugin file %s expanded from short plugin name %s: %m", | 186 (input_location, |
187 "inaccessible plugin file %s expanded from short plugin name %s: %m", | |
153 plugin_name, base_name); | 188 plugin_name, base_name); |
154 } | 189 } |
155 else | 190 else |
156 base_name = get_plugin_base_name (plugin_name); | 191 base_name = get_plugin_base_name (plugin_name); |
157 | 192 |
158 /* If this is the first -fplugin= option we encounter, create | 193 /* If this is the first -fplugin= option we encounter, create |
159 'plugin_name_args_tab' hash table. */ | 194 'plugin_name_args_tab' hash table. */ |
160 if (!plugin_name_args_tab) | 195 if (!plugin_name_args_tab) |
161 plugin_name_args_tab = htab_create (10, htab_hash_string, htab_str_eq, | 196 plugin_name_args_tab = htab_create (10, htab_hash_plugin, htab_str_eq, |
162 NULL); | 197 NULL); |
163 | 198 |
164 slot = htab_find_slot (plugin_name_args_tab, base_name, INSERT); | 199 slot = htab_find_slot_with_hash (plugin_name_args_tab, base_name, |
200 htab_hash_string (base_name), INSERT); | |
165 | 201 |
166 /* If the same plugin (name) has been specified earlier, either emit an | 202 /* If the same plugin (name) has been specified earlier, either emit an |
167 error or a warning message depending on if they have identical full | 203 error or a warning message depending on if they have identical full |
168 (path) names. */ | 204 (path) names. */ |
169 if (*slot) | 205 if (*slot) |
212 name_parsed = true; | 248 name_parsed = true; |
213 continue; | 249 continue; |
214 } | 250 } |
215 else if (*ptr == '=') | 251 else if (*ptr == '=') |
216 { | 252 { |
217 if (key_parsed) | 253 if (!key_parsed) |
218 { | 254 { |
219 error ("malformed option -fplugin-arg-%s (multiple '=' signs)", | 255 key_len = len; |
220 arg); | 256 len = 0; |
221 return; | 257 value_start = ptr + 1; |
222 } | 258 key_parsed = true; |
223 key_len = len; | 259 } |
224 len = 0; | |
225 value_start = ptr + 1; | |
226 key_parsed = true; | |
227 continue; | 260 continue; |
228 } | 261 } |
229 else | 262 else |
230 ++len; | 263 ++len; |
231 } | 264 } |
249 name[name_len] = '\0'; | 282 name[name_len] = '\0'; |
250 | 283 |
251 /* Check if the named plugin has already been specified earlier in the | 284 /* Check if the named plugin has already been specified earlier in the |
252 command-line. */ | 285 command-line. */ |
253 if (plugin_name_args_tab | 286 if (plugin_name_args_tab |
254 && ((slot = htab_find_slot (plugin_name_args_tab, name, NO_INSERT)) | 287 && ((slot = htab_find_slot_with_hash (plugin_name_args_tab, name, |
288 htab_hash_string (name), NO_INSERT)) | |
255 != NULL)) | 289 != NULL)) |
256 { | 290 { |
257 struct plugin_name_args *plugin = (struct plugin_name_args *) *slot; | 291 struct plugin_name_args *plugin = (struct plugin_name_args *) *slot; |
258 | 292 |
259 key = XNEWVEC (char, key_len + 1); | 293 key = XNEWVEC (char, key_len + 1); |
305 plugin_init. INFO is the information that should be registered. */ | 339 plugin_init. INFO is the information that should be registered. */ |
306 | 340 |
307 static void | 341 static void |
308 register_plugin_info (const char* name, struct plugin_info *info) | 342 register_plugin_info (const char* name, struct plugin_info *info) |
309 { | 343 { |
310 void **slot = htab_find_slot (plugin_name_args_tab, name, NO_INSERT); | 344 void **slot = htab_find_slot_with_hash (plugin_name_args_tab, name, |
311 struct plugin_name_args *plugin = (struct plugin_name_args *) *slot; | 345 htab_hash_string (name), NO_INSERT); |
346 struct plugin_name_args *plugin; | |
347 | |
348 if (slot == NULL) | |
349 { | |
350 error ("unable to register info for plugin %qs - plugin name not found", | |
351 name); | |
352 return; | |
353 } | |
354 plugin = (struct plugin_name_args *) *slot; | |
312 plugin->version = info->version; | 355 plugin->version = info->version; |
313 plugin->help = info->help; | 356 plugin->help = info->help; |
314 } | 357 } |
315 | 358 |
316 /* Helper function for the event hash table that compares the name of an | |
317 existing entry (E1) with the given string (S2). */ | |
318 | |
319 static int | |
320 htab_event_eq (const void *e1, const void *s2) | |
321 { | |
322 const char *s1= *(const char * const *) e1; | |
323 return !strcmp (s1, (const char *) s2); | |
324 } | |
325 | |
326 /* Look up the event id for NAME. If the name is not found, return -1 | 359 /* Look up the event id for NAME. If the name is not found, return -1 |
327 if INSERT is NO_INSERT. */ | 360 if INSERT is NO_INSERT. */ |
328 | 361 |
329 int | 362 int |
330 get_named_event_id (const char *name, enum insert_option insert) | 363 get_named_event_id (const char *name, enum insert_option insert) |
331 { | 364 { |
332 void **slot; | 365 const char ***slot; |
333 | 366 |
334 if (!event_tab) | 367 if (!event_tab) |
335 { | 368 { |
336 int i; | 369 int i; |
337 | 370 |
338 event_tab = htab_create (150, htab_hash_string, htab_event_eq, NULL); | 371 event_tab = new hash_table<event_hasher> (150); |
339 for (i = 0; i < event_last; i++) | 372 for (i = 0; i < event_last; i++) |
340 { | 373 { |
341 slot = htab_find_slot (event_tab, plugin_event_name[i], INSERT); | 374 slot = event_tab->find_slot (&plugin_event_name[i], INSERT); |
342 gcc_assert (*slot == HTAB_EMPTY_ENTRY); | 375 gcc_assert (*slot == HTAB_EMPTY_ENTRY); |
343 *slot = &plugin_event_name[i]; | 376 *slot = &plugin_event_name[i]; |
344 } | 377 } |
345 } | 378 } |
346 slot = htab_find_slot (event_tab, name, insert); | 379 slot = event_tab->find_slot (&name, insert); |
347 if (slot == NULL) | 380 if (slot == NULL) |
348 return -1; | 381 return -1; |
349 if (*slot != HTAB_EMPTY_ENTRY) | 382 if (*slot != HTAB_EMPTY_ENTRY) |
350 return (const char **) *slot - &plugin_event_name[0]; | 383 return *slot - &plugin_event_name[0]; |
351 | 384 |
352 if (event_last >= event_horizon) | 385 if (event_last >= event_horizon) |
353 { | 386 { |
354 event_horizon = event_last * 2; | 387 event_horizon = event_last * 2; |
355 if (plugin_event_name == plugin_event_name_init) | 388 if (plugin_event_name == plugin_event_name_init) |
367 = XRESIZEVEC (const char *, plugin_event_name, event_horizon); | 400 = XRESIZEVEC (const char *, plugin_event_name, event_horizon); |
368 plugin_callbacks = XRESIZEVEC (struct callback_info *, | 401 plugin_callbacks = XRESIZEVEC (struct callback_info *, |
369 plugin_callbacks, event_horizon); | 402 plugin_callbacks, event_horizon); |
370 } | 403 } |
371 /* All the pointers in the hash table will need to be updated. */ | 404 /* All the pointers in the hash table will need to be updated. */ |
372 htab_delete (event_tab); | 405 delete event_tab; |
373 event_tab = NULL; | 406 event_tab = NULL; |
374 } | 407 } |
375 else | 408 else |
376 *slot = &plugin_event_name[event_last]; | 409 *slot = &plugin_event_name[event_last]; |
377 plugin_event_name[event_last] = name; | 410 plugin_event_name[event_last] = name; |
404 break; | 437 break; |
405 case PLUGIN_REGISTER_GGC_ROOTS: | 438 case PLUGIN_REGISTER_GGC_ROOTS: |
406 gcc_assert (!callback); | 439 gcc_assert (!callback); |
407 ggc_register_root_tab ((const struct ggc_root_tab*) user_data); | 440 ggc_register_root_tab ((const struct ggc_root_tab*) user_data); |
408 break; | 441 break; |
409 case PLUGIN_REGISTER_GGC_CACHES: | |
410 gcc_assert (!callback); | |
411 ggc_register_cache_tab ((const struct ggc_cache_tab*) user_data); | |
412 break; | |
413 case PLUGIN_EVENT_FIRST_DYNAMIC: | 442 case PLUGIN_EVENT_FIRST_DYNAMIC: |
414 default: | 443 default: |
415 if (event < PLUGIN_EVENT_FIRST_DYNAMIC || event >= event_last) | 444 if (event < PLUGIN_EVENT_FIRST_DYNAMIC || event >= event_last) |
416 { | 445 { |
417 error ("unknown callback event registered by plugin %s", | 446 error ("unknown callback event registered by plugin %s", |
418 plugin_name); | 447 plugin_name); |
419 return; | 448 return; |
420 } | 449 } |
421 /* Fall through. */ | 450 /* Fall through. */ |
451 case PLUGIN_START_PARSE_FUNCTION: | |
452 case PLUGIN_FINISH_PARSE_FUNCTION: | |
422 case PLUGIN_FINISH_TYPE: | 453 case PLUGIN_FINISH_TYPE: |
454 case PLUGIN_FINISH_DECL: | |
423 case PLUGIN_START_UNIT: | 455 case PLUGIN_START_UNIT: |
424 case PLUGIN_FINISH_UNIT: | 456 case PLUGIN_FINISH_UNIT: |
425 case PLUGIN_PRE_GENERICIZE: | 457 case PLUGIN_PRE_GENERICIZE: |
426 case PLUGIN_GGC_START: | 458 case PLUGIN_GGC_START: |
427 case PLUGIN_GGC_MARKING: | 459 case PLUGIN_GGC_MARKING: |
436 case PLUGIN_OVERRIDE_GATE: | 468 case PLUGIN_OVERRIDE_GATE: |
437 case PLUGIN_PASS_EXECUTION: | 469 case PLUGIN_PASS_EXECUTION: |
438 case PLUGIN_EARLY_GIMPLE_PASSES_START: | 470 case PLUGIN_EARLY_GIMPLE_PASSES_START: |
439 case PLUGIN_EARLY_GIMPLE_PASSES_END: | 471 case PLUGIN_EARLY_GIMPLE_PASSES_END: |
440 case PLUGIN_NEW_PASS: | 472 case PLUGIN_NEW_PASS: |
473 case PLUGIN_INCLUDE_FILE: | |
441 { | 474 { |
442 struct callback_info *new_callback; | 475 struct callback_info *new_callback; |
443 if (!callback) | 476 if (!callback) |
444 { | 477 { |
445 error ("plugin %s registered a null callback function " | 478 error ("plugin %s registered a null callback function " |
493 case PLUGIN_EVENT_FIRST_DYNAMIC: | 526 case PLUGIN_EVENT_FIRST_DYNAMIC: |
494 default: | 527 default: |
495 gcc_assert (event >= PLUGIN_EVENT_FIRST_DYNAMIC); | 528 gcc_assert (event >= PLUGIN_EVENT_FIRST_DYNAMIC); |
496 gcc_assert (event < event_last); | 529 gcc_assert (event < event_last); |
497 /* Fall through. */ | 530 /* Fall through. */ |
531 case PLUGIN_START_PARSE_FUNCTION: | |
532 case PLUGIN_FINISH_PARSE_FUNCTION: | |
498 case PLUGIN_FINISH_TYPE: | 533 case PLUGIN_FINISH_TYPE: |
534 case PLUGIN_FINISH_DECL: | |
499 case PLUGIN_START_UNIT: | 535 case PLUGIN_START_UNIT: |
500 case PLUGIN_FINISH_UNIT: | 536 case PLUGIN_FINISH_UNIT: |
501 case PLUGIN_PRE_GENERICIZE: | 537 case PLUGIN_PRE_GENERICIZE: |
502 case PLUGIN_ATTRIBUTES: | 538 case PLUGIN_ATTRIBUTES: |
503 case PLUGIN_PRAGMAS: | 539 case PLUGIN_PRAGMAS: |
512 case PLUGIN_OVERRIDE_GATE: | 548 case PLUGIN_OVERRIDE_GATE: |
513 case PLUGIN_PASS_EXECUTION: | 549 case PLUGIN_PASS_EXECUTION: |
514 case PLUGIN_EARLY_GIMPLE_PASSES_START: | 550 case PLUGIN_EARLY_GIMPLE_PASSES_START: |
515 case PLUGIN_EARLY_GIMPLE_PASSES_END: | 551 case PLUGIN_EARLY_GIMPLE_PASSES_END: |
516 case PLUGIN_NEW_PASS: | 552 case PLUGIN_NEW_PASS: |
553 case PLUGIN_INCLUDE_FILE: | |
517 { | 554 { |
518 /* Iterate over every callback registered with this event and | 555 /* Iterate over every callback registered with this event and |
519 call it. */ | 556 call it. */ |
520 struct callback_info *callback = plugin_callbacks[event]; | 557 struct callback_info *callback = plugin_callbacks[event]; |
521 | 558 |
526 } | 563 } |
527 break; | 564 break; |
528 | 565 |
529 case PLUGIN_PASS_MANAGER_SETUP: | 566 case PLUGIN_PASS_MANAGER_SETUP: |
530 case PLUGIN_REGISTER_GGC_ROOTS: | 567 case PLUGIN_REGISTER_GGC_ROOTS: |
531 case PLUGIN_REGISTER_GGC_CACHES: | |
532 gcc_assert (false); | 568 gcc_assert (false); |
533 } | 569 } |
534 | 570 |
535 timevar_pop (TV_PLUGIN_RUN); | 571 timevar_pop (TV_PLUGIN_RUN); |
536 return retval; | 572 return retval; |
569 /* Clear any existing error. */ | 605 /* Clear any existing error. */ |
570 dlerror (); | 606 dlerror (); |
571 | 607 |
572 /* Check the plugin license. */ | 608 /* Check the plugin license. */ |
573 if (dlsym (dl_handle, str_license) == NULL) | 609 if (dlsym (dl_handle, str_license) == NULL) |
574 fatal_error ("plugin %s is not licensed under a GPL-compatible license\n" | 610 fatal_error (input_location, |
611 "plugin %s is not licensed under a GPL-compatible license\n" | |
575 "%s", plugin->full_name, dlerror ()); | 612 "%s", plugin->full_name, dlerror ()); |
576 | 613 |
577 PTR_UNION_AS_VOID_PTR (plugin_init_union) = | 614 PTR_UNION_AS_VOID_PTR (plugin_init_union) = |
578 dlsym (dl_handle, str_plugin_init_func_name); | 615 dlsym (dl_handle, str_plugin_init_func_name); |
579 plugin_init = PTR_UNION_AS_CAST_PTR (plugin_init_union); | 616 plugin_init = PTR_UNION_AS_CAST_PTR (plugin_init_union); |
580 | 617 |
581 if ((err = dlerror ()) != NULL) | 618 if ((err = dlerror ()) != NULL) |
582 { | 619 { |
620 dlclose(dl_handle); | |
583 error ("cannot find %s in plugin %s\n%s", str_plugin_init_func_name, | 621 error ("cannot find %s in plugin %s\n%s", str_plugin_init_func_name, |
584 plugin->full_name, err); | 622 plugin->full_name, err); |
585 return false; | 623 return false; |
586 } | 624 } |
587 | 625 |
588 /* Call the plugin-provided initialization routine with the arguments. */ | 626 /* Call the plugin-provided initialization routine with the arguments. */ |
589 if ((*plugin_init) (plugin, &gcc_version)) | 627 if ((*plugin_init) (plugin, &gcc_version)) |
590 { | 628 { |
629 dlclose(dl_handle); | |
591 error ("fail to initialize plugin %s", plugin->full_name); | 630 error ("fail to initialize plugin %s", plugin->full_name); |
592 return false; | 631 return false; |
593 } | 632 } |
594 | 633 /* leak dl_handle on purpose to ensure the plugin is loaded for the |
634 entire run of the compiler. */ | |
595 return true; | 635 return true; |
596 } | 636 } |
597 | 637 |
598 | 638 |
599 /* Routine to dlopen and initialize one plugin. This function is passed to | 639 /* Routine to dlopen and initialize one plugin. This function is passed to |
609 { | 649 { |
610 struct plugin_name_args *plugin = (struct plugin_name_args *) *slot; | 650 struct plugin_name_args *plugin = (struct plugin_name_args *) *slot; |
611 bool ok = try_init_one_plugin (plugin); | 651 bool ok = try_init_one_plugin (plugin); |
612 if (!ok) | 652 if (!ok) |
613 { | 653 { |
614 htab_remove_elt (plugin_name_args_tab, plugin->base_name); | 654 htab_remove_elt_with_hash (plugin_name_args_tab, plugin->base_name, |
655 htab_hash_string (plugin->base_name)); | |
615 XDELETE (plugin); | 656 XDELETE (plugin); |
616 } | 657 } |
617 return 1; | 658 return 1; |
618 } | 659 } |
619 | 660 |
786 fprintf (file, FMT_FOR_PLUGIN_EVENT " |", plugin_event_name[event]); | 827 fprintf (file, FMT_FOR_PLUGIN_EVENT " |", plugin_event_name[event]); |
787 | 828 |
788 for (ci = plugin_callbacks[event]; ci; ci = ci->next) | 829 for (ci = plugin_callbacks[event]; ci; ci = ci->next) |
789 fprintf (file, " %s", ci->plugin_name); | 830 fprintf (file, " %s", ci->plugin_name); |
790 | 831 |
791 putc('\n', file); | 832 putc ('\n', file); |
792 } | 833 } |
793 } | 834 } |
794 | 835 |
795 | 836 |
796 /* Dump active plugins to stderr. */ | 837 /* Dump active plugins to stderr. */ |
813 " this as a bug unless you can reproduce it without enabling" | 854 " this as a bug unless you can reproduce it without enabling" |
814 " any plugins.\n"); | 855 " any plugins.\n"); |
815 dump_active_plugins (stderr); | 856 dump_active_plugins (stderr); |
816 } | 857 } |
817 | 858 |
818 } | |
819 | |
820 /* Likewise, as a callback from the diagnostics code. */ | |
821 | |
822 void | |
823 plugins_internal_error_function (diagnostic_context *context ATTRIBUTE_UNUSED, | |
824 const char *msgid ATTRIBUTE_UNUSED, | |
825 va_list *ap ATTRIBUTE_UNUSED) | |
826 { | |
827 warn_if_plugins (); | |
828 } | 859 } |
829 | 860 |
830 /* The default version check. Compares every field in VERSION. */ | 861 /* The default version check. Compares every field in VERSION. */ |
831 | 862 |
832 bool | 863 bool |
861 return event_last; | 892 return event_last; |
862 } | 893 } |
863 | 894 |
864 | 895 |
865 /* Retrieve the default plugin directory. The gcc driver should have passed | 896 /* Retrieve the default plugin directory. The gcc driver should have passed |
866 it as -iplugindir <dir> to the cc1 program, and it is queriable thru the | 897 it as -iplugindir <dir> to the cc1 program, and it is queriable through the |
867 -print-file-name=plugin option to gcc. */ | 898 -print-file-name=plugin option to gcc. */ |
868 const char* | 899 const char* |
869 default_plugin_dir_name (void) | 900 default_plugin_dir_name (void) |
870 { | 901 { |
871 if (!plugindir_string) | 902 if (!plugindir_string) |
872 fatal_error ("-iplugindir <dir> option not passed from the gcc driver"); | 903 fatal_error (input_location, |
904 "-iplugindir <dir> option not passed from the gcc driver"); | |
873 return plugindir_string; | 905 return plugindir_string; |
874 } | 906 } |