LCOV - code coverage report
Current view: top level - gcc - gcc-urlifier.cc (source / functions) Coverage Total Hit
Test: gcc.info Lines: 98.8 % 86 85
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 10 10
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Automatic generation of links into GCC's documentation.
       2              :    Copyright (C) 2023-2026 Free Software Foundation, Inc.
       3              :    Contributed by David Malcolm <dmalcolm@redhat.com>.
       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 "pretty-print.h"
      25              : #include "pretty-print-urlifier.h"
      26              : #include "gcc-urlifier.h"
      27              : #include "opts.h"
      28              : #include "options.h"
      29              : #include "diagnostic.h"
      30              : #include "selftest.h"
      31              : 
      32              : char *
      33        18794 : make_doc_url (const char *doc_url_suffix)
      34              : {
      35        18794 :   if (!doc_url_suffix)
      36              :     return nullptr;
      37              : 
      38        18794 :   return concat (DOCUMENTATION_ROOT_URL, doc_url_suffix, nullptr);
      39              : }
      40              : 
      41              : namespace {
      42              : 
      43              : /* Concrete subclass of urlifier for generating links into
      44              :    GCC's HTML documentation.  */
      45              : 
      46            0 : class gcc_urlifier : public urlifier
      47              : {
      48              : public:
      49       579711 :   gcc_urlifier (unsigned int lang_mask)
      50       579707 :   : m_lang_mask (lang_mask)
      51              :   {}
      52              : 
      53              :   char *get_url_for_quoted_text (const char *p, size_t sz) const final override;
      54              : 
      55              :   label_text get_url_suffix_for_quoted_text (const char *p, size_t sz) const;
      56              :   /* We use ATTRIBUTE_UNUSED as this helper is called only from ASSERTs.  */
      57              :   label_text get_url_suffix_for_quoted_text (const char *p) const ATTRIBUTE_UNUSED;
      58              : 
      59              : private:
      60              :   label_text get_url_suffix_for_option (const char *p, size_t sz) const;
      61              : 
      62              :   unsigned int m_lang_mask;
      63              : };
      64              : 
      65              : /* class gcc_urlifier : public urlifier.  */
      66              : 
      67              : /* Manage a hard-coded mapping from quoted string to URL suffixes
      68              :    in gcc-urlifier.def  */
      69              : 
      70              : #define DOC_URL(QUOTED_TEXT, URL_SUFFIX) \
      71              :   { (QUOTED_TEXT), (URL_SUFFIX) }
      72              : 
      73              : static const struct
      74              : {
      75              :   const char *quoted_text;
      76              :   const char *url_suffix;
      77              : } doc_urls[] = {
      78              : 
      79              : #include "gcc-urlifier.def"
      80              : 
      81              : };
      82              : 
      83              : /* Implementation of urlifier::get_url_for_quoted_text vfunc for GCC
      84              :    diagnostics.  */
      85              : 
      86              : char *
      87       865912 : gcc_urlifier::get_url_for_quoted_text (const char *p, size_t sz) const
      88              : {
      89       865912 :   label_text url_suffix = get_url_suffix_for_quoted_text (p, sz);
      90       865912 :   if (url_suffix.get ())
      91        14334 :     return make_doc_url (url_suffix.get ());
      92              :   return nullptr;
      93       865912 : }
      94              : 
      95              : /* Look for a URL for the quoted string (P, SZ).
      96              :    Return the url suffix if found, or nullptr otherwise.  */
      97              : 
      98              : label_text
      99       866004 : gcc_urlifier::get_url_suffix_for_quoted_text (const char *p, size_t sz) const
     100              : {
     101       866004 :   if (sz == 0)
     102            4 :     return label_text ();
     103              : 
     104              :   /* If this is an option, look up the option and see if we have
     105              :      a URL for it.  */
     106       866000 :   if (p[0] == '-')
     107              :     {
     108        29087 :       label_text suffix = get_url_suffix_for_option (p, sz);
     109        29087 :       if (suffix.get ())
     110        14173 :         return suffix;
     111        29087 :     }
     112              : 
     113              :   /* Otherwise, look within the hard-coded data table in gcc-urlifier.def.
     114              : 
     115              :      Binary search.  This assumes that the quoted_text fields of doc_urls
     116              :      are in sorted order.  */
     117       851827 :   int min = 0;
     118       851827 :   int max = ARRAY_SIZE (doc_urls) - 1;
     119      5105432 :   while (true)
     120              :     {
     121      5105432 :       if (min > max)
     122       851586 :         return label_text ();
     123      4253846 :       int midpoint = (min + max) / 2;
     124      4253846 :       gcc_assert ((size_t)midpoint < ARRAY_SIZE (doc_urls));
     125      4253846 :       int cmp = strncmp (p, doc_urls[midpoint].quoted_text, sz);
     126      4253846 :       if (cmp == 0)
     127              :         {
     128          810 :           if (doc_urls[midpoint].quoted_text[sz] == '\0')
     129          241 :             return label_text::borrow (doc_urls[midpoint].url_suffix);
     130              :           else
     131          569 :             max = midpoint - 1;
     132              :         }
     133      4253036 :       else if (cmp < 0)
     134        13484 :         max = midpoint - 1;
     135              :       else
     136      4239552 :         min = midpoint + 1;
     137              :     }
     138              : 
     139              :   /* Not found.  */
     140              :   return label_text ();
     141              : }
     142              : 
     143              : /* For use in selftests.  */
     144              : 
     145              : label_text
     146           92 : gcc_urlifier::get_url_suffix_for_quoted_text (const char *p) const
     147              : {
     148           92 :   return get_url_suffix_for_quoted_text (p, strlen (p));
     149              : }
     150              : 
     151              : /* Look for a URL for the quoted string (P, SZ) that appears to be
     152              :    an option.
     153              :    Return the url suffix if found, or nullptr otherwise.  */
     154              : 
     155              : label_text
     156        29087 : gcc_urlifier::get_url_suffix_for_option (const char *p, size_t sz) const
     157              : {
     158              :   /* Look up this option
     159              : 
     160              :      find_opt does a binary search, taking a 0-terminated string,
     161              :      and skipping the leading '-'.
     162              : 
     163              :      We have a (pointer,size) pair that doesn't necessarily have a
     164              :      terminator.
     165              :      Additionally, we could have one of the e.g. "-Wno-" variants of
     166              :      the option, which find_opt doesn't handle.
     167              : 
     168              :      Hence we need to create input for find_opt in a temporary buffer.  */
     169        29087 :   char *option_buffer;
     170              : 
     171        29087 :   const char *new_prefix;
     172        29087 :   if (const char *old_prefix = get_option_prefix_remapping (p, sz, &new_prefix))
     173              :     {
     174              :       /* We have one of the variants; generate a buffer containing a copy
     175              :          that maps from the old prefix to the new prefix
     176              :          e.g. given "-Wno-suffix", generate "-Wsuffix".  */
     177         9908 :       gcc_assert (old_prefix[0] == '-');
     178         9908 :       gcc_assert (new_prefix);
     179         9908 :       gcc_assert (new_prefix[0] == '-');
     180              : 
     181         9908 :       const size_t old_prefix_len = strlen (old_prefix);
     182         9908 :       gcc_assert (old_prefix_len <= sz);
     183         9908 :       const size_t suffix_len = sz - old_prefix_len;
     184         9908 :       const size_t new_prefix_len = strlen (new_prefix);
     185         9908 :       const size_t new_sz = new_prefix_len + suffix_len + 1;
     186              : 
     187         9908 :       option_buffer = (char *)xmalloc (new_sz);
     188         9908 :       memcpy (option_buffer, new_prefix, new_prefix_len);
     189              :       /* Copy suffix.  */
     190         9908 :       memcpy (option_buffer + new_prefix_len, p + old_prefix_len, suffix_len);
     191              :       /* Terminate.  */
     192         9908 :       option_buffer[new_prefix_len + suffix_len] = '\0';
     193              :     }
     194              :   else
     195              :     {
     196              :       /* Otherwise we can simply create a 0-terminated clone of the string.  */
     197        19179 :       gcc_assert (sz > 0);
     198        19179 :       gcc_assert (p[0] == '-');
     199        19179 :       option_buffer = xstrndup (p, sz);
     200              :     }
     201              : 
     202        29087 :   size_t opt = find_opt (option_buffer + 1, m_lang_mask);
     203        29087 :   free (option_buffer);
     204              : 
     205        29087 :   if (opt >= N_OPTS)
     206              :     /* Option not recognized.  */
     207         2869 :     return label_text ();
     208              : 
     209        26218 :   return get_option_url_suffix (opt, m_lang_mask);
     210              : }
     211              : 
     212              : } // anonymous namespace
     213              : 
     214              : std::unique_ptr<urlifier>
     215       579707 : make_gcc_urlifier (unsigned int lang_mask)
     216              : {
     217       579707 :   return std::make_unique<gcc_urlifier> (lang_mask);
     218              : }
     219              : 
     220              : /* class auto_override_urlifier.  */
     221              : 
     222   1942308833 : auto_override_urlifier::auto_override_urlifier (const urlifier &new_urlifier)
     223              : {
     224   1942308833 :   global_dc->push_borrowed_urlifier (new_urlifier);
     225   1942308833 : }
     226              : 
     227   1942308832 : auto_override_urlifier::~auto_override_urlifier ()
     228              : {
     229   1942308832 :   global_dc->pop_urlifier ();
     230   1942308832 : }
     231              : 
     232              : #if CHECKING_P
     233              : 
     234              : namespace selftest {
     235              : 
     236              : /* Selftests.  */
     237              : 
     238              : static void
     239            4 : test_gcc_urlifier ()
     240              : {
     241              :   /* Check that doc_urls.quoted_text is sorted.  */
     242           68 :   for (size_t idx = 1; idx < ARRAY_SIZE (doc_urls); idx++)
     243           64 :     gcc_assert (strcmp (doc_urls[idx - 1].quoted_text,
     244              :                         doc_urls[idx].quoted_text)
     245              :                 < 0);
     246              : 
     247            4 :   gcc_urlifier u (0);
     248              : 
     249            4 :   ASSERT_EQ (u.get_url_suffix_for_quoted_text ("").get (), nullptr);
     250            4 :   ASSERT_EQ (u.get_url_suffix_for_quoted_text (")").get (), nullptr);
     251              : 
     252            4 :   ASSERT_STREQ (u.get_url_suffix_for_quoted_text ("#pragma message").get (),
     253              :                 "gcc/Diagnostic-Pragmas.html");
     254              : 
     255              :   // Incomplete prefix of a quoted_text
     256            4 :   ASSERT_EQ (u.get_url_suffix_for_quoted_text ("#pragma mess").get (), nullptr);
     257              : 
     258              :   /* Check that every element is findable.  */
     259           72 :   for (size_t idx = 0; idx < ARRAY_SIZE (doc_urls); idx++)
     260           68 :     ASSERT_STREQ
     261              :       (u.get_url_suffix_for_quoted_text (doc_urls[idx].quoted_text).get (),
     262              :        doc_urls[idx].url_suffix);
     263              : 
     264              :   /* Check an option.  */
     265            4 :   const char *s1 = u.get_url_suffix_for_quoted_text ("-fpack-struct").get ();
     266            4 :   ASSERT_TRUE (!strcmp (s1,
     267              :                         "gcc/Code-Gen-Options.html#index-fno-pack-struct")
     268              :                || !strcmp (s1,
     269              :                            "gcc/Code-Gen-Options.html#index-fpack-struct"));
     270              : 
     271              :   /* Check a "-fno-" variant of an option.  */
     272            4 :   const char *s2 = u.get_url_suffix_for_quoted_text ("-fno-inline").get ();
     273            4 :   ASSERT_TRUE (!strcmp (s2,
     274              :                         "gcc/Optimize-Options.html#index-fno-inline")
     275              :                || !strcmp (s2,
     276              :                            "gcc/Optimize-Options.html#index-finline"));
     277            4 : }
     278              : 
     279              : /* Run all of the selftests within this file.  */
     280              : 
     281              : void
     282            4 : gcc_urlifier_cc_tests ()
     283              : {
     284            4 :   test_gcc_urlifier ();
     285            4 : }
     286              : 
     287              : } // namespace selftest
     288              : 
     289              : #endif /* #if CHECKING_P */
        

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.