LCOV - code coverage report
Current view: top level - libcpp/include - rich-location.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 100.0 % 33 33
Test Date: 2026-02-28 14:20:25 Functions: 100.0 % 2 2
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /* Bundles of location information used when printing diagnostics.
       2              :    Copyright (C) 2015-2026 Free Software Foundation, Inc.
       3              : 
       4              : This program is free software; you can redistribute it and/or modify it
       5              : under the terms of the GNU General Public License as published by the
       6              : Free Software Foundation; either version 3, or (at your option) any
       7              : later version.
       8              : 
       9              : This program is distributed in the hope that it will be useful,
      10              : but WITHOUT ANY WARRANTY; without even the implied warranty of
      11              : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12              : GNU General Public License for more details.
      13              : 
      14              : You should have received a copy of the GNU General Public License
      15              : along with this program; see the file COPYING3.  If not see
      16              : <http://www.gnu.org/licenses/>.
      17              : 
      18              :  In other words, you are welcome to use, share and improve this program.
      19              :  You are forbidden to forbid anyone else to use, share and improve
      20              :  what you give them.   Help stamp out software-hoarding!  */
      21              : 
      22              : #ifndef LIBCPP_RICH_LOCATION_H
      23              : #define LIBCPP_RICH_LOCATION_H
      24              : 
      25              : #include "label-text.h"
      26              : 
      27              : class range_label;
      28              : namespace diagnostics { class label_effects; }
      29              : 
      30              : /* A hint to diagnostic_show_locus on how to print a source range within a
      31              :    rich_location.
      32              : 
      33              :    Typically this is SHOW_RANGE_WITH_CARET for the 0th range, and
      34              :    SHOW_RANGE_WITHOUT_CARET for subsequent ranges,
      35              :    but the Fortran frontend uses SHOW_RANGE_WITH_CARET repeatedly for
      36              :    printing things like:
      37              : 
      38              :        x = x + y
      39              :            1   2
      40              :        Error: Shapes for operands at (1) and (2) are not conformable
      41              : 
      42              :    where "1" and "2" are notionally carets.  */
      43              : 
      44              : enum range_display_kind
      45              : {
      46              :   /* Show the pertinent source line(s), the caret, and underline(s).  */
      47              :   SHOW_RANGE_WITH_CARET,
      48              : 
      49              :   /* Show the pertinent source line(s) and underline(s), but don't
      50              :      show the caret (just an underline).  */
      51              :   SHOW_RANGE_WITHOUT_CARET,
      52              : 
      53              :   /* Just show the source lines; don't show the range itself.
      54              :      This is for use when displaying some line-insertion fix-it hints (for
      55              :      showing the user context on the change, for when it doesn't make sense
      56              :      to highlight the first column on the next line).  */
      57              :   SHOW_LINES_WITHOUT_RANGE
      58              : };
      59              : 
      60              : /* A location within a rich_location: a caret&range, with
      61              :    the caret potentially flagged for display, and an optional
      62              :    label.  */
      63              : 
      64              : struct location_range
      65              : {
      66              :   location_t m_loc;
      67              : 
      68              :   enum range_display_kind m_range_display_kind;
      69              : 
      70              :   /* If non-NULL, the label for this range.  */
      71              :   const range_label *m_label;
      72              : 
      73              :   /* If non-null, the name of the color to use for this range.  */
      74              :   const char *m_highlight_color;
      75              : };
      76              : 
      77              : /* A partially-embedded vec for use within rich_location for storing
      78              :    ranges and fix-it hints.
      79              : 
      80              :    Elements [0..NUM_EMBEDDED) are allocated within m_embed, after
      81              :    that they are within the dynamically-allocated m_extra.
      82              : 
      83              :    This allows for static allocation in the common case, whilst
      84              :    supporting the rarer case of an arbitrary number of elements.
      85              : 
      86              :    Dynamic allocation is not performed unless it's needed.  */
      87              : 
      88              : template <typename T, int NUM_EMBEDDED>
      89              : class semi_embedded_vec
      90              : {
      91              :  public:
      92              :   semi_embedded_vec ();
      93              :   ~semi_embedded_vec ();
      94              :   semi_embedded_vec (const semi_embedded_vec &other);
      95              : 
      96      1567051 :   unsigned int count () const { return m_num; }
      97              :   T& operator[] (int idx);
      98              :   const T& operator[] (int idx) const;
      99              : 
     100              :   void push (const T&);
     101              :   void truncate (int len);
     102              : 
     103              :  private:
     104              :   int m_num;
     105              :   T m_embedded[NUM_EMBEDDED];
     106              :   int m_alloc;
     107              :   T *m_extra;
     108              : };
     109              : 
     110              : /* Constructor for semi_embedded_vec.  In particular, no dynamic allocation
     111              :    is done.  */
     112              : 
     113              : template <typename T, int NUM_EMBEDDED>
     114              : semi_embedded_vec<T, NUM_EMBEDDED>::semi_embedded_vec ()
     115              : : m_num (0), m_alloc (0), m_extra (NULL)
     116              : {
     117              : }
     118              : 
     119              : /* Copy constructor for semi_embedded_vec.  */
     120              : 
     121              : template <typename T, int NUM_EMBEDDED>
     122              : semi_embedded_vec<T, NUM_EMBEDDED>::semi_embedded_vec (const semi_embedded_vec &other)
     123              : : m_num (0),
     124              :   m_alloc (other.m_alloc),
     125              :   m_extra (nullptr)
     126              : {
     127              :   if (other.m_extra)
     128              :     m_extra = XNEWVEC (T, m_alloc);
     129              : 
     130              :   for (int i = 0; i < other.m_num; i++)
     131              :     push (other[i]);
     132              : }
     133              : 
     134              : /* semi_embedded_vec's dtor.  Release any dynamically-allocated memory.  */
     135              : 
     136              : template <typename T, int NUM_EMBEDDED>
     137              : semi_embedded_vec<T, NUM_EMBEDDED>::~semi_embedded_vec ()
     138              : {
     139              :   XDELETEVEC (m_extra);
     140              : }
     141              : 
     142              : /* Look up element IDX, mutably.  */
     143              : 
     144              : template <typename T, int NUM_EMBEDDED>
     145              : T&
     146              : semi_embedded_vec<T, NUM_EMBEDDED>::operator[] (int idx)
     147              : {
     148              :   linemap_assert (idx < m_num);
     149              :   if (idx < NUM_EMBEDDED)
     150              :     return m_embedded[idx];
     151              :   else
     152              :     {
     153              :       linemap_assert (m_extra != NULL);
     154              :       return m_extra[idx - NUM_EMBEDDED];
     155              :     }
     156              : }
     157              : 
     158              : /* Look up element IDX (const).  */
     159              : 
     160              : template <typename T, int NUM_EMBEDDED>
     161              : const T&
     162        19376 : semi_embedded_vec<T, NUM_EMBEDDED>::operator[] (int idx) const
     163              : {
     164        19376 :   linemap_assert (idx < m_num);
     165        19376 :   if (idx < NUM_EMBEDDED)
     166        13695 :     return m_embedded[idx];
     167              :   else
     168              :     {
     169         5681 :       linemap_assert (m_extra != NULL);
     170         5681 :       return m_extra[idx - NUM_EMBEDDED];
     171              :     }
     172              : }
     173              : 
     174              : /* Append VALUE to the end of the semi_embedded_vec.  */
     175              : 
     176              : template <typename T, int NUM_EMBEDDED>
     177              : void
     178              : semi_embedded_vec<T, NUM_EMBEDDED>::push (const T& value)
     179              : {
     180              :   int idx = m_num++;
     181              :   if (idx < NUM_EMBEDDED)
     182              :     m_embedded[idx] = value;
     183              :   else
     184              :     {
     185              :       /* Offset "idx" to be an index within m_extra.  */
     186              :       idx -= NUM_EMBEDDED;
     187              :       if (NULL == m_extra)
     188              :         {
     189              :           linemap_assert (m_alloc == 0);
     190              :           m_alloc = 16;
     191              :           m_extra = XNEWVEC (T, m_alloc);
     192              :         }
     193              :       else if (idx >= m_alloc)
     194              :         {
     195              :           linemap_assert (m_alloc > 0);
     196              :           m_alloc *= 2;
     197              :           m_extra = XRESIZEVEC (T, m_extra, m_alloc);
     198              :         }
     199              :       linemap_assert (m_extra);
     200              :       linemap_assert (idx < m_alloc);
     201              :       m_extra[idx] = value;
     202              :     }
     203              : }
     204              : 
     205              : /* Truncate to length LEN.  No deallocation is performed.  */
     206              : 
     207              : template <typename T, int NUM_EMBEDDED>
     208              : void
     209              : semi_embedded_vec<T, NUM_EMBEDDED>::truncate (int len)
     210              : {
     211              :   linemap_assert (len <= m_num);
     212              :   m_num = len;
     213              : }
     214              : 
     215              : class fixit_hint;
     216              : namespace diagnostics { namespace paths { class path; }}
     217              : 
     218              : /* A "rich" source code location, for use when printing diagnostics.
     219              :    A rich_location has one or more carets&ranges, where the carets
     220              :    are optional.  These are referred to as "ranges" from here.
     221              :    Typically the zeroth range has a caret; other ranges sometimes
     222              :    have carets.
     223              : 
     224              :    The "primary" location of a rich_location is the caret of range 0,
     225              :    used for determining the line/column when printing diagnostic
     226              :    text, such as:
     227              : 
     228              :       some-file.c:3:1: error: ...etc...
     229              : 
     230              :    Additional ranges may be added to help the user identify other
     231              :    pertinent clauses in a diagnostic.
     232              : 
     233              :    Ranges can (optionally) be given labels via class range_label.
     234              : 
     235              :    rich_location instances are intended to be allocated on the stack
     236              :    when generating diagnostics, and to be short-lived.
     237              : 
     238              :    Examples of rich locations
     239              :    --------------------------
     240              : 
     241              :    Example A
     242              :    *********
     243              :       int i = "foo";
     244              :               ^
     245              :    This "rich" location is simply a single range (range 0), with
     246              :    caret = start = finish at the given point.
     247              : 
     248              :    Example B
     249              :    *********
     250              :       a = (foo && bar)
     251              :           ~~~~~^~~~~~~
     252              :    This rich location has a single range (range 0), with the caret
     253              :    at the first "&", and the start/finish at the parentheses.
     254              :    Compare with example C below.
     255              : 
     256              :    Example C
     257              :    *********
     258              :       a = (foo && bar)
     259              :            ~~~ ^~ ~~~
     260              :    This rich location has three ranges:
     261              :    - Range 0 has its caret and start location at the first "&" and
     262              :      end at the second "&.
     263              :    - Range 1 has its start and finish at the "f" and "o" of "foo";
     264              :      the caret is not flagged for display, but is perhaps at the "f"
     265              :      of "foo".
     266              :    - Similarly, range 2 has its start and finish at the "b" and "r" of
     267              :      "bar"; the caret is not flagged for display, but is perhaps at the
     268              :      "b" of "bar".
     269              :    Compare with example B above.
     270              : 
     271              :    Example D (Fortran frontend)
     272              :    ****************************
     273              :        x = x + y
     274              :            1   2
     275              :    This rich location has range 0 at "1", and range 1 at "2".
     276              :    Both are flagged for caret display.  Both ranges have start/finish
     277              :    equal to their caret point.  The frontend overrides the diagnostic
     278              :    context's default caret character for these ranges.
     279              : 
     280              :    Example E (range labels)
     281              :    ************************
     282              :       printf ("arg0: %i  arg1: %s arg2: %i",
     283              :                                ^~
     284              :                                |
     285              :                                const char *
     286              :               100, 101, 102);
     287              :                    ~~~
     288              :                    |
     289              :                    int
     290              :    This rich location has two ranges:
     291              :    - range 0 is at the "%s" with start = caret = "%" and finish at
     292              :      the "s".  It has a range_label ("const char *").
     293              :    - range 1 has start/finish covering the "101" and is not flagged for
     294              :      caret printing.  The caret is at the start of "101", where its
     295              :      range_label is printed ("int").
     296              : 
     297              :    Fix-it hints
     298              :    ------------
     299              : 
     300              :    Rich locations can also contain "fix-it hints", giving suggestions
     301              :    for the user on how to edit their code to fix a problem.  These
     302              :    can be expressed as insertions, replacements, and removals of text.
     303              :    The edits by default are relative to the zeroth range within the
     304              :    rich_location, but optionally they can be expressed relative to
     305              :    other locations (using various overloaded methods of the form
     306              :    rich_location::add_fixit_*).
     307              : 
     308              :    For example:
     309              : 
     310              :    Example F: fix-it hint: insert_before
     311              :    *************************************
     312              :       ptr = arr[0];
     313              :             ^~~~~~
     314              :             &
     315              :    This rich location has a single range (range 0) covering "arr[0]",
     316              :    with the caret at the start.  The rich location has a single
     317              :    insertion fix-it hint, inserted before range 0, added via
     318              :      richloc.add_fixit_insert_before ("&");
     319              : 
     320              :    Example G: multiple fix-it hints: insert_before and insert_after
     321              :    ****************************************************************
     322              :       #define FN(ARG0, ARG1, ARG2) fn(ARG0, ARG1, ARG2)
     323              :                                       ^~~~  ^~~~  ^~~~
     324              :                                       (   ) (   ) (   )
     325              :    This rich location has three ranges, covering "arg0", "arg1",
     326              :    and "arg2", all with caret-printing enabled.
     327              :    The rich location has 6 insertion fix-it hints: each arg
     328              :    has a pair of insertion fix-it hints, suggesting wrapping
     329              :    them with parentheses: one a '(' inserted before,
     330              :    the other a ')' inserted after, added via
     331              :      richloc.add_fixit_insert_before (LOC, "(");
     332              :    and
     333              :      richloc.add_fixit_insert_after (LOC, ")");
     334              : 
     335              :    Example H: fix-it hint: removal
     336              :    *******************************
     337              :      struct s {int i};;
     338              :                       ^
     339              :                       -
     340              :    This rich location has a single range at the stray trailing
     341              :    semicolon, along with a single removal fix-it hint, covering
     342              :    the same range, added via:
     343              :      richloc.add_fixit_remove ();
     344              : 
     345              :    Example I: fix-it hint: replace
     346              :    *******************************
     347              :       c = s.colour;
     348              :             ^~~~~~
     349              :             color
     350              :    This rich location has a single range (range 0) covering "colour",
     351              :    and a single "replace" fix-it hint, covering the same range,
     352              :    added via
     353              :      richloc.add_fixit_replace ("color");
     354              : 
     355              :    Example J: fix-it hint: line insertion
     356              :    **************************************
     357              : 
     358              :      3 | #include <stddef.h>
     359              :      + |+#include <stdio.h>
     360              :      4 | int the_next_line;
     361              : 
     362              :    This rich location has a single range at line 4 column 1, marked
     363              :    with SHOW_LINES_WITHOUT_RANGE (to avoid printing a meaningless caret
     364              :    on the "i" of int).  It has a insertion fix-it hint of the string
     365              :    "#include <stdio.h>\n".
     366              : 
     367              :    Adding a fix-it hint can fail: for example, attempts to insert content
     368              :    at the transition between two line maps may fail due to there being no
     369              :    location_t value to express the new location.
     370              : 
     371              :    Attempts to add a fix-it hint within a macro expansion will fail.
     372              : 
     373              :    There is only limited support for newline characters in fix-it hints:
     374              :    only hints with newlines which insert an entire new line are permitted,
     375              :    inserting at the start of a line, and finishing with a newline
     376              :    (with no interior newline characters).  Other attempts to add
     377              :    fix-it hints containing newline characters will fail.
     378              :    Similarly, attempts to delete or replace a range *affecting* multiple
     379              :    lines will fail.
     380              : 
     381              :    The rich_location API handles these failures gracefully, so that
     382              :    diagnostics can attempt to add fix-it hints without each needing
     383              :    extensive checking.
     384              : 
     385              :    Fix-it hints within a rich_location are "atomic": if any hints can't
     386              :    be applied, none of them will be (tracked by the m_seen_impossible_fixit
     387              :    flag), and no fix-its hints will be displayed for that rich_location.
     388              :    This implies that diagnostic messages need to be worded in such a way
     389              :    that they make sense whether or not the fix-it hints are displayed,
     390              :    or that richloc.seen_impossible_fixit_p () should be checked before
     391              :    issuing the diagnostics.  */
     392              : 
     393              : class rich_location
     394              : {
     395              :  public:
     396              :   /* Constructors.  */
     397              : 
     398              :   /* Constructing from a location.  */
     399              :   rich_location (line_maps *set, location_t loc,
     400              :                  const range_label *label = nullptr,
     401              :                  const char *label_highlight_color = nullptr);
     402              : 
     403              :   /* Destructor.  */
     404              :   ~rich_location ();
     405              : 
     406              :   rich_location (const rich_location &);
     407              :   rich_location (rich_location &&) = delete;
     408              :   rich_location &operator= (const rich_location &) = delete;
     409              :   rich_location &operator= (rich_location &&) = delete;
     410              : 
     411              :   /* Accessors.  */
     412    106099960 :   location_t get_loc () const { return get_loc (0); }
     413              :   location_t get_loc (unsigned int idx) const;
     414              : 
     415              :   void set_highlight_color (const char *highlight_color);
     416              : 
     417              :   void
     418              :   add_range (location_t loc,
     419              :              enum range_display_kind range_display_kind
     420              :                = SHOW_RANGE_WITHOUT_CARET,
     421              :              const range_label *label = nullptr,
     422              :              const char *highlight_color = nullptr);
     423              : 
     424              :   void
     425              :   set_range (unsigned int idx, location_t loc,
     426              :              enum range_display_kind range_display_kind,
     427              :              const char *highlight_color = nullptr);
     428              : 
     429      1440545 :   unsigned int get_num_locations () const { return m_ranges.count (); }
     430              : 
     431              :   const location_range *get_range (unsigned int idx) const;
     432              :   location_range *get_range (unsigned int idx);
     433              : 
     434              :   expanded_location get_expanded_location (unsigned int idx) const;
     435              : 
     436              :   void
     437              :   override_column (int column);
     438              : 
     439              :   /* Fix-it hints.  */
     440              : 
     441              :   /* Methods for adding insertion fix-it hints.  */
     442              : 
     443              :   /* Suggest inserting NEW_CONTENT immediately before the primary
     444              :      range's start.  */
     445              :   void
     446              :   add_fixit_insert_before (const char *new_content);
     447              : 
     448              :   /* Suggest inserting NEW_CONTENT immediately before the start of WHERE.  */
     449              :   void
     450              :   add_fixit_insert_before (location_t where,
     451              :                            const char *new_content);
     452              : 
     453              :   /* Suggest inserting NEW_CONTENT immediately after the end of the primary
     454              :      range.  */
     455              :   void
     456              :   add_fixit_insert_after (const char *new_content);
     457              : 
     458              :   /* Suggest inserting NEW_CONTENT immediately after the end of WHERE.  */
     459              :   void
     460              :   add_fixit_insert_after (location_t where,
     461              :                           const char *new_content);
     462              : 
     463              :   /* Methods for adding removal fix-it hints.  */
     464              : 
     465              :   /* Suggest removing the content covered by range 0.  */
     466              :   void
     467              :   add_fixit_remove ();
     468              : 
     469              :   /* Suggest removing the content covered between the start and finish
     470              :      of WHERE.  */
     471              :   void
     472              :   add_fixit_remove (location_t where);
     473              : 
     474              :   /* Suggest removing the content covered by SRC_RANGE.  */
     475              :   void
     476              :   add_fixit_remove (source_range src_range);
     477              : 
     478              :   /* Methods for adding "replace" fix-it hints.  */
     479              : 
     480              :   /* Suggest replacing the content covered by range 0 with NEW_CONTENT.  */
     481              :   void
     482              :   add_fixit_replace (const char *new_content);
     483              : 
     484              :   /* Suggest replacing the content between the start and finish of
     485              :      WHERE with NEW_CONTENT.  */
     486              :   void
     487              :   add_fixit_replace (location_t where,
     488              :                      const char *new_content);
     489              : 
     490              :   /* Suggest replacing the content covered by SRC_RANGE with
     491              :      NEW_CONTENT.  */
     492              :   void
     493              :   add_fixit_replace (source_range src_range,
     494              :                      const char *new_content);
     495              : 
     496       126506 :   unsigned int get_num_fixit_hints () const { return m_fixit_hints.count (); }
     497        19376 :   fixit_hint *get_fixit_hint (int idx) const { return m_fixit_hints[idx]; }
     498              :   fixit_hint *get_last_fixit_hint () const;
     499        13796 :   bool seen_impossible_fixit_p () const { return m_seen_impossible_fixit; }
     500              : 
     501              :   /* Set this if the fix-it hints are not suitable to be
     502              :      automatically applied.
     503              : 
     504              :      For example, if you are suggesting more than one
     505              :      mutually exclusive solution to a problem, then
     506              :      it doesn't make sense to apply all of the solutions;
     507              :      manual intervention is required.
     508              : 
     509              :      If set, then the fix-it hints in the rich_location will
     510              :      be printed, but will not be added to generated patches,
     511              :      or affect the modified version of the file.  */
     512          140 :   void fixits_cannot_be_auto_applied ()
     513              :   {
     514          140 :     m_fixits_cannot_be_auto_applied = true;
     515              :   }
     516              : 
     517           60 :   bool fixits_can_be_auto_applied_p () const
     518              :   {
     519           60 :     return !m_fixits_cannot_be_auto_applied;
     520              :   }
     521              : 
     522              :   /* An optional path through the code.  */
     523       345058 :   const diagnostics::paths::path *get_path () const { return m_path; }
     524       893512 :   void set_path (const diagnostics::paths::path *path) { m_path = path; }
     525              : 
     526              :   /* A flag for hinting that the diagnostic involves character encoding
     527              :      issues, and thus that it will be helpful to the user if we show some
     528              :      representation of how the characters in the pertinent source lines
     529              :      are encoded.
     530              :      The default is false (i.e. do not escape).
     531              :      When set to true, non-ASCII bytes in the pertinent source lines will
     532              :      be escaped in a manner controlled by the user-supplied option
     533              :      -fdiagnostics-escape-format=, so that the user can better understand
     534              :      what's going on with the encoding in their source file.  */
     535       101458 :   bool escape_on_output_p () const { return m_escape_on_output; }
     536          468 :   void set_escape_on_output (bool flag) { m_escape_on_output = flag; }
     537              : 
     538        49799 :   const line_maps *get_line_table () const { return m_line_table; }
     539              : 
     540         1178 :   int get_column_override () const { return m_column_override; }
     541              : 
     542              : private:
     543              :   bool reject_impossible_fixit (location_t where);
     544              :   void stop_supporting_fixits ();
     545              :   void maybe_add_fixit (location_t start,
     546              :                         location_t next_loc,
     547              :                         const char *new_content);
     548              : 
     549              : public:
     550              :   static const int STATICALLY_ALLOCATED_RANGES = 3;
     551              : 
     552              : protected:
     553              :   line_maps * const m_line_table;
     554              :   semi_embedded_vec <location_range, STATICALLY_ALLOCATED_RANGES> m_ranges;
     555              : 
     556              :   int m_column_override;
     557              : 
     558              :   mutable bool m_have_expanded_location;
     559              :   bool m_seen_impossible_fixit;
     560              :   bool m_fixits_cannot_be_auto_applied;
     561              :   bool m_escape_on_output;
     562              : 
     563              :   mutable expanded_location m_expanded_location;
     564              : 
     565              :   /* The class manages the memory pointed to by the elements of
     566              :      the m_fixit_hints vector.  */
     567              :   static const int MAX_STATIC_FIXIT_HINTS = 2;
     568              :   semi_embedded_vec <fixit_hint *, MAX_STATIC_FIXIT_HINTS> m_fixit_hints;
     569              : 
     570              :   const diagnostics::paths::path *m_path;
     571              : };
     572              : 
     573              : /* Abstract base class for labelling a range within a rich_location
     574              :    (e.g. for labelling expressions with their type).
     575              : 
     576              :    Generating the text could require non-trivial work, so this work
     577              :    is delayed (via the "get_text" virtual function) until the diagnostic
     578              :    printing code "knows" it needs it, thus avoiding doing it e.g. for
     579              :    warnings that are filtered by command-line flags.  This virtual
     580              :    function also isolates libcpp and the diagnostics subsystem from
     581              :    the front-end and middle-end-specific code for generating the text
     582              :    for the labels.
     583              : 
     584              :    Like the rich_location instances they annotate, range_label instances
     585              :    are intended to be allocated on the stack when generating diagnostics,
     586              :    and to be short-lived.  */
     587              : 
     588        10496 : class range_label
     589              : {
     590              :  public:
     591         9194 :   virtual ~range_label () {}
     592              : 
     593              :   /* Get localized text for the label.
     594              :      The RANGE_IDX is provided, allowing for range_label instances to be
     595              :      shared by multiple ranges if need be (the "flyweight" design pattern).  */
     596              :   virtual label_text get_text (unsigned range_idx) const = 0;
     597              : 
     598              :   /* Get any special effects for the label (e.g. links to other labels).  */
     599              :   virtual const diagnostics::label_effects *
     600         8266 :   get_effects (unsigned /*range_idx*/) const
     601              :   {
     602         8266 :     return nullptr;
     603              :   }
     604              : };
     605              : 
     606              : /* A fix-it hint: a suggested insertion, replacement, or deletion of text.
     607              :    We handle these three types of edit with one class, by representing
     608              :    them as replacement of a half-open range:
     609              :        [start, next_loc)
     610              :    Insertions have start == next_loc: "replace" the empty string at the
     611              :    start location with the new string.
     612              :    Deletions are replacement with the empty string.
     613              : 
     614              :    There is only limited support for newline characters in fix-it hints
     615              :    as noted above in the comment for class rich_location.
     616              :    A fixit_hint instance can have at most one newline character; if
     617              :    present, the newline character must be the final character of
     618              :    the content (preventing e.g. fix-its that split a pre-existing line).  */
     619              : 
     620              : class fixit_hint
     621              : {
     622              :  public:
     623              :   fixit_hint (location_t start,
     624              :               location_t next_loc,
     625              :               const char *new_content);
     626              :   fixit_hint (const fixit_hint &other);
     627              :   fixit_hint (fixit_hint &&other) = delete;
     628              :   ~fixit_hint () { free (m_bytes); }
     629              :   fixit_hint &operator= (const fixit_hint &) = delete;
     630              :   fixit_hint &operator= (fixit_hint &&) = delete;
     631              : 
     632              :   bool affects_line_p (const line_maps *set,
     633              :                        const char *file,
     634              :                        int line) const;
     635        76028 :   location_t get_start_loc () const { return m_start; }
     636        60148 :   location_t get_next_loc () const { return m_next_loc; }
     637              :   bool maybe_append (location_t start,
     638              :                      location_t next_loc,
     639              :                      const char *new_content);
     640              : 
     641        12641 :   const char *get_string () const { return m_bytes; }
     642        39337 :   size_t get_length () const { return m_len; }
     643              : 
     644        27762 :   bool insertion_p () const { return m_start == m_next_loc; }
     645            5 :   bool deletion_p () const { return m_len == 0; }
     646            4 :   bool replacement_p () const { return m_len > 0 && m_start != m_next_loc; }
     647              : 
     648              :   bool ends_with_newline_p () const;
     649              : 
     650              :  private:
     651              :   /* We don't use source_range here since, unlike most places,
     652              :      this is a half-open/half-closed range:
     653              :        [start, next_loc)
     654              :      so that we can support insertion via start == next_loc.  */
     655              :   location_t m_start;
     656              :   location_t m_next_loc;
     657              :   char *m_bytes;
     658              :   size_t m_len;
     659              : };
     660              : 
     661              : #endif /* !LIBCPP_RICH_LOCATION_H  */
        

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.