LCOV - code coverage report
Current view: top level - gcc - pretty-print-format-impl.h (source / functions) Coverage Total Hit
Test: gcc.info Lines: 82.6 % 69 57
Test Date: 2025-03-22 13:13:03 Functions: 84.8 % 33 28
Legend: Lines: hit not hit | Branches: + taken - not taken # not executed Branches: - 0 0

             Branch data     Line data    Source code
       1                 :             : /* Implementation detail of pp_format.
       2                 :             :    Copyright (C) 2002-2025 Free Software Foundation, Inc.
       3                 :             :    Contributed by Gabriel Dos Reis <gdr@integrable-solutions.net>
       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                 :             : #ifndef GCC_PRETTY_PRINT_FORMAT_IMPL_H
      22                 :             : #define GCC_PRETTY_PRINT_FORMAT_IMPL_H
      23                 :             : 
      24                 :             : #include "pretty-print.h"
      25                 :             : #include "diagnostic-event-id.h"
      26                 :             : 
      27                 :             : /* A struct representing a pending item to be printed within
      28                 :             :    pp_format.
      29                 :             : 
      30                 :             :    These can represent:
      31                 :             :    - a run of text within one of the output_buffers's obstacks
      32                 :             :    - begin/end named color
      33                 :             :    - open/close quote
      34                 :             :    - begin/end URL
      35                 :             :    - event IDs
      36                 :             :    - custom data (for the formatter, for the pretty_printer,
      37                 :             :      or the output format)
      38                 :             : 
      39                 :             :    These are built into pp_token_list instances.
      40                 :             : 
      41                 :             :    Doing so allows for interaction between:
      42                 :             : 
      43                 :             :    - pretty_printer formatting codes (such as C++'s %H and %I,
      44                 :             :    which can't be printed until we've seen both)
      45                 :             : 
      46                 :             :    - output formats, such as text vs SARIF (so each can handle URLs
      47                 :             :    and event IDs it its own way)
      48                 :             : 
      49                 :             :    - optimization records, where we want to stash data into the
      50                 :             :    formatted messages
      51                 :             : 
      52                 :             :    - urlifiers: these can be run in phase 3 of formatting
      53                 :             : 
      54                 :             :    without needing lots of fragile logic on char pointers.
      55                 :             : 
      56                 :             :    To avoid needing lots of heap allocation/deallocation, pp_token
      57                 :             :    instances are allocated in the pretty_printer's chunk_obstack:
      58                 :             :    they must not outlive phase 3 of formatting of the given
      59                 :             :    pp_formatted_chunks level.  */
      60                 :             : 
      61                 :             : struct pp_token
      62                 :             : {
      63                 :             : public:
      64                 :             :   enum class kind
      65                 :             :   {
      66                 :             :     text,
      67                 :             : 
      68                 :             :     begin_color,
      69                 :             :     end_color,
      70                 :             : 
      71                 :             :     begin_quote,
      72                 :             :     end_quote,
      73                 :             : 
      74                 :             :     begin_url,
      75                 :             :     end_url,
      76                 :             : 
      77                 :             :     event_id,
      78                 :             : 
      79                 :             :     custom_data,
      80                 :             : 
      81                 :             :     NUM_KINDS
      82                 :             :   };
      83                 :             : 
      84                 :             :   pp_token (enum kind k);
      85                 :             : 
      86                 :             :   pp_token (const pp_token &) = delete;
      87                 :             :   pp_token (pp_token &&) = delete;
      88                 :             : 
      89                 :           0 :   virtual ~pp_token () = default;
      90                 :             : 
      91                 :             :   pp_token &operator= (const pp_token &) = delete;
      92                 :             :   pp_token &operator= (pp_token &&) = delete;
      93                 :             : 
      94                 :             :   void dump (FILE *out) const;
      95                 :           0 :   void DEBUG_FUNCTION dump () const { dump (stderr); }
      96                 :             : 
      97                 :             :   static void *operator new (size_t sz, obstack &s);
      98                 :             :   static void operator delete (void *);
      99                 :             : 
     100                 :             :   enum kind m_kind;
     101                 :             : 
     102                 :             :   // Intrusive doubly-linked list
     103                 :             :   pp_token *m_prev;
     104                 :             :   pp_token *m_next;
     105                 :             : };
     106                 :             : 
     107                 :             : /* Subclasses of pp_token for the various kinds of token.  */
     108                 :             : 
     109                 :             : struct pp_token_text : public pp_token
     110                 :             : {
     111                 :    46625924 :   pp_token_text (label_text &&value)
     112                 :    46625924 :   : pp_token (kind::text),
     113                 :    46625924 :     m_value (std::move (value))
     114                 :             :   {
     115                 :    46625924 :     gcc_assert (m_value.get ());
     116                 :    46625924 :   }
     117                 :             : 
     118                 :             :   label_text m_value;
     119                 :             : };
     120                 :             : 
     121                 :             : template <>
     122                 :             : template <>
     123                 :             : inline bool
     124                 :    33603533 : is_a_helper <pp_token_text *>::test (pp_token *tok)
     125                 :             : {
     126                 :    33603533 :   return tok->m_kind == pp_token::kind::text;
     127                 :             : }
     128                 :             : 
     129                 :             : template <>
     130                 :             : template <>
     131                 :             : inline bool
     132                 :        1302 : is_a_helper <const pp_token_text *>::test (const pp_token *tok)
     133                 :             : {
     134                 :        1302 :   return tok->m_kind == pp_token::kind::text;
     135                 :             : }
     136                 :             : 
     137                 :             : struct pp_token_begin_color : public pp_token
     138                 :             : {
     139                 :       22763 :   pp_token_begin_color (label_text &&value)
     140                 :       22763 :   : pp_token (kind::begin_color),
     141                 :       22763 :     m_value (std::move (value))
     142                 :             :   {
     143                 :       22763 :     gcc_assert (m_value.get ());
     144                 :       22763 :   }
     145                 :             : 
     146                 :             :   label_text m_value;
     147                 :             : };
     148                 :             : 
     149                 :             : template <>
     150                 :             : template <>
     151                 :             : inline bool
     152                 :       22761 : is_a_helper <pp_token_begin_color *>::test (pp_token *tok)
     153                 :             : {
     154                 :       22761 :   return tok->m_kind == pp_token::kind::begin_color;
     155                 :             : }
     156                 :             : 
     157                 :             : template <>
     158                 :             : template <>
     159                 :             : inline bool
     160                 :           0 : is_a_helper <const pp_token_begin_color *>::test (const pp_token *tok)
     161                 :             : {
     162                 :           0 :   return tok->m_kind == pp_token::kind::begin_color;
     163                 :             : }
     164                 :             : 
     165                 :             : struct pp_token_end_color : public pp_token
     166                 :             : {
     167                 :       22763 :   pp_token_end_color ()
     168                 :       45526 :   : pp_token (kind::end_color)
     169                 :             :   {
     170                 :             :   }
     171                 :             : };
     172                 :             : 
     173                 :             : struct pp_token_begin_quote : public pp_token
     174                 :             : {
     175                 :     1061318 :   pp_token_begin_quote ()
     176                 :     2122636 :   : pp_token (kind::begin_quote)
     177                 :             :   {
     178                 :             :   }
     179                 :             : };
     180                 :             : 
     181                 :             : struct pp_token_end_quote : public pp_token
     182                 :             : {
     183                 :     1036634 :   pp_token_end_quote ()
     184                 :     2073268 :   : pp_token (kind::end_quote)
     185                 :             :   {
     186                 :             :   }
     187                 :             : };
     188                 :             : 
     189                 :             : struct pp_token_begin_url : public pp_token
     190                 :             : {
     191                 :       18333 :   pp_token_begin_url (label_text &&value)
     192                 :       18333 :   : pp_token (kind::begin_url),
     193                 :       18333 :     m_value (std::move (value))
     194                 :             :   {
     195                 :       18333 :     gcc_assert (m_value.get ());
     196                 :       18333 :   }
     197                 :             : 
     198                 :             :   label_text m_value;
     199                 :             : };
     200                 :             : 
     201                 :             : template <>
     202                 :             : template <>
     203                 :             : inline bool
     204                 :       18333 : is_a_helper <pp_token_begin_url*>::test (pp_token *tok)
     205                 :             : {
     206                 :       18333 :   return tok->m_kind == pp_token::kind::begin_url;
     207                 :             : }
     208                 :             : 
     209                 :             : template <>
     210                 :             : template <>
     211                 :             : inline bool
     212                 :           0 : is_a_helper <const pp_token_begin_url*>::test (const pp_token *tok)
     213                 :             : {
     214                 :           0 :   return tok->m_kind == pp_token::kind::begin_url;
     215                 :             : }
     216                 :             : 
     217                 :             : struct pp_token_end_url : public pp_token
     218                 :             : {
     219                 :       18333 :   pp_token_end_url ()
     220                 :       36666 :     : pp_token (kind::end_url)
     221                 :             :   {
     222                 :             :   }
     223                 :             : };
     224                 :             : 
     225                 :             : struct pp_token_event_id : public pp_token
     226                 :             : {
     227                 :       22993 :   pp_token_event_id (diagnostic_event_id_t event_id)
     228                 :       22993 :   : pp_token (kind::event_id),
     229                 :       22993 :     m_event_id (event_id)
     230                 :             :   {
     231                 :       22993 :     gcc_assert (event_id.known_p ());
     232                 :       22993 :   }
     233                 :             : 
     234                 :             :   diagnostic_event_id_t m_event_id;
     235                 :             : };
     236                 :             : 
     237                 :             : template <>
     238                 :             : template <>
     239                 :             : inline bool
     240                 :       22993 : is_a_helper <pp_token_event_id *>::test (pp_token *tok)
     241                 :             : {
     242                 :       22993 :   return tok->m_kind == pp_token::kind::event_id;
     243                 :             : }
     244                 :             : 
     245                 :             : template <>
     246                 :             : template <>
     247                 :             : inline bool
     248                 :           0 : is_a_helper <const pp_token_event_id *>::test (const pp_token *tok)
     249                 :             : {
     250                 :           0 :   return tok->m_kind == pp_token::kind::event_id;
     251                 :             : }
     252                 :             : 
     253                 :             : struct pp_token_custom_data : public pp_token
     254                 :             : {
     255                 :     4740927 :   class value
     256                 :             :   {
     257                 :             :   public:
     258                 :          16 :     virtual ~value () {}
     259                 :             :     virtual void dump (FILE *out) const = 0;
     260                 :             : 
     261                 :             :     /* Hook for lowering a custom_data token to standard tokens.
     262                 :             :        Return true and write to OUT if possible.
     263                 :             :        Return false for custom_data that is to be handled by
     264                 :             :        the token_printer.  */
     265                 :             :     virtual bool as_standard_tokens (pp_token_list &out) = 0;
     266                 :             :   };
     267                 :             : 
     268                 :     4740927 :   pp_token_custom_data (std::unique_ptr<value> val)
     269                 :     4740927 :   : pp_token (kind::custom_data),
     270                 :     4740927 :     m_value (std::move (val))
     271                 :             :   {
     272                 :     4740927 :     gcc_assert (m_value.get ());
     273                 :     4740927 :   }
     274                 :             : 
     275                 :             :   std::unique_ptr<value> m_value;
     276                 :             : };
     277                 :             : 
     278                 :             : template <>
     279                 :             : template <>
     280                 :             : inline bool
     281                 :     9481846 : is_a_helper <pp_token_custom_data *>::test (pp_token *tok)
     282                 :             : {
     283                 :     9481846 :   return tok->m_kind == pp_token::kind::custom_data;
     284                 :             : }
     285                 :             : 
     286                 :             : template <>
     287                 :             : template <>
     288                 :             : inline bool
     289                 :           0 : is_a_helper <const pp_token_custom_data *>::test (const pp_token *tok)
     290                 :             : {
     291                 :           0 :   return tok->m_kind == pp_token::kind::custom_data;
     292                 :             : }
     293                 :             : 
     294                 :             : /* A list of pp_token, with ownership of the tokens, using
     295                 :             :    a particular obstack to allocate its tokens.  These are
     296                 :             :    also allocated on the obstack during formatting (or, occasionally,
     297                 :             :    the stack).  */
     298                 :             : 
     299                 :             : class pp_token_list
     300                 :             : {
     301                 :             : public:
     302                 :             :   // Allocate a new pp_token_list within S.
     303                 :    54114845 :   static pp_token_list *make (obstack &s)
     304                 :             :   {
     305                 :    54114845 :     return new (s) pp_token_list (s);
     306                 :             :   }
     307                 :             :   static void *operator new (size_t sz, obstack &s);
     308                 :             :   static void operator delete (void *);
     309                 :             : 
     310                 :             :   pp_token_list (obstack &s);
     311                 :             :   pp_token_list (const pp_token_list &) = delete;
     312                 :             :   pp_token_list (pp_token_list &&);
     313                 :             : 
     314                 :             :   ~pp_token_list ();
     315                 :             : 
     316                 :             :   pp_token &operator= (const pp_token_list &) = delete;
     317                 :             :   pp_token &operator= (pp_token_list &&) = delete;
     318                 :             : 
     319                 :             : /* Make a pp_token of the given subclass, using the relevant obstack to provide
     320                 :             :    the memory.  The pp_token must therefore not outlive the current
     321                 :             :    pp_formatted_chunks level during formatting.  */
     322                 :             :   template<typename Subclass, typename... Args>
     323                 :             :   std::unique_ptr<pp_token>
     324                 :    53569988 :   make_token (Args&&... args)
     325                 :             :   {
     326                 :             :     return std::unique_ptr<pp_token>
     327                 :    53569988 :       (new (m_obstack) Subclass (std::forward<Args> (args)...));
     328                 :             :   }
     329                 :             : 
     330                 :             :   template<typename Subclass, typename... Args>
     331                 :    53533394 :   void push_back (Args&&... args)
     332                 :             :   {
     333                 :    53533394 :     auto tok = make_token<Subclass> (std::forward<Args> (args)...);
     334                 :    53533394 :     push_back (std::move (tok));
     335                 :    53533394 :   }
     336                 :             :   void push_back_text (label_text &&text);
     337                 :             :   void push_back (std::unique_ptr<pp_token> tok);
     338                 :             :   void push_back_list (pp_token_list &&list);
     339                 :             : 
     340                 :             :   std::unique_ptr<pp_token> pop_front ();
     341                 :             : 
     342                 :             :   std::unique_ptr<pp_token> remove_token (pp_token *tok);
     343                 :             : 
     344                 :             :   void insert_after (std::unique_ptr<pp_token> new_tok,
     345                 :             :                      pp_token *relative_tok);
     346                 :             : 
     347                 :             :   void replace_custom_tokens ();
     348                 :             :   void merge_consecutive_text_tokens ();
     349                 :             :   void apply_urlifier (const urlifier &urlifier);
     350                 :             : 
     351                 :             :   void dump (FILE *out) const;
     352                 :           0 :   void DEBUG_FUNCTION dump () const { dump (stderr); }
     353                 :             : 
     354                 :             :   obstack &m_obstack;
     355                 :             : 
     356                 :             :   pp_token *m_first;
     357                 :             :   pp_token *m_end;
     358                 :             : };
     359                 :             : 
     360                 :             : /* The pp_formatted_chunks data structure forms a stack of the results from the
     361                 :             :    first phase of formatting (pp_format) which have not yet been
     362                 :             :    output (pp_output_formatted_text).  A stack is necessary because
     363                 :             :    the diagnostic starter may decide to generate its own output by way
     364                 :             :    of the formatter.  */
     365                 :             : class pp_formatted_chunks
     366                 :             : {
     367                 :             :   friend class pretty_printer;
     368                 :             :   friend class pp_markup::context;
     369                 :             :   friend class output_buffer;
     370                 :             : 
     371                 :             : public:
     372                 :    14974731 :   pp_token_list * const * get_token_lists () const { return m_args; }
     373                 :             : 
     374                 :             :   void append_formatted_chunk (obstack &s, const char *content);
     375                 :             : 
     376                 :             :   void dump (FILE *out, int indent) const;
     377                 :           0 :   void DEBUG_FUNCTION dump () const { dump (stderr, 0); }
     378                 :             : 
     379                 :             :   // For use in selftests
     380                 :           8 :   pp_formatted_chunks *get_prev () const { return m_prev; }
     381                 :             : 
     382                 :             : private:
     383                 :             :   /* Pointer to previous level on the stack.  */
     384                 :             :   pp_formatted_chunks *m_prev;
     385                 :             : 
     386                 :             :   /* Array of chunks to output.  Each chunk is a doubly-linked list of
     387                 :             :      pp_token.
     388                 :             : 
     389                 :             :      The chunks can be printed via pp_formatted_chunks::dump ().
     390                 :             : 
     391                 :             :      In the first phase of formatting, even-numbered chunks are
     392                 :             :      to be output verbatim, odd-numbered chunks are format specifiers.
     393                 :             :      For example, given:
     394                 :             :        pp_format (pp,
     395                 :             :                   "foo: %i, bar: %s, opt: %qs",
     396                 :             :                   42, "baz", "-foption");
     397                 :             : 
     398                 :             :      after phase 1 we might have:
     399                 :             :        (gdb) call buffer->cur_chunk_array->dump()
     400                 :             :        0: [TEXT("foo: ")]
     401                 :             :        1: [TEXT("i")]
     402                 :             :        2: [TEXT(", bar: ")]
     403                 :             :        3: [TEXT("s")]
     404                 :             :        4: [TEXT(", opt: ")]
     405                 :             :        5: [TEXT("qs")]
     406                 :             : 
     407                 :             :      The second phase replaces all odd-numbered chunks with formatted
     408                 :             :      token lists.  In the above example, after phase 2 we might have:
     409                 :             :        (gdb) call pp->m_buffer->cur_chunk_array->dump()
     410                 :             :        0: [TEXT("foo: ")]
     411                 :             :        1: [TEXT("42")]
     412                 :             :        2: [TEXT(", bar: ")]
     413                 :             :        3: [TEXT("baz")]
     414                 :             :        4: [TEXT(", opt: ")]
     415                 :             :        5: [BEGIN_QUOTE, TEXT("-foption"), END_QUOTE]
     416                 :             :      For example the %qs has become the three tokens:
     417                 :             :        [BEGIN_QUOTE, TEXT("-foption"), END_QUOTE]
     418                 :             : 
     419                 :             :      The third phase (in pp_output_formatted_text):
     420                 :             : 
     421                 :             :      (1) merges the tokens from all the chunks into one list,
     422                 :             :      giving e.g.
     423                 :             :       (gdb) call tokens.dump()
     424                 :             :       [TEXT("foo: "), TEXT("42"), TEXT(", bar: "), TEXT("baz"),
     425                 :             :        TEXT(", opt: "), BEGIN_QUOTE, TEXT("-foption"), END_QUOTE]
     426                 :             : 
     427                 :             :      (2) lowers some custom tokens into non-custom tokens
     428                 :             : 
     429                 :             :      (3) merges consecutive text tokens, giving e.g.:
     430                 :             :       (gdb) call tokens.dump()
     431                 :             :       [TEXT("foo: 42, bar: baz, option: "),
     432                 :             :        BEGIN_QUOTE, TEXT("-foption"), END_QUOTE]
     433                 :             : 
     434                 :             :      (4) if provided with a urlifier, tries to apply it to quoted text,
     435                 :             :      giving e.g:
     436                 :             :       (gdb) call tokens.dump()
     437                 :             :       [TEXT("foo: 42, bar: baz, option: "), BEGIN_QUOTE,
     438                 :             :        BEGIN_URL("http://example.com"), TEXT("-foption"), END_URL, END_QUOTE]
     439                 :             : 
     440                 :             :      (5) emits all tokens in sequence with appropriate line-wrapping.  This
     441                 :             :      can be overridded via the pretty_printer's token_printer, allowing for
     442                 :             :      output formats to e.g. override how URLs are handled, or to handle
     443                 :             :      custom_data that wasn't lowered in (2) above, e.g. for handling JSON
     444                 :             :      output of optimization records.  */
     445                 :             :   pp_token_list *m_args[PP_NL_ARGMAX * 2];
     446                 :             : 
     447                 :             :   /* The pp_tokens, pp_token_lists, and the accumulated text buffers are
     448                 :             :      allocated within the output_buffer's chunk_obstack.  In the above
     449                 :             :      example, the in-memory layout of the chunk_obstack might look like
     450                 :             :      this after phase 1:
     451                 :             : 
     452                 :             :       + pp_formatted_chunks instance   <--- START of pp_formatted_chunks level
     453                 :             :       |
     454                 :             :       + pp_token_list for chunk 0 (m_first: *)
     455                 :             :       |                                     |
     456                 :             :       + "foo: \0"  <-------------\          |
     457                 :             :       |                          |          |
     458                 :             :       + pp_token_text (borrowed: *) <-------/
     459                 :             :       |
     460                 :             :       + pp_token_list for chunk 1
     461                 :             :       |
     462                 :             :       + "i\0" <------------------\
     463                 :             :       |                          |
     464                 :             :       + pp_token_text (borrowed: *)
     465                 :             :       |
     466                 :             :       +  ...etc for chunks 2 to 4...
     467                 :             :       |
     468                 :             :       + pp_token_list for chunk 5
     469                 :             :       |
     470                 :             :       + "qs\0" <-----------------\
     471                 :             :       |                          |
     472                 :             :       + pp_token_text (borrowed: *)
     473                 :             :       |
     474                 :             :       |
     475                 :             :       V
     476                 :             :      obstack grows this way
     477                 :             : 
     478                 :             :      At each stage, allocation of additional text buffers, tokens, and lists
     479                 :             :      grow forwards in the obstack (though the internal pointers in linked
     480                 :             :      lists might point backwards to earlier objects within the same
     481                 :             :      pp_formatted_chunks level).  */
     482                 :             : };
     483                 :             : 
     484                 :             : #endif /* GCC_PRETTY_PRINT_FORMAT_IMPL_H */
        

Generated by: LCOV version 2.1-beta

LCOV profile is generated on x86_64 machine using following configure options: configure --disable-bootstrap --enable-coverage=opt --enable-languages=c,c++,fortran,go,jit,lto,rust,m2 --enable-host-shared. GCC test suite is run with the built compiler.