LCOV - code coverage report
Current view: top level - gcc - opts-global.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 82.9 % 211 175
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 14 14
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Command line option handling.  Code involving global state that
       2              :    should not be shared with the driver.
       3              :    Copyright (C) 2002-2026 Free Software Foundation, Inc.
       4              : 
       5              : This file is part of GCC.
       6              : 
       7              : GCC is free software; you can redistribute it and/or modify it under
       8              : the terms of the GNU General Public License as published by the Free
       9              : Software Foundation; either version 3, or (at your option) any later
      10              : version.
      11              : 
      12              : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      13              : WARRANTY; without even the implied warranty of MERCHANTABILITY or
      14              : FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      15              : for more details.
      16              : 
      17              : You should have received a copy of the GNU General Public License
      18              : along with GCC; see the file COPYING3.  If not see
      19              : <http://www.gnu.org/licenses/>.  */
      20              : 
      21              : #include "config.h"
      22              : #include "system.h"
      23              : #include "coretypes.h"
      24              : #include "backend.h"
      25              : #include "rtl.h"
      26              : #include "tree.h"
      27              : #include "tree-pass.h"
      28              : #include "diagnostic.h"
      29              : #include "opts.h"
      30              : #include "flags.h"
      31              : #include "langhooks.h"
      32              : #include "dbgcnt.h"
      33              : #include "debug.h"
      34              : #include "output.h"
      35              : #include "plugin.h"
      36              : #include "toplev.h"
      37              : #include "context.h"
      38              : #include "stringpool.h"
      39              : #include "attribs.h"
      40              : #include "asan.h"
      41              : #include "file-prefix-map.h" /* add_*_prefix_map()  */
      42              : 
      43              : typedef const char *const_char_p; /* For DEF_VEC_P.  */
      44              : 
      45              : static vec<const_char_p> ignored_options;
      46              : 
      47              : /* Input file names.  */
      48              : const char **in_fnames;
      49              : unsigned num_in_fnames;
      50              : 
      51              : /* Return a malloced slash-separated list of languages in MASK.  */
      52              : 
      53              : char *
      54          588 : write_langs (unsigned int mask)
      55              : {
      56          588 :   unsigned int n = 0, len = 0;
      57          588 :   const char *lang_name;
      58          588 :   char *result;
      59              : 
      60         9996 :   for (n = 0; (lang_name = lang_names[n]) != 0; n++)
      61         9408 :     if (mask & (1U << n))
      62          726 :       len += strlen (lang_name) + 1;
      63              : 
      64              :   /* Allocate at least one character as we'll terminate the string
      65              :      at the very end of this function.  */
      66          588 :   result = XNEWVEC (char, MAX (1, len));
      67          588 :   len = 0;
      68        10584 :   for (n = 0; (lang_name = lang_names[n]) != 0; n++)
      69         9408 :     if (mask & (1U << n))
      70              :       {
      71          726 :         if (len)
      72          139 :           result[len++] = '/';
      73          726 :         strcpy (result + len, lang_name);
      74          726 :         len += strlen (lang_name);
      75              :       }
      76              : 
      77          588 :   result[len] = 0;
      78              : 
      79          588 :   return result;
      80              : }
      81              : 
      82              : /* Complain that switch DECODED does not apply to this front end (mask
      83              :    LANG_MASK).  */
      84              : 
      85              : static void
      86          492 : complain_wrong_lang (const struct cl_decoded_option *decoded,
      87              :                      unsigned int lang_mask)
      88              : {
      89          492 :   const struct cl_option *option = &cl_options[decoded->opt_index];
      90          492 :   const char *text = decoded->orig_option_with_args_text;
      91          492 :   char *ok_langs = NULL, *bad_lang = NULL;
      92          492 :   unsigned int opt_flags = option->flags;
      93              : 
      94          492 :   if (!warn_complain_wrong_lang)
      95              :     return;
      96              : 
      97          299 :   if (!lang_hooks.complain_wrong_lang_p (option))
      98              :     return;
      99              : 
     100          293 :   opt_flags &= ((1U << cl_lang_count) - 1) | CL_DRIVER;
     101          293 :   if (opt_flags != CL_DRIVER)
     102          293 :     ok_langs = write_langs (opt_flags);
     103          293 :   if (lang_mask != CL_DRIVER)
     104          293 :     bad_lang = write_langs (lang_mask);
     105              : 
     106          293 :   if (opt_flags == CL_DRIVER)
     107            0 :     error ("command-line option %qs is valid for the driver but not for %s",
     108              :            text, bad_lang);
     109          293 :   else if (lang_mask == CL_DRIVER)
     110            0 :     gcc_unreachable ();
     111          293 :   else if (ok_langs[0] != '\0')
     112              :     /* Eventually this should become a hard error IMO.  */
     113          292 :     warning (0, "command-line option %qs is valid for %s but not for %s",
     114              :              text, ok_langs, bad_lang);
     115              :   else
     116              :     /* Happens for -Werror=warning_name.  */
     117            1 :     warning (0, "%<-Werror=%> argument %qs is not valid for %s",
     118              :              text, bad_lang);
     119              : 
     120          293 :   free (ok_langs);
     121          293 :   free (bad_lang);
     122              : }
     123              : 
     124              : /* Buffer the unknown option described by the string OPT.  Currently,
     125              :    we only complain about unknown -Wno-* options if they may have
     126              :    prevented a diagnostic. Otherwise, we just ignore them.  Note that
     127              :    if we do complain, it is only as a warning, not an error; passing
     128              :    the compiler an unrecognized -Wno-* option should never change
     129              :    whether the compilation succeeds or fails.  */
     130              : 
     131              : static void
     132           91 : postpone_unknown_option_warning (const char *opt)
     133              : {
     134            0 :   ignored_options.safe_push (opt);
     135            0 : }
     136              : 
     137              : /* Produce a warning for each option previously buffered.  */
     138              : 
     139              : void
     140        39899 : print_ignored_options (void)
     141              : {
     142        39922 :   while (!ignored_options.is_empty ())
     143              :     {
     144           23 :       const char *opt;
     145              : 
     146           23 :       opt = ignored_options.pop ();
     147              :       /* Use inform, not warning_at, to avoid promoting these to errors.  */
     148           23 :       inform (UNKNOWN_LOCATION,
     149              :               "unrecognized command-line option %qs may have been intended "
     150              :               "to silence earlier diagnostics", opt);
     151              :     }
     152        39899 : }
     153              : 
     154              : /* Handle an unknown option DECODED, returning true if an error should
     155              :    be given.  */
     156              : 
     157              : static bool
     158           91 : unknown_option_callback (const struct cl_decoded_option *decoded)
     159              : {
     160           91 :   const char *opt = decoded->arg;
     161              : 
     162           91 :   if (opt[1] == 'W' && opt[2] == 'n' && opt[3] == 'o' && opt[4] == '-'
     163           91 :       && !(decoded->errors & CL_ERR_NEGATIVE))
     164              :     {
     165              :       /* We don't generate warnings for unknown -Wno-* options unless
     166              :          we issue diagnostics.  */
     167           91 :       postpone_unknown_option_warning (opt);
     168           91 :       return false;
     169              :     }
     170              :   else
     171              :     return true;
     172              : }
     173              : 
     174              : /* Handle a front-end option; arguments and return value as for
     175              :    handle_option.  */
     176              : 
     177              : static bool
     178      4205359 : lang_handle_option (struct gcc_options *opts,
     179              :                     struct gcc_options *opts_set,
     180              :                     const struct cl_decoded_option *decoded,
     181              :                     unsigned int lang_mask ATTRIBUTE_UNUSED, int kind,
     182              :                     location_t loc,
     183              :                     const struct cl_option_handlers *handlers,
     184              :                     diagnostics::context *dc,
     185              :                     void (*) (void))
     186              : {
     187      4205359 :   gcc_assert (opts == &global_options);
     188      4205359 :   gcc_assert (opts_set == &global_options_set);
     189      4205359 :   gcc_assert (dc == global_dc);
     190      4205359 :   gcc_assert (decoded->canonical_option_num_elements <= 2);
     191      4205359 :   return lang_hooks.handle_option (decoded->opt_index, decoded->arg,
     192      4205359 :                                    decoded->value, kind, loc, handlers);
     193              : }
     194              : 
     195              : /* Handle FILENAME from the command line.  */
     196              : 
     197              : static void
     198       296521 : add_input_filename (const char *filename)
     199              : {
     200       296521 :   num_in_fnames++;
     201       296521 :   in_fnames = XRESIZEVEC (const char *, in_fnames, num_in_fnames);
     202       296521 :   in_fnames[num_in_fnames - 1] = filename;
     203       296521 : }
     204              : 
     205              : /* Handle the vector of command line options (located at LOC), storing
     206              :    the results of processing DECODED_OPTIONS and DECODED_OPTIONS_COUNT
     207              :    in OPTS and OPTS_SET and using DC for diagnostic state.  LANG_MASK
     208              :    contains has a single bit set representing the current language.
     209              :    HANDLERS describes what functions to call for the options.  */
     210              : 
     211              : static void
     212       629766 : read_cmdline_options (struct gcc_options *opts, struct gcc_options *opts_set,
     213              :                       struct cl_decoded_option *decoded_options,
     214              :                       unsigned int decoded_options_count,
     215              :                       location_t loc,
     216              :                       unsigned int lang_mask,
     217              :                       const struct cl_option_handlers *handlers,
     218              :                       diagnostics::context *dc)
     219              : {
     220       629766 :   unsigned int i;
     221              : 
     222     10646069 :   for (i = 1; i < decoded_options_count; i++)
     223              :     {
     224     10016303 :       if (decoded_options[i].opt_index == OPT_SPECIAL_input_file)
     225              :         {
     226              :           /* Input files should only ever appear on the main command
     227              :              line.  */
     228       296521 :           gcc_assert (opts == &global_options);
     229       296521 :           gcc_assert (opts_set == &global_options_set);
     230              : 
     231       296521 :           if (opts->x_main_input_filename == NULL)
     232              :             {
     233       285722 :               opts->x_main_input_filename = decoded_options[i].arg;
     234       285722 :               opts->x_main_input_baselength
     235       285722 :                 = base_of_path (opts->x_main_input_filename,
     236              :                                 &opts->x_main_input_basename);
     237              :             }
     238       296521 :           add_input_filename (decoded_options[i].arg);
     239       296521 :           continue;
     240              :         }
     241              : 
     242      9719782 :       read_cmdline_option (opts, opts_set,
     243              :                            decoded_options + i, loc, lang_mask, handlers,
     244              :                            dc);
     245              :     }
     246       629766 : }
     247              : 
     248              : /* Language mask determined at initialization.  */
     249              : static unsigned int initial_lang_mask;
     250              : 
     251              : /* Initialize global options-related settings at start-up.  */
     252              : 
     253              : void
     254       285722 : init_options_once (void)
     255              : {
     256              :   /* Perform language-specific options initialization.  */
     257       285722 :   initial_lang_mask = lang_hooks.option_lang_mask ();
     258              : 
     259       285722 :   const bool show_highlight_colors
     260       285722 :     = pp_show_highlight_colors (global_dc->get_reference_printer ());
     261              : 
     262       285722 :   lang_hooks.initialize_diagnostics (global_dc);
     263              :   /* ??? Ideally, we should do this earlier and the FEs will override
     264              :      it if desired (none do it so far).  However, the way the FEs
     265              :      construct their pretty-printers means that all previous settings
     266              :      are overriden.  */
     267       285722 :   global_dc->set_show_highlight_colors (show_highlight_colors);
     268              : 
     269       285722 :   diagnostic_color_init (global_dc);
     270       285722 :   diagnostic_urls_init (global_dc);
     271       285722 :   global_dc->refresh_output_sinks ();
     272       285722 : }
     273              : 
     274              : /* Decode command-line options to an array, like
     275              :    decode_cmdline_options_to_array and with the same arguments but
     276              :    using the default lang_mask.  */
     277              : 
     278              : void
     279       629766 : decode_cmdline_options_to_array_default_mask (unsigned int argc,
     280              :                                               const char **argv,
     281              :                                               struct cl_decoded_option **decoded_options,
     282              :                                               unsigned int *decoded_options_count)
     283              : {
     284       629766 :   decode_cmdline_options_to_array (argc, argv,
     285              :                                    initial_lang_mask | CL_COMMON | CL_TARGET,
     286              :                                    decoded_options, decoded_options_count);
     287       629766 : }
     288              : 
     289              : /* Set *HANDLERS to the default set of option handlers for use in the
     290              :    compilers proper (not the driver).  */
     291              : void
     292      4586433 : set_default_handlers (struct cl_option_handlers *handlers,
     293              :                       void (*target_option_override_hook) (void))
     294              : {
     295      4586433 :   handlers->unknown_option_callback = unknown_option_callback;
     296      4586433 :   handlers->wrong_lang_callback = complain_wrong_lang;
     297      4586433 :   handlers->target_option_override_hook = target_option_override_hook;
     298      4586433 :   handlers->num_handlers = 3;
     299      4586433 :   handlers->handlers[0].handler = lang_handle_option;
     300      4586433 :   handlers->handlers[0].mask = initial_lang_mask;
     301      4586433 :   handlers->handlers[1].handler = common_handle_option;
     302      4586433 :   handlers->handlers[1].mask = CL_COMMON;
     303      4586433 :   handlers->handlers[2].handler = target_handle_option;
     304      4586433 :   handlers->handlers[2].mask = CL_TARGET;
     305      4586433 : }
     306              : 
     307              : /* Parse command line options and set default flag values.  Do minimal
     308              :    options processing.  The decoded options are in *DECODED_OPTIONS
     309              :    and *DECODED_OPTIONS_COUNT; settings go in OPTS, OPTS_SET and DC;
     310              :    the options are located at LOC.  */
     311              : void
     312       629766 : decode_options (struct gcc_options *opts, struct gcc_options *opts_set,
     313              :                 struct cl_decoded_option *decoded_options,
     314              :                 unsigned int decoded_options_count,
     315              :                 location_t loc, diagnostics::context *dc,
     316              :                 void (*target_option_override_hook) (void))
     317              : {
     318       629766 :   struct cl_option_handlers handlers;
     319              : 
     320       629766 :   unsigned int lang_mask;
     321              : 
     322       629766 :   lang_mask = initial_lang_mask;
     323              : 
     324       629766 :   set_default_handlers (&handlers, target_option_override_hook);
     325              : 
     326       629766 :   default_options_optimization (opts, opts_set,
     327              :                                 decoded_options, decoded_options_count,
     328              :                                 loc, lang_mask, &handlers, dc);
     329              : 
     330       629766 :   read_cmdline_options (opts, opts_set,
     331              :                         decoded_options, decoded_options_count,
     332              :                         loc, lang_mask,
     333              :                         &handlers, dc);
     334              : 
     335       629766 :   finish_options (opts, opts_set, loc);
     336              : 
     337              :   /* Print --help=* if used.  */
     338       629766 :   unsigned i;
     339       629766 :   const char *arg;
     340              : 
     341       629766 :   if (!help_option_arguments.is_empty ())
     342              :     {
     343              :       /* Make sure --help=* sees the overridden values.  */
     344           71 :       target_option_override_hook ();
     345              : 
     346          215 :       FOR_EACH_VEC_ELT (help_option_arguments, i, arg)
     347           73 :         print_help (opts, lang_mask, arg);
     348              :     }
     349       629766 : }
     350              : 
     351              : /* Hold command-line options associated with stack limitation.  */
     352              : const char *opt_fstack_limit_symbol_arg = NULL;
     353              : int opt_fstack_limit_register_no = -1;
     354              : 
     355              : /* Process common options that have been deferred until after the
     356              :    handlers have been called for all options.  */
     357              : 
     358              : void
     359       285722 : handle_common_deferred_options (void)
     360              : {
     361       285722 :   unsigned int i;
     362       285722 :   cl_deferred_option *opt;
     363       285722 :   vec<cl_deferred_option> v;
     364              : 
     365       285722 :   if (common_deferred_options)
     366        23413 :     v = *((vec<cl_deferred_option> *) common_deferred_options);
     367              :   else
     368              :     v = vNULL;
     369              : 
     370       285722 :   if (flag_dump_all_passed)
     371            4 :     enable_rtl_dump_file ();
     372              : 
     373       285722 :   if (flag_opt_info)
     374            1 :     opt_info_switch_p (NULL);
     375              : 
     376       285722 :   flag_canon_prefix_map = false;
     377       311930 :   FOR_EACH_VEC_ELT (v, i, opt)
     378              :     {
     379        26212 :       switch (opt->opt_index)
     380              :         {
     381            0 :         case OPT_fcall_used_:
     382            0 :           fix_register (opt->arg, 0, 1);
     383            0 :           break;
     384              : 
     385            0 :         case OPT_fcall_saved_:
     386            0 :           fix_register (opt->arg, 0, 0);
     387            0 :           break;
     388              : 
     389            3 :         case OPT_fdbg_cnt_:
     390            3 :           dbg_cnt_process_opt (opt->arg);
     391            3 :           break;
     392              : 
     393          552 :         case OPT_fdebug_prefix_map_:
     394          552 :           add_debug_prefix_map (opt->arg);
     395          552 :           break;
     396              : 
     397          220 :         case OPT_ffile_prefix_map_:
     398          220 :           add_file_prefix_map (opt->arg);
     399          220 :           break;
     400              : 
     401            0 :         case OPT_fprofile_prefix_map_:
     402            0 :           add_profile_prefix_map (opt->arg);
     403            0 :           break;
     404              : 
     405            0 :         case OPT_fcanon_prefix_map:
     406            0 :           flag_canon_prefix_map = opt->value;
     407            0 :           break;
     408              : 
     409              :         case OPT_fdump_:
     410              :           /* Deferred until plugins initialized.  */
     411              :           break;
     412              : 
     413          674 :         case OPT_fopt_info_:
     414          674 :           if (!opt_info_switch_p (opt->arg))
     415            0 :             error ("unrecognized command-line option %<-fopt-info-%s%>",
     416              :                    opt->arg);
     417              :           break;
     418              : 
     419          209 :         case OPT_fenable_:
     420          209 :         case OPT_fdisable_:
     421          209 :           if (opt->opt_index == OPT_fenable_)
     422            4 :             enable_pass (opt->arg);
     423              :           else
     424          205 :             disable_pass (opt->arg);
     425              :           break;
     426              : 
     427           93 :         case OPT_ffixed_:
     428              :           /* Deferred.  */
     429           93 :           fix_register (opt->arg, 1, 1);
     430           93 :           break;
     431              : 
     432          257 :         case OPT_fplugin_:
     433              : #ifdef ENABLE_PLUGIN
     434          257 :           add_new_plugin (opt->arg);
     435              : #else
     436              :           error ("plugin support is disabled; configure with "
     437              :                  "%<--enable-plugin%>");
     438              : #endif
     439          257 :           break;
     440              : 
     441           17 :         case OPT_fplugin_arg_:
     442              : #ifdef ENABLE_PLUGIN
     443           17 :           parse_plugin_arg_opt (opt->arg);
     444              : #else
     445              :           error ("plugin support is disabled; configure with "
     446              :                  "%<--enable-plugin%>");
     447              : #endif
     448           17 :           break;
     449              : 
     450            0 :         case OPT_frandom_seed:
     451              :           /* The real switch is -fno-random-seed.  */
     452            0 :           if (!opt->value)
     453            0 :             set_random_seed (NULL);
     454              :           break;
     455              : 
     456         1794 :         case OPT_frandom_seed_:
     457         1794 :           set_random_seed (opt->arg);
     458         1794 :           break;
     459              : 
     460            1 :         case OPT_fstack_limit:
     461              :           /* The real switch is -fno-stack-limit.  */
     462            1 :           if (!opt->value)
     463            0 :             stack_limit_rtx = NULL_RTX;
     464              :           break;
     465              : 
     466            0 :         case OPT_fstack_limit_register_:
     467            0 :           {
     468            0 :             int reg = decode_reg_name (opt->arg);
     469            0 :             if (reg < 0)
     470            0 :               error ("unrecognized register name %qs", opt->arg);
     471              :             else
     472              :               {
     473              :                 /* Deactivate previous OPT_fstack_limit_symbol_ options.  */
     474            0 :                 opt_fstack_limit_symbol_arg = NULL;
     475            0 :                 opt_fstack_limit_register_no = reg;
     476              :               }
     477              :           }
     478              :           break;
     479              : 
     480            0 :         case OPT_fstack_limit_symbol_:
     481              :           /* Deactivate previous OPT_fstack_limit_register_ options.  */
     482            0 :           opt_fstack_limit_register_no = -1;
     483            0 :           opt_fstack_limit_symbol_arg = opt->arg;
     484            0 :           break;
     485              : 
     486           11 :         case OPT_fasan_shadow_offset_:
     487           11 :           if (!(flag_sanitize & SANITIZE_KERNEL_ADDRESS))
     488            0 :             error ("%<-fasan-shadow-offset%> should only be used "
     489              :                    "with %<-fsanitize=kernel-address%>");
     490           11 :           if (!set_asan_shadow_offset (opt->arg))
     491            0 :              error ("unrecognized shadow offset %qs", opt->arg);
     492              :           break;
     493              : 
     494           40 :         case OPT_fsanitize_sections_:
     495           40 :           set_sanitized_sections (opt->arg);
     496           40 :           break;
     497              : 
     498            0 :         default:
     499            0 :           gcc_unreachable ();
     500              :         }
     501              :     }
     502       285718 : }
     503              : 
     504              : /* Handle deferred dump options.  */
     505              : 
     506              : void
     507       285718 : handle_deferred_dump_options (void)
     508              : {
     509       285718 :   unsigned int i;
     510       285718 :   cl_deferred_option *opt;
     511       285718 :   vec<cl_deferred_option> v;
     512              : 
     513       285718 :   if (common_deferred_options)
     514        23409 :     v = *((vec<cl_deferred_option> *) common_deferred_options);
     515              :   else
     516              :     v = vNULL;
     517       311926 :   FOR_EACH_VEC_ELT (v, i, opt)
     518        26208 :     if (opt->opt_index == OPT_fdump_)
     519        22341 :       g->get_dumps ()->dump_switch_p (opt->arg);
     520       285718 : }
        

Generated by: LCOV version 2.4-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.