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