LCOV - code coverage report
Current view: top level - gcc - opt-suggestions.c (source / functions) Hit Total Coverage
Test: gcc.info Lines: 129 129 100.0 %
Date: 2020-04-04 11:58:09 Functions: 13 13 100.0 %
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-2020 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                 :     405488 : option_proposer::~option_proposer ()
      32                 :            : {
      33                 :     202744 :   delete m_option_suggestions;
      34                 :     202744 : }
      35                 :            : 
      36                 :            : const char *
      37                 :        348 : option_proposer::suggest_option (const char *bad_opt)
      38                 :            : {
      39                 :            :   /* Lazily populate m_option_suggestions.  */
      40                 :        348 :   if (!m_option_suggestions)
      41                 :        343 :     build_option_suggestions (NULL);
      42                 :        348 :   gcc_assert (m_option_suggestions);
      43                 :            : 
      44                 :            :   /* "m_option_suggestions" is now populated.  Use it.  */
      45                 :        348 :   return find_closest_string
      46                 :        348 :     (bad_opt,
      47                 :        348 :      (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                 :        197 : option_proposer::get_completions (const char *option_prefix,
      55                 :            :                                   auto_string_vec &results)
      56                 :            : {
      57                 :            :   /* Bail out for an invalid input.  */
      58                 :        197 :   if (option_prefix == NULL || option_prefix[0] == '\0')
      59                 :            :     return;
      60                 :            : 
      61                 :            :   /* Option suggestions are built without first leading dash character.  */
      62                 :        193 :   if (option_prefix[0] == '-')
      63                 :        189 :     option_prefix++;
      64                 :            : 
      65                 :        193 :   size_t length = strlen (option_prefix);
      66                 :            : 
      67                 :            :   /* Lazily populate m_option_suggestions.  */
      68                 :        193 :   if (!m_option_suggestions)
      69                 :          7 :     build_option_suggestions (option_prefix);
      70                 :        193 :   gcc_assert (m_option_suggestions);
      71                 :            : 
      72                 :    2896160 :   for (unsigned i = 0; i < m_option_suggestions->length (); i++)
      73                 :            :     {
      74                 :    1447890 :       char *candidate = (*m_option_suggestions)[i];
      75                 :    1447890 :       if (strlen (candidate) >= length
      76                 :     706297 :           && strstr (candidate, option_prefix) == candidate)
      77                 :      17430 :         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                 :         10 :   auto_string_vec results;
      90                 :          5 :   get_completions (option_prefix, results);
      91                 :         50 :   for (unsigned i = 0; i < results.length (); i++)
      92                 :         20 :     printf ("%s\n", results[i]);
      93                 :          5 : }
      94                 :            : 
      95                 :            : void
      96                 :        350 : option_proposer::build_option_suggestions (const char *prefix)
      97                 :            : {
      98                 :        350 :   gcc_assert (m_option_suggestions == NULL);
      99                 :        350 :   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                 :     670950 :   for (unsigned int i = 0; i < cl_options_count; i++)
     105                 :            :     {
     106                 :     670600 :       const struct cl_option *option = &cl_options[i];
     107                 :     670600 :       const char *opt_text = option->opt_text;
     108                 :     670600 :       switch (i)
     109                 :            :         {
     110                 :     669900 :         default:
     111                 :     669900 :           if (option->var_type == CLVC_ENUM)
     112                 :            :             {
     113                 :      17500 :               const struct cl_enum *e = &cl_enums[option->var_enum];
     114                 :      75250 :               for (unsigned j = 0; e->values[j].arg != NULL; j++)
     115                 :            :                 {
     116                 :      57750 :                   char *with_arg = concat (opt_text, e->values[j].arg, NULL);
     117                 :      57750 :                   add_misspelling_candidates (m_option_suggestions, option,
     118                 :            :                                               with_arg);
     119                 :      57750 :                   free (with_arg);
     120                 :            :                 }
     121                 :            : 
     122                 :            :               /* Add also variant without an option argument.  */
     123                 :      17500 :               add_misspelling_candidates (m_option_suggestions, option,
     124                 :            :                                           opt_text);
     125                 :            :             }
     126                 :            :           else
     127                 :            :             {
     128                 :     652400 :               bool option_added = false;
     129                 :     652400 :               if (option->flags & CL_TARGET)
     130                 :            :                 {
     131                 :      60900 :                   vec<const char *> option_values
     132                 :      60900 :                     = targetm_common.get_valid_option_values (i, prefix);
     133                 :      60900 :                   if (!option_values.is_empty ())
     134                 :            :                     {
     135                 :      46550 :                       option_added = true;
     136                 :      46550 :                       for (unsigned j = 0; j < option_values.length (); j++)
     137                 :            :                         {
     138                 :      45850 :                           char *with_arg = concat (opt_text, option_values[j],
     139                 :            :                                                    NULL);
     140                 :      45850 :                           add_misspelling_candidates (m_option_suggestions, option,
     141                 :            :                                                       with_arg);
     142                 :      45850 :                           free (with_arg);
     143                 :            :                         }
     144                 :            :                     }
     145                 :      60900 :                   option_values.release ();
     146                 :            :                 }
     147                 :            : 
     148                 :      60900 :               if (!option_added)
     149                 :     651700 :                 add_misspelling_candidates (m_option_suggestions, option,
     150                 :            :                                             opt_text);
     151                 :            :             }
     152                 :            :           break;
     153                 :            : 
     154                 :        700 :         case OPT_fsanitize_:
     155                 :        700 :         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                 :        700 :           {
     166                 :            :             /* Add also variant without an option argument.  */
     167                 :        700 :             add_misspelling_candidates (m_option_suggestions, option,
     168                 :            :                                         opt_text);
     169                 :            : 
     170                 :      21700 :             for (int j = 0; sanitizer_opts[j].name != NULL; ++j)
     171                 :            :               {
     172                 :      21000 :                 struct cl_option optb;
     173                 :            :                 /* -fsanitize=all is not valid, only -fno-sanitize=all.
     174                 :            :                    So don't register the positive misspelling candidates
     175                 :            :                    for it.  */
     176                 :      21000 :                 if (sanitizer_opts[j].flag == ~0U && i == OPT_fsanitize_)
     177                 :            :                   {
     178                 :        350 :                     optb = *option;
     179                 :        350 :                     optb.opt_text = opt_text = "-fno-sanitize=";
     180                 :        350 :                     optb.cl_reject_negative = true;
     181                 :        350 :                     option = &optb;
     182                 :            :                   }
     183                 :            :                 /* Get one arg at a time e.g. "-fsanitize=address".  */
     184                 :      21000 :                 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                 :      21000 :                 add_misspelling_candidates (m_option_suggestions, option,
     191                 :            :                                             with_arg);
     192                 :      21000 :                 free (with_arg);
     193                 :            :               }
     194                 :            :           }
     195                 :            :           break;
     196                 :            :         }
     197                 :            :     }
     198                 :        350 : }
     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                 :        154 : verify_autocompletions (option_proposer &proposer, const char *option_prefix)
     209                 :            : {
     210                 :        308 :   auto_string_vec suggestions;
     211                 :        154 :   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                 :        154 :   ASSERT_GT (suggestions.length (), 0);
     217                 :            : 
     218                 :        636 :   for (unsigned i = 0; i < suggestions.length (); i++)
     219                 :        164 :     ASSERT_STR_STARTSWITH (suggestions[i], option_prefix);
     220                 :        154 : }
     221                 :            : 
     222                 :            : /* Verify that valid options are auto-completed correctly.  */
     223                 :            : 
     224                 :            : static void
     225                 :          2 : test_completion_valid_options (option_proposer &proposer)
     226                 :            : {
     227                 :          2 :   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                 :        100 :   for (const char **ptr = option_prefixes; *ptr != NULL; ptr++)
     282                 :         98 :     verify_autocompletions (proposer, *ptr);
     283                 :          2 : }
     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                 :          2 : test_completion_valid_params (option_proposer &proposer)
     290                 :            : {
     291                 :          2 :   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                 :         58 :   for (const char **ptr = option_prefixes; *ptr != NULL; ptr++)
     325                 :         56 :     verify_autocompletions (proposer, *ptr);
     326                 :          2 : }
     327                 :            : 
     328                 :            : /* Return true when EXPECTED is one of completions for OPTION_PREFIX string.  */
     329                 :            : 
     330                 :            : static bool
     331                 :         16 : in_completion_p (option_proposer &proposer, const char *option_prefix,
     332                 :            :                  const char *expected)
     333                 :            : {
     334                 :         32 :   auto_string_vec suggestions;
     335                 :         16 :   proposer.get_completions (option_prefix, suggestions);
     336                 :            : 
     337                 :       1504 :   for (unsigned i = 0; i < suggestions.length (); i++)
     338                 :            :     {
     339                 :        748 :       char *r = suggestions[i];
     340                 :        748 :       if (strcmp (r, expected) == 0)
     341                 :            :         return true;
     342                 :            :     }
     343                 :            : 
     344                 :            :   return false;
     345                 :            : }
     346                 :            : 
     347                 :            : /* Return true when PROPOSER does not find any partial completion
     348                 :            :    for OPTION_PREFIX.  */
     349                 :            : 
     350                 :            : static bool
     351                 :         22 : empty_completion_p (option_proposer &proposer, const char *option_prefix)
     352                 :            : {
     353                 :         44 :   auto_string_vec suggestions;
     354                 :         22 :   proposer.get_completions (option_prefix, suggestions);
     355                 :         22 :   return suggestions.is_empty ();
     356                 :            : }
     357                 :            : 
     358                 :            : /* Verify autocompletions of partially-complete options.  */
     359                 :            : 
     360                 :            : static void
     361                 :          2 : test_completion_partial_match (option_proposer &proposer)
     362                 :            : {
     363                 :          2 :   ASSERT_TRUE (in_completion_p (proposer, "-fsani", "-fsanitize=address"));
     364                 :          2 :   ASSERT_TRUE (in_completion_p (proposer, "-fsani",
     365                 :            :                                 "-fsanitize-address-use-after-scope"));
     366                 :          2 :   ASSERT_TRUE (in_completion_p (proposer, "-fipa-icf", "-fipa-icf-functions"));
     367                 :          2 :   ASSERT_TRUE (in_completion_p (proposer, "-fipa-icf", "-fipa-icf"));
     368                 :          2 :   ASSERT_TRUE (in_completion_p (proposer, "--param=",
     369                 :            :                                 "--param=max-vartrack-reverse-op-size="));
     370                 :          2 :   ASSERT_TRUE (in_completion_p (proposer, "--param ",
     371                 :            :                                 "--param max-vartrack-reverse-op-size="));
     372                 :            : 
     373                 :          2 :   ASSERT_FALSE (in_completion_p (proposer, "-fipa-icf", "-fipa"));
     374                 :          2 :   ASSERT_FALSE (in_completion_p (proposer, "-fipa-icf-functions", "-fipa-icf"));
     375                 :            : 
     376                 :          2 :   ASSERT_FALSE (empty_completion_p (proposer, "-"));
     377                 :          2 :   ASSERT_FALSE (empty_completion_p (proposer, "-fipa"));
     378                 :          2 :   ASSERT_FALSE (empty_completion_p (proposer, "--par"));
     379                 :          2 : }
     380                 :            : 
     381                 :            : /* Verify that autocompletion does not return any match for garbage inputs.  */
     382                 :            : 
     383                 :            : static void
     384                 :          2 : test_completion_garbage (option_proposer &proposer)
     385                 :            : {
     386                 :          2 :   ASSERT_TRUE (empty_completion_p (proposer, NULL));
     387                 :          2 :   ASSERT_TRUE (empty_completion_p (proposer, ""));
     388                 :          2 :   ASSERT_TRUE (empty_completion_p (proposer, "- "));
     389                 :          2 :   ASSERT_TRUE (empty_completion_p (proposer, "123456789"));
     390                 :          2 :   ASSERT_TRUE (empty_completion_p (proposer, "---------"));
     391                 :          2 :   ASSERT_TRUE (empty_completion_p (proposer, "#########"));
     392                 :          2 :   ASSERT_TRUE (empty_completion_p (proposer, "- - - - - -"));
     393                 :          2 :   ASSERT_TRUE (empty_completion_p (proposer, "-fsanitize=address2"));
     394                 :          2 : }
     395                 :            : 
     396                 :            : /* Run all of the selftests within this file.  */
     397                 :            : 
     398                 :            : void
     399                 :          2 : opt_proposer_c_tests ()
     400                 :            : {
     401                 :          4 :   option_proposer proposer;
     402                 :            : 
     403                 :          2 :   test_completion_valid_options (proposer);
     404                 :          2 :   test_completion_valid_params (proposer);
     405                 :          2 :   test_completion_partial_match (proposer);
     406                 :          2 :   test_completion_garbage (proposer);
     407                 :          2 : }
     408                 :            : 
     409                 :            : } // namespace selftest
     410                 :            : 
     411                 :            : #endif /* #if CHECKING_P */

Generated by: LCOV version 1.0

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 --enable-host-shared. GCC test suite is run with the built compiler.