LCOV - code coverage report
Current view: top level - gcc - opt-suggestions.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 100.0 % 132 132
Test Date: 2024-12-21 13:15:12 Functions: 100.0 % 13 13
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Provide option suggestion for --complete option and a misspelled
       2                 :             :    used by a user.
       3                 :             :    Copyright (C) 2016-2024 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 "tm.h"
      25                 :             : #include "opts.h"
      26                 :             : #include "spellcheck.h"
      27                 :             : #include "opt-suggestions.h"
      28                 :             : #include "common/common-target.h"
      29                 :             : #include "selftest.h"
      30                 :             : 
      31                 :      290429 : option_proposer::~option_proposer ()
      32                 :             : {
      33                 :      290429 :   delete m_option_suggestions;
      34                 :      290429 : }
      35                 :             : 
      36                 :             : const char *
      37                 :         524 : option_proposer::suggest_option (const char *bad_opt)
      38                 :             : {
      39                 :             :   /* Lazily populate m_option_suggestions.  */
      40                 :         524 :   if (!m_option_suggestions)
      41                 :         515 :     build_option_suggestions (NULL);
      42                 :         524 :   gcc_assert (m_option_suggestions);
      43                 :             : 
      44                 :             :   /* "m_option_suggestions" is now populated.  Use it.  */
      45                 :         524 :   return find_closest_string
      46                 :         524 :     (bad_opt,
      47                 :         524 :      (auto_vec <const char *> *) m_option_suggestions);
      48                 :             : }
      49                 :             : 
      50                 :             : /* Populate RESULTS with valid completions of options that begin
      51                 :             :    with OPTION_PREFIX.  */
      52                 :             : 
      53                 :             : void
      54                 :         389 : option_proposer::get_completions (const char *option_prefix,
      55                 :             :                                   auto_string_vec &results)
      56                 :             : {
      57                 :             :   /* Bail out for an invalid input.  */
      58                 :         389 :   if (option_prefix == NULL || option_prefix[0] == '\0')
      59                 :             :     return;
      60                 :             : 
      61                 :             :   /* Option suggestions are built without first leading dash character.  */
      62                 :         381 :   if (option_prefix[0] == '-')
      63                 :         373 :     option_prefix++;
      64                 :             : 
      65                 :         381 :   size_t length = strlen (option_prefix);
      66                 :             : 
      67                 :             :   /* Lazily populate m_option_suggestions.  */
      68                 :         381 :   if (!m_option_suggestions)
      69                 :           9 :     build_option_suggestions (option_prefix);
      70                 :         381 :   gcc_assert (m_option_suggestions);
      71                 :             : 
      72                 :     3744849 :   for (unsigned i = 0; i < m_option_suggestions->length (); i++)
      73                 :             :     {
      74                 :     3744468 :       char *candidate = (*m_option_suggestions)[i];
      75                 :     3744468 :       if (strlen (candidate) >= length
      76                 :     1875824 :           && strstr (candidate, option_prefix) == candidate)
      77                 :       45438 :         results.safe_push (concat ("-", candidate, NULL));
      78                 :             :     }
      79                 :             : }
      80                 :             : 
      81                 :             : /* Print on stdout a list of valid options that begin with OPTION_PREFIX,
      82                 :             :    one per line, suitable for use by Bash completion.
      83                 :             : 
      84                 :             :    Implementation of the "-completion=" option.  */
      85                 :             : 
      86                 :             : void
      87                 :           5 : option_proposer::suggest_completion (const char *option_prefix)
      88                 :             : {
      89                 :           5 :   auto_string_vec results;
      90                 :           5 :   get_completions (option_prefix, results);
      91                 :          27 :   for (unsigned i = 0; i < results.length (); i++)
      92                 :          22 :     printf ("%s\n", results[i]);
      93                 :           5 : }
      94                 :             : 
      95                 :             : void
      96                 :         524 : option_proposer::build_option_suggestions (const char *prefix)
      97                 :             : {
      98                 :         524 :   gcc_assert (m_option_suggestions == NULL);
      99                 :         524 :   m_option_suggestions = new auto_string_vec ();
     100                 :             : 
     101                 :             :   /* We build a vec of m_option_suggestions, using add_misspelling_candidates
     102                 :             :      to add copies of strings, without a leading dash.  */
     103                 :             : 
     104                 :     1261268 :   for (unsigned int i = 0; i < cl_options_count; i++)
     105                 :             :     {
     106                 :     1260744 :       const struct cl_option *option = &cl_options[i];
     107                 :     1260744 :       const char *opt_text = option->opt_text;
     108                 :     1260744 :       switch (i)
     109                 :             :         {
     110                 :     1259696 :         default:
     111                 :     1259696 :           if (option->var_type == CLVC_ENUM)
     112                 :             :             {
     113                 :       42968 :               const struct cl_enum *e = &cl_enums[option->var_enum];
     114                 :      199120 :               for (unsigned j = 0; e->values[j].arg != NULL; j++)
     115                 :             :                 {
     116                 :      156152 :                   char *with_arg = concat (opt_text, e->values[j].arg, NULL);
     117                 :      156152 :                   add_misspelling_candidates (m_option_suggestions, option,
     118                 :             :                                               with_arg);
     119                 :      156152 :                   free (with_arg);
     120                 :             :                 }
     121                 :             : 
     122                 :             :               /* Add also variant without an option argument.  */
     123                 :       42968 :               add_misspelling_candidates (m_option_suggestions, option,
     124                 :             :                                           opt_text);
     125                 :             :             }
     126                 :             :           else
     127                 :             :             {
     128                 :     1216728 :               bool option_added = false;
     129                 :     1216728 :               if (option->flags & CL_TARGET)
     130                 :             :                 {
     131                 :      115804 :                   vec<const char *> option_values
     132                 :      115804 :                     = targetm_common.get_valid_option_values (i, prefix);
     133                 :      115804 :                   if (!option_values.is_empty ())
     134                 :             :                     {
     135                 :       90652 :                       option_added = true;
     136                 :       90652 :                       for (unsigned j = 0; j < option_values.length (); j++)
     137                 :             :                         {
     138                 :       89604 :                           char *with_arg = concat (opt_text, option_values[j],
     139                 :             :                                                    NULL);
     140                 :       89604 :                           add_misspelling_candidates (m_option_suggestions, option,
     141                 :             :                                                       with_arg);
     142                 :       89604 :                           free (with_arg);
     143                 :             :                         }
     144                 :             :                     }
     145                 :      115804 :                   option_values.release ();
     146                 :             :                 }
     147                 :             : 
     148                 :      115804 :               if (!option_added)
     149                 :     1215680 :                 add_misspelling_candidates (m_option_suggestions, option,
     150                 :             :                                             opt_text);
     151                 :             :             }
     152                 :             :           break;
     153                 :             : 
     154                 :        1048 :         case OPT_fsanitize_:
     155                 :        1048 :         case OPT_fsanitize_recover_:
     156                 :             :           /* -fsanitize= and -fsanitize-recover= can take
     157                 :             :              a comma-separated list of arguments.  Given that combinations
     158                 :             :              are supported, we can't add all potential candidates to the
     159                 :             :              vec, but if we at least add them individually without commas,
     160                 :             :              we should do a better job e.g. correcting
     161                 :             :                "-sanitize=address"
     162                 :             :              to
     163                 :             :                "-fsanitize=address"
     164                 :             :              rather than to "-Wframe-address" (PR driver/69265).  */
     165                 :        1048 :           {
     166                 :             :             /* Add also variant without an option argument.  */
     167                 :        1048 :             add_misspelling_candidates (m_option_suggestions, option,
     168                 :             :                                         opt_text);
     169                 :             : 
     170                 :        1048 :             struct cl_option optb;
     171                 :       35632 :             for (int j = 0; sanitizer_opts[j].name != NULL; ++j)
     172                 :             :               {
     173                 :             :                 /* -fsanitize=all is not valid, only -fno-sanitize=all.
     174                 :             :                    So don't register the positive misspelling candidates
     175                 :             :                    for it.  */
     176                 :       34584 :                 if (sanitizer_opts[j].flag == ~0U && i == OPT_fsanitize_)
     177                 :             :                   {
     178                 :         524 :                     optb = *option;
     179                 :         524 :                     optb.opt_text = opt_text = "-fno-sanitize=";
     180                 :         524 :                     optb.cl_reject_negative = true;
     181                 :         524 :                     option = &optb;
     182                 :             :                   }
     183                 :             :                 /* Get one arg at a time e.g. "-fsanitize=address".  */
     184                 :       34584 :                 char *with_arg = concat (opt_text,
     185                 :             :                                          sanitizer_opts[j].name,
     186                 :             :                                          NULL);
     187                 :             :                 /* Add with_arg and all of its variant spellings e.g.
     188                 :             :                    "-fno-sanitize=address" to candidates (albeit without
     189                 :             :                    leading dashes).  */
     190                 :       34584 :                 add_misspelling_candidates (m_option_suggestions, option,
     191                 :             :                                             with_arg);
     192                 :       34584 :                 free (with_arg);
     193                 :             :               }
     194                 :             :           }
     195                 :        1048 :           break;
     196                 :             :         }
     197                 :             :     }
     198                 :         524 : }
     199                 :             : 
     200                 :             : #if CHECKING_P
     201                 :             : 
     202                 :             : namespace selftest {
     203                 :             : 
     204                 :             : /* Verify that PROPOSER generates sane auto-completion suggestions
     205                 :             :    for OPTION_PREFIX.  */
     206                 :             : 
     207                 :             : static void
     208                 :         308 : verify_autocompletions (option_proposer &proposer, const char *option_prefix)
     209                 :             : {
     210                 :         308 :   auto_string_vec suggestions;
     211                 :         308 :   proposer.get_completions (option_prefix, suggestions);
     212                 :             : 
     213                 :             :   /* There must be at least one suggestion, and every suggestion must
     214                 :             :      indeed begin with OPTION_PREFIX.  */
     215                 :             : 
     216                 :         308 :   ASSERT_GT (suggestions.length (), 0);
     217                 :             : 
     218                 :         640 :   for (unsigned i = 0; i < suggestions.length (); i++)
     219                 :         332 :     ASSERT_STR_STARTSWITH (suggestions[i], option_prefix);
     220                 :         308 : }
     221                 :             : 
     222                 :             : /* Verify that valid options are auto-completed correctly.  */
     223                 :             : 
     224                 :             : static void
     225                 :           4 : test_completion_valid_options (option_proposer &proposer)
     226                 :             : {
     227                 :           4 :   const char *option_prefixes[] =
     228                 :             :   {
     229                 :             :     "-fno-var-tracking-assignments-toggle",
     230                 :             :     "-fpredictive-commoning",
     231                 :             :     "--param=stack-clash-protection-guard-size",
     232                 :             :     "--param=max-predicted-iterations",
     233                 :             :     "-ftree-loop-distribute-patterns",
     234                 :             :     "-fno-var-tracking",
     235                 :             :     "-Walloc-zero",
     236                 :             :     "--param=ipa-cp-value-list-size",
     237                 :             :     "-Wsync-nand",
     238                 :             :     "-Wno-attributes",
     239                 :             :     "--param=tracer-dynamic-coverage-feedback",
     240                 :             :     "-Wno-format-contains-nul",
     241                 :             :     "-Wnamespaces",
     242                 :             :     "-fisolate-erroneous-paths-attribute",
     243                 :             :     "-Wno-underflow",
     244                 :             :     "-Wtarget-lifetime",
     245                 :             :     "--param=asan-globals",
     246                 :             :     "-Wno-empty-body",
     247                 :             :     "-Wno-odr",
     248                 :             :     "-Wformat-zero-length",
     249                 :             :     "-Wstringop-truncation",
     250                 :             :     "-fno-ipa-vrp",
     251                 :             :     "-fmath-errno",
     252                 :             :     "-Warray-temporaries",
     253                 :             :     "-Wno-unused-label",
     254                 :             :     "-Wreturn-local-addr",
     255                 :             :     "--param=sms-dfa-history",
     256                 :             :     "--param=asan-instrument-reads",
     257                 :             :     "-Wreturn-type",
     258                 :             :     "-Wc++17-compat",
     259                 :             :     "-Wno-effc++",
     260                 :             :     "--param=max-fields-for-field-sensitive",
     261                 :             :     "-fisolate-erroneous-paths-dereference",
     262                 :             :     "-fno-defer-pop",
     263                 :             :     "-Wcast-align=strict",
     264                 :             :     "-foptimize-strlen",
     265                 :             :     "-Wpacked-not-aligned",
     266                 :             :     "-funroll-loops",
     267                 :             :     "-fif-conversion2",
     268                 :             :     "-Wdesignated-init",
     269                 :             :     "--param=max-iterations-computation-cost",
     270                 :             :     "-Wmultiple-inheritance",
     271                 :             :     "-fno-sel-sched-reschedule-pipelined",
     272                 :             :     "-Wassign-intercept",
     273                 :             :     "-Wno-format-security",
     274                 :             :     "-fno-sched-stalled-insns",
     275                 :             :     "-fno-tree-tail-merge",
     276                 :             :     "-Wlong-long",
     277                 :             :     "-Wno-unused-but-set-parameter",
     278                 :             :     NULL
     279                 :             :   };
     280                 :             : 
     281                 :         200 :   for (const char **ptr = option_prefixes; *ptr != NULL; ptr++)
     282                 :         196 :     verify_autocompletions (proposer, *ptr);
     283                 :           4 : }
     284                 :             : 
     285                 :             : /* Verify that valid parameters are auto-completed correctly,
     286                 :             :    both with the "--param=PARAM" form and the "--param PARAM" form.  */
     287                 :             : 
     288                 :             : static void
     289                 :           4 : test_completion_valid_params (option_proposer &proposer)
     290                 :             : {
     291                 :           4 :   const char *option_prefixes[] =
     292                 :             :   {
     293                 :             :     "--param=sched-state-edge-prob-cutoff",
     294                 :             :     "--param=iv-consider-all-candidates-bound",
     295                 :             :     "--param=align-threshold",
     296                 :             :     "--param=prefetch-min-insn-to-mem-ratio",
     297                 :             :     "--param=max-unrolled-insns",
     298                 :             :     "--param=max-early-inliner-iterations",
     299                 :             :     "--param=max-vartrack-reverse-op-size",
     300                 :             :     "--param=ipa-cp-loop-hint-bonus",
     301                 :             :     "--param=tracer-min-branch-ratio",
     302                 :             :     "--param=graphite-max-arrays-per-scop",
     303                 :             :     "--param=sink-frequency-threshold",
     304                 :             :     "--param=max-cse-path-length",
     305                 :             :     "--param=sra-max-scalarization-size-Osize",
     306                 :             :     "--param=prefetch-latency",
     307                 :             :     "--param=dse-max-object-size",
     308                 :             :     "--param=asan-globals",
     309                 :             :     "--param=max-vartrack-size",
     310                 :             :     "--param=case-values-threshold",
     311                 :             :     "--param=max-slsr-cand-scan",
     312                 :             :     "--param=min-insn-to-prefetch-ratio",
     313                 :             :     "--param=tracer-min-branch-probability",
     314                 :             :     "--param sink-frequency-threshold",
     315                 :             :     "--param max-cse-path-length",
     316                 :             :     "--param sra-max-scalarization-size-Osize",
     317                 :             :     "--param prefetch-latency",
     318                 :             :     "--param dse-max-object-size",
     319                 :             :     "--param asan-globals",
     320                 :             :     "--param max-vartrack-size",
     321                 :             :     NULL
     322                 :             :   };
     323                 :             : 
     324                 :         116 :   for (const char **ptr = option_prefixes; *ptr != NULL; ptr++)
     325                 :         112 :     verify_autocompletions (proposer, *ptr);
     326                 :           4 : }
     327                 :             : 
     328                 :             : /* Return true when EXPECTED is one of completions for OPTION_PREFIX string.  */
     329                 :             : 
     330                 :             : static bool
     331                 :          32 : in_completion_p (option_proposer &proposer, const char *option_prefix,
     332                 :             :                  const char *expected)
     333                 :             : {
     334                 :          32 :   auto_string_vec suggestions;
     335                 :          32 :   proposer.get_completions (option_prefix, suggestions);
     336                 :             : 
     337                 :        1780 :   for (unsigned i = 0; i < suggestions.length (); i++)
     338                 :             :     {
     339                 :        1772 :       char *r = suggestions[i];
     340                 :        1772 :       if (strcmp (r, expected) == 0)
     341                 :             :         return true;
     342                 :             :     }
     343                 :             : 
     344                 :             :   return false;
     345                 :          32 : }
     346                 :             : 
     347                 :             : /* Return true when PROPOSER does not find any partial completion
     348                 :             :    for OPTION_PREFIX.  */
     349                 :             : 
     350                 :             : static bool
     351                 :          44 : empty_completion_p (option_proposer &proposer, const char *option_prefix)
     352                 :             : {
     353                 :          44 :   auto_string_vec suggestions;
     354                 :          44 :   proposer.get_completions (option_prefix, suggestions);
     355                 :          44 :   return suggestions.is_empty ();
     356                 :          44 : }
     357                 :             : 
     358                 :             : /* Verify autocompletions of partially-complete options.  */
     359                 :             : 
     360                 :             : static void
     361                 :           4 : test_completion_partial_match (option_proposer &proposer)
     362                 :             : {
     363                 :           4 :   ASSERT_TRUE (in_completion_p (proposer, "-fsani", "-fsanitize=address"));
     364                 :           4 :   ASSERT_TRUE (in_completion_p (proposer, "-fsani",
     365                 :             :                                 "-fsanitize-address-use-after-scope"));
     366                 :           4 :   ASSERT_TRUE (in_completion_p (proposer, "-fipa-icf", "-fipa-icf-functions"));
     367                 :           4 :   ASSERT_TRUE (in_completion_p (proposer, "-fipa-icf", "-fipa-icf"));
     368                 :           4 :   ASSERT_TRUE (in_completion_p (proposer, "--param=",
     369                 :             :                                 "--param=max-vartrack-reverse-op-size="));
     370                 :           4 :   ASSERT_TRUE (in_completion_p (proposer, "--param ",
     371                 :             :                                 "--param max-vartrack-reverse-op-size="));
     372                 :             : 
     373                 :           4 :   ASSERT_FALSE (in_completion_p (proposer, "-fipa-icf", "-fipa"));
     374                 :           4 :   ASSERT_FALSE (in_completion_p (proposer, "-fipa-icf-functions", "-fipa-icf"));
     375                 :             : 
     376                 :           4 :   ASSERT_FALSE (empty_completion_p (proposer, "-"));
     377                 :           4 :   ASSERT_FALSE (empty_completion_p (proposer, "-fipa"));
     378                 :           4 :   ASSERT_FALSE (empty_completion_p (proposer, "--par"));
     379                 :           4 : }
     380                 :             : 
     381                 :             : /* Verify that autocompletion does not return any match for garbage inputs.  */
     382                 :             : 
     383                 :             : static void
     384                 :           4 : test_completion_garbage (option_proposer &proposer)
     385                 :             : {
     386                 :           4 :   ASSERT_TRUE (empty_completion_p (proposer, NULL));
     387                 :           4 :   ASSERT_TRUE (empty_completion_p (proposer, ""));
     388                 :           4 :   ASSERT_TRUE (empty_completion_p (proposer, "- "));
     389                 :           4 :   ASSERT_TRUE (empty_completion_p (proposer, "123456789"));
     390                 :           4 :   ASSERT_TRUE (empty_completion_p (proposer, "---------"));
     391                 :           4 :   ASSERT_TRUE (empty_completion_p (proposer, "#########"));
     392                 :           4 :   ASSERT_TRUE (empty_completion_p (proposer, "- - - - - -"));
     393                 :           4 :   ASSERT_TRUE (empty_completion_p (proposer, "-fsanitize=address2"));
     394                 :           4 : }
     395                 :             : 
     396                 :             : /* Run all of the selftests within this file.  */
     397                 :             : 
     398                 :             : void
     399                 :           4 : opt_suggestions_cc_tests ()
     400                 :             : {
     401                 :           4 :   option_proposer proposer;
     402                 :             : 
     403                 :           4 :   test_completion_valid_options (proposer);
     404                 :           4 :   test_completion_valid_params (proposer);
     405                 :           4 :   test_completion_partial_match (proposer);
     406                 :           4 :   test_completion_garbage (proposer);
     407                 :           4 : }
     408                 :             : 
     409                 :             : } // namespace selftest
     410                 :             : 
     411                 :             : #endif /* #if CHECKING_P */
        

Generated by: LCOV version 2.1-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.